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