1 //
2 // Copyright (c) 2017 The Khronos Group Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 #include "harness/testHarness.h"
17 #include "harness/typeWrappers.h"
18 #include "harness/mt19937.h"
19 #include "base.h"
20
21 #include <string>
22 #include <vector>
23 #include <algorithm>
24 #include <sstream>
25
26 class CStressTest : public CTest {
27 public:
CStressTest(const std::vector<std::string> & kernel)28 CStressTest(const std::vector<std::string>& kernel) : CTest(), _kernels(kernel) {
29
30 }
31
CStressTest(const std::string & kernel)32 CStressTest(const std::string& kernel) : CTest(), _kernels(1, kernel) {
33
34 }
35
ExecuteSubcase(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements,const std::string & src)36 int ExecuteSubcase(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, const std::string& src) {
37 cl_int error;
38
39 clProgramWrapper program;
40 clKernelWrapper kernel;
41
42 const char *srcPtr = src.c_str();
43
44 if (create_single_kernel_helper_with_build_options(context, &program, &kernel, 1, &srcPtr, "testKernel", "-cl-std=CL2.0")) {
45 log_error("create_single_kernel_helper failed");
46 return -1;
47 }
48
49 size_t bufferSize = num_elements * sizeof(cl_uint);
50 clMemWrapper buffer = clCreateBuffer(context, CL_MEM_WRITE_ONLY, bufferSize, NULL, &error);
51 test_error(error, "clCreateBuffer failed");
52
53 error = clSetKernelArg(kernel, 0, sizeof(buffer), &buffer);
54 test_error(error, "clSetKernelArg failed");
55
56 size_t globalWorkGroupSize = num_elements;
57 size_t localWorkGroupSize = 0;
58 error = get_max_common_work_group_size(context, kernel, globalWorkGroupSize, &localWorkGroupSize);
59 test_error(error, "Unable to get common work group size");
60
61 error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &globalWorkGroupSize, &localWorkGroupSize, 0, NULL, NULL);
62 test_error(error, "clEnqueueNDRangeKernel failed");
63
64 // verify results
65 std::vector<cl_uint> results(num_elements);
66
67 error = clEnqueueReadBuffer(queue, buffer, CL_TRUE, 0, bufferSize, &results[0], 0, NULL, NULL);
68 test_error(error, "clEnqueueReadBuffer failed");
69
70 size_t passCount = std::count(results.begin(), results.end(), 1);
71 if (passCount != results.size()) {
72 std::vector<cl_uint>::iterator iter = std::find(results.begin(), results.end(), 0);
73 log_error("Verification on device failed at index %ld\n", std::distance(results.begin(), iter));
74 log_error("%ld out of %ld failed\n", (results.size()-passCount), results.size());
75 return -1;
76 }
77
78 return CL_SUCCESS;
79 }
80
Execute(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)81 int Execute(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) {
82 cl_int result = CL_SUCCESS;
83
84 for (std::vector<std::string>::const_iterator it = _kernels.begin(); it != _kernels.end(); ++it) {
85 log_info("Executing subcase #%ld out of %ld\n", (it - _kernels.begin() + 1), _kernels.size());
86
87 result |= ExecuteSubcase(deviceID, context, queue, num_elements, *it);
88 }
89
90 return result;
91 }
92
93 private:
94 const std::vector<std::string> _kernels;
95 };
96
test_max_number_of_params(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)97 int test_max_number_of_params(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) {
98 cl_int error;
99
100 size_t deviceMaxParameterSize;
101 error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_PARAMETER_SIZE, sizeof(deviceMaxParameterSize), &deviceMaxParameterSize, NULL);
102 test_error(error, "clGetDeviceInfo failed");
103
104 size_t deviceAddressBits;
105 error = clGetDeviceInfo(deviceID, CL_DEVICE_ADDRESS_BITS, sizeof(deviceAddressBits), &deviceAddressBits, NULL);
106 test_error(error, "clGetDeviceInfo failed");
107
108 size_t maxParams = deviceMaxParameterSize / (deviceAddressBits / 8);
109
110 const std::string KERNEL_FUNCTION_TEMPLATE[] = {
111 common::CONFORMANCE_VERIFY_FENCE +
112 NL
113 NL "bool helperFunction(int *ptr0 ",
114 // the rest of arguments goes here
115 ") {"
116 NL " // check first pointer only"
117 NL " if (!isFenceValid(get_fence(ptr0)))"
118 NL " return false;"
119 NL
120 NL " return true;"
121 NL "}"
122 NL
123 NL "__kernel void testKernel(__global uint *results) {"
124 NL " uint tid = get_global_id(0);"
125 NL
126 NL " __global int * gptr;"
127 NL " __local int * lptr;"
128 NL " __private int * pptr;"
129 NL
130 NL " size_t failures = 0;"
131 NL
132 NL,
133 // the function body goes here
134 NL
135 NL " results[tid] = (failures == 0);"
136 NL "}"
137 NL
138 };
139
140 std::ostringstream type_params;
141 std::ostringstream function_calls;
142
143 for (size_t i = 0; i < maxParams; i++) {
144 type_params << ", int *ptr" << i+1;
145 }
146
147 // use pseudo random generator to shuffle params
148 MTdata d = init_genrand(gRandomSeed);
149 if (!d)
150 return -1;
151
152 std::string pointers[] = { "gptr", "lptr", "pptr" };
153
154 size_t totalCalls = maxParams / 2;
155 for (size_t i = 0; i < totalCalls; i++) {
156 function_calls << "\tif (!helperFunction(gptr";
157
158 for (size_t j = 0; j < maxParams; j++) {
159 function_calls << ", " << pointers[genrand_int32(d)%3];
160 }
161
162 function_calls << ")) failures++;" << NL;
163 }
164
165 free_mtdata(d);
166 d = NULL;
167
168 const std::string KERNEL_FUNCTION = KERNEL_FUNCTION_TEMPLATE[0] + type_params.str() + KERNEL_FUNCTION_TEMPLATE[1] + function_calls.str() + KERNEL_FUNCTION_TEMPLATE[2];
169
170 CStressTest test(KERNEL_FUNCTION);
171
172 return test.Execute(deviceID, context, queue, num_elements);
173 }
174