• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (c) 2022 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 "basic_command_buffer.h"
17 #include "procs.h"
18 
19 #include <vector>
20 
21 namespace {
22 
23 ////////////////////////////////////////////////////////////////////////////////
24 // Command-queue substitution tests which handles below cases:
25 // -substitution on queue without properties
26 // -substitution on queue with properties
27 // -simultaneous use queue substitution
28 
29 template <bool prop_use, bool simul_use>
30 struct SubstituteQueueTest : public BasicCommandBufferTest
31 {
SubstituteQueueTest__anon33b54d660111::SubstituteQueueTest32     SubstituteQueueTest(cl_device_id device, cl_context context,
33                         cl_command_queue queue)
34         : BasicCommandBufferTest(device, context, queue),
35           properties_use_requested(prop_use), user_event(nullptr)
36     {
37         simultaneous_use_requested = simul_use;
38         if (simul_use) buffer_size_multiplier = 2;
39     }
40 
41     //--------------------------------------------------------------------------
Skip__anon33b54d660111::SubstituteQueueTest42     bool Skip() override
43     {
44         if (properties_use_requested)
45         {
46             Version version = get_device_cl_version(device);
47             const cl_device_info host_queue_query = version >= Version(2, 0)
48                 ? CL_DEVICE_QUEUE_ON_HOST_PROPERTIES
49                 : CL_DEVICE_QUEUE_PROPERTIES;
50 
51             cl_queue_properties host_queue_props = 0;
52             int error = clGetDeviceInfo(device, host_queue_query,
53                                         sizeof(host_queue_props),
54                                         &host_queue_props, NULL);
55             test_error(error, "clGetDeviceInfo failed");
56 
57             if ((host_queue_props & CL_QUEUE_PROFILING_ENABLE) == 0)
58                 return true;
59         }
60 
61         return BasicCommandBufferTest::Skip()
62             || (simultaneous_use_requested && !simultaneous_use_support);
63     }
64 
65     //--------------------------------------------------------------------------
SetUp__anon33b54d660111::SubstituteQueueTest66     cl_int SetUp(int elements) override
67     {
68         // By default command queue is created without properties,
69         // if test requires queue with properties default queue must be
70         // replaced.
71         if (properties_use_requested)
72         {
73             // due to the skip condition
74             cl_int error = CL_SUCCESS;
75             queue = clCreateCommandQueue(context, device,
76                                          CL_QUEUE_PROFILING_ENABLE, &error);
77             test_error(
78                 error,
79                 "clCreateCommandQueue with CL_QUEUE_PROFILING_ENABLE failed");
80         }
81 
82         return BasicCommandBufferTest::SetUp(elements);
83     }
84 
85     //--------------------------------------------------------------------------
Run__anon33b54d660111::SubstituteQueueTest86     cl_int Run() override
87     {
88         // record command buffer with primary queue
89         cl_int error = RecordCommandBuffer();
90         test_error(error, "RecordCommandBuffer failed");
91 
92         // create substitute queue
93         clCommandQueueWrapper new_queue;
94         if (properties_use_requested)
95         {
96             new_queue = clCreateCommandQueue(context, device,
97                                              CL_QUEUE_PROFILING_ENABLE, &error);
98             test_error(
99                 error,
100                 "clCreateCommandQueue with CL_QUEUE_PROFILING_ENABLE failed");
101         }
102         else
103         {
104             const cl_command_queue_properties queue_properties = 0;
105             new_queue =
106                 clCreateCommandQueue(context, device, queue_properties, &error);
107             test_error(error, "clCreateCommandQueue failed");
108         }
109 
110         if (simultaneous_use_support)
111         {
112             // enque simultaneous command-buffers with substitute queue
113             error = RunSimultaneous(new_queue);
114             test_error(error, "RunSimultaneous failed");
115         }
116         else
117         {
118             // enque single command-buffer with substitute queue
119             error = RunSingle(new_queue);
120             test_error(error, "RunSingle failed");
121         }
122 
123         return CL_SUCCESS;
124     }
125 
126     //--------------------------------------------------------------------------
RecordCommandBuffer__anon33b54d660111::SubstituteQueueTest127     cl_int RecordCommandBuffer()
128     {
129         cl_int error = clCommandNDRangeKernelKHR(
130             command_buffer, nullptr, nullptr, kernel, 1, nullptr, &num_elements,
131             nullptr, 0, nullptr, nullptr, nullptr);
132         test_error(error, "clCommandNDRangeKernelKHR failed");
133 
134         error = clFinalizeCommandBufferKHR(command_buffer);
135         test_error(error, "clFinalizeCommandBufferKHR failed");
136         return CL_SUCCESS;
137     }
138 
139     //--------------------------------------------------------------------------
RunSingle__anon33b54d660111::SubstituteQueueTest140     cl_int RunSingle(const cl_command_queue& q)
141     {
142         cl_int error = CL_SUCCESS;
143         std::vector<cl_int> output_data(num_elements);
144 
145         error = clEnqueueFillBuffer(q, in_mem, &pattern_pri, sizeof(cl_int), 0,
146                                     data_size(), 0, nullptr, nullptr);
147         test_error(error, "clEnqueueFillBuffer failed");
148 
149         cl_command_queue queues[] = { q };
150         error = clEnqueueCommandBufferKHR(1, queues, command_buffer, 0, nullptr,
151                                           nullptr);
152         test_error(error, "clEnqueueCommandBufferKHR failed");
153 
154         error = clEnqueueReadBuffer(q, out_mem, CL_TRUE, 0, data_size(),
155                                     output_data.data(), 0, nullptr, nullptr);
156         test_error(error, "clEnqueueReadBuffer failed");
157 
158         error = clFinish(q);
159         test_error(error, "clFinish failed");
160 
161         for (size_t i = 0; i < num_elements; i++)
162         {
163             CHECK_VERIFICATION_ERROR(pattern_pri, output_data[i], i);
164         }
165 
166         return CL_SUCCESS;
167     }
168 
169     //--------------------------------------------------------------------------
170     struct SimulPassData
171     {
172         cl_int pattern;
173         cl_int offset;
174         cl_command_queue queue;
175         std::vector<cl_int> output_buffer;
176     };
177 
178     //--------------------------------------------------------------------------
EnqueueSimultaneousPass__anon33b54d660111::SubstituteQueueTest179     cl_int EnqueueSimultaneousPass(SimulPassData& pd)
180     {
181         cl_int error = clEnqueueFillBuffer(
182             pd.queue, in_mem, &pd.pattern, sizeof(cl_int),
183             pd.offset * sizeof(cl_int), data_size(), 0, nullptr, nullptr);
184         test_error(error, "clEnqueueFillBuffer failed");
185 
186         error =
187             clEnqueueFillBuffer(pd.queue, off_mem, &pd.offset, sizeof(cl_int),
188                                 0, sizeof(cl_int), 0, nullptr, nullptr);
189         test_error(error, "clEnqueueFillBuffer failed");
190 
191         if (!user_event)
192         {
193             user_event = clCreateUserEvent(context, &error);
194             test_error(error, "clCreateUserEvent failed");
195         }
196 
197         cl_command_queue queues[] = { pd.queue };
198         error = clEnqueueCommandBufferKHR(1, queues, command_buffer, 1,
199                                           &user_event, nullptr);
200         test_error(error, "clEnqueueCommandBufferKHR failed");
201 
202         error = clEnqueueReadBuffer(
203             pd.queue, out_mem, CL_FALSE, pd.offset * sizeof(cl_int),
204             data_size(), pd.output_buffer.data(), 0, nullptr, nullptr);
205 
206         test_error(error, "clEnqueueReadBuffer failed");
207 
208         return CL_SUCCESS;
209     }
210 
211     //--------------------------------------------------------------------------
RunSimultaneous__anon33b54d660111::SubstituteQueueTest212     cl_int RunSimultaneous(const cl_command_queue& q)
213     {
214         cl_int error = CL_SUCCESS;
215         cl_int offset = static_cast<cl_int>(num_elements);
216 
217         std::vector<SimulPassData> simul_passes = {
218             { pattern_pri, 0, q, std::vector<cl_int>(num_elements) },
219             { pattern_sec, offset, q, std::vector<cl_int>(num_elements) }
220         };
221 
222         for (auto&& pass : simul_passes)
223         {
224             error = EnqueueSimultaneousPass(pass);
225             test_error(error, "EnqueuePass failed");
226         }
227 
228         error = clSetUserEventStatus(user_event, CL_COMPLETE);
229         test_error(error, "clSetUserEventStatus failed");
230 
231         for (auto&& pass : simul_passes)
232         {
233             error = clFinish(pass.queue);
234             test_error(error, "clFinish failed");
235 
236             auto& res_data = pass.output_buffer;
237 
238             for (size_t i = 0; i < num_elements; i++)
239             {
240                 CHECK_VERIFICATION_ERROR(pass.pattern, res_data[i], i);
241             }
242         }
243 
244         return CL_SUCCESS;
245     }
246 
247     //--------------------------------------------------------------------------
248     const cl_int pattern_pri = 0xB;
249     const cl_int pattern_sec = 0xC;
250 
251     bool properties_use_requested;
252     clEventWrapper user_event;
253 };
254 
255 } // anonymous namespace
256 
test_queue_substitution(cl_device_id device,cl_context context,cl_command_queue queue,int num_elements)257 int test_queue_substitution(cl_device_id device, cl_context context,
258                             cl_command_queue queue, int num_elements)
259 {
260     return MakeAndRunTest<SubstituteQueueTest<false, false>>(
261         device, context, queue, num_elements);
262 }
263 
test_properties_queue_substitution(cl_device_id device,cl_context context,cl_command_queue queue,int num_elements)264 int test_properties_queue_substitution(cl_device_id device, cl_context context,
265                                        cl_command_queue queue, int num_elements)
266 {
267     return MakeAndRunTest<SubstituteQueueTest<true, false>>(
268         device, context, queue, num_elements);
269 }
270 
test_simultaneous_queue_substitution(cl_device_id device,cl_context context,cl_command_queue queue,int num_elements)271 int test_simultaneous_queue_substitution(cl_device_id device,
272                                          cl_context context,
273                                          cl_command_queue queue,
274                                          int num_elements)
275 {
276     return MakeAndRunTest<SubstituteQueueTest<false, true>>(
277         device, context, queue, num_elements);
278 }
279