mirror of
https://github.com/intel/compute-runtime.git
synced 2025-12-30 09:58:55 +08:00
feature(ocl): Improve Linux CL/GL sharing support
This commit is aimed at drastically improving the support for the CL/GL sharing extension on linux. The current support is not really usable as it only supports a few texture format, and only on EGL contexts. It is also pretty buggy since it requires the texture to be bound when placing the CL call to share it which is just plain wrong and will not work in many applications. This new version makes used of the "official" interop extension from MESA which is available for GLX and EGL contexts, allows sharing of buffers and not just texture and supports many more formats. This is still far from being a fully compliant / full featured version of the extension, but it's a big step forward in my opinion and allows to run some real applications. I've tested gr-fosphor (SDR spectrum display) and Davinci Resolve as examples. Both of theses don't work without theses improvements. Fixes: https://github.com/intel/compute-runtime/issues/659 Fixes: https://github.com/intel/compute-runtime/issues/667 https://github.com/intel/compute-runtime/pull/673 Related-To: NEO-3599 Signed-off-by: Sylvain Munaut <tnt@246tNt.com> Signed-off-by: Mateusz Jablonski <mateusz.jablonski@intel.com>
This commit is contained in:
committed by
Compute-Runtime-Automation
parent
80aa55a3cb
commit
e2c511bc00
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Intel Corporation
|
||||
* Copyright (C) 2023-2024 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
@@ -20,19 +20,71 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <poll.h>
|
||||
#include <unistd.h>
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
Buffer *GlBuffer::createSharedGlBuffer(Context *context, cl_mem_flags flags, unsigned int bufferId, cl_int *errcodeRet) {
|
||||
ErrorCodeHelper errorCode(errcodeRet, CL_SUCCESS);
|
||||
CL_GL_BUFFER_INFO bufferInfo = {0};
|
||||
bufferInfo.bufferName = bufferId;
|
||||
|
||||
GLSharingFunctionsLinux *sharingFunctions = context->getSharing<GLSharingFunctionsLinux>();
|
||||
if (sharingFunctions->acquireSharedBufferINTEL(&bufferInfo) == GL_FALSE) {
|
||||
errorCode.set(CL_INVALID_GL_OBJECT);
|
||||
/* Prepare export request */
|
||||
struct mesa_glinterop_export_in objIn = {};
|
||||
struct mesa_glinterop_export_out objOut = {};
|
||||
|
||||
objIn.version = 2;
|
||||
objIn.target = GL_ARRAY_BUFFER;
|
||||
objIn.obj = bufferId;
|
||||
|
||||
switch (flags) {
|
||||
case CL_MEM_READ_ONLY:
|
||||
objIn.access = MESA_GLINTEROP_ACCESS_READ_ONLY;
|
||||
break;
|
||||
case CL_MEM_WRITE_ONLY:
|
||||
objIn.access = MESA_GLINTEROP_ACCESS_WRITE_ONLY;
|
||||
break;
|
||||
case CL_MEM_READ_WRITE:
|
||||
objIn.access = MESA_GLINTEROP_ACCESS_READ_WRITE;
|
||||
break;
|
||||
default:
|
||||
errorCode.set(CL_INVALID_VALUE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
objOut.version = 2;
|
||||
|
||||
/* Call MESA interop */
|
||||
GLSharingFunctionsLinux *sharingFunctions = context->getSharing<GLSharingFunctionsLinux>();
|
||||
|
||||
int retValue = sharingFunctions->exportObject(&objIn, &objOut);
|
||||
if ((retValue != MESA_GLINTEROP_SUCCESS) || (objOut.version != 2)) {
|
||||
switch (retValue) {
|
||||
case MESA_GLINTEROP_INVALID_DISPLAY:
|
||||
case MESA_GLINTEROP_INVALID_CONTEXT:
|
||||
errorCode.set(CL_INVALID_CONTEXT);
|
||||
break;
|
||||
case MESA_GLINTEROP_INVALID_OBJECT:
|
||||
errorCode.set(CL_INVALID_GL_OBJECT);
|
||||
break;
|
||||
case MESA_GLINTEROP_OUT_OF_HOST_MEMORY:
|
||||
errorCode.set(CL_OUT_OF_HOST_MEMORY);
|
||||
break;
|
||||
case MESA_GLINTEROP_OUT_OF_RESOURCES:
|
||||
default:
|
||||
errorCode.set(CL_OUT_OF_RESOURCES);
|
||||
break;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Map result for rest of the function */
|
||||
CL_GL_BUFFER_INFO bufferInfo = {};
|
||||
bufferInfo.bufferName = bufferId;
|
||||
bufferInfo.globalShareHandle = static_cast<unsigned int>(objOut.dmabuf_fd);
|
||||
bufferInfo.bufferSize = static_cast<GLint>(objOut.buf_size);
|
||||
bufferInfo.bufferOffset = static_cast<GLint>(objOut.buf_offset);
|
||||
|
||||
auto graphicsAllocation = GlBuffer::createGraphicsAllocation(context, bufferId, bufferInfo);
|
||||
if (!graphicsAllocation) {
|
||||
errorCode.set(CL_INVALID_GL_OBJECT);
|
||||
@@ -50,20 +102,36 @@ Buffer *GlBuffer::createSharedGlBuffer(Context *context, cl_mem_flags flags, uns
|
||||
void GlBuffer::synchronizeObject(UpdateData &updateData) {
|
||||
auto sharingFunctions = static_cast<GLSharingFunctionsLinux *>(this->sharingFunctions);
|
||||
|
||||
CL_GL_BUFFER_INFO bufferInfo = {};
|
||||
bufferInfo.bufferName = this->clGlObjectId;
|
||||
sharingFunctions->acquireSharedBufferINTEL(&bufferInfo);
|
||||
/* Prepare flush request */
|
||||
struct mesa_glinterop_export_in objIn = {};
|
||||
struct mesa_glinterop_flush_out syncOut = {};
|
||||
int fenceFd = -1;
|
||||
|
||||
auto graphicsAllocation = updateData.memObject->getGraphicsAllocation(updateData.rootDeviceIndex);
|
||||
objIn.version = 2;
|
||||
objIn.target = GL_ARRAY_BUFFER;
|
||||
objIn.obj = this->clGlObjectId;
|
||||
|
||||
updateData.sharedHandle = bufferInfo.globalShareHandle;
|
||||
updateData.synchronizationStatus = SynchronizeStatus::ACQUIRE_SUCCESFUL;
|
||||
graphicsAllocation->setAllocationOffset(bufferInfo.bufferOffset);
|
||||
syncOut.version = 1;
|
||||
syncOut.fence_fd = &fenceFd;
|
||||
|
||||
const auto currentSharedHandle = graphicsAllocation->peekSharedHandle();
|
||||
if (currentSharedHandle != updateData.sharedHandle) {
|
||||
updateData.updateData = new CL_GL_BUFFER_INFO(bufferInfo);
|
||||
/* Call MESA interop */
|
||||
int retValue = sharingFunctions->flushObjects(1, &objIn, &syncOut);
|
||||
if (retValue != MESA_GLINTEROP_SUCCESS) {
|
||||
updateData.synchronizationStatus = SynchronizeStatus::SYNCHRONIZE_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Wait on the fence fd */
|
||||
struct pollfd fp = {
|
||||
.fd = fenceFd,
|
||||
.events = POLLIN,
|
||||
.revents = 0,
|
||||
};
|
||||
poll(&fp, 1, 1000);
|
||||
close(fenceFd);
|
||||
|
||||
/* Done */
|
||||
updateData.synchronizationStatus = SynchronizeStatus::ACQUIRE_SUCCESFUL;
|
||||
}
|
||||
|
||||
void GlBuffer::resolveGraphicsAllocationChange(osHandle currentSharedHandle, UpdateData *updateData) {
|
||||
@@ -153,7 +221,7 @@ GraphicsAllocation *GlBuffer::createGraphicsAllocation(Context *context, unsigne
|
||||
context->getDeviceBitfieldForAllocation(context->getDevice(0)->getRootDeviceIndex())};
|
||||
// couldn't find allocation for reuse - create new
|
||||
graphicsAllocation =
|
||||
context->getMemoryManager()->createGraphicsAllocationFromSharedHandle(bufferInfo.globalShareHandle, properties, true, false, false, nullptr);
|
||||
context->getMemoryManager()->createGraphicsAllocationFromSharedHandle(bufferInfo.globalShareHandle, properties, false, false, false, nullptr);
|
||||
}
|
||||
|
||||
if (!graphicsAllocation) {
|
||||
@@ -167,6 +235,13 @@ GraphicsAllocation *GlBuffer::createGraphicsAllocation(Context *context, unsigne
|
||||
DEBUG_BREAK_IF(graphicsAllocation->getDefaultGmm() != nullptr);
|
||||
auto helper = context->getDevice(0)->getRootDeviceEnvironment().getGmmHelper();
|
||||
graphicsAllocation->setDefaultGmm(new Gmm(helper, bufferInfo.pGmmResInfo));
|
||||
} else {
|
||||
auto helper = context->getDevice(0)->getRootDeviceEnvironment().getGmmHelper();
|
||||
StorageInfo storageInfo = {};
|
||||
GmmRequirements gmmRequirements{};
|
||||
|
||||
graphicsAllocation->setDefaultGmm(new Gmm(helper,
|
||||
nullptr, bufferInfo.bufferSize, 1, GMM_RESOURCE_USAGE_UNKNOWN, storageInfo, gmmRequirements));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,8 +249,6 @@ GraphicsAllocation *GlBuffer::createGraphicsAllocation(Context *context, unsigne
|
||||
}
|
||||
|
||||
void GlBuffer::releaseResource(MemObj *memObject, uint32_t rootDeviceIndex) {
|
||||
auto sharingFunctions = static_cast<GLSharingFunctionsLinux *>(this->sharingFunctions);
|
||||
CL_GL_BUFFER_INFO bufferInfo = {};
|
||||
bufferInfo.bufferName = this->clGlObjectId;
|
||||
sharingFunctions->releaseSharedBufferINTEL(&bufferInfo);
|
||||
auto memoryManager = memObject->getMemoryManager();
|
||||
memoryManager->closeSharedHandle(memObject->getGraphicsAllocation(rootDeviceIndex));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user