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.h"
17
18 #define ADD_BUFFER_PROPERTIES(w, x, y, z) \
19 { w, x, y, z, #x, #y, #z, }
20
21 BufferProperties bufferProperties[] =
22 {
23 ADD_BUFFER_PROPERTIES( 0x110, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE),
24 ADD_BUFFER_PROPERTIES( 0x1100, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE),
25 ADD_BUFFER_PROPERTIES( 0x8000, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE),
26
27 ADD_BUFFER_PROPERTIES( 0x7FFFF, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0),
28 ADD_BUFFER_PROPERTIES( 0x110000, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0),
29 ADD_BUFFER_PROPERTIES( 0x110000, D3D11_BIND_STREAM_OUTPUT, D3D11_USAGE_DEFAULT, 0),
30 ADD_BUFFER_PROPERTIES( 0x110001, D3D11_BIND_STREAM_OUTPUT, D3D11_USAGE_DEFAULT, 0),
31
32 ADD_BUFFER_PROPERTIES( 0x11, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DEFAULT, 0),
33 ADD_BUFFER_PROPERTIES( 0x11, D3D11_BIND_INDEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE),
34 ADD_BUFFER_PROPERTIES( 0x121, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DEFAULT, 0),
35 ADD_BUFFER_PROPERTIES( 0x1234, D3D11_BIND_INDEX_BUFFER, D3D11_USAGE_DEFAULT, 0),
36 ADD_BUFFER_PROPERTIES( 0x12345, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE),
37 ADD_BUFFER_PROPERTIES( 0x123456, D3D11_BIND_INDEX_BUFFER, D3D11_USAGE_DEFAULT, 0),
38 #if 0 // avoid large sizes on automation
39 ADD_BUFFER_PROPERTIES( 0x1234567, D3D11_BIND_INDEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE),
40
41 ADD_BUFFER_PROPERTIES( 0x4000000, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DEFAULT, 0),
42 ADD_BUFFER_PROPERTIES( 0x4000004, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DEFAULT, 0),
43 ADD_BUFFER_PROPERTIES( 0x4000008, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DEFAULT, 0),
44 ADD_BUFFER_PROPERTIES( 0x4000011, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DEFAULT, 0),
45 ADD_BUFFER_PROPERTIES( 0x4000014, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DEFAULT, 0),
46 #endif
47 };
48 UINT bufferPropertyCount = sizeof(bufferProperties)/sizeof(bufferProperties[0]);
49
SubTestBuffer(cl_context context,cl_command_queue command_queue,ID3D11Device * pDevice,ID3D11DeviceContext * pDC,const BufferProperties * props)50 void SubTestBuffer(
51 cl_context context,
52 cl_command_queue command_queue,
53 ID3D11Device* pDevice,
54 ID3D11DeviceContext* pDC,
55 const BufferProperties* props)
56 {
57 ID3D11Buffer* pBuffer = NULL;
58 HRESULT hr = S_OK;
59 cl_mem mem = NULL;
60 cl_int result = CL_SUCCESS;
61
62 HarnessD3D11_TestBegin("Buffer: Size=%d, BindFlags=%s, Usage=%s, CPUAccess=%s",
63 props->ByteWidth,
64 props->name_BindFlags,
65 props->name_Usage,
66 props->name_CPUAccess);
67
68 // create the D3D11 resource
69 {
70 D3D11_BUFFER_DESC desc = {0};
71 desc.ByteWidth = props->ByteWidth;
72 desc.Usage = props->Usage;
73 desc.CPUAccessFlags = props->CPUAccess;
74 desc.BindFlags = props->BindFlags;
75 desc.MiscFlags = 0;
76 hr = pDevice->CreateBuffer(&desc, NULL, &pBuffer);
77 TestRequire(SUCCEEDED(hr), "Creating vertex buffer failed!");
78 }
79
80 // populate the D3D11 resource with data
81 {
82 ID3D11Buffer* pStagingBuffer = NULL;
83 char *pStagingData = NULL;
84 D3D11_MAPPED_SUBRESOURCE map = {0};
85
86 // create a staging buffer to use to copy data to the D3D buffer
87 D3D11_BUFFER_DESC desc = {0};
88 desc.ByteWidth = 16;
89 desc.Usage = D3D11_USAGE_STAGING;
90 desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE|D3D11_CPU_ACCESS_READ;
91 desc.BindFlags = 0;
92 desc.MiscFlags = 0;
93 hr = pDevice->CreateBuffer(&desc, NULL, &pStagingBuffer);
94 TestRequire(SUCCEEDED(hr), "Creating staging vertex buffer failed!");
95
96 // populate the staging buffer
97 hr = pDC->Map(
98 pStagingBuffer,
99 0,
100 D3D11_MAP_READ_WRITE,
101 0,
102 &map);
103 TestRequire(SUCCEEDED(hr), "Map failed!");
104 memcpy(map.pData, "abcdXXXXxxxx1234", 16);
105 pDC->Unmap(pStagingBuffer, 0);
106 TestRequire(SUCCEEDED(hr), "Unmap failed!");
107
108 // copy 'abcdXXXX' to the front of the buffer and 'xxxx1234' to the back
109 D3D11_BOX box = {0};
110 box.front = 0;
111 box.back = 1;
112 box.top = 0;
113 box.bottom = 1;
114
115 box.left = 0;
116 box.right = 8;
117 pDC->CopySubresourceRegion(
118 pBuffer,
119 0,
120 0,
121 0,
122 0,
123 pStagingBuffer,
124 0,
125 &box);
126 box.left = 8;
127 box.right = 16;
128 pDC->CopySubresourceRegion(
129 pBuffer,
130 0,
131 props->ByteWidth-8,
132 0,
133 0,
134 pStagingBuffer,
135 0,
136 &box);
137 pStagingBuffer->Release();
138 }
139
140 // share the resource with OpenCL
141 {
142 mem = clCreateFromD3D11BufferKHR(
143 context,
144 0,
145 pBuffer,
146 &result);
147 TestRequire(CL_SUCCESS == result, "clCreateFromD3D11BufferKHR failed");
148 }
149
150 // validate the OpenCL mem obj's properties
151 {
152 ID3D11Resource* clResource = NULL;
153 result = clGetMemObjectInfo(
154 mem,
155 CL_MEM_D3D11_RESOURCE_KHR,
156 sizeof(clResource),
157 &clResource,
158 NULL);
159 TestRequire(result == CL_SUCCESS, "clGetMemObjectInfo for CL_MEM_D3D11_RESOURCE_KHR failed.");
160 TestRequire(clResource == pBuffer, "clGetMemObjectInfo for CL_MEM_D3D11_RESOURCE_KHR returned incorrect value.");
161 }
162
163 // acquire the resource from OpenCL
164 {
165 result = clEnqueueAcquireD3D11ObjectsKHR(
166 command_queue,
167 1,
168 &mem,
169 0,
170 NULL,
171 NULL);
172 TestRequire(result == CL_SUCCESS, "clEnqueueAcquireD3D11ObjectsKHR failed.");
173 }
174
175 // read+write data from the buffer in OpenCL
176 {
177 // overwrite the 'XXXX' with '1234' and the 'xxxx' with 'abcd' so we now have
178 // 'abcd1234' at the beginning and end of the buffer
179 result = clEnqueueCopyBuffer(
180 command_queue,
181 mem,
182 mem,
183 0,
184 props->ByteWidth-8,
185 4,
186 0,
187 NULL,
188 NULL);
189 TestRequire(result == CL_SUCCESS, "clEnqueueCopyBuffer failed.");
190
191 result = clEnqueueCopyBuffer(
192 command_queue,
193 mem,
194 mem,
195 props->ByteWidth-4,
196 4,
197 4,
198 0,
199 NULL,
200 NULL);
201 TestRequire(result == CL_SUCCESS, "clEnqueueCopyBuffer failed.");
202 }
203
204 // release the resource from OpenCL
205 {
206 result = clEnqueueReleaseD3D11ObjectsKHR(
207 command_queue,
208 1,
209 &mem,
210 0,
211 NULL,
212 NULL);
213 TestRequire(result == CL_SUCCESS, "clEnqueueReleaseD3D11ObjectsKHR failed.");
214 }
215
216 // read data in D3D
217 {
218 ID3D11Buffer* pStagingBuffer = NULL;
219 char *pStagingData = NULL;
220 D3D11_MAPPED_SUBRESOURCE map = {0};
221
222 // create a staging buffer to read the data back
223 D3D11_BUFFER_DESC desc = {0};
224 desc.ByteWidth = 16;
225 desc.Usage = D3D11_USAGE_STAGING;
226 desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE|D3D11_CPU_ACCESS_READ;
227 desc.BindFlags = 0;
228 desc.MiscFlags = 0;
229 hr = pDevice->CreateBuffer(&desc, NULL, &pStagingBuffer);
230 TestRequire(SUCCEEDED(hr), "Creating staging vertex buffer failed!");
231
232 // make sure the staging buffer doesn't get stale data
233 hr = pDC->Map(
234 pStagingBuffer,
235 0,
236 D3D11_MAP_READ_WRITE,
237 0,
238 &map);
239 TestRequire(SUCCEEDED(hr), "Map failed!");
240 memset(map.pData, 0, 16);
241 pDC->Unmap(pStagingBuffer, 0);
242 TestRequire(SUCCEEDED(hr), "Unmap failed!");
243
244 // copy the 'abcd1234' from the front and back of the buffer to the staging buffer
245 D3D11_BOX box = {0};
246 box.front = 0;
247 box.back = 1;
248 box.top = 0;
249 box.bottom = 1;
250
251 box.left = 0;
252 box.right = 8;
253 pDC->CopySubresourceRegion(
254 pStagingBuffer,
255 0,
256 0,
257 0,
258 0,
259 pBuffer,
260 0,
261 &box);
262 box.left = props->ByteWidth-8;
263 box.right = props->ByteWidth;
264 pDC->CopySubresourceRegion(
265 pStagingBuffer,
266 0,
267 8,
268 0,
269 0,
270 pBuffer,
271 0,
272 &box);
273 TestRequire(SUCCEEDED(hr), "CopySubresourceRegion failed!");
274
275 // verify that we got the 'abcd1234'
276 hr = pDC->Map(
277 pStagingBuffer,
278 0,
279 D3D11_MAP_READ_WRITE,
280 0,
281 &map);
282 TestRequire(SUCCEEDED(hr), "Map failed!");
283 TestRequire(!memcmp(map.pData, "abcd1234abcd1234", 16), "Data was not accurately");
284 pDC->Unmap(pStagingBuffer, 0);
285 TestRequire(SUCCEEDED(hr), "Unmap failed!");
286
287 pStagingBuffer->Release();
288 }
289
290 Cleanup:
291
292 if (pBuffer)
293 {
294 pBuffer->Release();
295 }
296 if (mem)
297 {
298 clReleaseMemObject(mem);
299 }
300
301 HarnessD3D11_TestEnd();
302 }
303
304
TestDeviceBuffer(cl_context context,cl_command_queue command_queue,ID3D11Device * pDevice,ID3D11DeviceContext * pDC)305 void TestDeviceBuffer(
306 cl_context context,
307 cl_command_queue command_queue,
308 ID3D11Device* pDevice,
309 ID3D11DeviceContext* pDC)
310 {
311 for (UINT i = 0; i < bufferPropertyCount; ++i)
312 {
313 SubTestBuffer(
314 context,
315 command_queue,
316 pDevice,
317 pDC,
318 &bufferProperties[i]);
319 }
320 }
321
322