• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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