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 #define _CRT_SECURE_NO_WARNINGS
17 #include "harness.h"
18
19 Texture3DSize texture3DSizes[] =
20 {
21 {
22 4, // Width
23 4, // Height
24 4, // Depth
25 1, // MipLevels
26 1, // SubResourceCount
27 { // SubResources
28 { 0 }, // MipLevel
29 { 0 }, // MipLevel
30 { 0 }, // MipLevel
31 { 0 }, // MipLevel
32 },
33 0, // MiscFlags
34 },
35 {
36 127, // Width
37 55, // Height
38 33, // Depth
39 1, // MipLevels
40 1, // SubResourceCount
41 { // SubResources
42 { 0 }, // MipLevel
43 { 0 }, // MipLevel
44 { 0 }, // MipLevel
45 { 0 }, // MipLevel
46 },
47 0, // MiscFlags
48 },
49 {
50 128, // Width
51 256, // Height
52 64, // Depth
53 4, // MipLevels
54 3, // SubResourceCount
55 { // SubResources
56 { 2 }, // MipLevel
57 { 1 }, // MipLevel
58 { 0 }, // MipLevel
59 { 0 }, // MipLevel
60 },
61 0, // MiscFlags
62 },
63 {
64 512, // Width
65 64, // Height
66 32, // Depth
67 3, // MipLevels
68 1, // SubResourceCount
69 { // SubResources
70 { 2 }, // MipLevel
71 { 0 }, // MipLevel
72 { 0 }, // MipLevel
73 { 0 }, // MipLevel
74 },
75 0, // MiscFlags
76 },
77 };
78 UINT texture3DSizeCount = sizeof(texture3DSizes)/sizeof(texture3DSizes[0]);
79
80 const char *
81 texture3DPatterns[2][2][2] =
82 {
83 {
84 {"PlaceTheCasseroleDis", "hInAColdOvenPlaceACh"},
85 {"airFacingTheOvenAndS", "itInItForeverThinkAb"},
86 },
87 {
88 {"outHowHungryYouAreWh", "enNightFallsDoNotTur"},
89 {"nOnTheLightMyEyeBeca", "meInflamedIHateCamus"},
90 },
91 };
92
SubTestTexture3D(cl_context context,cl_command_queue command_queue,ID3D11Device * pDevice,ID3D11DeviceContext * pDC,const TextureFormat * format,const Texture3DSize * size)93 void SubTestTexture3D(
94 cl_context context,
95 cl_command_queue command_queue,
96 ID3D11Device* pDevice,
97 ID3D11DeviceContext* pDC,
98 const TextureFormat* format,
99 const Texture3DSize* size)
100 {
101 ID3D11Texture3D* pTexture = NULL;
102 HRESULT hr = S_OK;
103
104 cl_int result = CL_SUCCESS;
105
106 HarnessD3D11_TestBegin("3D Texture: Format=%s, Width=%d, Height=%d, Depth=%d, MipLevels=%d",
107 format->name_format,
108 size->Width,
109 size->Height,
110 size->Depth,
111 size->MipLevels);
112
113 struct
114 {
115 cl_mem mem;
116 UINT subResource;
117 UINT width;
118 UINT height;
119 UINT depth;
120 }
121 subResourceInfo[4];
122
123 // create the D3D11 resources
124 {
125 D3D11_TEXTURE3D_DESC desc;
126 memset(&desc, 0, sizeof(desc) );
127 desc.Width = size->Width;
128 desc.Height = size->Height;
129 desc.Depth = size->Depth;
130 desc.MipLevels = size->MipLevels;
131 desc.Format = format->format;
132 desc.Usage = D3D11_USAGE_DEFAULT;
133 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
134 desc.CPUAccessFlags = 0;
135 desc.MiscFlags = 0;
136
137 hr = pDevice->CreateTexture3D(&desc, NULL, &pTexture);
138 TestRequire(SUCCEEDED(hr), "CreateTexture3D failed.");
139 }
140
141 // initialize some useful variables
142 for (UINT i = 0; i < size->SubResourceCount; ++i)
143 {
144 // compute the expected values for the subresource
145 subResourceInfo[i].subResource = size->subResources[i].MipLevel;
146 subResourceInfo[i].width = size->Width;
147 subResourceInfo[i].height = size->Height;
148 subResourceInfo[i].depth = size->Depth;
149 for (UINT j = 0; j < size->subResources[i].MipLevel; ++j) {
150 subResourceInfo[i].width /= 2;
151 subResourceInfo[i].height /= 2;
152 subResourceInfo[i].depth /= 2;
153 }
154 subResourceInfo[i].mem = NULL;
155 }
156
157 // copy a pattern into the corners of the image, coordinates
158 for (UINT i = 0; i < size->SubResourceCount; ++i)
159 for (UINT x = 0; x < 2; ++x)
160 for (UINT y = 0; y < 2; ++y)
161 for (UINT z = 0; z < 2; ++z)
162 {
163 // create the staging buffer
164 ID3D11Texture3D* pStagingBuffer = NULL;
165 {
166 D3D11_TEXTURE3D_DESC desc = {0};
167 desc.Width = 1;
168 desc.Height = 1;
169 desc.Depth = 1;
170 desc.MipLevels = 1;
171 desc.Format = format->format;
172 desc.Usage = D3D11_USAGE_STAGING;
173 desc.BindFlags = 0;
174 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
175 desc.MiscFlags = 0;
176 hr = pDevice->CreateTexture3D(&desc, NULL, &pStagingBuffer);
177 TestRequire(SUCCEEDED(hr), "CreateTexture3D failed.");
178 }
179
180 // write the data to the staging buffer
181 {
182 D3D11_MAPPED_SUBRESOURCE mappedTexture;
183 hr = pDC->Map(
184 pStagingBuffer,
185 0,
186 D3D11_MAP_READ_WRITE,
187 0,
188 &mappedTexture);
189 memcpy(mappedTexture.pData, texture3DPatterns[x][y][z], format->bytesPerPixel);
190 pDC->Unmap(pStagingBuffer, 0);
191 }
192
193 // copy the data to to the texture
194 {
195 D3D11_BOX box = {0};
196 box.front = 0; box.back = 1;
197 box.top = 0; box.bottom = 1;
198 box.left = 0; box.right = 1;
199 pDC->CopySubresourceRegion(
200 pTexture,
201 subResourceInfo[i].subResource,
202 x ? subResourceInfo[i].width - 1 : 0,
203 y ? subResourceInfo[i].height - 1 : 0,
204 z ? subResourceInfo[i].depth - 1 : 0,
205 pStagingBuffer,
206 0,
207 &box);
208 }
209
210 pStagingBuffer->Release();
211 }
212
213 // create the cl_mem objects for the resources and verify its sanity
214 for (UINT i = 0; i < size->SubResourceCount; ++i)
215 {
216 // create a cl_mem for the resource
217 subResourceInfo[i].mem = clCreateFromD3D11Texture3DKHR(
218 context,
219 0,
220 pTexture,
221 subResourceInfo[i].subResource,
222 &result);
223 if (CL_IMAGE_FORMAT_NOT_SUPPORTED == result)
224 {
225 goto Cleanup;
226 }
227 TestRequire(result == CL_SUCCESS, "clCreateFromD3D11Texture3DKHR failed");
228
229 // query resource pointer and verify
230 ID3D11Resource* clResource = NULL;
231 result = clGetMemObjectInfo(
232 subResourceInfo[i].mem,
233 CL_MEM_D3D11_RESOURCE_KHR,
234 sizeof(clResource),
235 &clResource,
236 NULL);
237 TestRequire(result == CL_SUCCESS, "clGetMemObjectInfo for CL_MEM_D3D11_RESOURCE_KHR failed.");
238 TestRequire(clResource == pTexture, "clGetMemObjectInfo for CL_MEM_D3D11_RESOURCE_KHR returned incorrect value.");
239
240 // query subresource and verify
241 UINT clSubResource;
242 result = clGetImageInfo(
243 subResourceInfo[i].mem,
244 CL_IMAGE_D3D11_SUBRESOURCE_KHR,
245 sizeof(clSubResource),
246 &clSubResource,
247 NULL);
248 TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_D3D11_SUBRESOURCE_KHR failed");
249 TestRequire(clSubResource == subResourceInfo[i].subResource, "clGetImageInfo for CL_IMAGE_D3D11_SUBRESOURCE_KHR returned incorrect value.");
250
251 // query format and verify
252 cl_image_format clFormat;
253 result = clGetImageInfo(
254 subResourceInfo[i].mem,
255 CL_IMAGE_FORMAT,
256 sizeof(clFormat),
257 &clFormat,
258 NULL);
259 TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_FORMAT failed");
260 TestRequire(clFormat.image_channel_order == format->channel_order, "clGetImageInfo for CL_IMAGE_FORMAT returned incorrect channel order.");
261 TestRequire(clFormat.image_channel_data_type == format->channel_type, "clGetImageInfo for CL_IMAGE_FORMAT returned incorrect channel data type.");
262
263 // query width
264 size_t width;
265 result = clGetImageInfo(
266 subResourceInfo[i].mem,
267 CL_IMAGE_WIDTH,
268 sizeof(width),
269 &width,
270 NULL);
271 TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_WIDTH failed");
272 TestRequire(width == subResourceInfo[i].width, "clGetImageInfo for CL_IMAGE_HEIGHT returned incorrect value.");
273
274 // query height
275 size_t height;
276 result = clGetImageInfo(
277 subResourceInfo[i].mem,
278 CL_IMAGE_HEIGHT,
279 sizeof(height),
280 &height,
281 NULL);
282 TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_HEIGHT failed");
283 TestRequire(height == subResourceInfo[i].height, "clGetImageInfo for CL_IMAGE_HEIGHT returned incorrect value.");
284
285 // query depth
286 size_t depth;
287 result = clGetImageInfo(
288 subResourceInfo[i].mem,
289 CL_IMAGE_DEPTH,
290 sizeof(depth),
291 &depth,
292 NULL);
293 TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_DEPTH failed");
294 TestRequire(depth == subResourceInfo[i].depth, "clGetImageInfo for CL_IMAGE_DEPTH returned incorrect value.");
295
296 }
297
298 // acquire the resources for OpenCL
299 {
300 cl_mem memToAcquire[MAX_REGISTERED_SUBRESOURCES];
301
302 // cut the registered sub-resources into two sets and send the acquire calls for them separately
303 for(UINT i = 0; i < size->SubResourceCount; ++i)
304 {
305 memToAcquire[i] = subResourceInfo[i].mem;
306 }
307
308 // do the acquire
309 result = clEnqueueAcquireD3D11ObjectsKHR(
310 command_queue,
311 size->SubResourceCount,
312 memToAcquire,
313 0,
314 NULL,
315 NULL);
316 TestRequire(result == CL_SUCCESS, "clEnqueueAcquireD3D11ObjectsKHR failed.");
317 }
318
319 // download the data using OpenCL & compare with the expected results
320 // copy the corners of the image into the image
321 for (UINT i = 0; i < size->SubResourceCount; ++i)
322 for (UINT x = 0; x < 2; ++x)
323 for (UINT y = 0; y < 2; ++y)
324 for (UINT z = 0; z < 2; ++z)
325 {
326 if (x == y && y == z && 0)
327 {
328 continue;
329 }
330 size_t src[3] =
331 {
332 x ? subResourceInfo[i].width - 1 : 0,
333 y ? subResourceInfo[i].height - 1 : 0,
334 z ? subResourceInfo[i].depth - 1 : 0,
335 };
336 size_t dst[3] =
337 {
338 x ? subResourceInfo[i].width - 2 : 1,
339 y ? subResourceInfo[i].height - 2 : 1,
340 z ? subResourceInfo[i].depth - 2 : 1,
341 };
342 size_t region[3] =
343 {
344 1,
345 1,
346 1,
347 };
348 result = clEnqueueCopyImage(
349 command_queue,
350 subResourceInfo[i].mem,
351 subResourceInfo[i].mem,
352 src,
353 dst,
354 region,
355 0,
356 NULL,
357 NULL);
358 TestRequire(result == CL_SUCCESS, "clEnqueueCopyImage failed.");
359 }
360
361 // release the resource from OpenCL
362 {
363 cl_mem memToAcquire[MAX_REGISTERED_SUBRESOURCES];
364 for(UINT i = 0; i < size->SubResourceCount; ++i)
365 {
366 memToAcquire[i] = subResourceInfo[i].mem;
367 }
368
369 // do the release
370 result = clEnqueueReleaseD3D11ObjectsKHR(
371 command_queue,
372 size->SubResourceCount,
373 memToAcquire,
374 0,
375 NULL,
376 NULL);
377 TestRequire(result == CL_SUCCESS, "clEnqueueReleaseD3D11ObjectsKHR failed.");
378 }
379
380 for (UINT i = 0; i < size->SubResourceCount; ++i)
381 for (UINT x = 0; x < 2; ++x)
382 for (UINT y = 0; y < 2; ++y)
383 for (UINT z = 0; z < 2; ++z)
384 {
385 // create the staging buffer
386 ID3D11Texture3D* pStagingBuffer = NULL;
387 {
388 D3D11_TEXTURE3D_DESC desc = {0};
389 desc.Width = 1;
390 desc.Height = 1;
391 desc.Depth = 1;
392 desc.MipLevels = 1;
393 desc.Format = format->format;
394 desc.Usage = D3D11_USAGE_STAGING;
395 desc.BindFlags = 0;
396 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
397 desc.MiscFlags = 0;
398 hr = pDevice->CreateTexture3D(&desc, NULL, &pStagingBuffer);
399 TestRequire(SUCCEEDED(hr), "Failed to create staging buffer.");
400 }
401
402 // wipe out the staging buffer to make sure we don't get stale values
403 {
404 D3D11_MAPPED_SUBRESOURCE mappedTexture;
405 hr = pDC->Map(
406 pStagingBuffer,
407 0,
408 D3D11_MAP_READ_WRITE,
409 0,
410 &mappedTexture);
411 TestRequire(SUCCEEDED(hr), "Failed to map staging buffer");
412 memset(mappedTexture.pData, 0, format->bytesPerPixel);
413 pDC->Unmap(pStagingBuffer, 0);
414 }
415
416 // copy the pixel to the staging buffer
417 {
418 D3D11_BOX box = {0};
419 box.left = x ? subResourceInfo[i].width - 2 : 1; box.right = box.left + 1;
420 box.top = y ? subResourceInfo[i].height - 2 : 1; box.bottom = box.top + 1;
421 box.front = z ? subResourceInfo[i].depth - 2 : 1; box.back = box.front + 1;
422 pDC->CopySubresourceRegion(
423 pStagingBuffer,
424 0,
425 0,
426 0,
427 0,
428 pTexture,
429 subResourceInfo[i].subResource,
430 &box);
431 }
432
433 // make sure we read back what was written next door
434 {
435 D3D11_MAPPED_SUBRESOURCE mappedTexture;
436 hr = pDC->Map(
437 pStagingBuffer,
438 0,
439 D3D11_MAP_READ_WRITE,
440 0,
441 &mappedTexture);
442 TestRequire(SUCCEEDED(hr), "Failed to map staging buffer");
443 TestRequire(
444 !memcmp(mappedTexture.pData, texture3DPatterns[x][y][z], format->bytesPerPixel),
445 "Failed to map staging buffer");
446 pDC->Unmap(pStagingBuffer, 0);
447 }
448
449 pStagingBuffer->Release();
450 }
451
452
453 Cleanup:
454
455 if (pTexture)
456 {
457 pTexture->Release();
458 }
459 for (UINT i = 0; i < size->SubResourceCount; ++i)
460 {
461 clReleaseMemObject(subResourceInfo[i].mem);
462 }
463
464 HarnessD3D11_TestEnd();
465 }
466
467
TestDeviceTexture3D(cl_device_id device,cl_context context,cl_command_queue command_queue,ID3D11Device * pDevice,ID3D11DeviceContext * pDC)468 void TestDeviceTexture3D(
469 cl_device_id device,
470 cl_context context,
471 cl_command_queue command_queue,
472 ID3D11Device* pDevice,
473 ID3D11DeviceContext* pDC)
474 {
475 cl_int result = CL_SUCCESS;
476
477
478 for (UINT format = 0, size = 0; format < formatCount; ++size, ++format)
479 {
480 SubTestTexture3D(
481 context,
482 command_queue,
483 pDevice,
484 pDC,
485 &formats[format],
486 &texture3DSizes[size % texture3DSizeCount]);
487 }
488 }
489
490