Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature/ocl: Improve Linux CL/GL sharing support #673

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
597fcd6
linux/clgl: Disable code in gl_buffer_linux.cpp
smunaut Aug 9, 2023
f1e4739
linux/clgl: Disable code in gl_sync_event_linux.cpp
smunaut Aug 10, 2023
0cd8d3b
linux/clgl: Disable code in gl_context_guard_linux.cpp
smunaut Aug 10, 2023
fca8baf
linux/clgl: Disable calls to acquireSharedRenderBuffer
smunaut Aug 10, 2023
623d1fe
linux/clgl: Remove CreateBackupContext()
smunaut Aug 9, 2023
a979c60
linux/clgl: Remove GL context manipulation funcs
smunaut Aug 10, 2023
41642dd
linux/clgl: Remove setSharedOCLContextState
smunaut Aug 10, 2023
8c28604
linux/clgl: Remove Windown INTEL specific extensions
smunaut Aug 9, 2023
c724927
linux/clgl: Remove getGL{Device/Context}Handle from GLSharingFunction…
smunaut Aug 11, 2023
16d2618
linux/clgl: Add support for MESA GL interop functions
smunaut Aug 10, 2023
66f0034
linux/clgl: Use MESA interop function instead of eglExportDMABUFImage…
smunaut Aug 10, 2023
43ba95c
linux/clgl: Update unit tests to use MESA interop functions
smunaut Oct 2, 2023
8aa4850
linux/clgl: Remove {acquire,release}Texture funcs, they have been rep…
smunaut Aug 10, 2023
9760c28
linux/clgl: Remove EGLImage related functions
smunaut Aug 8, 2023
c96e1cf
linux/clgl: Add equivalent GLX functions to EGL ones in SharingFunctions
smunaut Aug 10, 2023
fce7d2b
linux/clgl: Add proper dispatch to GLX/EGL extension
smunaut Aug 10, 2023
67bf12a
linux/clgl: Remove glGetTexLevelParameteriv
smunaut Aug 11, 2023
23b9fcf
linux/clgl: Fix the getExtensions logic
smunaut Aug 11, 2023
72e82c0
linux/clgl: Update isGlSharingEnabled()
smunaut Aug 11, 2023
7454aa4
linux/clgl: Don't force load libraries by name
smunaut Aug 11, 2023
d11435d
linux/clgl: Reset contextData in finalizeProperties
smunaut Aug 11, 2023
525ccd0
linux/clgl: Add support for sharing GL buffer
smunaut Aug 25, 2023
5f5fba7
linux/clgl: Remove isGlSharingEnabled()
smunaut Nov 21, 2023
de9d857
linux/clgl: Remove broken tests
smunaut Jan 24, 2024
aaa4c0b
linux/clgl: Wait for fence during sync
smunaut Jan 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions opencl/source/helpers/gl_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ class GlFunctionHelper {
ConvertibleProcAddr operator[](const char *name) {
return ConvertibleProcAddr{reinterpret_cast<void *>(glFunctionPtr(name))};
}
bool ready() const {
return glFunctionPtr != nullptr;
}

protected:
GLFunctionType glFunctionPtr = nullptr;
Expand Down
1 change: 0 additions & 1 deletion opencl/source/sharings/gl/linux/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ if(UNIX)
${CMAKE_CURRENT_SOURCE_DIR}/gl_arb_sync_event_linux.cpp
${CMAKE_CURRENT_SOURCE_DIR}/gl_buffer_linux.cpp
${CMAKE_CURRENT_SOURCE_DIR}/gl_context_guard_linux.cpp
${CMAKE_CURRENT_SOURCE_DIR}/gl_library_linux.cpp
${CMAKE_CURRENT_SOURCE_DIR}/gl_sharing_linux.h
${CMAKE_CURRENT_SOURCE_DIR}/gl_sharing_linux.cpp
${CMAKE_CURRENT_SOURCE_DIR}/gl_sync_event_linux.cpp
Expand Down
112 changes: 93 additions & 19 deletions opencl/source/sharings/gl/linux/gl_buffer_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,72 @@

#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;

/* 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>();
if (sharingFunctions->acquireSharedBufferINTEL(&bufferInfo) == GL_FALSE) {
errorCode.set(CL_INVALID_GL_OBJECT);

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 = {
.bufferName = bufferId,
.globalShareHandle = static_cast<unsigned int>(objOut.dmabuf_fd),
.bufferSize = static_cast<GLint>(objOut.buf_size),
.bufferOffset = static_cast<GLint>(objOut.buf_offset),
};

auto graphicsAllocation = GlBuffer::createGraphicsAllocation(context, bufferId, bufferInfo);
if (!graphicsAllocation) {
errorCode.set(CL_INVALID_GL_OBJECT);
Expand All @@ -50,20 +103,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) {
Expand Down Expand Up @@ -153,7 +222,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) {
Expand All @@ -167,15 +236,20 @@ 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));
}
}

return graphicsAllocation;
}

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));
}
21 changes: 0 additions & 21 deletions opencl/source/sharings/gl/linux/gl_context_guard_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,8 @@

namespace NEO {
GLContextGuard::GLContextGuard(GLSharingFunctions &sharingFcns) : sharingFunctions(&sharingFcns) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this class still needed ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's used by the "common code" shared between linux / windows. The alternative would be #ifdef in the common code but I wanted to avoid touching windows / common code as much as possible.

auto &sharing = *static_cast<GLSharingFunctionsLinux *>(sharingFunctions);

currentContextHandle = sharing.getCurrentContext();
currentDisplayHandle = sharing.getCurrentDisplay();
auto ctxToMakeCurrent = sharing.getContextHandle();

if (currentContextHandle == 0) {
ctxToMakeCurrent = sharing.getBackupContextHandle();
}

if (currentContextHandle != sharing.getContextHandle() && currentContextHandle != sharing.getBackupContextHandle()) {
if (sharing.makeCurrent(ctxToMakeCurrent) == GL_FALSE) {
while (sharing.makeCurrent(sharing.getBackupContextHandle()) == GL_FALSE) {
;
}
}
}
}

GLContextGuard::~GLContextGuard() {
auto &sharing = *static_cast<GLSharingFunctionsLinux *>(sharingFunctions);
if (currentContextHandle != sharing.getContextHandle()) {
sharing.makeCurrent(currentContextHandle, currentDisplayHandle);
}
}
} // namespace NEO
13 changes: 0 additions & 13 deletions opencl/source/sharings/gl/linux/gl_library_linux.cpp

This file was deleted.

66 changes: 18 additions & 48 deletions opencl/source/sharings/gl/linux/gl_sharing_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,43 +11,13 @@
#include "opencl/source/helpers/gl_helper.h"
#include "opencl/source/sharings/gl/gl_arb_sync_event.h"

namespace Os {
extern const char *eglDllName;
extern const char *openglDllName;
} // namespace Os

namespace NEO {
GLSharingFunctionsLinux::GLSharingFunctionsLinux(GLType glhdcType, GLContext glhglrcHandle, GLContext glhglrcHandleBkpCtx, GLDisplay glhdcHandle)
: glHDCType(glhdcType), glHGLRCHandle(glhglrcHandle), glHGLRCHandleBkpCtx(glhglrcHandleBkpCtx), glHDCHandle(glhdcHandle) {
GLSharingFunctionsLinux::initGLFunctions();
updateOpenGLContext();
}
GLSharingFunctionsLinux::~GLSharingFunctionsLinux() = default;

bool GLSharingFunctionsLinux::isGlSharingEnabled() {
static bool oglLibAvailable = std::unique_ptr<OsLibrary>(OsLibrary::load(Os::eglDllName)).get() != nullptr;
return oglLibAvailable;
}

void GLSharingFunctionsLinux::createBackupContext() {
if (pfnEglCreateContext) {
glHGLRCHandleBkpCtx = pfnEglCreateContext(glHDCHandle);
pfnEglShareLists(glHGLRCHandle, glHGLRCHandleBkpCtx);
}
}

GLboolean GLSharingFunctionsLinux::setSharedOCLContextState() {
ContextInfo contextInfo{};
GLboolean retVal = glSetSharedOCLContextState(glHDCHandle, glHGLRCHandle, CL_TRUE, &contextInfo);
if (retVal == GL_FALSE) {
return GL_FALSE;
}
glContextHandle = contextInfo.contextHandle;
glDeviceHandle = contextInfo.deviceHandle;

return retVal;
}

bool GLSharingFunctionsLinux::isOpenGlExtensionSupported(const unsigned char *pExtensionString) {
if (glGetStringi == nullptr || glGetIntegerv == nullptr) {
return false;
Expand Down Expand Up @@ -123,26 +93,26 @@ void GLSharingFunctionsLinux::removeGlArbSyncEventMapping(Event &baseEvent) {
}

GLboolean GLSharingFunctionsLinux::initGLFunctions() {
eglLibrary.reset(OsLibrary::load(Os::eglDllName));
glLibrary.reset(OsLibrary::load(Os::openglDllName));

if (eglLibrary->isLoaded()) {
GlFunctionHelper eglGetProc(eglLibrary.get(), "eglGetProcAddress");
glGetCurrentContext = eglGetProc["eglGetCurrentContext"];
glGetCurrentDisplay = eglGetProc["eglGetCurrentDisplay"];
pfnEglCreateContext = eglGetProc["eglCreateContext"];
pfnEglDeleteContext = eglGetProc["eglDestroyContext"];
eglMakeCurrent = eglGetProc["eglMakeCurrent"];
eglCreateImage = eglGetProc["eglCreateImage"];
eglDestroyImage = eglGetProc["eglDestroyImage"];
glAcquireSharedTexture = eglGetProc["eglExportDMABUFImageMESA"];
std::unique_ptr<OsLibrary> dynLibrary(OsLibrary::load(""));

GlFunctionHelper glXGetProc(dynLibrary.get(), "glXGetProcAddress");
if (glXGetProc.ready()) {
glXGLInteropQueryDeviceInfo = glXGetProc["glXGLInteropQueryDeviceInfoMESA"];
glXGLInteropExportObject = glXGetProc["glXGLInteropExportObjectMESA"];
glXGLInteropFlushObjects = glXGetProc["glXGLInteropFlushObjectsMESA"];
}
if (glLibrary->isLoaded()) {
glGetString = (*glLibrary)["glGetString"];
glGetStringi = (*glLibrary)["glGetStringi"];
glGetIntegerv = (*glLibrary)["glGetIntegerv"];
glGetTexLevelParameteriv = (*glLibrary)["glGetTexLevelParameteriv"];

GlFunctionHelper eglGetProc(dynLibrary.get(), "eglGetProcAddress");
if (eglGetProc.ready()) {
eglGLInteropQueryDeviceInfo = eglGetProc["eglGLInteropQueryDeviceInfoMESA"];
eglGLInteropExportObject = eglGetProc["eglGLInteropExportObjectMESA"];
eglGLInteropFlushObjects = eglGetProc["eglGLInteropFlushObjectsMESA"];
}

glGetString = (*dynLibrary)["glGetString"];
glGetStringi = (*dynLibrary)["glGetStringi"];
glGetIntegerv = (*dynLibrary)["glGetIntegerv"];

this->pfnGlArbSyncObjectCleanup = cleanupArbSyncObject;
this->pfnGlArbSyncObjectSetup = setupArbSyncObject;
this->pfnGlArbSyncObjectSignal = signalArbSyncObject;
Expand Down
Loading