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 #ifndef test_conformance_check_mem_host_write_only__h
17 #define test_conformance_check_mem_host_write_only__h
18 
19 #include "checker.h"
20 
21 template <class T>
22 class cBuffer_check_mem_host_write_only : public cBuffer_checker<T> {
23 public:
cBuffer_check_mem_host_write_only(cl_device_id deviceID,cl_context context,cl_command_queue queue)24     cBuffer_check_mem_host_write_only(cl_device_id deviceID, cl_context context,
25                                       cl_command_queue queue)
26         : cBuffer_checker<T>(deviceID, context, queue)
27     {
28         this->m_nNumber_elements = 1000;
29     };
30 
~cBuffer_check_mem_host_write_only()31     ~cBuffer_check_mem_host_write_only(){};
32 
33     cl_program program;
34     cl_kernel kernel;
35 
36     clMemWrapper m_buffer2;
37 
38     cl_int Setup_Test_Environment();
39 
40     cl_int SetupBuffer();
41     cl_int SetupASSubBuffer(cl_mem_flags flag_p);
42 
43     cl_int verifyData(cl_int err, cl_event &event);
44     cl_int update_host_mem_2();
45 
46     cl_int verify_RW_Buffer();
47     cl_int verify_RW_Buffer_rect();
48     cl_int verify_RW_Buffer_mapping();
49 
50     C_host_memory_block<T> tmp_host_m;
51 
52     virtual cl_int verify_Buffer_initialization();
53 };
54 
SetupBuffer()55 template <class T> cl_int cBuffer_check_mem_host_write_only<T>::SetupBuffer()
56 {
57     T vv1 = 0;
58     this->host_m_1.Init(this->m_nNumber_elements, vv1); // zero out buffer
59 
60     // init buffer to 0
61     cl_int err;
62     int block_size_in_byte = this->get_block_size_bytes();
63 
64     this->m_buffer =
65         clCreateBuffer(this->m_context, this->buffer_mem_flag,
66                        block_size_in_byte, this->host_m_1.pData, &err);
67     test_error(err, "clCreateBuffer error");
68 
69     err = this->Check_GetMemObjectInfo(this->buffer_mem_flag);
70 
71     if (this->buffer_mem_flag | CL_MEM_USE_HOST_PTR)
72     {
73         this->pHost_ptr = (void *)this->host_m_1.pData;
74     }
75 
76     return err;
77 }
78 
79 template <class T>
80 cl_int
SetupASSubBuffer(cl_mem_flags flag_p)81 cBuffer_check_mem_host_write_only<T>::SetupASSubBuffer(cl_mem_flags flag_p)
82 {
83     return cBuffer_checker<T>::SetupASSubBuffer(flag_p);
84 }
85 
86 template <class T>
Setup_Test_Environment()87 cl_int cBuffer_check_mem_host_write_only<T>::Setup_Test_Environment()
88 {
89     cl_int err;
90     T vv2 = 0;
91     this->host_m_2.Init(this->m_nNumber_elements, vv2);
92 
93     // init buffer2 to 0
94     cl_mem_flags buffer_mem_flag2 =
95         CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR | CL_MEM_HOST_READ_ONLY;
96     this->m_buffer2 = clCreateBuffer(this->m_context, buffer_mem_flag2,
97                                      this->get_block_size_bytes(),
98                                      this->host_m_2.pData, &err);
99     test_error(err, "clCreateBuffer error\n");
100 
101     return err;
102 }
103 
104 template <class T>
verify_Buffer_initialization()105 cl_int cBuffer_check_mem_host_write_only<T>::verify_Buffer_initialization()
106 {
107     cl_int err = CL_SUCCESS;
108 
109     if (this->host_m_1.pData == NULL || this->host_m_2.pData == NULL)
110     {
111         log_error("Data not ready\n");
112         return FAILURE;
113     }
114 
115     update_host_mem_2();
116 
117     if (!this->host_m_1.Equal(this->host_m_2))
118     {
119         log_error("Buffer content difference found\n");
120         return FAILURE;
121     }
122 
123     return err;
124 }
125 
126 template <class T>
verify_RW_Buffer()127 cl_int cBuffer_check_mem_host_write_only<T>::verify_RW_Buffer()
128 {
129     T vv1 = TEST_VALUE;
130     T vv2 = 0;
131     this->host_m_2.Set_to(vv2);
132 
133     tmp_host_m.Init(this->host_m_1.num_elements, vv1);
134 
135     cl_event event;
136     cl_int err = CL_SUCCESS;
137     err = clEnqueueWriteBuffer(this->m_queue, this->m_buffer, this->m_blocking,
138                                0, this->get_block_size_bytes(),
139                                tmp_host_m.pData, 0, NULL, &event);
140     if (err != CL_SUCCESS)
141     {
142         test_error(err, "clEnqueueWriteBuffer error");
143     }
144 
145     if (!this->m_blocking)
146     {
147         err = clWaitForEvents(1, &event);
148         test_error(err, "clWaitForEvents error")
149     }
150 
151     err = clReleaseEvent(event);
152     test_error(err, "clReleaseEvent error");
153 
154     if (tmp_host_m.Equal(this->host_m_2))
155     {
156         log_error("Test data should be different\n");
157         return FAILURE;
158     }
159 
160     update_host_mem_2();
161 
162     if (!tmp_host_m.Equal(this->host_m_2))
163     {
164         log_error("Buffer content difference found\n");
165         return FAILURE;
166     }
167 
168     err = clEnqueueReadBuffer(this->m_queue, this->m_buffer, CL_TRUE, 0,
169                               this->get_block_size_bytes(),
170                               this->host_m_2.pData, 0, NULL, &event);
171 
172     if (err == CL_SUCCESS)
173     {
174         log_error(
175             "Calling clEnqueueReadBuffer on a memory object created with the "
176             "CL_MEM_HOST_WRITE_ONLY flag should not return CL_SUCCESS\n");
177         err = FAILURE;
178         return FAILURE;
179     }
180     else
181     {
182         log_info("Test succeeded\n\n");
183         err = CL_SUCCESS;
184     }
185 
186     return err;
187 }
188 
189 template <class T>
verify_RW_Buffer_rect()190 cl_int cBuffer_check_mem_host_write_only<T>::verify_RW_Buffer_rect()
191 {
192     this->Init_rect();
193 
194     T vv1 = TEST_VALUE;
195     this->host_m_1.Set_to(vv1);
196 
197     T vv2 = 0;
198     this->host_m_2.Set_to(vv2);
199 
200     cl_event event, event_1;
201 
202     cl_int err = CL_SUCCESS;
203 
204     vv1 = 0;
205     C_host_memory_block<T> tmp_host_m;
206     tmp_host_m.Init(this->host_m_1.num_elements, vv1); // zero out the buffer
207     err = clEnqueueWriteBuffer(this->m_queue, this->m_buffer, CL_TRUE, 0,
208                                this->get_block_size_bytes(), tmp_host_m.pData,
209                                0, NULL, &event_1);
210     test_error(err, "clEnqueueWriteBuffer error");
211 
212     vv1 = TEST_VALUE;
213     tmp_host_m.Set_to(vv1);
214     err = clEnqueueWriteBufferRect(
215         this->m_queue, this->m_buffer, this->m_blocking,
216         this->buffer_origin_bytes, this->host_origin_bytes, this->region_bytes,
217         this->buffer_row_pitch_bytes, this->buffer_slice_pitch_bytes,
218         this->host_row_pitch_bytes, this->host_slice_pitch_bytes,
219         tmp_host_m.pData, 1, &event_1, &event);
220     test_error(err, "clEnqueueWriteBufferRect error");
221 
222     if (!this->m_blocking)
223     {
224         err = clWaitForEvents(1, &event);
225         test_error(err, "clWaitForEvents error")
226     }
227 
228     if (tmp_host_m.Equal(this->host_m_2))
229     {
230         log_error("Test data should be different\n");
231         return FAILURE;
232     }
233 
234     err = clReleaseEvent(event_1);
235     test_error(err, "clReleaseEvent error");
236     err = clReleaseEvent(event);
237     test_error(err, "clReleaseEvent error");
238 
239     update_host_mem_2();
240 
241     size_t tot_in_reg = this->region[0] * this->region[1] * this->region[2];
242     if (!tmp_host_m.Equal_rect(this->host_m_2, this->host_origin, this->region,
243                                this->host_row_pitch, this->host_slice_pitch))
244     {
245         log_error("Buffer rect content difference found\n");
246         return FAILURE;
247     }
248 
249     if (this->host_m_2.Count(vv1) != tot_in_reg)
250     {
251         log_error("Buffer rect content difference found\n");
252         return FAILURE;
253     }
254 
255     err = clEnqueueReadBufferRect(
256         this->m_queue, this->m_buffer, this->m_blocking,
257         this->buffer_origin_bytes, this->host_origin_bytes, this->region_bytes,
258         this->buffer_row_pitch_bytes, this->buffer_slice_pitch_bytes,
259         this->host_row_pitch_bytes, this->host_slice_pitch_bytes,
260         this->host_m_2.pData, 0, NULL, &event);
261 
262     if (err == CL_SUCCESS)
263     {
264         log_error(
265             "Calling clEnqueueReadBufferRect on a memory object created with "
266             "the CL_MEM_HOST_WRITE_ONLY flag should not return CL_SUCCESS\n");
267         err = FAILURE;
268         return FAILURE;
269     }
270     else
271     {
272         log_info("Test succeeded\n\n");
273         err = CL_SUCCESS;
274     }
275 
276     return err;
277 }
278 
279 template <class T>
update_host_mem_2()280 cl_int cBuffer_check_mem_host_write_only<T>::update_host_mem_2()
281 {
282     cl_event event, event_2;
283     cl_int err = clEnqueueCopyBuffer(
284         this->m_queue, this->m_buffer, this->m_buffer2, 0, 0,
285         this->m_nNumber_elements * sizeof(T), 0, NULL, &event);
286     test_error(err, "clEnqueueCopyBuffer error");
287 
288     this->host_m_2.Set_to_zero();
289     err = clEnqueueReadBuffer(this->m_queue, this->m_buffer2, CL_TRUE, 0,
290                               this->get_block_size_bytes(),
291                               this->host_m_2.pData, 1, &event, &event_2);
292     test_error(err, "clEnqueueReadBuffer error");
293 
294     clWaitForEvents(1, &event_2);
295     test_error(err, "clWaitForEvents error");
296 
297     err = clReleaseEvent(event_2);
298     test_error(err, "clReleaseEvent error");
299 
300     err = clReleaseEvent(event);
301     test_error(err, "clReleaseEvent error");
302     return err;
303 }
304 
305 template <class T>
verify_RW_Buffer_mapping()306 cl_int cBuffer_check_mem_host_write_only<T>::verify_RW_Buffer_mapping()
307 {
308     T vv2 = 0;
309     this->host_m_2.Set_to(vv2);
310 
311     cl_event event;
312     cl_int err = CL_SUCCESS;
313 
314     void *dataPtr;
315     int size = this->get_block_size_bytes();
316     dataPtr =
317         clEnqueueMapBuffer(this->m_queue, this->m_buffer, this->m_blocking,
318                            CL_MAP_WRITE, 0, size, 0, NULL, &event, &err);
319     test_error(err, "clEnqueueMapBuffer error");
320 
321     if (!this->m_blocking)
322     {
323         err = clWaitForEvents(1, &event);
324         test_error(err, "clWaitForEvents error");
325     }
326 
327     err = clReleaseEvent(event);
328     test_error(err, "clReleaseEvent error");
329 
330     update_host_mem_2();
331 
332     if ((this->buffer_mem_flag & CL_MEM_USE_HOST_PTR)
333         && dataPtr != this->pHost_ptr)
334     {
335         log_error("Mapped host pointer difference found\n");
336         return FAILURE;
337     }
338 
339     if (!this->host_m_2.Equal((T *)dataPtr, this->m_nNumber_elements))
340     {
341         log_error("Buffer content difference found\n");
342         return FAILURE;
343     }
344 
345     err = clEnqueueUnmapMemObject(this->m_queue, this->m_buffer, dataPtr, 0,
346                                   nullptr, nullptr);
347     test_error(err, "clEnqueueUnmapMemObject error");
348 
349     // test map read
350     clEnqueueMapBuffer(this->m_queue, this->m_buffer, this->m_blocking,
351                        CL_MAP_READ, 0, this->get_block_size_bytes(), 0, NULL,
352                        &event, &err);
353 
354     if (err == CL_SUCCESS)
355     {
356         log_error("Calling clEnqueueMapBuffer (CL_MAP_READ) on a memory object "
357                   "created with the MEM_HOST_WRITE_ONLY flag should not return "
358                   "CL_SUCCESS\n");
359         err = FAILURE;
360     }
361     else
362     {
363         log_info("Test succeeded\n\n");
364         err = CL_SUCCESS;
365     }
366 
367     return err;
368 }
369 
370 #endif
371