// // Copyright (c) 2017 The Khronos Group Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "harness.h" #define ADD_BUFFER_PROPERTIES(w, x, y, z) \ { w, x, y, z, #x, #y, #z, } BufferProperties bufferProperties[] = { ADD_BUFFER_PROPERTIES( 0x100, D3D10_BIND_CONSTANT_BUFFER, D3D10_USAGE_DYNAMIC, D3D10_CPU_ACCESS_WRITE), ADD_BUFFER_PROPERTIES( 0x1000, D3D10_BIND_CONSTANT_BUFFER, D3D10_USAGE_DYNAMIC, D3D10_CPU_ACCESS_WRITE), ADD_BUFFER_PROPERTIES( 0x8000, D3D10_BIND_CONSTANT_BUFFER, D3D10_USAGE_DYNAMIC, D3D10_CPU_ACCESS_WRITE), ADD_BUFFER_PROPERTIES( 0x7FFFF, D3D10_BIND_SHADER_RESOURCE, D3D10_USAGE_DEFAULT, 0), ADD_BUFFER_PROPERTIES( 0x100000, D3D10_BIND_SHADER_RESOURCE, D3D10_USAGE_DEFAULT, 0), ADD_BUFFER_PROPERTIES( 0x100000, D3D10_BIND_STREAM_OUTPUT, D3D10_USAGE_DEFAULT, 0), ADD_BUFFER_PROPERTIES( 0x100001, D3D10_BIND_STREAM_OUTPUT, D3D10_USAGE_DEFAULT, 0), ADD_BUFFER_PROPERTIES( 0x10, D3D10_BIND_VERTEX_BUFFER, D3D10_USAGE_DEFAULT, 0), ADD_BUFFER_PROPERTIES( 0x11, D3D10_BIND_INDEX_BUFFER, D3D10_USAGE_DYNAMIC, D3D10_CPU_ACCESS_WRITE), ADD_BUFFER_PROPERTIES( 0x121, D3D10_BIND_VERTEX_BUFFER, D3D10_USAGE_DEFAULT, 0), ADD_BUFFER_PROPERTIES( 0x1234, D3D10_BIND_INDEX_BUFFER, D3D10_USAGE_DEFAULT, 0), ADD_BUFFER_PROPERTIES( 0x12345, D3D10_BIND_VERTEX_BUFFER, D3D10_USAGE_DYNAMIC, D3D10_CPU_ACCESS_WRITE), ADD_BUFFER_PROPERTIES( 0x123456, D3D10_BIND_INDEX_BUFFER, D3D10_USAGE_DEFAULT, 0), #if 0 // avoid large sizes on automation ADD_BUFFER_PROPERTIES( 0x1234567, D3D10_BIND_INDEX_BUFFER, D3D10_USAGE_DYNAMIC, D3D10_CPU_ACCESS_WRITE), ADD_BUFFER_PROPERTIES( 0x4000000, D3D10_BIND_VERTEX_BUFFER, D3D10_USAGE_DEFAULT, 0), ADD_BUFFER_PROPERTIES( 0x4000004, D3D10_BIND_VERTEX_BUFFER, D3D10_USAGE_DEFAULT, 0), ADD_BUFFER_PROPERTIES( 0x4000008, D3D10_BIND_VERTEX_BUFFER, D3D10_USAGE_DEFAULT, 0), ADD_BUFFER_PROPERTIES( 0x4000010, D3D10_BIND_VERTEX_BUFFER, D3D10_USAGE_DEFAULT, 0), ADD_BUFFER_PROPERTIES( 0x4000014, D3D10_BIND_VERTEX_BUFFER, D3D10_USAGE_DEFAULT, 0), #endif }; UINT bufferPropertyCount = sizeof(bufferProperties)/sizeof(bufferProperties[0]); void SubTestBuffer( cl_context context, cl_command_queue command_queue, ID3D10Device* pDevice, const BufferProperties* props) { ID3D10Buffer* pBuffer = NULL; HRESULT hr = S_OK; cl_mem mem = NULL; cl_int result = CL_SUCCESS; HarnessD3D10_TestBegin("Buffer: Size=%d, BindFlags=%s, Usage=%s, CPUAccess=%s", props->ByteWidth, props->name_BindFlags, props->name_Usage, props->name_CPUAccess); // create the D3D10 resource { D3D10_BUFFER_DESC desc = {0}; desc.ByteWidth = props->ByteWidth; desc.Usage = props->Usage; desc.CPUAccessFlags = props->CPUAccess; desc.BindFlags = props->BindFlags; desc.MiscFlags = 0; hr = pDevice->CreateBuffer(&desc, NULL, &pBuffer); TestRequire(SUCCEEDED(hr), "Creating vertex buffer failed!"); } // populate the D3D10 resource with data { ID3D10Buffer* pStagingBuffer = NULL; char *pStagingData = NULL; // create a staging buffer to use to copy data to the D3D buffer D3D10_BUFFER_DESC desc = {0}; desc.ByteWidth = 16; desc.Usage = D3D10_USAGE_STAGING; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE|D3D10_CPU_ACCESS_READ; desc.BindFlags = 0; desc.MiscFlags = 0; hr = pDevice->CreateBuffer(&desc, NULL, &pStagingBuffer); TestRequire(SUCCEEDED(hr), "Creating staging vertex buffer failed!"); // populate the staging buffer hr = pStagingBuffer->Map( D3D10_MAP_READ_WRITE, 0, (void **)&pStagingData); TestRequire(SUCCEEDED(hr), "Map failed!"); memcpy(pStagingData, "abcdXXXXxxxx1234", 16); pStagingBuffer->Unmap(); TestRequire(SUCCEEDED(hr), "Unmap failed!"); // copy 'abcdXXXX' to the front of the buffer and 'xxxx1234' to the back D3D10_BOX box = {0}; box.front = 0; box.back = 1; box.top = 0; box.bottom = 1; box.left = 0; box.right = 8; pDevice->CopySubresourceRegion( pBuffer, 0, 0, 0, 0, pStagingBuffer, 0, &box); box.left = 8; box.right = 16; pDevice->CopySubresourceRegion( pBuffer, 0, props->ByteWidth-8, 0, 0, pStagingBuffer, 0, &box); pStagingBuffer->Release(); } // share the resource with OpenCL { mem = clCreateFromD3D10BufferKHR( context, 0, pBuffer, &result); TestRequire(CL_SUCCESS == result, "clCreateFromD3D10BufferKHR failed"); } // validate the OpenCL mem obj's properties { ID3D10Resource* clResource = NULL; result = clGetMemObjectInfo( mem, CL_MEM_D3D10_RESOURCE_KHR, sizeof(clResource), &clResource, NULL); TestRequire(result == CL_SUCCESS, "clGetMemObjectInfo for CL_MEM_D3D10_RESOURCE_KHR failed."); TestRequire(clResource == pBuffer, "clGetMemObjectInfo for CL_MEM_D3D10_RESOURCE_KHR returned incorrect value."); } // acquire the resource from OpenCL { result = clEnqueueAcquireD3D10ObjectsKHR( command_queue, 1, &mem, 0, NULL, NULL); TestRequire(result == CL_SUCCESS, "clEnqueueAcquireD3D10ObjectsKHR failed."); } // read+write data from the buffer in OpenCL { // overwrite the 'XXXX' with '1234' and the 'xxxx' with 'abcd' so we now have // 'abcd1234' at the beginning and end of the buffer result = clEnqueueCopyBuffer( command_queue, mem, mem, 0, props->ByteWidth-8, 4, 0, NULL, NULL); TestRequire(result == CL_SUCCESS, "clEnqueueCopyBuffer failed."); result = clEnqueueCopyBuffer( command_queue, mem, mem, props->ByteWidth-4, 4, 4, 0, NULL, NULL); TestRequire(result == CL_SUCCESS, "clEnqueueCopyBuffer failed."); } // release the resource from OpenCL { result = clEnqueueReleaseD3D10ObjectsKHR( command_queue, 1, &mem, 0, NULL, NULL); TestRequire(result == CL_SUCCESS, "clEnqueueReleaseD3D10ObjectsKHR failed."); } // read data in D3D { ID3D10Buffer* pStagingBuffer = NULL; char *pStagingData = NULL; // create a staging buffer to read the data back D3D10_BUFFER_DESC desc = {0}; desc.ByteWidth = 16; desc.Usage = D3D10_USAGE_STAGING; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE|D3D10_CPU_ACCESS_READ; desc.BindFlags = 0; desc.MiscFlags = 0; hr = pDevice->CreateBuffer(&desc, NULL, &pStagingBuffer); TestRequire(SUCCEEDED(hr), "Creating staging vertex buffer failed!"); // make sure the staging buffer doesn't get stale data hr = pStagingBuffer->Map( D3D10_MAP_READ_WRITE, 0, (void **)&pStagingData); TestRequire(SUCCEEDED(hr), "Map failed!"); memset(pStagingData, 0, 16); pStagingBuffer->Unmap(); // copy the 'abcd1234' from the front and back of the buffer to the staging buffer D3D10_BOX box = {0}; box.front = 0; box.back = 1; box.top = 0; box.bottom = 1; box.left = 0; box.right = 8; pDevice->CopySubresourceRegion( pStagingBuffer, 0, 0, 0, 0, pBuffer, 0, &box); box.left = props->ByteWidth-8; box.right = props->ByteWidth; pDevice->CopySubresourceRegion( pStagingBuffer, 0, 8, 0, 0, pBuffer, 0, &box); TestRequire(SUCCEEDED(hr), "CopySubresourceRegion failed!"); // verify that we got the 'abcd1234' hr = pStagingBuffer->Map( D3D10_MAP_READ_WRITE, 0, (void **)&pStagingData); TestRequire(SUCCEEDED(hr), "Map failed!"); TestRequire(!memcmp(pStagingData, "abcd1234abcd1234", 16), "Data was not accurately"); pStagingBuffer->Unmap(); TestRequire(SUCCEEDED(hr), "Unmap failed!"); pStagingBuffer->Release(); } Cleanup: if (pBuffer) { pBuffer->Release(); } if (mem) { clReleaseMemObject(mem); } HarnessD3D10_TestEnd(); } void TestDeviceBuffer( cl_context context, cl_command_queue command_queue, ID3D10Device* pDevice) { for (UINT i = 0; i < bufferPropertyCount; ++i) { SubTestBuffer( context, command_queue, pDevice, &bufferProperties[i]); } }