// // 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 INITGUID #include "harness.h" #include #include #include /* * OpenCL state */ clGetDeviceIDsFromD3D11KHR_fn clGetDeviceIDsFromD3D11KHR = NULL; clCreateFromD3D11BufferKHR_fn clCreateFromD3D11BufferKHR = NULL; clCreateFromD3D11Texture2DKHR_fn clCreateFromD3D11Texture2DKHR = NULL; clCreateFromD3D11Texture3DKHR_fn clCreateFromD3D11Texture3DKHR = NULL; clEnqueueAcquireD3D11ObjectsKHR_fn clEnqueueAcquireD3D11ObjectsKHR = NULL; clEnqueueReleaseD3D11ObjectsKHR_fn clEnqueueReleaseD3D11ObjectsKHR = NULL; #define INITPFN(x) \ x = (x ## _fn)clGetExtensionFunctionAddressForPlatform(platform, #x); NonTestRequire(x, "Failed to get function pointer for %s", #x); void HarnessD3D11_ExtensionCheck() { cl_int result = CL_SUCCESS; cl_platform_id platform = NULL; HarnessD3D11_TestBegin("Extension query"); bool platform_d3d11 = false; // Does platform support the extension? { std::vector< char > buffer; size_t size = 0; result = clGetPlatformIDs( 1, &platform, NULL ); NonTestRequire( result == CL_SUCCESS, "Failed to get any platforms." ); result = clGetPlatformInfo( platform, CL_PLATFORM_EXTENSIONS, 0, NULL, & size ); NonTestRequire( result == CL_SUCCESS, "Failed to get size of extension string." ); buffer.resize( size ); result = clGetPlatformInfo( platform, CL_PLATFORM_EXTENSIONS, buffer.size(), & buffer.front(), & size ); NonTestRequire( result == CL_SUCCESS, "Failed to get extension string." ); std::string extensions = std::string( " " ) + & buffer.front() + " "; platform_d3d11 = ( extensions.find( " cl_khr_d3d11_sharing " ) != std::string::npos ); } // Platform is required to report the extension only if all devices support it, // so let us iterate through all the devices and count devices supporting the extension. // Get list of all devices. std::vector< cl_device_id > devices; cl_uint num_devices = 0; result = clGetDeviceIDs( platform, CL_DEVICE_TYPE_ALL, 0, NULL, & num_devices ); NonTestRequire( result == CL_SUCCESS, "Failed to get number of devices." ); devices.resize( num_devices ); result = clGetDeviceIDs( platform, CL_DEVICE_TYPE_ALL, devices.size(), & devices.front(), & num_devices ); NonTestRequire( result == CL_SUCCESS, "Failed to get list of device ids." ); NonTestRequire( num_devices == devices.size(), "Failed to get list of device ids." ); // Iterate through the devices and count devices supporting the extension. cl_uint num_devices_d3d11 = 0; // Number of devices supporting cl_khr_d3d11_sharing. for ( cl_uint i = 0; i < devices.size(); ++ i ) { if (is_extension_available(devices[i], "cl_khr_d3d11_sharing")) { ++ num_devices_d3d11; } } OSVERSIONINFO osvi; osvi.dwOSVersionInfoSize = sizeof(osvi); GetVersionEx(&osvi); if (osvi.dwMajorVersion <= 5) { // Neither platform nor devices should declare support. TestRequire( ! platform_d3d11, "Platform should not declare extension on Windows < 6" ); TestRequire( num_devices_d3d11 == 0, "Devices should not declare extension on Windows < 6" ); } else { if ( num_devices_d3d11 == num_devices ) { // All the devices declare support, so platform must declare support as well. TestRequire( platform_d3d11, "Extension should be exported on Windows >= 6" ); } else { // Not all the devices support th eextension => platform should not declare it. TestRequire( ! platform_d3d11, "Extension should not be exported on Windows >= 6" ); } } Cleanup: HarnessD3D11_TestEnd(); // early-out of the extension is not present if ( num_devices_d3d11 == 0 ) { HarnessD3D11_TestStats(); } } void HarnessD3D11_Initialize(cl_platform_id platform) { HarnessD3D11_ExtensionCheck(); // extract function pointers for exported functions INITPFN(clGetDeviceIDsFromD3D11KHR); INITPFN(clCreateFromD3D11BufferKHR); INITPFN(clCreateFromD3D11Texture2DKHR); INITPFN(clCreateFromD3D11Texture3DKHR); INITPFN(clEnqueueAcquireD3D11ObjectsKHR); INITPFN(clEnqueueReleaseD3D11ObjectsKHR); } /* * Window management */ static IDXGISwapChain* HarnessD3D11_pSwapChain = NULL; static ID3D11Device* HarnessD3D11_pDevice = NULL; static ID3D11DeviceContext* HarnessD3D11_pDC = NULL; static HWND HarnessD3D11_hWnd = NULL; static LRESULT WINAPI HarnessD3D11_Proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_KEYDOWN: return 0; break; case WM_DESTROY: HarnessD3D11_hWnd = NULL; PostQuitMessage(0); return 0; case WM_PAINT: ValidateRect(hWnd, NULL); return 0; } return DefWindowProc(hWnd, msg, wParam, lParam); } static void HarnessD3D11_InteractiveLoop() { MSG msg; while(PeekMessage(&msg,HarnessD3D11_hWnd,0,0,PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } } cl_int HarnessD3D11_CreateDevice( IDXGIAdapter* pAdapter, ID3D11Device **ppDevice, ID3D11DeviceContext** ppDC) { HRESULT hr = S_OK; unsigned int cuStatus = 1; *ppDevice = NULL; // create window static WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, HarnessD3D11_Proc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, _T( "cl_khr_d3d11_sharing_conformance" ), NULL }; RegisterClassEx(&wc); HarnessD3D11_hWnd = CreateWindow( _T( "cl_khr_d3d11_sharing_conformance" ), _T( "cl_khr_d3d11_sharing_conformance" ), WS_OVERLAPPEDWINDOW, 0, 0, 256, 256, NULL, NULL, wc.hInstance, NULL); NonTestRequire(0 != HarnessD3D11_hWnd, "Failed to create window"); ShowWindow(HarnessD3D11_hWnd,SW_SHOWDEFAULT); UpdateWindow(HarnessD3D11_hWnd); RECT rc; GetClientRect(HarnessD3D11_hWnd, &rc); UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top; // Create device and swapchain DXGI_SWAP_CHAIN_DESC sd; ZeroMemory( &sd, sizeof(sd) ); sd.BufferCount = 1; sd.BufferDesc.Width = width; sd.BufferDesc.Height = height; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = HarnessD3D11_hWnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; D3D_FEATURE_LEVEL requestedFeatureLevels[] = {D3D_FEATURE_LEVEL_10_0}; D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0; hr = D3D11CreateDeviceAndSwapChain( NULL, // pAdapter, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, requestedFeatureLevels, 1, D3D11_SDK_VERSION, &sd, &HarnessD3D11_pSwapChain, &HarnessD3D11_pDevice, &featureLevel, &HarnessD3D11_pDC); if (FAILED(hr) ) { return CL_DEVICE_NOT_FOUND; } *ppDevice = HarnessD3D11_pDevice; *ppDC = HarnessD3D11_pDC; return CL_SUCCESS; } void HarnessD3D11_DestroyDevice() { HarnessD3D11_pSwapChain->Release(); HarnessD3D11_pDevice->Release(); HarnessD3D11_pDC->Release(); if (HarnessD3D11_hWnd) DestroyWindow(HarnessD3D11_hWnd); HarnessD3D11_hWnd = 0; } /* * * texture formats * */ #define ADD_TEXTURE_FORMAT(x,y,z,a,b,g) { x, y, z, a*b/8, g, #x, #y, #z, } TextureFormat formats[] = { ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32G32B32A32_FLOAT , CL_RGBA , CL_FLOAT , 32, 4, TextureFormat::GENERIC_FLOAT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32G32B32A32_UINT , CL_RGBA , CL_UNSIGNED_INT32 , 32, 4, TextureFormat::GENERIC_UINT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32G32B32A32_SINT , CL_RGBA , CL_SIGNED_INT32 , 32, 4, TextureFormat::GENERIC_SINT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16B16A16_FLOAT , CL_RGBA , CL_HALF_FLOAT , 16, 4, TextureFormat::GENERIC_FLOAT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16B16A16_UNORM , CL_RGBA , CL_UNORM_INT16 , 16, 4, TextureFormat::GENERIC_FLOAT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16B16A16_UINT , CL_RGBA , CL_UNSIGNED_INT16 , 16, 4, TextureFormat::GENERIC_UINT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16B16A16_SNORM , CL_RGBA , CL_SNORM_INT16 , 16, 4, TextureFormat::GENERIC_FLOAT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16B16A16_SINT , CL_RGBA , CL_SIGNED_INT16 , 16, 4, TextureFormat::GENERIC_SINT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8B8A8_UNORM , CL_RGBA , CL_UNORM_INT8 , 8, 4, TextureFormat::GENERIC_FLOAT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8B8A8_UINT , CL_RGBA , CL_UNSIGNED_INT8 , 8, 4, TextureFormat::GENERIC_UINT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8B8A8_SNORM , CL_RGBA , CL_SNORM_INT8 , 8, 4, TextureFormat::GENERIC_FLOAT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8B8A8_SINT , CL_RGBA , CL_SIGNED_INT8 , 8, 4, TextureFormat::GENERIC_SINT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32G32_FLOAT , CL_RG , CL_FLOAT , 32, 2, TextureFormat::GENERIC_FLOAT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32G32_UINT , CL_RG , CL_UNSIGNED_INT32 , 32, 2, TextureFormat::GENERIC_UINT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32G32_SINT , CL_RG , CL_SIGNED_INT32 , 32, 2, TextureFormat::GENERIC_SINT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16_FLOAT , CL_RG , CL_HALF_FLOAT , 16, 2, TextureFormat::GENERIC_FLOAT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16_UNORM , CL_RG , CL_UNORM_INT16 , 16, 2, TextureFormat::GENERIC_FLOAT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16_UINT , CL_RG , CL_UNSIGNED_INT16 , 16, 2, TextureFormat::GENERIC_UINT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16_SNORM , CL_RG , CL_SNORM_INT16 , 16, 2, TextureFormat::GENERIC_FLOAT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16_SINT , CL_RG , CL_SIGNED_INT16 , 16, 2, TextureFormat::GENERIC_SINT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8_UNORM , CL_RG , CL_UNORM_INT8 , 8, 2, TextureFormat::GENERIC_FLOAT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8_UINT , CL_RG , CL_UNSIGNED_INT8 , 8, 2, TextureFormat::GENERIC_UINT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8_SNORM , CL_RG , CL_SNORM_INT8 , 8, 2, TextureFormat::GENERIC_FLOAT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8_SINT , CL_RG , CL_SIGNED_INT8 , 8, 2, TextureFormat::GENERIC_SINT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32_FLOAT , CL_R , CL_FLOAT , 32, 1, TextureFormat::GENERIC_FLOAT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32_UINT , CL_R , CL_UNSIGNED_INT32 , 32, 1, TextureFormat::GENERIC_UINT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32_SINT , CL_R , CL_SIGNED_INT32 , 32, 1, TextureFormat::GENERIC_SINT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16_FLOAT , CL_R , CL_HALF_FLOAT , 16, 1, TextureFormat::GENERIC_FLOAT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16_UNORM , CL_R , CL_UNORM_INT16 , 16, 1, TextureFormat::GENERIC_FLOAT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16_UINT , CL_R , CL_UNSIGNED_INT16 , 16, 1, TextureFormat::GENERIC_UINT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16_SNORM , CL_R , CL_SNORM_INT16 , 16, 1, TextureFormat::GENERIC_FLOAT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16_SINT , CL_R , CL_SIGNED_INT16 , 16, 1, TextureFormat::GENERIC_SINT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8_UNORM , CL_R , CL_UNORM_INT8 , 8, 1, TextureFormat::GENERIC_FLOAT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8_UINT , CL_R , CL_UNSIGNED_INT8 , 8, 1, TextureFormat::GENERIC_UINT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8_SNORM , CL_R , CL_SNORM_INT8 , 8, 1, TextureFormat::GENERIC_FLOAT ), ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8_SINT , CL_R , CL_SIGNED_INT8 , 8, 1, TextureFormat::GENERIC_SINT ), }; UINT formatCount = sizeof(formats)/sizeof(formats[0]); /* * * Logging and error reporting * */ static struct { cl_int testCount; cl_int passCount; cl_int nonTestFailures; cl_int inTest; cl_int currentTestPass; char currentTestName[1024]; } HarnessD3D11_testStats = {0}; void HarnessD3D11_TestBegin(const char* fmt, ...) { va_list ap; va_start(ap, fmt); vsprintf(HarnessD3D11_testStats.currentTestName, fmt, ap); va_end(ap); printf("[%s] ... ", HarnessD3D11_testStats.currentTestName); HarnessD3D11_testStats.inTest = 1; HarnessD3D11_testStats.currentTestPass = 1; } void HarnessD3D11_TestFail() { if (HarnessD3D11_testStats.inTest) { HarnessD3D11_testStats.currentTestPass = 0; } else { ++HarnessD3D11_testStats.nonTestFailures; } } void HarnessD3D11_TestEnd() { HarnessD3D11_testStats.inTest = 0; HarnessD3D11_testStats.testCount += 1; HarnessD3D11_testStats.passCount += HarnessD3D11_testStats.currentTestPass; TestPrint("%s\n", HarnessD3D11_testStats.currentTestPass ? "PASSED" : "FAILED"); } void HarnessD3D11_TestStats() { TestPrint("PASSED %d of %d tests.\n", HarnessD3D11_testStats.passCount, HarnessD3D11_testStats.testCount); if (HarnessD3D11_testStats.testCount > HarnessD3D11_testStats.passCount) { TestPrint("***FAILED***\n"); exit(1); } else { TestPrint("&&&& cl_khr_d3d11_sharing test PASSED\n"); } exit(0); } /* * * Helper function * */ cl_int HarnessD3D11_CreateKernelFromSource( cl_kernel *outKernel, cl_device_id device, cl_context context, const char *source, const char *entrypoint) { cl_int status; cl_kernel kernel = NULL; // compile program cl_program program = NULL; { const char *sourceTexts[] = {source}; size_t sourceLengths[] = {strlen(source) }; status = create_single_kernel_helper(context, &program, &kernel, 1, &sourceTexts[0], entrypoint); TestRequire(CL_SUCCESS == status, "Kernel creation failed"); } clReleaseProgram(program); *outKernel = kernel; Cleanup: return CL_SUCCESS; }