From 74ccb4e981c3b16c828e245f0f6e318ba4c524de Mon Sep 17 00:00:00 2001 From: Username-Leon Date: Tue, 19 May 2026 16:11:02 +0200 Subject: [PATCH 1/2] Add support for external semaphores in the HIP backend --- devices/hip/CMakeLists.txt | 2 + devices/hip/hip_device.cpp | 11 +++ devices/hip/hip_engine.cpp | 107 +++++++++++++++++++++++++ devices/hip/hip_engine.h | 21 +++++ devices/hip/hip_external_semaphore.cpp | 58 ++++++++++++++ devices/hip/hip_external_semaphore.h | 34 ++++++++ 6 files changed, 233 insertions(+) create mode 100644 devices/hip/hip_external_semaphore.cpp create mode 100644 devices/hip/hip_external_semaphore.h diff --git a/devices/hip/CMakeLists.txt b/devices/hip/CMakeLists.txt index ed253356..72c33f29 100644 --- a/devices/hip/CMakeLists.txt +++ b/devices/hip/CMakeLists.txt @@ -43,6 +43,8 @@ set(OIDN_HIP_SOURCES hip_engine.cpp hip_external_buffer.h hip_external_buffer.cpp + hip_external_semaphore.h + hip_external_semaphore.cpp hip_module.cpp ) diff --git a/devices/hip/hip_device.cpp b/devices/hip/hip_device.cpp index 85061b86..8f1b673a 100644 --- a/devices/hip/hip_device.cpp +++ b/devices/hip/hip_device.cpp @@ -200,8 +200,19 @@ OIDN_NAMESPACE_BEGIN ExternalMemoryTypeFlag::D3D11ResourceKMT | ExternalMemoryTypeFlag::D3D12Heap | ExternalMemoryTypeFlag::D3D12Resource; + + externalSemaphoreTypes = ExternalSemaphoreTypeFlag::OpaqueWin32 | + ExternalSemaphoreTypeFlag::OpaqueWin32KMT | + ExternalSemaphoreTypeFlag::D3D11Fence | + ExternalSemaphoreTypeFlag::D3D12Fence | + ExternalSemaphoreTypeFlag::KeyedMutex | + ExternalSemaphoreTypeFlag::KeyedMutexKMT | + ExternalSemaphoreTypeFlag::TimelineSemaphoreWin32; #else externalMemoryTypes = ExternalMemoryTypeFlag::OpaqueFD; + + // Not yet supported by HIP on Linux. + externalSemaphoreTypes = 0; #endif externalMemoryTypes |= ExternalMemoryTypeFlag::Dedicated; diff --git a/devices/hip/hip_engine.cpp b/devices/hip/hip_engine.cpp index 305f76b9..00f9d851 100644 --- a/devices/hip/hip_engine.cpp +++ b/devices/hip/hip_engine.cpp @@ -3,6 +3,7 @@ #include "hip_engine.h" #include "hip_external_buffer.h" +#include "hip_external_semaphore.h" #include "hip_conv.h" #include "../gpu/gpu_autoexposure.h" #include "../gpu/gpu_input_process.h" @@ -30,6 +31,112 @@ OIDN_NAMESPACE_BEGIN return makeRef(this, handleType, handle, name, byteSize); } + Ref HIPEngine::newExternalSemaphore(ExternalSemaphoreTypeFlags fdType, + int fd) + { + return makeRef(this, fdType, fd); + } + + Ref HIPEngine::newExternalSemaphore(ExternalSemaphoreTypeFlags handleType, + void* handle, const void* name) + { + return makeRef(this, handleType, handle, name); + } + + void HIPEngine::submitSignalSemaphores(Semaphore* const* semaphores, + const uint64_t* values, + int numSemaphores) + { + if (numSemaphores < 0) + throw Exception(Error::InvalidArgument, "number of semaphores is negative"); + if (numSemaphores == 0) + return; + if (semaphores == nullptr) + throw Exception(Error::InvalidArgument, "semaphores pointer is null"); + + semaphoreHandles.resize(numSemaphores); + semaphoreSignalParams.resize(numSemaphores); + + for (int i = 0; i < numSemaphores; ++i) + { + if (semaphores[i] == nullptr) + throw Exception(Error::InvalidArgument, "semaphore is null"); + if (semaphores[i]->getDevice() != getDevice()) + throw Exception(Error::InvalidArgument, "semaphore was created on a different device"); + + HIPExternalSemaphore* hipSemaphore = reinterpret_cast(semaphores[i]); + ExternalSemaphoreTypeFlags type = hipSemaphore->getType(); + + semaphoreHandles[i] = hipSemaphore->getHandle(); + + semaphoreSignalParams[i] = {}; + if (values != nullptr) + { + if (type == ExternalSemaphoreTypeFlag::KeyedMutex || + type == ExternalSemaphoreTypeFlag::KeyedMutexKMT) + semaphoreSignalParams[i].params.keyedMutex.key = values[i]; + else + semaphoreSignalParams[i].params.fence.value = values[i]; + } + } + + checkError(hipSignalExternalSemaphoresAsync( + semaphoreHandles.data(), + semaphoreSignalParams.data(), + numSemaphores, + stream)); + } + + void HIPEngine::submitWaitSemaphores(Semaphore* const* semaphores, + const uint64_t* values, + const uint32_t* timeoutsMs, + int numSemaphores) + { + if (numSemaphores < 0) + throw Exception(Error::InvalidArgument, "number of semaphores is negative"); + if (numSemaphores == 0) + return; + if (semaphores == nullptr) + throw Exception(Error::InvalidArgument, "semaphores pointer is null"); + + semaphoreHandles.resize(numSemaphores); + semaphoreWaitParams.resize(numSemaphores); + + for (int i = 0; i < numSemaphores; ++i) + { + if (semaphores[i] == nullptr) + throw Exception(Error::InvalidArgument, "semaphore is null"); + if (semaphores[i]->getDevice() != getDevice()) + throw Exception(Error::InvalidArgument, "semaphore was created on a different device"); + + HIPExternalSemaphore* hipSemaphore = reinterpret_cast(semaphores[i]); + ExternalSemaphoreTypeFlags type = hipSemaphore->getType(); + + semaphoreHandles[i] = hipSemaphore->getHandle(); + + semaphoreWaitParams[i] = {}; + if (type == ExternalSemaphoreTypeFlag::KeyedMutex || + type == ExternalSemaphoreTypeFlag::KeyedMutexKMT) + { + if (values != nullptr) + semaphoreWaitParams[i].params.keyedMutex.key = values[i]; + if (timeoutsMs != nullptr) + semaphoreWaitParams[i].params.keyedMutex.timeoutMs = timeoutsMs[i]; + } + else + { + if (values != nullptr) + semaphoreWaitParams[i].params.fence.value = values[i]; + } + } + + checkError(hipWaitExternalSemaphoresAsync( + semaphoreHandles.data(), + semaphoreWaitParams.data(), + numSemaphores, + stream)); + } + bool HIPEngine::isSupported(const TensorDesc& desc) const { // CK tensors must be smaller than 2GB diff --git a/devices/hip/hip_engine.h b/devices/hip/hip_engine.h index 675f7b08..e6aaa453 100644 --- a/devices/hip/hip_engine.h +++ b/devices/hip/hip_engine.h @@ -73,6 +73,22 @@ OIDN_NAMESPACE_BEGIN // Tensor bool isSupported(const TensorDesc& desc) const override; + // Semaphore + Ref newExternalSemaphore(ExternalSemaphoreTypeFlags fdType, + int fd) override; + + Ref newExternalSemaphore(ExternalSemaphoreTypeFlags handleType, + void* handle, const void* name) override; + + void submitSignalSemaphores(Semaphore* const* semaphores, + const uint64_t* values, + int numSemaphores) override; + + void submitWaitSemaphores(Semaphore* const* semaphores, + const uint64_t* values, + const uint32_t* timeoutsMs, + int numSemaphores) override; + // Ops Ref newConv(const ConvDesc& desc) override; Ref newPool(const PoolDesc& desc) override; @@ -135,6 +151,11 @@ OIDN_NAMESPACE_BEGIN HIPDevice* device; hipStream_t stream; + + // Temporary storage for semaphore handles and params + std::vector semaphoreHandles; + std::vector semaphoreSignalParams; + std::vector semaphoreWaitParams; }; OIDN_NAMESPACE_END diff --git a/devices/hip/hip_external_semaphore.cpp b/devices/hip/hip_external_semaphore.cpp new file mode 100644 index 00000000..3deb93b0 --- /dev/null +++ b/devices/hip/hip_external_semaphore.cpp @@ -0,0 +1,58 @@ +// Copyright 2026 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "hip_external_semaphore.h" + +OIDN_NAMESPACE_BEGIN + + HIPExternalSemaphore::HIPExternalSemaphore(Engine* engine, + ExternalSemaphoreTypeFlags fdType, + int fd) + : Semaphore(engine->getDevice()), + type(fdType) + { + // Not yet supported on Linux by HIP. + throw Exception(Error::InvalidArgument, "external semaphore type not supported by the device"); + } + + HIPExternalSemaphore::HIPExternalSemaphore(Engine* engine, + ExternalSemaphoreTypeFlags handleType, + void* handle, const void* name) + : Semaphore(engine->getDevice()), + type(handleType) + { + hipExternalSemaphoreHandleDesc handleDesc{}; + handleDesc.handle.win32.handle = handle; + handleDesc.handle.win32.name = name; + + if (handleType == ExternalSemaphoreTypeFlag::OpaqueWin32) + handleDesc.type = hipExternalSemaphoreHandleTypeOpaqueWin32; + else if (handleType == ExternalSemaphoreTypeFlag::OpaqueWin32KMT) + handleDesc.type = hipExternalSemaphoreHandleTypeOpaqueWin32Kmt; + else if (handleType == ExternalSemaphoreTypeFlag::D3D11Fence) + handleDesc.type = hipExternalSemaphoreHandleTypeD3D11Fence; + else if (handleType == ExternalSemaphoreTypeFlag::D3D12Fence) + handleDesc.type = hipExternalSemaphoreHandleTypeD3D12Fence; + else if (handleType == ExternalSemaphoreTypeFlag::KeyedMutex) + handleDesc.type = hipExternalSemaphoreHandleTypeKeyedMutex; + else if (handleType == ExternalSemaphoreTypeFlag::KeyedMutexKMT) + handleDesc.type = hipExternalSemaphoreHandleTypeKeyedMutexKmt; + else if (handleType == ExternalSemaphoreTypeFlag::TimelineSemaphoreWin32) + handleDesc.type = hipExternalSemaphoreHandleTypeTimelineSemaphoreWin32; + else + throw Exception(Error::InvalidArgument, "external semaphore type not supported by the device"); + + init(handleDesc); + } + + void HIPExternalSemaphore::init(const hipExternalSemaphoreHandleDesc& handleDesc) + { + checkError(hipImportExternalSemaphore(&extSem, &handleDesc)); + } + + HIPExternalSemaphore::~HIPExternalSemaphore() + { + hipDestroyExternalSemaphore(extSem); + } + +OIDN_NAMESPACE_END \ No newline at end of file diff --git a/devices/hip/hip_external_semaphore.h b/devices/hip/hip_external_semaphore.h new file mode 100644 index 00000000..d8f98117 --- /dev/null +++ b/devices/hip/hip_external_semaphore.h @@ -0,0 +1,34 @@ +// Copyright 2026 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "core/semaphore.h" +#include "hip_engine.h" + +OIDN_NAMESPACE_BEGIN + + class HIPExternalSemaphore : public Semaphore + { + public: + HIPExternalSemaphore(Engine* engine, + ExternalSemaphoreTypeFlags fdType, + int fd); + + HIPExternalSemaphore(Engine* engine, + ExternalSemaphoreTypeFlags handleType, + void* handle, const void* name); + + ~HIPExternalSemaphore(); + + ExternalSemaphoreTypeFlags getType() const { return type; } + hipExternalSemaphore_t getHandle() const { return extSem; } + + private: + ExternalSemaphoreTypeFlags type; + hipExternalSemaphore_t extSem; + + void init(const hipExternalSemaphoreHandleDesc& handleDesc); + }; + +OIDN_NAMESPACE_END \ No newline at end of file From a0c335b34f0136f5e3c914348fccb3a47e9a468d Mon Sep 17 00:00:00 2001 From: Username-Leon Date: Tue, 19 May 2026 16:14:07 +0200 Subject: [PATCH 2/2] Minor error message correction --- api/api.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/api.cpp b/api/api.cpp index 6ac78c96..92b7ed1d 100644 --- a/api/api.cpp +++ b/api/api.cpp @@ -782,7 +782,7 @@ OIDN_API_NAMESPACE_BEGIN if ((handleType & device->getExternalSemaphoreTypes()) != handleType) throw Exception(Error::InvalidArgument, "external semaphore type not supported by the device"); if ((!handle && !name) || (handle && name)) - throw Exception(Error::InvalidArgument, "exactly one of the external memory handle and name must be non-null"); + throw Exception(Error::InvalidArgument, "exactly one of the external semaphore handle and name must be non-null"); Ref semaphore = device->newExternalSemaphore(handleType, handle, name); return reinterpret_cast(semaphore.detach()); OIDN_CATCH_DEVICE(device)