diff --git a/opencl/extensions/public/cl_ext_private.h b/opencl/extensions/public/cl_ext_private.h index 6308b7316f..e2daff7593 100644 --- a/opencl/extensions/public/cl_ext_private.h +++ b/opencl/extensions/public/cl_ext_private.h @@ -266,3 +266,26 @@ typedef cl_bitfield cl_command_queue_mdapi_properties_intel; /* cl_command_queue_mdapi_properties_intel - bitfield */ #define CL_QUEUE_MDAPI_ENABLE_INTEL (1 << 0) + +/************************************************ + * cl_khr_external_memory extension * + *************************************************/ + +/* clGetPlatformInfo */ +#define CL_PLATFORM_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR 0x2044 + +/* clGetDeviceInfo */ +#define CL_DEVICE_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR 0x204F + +/* clCreateBufferWithProperties and clCreateImageWithProperties */ +#define CL_DEVICE_HANDLE_LIST_KHR 0x2051 +#define CL_DEVICE_HANDLE_LIST_END_KHR 0 + +#define CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR 0x2060 +#define CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR 0x2061 +#define CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR 0x2062 +#define CL_EXTERNAL_MEMORY_HANDLE_D3D11_TEXTURE_KHR 0x2063 +#define CL_EXTERNAL_MEMORY_HANDLE_D3D11_TEXTURE_KMT_KHR 0x2064 +#define CL_EXTERNAL_MEMORY_HANDLE_D3D12_HEAP_KHR 0x2065 +#define CL_EXTERNAL_MEMORY_HANDLE_D3D12_RESOURCE_KHR 0x2066 +#define CL_EXTERNAL_MEMORY_HANDLE_DMA_BUF_KHR 0x2067 diff --git a/opencl/source/helpers/cl_memory_properties_helpers.cpp b/opencl/source/helpers/cl_memory_properties_helpers.cpp index 98c20860a5..dc3b730e94 100644 --- a/opencl/source/helpers/cl_memory_properties_helpers.cpp +++ b/opencl/source/helpers/cl_memory_properties_helpers.cpp @@ -9,6 +9,7 @@ #include "opencl/source/context/context.h" #include "opencl/source/helpers/cl_memory_properties_helpers_base.inl" #include "opencl/source/mem_obj/mem_obj_helper.h" +#include "opencl/source/sharings/unified/unified_buffer.h" namespace NEO { @@ -16,6 +17,8 @@ bool ClMemoryPropertiesHelper::parseMemoryProperties(const cl_mem_properties_int cl_mem_flags &flags, cl_mem_flags_intel &flagsIntel, cl_mem_alloc_flags_intel &allocflags, MemoryPropertiesHelper::ObjType objectType, Context &context) { Device *pDevice = &context.getDevice(0)->getDevice(); + uint64_t handle = 0; + uint64_t handleType = 0; uintptr_t hostptr = 0; if (properties != nullptr) { for (int i = 0; properties[i] != 0; i += 2) { @@ -32,6 +35,10 @@ bool ClMemoryPropertiesHelper::parseMemoryProperties(const cl_mem_properties_int case CL_MEM_ALLOC_USE_HOST_PTR_INTEL: hostptr = static_cast(properties[i + 1]); break; + case CL_EXTERNAL_MEMORY_HANDLE_DMA_BUF_KHR: + handle = static_cast(properties[i + 1]); + handleType = static_cast(UnifiedSharingHandleType::LinuxFd); + break; default: return false; } @@ -39,6 +46,8 @@ bool ClMemoryPropertiesHelper::parseMemoryProperties(const cl_mem_properties_int } memoryProperties = ClMemoryPropertiesHelper::createMemoryProperties(flags, flagsIntel, allocflags, pDevice); + memoryProperties.handleType = handleType; + memoryProperties.handle = handle; memoryProperties.hostptr = hostptr; switch (objectType) { diff --git a/opencl/source/mem_obj/CMakeLists.txt b/opencl/source/mem_obj/CMakeLists.txt index bfc0100930..83c3c43a62 100644 --- a/opencl/source/mem_obj/CMakeLists.txt +++ b/opencl/source/mem_obj/CMakeLists.txt @@ -27,6 +27,16 @@ set(RUNTIME_SRCS_MEM_OBJ ${CMAKE_CURRENT_SOURCE_DIR}/definitions${BRANCH_DIR_SUFFIX}image_ext.inl ) +if(WIN32) + list(APPEND RUNTIME_SRCS_MEM_OBJ + ${CMAKE_CURRENT_SOURCE_DIR}/buffer_windows.cpp + ) +else() + list(APPEND RUNTIME_SRCS_MEM_OBJ + ${CMAKE_CURRENT_SOURCE_DIR}/buffer_linux.cpp + ) +endif() + target_sources(${NEO_STATIC_LIB_NAME} PRIVATE ${RUNTIME_SRCS_MEM_OBJ}) set_property(GLOBAL PROPERTY RUNTIME_SRCS_MEM_OBJ ${RUNTIME_SRCS_MEM_OBJ}) add_subdirectories() diff --git a/opencl/source/mem_obj/buffer.cpp b/opencl/source/mem_obj/buffer.cpp index 254e643654..a2c5dc0919 100644 --- a/opencl/source/mem_obj/buffer.cpp +++ b/opencl/source/mem_obj/buffer.cpp @@ -141,13 +141,28 @@ cl_mem Buffer::validateInputAndCreateBuffer(cl_context context, } // create the buffer - auto buffer = create(pContext, memoryProperties, flags, flagsIntel, size, hostPtr, retVal); - if (retVal == CL_SUCCESS) { - buffer->storeProperties(properties); + Buffer *pBuffer = nullptr; + UnifiedSharingMemoryDescription extMem{}; + + if (memoryProperties.handle) { + if (validateHandleType(memoryProperties, extMem)) { + extMem.handle = &memoryProperties.handle; + extMem.size = size; + pBuffer = UnifiedBuffer::createSharedUnifiedBuffer(pContext, flags, extMem, &retVal); + } else { + retVal = CL_INVALID_PROPERTY; + return nullptr; + } + } else { + pBuffer = create(pContext, memoryProperties, flags, flagsIntel, size, hostPtr, retVal); } - return buffer; + if (retVal == CL_SUCCESS) { + pBuffer->storeProperties(properties); + } + + return pBuffer; } Buffer *Buffer::create(Context *context, diff --git a/opencl/source/mem_obj/buffer.h b/opencl/source/mem_obj/buffer.h index 8474df50b5..a5b96fb777 100644 --- a/opencl/source/mem_obj/buffer.h +++ b/opencl/source/mem_obj/buffer.h @@ -12,6 +12,7 @@ #include "opencl/extensions/public/cl_ext_private.h" #include "opencl/source/context/context_type.h" #include "opencl/source/mem_obj/mem_obj.h" +#include "opencl/source/sharings/unified/unified_buffer.h" #include "igfxfmid.h" #include "memory_properties_flags.h" @@ -162,6 +163,8 @@ class Buffer : public MemObj { bool isCompressed(uint32_t rootDeviceIndex) const; + static bool validateHandleType(MemoryProperties &memoryProperties, UnifiedSharingMemoryDescription &extMem); + protected: Buffer(Context *context, MemoryProperties memoryProperties, diff --git a/opencl/source/mem_obj/buffer_linux.cpp b/opencl/source/mem_obj/buffer_linux.cpp new file mode 100644 index 0000000000..18442c1e6b --- /dev/null +++ b/opencl/source/mem_obj/buffer_linux.cpp @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "opencl/source/mem_obj/buffer.h" + +namespace NEO { +bool Buffer::validateHandleType(MemoryProperties &memoryProperties, UnifiedSharingMemoryDescription &extMem) { + if (memoryProperties.handleType == static_cast(UnifiedSharingHandleType::LinuxFd)) { + extMem.type = UnifiedSharingHandleType::LinuxFd; + return true; + } + return false; +} +} // namespace NEO diff --git a/opencl/source/mem_obj/buffer_windows.cpp b/opencl/source/mem_obj/buffer_windows.cpp new file mode 100644 index 0000000000..3bbfceed66 --- /dev/null +++ b/opencl/source/mem_obj/buffer_windows.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "opencl/source/mem_obj/buffer.h" + +namespace NEO { +bool Buffer::validateHandleType(MemoryProperties &memoryProperties, UnifiedSharingMemoryDescription &extMem) { + return false; +} +} // namespace NEO diff --git a/opencl/test/unit_test/helpers/memory_properties_helpers_tests.cpp b/opencl/test/unit_test/helpers/memory_properties_helpers_tests.cpp index 112569efa4..126584a0dd 100644 --- a/opencl/test/unit_test/helpers/memory_properties_helpers_tests.cpp +++ b/opencl/test/unit_test/helpers/memory_properties_helpers_tests.cpp @@ -409,6 +409,18 @@ TEST_F(MemoryPropertiesHelperTests, givenMemFlagsWithFlagsAndPropertiesWhenParsi } } +TEST_F(MemoryPropertiesHelperTests, givenDmaBufWhenParsePropertiesThenHandleIsSet) { + cl_mem_properties_intel properties[] = { + CL_EXTERNAL_MEMORY_HANDLE_DMA_BUF_KHR, + 0x1234u, + 0}; + + EXPECT_TRUE(ClMemoryPropertiesHelper::parseMemoryProperties(properties, memoryProperties, flags, flagsIntel, allocflags, + MemoryPropertiesHelper::ObjType::BUFFER, context)); + + EXPECT_EQ(memoryProperties.handle, 0x1234u); +} + TEST_F(MemoryPropertiesHelperTests, WhenAdjustingDeviceBitfieldThenCorrectBitfieldIsReturned) { UltClDeviceFactory deviceFactory{2, 4}; auto memoryPropertiesRootDevice0 = ClMemoryPropertiesHelper::createMemoryProperties(0, 0, 0, &deviceFactory.rootDevices[0]->getDevice()); diff --git a/opencl/test/unit_test/mem_obj/buffer_tests.cpp b/opencl/test/unit_test/mem_obj/buffer_tests.cpp index 5efe916b37..bd74189556 100644 --- a/opencl/test/unit_test/mem_obj/buffer_tests.cpp +++ b/opencl/test/unit_test/mem_obj/buffer_tests.cpp @@ -608,6 +608,7 @@ TEST(Buffer, givenClMemCopyHostPointerPassedToBufferCreateWhenAllocationIsNotInS EXPECT_LT(taskCount, taskCountSent); } } + struct CompressedBuffersTests : public ::testing::Test { void SetUp() override { ExecutionEnvironment *executionEnvironment = MockDevice::prepareExecutionEnvironment(defaultHwInfo.get(), 0u); @@ -1195,6 +1196,14 @@ TEST_P(ValidHostPtr, GivenSvmHostPtrWhenCreatingBufferThenBufferIsCreatedCorrect } } +TEST_P(ValidHostPtr, WhenValidateInputAndCreateBufferThenCorrectBufferIsSet) { + auto buffer = BufferFunctions::validateInputAndCreateBuffer(context.get(), nullptr, flags, 0, g_scTestBufferSizeInBytes, pHostPtr, retVal); + EXPECT_EQ(retVal, CL_SUCCESS); + EXPECT_NE(nullptr, buffer); + + clReleaseMemObject(buffer); +} + // Parameterized test that tests buffer creation with all flags that should be // valid with a valid host ptr cl_mem_flags ValidHostPtrFlags[] = { diff --git a/opencl/test/unit_test/mem_obj/linux/CMakeLists.txt b/opencl/test/unit_test/mem_obj/linux/CMakeLists.txt new file mode 100644 index 0000000000..392d7d75eb --- /dev/null +++ b/opencl/test/unit_test/mem_obj/linux/CMakeLists.txt @@ -0,0 +1,15 @@ +# +# Copyright (C) 2022 Intel Corporation +# +# SPDX-License-Identifier: MIT +# + +if(UNIX) + set(IGDRCL_SRCS_tests_mem_obj_linux + ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt + ${CMAKE_CURRENT_SOURCE_DIR}/buffer_linux_tests.cpp + ) + + target_sources(igdrcl_tests PRIVATE ${IGDRCL_SRCS_tests_mem_obj_linux}) + set_property(GLOBAL PROPERTY IGDRCL_SRCS_tests_mem_obj_linux ${IGDRCL_SRCS_tests_mem_obj_linux}) +endif() diff --git a/opencl/test/unit_test/mem_obj/linux/buffer_linux_tests.cpp b/opencl/test/unit_test/mem_obj/linux/buffer_linux_tests.cpp new file mode 100644 index 0000000000..5f87ccab53 --- /dev/null +++ b/opencl/test/unit_test/mem_obj/linux/buffer_linux_tests.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2018-2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/source/gmm_helper/gmm_helper.h" +#include "shared/source/helpers/array_count.h" +#include "shared/source/helpers/compiler_hw_info_config.h" +#include "shared/source/helpers/hw_helper.h" +#include "shared/source/memory_manager/memory_operations_handler.h" +#include "shared/source/memory_manager/unified_memory_manager.h" +#include "shared/test/common/fixtures/memory_management_fixture.h" +#include "shared/test/common/helpers/ult_hw_config.h" +#include "shared/test/common/helpers/unit_test_helper.h" +#include "shared/test/common/mocks/mock_allocation_properties.h" +#include "shared/test/common/mocks/mock_device.h" +#include "shared/test/common/mocks/mock_execution_environment.h" +#include "shared/test/common/mocks/mock_gmm.h" +#include "shared/test/common/mocks/ult_device_factory.h" +#include "shared/test/common/test_macros/test.h" + +#include "opencl/extensions/public/cl_ext_private.h" +#include "opencl/source/command_queue/command_queue_hw.h" +#include "opencl/source/mem_obj/mem_obj_helper.h" +#include "opencl/test/unit_test/fixtures/cl_device_fixture.h" +#include "opencl/test/unit_test/fixtures/multi_root_device_fixture.h" +#include "opencl/test/unit_test/mocks/mock_buffer.h" +#include "opencl/test/unit_test/mocks/mock_command_queue.h" + +using namespace NEO; + +static const unsigned int g_scTestBufferSizeInBytes = 16; + +TEST(Buffer, GivenInvalidHandleTypeWhenValidateHandleTypeThenReturnFalse) { + MemoryProperties memoryProperties; + memoryProperties.handleType = 0; + UnifiedSharingMemoryDescription extMem; + bool isValid = Buffer::validateHandleType(memoryProperties, extMem); + EXPECT_FALSE(isValid); +} + +TEST(Buffer, GivenLinuxFdHandleTypeWhenValidateHandleTypeThenReturnTrue) { + MemoryProperties memoryProperties; + memoryProperties.handleType = static_cast(UnifiedSharingHandleType::LinuxFd); + UnifiedSharingMemoryDescription extMem; + bool isValid = Buffer::validateHandleType(memoryProperties, extMem); + EXPECT_TRUE(isValid); +} + +class ExportBufferTests : public ClDeviceFixture, + public testing::Test { + public: + ExportBufferTests() { + } + + protected: + void SetUp() override { + flags = CL_MEM_READ_WRITE; + ClDeviceFixture::SetUp(); + context.reset(new MockContext(pClDevice)); + } + + void TearDown() override { + context.reset(); + ClDeviceFixture::TearDown(); + } + + cl_int retVal = CL_SUCCESS; + std::unique_ptr context; + MemoryManager *contextMemoryManager; + cl_mem_flags flags = CL_MEM_READ_WRITE; + unsigned char pHostPtr[g_scTestBufferSizeInBytes]; +}; + +struct ValidExportHostPtr + : public ExportBufferTests, + public MemoryManagementFixture { + typedef ExportBufferTests BaseClass; + + using ExportBufferTests::SetUp; + using MemoryManagementFixture::SetUp; + + ValidExportHostPtr() { + } + + void SetUp() override { + MemoryManagementFixture::SetUp(); + BaseClass::SetUp(); + + ASSERT_NE(nullptr, pDevice); + } + + void TearDown() override { + delete buffer; + BaseClass::TearDown(); + MemoryManagementFixture::TearDown(); + } + + Buffer *createBuffer() { + return Buffer::create( + context.get(), + flags, + g_scTestBufferSizeInBytes, + pHostPtr, + retVal); + } + + cl_int retVal = CL_INVALID_VALUE; + Buffer *buffer = nullptr; +}; + +TEST_F(ValidExportHostPtr, givenPropertiesWithDmaBufWhenValidateInputAndCreateBufferThenCorrectBufferIsSet) { + cl_mem_properties properties[] = {CL_EXTERNAL_MEMORY_HANDLE_DMA_BUF_KHR, 0x1234, 0}; + auto buffer = BufferFunctions::validateInputAndCreateBuffer(context.get(), properties, flags, 0, g_scTestBufferSizeInBytes, nullptr, retVal); + EXPECT_EQ(retVal, CL_SUCCESS); + EXPECT_NE(nullptr, buffer); + + clReleaseMemObject(buffer); +} diff --git a/opencl/test/unit_test/mem_obj/windows/CMakeLists.txt b/opencl/test/unit_test/mem_obj/windows/CMakeLists.txt new file mode 100644 index 0000000000..3bb5f0bc80 --- /dev/null +++ b/opencl/test/unit_test/mem_obj/windows/CMakeLists.txt @@ -0,0 +1,15 @@ +# +# Copyright (C) 2022 Intel Corporation +# +# SPDX-License-Identifier: MIT +# + +if(WIN32) + set(IGDRCL_SRCS_tests_mem_obj_windows + ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt + ${CMAKE_CURRENT_SOURCE_DIR}/buffer_windows_tests.cpp + ) + + target_sources(igdrcl_tests PRIVATE ${IGDRCL_SRCS_tests_mem_obj_windows}) + set_property(GLOBAL PROPERTY IGDRCL_SRCS_tests_mem_obj_windows ${IGDRCL_SRCS_tests_mem_obj_windows}) +endif() diff --git a/opencl/test/unit_test/mem_obj/windows/buffer_windows_tests.cpp b/opencl/test/unit_test/mem_obj/windows/buffer_windows_tests.cpp new file mode 100644 index 0000000000..663ada095e --- /dev/null +++ b/opencl/test/unit_test/mem_obj/windows/buffer_windows_tests.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/source/gmm_helper/gmm_helper.h" +#include "shared/source/helpers/array_count.h" +#include "shared/source/helpers/compiler_hw_info_config.h" +#include "shared/source/helpers/hw_helper.h" +#include "shared/source/memory_manager/memory_operations_handler.h" +#include "shared/source/memory_manager/unified_memory_manager.h" +#include "shared/test/common/fixtures/memory_management_fixture.h" +#include "shared/test/common/helpers/ult_hw_config.h" +#include "shared/test/common/helpers/unit_test_helper.h" +#include "shared/test/common/mocks/mock_allocation_properties.h" +#include "shared/test/common/mocks/mock_device.h" +#include "shared/test/common/mocks/mock_execution_environment.h" +#include "shared/test/common/mocks/mock_gmm.h" +#include "shared/test/common/mocks/ult_device_factory.h" +#include "shared/test/common/test_macros/test.h" + +#include "opencl/extensions/public/cl_ext_private.h" +#include "opencl/source/command_queue/command_queue_hw.h" +#include "opencl/source/mem_obj/mem_obj_helper.h" +#include "opencl/test/unit_test/fixtures/cl_device_fixture.h" +#include "opencl/test/unit_test/fixtures/multi_root_device_fixture.h" +#include "opencl/test/unit_test/mocks/mock_buffer.h" +#include "opencl/test/unit_test/mocks/mock_command_queue.h" + +using namespace NEO; + +static const unsigned int g_scTestBufferSizeInBytes = 16; + +TEST(Buffer, WhenValidateHandleTypeThenReturnFalse) { + MemoryProperties memoryProperties; + UnifiedSharingMemoryDescription extMem; + bool isValid = Buffer::validateHandleType(memoryProperties, extMem); + EXPECT_FALSE(isValid); +} + +class ExportBufferTests : public ClDeviceFixture, + public testing::Test { + public: + ExportBufferTests() { + } + + protected: + void SetUp() override { + flags = CL_MEM_READ_WRITE; + ClDeviceFixture::SetUp(); + context.reset(new MockContext(pClDevice)); + } + + void TearDown() override { + context.reset(); + ClDeviceFixture::TearDown(); + } + + cl_int retVal = CL_SUCCESS; + std::unique_ptr context; + MemoryManager *contextMemoryManager; + cl_mem_flags flags = CL_MEM_READ_WRITE; + unsigned char pHostPtr[g_scTestBufferSizeInBytes]; +}; + +struct ValidExportHostPtr + : public ExportBufferTests, + public MemoryManagementFixture { + typedef ExportBufferTests BaseClass; + + using ExportBufferTests::SetUp; + using MemoryManagementFixture::SetUp; + + ValidExportHostPtr() { + } + + void SetUp() override { + MemoryManagementFixture::SetUp(); + BaseClass::SetUp(); + + ASSERT_NE(nullptr, pDevice); + } + + void TearDown() override { + delete buffer; + BaseClass::TearDown(); + MemoryManagementFixture::TearDown(); + } + + Buffer *createBuffer() { + return Buffer::create( + context.get(), + flags, + g_scTestBufferSizeInBytes, + pHostPtr, + retVal); + } + + cl_int retVal = CL_INVALID_VALUE; + Buffer *buffer = nullptr; +}; + +TEST_F(ValidExportHostPtr, givenPropertiesWithDmaBufWhenValidateInputAndCreateBufferThenCorrectBufferIsSet) { + cl_mem_properties properties[] = {CL_EXTERNAL_MEMORY_HANDLE_DMA_BUF_KHR, 0x1234, 0}; + auto buffer = BufferFunctions::validateInputAndCreateBuffer(context.get(), properties, flags, 0, g_scTestBufferSizeInBytes, nullptr, retVal); + EXPECT_EQ(retVal, CL_INVALID_PROPERTY); + EXPECT_EQ(nullptr, buffer); + + clReleaseMemObject(buffer); +} diff --git a/shared/source/memory_properties/memory_properties_flags.h b/shared/source/memory_properties/memory_properties_flags.h index 7727af255c..e231c12218 100644 --- a/shared/source/memory_properties/memory_properties_flags.h +++ b/shared/source/memory_properties/memory_properties_flags.h @@ -13,6 +13,9 @@ namespace NEO { class Device; struct MemoryProperties { + uint64_t handle = 0; + uint64_t handleType = 0; + uintptr_t hostptr = 0; const Device *pDevice = nullptr; uint32_t memCacheClos = 0; union { @@ -23,7 +26,6 @@ struct MemoryProperties { MemoryAllocFlags allocFlags; uint32_t allAllocFlags = 0; }; - uintptr_t hostptr = 0; static_assert(sizeof(MemoryProperties::flags) == sizeof(MemoryProperties::allFlags) && sizeof(MemoryProperties::allocFlags) == sizeof(MemoryProperties::allAllocFlags), ""); }; } // namespace NEO