mirror of
https://github.com/KhronosGroup/OpenCL-CTS.git
synced 2026-03-19 06:09:01 +00:00
Fixes #2155 according to issue description Additional remark: The image size was previously calculated based on the memory size, which seems unusual. Due to Vulkan's configuration capabilities, the size of memory allocated for a specific texture may differ from what would be expected based on the texture dimensions. Thus, calculating the image dimensions back from the memory size of a Vulkan texture can be challenging.
1328 lines
48 KiB
C++
1328 lines
48 KiB
C++
//
|
|
// Copyright (c) 2022 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 <CL/cl_ext.h>
|
|
#include "opencl_vulkan_wrapper.hpp"
|
|
#include "vulkan_wrapper.hpp"
|
|
#include "harness/errorHelpers.h"
|
|
#include "harness/deviceInfo.h"
|
|
#include <assert.h>
|
|
#include <algorithm>
|
|
#include <stdexcept>
|
|
|
|
#define ASSERT(x) assert((x))
|
|
#define GB(x) ((unsigned long long)(x) << 30)
|
|
|
|
pfnclCreateSemaphoreWithPropertiesKHR clCreateSemaphoreWithPropertiesKHRptr;
|
|
pfnclEnqueueWaitSemaphoresKHR clEnqueueWaitSemaphoresKHRptr;
|
|
pfnclEnqueueSignalSemaphoresKHR clEnqueueSignalSemaphoresKHRptr;
|
|
pfnclEnqueueAcquireExternalMemObjectsKHR
|
|
clEnqueueAcquireExternalMemObjectsKHRptr;
|
|
pfnclEnqueueReleaseExternalMemObjectsKHR
|
|
clEnqueueReleaseExternalMemObjectsKHRptr;
|
|
pfnclReleaseSemaphoreKHR clReleaseSemaphoreKHRptr;
|
|
pfnclGetSemaphoreHandleForTypeKHR clGetSemaphoreHandleForTypeKHRptr;
|
|
pfnclReImportSemaphoreSyncFdKHR clReImportSemaphoreSyncFdKHRptr;
|
|
|
|
void init_cl_vk_ext(cl_platform_id opencl_platform, cl_uint num_devices,
|
|
cl_device_id *deviceIds)
|
|
{
|
|
clEnqueueWaitSemaphoresKHRptr =
|
|
(pfnclEnqueueWaitSemaphoresKHR)clGetExtensionFunctionAddressForPlatform(
|
|
opencl_platform, "clEnqueueWaitSemaphoresKHR");
|
|
if (NULL == clEnqueueWaitSemaphoresKHRptr)
|
|
{
|
|
throw std::runtime_error("Failed to get the function pointer of "
|
|
"clEnqueueWaitSemaphoresKHRptr!");
|
|
}
|
|
clEnqueueSignalSemaphoresKHRptr = (pfnclEnqueueSignalSemaphoresKHR)
|
|
clGetExtensionFunctionAddressForPlatform(
|
|
opencl_platform, "clEnqueueSignalSemaphoresKHR");
|
|
if (NULL == clEnqueueSignalSemaphoresKHRptr)
|
|
{
|
|
throw std::runtime_error("Failed to get the function pointer of "
|
|
"clEnqueueSignalSemaphoresKHRptr!");
|
|
}
|
|
clReleaseSemaphoreKHRptr =
|
|
(pfnclReleaseSemaphoreKHR)clGetExtensionFunctionAddressForPlatform(
|
|
opencl_platform, "clReleaseSemaphoreKHR");
|
|
if (NULL == clReleaseSemaphoreKHRptr)
|
|
{
|
|
throw std::runtime_error("Failed to get the function pointer of "
|
|
"clReleaseSemaphoreKHRptr!");
|
|
}
|
|
clCreateSemaphoreWithPropertiesKHRptr =
|
|
(pfnclCreateSemaphoreWithPropertiesKHR)
|
|
clGetExtensionFunctionAddressForPlatform(
|
|
opencl_platform, "clCreateSemaphoreWithPropertiesKHR");
|
|
if (NULL == clCreateSemaphoreWithPropertiesKHRptr)
|
|
{
|
|
throw std::runtime_error("Failed to get the function pointer of "
|
|
"clCreateSemaphoreWithPropertiesKHRptr!");
|
|
}
|
|
|
|
clGetSemaphoreHandleForTypeKHRptr = (pfnclGetSemaphoreHandleForTypeKHR)
|
|
clGetExtensionFunctionAddressForPlatform(
|
|
opencl_platform, "clGetSemaphoreHandleForTypeKHR");
|
|
if (NULL == clGetSemaphoreHandleForTypeKHRptr)
|
|
{
|
|
throw std::runtime_error("Failed to get the function pointer of "
|
|
"clGetSemaphoreHandleForTypeKHRptr!");
|
|
}
|
|
|
|
// Required only if cl_khr_external_semaphore_sync_fd is reported
|
|
clReImportSemaphoreSyncFdKHRptr = (pfnclReImportSemaphoreSyncFdKHR)
|
|
clGetExtensionFunctionAddressForPlatform(
|
|
opencl_platform, "clReImportSemaphoreSyncFdKHR");
|
|
for (cl_uint i = 0; i < num_devices; i++)
|
|
{
|
|
if (is_extension_available(deviceIds[i],
|
|
"cl_khr_external_semaphore_sync_fd")
|
|
&& (NULL == clReImportSemaphoreSyncFdKHRptr))
|
|
{
|
|
throw std::runtime_error("Failed to get the function pointer of "
|
|
"clReImportSemaphoreSyncFdKHR!");
|
|
}
|
|
}
|
|
|
|
clEnqueueAcquireExternalMemObjectsKHRptr =
|
|
(pfnclEnqueueAcquireExternalMemObjectsKHR)
|
|
clGetExtensionFunctionAddressForPlatform(
|
|
opencl_platform, "clEnqueueAcquireExternalMemObjectsKHR");
|
|
if (nullptr == clEnqueueAcquireExternalMemObjectsKHRptr)
|
|
{
|
|
throw std::runtime_error("Failed to get the function pointer of "
|
|
"clEnqueueAcquireExternalMemObjectsKHR!");
|
|
}
|
|
|
|
clEnqueueReleaseExternalMemObjectsKHRptr =
|
|
(pfnclEnqueueReleaseExternalMemObjectsKHR)
|
|
clGetExtensionFunctionAddressForPlatform(
|
|
opencl_platform, "clEnqueueReleaseExternalMemObjectsKHR");
|
|
if (nullptr == clEnqueueReleaseExternalMemObjectsKHRptr)
|
|
{
|
|
throw std::runtime_error("Failed to get the function pointer of "
|
|
"clEnqueueReleaseExternalMemObjectsKHR!");
|
|
}
|
|
}
|
|
|
|
cl_int setMaxImageDimensions(cl_device_id deviceID, size_t &max_width,
|
|
size_t &max_height)
|
|
{
|
|
cl_int result = CL_SUCCESS;
|
|
cl_ulong val;
|
|
size_t paramSize;
|
|
|
|
result = clGetDeviceInfo(deviceID, CL_DEVICE_GLOBAL_MEM_SIZE,
|
|
sizeof(cl_ulong), &val, ¶mSize);
|
|
|
|
if (result != CL_SUCCESS)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
if (val < GB(4))
|
|
{
|
|
max_width = 256;
|
|
max_height = 256;
|
|
}
|
|
else if (val < GB(8))
|
|
{
|
|
max_width = 512;
|
|
max_height = 256;
|
|
}
|
|
else
|
|
{
|
|
max_width = 1024;
|
|
max_height = 512;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
cl_int getCLFormatFromVkFormat(VkFormat vkFormat,
|
|
cl_image_format *clImageFormat)
|
|
{
|
|
cl_int result = CL_SUCCESS;
|
|
switch (vkFormat)
|
|
{
|
|
case VK_FORMAT_R8G8B8A8_UNORM:
|
|
clImageFormat->image_channel_order = CL_RGBA;
|
|
clImageFormat->image_channel_data_type = CL_UNORM_INT8;
|
|
break;
|
|
case VK_FORMAT_B8G8R8A8_UNORM:
|
|
clImageFormat->image_channel_order = CL_BGRA;
|
|
clImageFormat->image_channel_data_type = CL_UNORM_INT8;
|
|
break;
|
|
case VK_FORMAT_R16G16B16A16_UNORM:
|
|
clImageFormat->image_channel_order = CL_RGBA;
|
|
clImageFormat->image_channel_data_type = CL_UNORM_INT16;
|
|
break;
|
|
case VK_FORMAT_R8G8B8A8_SINT:
|
|
clImageFormat->image_channel_order = CL_RGBA;
|
|
clImageFormat->image_channel_data_type = CL_SIGNED_INT8;
|
|
break;
|
|
case VK_FORMAT_R16G16B16A16_SINT:
|
|
clImageFormat->image_channel_order = CL_RGBA;
|
|
clImageFormat->image_channel_data_type = CL_SIGNED_INT16;
|
|
break;
|
|
case VK_FORMAT_R32G32B32A32_SINT:
|
|
clImageFormat->image_channel_order = CL_RGBA;
|
|
clImageFormat->image_channel_data_type = CL_SIGNED_INT32;
|
|
break;
|
|
case VK_FORMAT_R8G8B8A8_UINT:
|
|
clImageFormat->image_channel_order = CL_RGBA;
|
|
clImageFormat->image_channel_data_type = CL_UNSIGNED_INT8;
|
|
break;
|
|
case VK_FORMAT_R16G16B16A16_UINT:
|
|
clImageFormat->image_channel_order = CL_RGBA;
|
|
clImageFormat->image_channel_data_type = CL_UNSIGNED_INT16;
|
|
break;
|
|
case VK_FORMAT_R32G32B32A32_UINT:
|
|
clImageFormat->image_channel_order = CL_RGBA;
|
|
clImageFormat->image_channel_data_type = CL_UNSIGNED_INT32;
|
|
break;
|
|
case VK_FORMAT_R16G16B16A16_SFLOAT:
|
|
clImageFormat->image_channel_order = CL_RGBA;
|
|
clImageFormat->image_channel_data_type = CL_HALF_FLOAT;
|
|
break;
|
|
case VK_FORMAT_R32G32B32A32_SFLOAT:
|
|
clImageFormat->image_channel_order = CL_RGBA;
|
|
clImageFormat->image_channel_data_type = CL_FLOAT;
|
|
break;
|
|
case VK_FORMAT_R8_SNORM:
|
|
clImageFormat->image_channel_order = CL_R;
|
|
clImageFormat->image_channel_data_type = CL_SNORM_INT8;
|
|
break;
|
|
case VK_FORMAT_R16_SNORM:
|
|
clImageFormat->image_channel_order = CL_R;
|
|
clImageFormat->image_channel_data_type = CL_SNORM_INT16;
|
|
break;
|
|
case VK_FORMAT_R8_UNORM:
|
|
clImageFormat->image_channel_order = CL_R;
|
|
clImageFormat->image_channel_data_type = CL_UNORM_INT8;
|
|
break;
|
|
case VK_FORMAT_R16_UNORM:
|
|
clImageFormat->image_channel_order = CL_R;
|
|
clImageFormat->image_channel_data_type = CL_UNORM_INT16;
|
|
break;
|
|
case VK_FORMAT_R8_SINT:
|
|
clImageFormat->image_channel_order = CL_R;
|
|
clImageFormat->image_channel_data_type = CL_SIGNED_INT8;
|
|
break;
|
|
case VK_FORMAT_R16_SINT:
|
|
clImageFormat->image_channel_order = CL_R;
|
|
clImageFormat->image_channel_data_type = CL_SIGNED_INT16;
|
|
break;
|
|
case VK_FORMAT_R32_SINT:
|
|
clImageFormat->image_channel_order = CL_R;
|
|
clImageFormat->image_channel_data_type = CL_SIGNED_INT32;
|
|
break;
|
|
case VK_FORMAT_R8_UINT:
|
|
clImageFormat->image_channel_order = CL_R;
|
|
clImageFormat->image_channel_data_type = CL_UNSIGNED_INT8;
|
|
break;
|
|
case VK_FORMAT_R16_UINT:
|
|
clImageFormat->image_channel_order = CL_R;
|
|
clImageFormat->image_channel_data_type = CL_UNSIGNED_INT16;
|
|
break;
|
|
case VK_FORMAT_R32_UINT:
|
|
clImageFormat->image_channel_order = CL_R;
|
|
clImageFormat->image_channel_data_type = CL_UNSIGNED_INT32;
|
|
break;
|
|
case VK_FORMAT_R16_SFLOAT:
|
|
clImageFormat->image_channel_order = CL_R;
|
|
clImageFormat->image_channel_data_type = CL_HALF_FLOAT;
|
|
break;
|
|
case VK_FORMAT_R32_SFLOAT:
|
|
clImageFormat->image_channel_order = CL_R;
|
|
clImageFormat->image_channel_data_type = CL_FLOAT;
|
|
break;
|
|
case VK_FORMAT_R8G8_SNORM:
|
|
clImageFormat->image_channel_order = CL_RG;
|
|
clImageFormat->image_channel_data_type = CL_SNORM_INT8;
|
|
break;
|
|
case VK_FORMAT_R16G16_SNORM:
|
|
clImageFormat->image_channel_order = CL_RG;
|
|
clImageFormat->image_channel_data_type = CL_SNORM_INT16;
|
|
break;
|
|
case VK_FORMAT_R8G8_UNORM:
|
|
clImageFormat->image_channel_order = CL_RG;
|
|
clImageFormat->image_channel_data_type = CL_UNORM_INT8;
|
|
break;
|
|
case VK_FORMAT_R16G16_UNORM:
|
|
clImageFormat->image_channel_order = CL_RG;
|
|
clImageFormat->image_channel_data_type = CL_UNORM_INT16;
|
|
break;
|
|
case VK_FORMAT_R8G8_SINT:
|
|
clImageFormat->image_channel_order = CL_RG;
|
|
clImageFormat->image_channel_data_type = CL_SIGNED_INT8;
|
|
break;
|
|
case VK_FORMAT_R16G16_SINT:
|
|
clImageFormat->image_channel_order = CL_RG;
|
|
clImageFormat->image_channel_data_type = CL_SIGNED_INT16;
|
|
break;
|
|
case VK_FORMAT_R32G32_SINT:
|
|
clImageFormat->image_channel_order = CL_RG;
|
|
clImageFormat->image_channel_data_type = CL_SIGNED_INT32;
|
|
break;
|
|
case VK_FORMAT_R8G8_UINT:
|
|
clImageFormat->image_channel_order = CL_RG;
|
|
clImageFormat->image_channel_data_type = CL_UNSIGNED_INT8;
|
|
break;
|
|
case VK_FORMAT_R16G16_UINT:
|
|
clImageFormat->image_channel_order = CL_RG;
|
|
clImageFormat->image_channel_data_type = CL_UNSIGNED_INT16;
|
|
break;
|
|
case VK_FORMAT_R32G32_UINT:
|
|
clImageFormat->image_channel_order = CL_RG;
|
|
clImageFormat->image_channel_data_type = CL_UNSIGNED_INT32;
|
|
break;
|
|
case VK_FORMAT_R16G16_SFLOAT:
|
|
clImageFormat->image_channel_order = CL_RG;
|
|
clImageFormat->image_channel_data_type = CL_HALF_FLOAT;
|
|
break;
|
|
case VK_FORMAT_R32G32_SFLOAT:
|
|
clImageFormat->image_channel_order = CL_RG;
|
|
clImageFormat->image_channel_data_type = CL_FLOAT;
|
|
break;
|
|
case VK_FORMAT_R5G6B5_UNORM_PACK16:
|
|
clImageFormat->image_channel_order = CL_RGBA;
|
|
clImageFormat->image_channel_data_type = CL_UNORM_SHORT_565;
|
|
break;
|
|
case VK_FORMAT_R5G5B5A1_UNORM_PACK16:
|
|
clImageFormat->image_channel_order = CL_RGBA;
|
|
clImageFormat->image_channel_data_type = CL_UNORM_SHORT_555;
|
|
break;
|
|
case VK_FORMAT_R8G8B8A8_SNORM:
|
|
clImageFormat->image_channel_order = CL_RGBA;
|
|
clImageFormat->image_channel_data_type = CL_SNORM_INT8;
|
|
break;
|
|
case VK_FORMAT_R16G16B16A16_SNORM:
|
|
clImageFormat->image_channel_order = CL_RGBA;
|
|
clImageFormat->image_channel_data_type = CL_SNORM_INT16;
|
|
break;
|
|
case VK_FORMAT_B8G8R8A8_SNORM:
|
|
clImageFormat->image_channel_order = CL_BGRA;
|
|
clImageFormat->image_channel_data_type = CL_SNORM_INT8;
|
|
break;
|
|
case VK_FORMAT_B5G6R5_UNORM_PACK16:
|
|
clImageFormat->image_channel_order = CL_BGRA;
|
|
clImageFormat->image_channel_data_type = CL_UNORM_SHORT_565;
|
|
break;
|
|
case VK_FORMAT_B5G5R5A1_UNORM_PACK16:
|
|
clImageFormat->image_channel_order = CL_BGRA;
|
|
clImageFormat->image_channel_data_type = CL_UNORM_SHORT_555;
|
|
break;
|
|
case VK_FORMAT_B8G8R8A8_SINT:
|
|
clImageFormat->image_channel_order = CL_BGRA;
|
|
clImageFormat->image_channel_data_type = CL_SIGNED_INT8;
|
|
break;
|
|
case VK_FORMAT_B8G8R8A8_UINT:
|
|
clImageFormat->image_channel_order = CL_BGRA;
|
|
clImageFormat->image_channel_data_type = CL_UNSIGNED_INT8;
|
|
break;
|
|
case VK_FORMAT_A8B8G8R8_SNORM_PACK32: result = CL_INVALID_VALUE; break;
|
|
case VK_FORMAT_A8B8G8R8_UNORM_PACK32: result = CL_INVALID_VALUE; break;
|
|
case VK_FORMAT_A8B8G8R8_SINT_PACK32: result = CL_INVALID_VALUE; break;
|
|
case VK_FORMAT_A8B8G8R8_UINT_PACK32: result = CL_INVALID_VALUE; break;
|
|
default:
|
|
log_error("Unsupported format\n");
|
|
ASSERT(0);
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
cl_mem_object_type getImageTypeFromVk(VkImageType imageType)
|
|
{
|
|
cl_mem_object_type cl_image_type = CL_INVALID_VALUE;
|
|
switch (imageType)
|
|
{
|
|
case VK_IMAGE_TYPE_1D: cl_image_type = CL_MEM_OBJECT_IMAGE1D; break;
|
|
case VK_IMAGE_TYPE_2D: cl_image_type = CL_MEM_OBJECT_IMAGE2D; break;
|
|
case VK_IMAGE_TYPE_3D: cl_image_type = CL_MEM_OBJECT_IMAGE3D; break;
|
|
default: break;
|
|
}
|
|
return cl_image_type;
|
|
}
|
|
|
|
size_t GetElementNBytes(const cl_image_format *format)
|
|
{
|
|
size_t result;
|
|
|
|
switch (format->image_channel_order)
|
|
{
|
|
case CL_R:
|
|
case CL_A:
|
|
case CL_INTENSITY:
|
|
case CL_LUMINANCE:
|
|
case CL_DEPTH: result = 1; break;
|
|
case CL_RG:
|
|
case CL_RA: result = 2; break;
|
|
case CL_RGB: result = 3; break;
|
|
case CL_RGBA:
|
|
case CL_ARGB:
|
|
case CL_BGRA:
|
|
case CL_sRGBA: result = 4; break;
|
|
default: result = 0; break;
|
|
}
|
|
|
|
switch (format->image_channel_data_type)
|
|
{
|
|
case CL_SNORM_INT8:
|
|
case CL_UNORM_INT8:
|
|
case CL_SIGNED_INT8:
|
|
case CL_UNSIGNED_INT8:
|
|
// result *= 1;
|
|
break;
|
|
|
|
case CL_SNORM_INT16:
|
|
case CL_UNORM_INT16:
|
|
case CL_SIGNED_INT16:
|
|
case CL_UNSIGNED_INT16:
|
|
case CL_HALF_FLOAT: result *= 2; break;
|
|
|
|
case CL_SIGNED_INT32:
|
|
case CL_UNSIGNED_INT32:
|
|
case CL_FLOAT: result *= 4; break;
|
|
|
|
case CL_UNORM_SHORT_565:
|
|
case CL_UNORM_SHORT_555:
|
|
if (result == 3)
|
|
{
|
|
result = 2;
|
|
}
|
|
else
|
|
{
|
|
result = 0;
|
|
}
|
|
break;
|
|
|
|
case CL_UNORM_INT_101010:
|
|
if (result == 3)
|
|
{
|
|
result = 4;
|
|
}
|
|
else
|
|
{
|
|
result = 0;
|
|
}
|
|
break;
|
|
|
|
default: result = 0; break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
cl_int getImageDimensions(const VkImageCreateInfo *VulkanImageCreateInfo,
|
|
cl_image_format *img_fmt, cl_image_desc *img_desc,
|
|
VkExtent3D max_ext, const VkSubresourceLayout *layout)
|
|
{
|
|
test_assert_error(
|
|
VulkanImageCreateInfo != nullptr,
|
|
"getImageDimensions: invalid VulkanImageCreateInfo pointer!");
|
|
test_assert_error(img_fmt != nullptr,
|
|
"getImageDimensions: invalid img_fmt pointer!");
|
|
test_assert_error(img_desc != nullptr,
|
|
"getImageDimensions: invalid img_desc pointer!");
|
|
|
|
img_desc->image_depth = VulkanImageCreateInfo->extent.depth;
|
|
img_desc->image_width = VulkanImageCreateInfo->extent.width;
|
|
img_desc->image_height = VulkanImageCreateInfo->extent.height;
|
|
|
|
if (layout != nullptr)
|
|
{
|
|
size_t element_size = GetElementNBytes(img_fmt);
|
|
size_t row_pitch = element_size * VulkanImageCreateInfo->extent.width;
|
|
row_pitch = row_pitch < layout->rowPitch ? layout->rowPitch : row_pitch;
|
|
img_desc->image_row_pitch = row_pitch;
|
|
|
|
size_t slice_pitch = row_pitch * VulkanImageCreateInfo->extent.height;
|
|
slice_pitch =
|
|
slice_pitch < layout->depthPitch ? layout->depthPitch : slice_pitch;
|
|
img_desc->image_slice_pitch = slice_pitch;
|
|
}
|
|
|
|
switch (img_desc->image_type)
|
|
{
|
|
case CL_MEM_OBJECT_IMAGE3D:
|
|
test_assert_error(img_desc->image_depth >= 1
|
|
&& img_desc->image_depth <= max_ext.depth,
|
|
"getImageDimensions: invalid image depth!");
|
|
case CL_MEM_OBJECT_IMAGE2D:
|
|
test_assert_error(img_desc->image_height >= 1
|
|
&& img_desc->image_height <= max_ext.height,
|
|
"getImageDimensions: invalid image height!");
|
|
case CL_MEM_OBJECT_IMAGE1D:
|
|
test_assert_error(img_desc->image_width >= 1
|
|
&& img_desc->image_width <= max_ext.width,
|
|
"getImageDimensions: invalid image width!");
|
|
}
|
|
|
|
return CL_SUCCESS;
|
|
}
|
|
|
|
cl_int
|
|
getCLImageInfoFromVkImageInfo(const cl_device_id device,
|
|
const VkImageCreateInfo *VulkanImageCreateInfo,
|
|
cl_image_format *img_fmt, cl_image_desc *img_desc,
|
|
const VkSubresourceLayout *layout)
|
|
{
|
|
cl_int error = CL_SUCCESS;
|
|
|
|
cl_image_format clImgFormat = { 0 };
|
|
error =
|
|
getCLFormatFromVkFormat(VulkanImageCreateInfo->format, &clImgFormat);
|
|
if (CL_SUCCESS != error)
|
|
{
|
|
return error;
|
|
}
|
|
memcpy(img_fmt, &clImgFormat, sizeof(cl_image_format));
|
|
|
|
img_desc->image_type = getImageTypeFromVk(VulkanImageCreateInfo->imageType);
|
|
if (CL_INVALID_VALUE == static_cast<cl_int>(img_desc->image_type))
|
|
{
|
|
return CL_INVALID_VALUE;
|
|
}
|
|
|
|
VkExtent3D max_ext = { 0, 0, 0 };
|
|
|
|
size_t width = 0, height = 0, depth = 0;
|
|
if (img_desc->image_type == CL_MEM_OBJECT_IMAGE3D)
|
|
{
|
|
error = clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_WIDTH,
|
|
sizeof(width), &width, NULL);
|
|
test_error(error, "Unable to get CL_DEVICE_IMAGE3D_MAX_WIDTH");
|
|
error = clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_HEIGHT,
|
|
sizeof(height), &height, NULL);
|
|
test_error(error, "Unable to get CL_DEVICE_IMAGE3D_MAX_HEIGHT");
|
|
error = clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_DEPTH,
|
|
sizeof(depth), &depth, NULL);
|
|
test_error(error, "Unable to get CL_DEVICE_IMAGE3D_MAX_DEPTH");
|
|
}
|
|
else
|
|
{
|
|
error = clGetDeviceInfo(device, CL_DEVICE_IMAGE2D_MAX_WIDTH,
|
|
sizeof(width), &width, NULL);
|
|
test_error(error, "Unable to get CL_DEVICE_IMAGE2D_MAX_WIDTH");
|
|
error = clGetDeviceInfo(device, CL_DEVICE_IMAGE2D_MAX_HEIGHT,
|
|
sizeof(height), &height, NULL);
|
|
test_error(error, "Unable to get CL_DEVICE_IMAGE2D_MAX_HEIGHT");
|
|
}
|
|
|
|
max_ext.depth = depth;
|
|
max_ext.height = height;
|
|
max_ext.width = width;
|
|
|
|
// If image_row_pitch is zero and the image is created from an external
|
|
// memory handle, then the image row pitch is implementation-defined
|
|
img_desc->image_row_pitch = 0;
|
|
// If image_slice_pitch is zero and the image is created from an external
|
|
// memory handle, then the image slice pitch is implementation-defined
|
|
img_desc->image_slice_pitch = 0;
|
|
|
|
error = getImageDimensions(VulkanImageCreateInfo, img_fmt, img_desc,
|
|
max_ext, layout);
|
|
if (CL_SUCCESS != error)
|
|
{
|
|
throw std::runtime_error("getImageDimensions failed!!!");
|
|
}
|
|
|
|
img_desc->image_depth =
|
|
static_cast<size_t>(VulkanImageCreateInfo->extent.depth);
|
|
img_desc->image_array_size = 0;
|
|
img_desc->num_mip_levels = 0;
|
|
img_desc->num_samples = 0;
|
|
img_desc->buffer = NULL;
|
|
|
|
return error;
|
|
}
|
|
|
|
cl_int check_external_memory_handle_type(
|
|
cl_device_id deviceID,
|
|
cl_external_memory_handle_type_khr requiredHandleType)
|
|
{
|
|
unsigned int i;
|
|
cl_external_memory_handle_type_khr *handle_type;
|
|
size_t handle_type_size = 0;
|
|
|
|
cl_int errNum = CL_SUCCESS;
|
|
|
|
errNum = clGetDeviceInfo(deviceID,
|
|
CL_DEVICE_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR,
|
|
0, NULL, &handle_type_size);
|
|
test_error(errNum, "clGetDeviceInfo failed");
|
|
|
|
handle_type =
|
|
(cl_external_memory_handle_type_khr *)malloc(handle_type_size);
|
|
|
|
errNum = clGetDeviceInfo(deviceID,
|
|
CL_DEVICE_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR,
|
|
handle_type_size, handle_type, NULL);
|
|
|
|
test_error(
|
|
errNum,
|
|
"Unable to query CL_DEVICE_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR \n");
|
|
|
|
for (i = 0; i < handle_type_size; i++)
|
|
{
|
|
if (requiredHandleType == handle_type[i])
|
|
{
|
|
return CL_SUCCESS;
|
|
}
|
|
}
|
|
log_error("cl_khr_external_memory extension is missing support for %d\n",
|
|
requiredHandleType);
|
|
|
|
return CL_INVALID_VALUE;
|
|
}
|
|
|
|
void check_external_semaphore_handle_type(
|
|
cl_device_id device,
|
|
cl_external_semaphore_handle_type_khr requiredHandleType,
|
|
cl_device_info queryParamName)
|
|
{
|
|
unsigned int i;
|
|
cl_external_semaphore_handle_type_khr *handle_type;
|
|
size_t handle_type_size = 0;
|
|
cl_int errNum = CL_SUCCESS;
|
|
|
|
errNum =
|
|
clGetDeviceInfo(device, queryParamName, 0, NULL, &handle_type_size);
|
|
ASSERT_SUCCESS(errNum, "clGetDeviceInfo");
|
|
|
|
if (handle_type_size == 0)
|
|
{
|
|
log_error("Device does not support %s semaphore\n",
|
|
queryParamName == CL_DEVICE_SEMAPHORE_IMPORT_HANDLE_TYPES_KHR
|
|
? "importing"
|
|
: "exporting");
|
|
|
|
throw std::runtime_error("");
|
|
}
|
|
|
|
handle_type =
|
|
(cl_external_semaphore_handle_type_khr *)malloc(handle_type_size);
|
|
|
|
errNum = clGetDeviceInfo(device, queryParamName, handle_type_size,
|
|
handle_type, NULL);
|
|
ASSERT_SUCCESS(errNum, "clGetDeviceInfo");
|
|
|
|
bool found = false;
|
|
for (i = 0; i < handle_type_size; i++)
|
|
{
|
|
if (requiredHandleType == handle_type[i])
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!found)
|
|
{
|
|
log_error("cl_khr_external_semaphore extension is missing support for "
|
|
"handle type %d\n",
|
|
requiredHandleType);
|
|
|
|
throw std::runtime_error("");
|
|
}
|
|
}
|
|
|
|
clExternalMemory::clExternalMemory() {}
|
|
|
|
clExternalMemory::clExternalMemory(const clExternalMemory &externalMemory)
|
|
: m_externalMemory(externalMemory.m_externalMemory)
|
|
{}
|
|
|
|
clExternalMemory::clExternalMemory(
|
|
const VulkanDeviceMemory *deviceMemory,
|
|
VulkanExternalMemoryHandleType externalMemoryHandleType, uint64_t size,
|
|
cl_context context, cl_device_id deviceId)
|
|
{
|
|
int err = 0;
|
|
m_externalMemory = NULL;
|
|
cl_device_id devList[] = { deviceId, NULL };
|
|
std::vector<cl_mem_properties> extMemProperties;
|
|
#ifdef _WIN32
|
|
if (!is_extension_available(devList[0], "cl_khr_external_memory_win32"))
|
|
{
|
|
throw std::runtime_error(
|
|
"Device does not support cl_khr_external_memory_win32 extension\n");
|
|
}
|
|
#else
|
|
if (!is_extension_available(devList[0], "cl_khr_external_memory_opaque_fd"))
|
|
{
|
|
throw std::runtime_error(
|
|
"Device does not support cl_khr_external_memory_opaque_fd "
|
|
"extension \n");
|
|
}
|
|
#endif
|
|
|
|
switch (externalMemoryHandleType)
|
|
{
|
|
case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD:
|
|
#ifdef _WIN32
|
|
log_info("Opaque file descriptors are not supported on Windows\n");
|
|
ASSERT(0);
|
|
#else
|
|
fd = (int)deviceMemory->getHandle(externalMemoryHandleType);
|
|
err = check_external_memory_handle_type(
|
|
devList[0], CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR);
|
|
extMemProperties.push_back(
|
|
(cl_mem_properties)CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR);
|
|
extMemProperties.push_back((cl_mem_properties)fd);
|
|
#endif
|
|
break;
|
|
case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT:
|
|
#ifndef _WIN32
|
|
log_info("Opaque NT handles are only supported on Windows\n");
|
|
ASSERT(0);
|
|
#else
|
|
handle = deviceMemory->getHandle(externalMemoryHandleType);
|
|
err = check_external_memory_handle_type(
|
|
devList[0], CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR);
|
|
extMemProperties.push_back(
|
|
(cl_mem_properties)CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR);
|
|
extMemProperties.push_back((cl_mem_properties)handle);
|
|
#endif
|
|
break;
|
|
case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT_NAME: {
|
|
#ifndef _WIN32
|
|
log_info("Opaque NT handles are only supported on Windows\n");
|
|
ASSERT(0);
|
|
#else
|
|
const std::wstring &name = deviceMemory->getName();
|
|
if (name.size())
|
|
{
|
|
err = check_external_memory_handle_type(
|
|
devList[0],
|
|
CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_NAME_KHR);
|
|
extMemProperties.push_back(
|
|
(cl_mem_properties)
|
|
CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_NAME_KHR);
|
|
extMemProperties.push_back((cl_mem_properties)name.c_str());
|
|
}
|
|
else
|
|
{
|
|
throw std::runtime_error("Unsupported operation: import via "
|
|
"name but no name provided\n");
|
|
}
|
|
#endif
|
|
}
|
|
break;
|
|
case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT:
|
|
#ifndef _WIN32
|
|
log_info("Opaque D3DKMT handles are only supported on Windows\n");
|
|
ASSERT(0);
|
|
#else
|
|
handle = deviceMemory->getHandle(externalMemoryHandleType);
|
|
err = check_external_memory_handle_type(
|
|
devList[0], CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR);
|
|
extMemProperties.push_back(
|
|
(cl_mem_properties)
|
|
CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR);
|
|
extMemProperties.push_back((cl_mem_properties)handle);
|
|
#endif
|
|
break;
|
|
default:
|
|
log_error("Unsupported external memory handle type\n");
|
|
ASSERT(0);
|
|
break;
|
|
}
|
|
if (CL_SUCCESS != err)
|
|
{
|
|
throw std::runtime_error("Unsupported external memory type\n");
|
|
}
|
|
|
|
extMemProperties.push_back(
|
|
(cl_mem_properties)CL_MEM_DEVICE_HANDLE_LIST_KHR);
|
|
extMemProperties.push_back((cl_mem_properties)devList[0]);
|
|
extMemProperties.push_back(
|
|
(cl_mem_properties)CL_MEM_DEVICE_HANDLE_LIST_END_KHR);
|
|
extMemProperties.push_back(0);
|
|
|
|
m_externalMemory = clCreateBufferWithProperties(
|
|
context, extMemProperties.data(), 1, size, NULL, &err);
|
|
if (CL_SUCCESS != err)
|
|
{
|
|
log_error("clCreateBufferWithProperties failed with %d\n", err);
|
|
throw std::runtime_error("clCreateBufferWithProperties failed\n");
|
|
}
|
|
}
|
|
clExternalMemoryImage::clExternalMemoryImage(
|
|
const VulkanDeviceMemory &deviceMemory,
|
|
VulkanExternalMemoryHandleType externalMemoryHandleType, cl_context context,
|
|
size_t totalImageMemSize, size_t imageWidth, size_t imageHeight,
|
|
size_t totalSize, const VulkanImage2D &image2D, cl_device_id deviceId)
|
|
{
|
|
cl_int errcode_ret = 0;
|
|
std::vector<cl_mem_properties> extMemProperties1;
|
|
cl_device_id devList[] = { deviceId, NULL };
|
|
|
|
auto vulkanImageTiling = vkClExternalMemoryHandleTilingAssumption(
|
|
deviceId, externalMemoryHandleType, &errcode_ret);
|
|
if (CL_SUCCESS != errcode_ret)
|
|
{
|
|
throw std::runtime_error("Failed to query OpenCL tiling mode");
|
|
}
|
|
if (vulkanImageTiling == std::nullopt)
|
|
{
|
|
throw std::runtime_error(
|
|
"Could not find image tiling supported by both Vulkan and OpenCL");
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
if (!is_extension_available(devList[0], "cl_khr_external_memory_win32"))
|
|
{
|
|
throw std::runtime_error("Device does not support "
|
|
"cl_khr_external_memory_win32 extension \n");
|
|
}
|
|
#elif !defined(__APPLE__)
|
|
if (!is_extension_available(devList[0], "cl_khr_external_memory_opaque_fd"))
|
|
{
|
|
throw std::runtime_error(
|
|
"Device does not support cl_khr_external_memory_opaque_fd "
|
|
"extension\n");
|
|
}
|
|
#endif
|
|
|
|
switch (externalMemoryHandleType)
|
|
{
|
|
#ifdef _WIN32
|
|
case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT:
|
|
handle = deviceMemory.getHandle(externalMemoryHandleType);
|
|
errcode_ret = check_external_memory_handle_type(
|
|
devList[0], CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR);
|
|
extMemProperties1.push_back(
|
|
(cl_mem_properties)CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR);
|
|
extMemProperties1.push_back((cl_mem_properties)handle);
|
|
break;
|
|
case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT_NAME: {
|
|
const std::wstring &name = deviceMemory.getName();
|
|
if (name.size())
|
|
{
|
|
errcode_ret = check_external_memory_handle_type(
|
|
devList[0],
|
|
CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_NAME_KHR);
|
|
extMemProperties1.push_back(
|
|
(cl_mem_properties)
|
|
CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_NAME_KHR);
|
|
extMemProperties1.push_back((cl_mem_properties)name.c_str());
|
|
}
|
|
else
|
|
{
|
|
throw std::runtime_error("Unsupported operation: import via "
|
|
"name but no name provided\n");
|
|
}
|
|
}
|
|
break;
|
|
case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT:
|
|
handle = deviceMemory.getHandle(externalMemoryHandleType);
|
|
errcode_ret = check_external_memory_handle_type(
|
|
devList[0], CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR);
|
|
extMemProperties1.push_back(
|
|
(cl_mem_properties)
|
|
CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR);
|
|
extMemProperties1.push_back((cl_mem_properties)handle);
|
|
break;
|
|
#elif !defined(__APPLE__)
|
|
case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD:
|
|
fd = (int)deviceMemory.getHandle(externalMemoryHandleType);
|
|
errcode_ret = check_external_memory_handle_type(
|
|
devList[0], CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR);
|
|
extMemProperties1.push_back(
|
|
(cl_mem_properties)CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR);
|
|
extMemProperties1.push_back((cl_mem_properties)fd);
|
|
break;
|
|
#endif
|
|
default:
|
|
log_error("Unsupported external memory handle type\n");
|
|
ASSERT(0);
|
|
break;
|
|
}
|
|
if (CL_SUCCESS != errcode_ret)
|
|
{
|
|
throw std::runtime_error("Unsupported external memory type\n");
|
|
}
|
|
|
|
// Set cl_image_desc
|
|
size_t clImageFormatSize;
|
|
cl_image_desc image_desc;
|
|
memset(&image_desc, 0x0, sizeof(cl_image_desc));
|
|
cl_image_format img_format = { 0 };
|
|
const VkImageCreateInfo VulkanImageCreateInfo =
|
|
image2D.getVkImageCreateInfo();
|
|
|
|
errcode_ret = getCLImageInfoFromVkImageInfo(
|
|
deviceId, &VulkanImageCreateInfo, &img_format, &image_desc);
|
|
if (CL_SUCCESS != errcode_ret)
|
|
{
|
|
throw std::runtime_error("getCLImageInfoFromVkImageInfo failed\n");
|
|
}
|
|
|
|
// If OpenCL will assume linear, query the Vulkan image's row pitch,
|
|
// otherwise it may not match OpenCL's assumption of the row pitch.
|
|
if (vulkanImageTiling == VULKAN_IMAGE_TILING_LINEAR)
|
|
{
|
|
VkSubresourceLayout subresourceLayout = image2D.getSubresourceLayout();
|
|
image_desc.image_row_pitch = subresourceLayout.rowPitch;
|
|
image_desc.image_slice_pitch = subresourceLayout.depthPitch;
|
|
}
|
|
|
|
extMemProperties1.push_back(
|
|
(cl_mem_properties)CL_MEM_DEVICE_HANDLE_LIST_KHR);
|
|
extMemProperties1.push_back((cl_mem_properties)devList[0]);
|
|
extMemProperties1.push_back(
|
|
(cl_mem_properties)CL_MEM_DEVICE_HANDLE_LIST_END_KHR);
|
|
extMemProperties1.push_back(0);
|
|
m_externalMemory = clCreateImageWithProperties(
|
|
context, extMemProperties1.data(), CL_MEM_READ_WRITE, &img_format,
|
|
&image_desc, NULL, &errcode_ret);
|
|
if (CL_SUCCESS != errcode_ret)
|
|
{
|
|
throw std::runtime_error("clCreateImageWithProperties failed\n");
|
|
}
|
|
}
|
|
|
|
cl_mem clExternalMemory::getExternalMemoryBuffer() { return m_externalMemory; }
|
|
|
|
cl_mem clExternalMemoryImage::getExternalMemoryImage()
|
|
{
|
|
return m_externalMemory;
|
|
}
|
|
|
|
clExternalMemoryImage::~clExternalMemoryImage()
|
|
{
|
|
clReleaseMemObject(m_externalMemory);
|
|
}
|
|
|
|
clExternalMemory::~clExternalMemory() { clReleaseMemObject(m_externalMemory); }
|
|
|
|
clExternalMemoryImage::clExternalMemoryImage() {}
|
|
|
|
|
|
//////////////////////////////////////////
|
|
// clExternalSemaphore implementation //
|
|
//////////////////////////////////////////
|
|
|
|
clExternalSemaphore::~clExternalSemaphore() = default;
|
|
|
|
clExternalImportableSemaphore::clExternalImportableSemaphore(
|
|
const VulkanSemaphore &semaphore, cl_context context,
|
|
VulkanExternalSemaphoreHandleType externalSemaphoreHandleType,
|
|
cl_device_id deviceId)
|
|
: m_deviceSemaphore(semaphore)
|
|
{
|
|
cl_int err = 0;
|
|
cl_device_id devList[] = { deviceId, NULL };
|
|
cl_external_semaphore_handle_type_khr clSemaphoreHandleType =
|
|
getCLSemaphoreTypeFromVulkanType(externalSemaphoreHandleType);
|
|
|
|
check_external_semaphore_handle_type(
|
|
deviceId, clSemaphoreHandleType,
|
|
CL_DEVICE_SEMAPHORE_IMPORT_HANDLE_TYPES_KHR);
|
|
|
|
m_externalHandleType = externalSemaphoreHandleType;
|
|
m_externalSemaphore = nullptr;
|
|
m_device = deviceId;
|
|
m_context = context;
|
|
|
|
std::vector<cl_semaphore_properties_khr> sema_props{
|
|
(cl_semaphore_properties_khr)CL_SEMAPHORE_TYPE_KHR,
|
|
(cl_semaphore_properties_khr)CL_SEMAPHORE_TYPE_BINARY_KHR,
|
|
};
|
|
switch (externalSemaphoreHandleType)
|
|
{
|
|
case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD:
|
|
#ifdef _WIN32
|
|
log_info("Opaque file descriptors are not supported on Windows\n");
|
|
ASSERT(0);
|
|
#else
|
|
fd = (int)semaphore.getHandle(externalSemaphoreHandleType);
|
|
sema_props.push_back(
|
|
(cl_semaphore_properties_khr)CL_SEMAPHORE_HANDLE_OPAQUE_FD_KHR);
|
|
sema_props.push_back((cl_semaphore_properties_khr)fd);
|
|
#endif
|
|
break;
|
|
case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_NT:
|
|
#ifndef _WIN32
|
|
log_info("Opaque NT handles are only supported on Windows\n");
|
|
ASSERT(0);
|
|
#else
|
|
handle = semaphore.getHandle(externalSemaphoreHandleType);
|
|
sema_props.push_back((cl_semaphore_properties_khr)
|
|
CL_SEMAPHORE_HANDLE_OPAQUE_WIN32_KHR);
|
|
sema_props.push_back((cl_semaphore_properties_khr)handle);
|
|
#endif
|
|
break;
|
|
case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_NT_NAME: {
|
|
#ifndef _WIN32
|
|
log_info("Opaque NT handles are only supported on Windows\n");
|
|
ASSERT(0);
|
|
#else
|
|
const std::wstring &name = semaphore.getName();
|
|
if (name.size())
|
|
{
|
|
sema_props.push_back(
|
|
(cl_semaphore_properties_khr)
|
|
CL_SEMAPHORE_HANDLE_OPAQUE_WIN32_NAME_KHR);
|
|
sema_props.push_back((cl_semaphore_properties_khr)name.c_str());
|
|
}
|
|
else
|
|
{
|
|
throw std::runtime_error("Unsupported operation: import via "
|
|
"name but no name provided\n");
|
|
}
|
|
#endif
|
|
}
|
|
break;
|
|
case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT:
|
|
#ifndef _WIN32
|
|
log_info("Opaque D3DKMT handles are only supported on Windows\n");
|
|
ASSERT(0);
|
|
#else
|
|
handle = semaphore.getHandle(externalSemaphoreHandleType);
|
|
sema_props.push_back((cl_semaphore_properties_khr)
|
|
CL_SEMAPHORE_HANDLE_OPAQUE_WIN32_KMT_KHR);
|
|
sema_props.push_back((cl_semaphore_properties_khr)handle);
|
|
#endif
|
|
break;
|
|
case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD:
|
|
sema_props.push_back(static_cast<cl_semaphore_properties_khr>(
|
|
CL_SEMAPHORE_HANDLE_SYNC_FD_KHR));
|
|
sema_props.push_back(static_cast<cl_semaphore_properties_khr>(-1));
|
|
break;
|
|
|
|
default:
|
|
log_error("Unsupported external memory handle type\n");
|
|
ASSERT(0);
|
|
break;
|
|
}
|
|
if (CL_SUCCESS != err)
|
|
{
|
|
throw std::runtime_error(
|
|
"Unsupported external sempahore handle type\n ");
|
|
}
|
|
|
|
sema_props.push_back(
|
|
(cl_semaphore_properties_khr)CL_SEMAPHORE_DEVICE_HANDLE_LIST_KHR);
|
|
sema_props.push_back((cl_semaphore_properties_khr)devList[0]);
|
|
sema_props.push_back(
|
|
(cl_semaphore_properties_khr)CL_SEMAPHORE_DEVICE_HANDLE_LIST_END_KHR);
|
|
sema_props.push_back(0);
|
|
m_externalSemaphore =
|
|
clCreateSemaphoreWithPropertiesKHRptr(context, sema_props.data(), &err);
|
|
if (CL_SUCCESS != err)
|
|
{
|
|
log_error("clCreateSemaphoreWithPropertiesKHRptr failed with %d\n",
|
|
err);
|
|
throw std::runtime_error(
|
|
"clCreateSemaphoreWithPropertiesKHRptr failed! ");
|
|
}
|
|
}
|
|
|
|
clExternalImportableSemaphore::~clExternalImportableSemaphore()
|
|
{
|
|
cl_int err = clReleaseSemaphoreKHRptr(m_externalSemaphore);
|
|
if (err != CL_SUCCESS)
|
|
{
|
|
log_error("clReleaseSemaphoreKHR failed with %d\n", err);
|
|
}
|
|
}
|
|
|
|
int clExternalImportableSemaphore::wait(cl_command_queue cmd_queue)
|
|
{
|
|
int err = CL_SUCCESS;
|
|
if (m_externalHandleType == VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD)
|
|
{
|
|
cl_int err = 0;
|
|
fd = (int)m_deviceSemaphore.getHandle(m_externalHandleType);
|
|
err = clReImportSemaphoreSyncFdKHRptr(m_externalSemaphore, nullptr, fd);
|
|
if (err != CL_SUCCESS)
|
|
{
|
|
return err;
|
|
}
|
|
}
|
|
|
|
err = clEnqueueWaitSemaphoresKHRptr(cmd_queue, 1, &m_externalSemaphore,
|
|
NULL, 0, NULL, NULL);
|
|
return err;
|
|
}
|
|
|
|
int clExternalImportableSemaphore::signal(cl_command_queue cmd_queue)
|
|
{
|
|
return clEnqueueSignalSemaphoresKHRptr(cmd_queue, 1, &m_externalSemaphore,
|
|
NULL, 0, NULL, NULL);
|
|
}
|
|
|
|
cl_semaphore_khr &clExternalImportableSemaphore::getCLSemaphore()
|
|
{
|
|
return m_externalSemaphore;
|
|
}
|
|
|
|
|
|
clExternalExportableSemaphore::clExternalExportableSemaphore(
|
|
const VulkanSemaphore &semaphore, cl_context context,
|
|
VulkanExternalSemaphoreHandleType externalSemaphoreHandleType,
|
|
cl_device_id deviceId)
|
|
: m_deviceSemaphore(semaphore)
|
|
{
|
|
cl_int err = 0;
|
|
cl_device_id devList[] = { deviceId, NULL };
|
|
cl_external_semaphore_handle_type_khr clSemaphoreHandleType =
|
|
getCLSemaphoreTypeFromVulkanType(externalSemaphoreHandleType);
|
|
|
|
check_external_semaphore_handle_type(
|
|
deviceId, clSemaphoreHandleType,
|
|
CL_DEVICE_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR);
|
|
|
|
m_externalHandleType = externalSemaphoreHandleType;
|
|
m_externalSemaphore = nullptr;
|
|
m_device = deviceId;
|
|
m_context = context;
|
|
|
|
std::vector<cl_semaphore_properties_khr> sema_props{
|
|
(cl_semaphore_properties_khr)CL_SEMAPHORE_TYPE_KHR,
|
|
(cl_semaphore_properties_khr)CL_SEMAPHORE_TYPE_BINARY_KHR,
|
|
};
|
|
sema_props.push_back(
|
|
(cl_semaphore_properties_khr)CL_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR);
|
|
sema_props.push_back((cl_semaphore_properties_khr)clSemaphoreHandleType);
|
|
sema_props.push_back((cl_semaphore_properties_khr)
|
|
CL_SEMAPHORE_EXPORT_HANDLE_TYPES_LIST_END_KHR);
|
|
sema_props.push_back(
|
|
(cl_semaphore_properties_khr)CL_SEMAPHORE_DEVICE_HANDLE_LIST_KHR);
|
|
sema_props.push_back((cl_semaphore_properties_khr)devList[0]);
|
|
sema_props.push_back(
|
|
(cl_semaphore_properties_khr)CL_SEMAPHORE_DEVICE_HANDLE_LIST_END_KHR);
|
|
sema_props.push_back(0);
|
|
m_externalSemaphore =
|
|
clCreateSemaphoreWithPropertiesKHRptr(context, sema_props.data(), &err);
|
|
if (CL_SUCCESS != err)
|
|
{
|
|
log_error("clCreateSemaphoreWithPropertiesKHRptr failed with %d\n",
|
|
err);
|
|
throw std::runtime_error(
|
|
"clCreateSemaphoreWithPropertiesKHRptr failed! ");
|
|
}
|
|
|
|
switch (m_externalHandleType)
|
|
{
|
|
case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD: {
|
|
err = clGetSemaphoreHandleForTypeKHRptr(
|
|
m_externalSemaphore, m_device, clSemaphoreHandleType,
|
|
sizeof(int), &fd, nullptr);
|
|
if (err != CL_SUCCESS)
|
|
{
|
|
throw std::runtime_error("Failed to export OpenCL semaphore\n");
|
|
}
|
|
|
|
VkImportSemaphoreFdInfoKHR vkImportSemaphoreFdInfoKHR = {};
|
|
vkImportSemaphoreFdInfoKHR.sType =
|
|
VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR;
|
|
vkImportSemaphoreFdInfoKHR.semaphore = m_deviceSemaphore;
|
|
vkImportSemaphoreFdInfoKHR.fd = fd;
|
|
vkImportSemaphoreFdInfoKHR.pNext = nullptr;
|
|
vkImportSemaphoreFdInfoKHR.handleType =
|
|
VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
|
|
vkImportSemaphoreFdInfoKHR.flags = 0;
|
|
|
|
if (vkImportSemaphoreFdKHR(m_deviceSemaphore.getDevice(),
|
|
&vkImportSemaphoreFdInfoKHR)
|
|
!= VK_SUCCESS)
|
|
{
|
|
throw std::runtime_error(
|
|
"Failed to import semaphore in Vulkan\n");
|
|
}
|
|
break;
|
|
}
|
|
case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT:
|
|
case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_NT: {
|
|
err = clGetSemaphoreHandleForTypeKHRptr(
|
|
m_externalSemaphore, m_device, clSemaphoreHandleType,
|
|
sizeof(void *), (void *)&handle, nullptr);
|
|
if (err != CL_SUCCESS)
|
|
{
|
|
throw std::runtime_error("Failed to export OpenCL semaphore\n");
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
VkImportSemaphoreWin32HandleInfoKHR
|
|
vkImportSemaphoreWin32HandleInfoKHR = {};
|
|
vkImportSemaphoreWin32HandleInfoKHR.sType =
|
|
VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR;
|
|
vkImportSemaphoreWin32HandleInfoKHR.pNext = nullptr;
|
|
vkImportSemaphoreWin32HandleInfoKHR.semaphore = m_deviceSemaphore;
|
|
vkImportSemaphoreWin32HandleInfoKHR.flags = 0;
|
|
vkImportSemaphoreWin32HandleInfoKHR.handleType =
|
|
(VkExternalSemaphoreHandleTypeFlagBits)m_externalHandleType;
|
|
vkImportSemaphoreWin32HandleInfoKHR.handle = (HANDLE)handle;
|
|
vkImportSemaphoreWin32HandleInfoKHR.name = nullptr;
|
|
|
|
if (vkImportSemaphoreWin32HandleKHR(
|
|
m_deviceSemaphore.getDevice(),
|
|
&vkImportSemaphoreWin32HandleInfoKHR)
|
|
!= VK_SUCCESS)
|
|
{
|
|
throw std::runtime_error(
|
|
"Failed to import semaphore in Vulkan\n");
|
|
}
|
|
#else
|
|
log_error(
|
|
"Opaque D3DKMT and NT handles are only supported on Windows\n");
|
|
ASSERT(0);
|
|
#endif
|
|
break;
|
|
}
|
|
case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD:
|
|
// Do nothing, imported after each signal from OpenCL
|
|
break;
|
|
default:
|
|
log_error("Unsupported external semaphore handle type\n");
|
|
ASSERT(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
clExternalExportableSemaphore::~clExternalExportableSemaphore()
|
|
{
|
|
cl_int err = clReleaseSemaphoreKHRptr(m_externalSemaphore);
|
|
if (err != CL_SUCCESS)
|
|
{
|
|
log_error("clReleaseSemaphoreKHR failed with %d\n", err);
|
|
}
|
|
}
|
|
|
|
int clExternalExportableSemaphore::signal(cl_command_queue cmd_queue)
|
|
{
|
|
int err = clEnqueueSignalSemaphoresKHRptr(
|
|
cmd_queue, 1, &m_externalSemaphore, NULL, 0, NULL, nullptr);
|
|
if (err != CL_SUCCESS)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
if (m_externalHandleType == VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD)
|
|
{
|
|
err = clGetSemaphoreHandleForTypeKHRptr(m_externalSemaphore, m_device,
|
|
CL_SEMAPHORE_HANDLE_SYNC_FD_KHR,
|
|
sizeof(int), &fd, nullptr);
|
|
if (err != CL_SUCCESS)
|
|
{
|
|
log_error("Failed to export fd from semaphore\n");
|
|
return err;
|
|
}
|
|
|
|
VkImportSemaphoreFdInfoKHR import = {};
|
|
import.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR;
|
|
import.semaphore = m_deviceSemaphore;
|
|
import.fd = fd;
|
|
import.pNext = nullptr;
|
|
import.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR;
|
|
import.flags = 0;
|
|
|
|
VkResult res =
|
|
vkImportSemaphoreFdKHR(m_deviceSemaphore.getDevice(), &import);
|
|
ASSERT(res == VK_SUCCESS);
|
|
if (res != VK_SUCCESS)
|
|
{
|
|
err = CL_INVALID_OPERATION;
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
int clExternalExportableSemaphore::wait(cl_command_queue command_queue)
|
|
{
|
|
return clEnqueueWaitSemaphoresKHRptr(command_queue, 1, &m_externalSemaphore,
|
|
NULL, 0, NULL, nullptr);
|
|
}
|
|
|
|
cl_semaphore_khr &clExternalExportableSemaphore::getCLSemaphore()
|
|
{
|
|
return m_externalSemaphore;
|
|
}
|
|
|
|
cl_external_memory_handle_type_khr vkToOpenCLExternalMemoryHandleType(
|
|
VulkanExternalMemoryHandleType vkExternalMemoryHandleType)
|
|
{
|
|
switch (vkExternalMemoryHandleType)
|
|
{
|
|
default:
|
|
case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_NONE:
|
|
log_error("Unexpected external memory handle type\n");
|
|
return 0;
|
|
case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD:
|
|
return CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR;
|
|
case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT:
|
|
return CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR;
|
|
case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT:
|
|
case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT_KMT:
|
|
return CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR;
|
|
case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT_NAME:
|
|
return CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_NAME_KHR;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
std::optional<VulkanImageTiling> vkClExternalMemoryHandleTilingAssumption(
|
|
cl_device_id deviceId,
|
|
VulkanExternalMemoryHandleType vkExternalMemoryHandleType, int *error_ret)
|
|
{
|
|
size_t size = 0;
|
|
|
|
assert(error_ret
|
|
!= nullptr); // errcode_ret is not optional, it must be checked
|
|
|
|
*error_ret = clGetDeviceInfo(
|
|
deviceId,
|
|
CL_DEVICE_EXTERNAL_MEMORY_IMPORT_ASSUME_LINEAR_IMAGES_HANDLE_TYPES_KHR,
|
|
0, nullptr, &size);
|
|
if (*error_ret != CL_SUCCESS)
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
|
|
if (size == 0)
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
|
|
std::vector<cl_external_memory_handle_type_khr> assume_linear_types(
|
|
size / sizeof(cl_external_memory_handle_type_khr));
|
|
|
|
*error_ret = clGetDeviceInfo(
|
|
deviceId,
|
|
CL_DEVICE_EXTERNAL_MEMORY_IMPORT_ASSUME_LINEAR_IMAGES_HANDLE_TYPES_KHR,
|
|
size, assume_linear_types.data(), nullptr);
|
|
if (*error_ret != CL_SUCCESS)
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
|
|
if (std::find(
|
|
assume_linear_types.begin(), assume_linear_types.end(),
|
|
vkToOpenCLExternalMemoryHandleType(vkExternalMemoryHandleType))
|
|
!= assume_linear_types.end())
|
|
{
|
|
return VULKAN_IMAGE_TILING_LINEAR;
|
|
}
|
|
|
|
return std::nullopt;
|
|
}
|