| // |
| // 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. |
| // |
| #define _CRT_SECURE_NO_WARNINGS |
| #include "harness.h" |
| |
| Texture3DSize texture3DSizes[] = |
| { |
| { |
| 4, // Width |
| 4, // Height |
| 4, // Depth |
| 1, // MipLevels |
| 1, // SubResourceCount |
| { // SubResources |
| { 0 }, // MipLevel |
| { 0 }, // MipLevel |
| { 0 }, // MipLevel |
| { 0 }, // MipLevel |
| }, |
| 0, // MiscFlags |
| }, |
| { |
| 127, // Width |
| 25, // Height |
| 33, // Depth |
| 1, // MipLevels |
| 1, // SubResourceCount |
| { // SubResources |
| { 0 }, // MipLevel |
| { 0 }, // MipLevel |
| { 0 }, // MipLevel |
| { 0 }, // MipLevel |
| }, |
| 0, // MiscFlags |
| }, |
| { |
| 128, // Width |
| 256, // Height |
| 64, // Depth |
| 4, // MipLevels |
| 3, // SubResourceCount |
| { // SubResources |
| { 2 }, // MipLevel |
| { 1 }, // MipLevel |
| { 0 }, // MipLevel |
| { 0 }, // MipLevel |
| }, |
| 0, // MiscFlags |
| }, |
| { |
| 512, // Width |
| 64, // Height |
| 32, // Depth |
| 3, // MipLevels |
| 1, // SubResourceCount |
| { // SubResources |
| { 2 }, // MipLevel |
| { 0 }, // MipLevel |
| { 0 }, // MipLevel |
| { 0 }, // MipLevel |
| }, |
| 0, // MiscFlags |
| }, |
| }; |
| UINT texture3DSizeCount = sizeof(texture3DSizes)/sizeof(texture3DSizes[0]); |
| |
| const char * |
| texture3DPatterns[2][2][2] = |
| { |
| { |
| {"PlaceTheCasseroleDis", "hInAColdOvenPlaceACh"}, |
| {"airFacingTheOvenAndS", "itInItForeverThinkAb"}, |
| }, |
| { |
| {"outHowHungryYouAreWh", "enNightFallsDoNotTur"}, |
| {"nOnTheLightMyEyeBeca", "meInflamedIHateCamus"}, |
| }, |
| }; |
| |
| void SubTestTexture3D( |
| cl_context context, |
| cl_command_queue command_queue, |
| ID3D10Device* pDevice, |
| const TextureFormat* format, |
| const Texture3DSize* size) |
| { |
| ID3D10Texture3D* pTexture = NULL; |
| HRESULT hr = S_OK; |
| |
| cl_int result = CL_SUCCESS; |
| |
| HarnessD3D10_TestBegin("3D Texture: Format=%s, Width=%d, Height=%d, Depth=%d, MipLevels=%d", |
| format->name_format, |
| size->Width, |
| size->Height, |
| size->Depth, |
| size->MipLevels); |
| |
| struct |
| { |
| cl_mem mem; |
| UINT subResource; |
| UINT width; |
| UINT height; |
| UINT depth; |
| } |
| subResourceInfo[4]; |
| |
| // create the D3D10 resources |
| { |
| D3D10_TEXTURE3D_DESC desc; |
| memset(&desc, 0, sizeof(desc) ); |
| desc.Width = size->Width; |
| desc.Height = size->Height; |
| desc.Depth = size->Depth; |
| desc.MipLevels = size->MipLevels; |
| desc.Format = format->format; |
| desc.Usage = D3D10_USAGE_DEFAULT; |
| desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; |
| desc.CPUAccessFlags = 0; |
| desc.MiscFlags = 0; |
| |
| hr = pDevice->CreateTexture3D(&desc, NULL, &pTexture); |
| TestRequire(SUCCEEDED(hr), "CreateTexture3D failed."); |
| } |
| |
| // initialize some useful variables |
| for (UINT i = 0; i < size->SubResourceCount; ++i) |
| { |
| // compute the expected values for the subresource |
| subResourceInfo[i].subResource = size->subResources[i].MipLevel; |
| subResourceInfo[i].width = size->Width; |
| subResourceInfo[i].height = size->Height; |
| subResourceInfo[i].depth = size->Depth; |
| for (UINT j = 0; j < size->subResources[i].MipLevel; ++j) { |
| subResourceInfo[i].width /= 2; |
| subResourceInfo[i].height /= 2; |
| subResourceInfo[i].depth /= 2; |
| } |
| } |
| |
| // copy a pattern into the corners of the image, coordinates |
| for (UINT i = 0; i < size->SubResourceCount; ++i) |
| for (UINT x = 0; x < 2; ++x) |
| for (UINT y = 0; y < 2; ++y) |
| for (UINT z = 0; z < 2; ++z) |
| { |
| // create the staging buffer |
| ID3D10Texture3D* pStagingBuffer = NULL; |
| { |
| D3D10_TEXTURE3D_DESC desc = {0}; |
| desc.Width = 1; |
| desc.Height = 1; |
| desc.Depth = 1; |
| desc.MipLevels = 1; |
| desc.Format = format->format; |
| desc.Usage = D3D10_USAGE_STAGING; |
| desc.BindFlags = 0; |
| desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ | D3D10_CPU_ACCESS_WRITE; |
| desc.MiscFlags = 0; |
| hr = pDevice->CreateTexture3D(&desc, NULL, &pStagingBuffer); |
| TestRequire(SUCCEEDED(hr), "CreateTexture3D failed."); |
| } |
| |
| // write the data to the staging buffer |
| { |
| D3D10_MAPPED_TEXTURE3D mappedTexture; |
| hr = pStagingBuffer->Map( |
| 0, |
| D3D10_MAP_READ_WRITE, |
| 0, |
| &mappedTexture); |
| memcpy(mappedTexture.pData, texture3DPatterns[x][y][z], format->bytesPerPixel); |
| pStagingBuffer->Unmap(0); |
| } |
| |
| // copy the data to to the texture |
| { |
| D3D10_BOX box = {0}; |
| box.front = 0; box.back = 1; |
| box.top = 0; box.bottom = 1; |
| box.left = 0; box.right = 1; |
| pDevice->CopySubresourceRegion( |
| pTexture, |
| subResourceInfo[i].subResource, |
| x ? subResourceInfo[i].width - 1 : 0, |
| y ? subResourceInfo[i].height - 1 : 0, |
| z ? subResourceInfo[i].depth - 1 : 0, |
| pStagingBuffer, |
| 0, |
| &box); |
| } |
| |
| pStagingBuffer->Release(); |
| } |
| |
| // create the cl_mem objects for the resources and verify its sanity |
| for (UINT i = 0; i < size->SubResourceCount; ++i) |
| { |
| // create a cl_mem for the resource |
| subResourceInfo[i].mem = clCreateFromD3D10Texture3DKHR( |
| context, |
| 0, |
| pTexture, |
| subResourceInfo[i].subResource, |
| &result); |
| TestRequire(result == CL_SUCCESS, "clCreateFromD3D10Texture3DKHR failed"); |
| |
| // query resource pointer and verify |
| ID3D10Resource* clResource = NULL; |
| result = clGetMemObjectInfo( |
| subResourceInfo[i].mem, |
| CL_MEM_D3D10_RESOURCE_KHR, |
| sizeof(clResource), |
| &clResource, |
| NULL); |
| TestRequire(result == CL_SUCCESS, "clGetMemObjectInfo for CL_MEM_D3D10_RESOURCE_KHR failed."); |
| TestRequire(clResource == pTexture, "clGetMemObjectInfo for CL_MEM_D3D10_RESOURCE_KHR returned incorrect value."); |
| |
| // query subresource and verify |
| UINT clSubResource; |
| result = clGetImageInfo( |
| subResourceInfo[i].mem, |
| CL_IMAGE_D3D10_SUBRESOURCE_KHR, |
| sizeof(clSubResource), |
| &clSubResource, |
| NULL); |
| TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_D3D10_SUBRESOURCE_KHR failed"); |
| TestRequire(clSubResource == subResourceInfo[i].subResource, "clGetImageInfo for CL_IMAGE_D3D10_SUBRESOURCE_KHR returned incorrect value."); |
| |
| // query format and verify |
| cl_image_format clFormat; |
| result = clGetImageInfo( |
| subResourceInfo[i].mem, |
| CL_IMAGE_FORMAT, |
| sizeof(clFormat), |
| &clFormat, |
| NULL); |
| TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_FORMAT failed"); |
| TestRequire(clFormat.image_channel_order == format->channel_order, "clGetImageInfo for CL_IMAGE_FORMAT returned incorrect channel order."); |
| TestRequire(clFormat.image_channel_data_type == format->channel_type, "clGetImageInfo for CL_IMAGE_FORMAT returned incorrect channel data type."); |
| |
| // query width |
| size_t width; |
| result = clGetImageInfo( |
| subResourceInfo[i].mem, |
| CL_IMAGE_WIDTH, |
| sizeof(width), |
| &width, |
| NULL); |
| TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_WIDTH failed"); |
| TestRequire(width == subResourceInfo[i].width, "clGetImageInfo for CL_IMAGE_HEIGHT returned incorrect value."); |
| |
| // query height |
| size_t height; |
| result = clGetImageInfo( |
| subResourceInfo[i].mem, |
| CL_IMAGE_HEIGHT, |
| sizeof(height), |
| &height, |
| NULL); |
| TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_HEIGHT failed"); |
| TestRequire(height == subResourceInfo[i].height, "clGetImageInfo for CL_IMAGE_HEIGHT returned incorrect value."); |
| |
| // query depth |
| size_t depth; |
| result = clGetImageInfo( |
| subResourceInfo[i].mem, |
| CL_IMAGE_DEPTH, |
| sizeof(depth), |
| &depth, |
| NULL); |
| TestRequire(result == CL_SUCCESS, "clGetImageInfo for CL_IMAGE_DEPTH failed"); |
| TestRequire(depth == subResourceInfo[i].depth, "clGetImageInfo for CL_IMAGE_DEPTH returned incorrect value."); |
| |
| } |
| |
| // acquire the resources for OpenCL |
| { |
| cl_mem memToAcquire[MAX_REGISTERED_SUBRESOURCES]; |
| |
| // cut the registered sub-resources into two sets and send the acquire calls for them separately |
| for(UINT i = 0; i < size->SubResourceCount; ++i) |
| { |
| memToAcquire[i] = subResourceInfo[i].mem; |
| } |
| |
| // do the acquire |
| result = clEnqueueAcquireD3D10ObjectsKHR( |
| command_queue, |
| size->SubResourceCount, |
| memToAcquire, |
| 0, |
| NULL, |
| NULL); |
| TestRequire(result == CL_SUCCESS, "clEnqueueAcquireD3D10ObjectsKHR failed."); |
| } |
| |
| // download the data using OpenCL & compare with the expected results |
| // copy the corners of the image into the image |
| for (UINT i = 0; i < size->SubResourceCount; ++i) |
| for (UINT x = 0; x < 2; ++x) |
| for (UINT y = 0; y < 2; ++y) |
| for (UINT z = 0; z < 2; ++z) |
| { |
| if (x == y && y == z && 0) |
| { |
| continue; |
| } |
| size_t src[3] = |
| { |
| x ? subResourceInfo[i].width - 1 : 0, |
| y ? subResourceInfo[i].height - 1 : 0, |
| z ? subResourceInfo[i].depth - 1 : 0, |
| }; |
| size_t dst[3] = |
| { |
| x ? subResourceInfo[i].width - 2 : 1, |
| y ? subResourceInfo[i].height - 2 : 1, |
| z ? subResourceInfo[i].depth - 2 : 1, |
| }; |
| size_t region[3] = |
| { |
| 1, |
| 1, |
| 1, |
| }; |
| result = clEnqueueCopyImage( |
| command_queue, |
| subResourceInfo[i].mem, |
| subResourceInfo[i].mem, |
| src, |
| dst, |
| region, |
| 0, |
| NULL, |
| NULL); |
| TestRequire(result == CL_SUCCESS, "clEnqueueCopyImage failed."); |
| } |
| |
| // release the resource from OpenCL |
| { |
| cl_mem memToAcquire[MAX_REGISTERED_SUBRESOURCES]; |
| for(UINT i = 0; i < size->SubResourceCount; ++i) |
| { |
| memToAcquire[i] = subResourceInfo[i].mem; |
| } |
| |
| // do the release |
| result = clEnqueueReleaseD3D10ObjectsKHR( |
| command_queue, |
| size->SubResourceCount, |
| memToAcquire, |
| 0, |
| NULL, |
| NULL); |
| TestRequire(result == CL_SUCCESS, "clEnqueueReleaseD3D10ObjectsKHR failed."); |
| } |
| |
| for (UINT i = 0; i < size->SubResourceCount; ++i) |
| for (UINT x = 0; x < 2; ++x) |
| for (UINT y = 0; y < 2; ++y) |
| for (UINT z = 0; z < 2; ++z) |
| { |
| // create the staging buffer |
| ID3D10Texture3D* pStagingBuffer = NULL; |
| { |
| D3D10_TEXTURE3D_DESC desc = {0}; |
| desc.Width = 1; |
| desc.Height = 1; |
| desc.Depth = 1; |
| desc.MipLevels = 1; |
| desc.Format = format->format; |
| desc.Usage = D3D10_USAGE_STAGING; |
| desc.BindFlags = 0; |
| desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ | D3D10_CPU_ACCESS_WRITE; |
| desc.MiscFlags = 0; |
| hr = pDevice->CreateTexture3D(&desc, NULL, &pStagingBuffer); |
| TestRequire(SUCCEEDED(hr), "Failed to create staging buffer."); |
| } |
| |
| // wipe out the staging buffer to make sure we don't get stale values |
| { |
| D3D10_MAPPED_TEXTURE3D mappedTexture; |
| hr = pStagingBuffer->Map( |
| 0, |
| D3D10_MAP_READ_WRITE, |
| 0, |
| &mappedTexture); |
| TestRequire(SUCCEEDED(hr), "Failed to map staging buffer"); |
| memset(mappedTexture.pData, 0, format->bytesPerPixel); |
| pStagingBuffer->Unmap(0); |
| } |
| |
| // copy the pixel to the staging buffer |
| { |
| D3D10_BOX box = {0}; |
| box.left = x ? subResourceInfo[i].width - 2 : 1; box.right = box.left + 1; |
| box.top = y ? subResourceInfo[i].height - 2 : 1; box.bottom = box.top + 1; |
| box.front = z ? subResourceInfo[i].depth - 2 : 1; box.back = box.front + 1; |
| pDevice->CopySubresourceRegion( |
| pStagingBuffer, |
| 0, |
| 0, |
| 0, |
| 0, |
| pTexture, |
| subResourceInfo[i].subResource, |
| &box); |
| } |
| |
| // make sure we read back what was written next door |
| { |
| D3D10_MAPPED_TEXTURE3D mappedTexture; |
| hr = pStagingBuffer->Map( |
| 0, |
| D3D10_MAP_READ_WRITE, |
| 0, |
| &mappedTexture); |
| TestRequire(SUCCEEDED(hr), "Failed to map staging buffer"); |
| |
| /* |
| // This can be helpful in debugging... |
| printf("\n"); |
| for (UINT k = 0; k < format->bytesPerPixel; ++k) |
| { |
| printf("[%c %c]\n", |
| texture2DPatterns[x][y][k], |
| ( (char *)mappedTexture.pData )[k]); |
| } |
| */ |
| |
| TestRequire( |
| !memcmp(mappedTexture.pData, texture3DPatterns[x][y][z], format->bytesPerPixel), |
| "Failed to map staging buffer"); |
| |
| pStagingBuffer->Unmap(0); |
| } |
| |
| pStagingBuffer->Release(); |
| } |
| |
| |
| Cleanup: |
| |
| if (pTexture) |
| { |
| pTexture->Release(); |
| } |
| for (UINT i = 0; i < size->SubResourceCount; ++i) |
| { |
| clReleaseMemObject(subResourceInfo[i].mem); |
| } |
| |
| HarnessD3D10_TestEnd(); |
| } |
| |
| |
| void TestDeviceTexture3D( |
| cl_device_id device, |
| cl_context context, |
| cl_command_queue command_queue, |
| ID3D10Device* pDevice) |
| { |
| cl_int result = CL_SUCCESS; |
| |
| |
| for (UINT format = 0, size = 0; format < formatCount; ++size, ++format) |
| { |
| SubTestTexture3D( |
| context, |
| command_queue, |
| pDevice, |
| &formats[format], |
| &texture3DSizes[size % texture3DSizeCount]); |
| } |
| } |
| |