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_checker_Image_MEM_HOST_WRITE_ONLY_h
17 #define test_conformance_checker_Image_MEM_HOST_WRITE_ONLY_h
18 
19 #include "checker_image_mem_host_read_only.hpp"
20 
21 template <class T>
22 class cImage_check_mem_host_write_only
23     : public cImage_check_mem_host_read_only<T> {
24 
25 public:
cImage_check_mem_host_write_only(cl_device_id deviceID,cl_context context,cl_command_queue queue)26     cImage_check_mem_host_write_only(cl_device_id deviceID, cl_context context,
27                                      cl_command_queue queue)
28         : cImage_check_mem_host_read_only<T>(deviceID, context, queue)
29     {}
30 
~cImage_check_mem_host_write_only()31     ~cImage_check_mem_host_write_only(){};
32 
33     clMemWrapper m_Image_2;
34 
35     cl_int verify_RW_Image();
36     cl_int verify_RW_Image_Mapping();
37 
38     cl_int Setup_Test_Environment();
39     cl_int update_host_mem_2();
40 
41     cl_int verify_data(T *pdtaIn);
42 };
43 
44 template <class T>
Setup_Test_Environment()45 cl_int cImage_check_mem_host_write_only<T>::Setup_Test_Environment()
46 {
47     int all = this->get_image_elements();
48 
49     T vv2 = 0;
50     this->host_m_2.Init(all, vv2);
51     vv2 = TEST_VALUE;
52     this->host_m_0.Init(all, vv2);
53 
54     cl_int err = CL_SUCCESS;
55     this->m_Image_2 = clCreateImage(
56         this->m_context,
57         CL_MEM_READ_WRITE | CL_MEM_HOST_READ_ONLY | CL_MEM_COPY_HOST_PTR,
58         &(this->m_cl_image_format), &(this->m_cl_Image_desc),
59         this->host_m_2.pData, &err);
60     test_error(err, "clCreateImage error");
61 
62     return err;
63 }
64 
65 // Copy image data from a write_only image to a read_write image and read the
66 // contents.
67 template <class T>
update_host_mem_2()68 cl_int cImage_check_mem_host_write_only<T>::update_host_mem_2()
69 {
70     size_t orig[3] = { 0, 0, 0 };
71     size_t img_region[3] = { 0, 0, 0 };
72     img_region[0] = this->m_cl_Image_desc.image_width;
73     img_region[1] = this->m_cl_Image_desc.image_height;
74     img_region[2] = this->m_cl_Image_desc.image_depth;
75 
76     cl_event event;
77     cl_int err = CL_SUCCESS;
78     err = clEnqueueCopyImage(this->m_queue, this->m_Image, this->m_Image_2,
79                              orig, orig, img_region, 0, NULL, &event);
80     test_error(err, "clEnqueueCopyImage error");
81 
82     if (!this->m_blocking)
83     {
84         err = clWaitForEvents(1, &event);
85         test_error(err, "clWaitForEvents error");
86     }
87 
88     err = clReleaseEvent(event);
89     test_error(err, "clReleaseEvent error");
90 
91     this->host_m_2.Set_to_zero();
92 
93     err = clEnqueueReadImage(
94         this->m_queue, this->m_Image_2, this->m_blocking, this->buffer_origin,
95         this->region, this->buffer_row_pitch_bytes,
96         this->buffer_slice_pitch_bytes, this->host_m_2.pData, 0, NULL, &event);
97     test_error(err, "clEnqueueReadImage error");
98 
99     if (!this->m_blocking)
100     {
101         err = clWaitForEvents(1, &event);
102         test_error(err, "clWaitForEvents error");
103     }
104 
105     err = clReleaseEvent(event);
106     test_error(err, "clReleaseEvent error");
107 
108     return err;
109 }
110 
111 template <class T>
verify_data(T * pdtaIn)112 cl_int cImage_check_mem_host_write_only<T>::verify_data(T *pdtaIn)
113 {
114     cl_int err = CL_SUCCESS;
115     if (!this->host_m_1.Equal_rect_from_orig(pdtaIn, this->buffer_origin,
116                                              this->region, this->host_row_pitch,
117                                              this->host_slice_pitch))
118     {
119         log_error("Image and host data difference found\n");
120         return FAILURE;
121     }
122 
123     int total = (int)(this->region[0] * this->region[1] * this->region[2]);
124     T v = TEST_VALUE;
125     int tot = (int)(this->host_m_2.Count(v));
126     if (tot != total)
127     {
128         log_error("Image data content difference found\n");
129         return FAILURE;
130     }
131 
132     return err;
133 }
134 
verify_RW_Image()135 template <class T> cl_int cImage_check_mem_host_write_only<T>::verify_RW_Image()
136 {
137     cl_int err = CL_SUCCESS;
138 
139     this->Init_rect();
140 
141     cl_event event;
142     size_t img_orig[3] = { 0, 0, 0 };
143     size_t img_region[3] = { 0, 0, 0 };
144     img_region[0] = this->m_cl_Image_desc.image_width;
145     img_region[1] = this->m_cl_Image_desc.image_height;
146     img_region[2] = this->m_cl_Image_desc.image_depth;
147 
148     int color[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
149     err = clEnqueueFillImage(this->m_queue, this->m_Image, &color, img_orig,
150                              img_region, 0, NULL,
151                              &event); // Fill the buffer with data
152 
153     if (!this->m_blocking)
154     {
155         err = clWaitForEvents(1, &event);
156         test_error(err, "clWaitForEvents error");
157     }
158     test_error(err, "clEnqueueFillImage error");
159 
160     err = clReleaseEvent(event);
161     test_error(err, "clReleaseEvent error");
162 
163     T v = TEST_VALUE;
164 
165     err = clEnqueueWriteImage(
166         this->m_queue, this->m_Image, this->m_blocking, this->buffer_origin,
167         this->region, this->buffer_row_pitch_bytes,
168         this->buffer_slice_pitch_bytes, this->host_m_0.pData, 0, NULL, &event);
169     test_error(err, "clEnqueueWriteImage error"); // Test writing to buffer
170 
171     if (!this->m_blocking)
172     {
173         err = clWaitForEvents(1, &event);
174         test_error(err, "clWaitForEvents error");
175     }
176 
177     err = clReleaseEvent(event);
178     test_error(err, "clReleaseEvent error");
179 
180     update_host_mem_2(); // Read buffer contents into mem_2
181 
182     err = this->verify_data(
183         this->host_m_2
184             .pData); // Compare the contents of mem_2 and mem_1,
185                      // mem_1 is same as mem_0 in setup test environment
186     test_error(err, "verify_data error");
187 
188     v = 0;
189     this->host_m_2.Set_to(v);
190     err = clEnqueueReadImage(
191         this->m_queue, this->m_Image, this->m_blocking, this->buffer_origin,
192         this->region, this->buffer_row_pitch_bytes,
193         this->buffer_slice_pitch_bytes, this->host_m_1.pData, 0, NULL, &event);
194 
195     if (err == CL_SUCCESS)
196     {
197         log_error(
198             "Calling clEnqueueReadImage on a memory object created with the "
199             "CL_MEM_HOST_WRITE_ONLY flag should not return CL_SUCCESS\n");
200         err = FAILURE;
201         return FAILURE;
202     }
203     else
204     {
205         log_info("Test succeeded\n\n");
206         err = CL_SUCCESS;
207     }
208 
209     /* Qualcomm fix: 12506 Do not wait on invalid event/ no need for
210     syncronization calls after clEnqueueReadImage fails
211      *
212      * The call to clEnqueueReadImage fails as expected and returns an invalid
213     event on
214      * which clWaitForEvents cannot be called. (It will rightly fail with a
215     CL_INVALID_EVENT error)
216      * Further, we don't need to do any additional flushes or finishes here
217     since we were in sync
218      * before the (failing) call to clEnqueueReadImage
219 
220     if (!this->m_blocking) {
221       err = clWaitForEvents(1, &event);
222       test_error(err, " clWaitForEvents error")
223     }
224     Qualcomm fix: end*/
225 
226     return err;
227 }
228 
229 template <class T>
verify_RW_Image_Mapping()230 cl_int cImage_check_mem_host_write_only<T>::verify_RW_Image_Mapping()
231 {
232     this->Init_rect();
233 
234     cl_event event;
235     size_t img_orig[3] = { 0, 0, 0 };
236     size_t img_region[3] = { 0, 0, 0 };
237     img_region[0] = this->m_cl_Image_desc.image_width;
238     img_region[1] = this->m_cl_Image_desc.image_height;
239     img_region[2] = this->m_cl_Image_desc.image_depth;
240 
241     int color[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
242     cl_int err = CL_SUCCESS;
243 
244 
245     // Fill image with pattern
246     err = clEnqueueFillImage(this->m_queue, this->m_Image, &color, img_orig,
247                              img_region, 0, NULL, &event);
248 
249     if (!this->m_blocking)
250     {
251         err = clWaitForEvents(1, &event);
252         test_error(err, "clWaitForEvents error");
253     }
254 
255     err = clReleaseEvent(event);
256     test_error(err, "clReleaseEvent error");
257 
258     // Map image for writing
259     T* dataPtr = (T*)clEnqueueMapImage(
260         this->m_queue, this->m_Image, this->m_blocking, CL_MAP_WRITE,
261         this->buffer_origin, this->region, &(this->buffer_row_pitch_bytes),
262         &(this->buffer_slice_pitch_bytes), 0, NULL, &event, &err);
263     test_error(err, "clEnqueueMapImage CL_MAP_WRITE pointer error");
264 
265     if (!this->m_blocking)
266     {
267         err = clWaitForEvents(1, &event);
268         test_error(err, "clWaitForEvents error");
269     }
270 
271     err = clReleaseEvent(event);
272     test_error(err, "clReleaseEvent error");
273 
274     // Verify map pointer
275     err = this->verify_mapping_ptr(dataPtr);
276     test_error(err, "clEnqueueMapImage CL_MAP_WRITE pointer error");
277 
278     // Verify mapped data
279 
280     // The verify_data_with_offset method below compares dataPtr against
281     // this->host_m_2.pData. The comparison should start at origin {0, 0, 0}.
282     update_host_mem_2();
283 
284     // Check the content of mem and host_ptr
285     size_t offset[3] = { 0, 0, 0 };
286     err = cImage_check_mem_host_read_only<T>::verify_data_with_offset(dataPtr,
287                                                                       offset);
288     test_error(err, "verify_data error");
289 
290     // Unmap memory object
291     err = clEnqueueUnmapMemObject(this->m_queue, this->m_Image, dataPtr, 0,
292                                   NULL, &event);
293     test_error(err, "clEnqueueUnmapMemObject error");
294 
295     if (!this->m_blocking)
296     {
297         err = clWaitForEvents(1, &event);
298         test_error(err, "clWaitForEvents error");
299     }
300 
301     err = clReleaseEvent(event);
302     test_error(err, "clReleaseEvent error");
303 
304     dataPtr = (T*)clEnqueueMapImage(
305         this->m_queue, this->m_Image, this->m_blocking, CL_MAP_READ,
306         this->buffer_origin, this->region, &(this->buffer_row_pitch_bytes),
307         &(this->buffer_slice_pitch_bytes), 0, NULL, &event, &err);
308 
309     if (err == CL_SUCCESS)
310     {
311         log_error("Calling clEnqueueMapImage (CL_MAP_READ) on a memory object "
312                   "created with the CL_MEM_HOST_WRITE_ONLY flag should not "
313                   "return CL_SUCCESS\n");
314         err = FAILURE;
315         return FAILURE;
316     }
317     else
318     {
319         log_info("Test succeeded\n\n");
320         err = CL_SUCCESS;
321     }
322 
323     return err;
324 }
325 
326 #endif
327