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(context, &program, &kernel, 1, &srcPtr,
45 "testKernel"))
46 {
47 log_error("create_single_kernel_helper failed");
48 return -1;
49 }
50
51 size_t bufferSize = num_elements * sizeof(cl_uint);
52 clMemWrapper buffer = clCreateBuffer(context, CL_MEM_WRITE_ONLY, bufferSize, NULL, &error);
53 test_error(error, "clCreateBuffer failed");
54
55 error = clSetKernelArg(kernel, 0, sizeof(buffer), &buffer);
56 test_error(error, "clSetKernelArg failed");
57
58 size_t globalWorkGroupSize = num_elements;
59 size_t localWorkGroupSize = 0;
60 error = get_max_common_work_group_size(context, kernel, globalWorkGroupSize, &localWorkGroupSize);
61 test_error(error, "Unable to get common work group size");
62
63 error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &globalWorkGroupSize, &localWorkGroupSize, 0, NULL, NULL);
64 test_error(error, "clEnqueueNDRangeKernel failed");
65
66 // verify results
67 std::vector<cl_uint> results(num_elements);
68
69 error = clEnqueueReadBuffer(queue, buffer, CL_TRUE, 0, bufferSize, &results[0], 0, NULL, NULL);
70 test_error(error, "clEnqueueReadBuffer failed");
71
72 size_t passCount = std::count(results.begin(), results.end(), 1);
73 if (passCount != results.size()) {
74 std::vector<cl_uint>::iterator iter = std::find(results.begin(), results.end(), 0);
75 log_error("Verification on device failed at index %ld\n", std::distance(results.begin(), iter));
76 log_error("%ld out of %ld failed\n", (results.size()-passCount), results.size());
77 return -1;
78 }
79
80 return CL_SUCCESS;
81 }
82
Execute(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)83 int Execute(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) {
84 cl_int result = CL_SUCCESS;
85
86 for (std::vector<std::string>::const_iterator it = _kernels.begin(); it != _kernels.end(); ++it) {
87 log_info("Executing subcase #%ld out of %ld\n", (it - _kernels.begin() + 1), _kernels.size());
88
89 result |= ExecuteSubcase(deviceID, context, queue, num_elements, *it);
90 }
91
92 return result;
93 }
94
95 private:
96 const std::vector<std::string> _kernels;
97 };
98
test_max_number_of_params(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)99 int test_max_number_of_params(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) {
100 cl_int error;
101
102 size_t deviceMaxParameterSize;
103 error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_PARAMETER_SIZE, sizeof(deviceMaxParameterSize), &deviceMaxParameterSize, NULL);
104 test_error(error, "clGetDeviceInfo failed");
105
106 size_t deviceAddressBits;
107 error = clGetDeviceInfo(deviceID, CL_DEVICE_ADDRESS_BITS, sizeof(deviceAddressBits), &deviceAddressBits, NULL);
108 test_error(error, "clGetDeviceInfo failed");
109
110 size_t maxParams = deviceMaxParameterSize / (deviceAddressBits / 8);
111
112 const std::string KERNEL_FUNCTION_TEMPLATE[] = {
113 common::CONFORMANCE_VERIFY_FENCE +
114 NL
115 NL "bool helperFunction(int *ptr0 ",
116 // the rest of arguments goes here
117 ") {"
118 NL " // check first pointer only"
119 NL " if (!isFenceValid(get_fence(ptr0)))"
120 NL " return false;"
121 NL
122 NL " return true;"
123 NL "}"
124 NL
125 NL "__kernel void testKernel(__global uint *results) {"
126 NL " uint tid = get_global_id(0);"
127 NL
128 NL " __global int * gptr;"
129 NL " __local int * lptr;"
130 NL " __private int * pptr;"
131 NL
132 NL " size_t failures = 0;"
133 NL
134 NL,
135 // the function body goes here
136 NL
137 NL " results[tid] = (failures == 0);"
138 NL "}"
139 NL
140 };
141
142 std::ostringstream type_params;
143 std::ostringstream function_calls;
144
145 for (size_t i = 0; i < maxParams; i++) {
146 type_params << ", int *ptr" << i+1;
147 }
148
149 // use pseudo random generator to shuffle params
150 MTdata d = init_genrand(gRandomSeed);
151 if (!d)
152 return -1;
153
154 std::string pointers[] = { "gptr", "lptr", "pptr" };
155
156 size_t totalCalls = maxParams / 2;
157 for (size_t i = 0; i < totalCalls; i++) {
158 function_calls << "\tif (!helperFunction(gptr";
159
160 for (size_t j = 0; j < maxParams; j++) {
161 function_calls << ", " << pointers[genrand_int32(d)%3];
162 }
163
164 function_calls << ")) failures++;" << NL;
165 }
166
167 free_mtdata(d);
168 d = NULL;
169
170 const std::string KERNEL_FUNCTION = KERNEL_FUNCTION_TEMPLATE[0] + type_params.str() + KERNEL_FUNCTION_TEMPLATE[1] + function_calls.str() + KERNEL_FUNCTION_TEMPLATE[2];
171
172 CStressTest test(KERNEL_FUNCTION);
173
174 return test.Execute(deviceID, context, queue, num_elements);
175 }
176