From cdf6ed67b9b9ce11a9ae8fdfe3a971e2e09f1c9b Mon Sep 17 00:00:00 2001 From: Igor Chorazewicz Date: Thu, 19 Dec 2024 23:33:11 +0100 Subject: [PATCH 01/12] [L0 v2] avoid nullptr derefernce in kernel.cpp --- source/adapters/level_zero/v2/kernel.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/source/adapters/level_zero/v2/kernel.cpp b/source/adapters/level_zero/v2/kernel.cpp index 28ffa73cc9..db10ff03ff 100644 --- a/source/adapters/level_zero/v2/kernel.cpp +++ b/source/adapters/level_zero/v2/kernel.cpp @@ -287,8 +287,12 @@ ur_result_t ur_kernel_handle_t_::prepareForSubmission( (hZeKernel, groupSizeX, groupSizeY, groupSizeZ)); for (auto &pending : pending_allocations) { - auto zePtr = pending.hMem->getDevicePtr(hDevice, pending.mode, 0, - pending.hMem->getSize(), migrate); + void *zePtr = nullptr; + if (pending.hMem) { + // NULL is a valid value + zePtr = pending.hMem->getDevicePtr(hDevice, pending.mode, 0, + pending.hMem->getSize(), migrate); + } UR_CALL(setArgPointer(pending.argIndex, nullptr, zePtr)); } pending_allocations.clear(); From f87cb7e4252dbce145024611bb408a28746fe1df Mon Sep 17 00:00:00 2001 From: Igor Chorazewicz Date: Thu, 19 Dec 2024 22:19:34 +0000 Subject: [PATCH 02/12] [L0 v2] remove unnecessary TODO comment The check is already done in validation layer --- source/adapters/level_zero/v2/memory.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/adapters/level_zero/v2/memory.cpp b/source/adapters/level_zero/v2/memory.cpp index 3e885d5f6c..135ded3352 100644 --- a/source/adapters/level_zero/v2/memory.cpp +++ b/source/adapters/level_zero/v2/memory.cpp @@ -419,8 +419,6 @@ ur_result_t urMemBufferCreate(ur_context_handle_t hContext, auto accessMode = getDeviceAccessMode(flags); if (useHostBuffer(hContext)) { - // TODO: assert that if hostPtr is set, either UR_MEM_FLAG_USE_HOST_POINTER - // or UR_MEM_FLAG_ALLOC_COPY_HOST_POINTER is set? auto hostPtrAction = flags & UR_MEM_FLAG_USE_HOST_POINTER ? ur_integrated_mem_handle_t::host_ptr_action_t::import From 8448f78be849ab3fdacb1e8c7a64a67ae0886861 Mon Sep 17 00:00:00 2001 From: Igor Chorazewicz Date: Thu, 19 Dec 2024 21:12:36 +0100 Subject: [PATCH 03/12] [CTS][L0 v2] adjust urEnqueueMemBufferMap to match SYCL expectations. When pHost is set in buffer properties, urEnqueueMemBufferMap should map memory to that pointer (instead of creating a new allocation). --- source/adapters/level_zero/v2/memory.cpp | 91 ++++++++++--------- source/adapters/level_zero/v2/memory.hpp | 11 ++- test/adapters/level_zero/CMakeLists.txt | 8 ++ .../urEnqueueMemBufferMapHostPtr.cpp | 38 ++++++++ 4 files changed, 102 insertions(+), 46 deletions(-) create mode 100644 test/adapters/level_zero/urEnqueueMemBufferMapHostPtr.cpp diff --git a/source/adapters/level_zero/v2/memory.cpp b/source/adapters/level_zero/v2/memory.cpp index 135ded3352..4de2a588a3 100644 --- a/source/adapters/level_zero/v2/memory.cpp +++ b/source/adapters/level_zero/v2/memory.cpp @@ -209,7 +209,7 @@ ur_discrete_mem_handle_t::ur_discrete_mem_handle_t( device_access_mode_t accessMode) : ur_mem_handle_t_(hContext, size, accessMode), deviceAllocations(hContext->getPlatform()->getNumDevices()), - activeAllocationDevice(nullptr), hostAllocations() { + activeAllocationDevice(nullptr), mapToPtr(hostPtr), hostAllocations() { if (hostPtr) { auto initialDevice = hContext->getDevices()[0]; UR_CALL_THROWS(migrateBufferTo(initialDevice, hostPtr, size)); @@ -246,12 +246,18 @@ ur_discrete_mem_handle_t::~ur_discrete_mem_handle_t() { if (!activeAllocationDevice || !writeBackPtr) return; - auto srcPtr = ur_cast( - deviceAllocations[activeAllocationDevice->Id.value()].get()); + auto srcPtr = getActiveDeviceAlloc(); synchronousZeCopy(hContext, activeAllocationDevice, writeBackPtr, srcPtr, getSize()); } +void *ur_discrete_mem_handle_t::getActiveDeviceAlloc(size_t offset) { + assert(activeAllocationDevice); + return ur_cast( + deviceAllocations[activeAllocationDevice->Id.value()].get()) + + offset; +} + void *ur_discrete_mem_handle_t::getDevicePtr( ur_device_handle_t hDevice, device_access_mode_t access, size_t offset, size_t size, std::function migrate) { @@ -272,10 +278,8 @@ void *ur_discrete_mem_handle_t::getDevicePtr( hDevice = activeAllocationDevice; } - char *ptr; if (activeAllocationDevice == hDevice) { - ptr = ur_cast(deviceAllocations[hDevice->Id.value()].get()); - return ptr + offset; + return getActiveDeviceAlloc(offset); } auto &p2pDevices = hContext->getP2PDevices(hDevice); @@ -288,9 +292,7 @@ void *ur_discrete_mem_handle_t::getDevicePtr( } // TODO: see if it's better to migrate the memory to the specified device - return ur_cast( - deviceAllocations[activeAllocationDevice->Id.value()].get()) + - offset; + return getActiveDeviceAlloc(offset); } void *ur_discrete_mem_handle_t::mapHostPtr( @@ -299,21 +301,27 @@ void *ur_discrete_mem_handle_t::mapHostPtr( TRACK_SCOPE_LATENCY("ur_discrete_mem_handle_t::mapHostPtr"); // TODO: use async alloc? - void *ptr; - UR_CALL_THROWS(hContext->getDefaultUSMPool()->allocate( - hContext, nullptr, nullptr, UR_USM_TYPE_HOST, size, &ptr)); + void *ptr = mapToPtr; + if (!ptr) { + UR_CALL_THROWS(hContext->getDefaultUSMPool()->allocate( + hContext, nullptr, nullptr, UR_USM_TYPE_HOST, size, &ptr)); + } - hostAllocations.emplace_back(ptr, size, offset, flags); + usm_unique_ptr_t mappedPtr = + usm_unique_ptr_t(ptr, [ownsAlloc = bool(mapToPtr), this](void *p) { + if (ownsAlloc) { + UR_CALL_THROWS(hContext->getDefaultUSMPool()->free(p)); + } + }); + + hostAllocations.emplace_back(std::move(mappedPtr), size, offset, flags); if (activeAllocationDevice && (flags & UR_MAP_FLAG_READ)) { - auto srcPtr = - ur_cast( - deviceAllocations[activeAllocationDevice->Id.value()].get()) + - offset; - migrate(srcPtr, hostAllocations.back().ptr, size); + auto srcPtr = getActiveDeviceAlloc(offset); + migrate(srcPtr, hostAllocations.back().ptr.get(), size); } - return hostAllocations.back().ptr; + return hostAllocations.back().ptr.get(); } void ur_discrete_mem_handle_t::unmapHostPtr( @@ -321,33 +329,32 @@ void ur_discrete_mem_handle_t::unmapHostPtr( std::function migrate) { TRACK_SCOPE_LATENCY("ur_discrete_mem_handle_t::unmapHostPtr"); - for (auto &hostAllocation : hostAllocations) { - if (hostAllocation.ptr == pMappedPtr) { - void *devicePtr = nullptr; - if (activeAllocationDevice) { - devicePtr = - ur_cast( - deviceAllocations[activeAllocationDevice->Id.value()].get()) + - hostAllocation.offset; - } else if (!(hostAllocation.flags & - UR_MAP_FLAG_WRITE_INVALIDATE_REGION)) { - devicePtr = ur_cast(getDevicePtr( - hContext->getDevices()[0], device_access_mode_t::read_only, - hostAllocation.offset, hostAllocation.size, migrate)); - } + auto hostAlloc = + std::find_if(hostAllocations.begin(), hostAllocations.end(), + [pMappedPtr](const host_allocation_desc_t &desc) { + return desc.ptr.get() == pMappedPtr; + }); - if (devicePtr) { - migrate(hostAllocation.ptr, devicePtr, hostAllocation.size); - } + if (hostAlloc == hostAllocations.end()) { + throw UR_RESULT_ERROR_INVALID_ARGUMENT; + } - // TODO: use async free here? - UR_CALL_THROWS(hContext->getDefaultUSMPool()->free(hostAllocation.ptr)); - return; - } + bool shouldMigrateToDevice = + !(hostAlloc->flags & UR_MAP_FLAG_WRITE_INVALIDATE_REGION); + + if (!activeAllocationDevice && shouldMigrateToDevice) { + allocateOnDevice(hContext->getDevices()[0], getSize()); + } + + // TODO: tests require that memory is migrated even for + // UR_MAP_FLAG_WRITE_INVALIDATE_REGION when there is an active device + // allocation. is this correct? + if (activeAllocationDevice) { + migrate(hostAlloc->ptr.get(), getActiveDeviceAlloc(hostAlloc->offset), + hostAlloc->size); } - // No mapping found - throw UR_RESULT_ERROR_INVALID_ARGUMENT; + hostAllocations.erase(hostAlloc); } static bool useHostBuffer(ur_context_handle_t hContext) { diff --git a/source/adapters/level_zero/v2/memory.hpp b/source/adapters/level_zero/v2/memory.hpp index 575a313e14..81e8495239 100644 --- a/source/adapters/level_zero/v2/memory.hpp +++ b/source/adapters/level_zero/v2/memory.hpp @@ -98,11 +98,11 @@ struct ur_integrated_mem_handle_t : public ur_mem_handle_t_ { }; struct host_allocation_desc_t { - host_allocation_desc_t(void *ptr, size_t size, size_t offset, + host_allocation_desc_t(usm_unique_ptr_t ptr, size_t size, size_t offset, ur_map_flags_t flags) - : ptr(ptr), size(size), offset(offset), flags(flags) {} + : ptr(std::move(ptr)), size(size), offset(offset), flags(flags) {} - void *ptr; + usm_unique_ptr_t ptr; size_t size; size_t offset; ur_map_flags_t flags; @@ -146,10 +146,13 @@ struct ur_discrete_mem_handle_t : public ur_mem_handle_t_ { // If not null, copy the buffer content back to this memory on release. void *writeBackPtr = nullptr; + // If not null, mapHostPtr should map memory to this ptr + void *mapToPtr = nullptr; + std::vector hostAllocations; + void *getActiveDeviceAlloc(size_t offset = 0); void *allocateOnDevice(ur_device_handle_t hDevice, size_t size); - ur_result_t migrateBufferTo(ur_device_handle_t hDevice, void *src, size_t size); }; diff --git a/test/adapters/level_zero/CMakeLists.txt b/test/adapters/level_zero/CMakeLists.txt index 97217a1f3b..fd58154d56 100644 --- a/test/adapters/level_zero/CMakeLists.txt +++ b/test/adapters/level_zero/CMakeLists.txt @@ -86,6 +86,14 @@ function(add_adapter_tests adapter) ur_umf ) endif() + + add_adapter_test(${adapter}_mem_buffer_map + FIXTURE DEVICES + SOURCES + urEnqueueMemBufferMapHostPtr.cpp + ENVIRONMENT + "UR_ADAPTERS_FORCE_LOAD=\"$\"" + ) endfunction() if(UR_BUILD_ADAPTER_L0) diff --git a/test/adapters/level_zero/urEnqueueMemBufferMapHostPtr.cpp b/test/adapters/level_zero/urEnqueueMemBufferMapHostPtr.cpp new file mode 100644 index 0000000000..120962b26f --- /dev/null +++ b/test/adapters/level_zero/urEnqueueMemBufferMapHostPtr.cpp @@ -0,0 +1,38 @@ +// Copyright (C) 2023 Intel Corporation +// Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM +// Exceptions. See LICENSE.TXT +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#include "../../enqueue/helpers.h" +#include +#include +#include + +using urEnqueueMemBufferMapTestWithParamL0 = + uur::urMemBufferQueueTestWithParam; + +UUR_DEVICE_TEST_SUITE_P( + urEnqueueMemBufferMapTestWithParamL0, + ::testing::ValuesIn(uur::mem_buffer_test_parameters), + uur::printMemBufferTestString); + +TEST_P(urEnqueueMemBufferMapTestWithParamL0, MapWithHostPtr) { + uur::raii::Mem buffer; + + char *ptr = new char[4096]; + + ur_buffer_properties_t props; + props.pHost = ptr; + + ASSERT_SUCCESS(urMemBufferCreate(context, UR_MEM_FLAG_USE_HOST_POINTER, 4096, + &props, buffer.ptr())); + + void *mappedPtr = nullptr; + ASSERT_SUCCESS(urEnqueueMemBufferMap( + queue, buffer.get(), true, UR_MAP_FLAG_READ | UR_MAP_FLAG_WRITE, 0, 4096, + 0, nullptr, nullptr, reinterpret_cast(&mappedPtr))); + + ASSERT_EQ(ptr, mappedPtr); + + delete[] ptr; +} From 87b2722f115aad835f1fa9e3108bd27e8f67ddbf Mon Sep 17 00:00:00 2001 From: Igor Chorazewicz Date: Thu, 19 Dec 2024 03:09:55 +0100 Subject: [PATCH 04/12] [L0 v2] check alignment in USM allocate functions --- source/adapters/level_zero/v2/usm.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/adapters/level_zero/v2/usm.cpp b/source/adapters/level_zero/v2/usm.cpp index 63d88b9b81..cd7d4502e7 100644 --- a/source/adapters/level_zero/v2/usm.cpp +++ b/source/adapters/level_zero/v2/usm.cpp @@ -200,6 +200,10 @@ ur_result_t ur_usm_pool_handle_t_::allocate( ur_usm_type_t type, size_t size, void **ppRetMem) { uint32_t alignment = pUSMDesc ? pUSMDesc->align : 0; + if ((alignment & (alignment - 1)) != 0) { + return UR_RESULT_ERROR_INVALID_VALUE; + } + auto umfPool = getPool(usm::pool_descriptor{this, hContext, hDevice, type, false}); if (!umfPool) { From 599dd57c41ac6f794b765d8c3edf7a3de2891d07 Mon Sep 17 00:00:00 2001 From: Igor Chorazewicz Date: Thu, 19 Dec 2024 03:19:34 +0100 Subject: [PATCH 05/12] [L0 v2] implement USM import/release support --- source/adapters/level_zero/v2/api.cpp | 11 --------- source/adapters/level_zero/v2/usm.cpp | 35 +++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/source/adapters/level_zero/v2/api.cpp b/source/adapters/level_zero/v2/api.cpp index 04ed82c03c..9ae9bddcb9 100644 --- a/source/adapters/level_zero/v2/api.cpp +++ b/source/adapters/level_zero/v2/api.cpp @@ -474,15 +474,4 @@ ur_result_t urCommandBufferCommandGetInfoExp( return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; } -ur_result_t urUSMImportExp(ur_context_handle_t hContext, void *pMem, - size_t size) { - logger::error("{} function not implemented!", __FUNCTION__); - return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; -} - -ur_result_t urUSMReleaseExp(ur_context_handle_t hContext, void *pMem) { - logger::error("{} function not implemented!", __FUNCTION__); - return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; -} - } // namespace ur::level_zero diff --git a/source/adapters/level_zero/v2/usm.cpp b/source/adapters/level_zero/v2/usm.cpp index cd7d4502e7..d14f1bfab4 100644 --- a/source/adapters/level_zero/v2/usm.cpp +++ b/source/adapters/level_zero/v2/usm.cpp @@ -461,4 +461,39 @@ ur_result_t urUSMGetMemAllocInfo( } catch (...) { return exceptionToResult(std::current_exception()); } + +ur_result_t urUSMImportExp(ur_context_handle_t hContext, void *hostPtr, + size_t size) { + UR_ASSERT(hContext, UR_RESULT_ERROR_INVALID_CONTEXT); + + // Promote the host ptr to USM host memory. + if (ZeUSMImport.Supported && hostPtr != nullptr) { + // Query memory type of the host pointer + ze_device_handle_t hDevice; + ZeStruct zeMemoryAllocationProperties; + ZE2UR_CALL(zeMemGetAllocProperties, + (hContext->getZeHandle(), hostPtr, &zeMemoryAllocationProperties, + &hDevice)); + + // If not shared of any type, we can import the ptr + if (zeMemoryAllocationProperties.type == ZE_MEMORY_TYPE_UNKNOWN) { + // Promote the host ptr to USM host memory + ze_driver_handle_t driverHandle = + hContext->getPlatform()->ZeDriverHandleExpTranslated; + ZeUSMImport.doZeUSMImport(driverHandle, hostPtr, size); + } + } + return UR_RESULT_SUCCESS; +} + +ur_result_t urUSMReleaseExp(ur_context_handle_t hContext, void *hostPtr) { + UR_ASSERT(hContext, UR_RESULT_ERROR_INVALID_CONTEXT); + + // Release the imported memory. + if (ZeUSMImport.Supported && hostPtr != nullptr) + ZeUSMImport.doZeUSMRelease( + hContext->getPlatform()->ZeDriverHandleExpTranslated, hostPtr); + return UR_RESULT_SUCCESS; +} + } // namespace ur::level_zero From 70d6207bba355c18f0b751e89331bfecddc52736 Mon Sep 17 00:00:00 2001 From: Igor Chorazewicz Date: Tue, 24 Dec 2024 01:26:15 +0100 Subject: [PATCH 06/12] [L0 v2] implement enqueueMemcpy2D --- .../v2/queue_immediate_in_order.cpp | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/source/adapters/level_zero/v2/queue_immediate_in_order.cpp b/source/adapters/level_zero/v2/queue_immediate_in_order.cpp index 52908385f2..31422210a5 100644 --- a/source/adapters/level_zero/v2/queue_immediate_in_order.cpp +++ b/source/adapters/level_zero/v2/queue_immediate_in_order.cpp @@ -872,17 +872,20 @@ ur_result_t ur_queue_immediate_in_order_t::enqueueUSMMemcpy2D( bool blocking, void *pDst, size_t dstPitch, const void *pSrc, size_t srcPitch, size_t width, size_t height, uint32_t numEventsInWaitList, const ur_event_handle_t *phEventWaitList, ur_event_handle_t *phEvent) { - std::ignore = blocking; - std::ignore = pDst; - std::ignore = dstPitch; - std::ignore = pSrc; - std::ignore = srcPitch; - std::ignore = width; - std::ignore = height; - std::ignore = numEventsInWaitList; - std::ignore = phEventWaitList; - std::ignore = phEvent; - return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; + TRACK_SCOPE_LATENCY("ur_queue_immediate_in_order_t::enqueueUSMMemcpy2D"); + + ur_rect_offset_t zeroOffset{0, 0, 0}; + ur_rect_region_t region{width, height, 0}; + + std::scoped_lock lock(this->Mutex); + + ur_usm_handle_t_ srcHandle(hContext, 0, pSrc); + ur_usm_handle_t_ dstHandle(hContext, 0, pDst); + + return enqueueRegionCopyUnlocked(&srcHandle, &dstHandle, blocking, zeroOffset, + zeroOffset, region, srcPitch, 0, dstPitch, 0, + numEventsInWaitList, phEventWaitList, + phEvent, UR_COMMAND_MEM_BUFFER_COPY_RECT); } static void *getGlobalPointerFromModule(ze_module_handle_t hModule, From 958f35a66520f0e5af494321c5712872794d28b2 Mon Sep 17 00:00:00 2001 From: Igor Chorazewicz Date: Tue, 24 Dec 2024 01:31:14 +0100 Subject: [PATCH 07/12] [L0 v2] properly handle shared device-read-only allocations --- source/adapters/level_zero/v2/usm.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/source/adapters/level_zero/v2/usm.cpp b/source/adapters/level_zero/v2/usm.cpp index d14f1bfab4..4e9c264182 100644 --- a/source/adapters/level_zero/v2/usm.cpp +++ b/source/adapters/level_zero/v2/usm.cpp @@ -192,6 +192,14 @@ ur_usm_pool_handle_t_::getPool(const usm::pool_descriptor &desc) { return pool; } +static ur_usm_device_mem_flags_t getDeviceFlags(const ur_usm_desc_t *pUSMDesc) { + if (auto devDesc = find_stype_node(pUSMDesc)) { + return devDesc->flags; + } + + return 0; +} + ur_result_t ur_usm_pool_handle_t_::allocate( /// [in] handle of the context object ur_context_handle_t hContext, @@ -204,8 +212,11 @@ ur_result_t ur_usm_pool_handle_t_::allocate( return UR_RESULT_ERROR_INVALID_VALUE; } - auto umfPool = - getPool(usm::pool_descriptor{this, hContext, hDevice, type, false}); + auto deviceFlags = getDeviceFlags(pUSMDesc); + + auto umfPool = getPool(usm::pool_descriptor{ + this, hContext, hDevice, type, + bool(deviceFlags & UR_USM_DEVICE_MEM_FLAG_DEVICE_READ_ONLY)}); if (!umfPool) { return UR_RESULT_ERROR_INVALID_ARGUMENT; } From 14ee7d654b77935b1c199bc75d2e0a7b2be7e37a Mon Sep 17 00:00:00 2001 From: Igor Chorazewicz Date: Thu, 26 Dec 2024 21:25:16 +0000 Subject: [PATCH 08/12] [L0 v2] fix enqueueMemBufferMap implementation event should always be signaled (if provided by the user). --- .../level_zero/v2/queue_immediate_in_order.cpp | 9 +++++---- test/conformance/enqueue/urEnqueueMemBufferMap.cpp | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/source/adapters/level_zero/v2/queue_immediate_in_order.cpp b/source/adapters/level_zero/v2/queue_immediate_in_order.cpp index 31422210a5..6136f487d8 100644 --- a/source/adapters/level_zero/v2/queue_immediate_in_order.cpp +++ b/source/adapters/level_zero/v2/queue_immediate_in_order.cpp @@ -660,10 +660,11 @@ ur_result_t ur_queue_immediate_in_order_t::enqueueMemBufferMap( // If memory was not migrated, we need to wait on the events here. ZE2UR_CALL(zeCommandListAppendWaitOnEvents, (handler.commandList.get(), waitList.second, waitList.first)); - if (signalEvent) { - ZE2UR_CALL(zeCommandListAppendSignalEvent, - (handler.commandList.get(), signalEvent->getZeEvent())); - } + } + + if (signalEvent) { + ZE2UR_CALL(zeCommandListAppendSignalEvent, + (handler.commandList.get(), signalEvent->getZeEvent())); } if (blockingMap) { diff --git a/test/conformance/enqueue/urEnqueueMemBufferMap.cpp b/test/conformance/enqueue/urEnqueueMemBufferMap.cpp index 8d7ddcb92c..e13757bb48 100644 --- a/test/conformance/enqueue/urEnqueueMemBufferMap.cpp +++ b/test/conformance/enqueue/urEnqueueMemBufferMap.cpp @@ -228,6 +228,20 @@ TEST_P(urEnqueueMemBufferMapTestWithParam, SuccessMultiMaps) { } } +TEST_P(urEnqueueMemBufferMapTestWithParam, MapSignalEvent) { + const std::vector input(count, 0); + ASSERT_SUCCESS(urEnqueueMemBufferWrite(queue, buffer, true, 0, size, + input.data(), 0, nullptr, nullptr)); + + uint32_t *map = nullptr; + ur_event_handle_t hEvent; + ASSERT_SUCCESS(urEnqueueMemBufferMap( + queue, buffer, true, UR_MAP_FLAG_READ | UR_MAP_FLAG_WRITE, 0, size, 0, + nullptr, &hEvent, (void **)&map)); + + ASSERT_SUCCESS(urEnqueueEventsWait(queue, 1, &hEvent, nullptr)); +} + TEST_P(urEnqueueMemBufferMapTestWithParam, InvalidNullHandleQueue) { void *map = nullptr; ASSERT_EQ_RESULT(UR_RESULT_ERROR_INVALID_NULL_HANDLE, From 2af41b12e18eee34756a797dd31a968f09c41b9b Mon Sep 17 00:00:00 2001 From: Igor Chorazewicz Date: Fri, 27 Dec 2024 18:42:32 +0000 Subject: [PATCH 09/12] [L0 v2] implement UR_QUEUE_INFO_EMPTY query --- .../level_zero/v2/queue_immediate_in_order.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/source/adapters/level_zero/v2/queue_immediate_in_order.cpp b/source/adapters/level_zero/v2/queue_immediate_in_order.cpp index 6136f487d8..af65df78a2 100644 --- a/source/adapters/level_zero/v2/queue_immediate_in_order.cpp +++ b/source/adapters/level_zero/v2/queue_immediate_in_order.cpp @@ -132,8 +132,15 @@ ur_queue_immediate_in_order_t::queueGetInfo(ur_queue_info_t propName, case UR_QUEUE_INFO_DEVICE_DEFAULT: return UR_RESULT_ERROR_UNSUPPORTED_ENUMERATION; case UR_QUEUE_INFO_EMPTY: { - // We can't tell if the queue is empty as we don't hold to any events - return ReturnValue(false); + auto status = ZE_CALL_NOCHECK(zeCommandListHostSynchronize, + (handler.commandList.get(), 0)); + if (status == ZE_RESULT_SUCCESS) { + return ReturnValue(true); + } else if (status == ZE_RESULT_NOT_READY) { + return ReturnValue(false); + } else { + return ze2urResult(status); + } } default: logger::error("Unsupported ParamName in urQueueGetInfo: " From ca304c6b78c4012360e21cbfd362649bc2e05352 Mon Sep 17 00:00:00 2001 From: Igor Chorazewicz Date: Fri, 27 Dec 2024 19:15:45 +0000 Subject: [PATCH 10/12] [L0 v2] add logs expected by SYCL tests --- source/adapters/level_zero/v2/event_provider_normal.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/adapters/level_zero/v2/event_provider_normal.cpp b/source/adapters/level_zero/v2/event_provider_normal.cpp index 029b95071b..3f7116adf3 100644 --- a/source/adapters/level_zero/v2/event_provider_normal.cpp +++ b/source/adapters/level_zero/v2/event_provider_normal.cpp @@ -50,6 +50,8 @@ provider_pool::provider_pool(ur_context_handle_t context, queue_type queue, devices.push_back(d->ZeDevice); } + logger::debug("ze_event_pool_desc_t flags set to: {}", desc.flags); + ZE2UR_CALL_THROWS(zeEventPoolCreate, (context->getZeHandle(), &desc, devices.size(), devices.data(), pool.ptr())); From e2c109b74430514b5338b5b7cdfb2196ec67f483 Mon Sep 17 00:00:00 2001 From: Igor Chorazewicz Date: Tue, 31 Dec 2024 03:01:04 +0000 Subject: [PATCH 11/12] [L0 v2] do not use usm pool free for native handles as they can be allocated by the user using L0 API directly (and then UMF will not know about those pointers and umfFree will do nothing). --- source/adapters/level_zero/v2/memory.cpp | 15 ++++++--------- source/adapters/level_zero/v2/usm.cpp | 8 +++++++- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/source/adapters/level_zero/v2/memory.cpp b/source/adapters/level_zero/v2/memory.cpp index 4de2a588a3..3ec16e8352 100644 --- a/source/adapters/level_zero/v2/memory.cpp +++ b/source/adapters/level_zero/v2/memory.cpp @@ -115,10 +115,7 @@ ur_integrated_mem_handle_t::ur_integrated_mem_handle_t( if (!ownHostPtr) { return; } - auto ret = hContext->getDefaultUSMPool()->free(ptr); - if (ret != UR_RESULT_SUCCESS) { - logger::error("Failed to free host memory: {}", ret); - } + ZE_CALL_NOCHECK(zeMemFree, (hContext->getZeHandle(), ptr)); }); } @@ -234,10 +231,7 @@ ur_discrete_mem_handle_t::ur_discrete_mem_handle_t( if (!ownZePtr) { return; } - auto ret = hContext->getDefaultUSMPool()->free(ptr); - if (ret != UR_RESULT_SUCCESS) { - logger::error("Failed to free device memory: {}", ret); - } + ZE_CALL_NOCHECK(zeMemFree, (hContext->getZeHandle(), ptr)); }); } } @@ -310,7 +304,10 @@ void *ur_discrete_mem_handle_t::mapHostPtr( usm_unique_ptr_t mappedPtr = usm_unique_ptr_t(ptr, [ownsAlloc = bool(mapToPtr), this](void *p) { if (ownsAlloc) { - UR_CALL_THROWS(hContext->getDefaultUSMPool()->free(p)); + auto ret = hContext->getDefaultUSMPool()->free(p); + if (ret != UR_RESULT_SUCCESS) { + logger::error("Failed to mapped memory: {}", ret); + } } }); diff --git a/source/adapters/level_zero/v2/usm.cpp b/source/adapters/level_zero/v2/usm.cpp index 4e9c264182..4f22221562 100644 --- a/source/adapters/level_zero/v2/usm.cpp +++ b/source/adapters/level_zero/v2/usm.cpp @@ -231,7 +231,13 @@ ur_result_t ur_usm_pool_handle_t_::allocate( } ur_result_t ur_usm_pool_handle_t_::free(void *ptr) { - return umf::umf2urResult(umfFree(ptr)); + auto umfPool = umfPoolByPtr(ptr); + if (umfPool) { + return umf::umf2urResult(umfPoolFree(umfPool, ptr)); + } else { + logger::error("Failed to find pool for pointer: {}", ptr); + return UR_RESULT_ERROR_INVALID_VALUE; + } } namespace ur::level_zero { From 96a845d92be9d43d5a657dc858be40c9c9a46338 Mon Sep 17 00:00:00 2001 From: Igor Chorazewicz Date: Tue, 31 Dec 2024 18:54:23 +0000 Subject: [PATCH 12/12] [L0][L0 v2] add command list creation logs To support both legacy and v2 adapter in SYCL tests --- source/adapters/level_zero/queue.cpp | 8 ++++++++ source/adapters/level_zero/v2/command_list_cache.cpp | 11 +++++++++++ 2 files changed, 19 insertions(+) diff --git a/source/adapters/level_zero/queue.cpp b/source/adapters/level_zero/queue.cpp index 2e5eb08008..aed521b605 100644 --- a/source/adapters/level_zero/queue.cpp +++ b/source/adapters/level_zero/queue.cpp @@ -2293,6 +2293,10 @@ ur_result_t ur_queue_handle_t_::createCommandList( IsInOrderList = true; } + logger::debug( + "create command list ordinal: {}, type: regular, device: {}, inOrder: {}", + QueueGroupOrdinal, Device->ZeDevice, IsInOrderList); + ZE2UR_CALL(zeCommandListCreate, (Context->ZeContext, Device->ZeDevice, &ZeCommandListDesc, &ZeCommandList)); @@ -2459,6 +2463,10 @@ ur_command_list_ptr_t &ur_queue_handle_t_::ur_queue_group_t::getImmCmdList() { "(round robin in [{}, {}]) priority = {}", ZeCommandQueueDesc.ordinal, ZeCommandQueueDesc.index, LowerIndex, UpperIndex, Priority); + logger::debug("create command list ordinal: {}, type: immediate, device: " + "{}, inOrder: {}", + ZeCommandQueueDesc.ordinal, Queue->Device->ZeDevice, + isInOrderList); ZE_CALL_NOCHECK(zeCommandListCreateImmediate, (Queue->Context->ZeContext, Queue->Device->ZeDevice, diff --git a/source/adapters/level_zero/v2/command_list_cache.cpp b/source/adapters/level_zero/v2/command_list_cache.cpp index be4cb813fd..2a5f7e20e2 100644 --- a/source/adapters/level_zero/v2/command_list_cache.cpp +++ b/source/adapters/level_zero/v2/command_list_cache.cpp @@ -69,6 +69,12 @@ command_list_cache_t::createCommandList(const command_list_descriptor_t &desc) { QueueDesc.index = ImmCmdDesc->Index.value(); } QueueDesc.pNext = &offloadDesc; + + logger::debug("create command list ordinal: {}, type: immediate, device: " + "{}, inOrder: {}", + ImmCmdDesc->Ordinal, ImmCmdDesc->ZeDevice, + ImmCmdDesc->IsInOrder); + ZE2UR_CALL_THROWS( zeCommandListCreateImmediate, (ZeContext, ImmCmdDesc->ZeDevice, &QueueDesc, &ZeCommandList)); @@ -81,6 +87,11 @@ command_list_cache_t::createCommandList(const command_list_descriptor_t &desc) { CmdListDesc.commandQueueGroupOrdinal = RegCmdDesc.Ordinal; CmdListDesc.pNext = &offloadDesc; + logger::debug("create command list ordinal: {}, type: immediate, device: " + "{}, inOrder: {}", + RegCmdDesc.Ordinal, RegCmdDesc.ZeDevice, + RegCmdDesc.IsInOrder); + ze_command_list_handle_t ZeCommandList; ZE2UR_CALL_THROWS(zeCommandListCreate, (ZeContext, RegCmdDesc.ZeDevice, &CmdListDesc, &ZeCommandList));