// // 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 "utils.h" #include "harness/errorHelpers.h" #include "harness/rounding_mode.h" #include static RoundingMode gFloatToHalfRoundingMode = kDefaultRoundingMode; CResult::CResult(): _result(TEST_PASS), _resultLast(TEST_NORESULT) { } CResult::~CResult() { } CResult::TTestResult CResult::ResultLast() const { return _resultLast; } int CResult::Result() const { switch (_result) { case TEST_NORESULT: case TEST_NOTSUPPORTED: case TEST_PASS: return 0; break; case TEST_FAIL: return 1; break; case TEST_ERROR: return 2; break; default: return -1; break; } } void CResult::ResultSub( TTestResult result ) { _resultLast = result; if (static_cast(result) > static_cast(_result)) _result = result; } void FunctionContextCreateToString(TContextFuncType contextCreateFunction, std::string &contextFunction) { switch(contextCreateFunction) { case CONTEXT_CREATE_DEFAULT: contextFunction = "CreateContext"; break; case CONTEXT_CREATE_FROM_TYPE: contextFunction = "CreateContextFromType"; break; default: contextFunction = "Unknown"; log_error("FunctionContextCreateToString(): Unknown create function enum!"); break; } } void AdapterToString(cl_dx9_media_adapter_type_khr adapterType, std::string &adapter) { switch(adapterType) { case CL_ADAPTER_D3D9_KHR: adapter = "D3D9"; break; case CL_ADAPTER_D3D9EX_KHR: adapter = "D3D9EX"; break; case CL_ADAPTER_DXVA_KHR: adapter = "DXVA"; break; default: adapter = "Unknown"; log_error("AdapterToString(): Unknown adapter type!"); break; } } cl_context_info AdapterTypeToContextInfo( cl_dx9_media_adapter_type_khr adapterType ) { switch (adapterType) { case CL_ADAPTER_D3D9_KHR: return CL_CONTEXT_ADAPTER_D3D9_KHR; break; case CL_ADAPTER_D3D9EX_KHR: return CL_CONTEXT_ADAPTER_D3D9EX_KHR; break; case CL_ADAPTER_DXVA_KHR: return CL_CONTEXT_ADAPTER_DXVA_KHR; break; default: log_error("AdapterTypeToContextInfo(): Unknown adapter type!"); return 0; break; } } void YUVGenerateNV12( std::vector &yuv, unsigned int width, unsigned int height, cl_uchar valueMin, cl_uchar valueMax, double valueAdd ) { yuv.clear(); yuv.resize(width * height * 3 / 2, 0); double min = static_cast(valueMin); double max = static_cast(valueMax); double range = 255; double add = static_cast(valueAdd * range); double stepX = (max - min) / static_cast(width); double stepY = (max - min) /static_cast(height); //generate Y plane for (unsigned int i = 0; i < height; ++i) { unsigned int offset = i * width; double valueYPlane0 = static_cast(stepY * i); for (unsigned int j = 0; j < width; ++j) { double valueXPlane0 = static_cast(stepX * j); yuv.at(offset + j) = static_cast(min + valueXPlane0 / 2 + valueYPlane0 / 2 + add); } } //generate UV planes for (unsigned int i = 0; i < height / 2; ++i) { unsigned int offset = width * height + i * width; double valueYPlane1 = static_cast(stepY * i); double valueYPlane2 = static_cast(stepY * (height / 2 + i)); for (unsigned int j = 0; j < width / 2; ++j) { double valueXPlane1 = static_cast(stepX * j); double valueXPlane2 = static_cast(stepX * (width / 2 + j)); yuv.at(offset + j * 2) = static_cast(min + valueXPlane1 / 2 + valueYPlane1 / 2 + add); yuv.at(offset + j * 2 + 1) = static_cast(min + valueXPlane2 / 2 + valueYPlane2 / 2 + add); } } } void YUVGenerateYV12( std::vector &yuv, unsigned int width, unsigned int height, cl_uchar valueMin, cl_uchar valueMax, double valueAdd /*= 0.0*/ ) { yuv.clear(); yuv.resize(width * height * 3 / 2, 0); double min = static_cast(valueMin); double max = static_cast(valueMax); double range = 255; double add = static_cast(valueAdd * range); double stepX = (max - min) / static_cast(width); double stepY = (max - min) /static_cast(height); unsigned offset = 0; //generate Y plane for (unsigned int i = 0; i < height; ++i) { unsigned int plane0Offset = offset + i * width; double valueYPlane0 = static_cast(stepY * i); for (unsigned int j = 0; j < width; ++j) { double valueXPlane0 = static_cast(stepX * j); yuv.at(plane0Offset + j) = static_cast(min + valueXPlane0 / 2 + valueYPlane0 / 2 + add); } } //generate V plane offset += width * height; for (unsigned int i = 0; i < height / 2; ++i) { unsigned int plane1Offset = offset + i * width / 2; double valueYPlane1 = static_cast(stepY * i); for (unsigned int j = 0; j < width / 2; ++j) { double valueXPlane1 = static_cast(stepX * j); yuv.at(plane1Offset + j) = static_cast(min + valueXPlane1 / 2 + valueYPlane1 / 2 + add); } } //generate U plane offset += width * height / 4; for (unsigned int i = 0; i < height / 2; ++i) { unsigned int plane2Offset = offset + i * width / 2; double valueYPlane2 = static_cast(stepY * (height / 2 + i)); for (unsigned int j = 0; j < width / 2; ++j) { double valueXPlane2 = static_cast(stepX * j); yuv.at(plane2Offset + j) = static_cast(min + valueXPlane2 / 2 + valueYPlane2 / 2 + add); } } } bool YUVGenerate( TSurfaceFormat surfaceFormat, std::vector &yuv, unsigned int width, unsigned int height, cl_uchar valueMin, cl_uchar valueMax, double valueAdd /*= 0.0*/ ) { switch (surfaceFormat) { case SURFACE_FORMAT_NV12: YUVGenerateNV12(yuv, width, height, valueMin, valueMax, valueAdd); break; case SURFACE_FORMAT_YV12: YUVGenerateYV12(yuv, width, height, valueMin, valueMax, valueAdd); break; default: log_error("YUVGenerate(): Invalid surface type\n"); return false; break; } return true; } bool YUVSurfaceSetNV12( std::auto_ptr &surface, const std::vector &yuv, unsigned int width, unsigned int height ) { #if defined(_WIN32) CD3D9SurfaceWrapper *d3dSurface = static_cast(surface.get()); D3DLOCKED_RECT rect; if (FAILED((*d3dSurface)->LockRect(&rect, NULL, 0))) { log_error("YUVSurfaceSetNV12(): Surface lock failed\n"); return false; } size_t pitch = rect.Pitch / sizeof(cl_uchar); size_t lineSize = width * sizeof(cl_uchar); cl_uchar *ptr = static_cast(rect.pBits); for (size_t y = 0; y < height; ++y) memcpy(ptr + y * pitch, &yuv.at(y * width), lineSize); for (size_t y = 0; y < height / 2; ++y) memcpy(ptr + height * pitch + y * pitch, &yuv.at(width * height + y * width), lineSize); (*d3dSurface)->UnlockRect(); return true; #else return false; #endif } bool YUVSurfaceSetYV12( std::auto_ptr &surface, const std::vector &yuv, unsigned int width, unsigned int height ) { #if defined(_WIN32) CD3D9SurfaceWrapper *d3dSurface = static_cast(surface.get()); D3DLOCKED_RECT rect; if (FAILED((*d3dSurface)->LockRect(&rect, NULL, 0))) { log_error("YUVSurfaceSetYV12(): Surface lock failed!\n"); return false; } size_t pitch = rect.Pitch / sizeof(cl_uchar); size_t pitchHalf = pitch / 2; size_t lineSize = width * sizeof(cl_uchar); size_t lineHalfSize = lineSize / 2; size_t surfaceOffset = 0; size_t yuvOffset = 0; cl_uchar *ptr = static_cast(rect.pBits); for (size_t y = 0; y < height; ++y) memcpy(ptr + surfaceOffset + y * pitch, &yuv.at(yuvOffset + y * width), lineSize); surfaceOffset += height * pitch; yuvOffset += width * height; for (size_t y = 0; y < height / 2; ++y) memcpy(ptr + surfaceOffset + y * pitchHalf, &yuv.at(yuvOffset + y * lineHalfSize), lineHalfSize); surfaceOffset += pitchHalf * height / 2; yuvOffset += width * height / 4; for (size_t y = 0; y < height / 2; ++y) memcpy(ptr + surfaceOffset + y * pitchHalf, &yuv.at(yuvOffset + y * lineHalfSize), lineHalfSize); (*d3dSurface)->UnlockRect(); return true; #else return false; #endif } bool YUVSurfaceSet(TSurfaceFormat surfaceFormat, std::auto_ptr &surface, const std::vector &yuv, unsigned int width, unsigned int height ) { switch (surfaceFormat) { case SURFACE_FORMAT_NV12: if(!YUVSurfaceSetNV12(surface, yuv, width, height)) return false; break; case SURFACE_FORMAT_YV12: if(!YUVSurfaceSetYV12(surface, yuv, width, height)) return false; break; default: log_error("YUVSurfaceSet(): Invalid surface type!\n"); return false; break; } return true; } bool YUVSurfaceGetNV12( std::auto_ptr &surface, std::vector &yuv, unsigned int width, unsigned int height ) { #if defined(_WIN32) CD3D9SurfaceWrapper *d3dSurface = static_cast(surface.get()); D3DLOCKED_RECT rect; if (FAILED((*d3dSurface)->LockRect(&rect, NULL, 0))) { log_error("YUVSurfaceGetNV12(): Surface lock failed!\n"); return false; } size_t pitch = rect.Pitch / sizeof(cl_uchar); size_t lineSize = width * sizeof(cl_uchar); cl_uchar *ptr = static_cast(rect.pBits); size_t yuvOffset = 0; size_t surfaceOffset = 0; for (size_t y = 0; y < height; ++y) memcpy(&yuv.at(yuvOffset + y * width), ptr + y * pitch, lineSize); yuvOffset += width * height; surfaceOffset += pitch * height; for (size_t y = 0; y < height / 2; ++y) memcpy(&yuv.at(yuvOffset + y * width), ptr + surfaceOffset + y * pitch, lineSize); (*d3dSurface)->UnlockRect(); return true; #else return false; #endif } bool YUVSurfaceGetYV12( std::auto_ptr &surface, std::vector &yuv, unsigned int width, unsigned int height ) { #if defined(_WIN32) CD3D9SurfaceWrapper *d3dSurface = static_cast(surface.get()); D3DLOCKED_RECT rect; if (FAILED((*d3dSurface)->LockRect(&rect, NULL, 0))) { log_error("YUVSurfaceGetYV12(): Surface lock failed!\n"); return false; } size_t pitch = rect.Pitch / sizeof(cl_uchar); size_t pitchHalf = pitch / 2; size_t lineSize = width * sizeof(cl_uchar); size_t lineHalfSize = lineSize / 2; size_t surfaceOffset = 0; size_t yuvOffset = 0; cl_uchar *ptr = static_cast(rect.pBits); for (size_t y = 0; y < height; ++y) memcpy(&yuv.at(yuvOffset + y * width), ptr + surfaceOffset + y * pitch, lineSize); surfaceOffset += pitch * height; yuvOffset += width * height; for (size_t y = 0; y < height / 2; ++y) memcpy(&yuv.at(yuvOffset + y * lineHalfSize), ptr + surfaceOffset + y * pitchHalf, lineHalfSize); surfaceOffset += pitchHalf * height / 2; yuvOffset += width * height / 4; for (size_t y = 0; y < height / 2; ++y) memcpy(&yuv.at(yuvOffset + y * lineHalfSize), ptr + surfaceOffset + y * pitchHalf, lineHalfSize); (*d3dSurface)->UnlockRect(); return true; #else return false; #endif } bool YUVSurfaceGet(TSurfaceFormat surfaceFormat, std::auto_ptr &surface, std::vector &yuv, unsigned int width, unsigned int height ) { switch (surfaceFormat) { case SURFACE_FORMAT_NV12: if(!YUVSurfaceGetNV12(surface, yuv, width, height)) return false; break; case SURFACE_FORMAT_YV12: if(!YUVSurfaceGetYV12(surface, yuv, width, height)) return false; break; default: log_error("YUVSurfaceGet(): Invalid surface type!\n"); return false; break; } return true; } bool YUVCompareNV12( const std::vector &yuvTest, const std::vector &yuvRef, unsigned int width, unsigned int height ) { //plane 0 verification size_t offset = 0; for (size_t y = 0; y < height; ++y) { size_t plane0Offset = offset + width * y; for (size_t x = 0; x < width; ++x) { if (yuvTest[plane0Offset + x] != yuvRef[plane0Offset + x]) { log_error("Plane 0 (Y) is different than expected, reference value: %i, test value: %i, x: %i, y: %i\n", yuvRef[plane0Offset + x], yuvTest[plane0Offset + x], x, y); return false; } } } //plane 1 and 2 verification offset += width * height; for (size_t y = 0; y < height / 2; ++y) { size_t plane12Offset = offset + width * y; for (size_t x = 0; x < width / 2; ++x) { if (yuvTest.at(plane12Offset + 2 * x) != yuvRef.at(plane12Offset + 2 * x)) { log_error("Plane 1 (U) is different than expected, reference value: %i, test value: %i, x: %i, y: %i\n", yuvRef[plane12Offset + 2 * x], yuvTest[plane12Offset + 2 * x], x, y); return false; } if (yuvTest.at(plane12Offset + 2 * x + 1) != yuvRef.at(plane12Offset + 2 * x + 1)) { log_error("Plane 2 (V) is different than expected, reference value: %i, test value: %i, x: %i, y: %i\n", yuvRef[plane12Offset + 2 * x + 1], yuvTest[plane12Offset + 2 * x + 1], x, y); return false; } } } return true; } bool YUVCompareYV12( const std::vector &yuvTest, const std::vector &yuvRef, unsigned int width, unsigned int height ) { //plane 0 verification size_t offset = 0; for (size_t y = 0; y < height; ++y) { size_t plane0Offset = width * y; for (size_t x = 0; x < width; ++x) { if (yuvTest.at(plane0Offset + x) != yuvRef.at(plane0Offset + x)) { log_error("Plane 0 (Y) is different than expected, reference value: %i, test value: %i, x: %i, y: %i\n", yuvRef[plane0Offset + x], yuvTest[plane0Offset + x], x ,y); return false; } } } //plane 1 verification offset += width * height; for (size_t y = 0; y < height / 2; ++y) { size_t plane1Offset = offset + width * y / 2; for (size_t x = 0; x < width / 2; ++x) { if (yuvTest.at(plane1Offset + x) != yuvRef.at(plane1Offset + x)) { log_error("Plane 1 (V) is different than expected, reference value: %i, test value: %i, x: %i, y: %i\n", yuvRef[plane1Offset + x], yuvTest[plane1Offset + x], x, y); return false; } } } //plane 2 verification offset += width * height / 4; for (size_t y = 0; y < height / 2; ++y) { size_t plane2Offset = offset + width * y / 2; for (size_t x = 0; x < width / 2; ++x) { if (yuvTest.at(plane2Offset + x) != yuvRef.at(plane2Offset + x)) { log_error("Plane 2 (U) is different than expected, reference value: %i, test value: %i, x: %i, y: %i\n", yuvRef[plane2Offset + x], yuvTest[plane2Offset + x], x, y); return false; } } } return true; } bool YUVCompare( TSurfaceFormat surfaceFormat, const std::vector &yuvTest, const std::vector &yuvRef, unsigned int width, unsigned int height ) { switch (surfaceFormat) { case SURFACE_FORMAT_NV12: if (!YUVCompareNV12(yuvTest, yuvRef, width, height)) { log_error("OCL object is different than expected!\n"); return false; } break; case SURFACE_FORMAT_YV12: if (!YUVCompareYV12(yuvTest, yuvRef, width, height)) { log_error("OCL object is different than expected!\n"); return false; } break; default: log_error("YUVCompare(): Invalid surface type!\n"); return false; break; } return true; } void DataGenerate( TSurfaceFormat surfaceFormat, cl_channel_type type, std::vector &data, unsigned int width, unsigned int height, unsigned int channelNum, float cmin /*= 0.0f*/, float cmax /*= 1.0f*/, float add /*= 0.0f*/ ) { data.clear(); data.reserve(width * height * channelNum); double valueMin = static_cast(cmin); double valueMax = static_cast(cmax); double stepX = (valueMax - valueMin) / static_cast(width); double stepY = (valueMax - valueMin) /static_cast(height); double valueAdd = static_cast(add); for (unsigned int i = 0; i < height; ++i) { double valueY = static_cast(stepY * i); for (unsigned int j = 0; j < width; ++j) { double valueX = static_cast(stepX * j); switch (channelNum) { case 1: data.push_back(static_cast(valueMin + valueX / 2 + valueY / 2 + valueAdd)); break; case 2: data.push_back(static_cast(valueMin + valueX + valueAdd)); data.push_back(static_cast(valueMin + valueY + valueAdd)); break; case 4: data.push_back(static_cast(valueMin + valueX + valueAdd)); data.push_back(static_cast(valueMin + valueY + valueAdd)); data.push_back(static_cast(valueMin + valueX / 2 + valueAdd)); data.push_back(static_cast(valueMin + valueY / 2 + valueAdd)); break; default: log_error("DataGenerate(): invalid channel number!"); return; break; } } } } void DataGenerate( TSurfaceFormat surfaceFormat, cl_channel_type type, std::vector &data, unsigned int width, unsigned int height, unsigned int channelNum, float cmin /*= 0.0f*/, float cmax /*= 1.0f*/, float add /*= 0.0f*/ ) { data.clear(); data.reserve(width * height * channelNum); double valueMin = static_cast(cmin); double valueMax = static_cast(cmax); double stepX = (valueMax - valueMin) / static_cast(width); double stepY = (valueMax - valueMin) /static_cast(height); switch(type) { case CL_HALF_FLOAT: { double valueAdd = static_cast(add); for (unsigned int i = 0; i < height; ++i) { double valueY = static_cast(stepY * i); for (unsigned int j = 0; j < width; ++j) { double valueX = static_cast(stepX * j); switch (channelNum) { case 1: data.push_back(convert_float_to_half(static_cast(valueMin + valueX / 2 + valueY / 2 + valueAdd))); break; case 2: data.push_back(convert_float_to_half(static_cast(valueMin + valueX + valueAdd))); data.push_back(convert_float_to_half(static_cast(valueMin + valueY + valueAdd))); break; case 4: data.push_back(convert_float_to_half(static_cast(valueMin + valueX + valueAdd))); data.push_back(convert_float_to_half(static_cast(valueMin + valueY + valueAdd))); data.push_back(convert_float_to_half(static_cast(valueMin + valueX / 2 + valueAdd))); data.push_back(convert_float_to_half(static_cast(valueMin + valueY / 2 + valueAdd))); break; default: log_error("DataGenerate(): invalid channel number!"); return; break; } } } break; } case CL_UNORM_INT16: { double range = 65535; double valueAdd = static_cast(add * range); for (unsigned int i = 0; i < height; ++i) { double valueY = static_cast(stepY * i * range); for (unsigned int j = 0; j < width; ++j) { double valueX = static_cast(stepX * j * range); switch (channelNum) { case 1: data.push_back(static_cast(valueMin + valueX / 2 + valueY / 2 + valueAdd)); break; case 2: data.push_back(static_cast(valueMin + valueX + valueAdd)); data.push_back(static_cast(valueMin + valueY + valueAdd)); break; case 4: data.push_back(static_cast(valueMin + valueX + valueAdd)); data.push_back(static_cast(valueMin + valueY + valueAdd)); data.push_back(static_cast(valueMin + valueX / 2 + valueAdd)); data.push_back(static_cast(valueMin + valueY / 2 + valueAdd)); break; default: log_error("DataGenerate(): invalid channel number!"); return; break; } } } } break; default: log_error("DataGenerate(): unknown data type!"); return; break; } } void DataGenerate( TSurfaceFormat surfaceFormat, cl_channel_type type, std::vector &data, unsigned int width, unsigned int height, unsigned int channelNum, float cmin /*= 0.0f*/, float cmax /*= 1.0f*/, float add /*= 0.0f*/ ) { data.clear(); data.reserve(width * height * channelNum); double valueMin = static_cast(cmin); double valueMax = static_cast(cmax); double stepX = (valueMax - valueMin) / static_cast(width); double stepY = (valueMax - valueMin) /static_cast(height); double range = 255; double valueAdd = static_cast(add * range); for (unsigned int i = 0; i < height; ++i) { double valueY = static_cast(stepY * i * range); for (unsigned int j = 0; j < width; ++j) { double valueX = static_cast(stepX * j * range); switch (channelNum) { case 1: data.push_back(static_cast(valueMin + valueX / 2 + valueY / 2 + valueAdd)); break; case 2: data.push_back(static_cast(valueMin + valueX + valueAdd)); data.push_back(static_cast(valueMin + valueY + valueAdd)); break; case 4: data.push_back(static_cast(valueMin + valueX + valueAdd)); data.push_back(static_cast(valueMin + valueY + valueAdd)); data.push_back(static_cast(valueMin + valueX / 2 + valueAdd)); if (surfaceFormat == SURFACE_FORMAT_X8R8G8B8) data.push_back(static_cast(0xff)); else data.push_back(static_cast(valueMin + valueY / 2 + valueAdd)); break; default: log_error("DataGenerate(): invalid channel number!"); return; break; } } } } bool DataCompare( TSurfaceFormat surfaceFormat, cl_channel_type type, const std::vector &dataTest, const std::vector &dataExp, unsigned int width, unsigned int height, unsigned int channelNum) { float epsilon = 0.000001f; for (unsigned int i = 0; i < height; ++i) { unsigned int offset = i * width * channelNum; for (unsigned int j = 0; j < width; ++j) { for(unsigned planeIdx = 0; planeIdx < channelNum; ++planeIdx) { if (abs(dataTest.at(offset + j * channelNum + planeIdx) - dataExp.at(offset + j * channelNum + planeIdx)) > epsilon) { log_error("Tested image is different than reference (x,y,plane) = (%i,%i,%i), test value = %f, expected value = %f\n", j, i, planeIdx, dataTest[offset + j * channelNum + planeIdx], dataExp[offset + j * channelNum + planeIdx]); return false; } } } } return true; } bool DataCompare( TSurfaceFormat surfaceFormat, cl_channel_type type, const std::vector &dataTest, const std::vector &dataExp, unsigned int width, unsigned int height, unsigned int channelNum) { switch(type) { case CL_HALF_FLOAT: { float epsilon = 0.001f; for (unsigned int i = 0; i < height; ++i) { unsigned int offset = i * width * channelNum; for (unsigned int j = 0; j < width; ++j) { for(unsigned planeIdx = 0; planeIdx < channelNum; ++planeIdx) { float test = convert_half_to_float(dataTest.at(offset + j * channelNum + planeIdx)); float ref = convert_half_to_float(dataExp.at(offset + j * channelNum + planeIdx)); if (abs(test - ref) > epsilon) { log_error("Tested image is different than reference (x,y,plane) = (%i,%i,%i), test value = %f, expected value = %f\n", j, i, planeIdx, test, ref); return false; } } } } } break; case CL_UNORM_INT16: { cl_ushort epsilon = 1; for (unsigned int i = 0; i < height; ++i) { unsigned int offset = i * width * channelNum; for (unsigned int j = 0; j < width; ++j) { for(unsigned planeIdx = 0; planeIdx < channelNum; ++planeIdx) { cl_ushort test = dataTest.at(offset + j * channelNum + planeIdx); cl_ushort ref = dataExp.at(offset + j * channelNum + planeIdx); if (abs(test - ref) > epsilon) { log_error("Tested image is different than reference (x,y,plane) = (%i,%i,%i), test value = %i, expected value = %i\n", j, i, planeIdx, test, ref); return false; } } } } } break; default: log_error("DataCompare(): Invalid data format!"); return false; break; } return true; } bool DataCompare( TSurfaceFormat surfaceFormat, cl_channel_type type, const std::vector &dataTest, const std::vector &dataExp, unsigned int width, unsigned int height, unsigned int planeNum ) { for (unsigned int i = 0; i < height; ++i) { unsigned int offset = i * width * planeNum; for (unsigned int j = 0; j < width; ++j) { for(unsigned planeIdx = 0; planeIdx < planeNum; ++planeIdx) { if (surfaceFormat == SURFACE_FORMAT_X8R8G8B8 && planeIdx == 3) continue; cl_uchar test = dataTest.at(offset + j * planeNum + planeIdx); cl_uchar ref = dataExp.at(offset + j * planeNum + planeIdx); if (test != ref) { log_error("Tested image is different than reference (x,y,plane) = (%i,%i,%i), test value = %i, expected value = %i\n", j, i, planeIdx, test, ref); return false; } } } } return true; } bool GetImageInfo( cl_mem object, cl_image_format formatExp, size_t elementSizeExp, size_t rowPitchExp, size_t slicePitchExp, size_t widthExp, size_t heightExp, size_t depthExp , unsigned int planeExp) { bool result = true; cl_image_format format; if (clGetImageInfo(object, CL_IMAGE_FORMAT, sizeof(cl_image_format), &format, 0) != CL_SUCCESS) { log_error("clGetImageInfo(CL_IMAGE_FORMAT) failed\n"); result = false; } if (formatExp.image_channel_order != format.image_channel_order || formatExp.image_channel_data_type != format.image_channel_data_type) { log_error("Value of CL_IMAGE_FORMAT is different than expected\n"); result = false; } size_t elementSize = 0; if (clGetImageInfo(object, CL_IMAGE_ELEMENT_SIZE, sizeof(size_t), &elementSize, 0) != CL_SUCCESS) { log_error("clGetImageInfo(CL_IMAGE_ELEMENT_SIZE) failed\n"); result = false; } if (elementSizeExp != elementSize) { log_error("Value of CL_IMAGE_ELEMENT_SIZE is different than expected (size: %i, exp size: %i)\n", elementSize, elementSizeExp); result = false; } size_t rowPitch = 0; if (clGetImageInfo(object, CL_IMAGE_ROW_PITCH, sizeof(size_t), &rowPitch, 0) != CL_SUCCESS) { log_error("clGetImageInfo(CL_IMAGE_ROW_PITCH) failed\n"); result = false; } if ((rowPitchExp == 0 && rowPitchExp != rowPitch) || (rowPitchExp > 0 && rowPitchExp > rowPitch)) { log_error("Value of CL_IMAGE_ROW_PITCH is different than expected (size: %i, exp size: %i)\n", rowPitch, rowPitchExp); result = false; } size_t slicePitch = 0; if (clGetImageInfo(object, CL_IMAGE_SLICE_PITCH, sizeof(size_t), &slicePitch, 0) != CL_SUCCESS) { log_error("clGetImageInfo(CL_IMAGE_SLICE_PITCH) failed\n"); result = false; } if ((slicePitchExp == 0 && slicePitchExp != slicePitch) || (slicePitchExp > 0 && slicePitchExp > slicePitch)) { log_error("Value of CL_IMAGE_SLICE_PITCH is different than expected (size: %i, exp size: %i)\n", slicePitch, slicePitchExp); result = false; } size_t width = 0; if (clGetImageInfo(object, CL_IMAGE_WIDTH, sizeof(size_t), &width, 0) != CL_SUCCESS) { log_error("clGetImageInfo(CL_IMAGE_WIDTH) failed\n"); result = false; } if (widthExp != width) { log_error("Value of CL_IMAGE_WIDTH is different than expected (size: %i, exp size: %i)\n", width, widthExp); result = false; } size_t height = 0; if (clGetImageInfo(object, CL_IMAGE_HEIGHT, sizeof(size_t), &height, 0) != CL_SUCCESS) { log_error("clGetImageInfo(CL_IMAGE_HEIGHT) failed\n"); result = false; } if (heightExp != height) { log_error("Value of CL_IMAGE_HEIGHT is different than expected (size: %i, exp size: %i)\n", height, heightExp); result = false; } size_t depth = 0; if (clGetImageInfo(object, CL_IMAGE_DEPTH, sizeof(size_t), &depth, 0) != CL_SUCCESS) { log_error("clGetImageInfo(CL_IMAGE_DEPTH) failed\n"); result = false; } if (depthExp != depth) { log_error("Value of CL_IMAGE_DEPTH is different than expected (size: %i, exp size: %i)\n", depth, depthExp); result = false; } unsigned int plane = 99; size_t paramSize = 0; if (clGetImageInfo(object, CL_IMAGE_DX9_MEDIA_PLANE_KHR, sizeof(unsigned int), &plane, ¶mSize) != CL_SUCCESS) { log_error("clGetImageInfo(CL_IMAGE_MEDIA_SURFACE_PLANE_KHR) failed\n"); result = false; } if (planeExp != plane) { log_error("Value of CL_IMAGE_MEDIA_SURFACE_PLANE_KHR is different than expected (plane: %i, exp plane: %i)\n", plane, planeExp); result = false; } return result; } bool GetMemObjInfo( cl_mem object, cl_dx9_media_adapter_type_khr adapterType, std::auto_ptr &surface, void *shareHandleExp ) { bool result = true; switch(adapterType) { case CL_ADAPTER_D3D9_KHR: case CL_ADAPTER_D3D9EX_KHR: case CL_ADAPTER_DXVA_KHR: { #if defined(_WIN32) cl_dx9_surface_info_khr surfaceInfo; #else void *surfaceInfo = 0; return false; #endif size_t paramSize = 0; if(clGetMemObjectInfo(object, CL_MEM_DX9_MEDIA_SURFACE_INFO_KHR, sizeof(surfaceInfo), &surfaceInfo, ¶mSize) != CL_SUCCESS) { log_error("clGetImageInfo(CL_MEM_DX9_MEDIA_SURFACE_INFO_KHR) failed\n"); result = false; } #if defined(_WIN32) CD3D9SurfaceWrapper *d3d9Surface = static_cast(surface.get()); if (*d3d9Surface != surfaceInfo.resource) { log_error("Invalid resource for CL_MEM_DX9_MEDIA_SURFACE_INFO_KHR\n"); result = false; } if (shareHandleExp != surfaceInfo.shared_handle) { log_error("Invalid shared handle for CL_MEM_DX9_MEDIA_SURFACE_INFO_KHR\n"); result = false; } #else return false; #endif if (paramSize != sizeof(surfaceInfo)) { log_error("Invalid CL_MEM_DX9_MEDIA_SURFACE_INFO_KHR parameter size: %i, expected: %i\n", paramSize, sizeof(surfaceInfo)); result = false; } paramSize = 0; cl_dx9_media_adapter_type_khr mediaAdapterType; if(clGetMemObjectInfo(object, CL_MEM_DX9_MEDIA_ADAPTER_TYPE_KHR, sizeof(mediaAdapterType), &mediaAdapterType, ¶mSize) != CL_SUCCESS) { log_error("clGetImageInfo(CL_MEM_DX9_MEDIA_ADAPTER_TYPE_KHR) failed\n"); result = false; } if (adapterType != mediaAdapterType) { log_error("Invalid media adapter type for CL_MEM_DX9_MEDIA_ADAPTER_TYPE_KHR\n"); result = false; } if (paramSize != sizeof(mediaAdapterType)) { log_error("Invalid CL_MEM_DX9_MEDIA_ADAPTER_TYPE_KHR parameter size: %i, expected: %i\n", paramSize, sizeof(mediaAdapterType)); result = false; } } break; default: log_error("GetMemObjInfo(): Unknown adapter type!\n"); return false; break; } return result; } bool ImageInfoVerify( cl_dx9_media_adapter_type_khr adapterType, const std::vector &memObjList, unsigned int width, unsigned int height, std::auto_ptr &surface, void *sharedHandle) { if (memObjList.size() != 2 && memObjList.size() != 3) { log_error("ImageInfoVerify(): Invalid object list parameter\n"); return false; } cl_image_format formatPlane; formatPlane.image_channel_data_type = CL_UNORM_INT8; formatPlane.image_channel_order = CL_R; //plane 0 verification if (!GetImageInfo(memObjList[0], formatPlane, sizeof(cl_uchar), width * sizeof(cl_uchar), 0, width, height, 0, 0)) { log_error("clGetImageInfo failed\n"); return false; } switch (memObjList.size()) { case 2: { formatPlane.image_channel_data_type = CL_UNORM_INT8; formatPlane.image_channel_order = CL_RG; if (!GetImageInfo(memObjList[1], formatPlane, sizeof(cl_uchar) * 2, width * sizeof(cl_uchar), 0, width / 2, height / 2, 0, 1)) { log_error("clGetImageInfo failed\n"); return false; } } break; case 3: { if (!GetImageInfo(memObjList[1], formatPlane, sizeof(cl_uchar), width * sizeof(cl_uchar) / 2, 0, width / 2, height / 2, 0, 1)) { log_error("clGetImageInfo failed\n"); return false; } if (!GetImageInfo(memObjList[2], formatPlane, sizeof(cl_uchar), width * sizeof(cl_uchar) / 2, 0, width / 2, height / 2, 0, 2)) { log_error("clGetImageInfo failed\n"); return false; } } break; default: log_error("ImageInfoVerify(): Invalid object list parameter\n"); return false; break; } for (size_t i = 0; i < memObjList.size(); ++i) { if (!GetMemObjInfo(memObjList[i], adapterType, surface, sharedHandle)) { log_error("clGetMemObjInfo(%i) failed\n", i); return false; } } return true; } bool ImageFormatCheck(cl_context context, cl_mem_object_type imageType, const cl_image_format imageFormatCheck) { cl_uint imageFormatsNum = 0; cl_int error = clGetSupportedImageFormats(context, CL_MEM_READ_WRITE, imageType, 0, 0, &imageFormatsNum); if(error != CL_SUCCESS) { log_error("clGetSupportedImageFormats failed\n"); return false; } if(imageFormatsNum < 1) { log_error("Invalid image format number returned by clGetSupportedImageFormats\n"); return false; } std::vector imageFormats(imageFormatsNum); error = clGetSupportedImageFormats(context, CL_MEM_READ_WRITE, imageType, imageFormatsNum, &imageFormats[0], 0); if(error != CL_SUCCESS) { log_error("clGetSupportedImageFormats failed\n"); return false; } for(cl_uint i = 0; i < imageFormatsNum; ++i) { if(imageFormats[i].image_channel_data_type == imageFormatCheck.image_channel_data_type && imageFormats[i].image_channel_order == imageFormatCheck.image_channel_order) { return true; } } return false; } unsigned int ChannelNum( TSurfaceFormat surfaceFormat ) { switch(surfaceFormat) { case SURFACE_FORMAT_R32F: case SURFACE_FORMAT_R16F: case SURFACE_FORMAT_L16: case SURFACE_FORMAT_A8: case SURFACE_FORMAT_L8: return 1; break; case SURFACE_FORMAT_G32R32F: case SURFACE_FORMAT_G16R16F: case SURFACE_FORMAT_G16R16: case SURFACE_FORMAT_A8L8: return 2; break; case SURFACE_FORMAT_NV12: case SURFACE_FORMAT_YV12: return 3; break; case SURFACE_FORMAT_A32B32G32R32F: case SURFACE_FORMAT_A16B16G16R16F: case SURFACE_FORMAT_A16B16G16R16: case SURFACE_FORMAT_A8B8G8R8: case SURFACE_FORMAT_X8B8G8R8: case SURFACE_FORMAT_A8R8G8B8: case SURFACE_FORMAT_X8R8G8B8: return 4; break; default: log_error("ChannelNum(): unknown surface format!\n"); return 0; break; } } unsigned int PlanesNum( TSurfaceFormat surfaceFormat ) { switch(surfaceFormat) { case SURFACE_FORMAT_R32F: case SURFACE_FORMAT_R16F: case SURFACE_FORMAT_L16: case SURFACE_FORMAT_A8: case SURFACE_FORMAT_L8: case SURFACE_FORMAT_G32R32F: case SURFACE_FORMAT_G16R16F: case SURFACE_FORMAT_G16R16: case SURFACE_FORMAT_A8L8: case SURFACE_FORMAT_A32B32G32R32F: case SURFACE_FORMAT_A16B16G16R16F: case SURFACE_FORMAT_A16B16G16R16: case SURFACE_FORMAT_A8B8G8R8: case SURFACE_FORMAT_X8B8G8R8: case SURFACE_FORMAT_A8R8G8B8: case SURFACE_FORMAT_X8R8G8B8: return 1; break; case SURFACE_FORMAT_NV12: return 2; break; case SURFACE_FORMAT_YV12: return 3; break; default: log_error("PlanesNum(): unknown surface format!\n"); return 0; break; } } #if defined(_WIN32) D3DFORMAT SurfaceFormatToD3D(TSurfaceFormat surfaceFormat) { switch(surfaceFormat) { case SURFACE_FORMAT_R32F: return D3DFMT_R32F; break; case SURFACE_FORMAT_R16F: return D3DFMT_R16F; break; case SURFACE_FORMAT_L16: return D3DFMT_L16; break; case SURFACE_FORMAT_A8: return D3DFMT_A8; break; case SURFACE_FORMAT_L8: return D3DFMT_L8; break; case SURFACE_FORMAT_G32R32F: return D3DFMT_G32R32F; break; case SURFACE_FORMAT_G16R16F: return D3DFMT_G16R16F; break; case SURFACE_FORMAT_G16R16: return D3DFMT_G16R16; break; case SURFACE_FORMAT_A8L8: return D3DFMT_A8L8; break; case SURFACE_FORMAT_A32B32G32R32F: return D3DFMT_A32B32G32R32F; break; case SURFACE_FORMAT_A16B16G16R16F: return D3DFMT_A16B16G16R16F; break; case SURFACE_FORMAT_A16B16G16R16: return D3DFMT_A16B16G16R16; break; case SURFACE_FORMAT_A8B8G8R8: return D3DFMT_A8B8G8R8; break; case SURFACE_FORMAT_X8B8G8R8: return D3DFMT_X8B8G8R8; break; case SURFACE_FORMAT_A8R8G8B8: return D3DFMT_A8R8G8B8; break; case SURFACE_FORMAT_X8R8G8B8: return D3DFMT_X8R8G8B8; break; case SURFACE_FORMAT_NV12: return static_cast(MAKEFOURCC('N', 'V', '1', '2')); break; case SURFACE_FORMAT_YV12: return static_cast(MAKEFOURCC('Y', 'V', '1', '2')); break; default: log_error("SurfaceFormatToD3D(): unknown surface format!\n"); return D3DFMT_R32F; break; } } #endif bool DeviceCreate( cl_dx9_media_adapter_type_khr adapterType, std::auto_ptr &device ) { switch (adapterType) { #if defined(_WIN32) case CL_ADAPTER_D3D9_KHR: device = std::auto_ptr(new CD3D9Wrapper()); break; case CL_ADAPTER_D3D9EX_KHR: device = std::auto_ptr(new CD3D9ExWrapper()); break; case CL_ADAPTER_DXVA_KHR: device = std::auto_ptr(new CDXVAWrapper()); break; #endif default: log_error("DeviceCreate(): Unknown adapter type!\n"); return false; break; } return device->Status(); } bool SurfaceFormatCheck( cl_dx9_media_adapter_type_khr adapterType, const CDeviceWrapper &device, TSurfaceFormat surfaceFormat ) { switch (adapterType) { #if defined(_WIN32) case CL_ADAPTER_D3D9_KHR: case CL_ADAPTER_D3D9EX_KHR: case CL_ADAPTER_DXVA_KHR: { D3DFORMAT d3dFormat = SurfaceFormatToD3D(surfaceFormat); LPDIRECT3D9 d3d9 = static_cast(device.D3D()); D3DDISPLAYMODE d3ddm; d3d9->GetAdapterDisplayMode(device.AdapterIdx(), &d3ddm); if( FAILED(d3d9->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3ddm.Format, 0, D3DRTYPE_SURFACE, d3dFormat)) ) return false; } break; #endif default: log_error("SurfaceFormatCheck(): Unknown adapter type!\n"); return false; break; } return true; } bool SurfaceFormatToOCL(TSurfaceFormat surfaceFormat, cl_image_format &format) { switch(surfaceFormat) { case SURFACE_FORMAT_R32F: format.image_channel_order = CL_R; format.image_channel_data_type = CL_FLOAT; break; case SURFACE_FORMAT_R16F: format.image_channel_order = CL_R; format.image_channel_data_type = CL_HALF_FLOAT; break; case SURFACE_FORMAT_L16: format.image_channel_order = CL_R; format.image_channel_data_type = CL_UNORM_INT16; break; case SURFACE_FORMAT_A8: format.image_channel_order = CL_A; format.image_channel_data_type = CL_UNORM_INT8; break; case SURFACE_FORMAT_L8: format.image_channel_order = CL_R; format.image_channel_data_type = CL_UNORM_INT8; break; case SURFACE_FORMAT_G32R32F: format.image_channel_order = CL_RG; format.image_channel_data_type = CL_FLOAT; break; case SURFACE_FORMAT_G16R16F: format.image_channel_order = CL_RG; format.image_channel_data_type = CL_HALF_FLOAT; break; case SURFACE_FORMAT_G16R16: format.image_channel_order = CL_RG; format.image_channel_data_type = CL_UNORM_INT16; break; case SURFACE_FORMAT_A8L8: format.image_channel_order = CL_RG; format.image_channel_data_type = CL_UNORM_INT8; break; case SURFACE_FORMAT_A32B32G32R32F: format.image_channel_order = CL_RGBA; format.image_channel_data_type = CL_FLOAT; break; case SURFACE_FORMAT_A16B16G16R16F: format.image_channel_order = CL_RGBA; format.image_channel_data_type = CL_HALF_FLOAT; break; case SURFACE_FORMAT_A16B16G16R16: format.image_channel_order = CL_RGBA; format.image_channel_data_type = CL_UNORM_INT16; break; case SURFACE_FORMAT_A8B8G8R8: format.image_channel_order = CL_RGBA; format.image_channel_data_type = CL_UNORM_INT8; break; case SURFACE_FORMAT_X8B8G8R8: format.image_channel_order = CL_RGBA; format.image_channel_data_type = CL_UNORM_INT8; break; case SURFACE_FORMAT_A8R8G8B8: format.image_channel_order = CL_BGRA; format.image_channel_data_type = CL_UNORM_INT8; break; case SURFACE_FORMAT_X8R8G8B8: format.image_channel_order = CL_BGRA; format.image_channel_data_type = CL_UNORM_INT8; break; case SURFACE_FORMAT_NV12: format.image_channel_order = CL_R; format.image_channel_data_type = CL_UNORM_INT8; break; case SURFACE_FORMAT_YV12: format.image_channel_order = CL_R; format.image_channel_data_type = CL_UNORM_INT8; break; default: log_error("SurfaceFormatToOCL(): Unknown surface format!\n"); return false; break; } return true; } void SurfaceFormatToString( TSurfaceFormat surfaceFormat, std::string &str ) { switch(surfaceFormat) { case SURFACE_FORMAT_R32F: str = "R32F"; break; case SURFACE_FORMAT_R16F: str = "R16F"; break; case SURFACE_FORMAT_L16: str = "L16"; break; case SURFACE_FORMAT_A8: str = "A8"; break; case SURFACE_FORMAT_L8: str = "L8"; break; case SURFACE_FORMAT_G32R32F: str = "G32R32F"; break; case SURFACE_FORMAT_G16R16F: str = "G16R16F"; break; case SURFACE_FORMAT_G16R16: str = "G16R16"; break; case SURFACE_FORMAT_A8L8: str = "A8L8"; break; case SURFACE_FORMAT_A32B32G32R32F: str = "A32B32G32R32F"; break; case SURFACE_FORMAT_A16B16G16R16F: str = "A16B16G16R16F"; break; case SURFACE_FORMAT_A16B16G16R16: str = "A16B16G16R16"; break; case SURFACE_FORMAT_A8B8G8R8: str = "A8B8G8R8"; break; case SURFACE_FORMAT_X8B8G8R8: str = "X8B8G8R8"; break; case SURFACE_FORMAT_A8R8G8B8: str = "A8R8G8B8"; break; case SURFACE_FORMAT_X8R8G8B8: str = "X8R8G8B8"; break; case SURFACE_FORMAT_NV12: str = "NV12"; break; case SURFACE_FORMAT_YV12: str = "YV12"; break; default: log_error("SurfaceFormatToString(): unknown surface format!\n"); str = "unknown"; break; } } bool MediaSurfaceCreate(cl_dx9_media_adapter_type_khr adapterType, unsigned int width, unsigned int height, TSurfaceFormat surfaceFormat, CDeviceWrapper &device, std::auto_ptr &surface, bool sharedHandle, void **objectSharedHandle) { switch (adapterType) { #if defined(_WIN32) case CL_ADAPTER_D3D9_KHR: { surface = std::auto_ptr(new CD3D9SurfaceWrapper); CD3D9SurfaceWrapper *d3dSurface = static_cast(surface.get()); HRESULT hr = 0; D3DFORMAT d3dFormat = SurfaceFormatToD3D(surfaceFormat); LPDIRECT3DDEVICE9 d3d9Device = (LPDIRECT3DDEVICE9)device.Device(); hr = d3d9Device->CreateOffscreenPlainSurface(width, height, d3dFormat, D3DPOOL_DEFAULT, &(*d3dSurface), sharedHandle ? objectSharedHandle: 0); if ( FAILED(hr)) { log_error("CreateOffscreenPlainSurface failed\n"); return false; } } break; case CL_ADAPTER_D3D9EX_KHR: { surface = std::auto_ptr(new CD3D9SurfaceWrapper); CD3D9SurfaceWrapper *d3dSurface = static_cast(surface.get()); HRESULT hr = 0; D3DFORMAT d3dFormat = SurfaceFormatToD3D(surfaceFormat); LPDIRECT3DDEVICE9EX d3d9ExDevice = (LPDIRECT3DDEVICE9EX)device.Device(); hr = d3d9ExDevice->CreateOffscreenPlainSurface(width, height, d3dFormat, D3DPOOL_DEFAULT, &(*d3dSurface), sharedHandle ? objectSharedHandle: 0); if ( FAILED(hr)) { log_error("CreateOffscreenPlainSurface failed\n"); return false; } } break; case CL_ADAPTER_DXVA_KHR: { surface = std::auto_ptr(new CD3D9SurfaceWrapper); CD3D9SurfaceWrapper *d3dSurface = static_cast(surface.get()); HRESULT hr = 0; D3DFORMAT d3dFormat = SurfaceFormatToD3D(surfaceFormat); IDXVAHD_Device *dxvaDevice = (IDXVAHD_Device *)device.Device(); hr = dxvaDevice->CreateVideoSurface(width, height, d3dFormat, D3DPOOL_DEFAULT, 0, DXVAHD_SURFACE_TYPE_VIDEO_INPUT, 1, &(*d3dSurface), sharedHandle ? objectSharedHandle: 0); if ( FAILED(hr)) { log_error("CreateVideoSurface failed\n"); return false; } } break; #endif default: log_error("MediaSurfaceCreate(): Unknown adapter type!\n"); return false; break; } return true; } cl_ushort float2half_rte( float f ) { union{ float f; cl_uint u; } u = {f}; cl_uint sign = (u.u >> 16) & 0x8000; float x = fabsf(f); //Nan if( x != x ) { u.u >>= (24-11); u.u &= 0x7fff; u.u |= 0x0200; //silence the NaN return u.u | sign; } // overflow if( x >= MAKE_HEX_FLOAT(0x1.ffep15f, 0x1ffeL, 3) ) return 0x7c00 | sign; // underflow if( x <= MAKE_HEX_FLOAT(0x1.0p-25f, 0x1L, -25) ) return sign; // The halfway case can return 0x0001 or 0. 0 is even. // very small if( x < MAKE_HEX_FLOAT(0x1.8p-24f, 0x18L, -28) ) return sign | 1; // half denormal if( x < MAKE_HEX_FLOAT(0x1.0p-14f, 0x1L, -14) ) { u.f = x * MAKE_HEX_FLOAT(0x1.0p-125f, 0x1L, -125); return sign | u.u; } u.f *= MAKE_HEX_FLOAT(0x1.0p13f, 0x1L, 13); u.u &= 0x7f800000; x += u.f; u.f = x - u.f; u.f *= MAKE_HEX_FLOAT(0x1.0p-112f, 0x1L, -112); return (u.u >> (24-11)) | sign; } cl_ushort float2half_rtz( float f ) { union{ float f; cl_uint u; } u = {f}; cl_uint sign = (u.u >> 16) & 0x8000; float x = fabsf(f); //Nan if( x != x ) { u.u >>= (24-11); u.u &= 0x7fff; u.u |= 0x0200; //silence the NaN return u.u | sign; } // overflow if( x >= MAKE_HEX_FLOAT(0x1.0p16f, 0x1L, 16) ) { if( x == INFINITY ) return 0x7c00 | sign; return 0x7bff | sign; } // underflow if( x < MAKE_HEX_FLOAT(0x1.0p-24f, 0x1L, -24) ) return sign; // The halfway case can return 0x0001 or 0. 0 is even. // half denormal if( x < MAKE_HEX_FLOAT(0x1.0p-14f, 0x1L, -14) ) { x *= MAKE_HEX_FLOAT(0x1.0p24f, 0x1L, 24); return (cl_ushort)((int) x | sign); } u.u &= 0xFFFFE000U; u.u -= 0x38000000U; return (u.u >> (24-11)) | sign; } cl_int deviceExistForCLTest(cl_platform_id platform, cl_dx9_media_adapter_type_khr media_adapters_type, void *media_adapters, CResult &result, TSharedHandleType sharedHandle /*default SHARED_HANDLE_ENABLED*/ ) { cl_int _error; cl_uint devicesAllNum = 0; std::string sharedHandleStr = (sharedHandle == SHARED_HANDLE_ENABLED)? "yes": "no"; std::string adapterStr; AdapterToString(media_adapters_type, adapterStr); _error = clGetDeviceIDsFromDX9MediaAdapterKHR(platform, 1, &media_adapters_type, &media_adapters, CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR, 0, 0, &devicesAllNum); if (_error != CL_SUCCESS) { if(_error != CL_DEVICE_NOT_FOUND) { log_error("clGetDeviceIDsFromDX9MediaAdapterKHR failed: %s\n", IGetErrorString(_error)); result.ResultSub(CResult::TEST_ERROR); } else { log_info("Skipping test case, device type is not supported by a device (adapter type: %s, shared handle: %s)\n", adapterStr.c_str(), sharedHandleStr.c_str()); result.ResultSub(CResult::TEST_NOTSUPPORTED); } } return _error; }