P4 to Git Change 1515374 by skeely@skeely_HSA_linux on 2018/02/12 17:53:32

SWDEV-94389 - Get gl display and context from cl context object.

	Also report Mesa interop errors in debug log.

Affected files ...

... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_gl_amd.hpp#20 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocdevice.cpp#82 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocdevice.hpp#25 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocglinterop.cpp#5 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocglinterop.hpp#5 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocmemory.cpp#33 edit


[ROCm/clr commit: 7175a76b6d]
This commit is contained in:
foreman
2018-02-12 18:02:35 -05:00
parent a0fa4d2b5e
commit fd96c14e23
5 changed files with 109 additions and 114 deletions
@@ -1205,14 +1205,11 @@ bool Device::bindExternalDevice(uint flags, void* const gfxDevice[], void* gfxCo
mesa_glinterop_device_info info;
info.size = sizeof(mesa_glinterop_device_info);
MesaInterop temp;
if (!temp.Bind(kind, display, context)) {
assert(false && "Failed mesa interop bind.");
if (!MesaInterop::Init(kind)) {
return false;
}
if (!temp.GetInfo(info)) {
assert(false && "Failed to get mesa interop device info.");
if (!MesaInterop::GetInfo(info, kind, display, context)) {
return false;
}
@@ -1223,8 +1220,6 @@ bool Device::bindExternalDevice(uint flags, void* const gfxDevice[], void* gfxCo
match &= info_.vendorId_ == info.vendor_id;
match &= deviceInfo_.pciDeviceId_ == info.device_id;
if (!validateOnly) mesa_ = temp;
return match;
#endif
}
@@ -1235,7 +1230,6 @@ bool Device::unbindExternalDevice(uint flags, void* const gfxDevice[], void* gfx
return false;
#else
if ((flags & amd::Context::GLDeviceKhr) == 0) return false;
if (!validateOnly) mesa_.Unbind();
return true;
#endif
}
@@ -367,8 +367,6 @@ class Device : public NullDevice {
const hsa_profile_t agent_profile() const { return agent_profile_; }
const MesaInterop& mesa() const { return mesa_; }
//! Finds an appropriate map target
amd::Memory* findMapTarget(size_t size) const;
@@ -417,7 +415,6 @@ class Device : public NullDevice {
static hsa_agent_t cpu_agent_;
static std::vector<hsa_agent_t> gpu_agents_;
std::vector<hsa_agent_t> p2p_agents_; //!< List of P2P agents available for this device
MesaInterop mesa_;
hsa_agent_t _bkendDevice;
hsa_profile_t agent_profile_;
hsa_amd_memory_pool_t group_segment_;
@@ -15,16 +15,29 @@
namespace roc {
namespace MesaInterop {
#if !defined(_WIN32)
static PFNMESAGLINTEROPGLXQUERYDEVICEINFOPROC GlxInfo = nullptr;
static PFNMESAGLINTEROPGLXEXPORTOBJECTPROC GlxExport = nullptr;
static PFNMESAGLINTEROPEGLQUERYDEVICEINFOPROC EglInfo = nullptr;
static PFNMESAGLINTEROPEGLEXPORTOBJECTPROC EglExport = nullptr;
static MESA_INTEROP_KIND loadedGLAPITypes(MESA_INTEROP_NONE);
#endif
std::atomic<uint32_t> MesaInterop::refCount(0);
static const char* errorStrings[] = {"MESA_GLINTEROP_SUCCESS",
"MESA_GLINTEROP_OUT_OF_RESOURCES",
"MESA_GLINTEROP_OUT_OF_HOST_MEMORY",
"MESA_GLINTEROP_INVALID_OPERATION",
"MESA_GLINTEROP_INVALID_VALUE",
"MESA_GLINTEROP_INVALID_DISPLAY",
"MESA_GLINTEROP_INVALID_CONTEXT",
"MESA_GLINTEROP_INVALID_TARGET",
"MESA_GLINTEROP_INVALID_OBJECT",
"MESA_GLINTEROP_INVALID_MIP_LEVEL",
"MESA_GLINTEROP_UNSUPPORTED"};
bool MesaInterop::Supported() {
bool Supported() {
#ifdef _WIN32
return false;
#else
@@ -32,79 +45,88 @@ bool MesaInterop::Supported() {
#endif
}
// Attempt to locate Mesa interop APIs. Return which of glx/egl are supported.
bool MesaInterop::Bind(MESA_INTEROP_KIND Kind, const DisplayHandle& Display,
const ContextHandle& Context) {
// Returns true if the required subsystem is supported on the GL device.
// Must be called at least once, may be called multiple times.
bool Init(MESA_INTEROP_KIND Kind) {
#if defined(_WIN32)
return false;
#else
if (Kind == MESA_INTEROP_NONE) return false;
if (loadedGLAPITypes == MESA_INTEROP_NONE) {
void* glxinfo = dlsym(RTLD_DEFAULT, "MesaGLInteropGLXQueryDeviceInfo");
void* eglinfo = dlsym(RTLD_DEFAULT, "MesaGLInteropEGLQueryDeviceInfo");
if (kind != MESA_INTEROP_NONE) {
LogError("Error - MesaInterop Bind while already bound.");
return false;
GlxInfo = (PFNMESAGLINTEROPGLXQUERYDEVICEINFOPROC)glxinfo;
EglInfo = (PFNMESAGLINTEROPEGLQUERYDEVICEINFOPROC)eglinfo;
GlxExport =
(PFNMESAGLINTEROPGLXEXPORTOBJECTPROC)dlsym(RTLD_DEFAULT, "MesaGLInteropGLXExportObject");
EglExport =
(PFNMESAGLINTEROPEGLEXPORTOBJECTPROC)dlsym(RTLD_DEFAULT, "MesaGLInteropEGLExportObject");
uint32_t ret = MESA_INTEROP_NONE;
if (GlxInfo && GlxExport) ret |= MESA_INTEROP_GLX;
if (EglInfo && EglExport) ret |= MESA_INTEROP_EGL;
loadedGLAPITypes = MESA_INTEROP_KIND(ret);
}
void* glxinfo = dlsym(RTLD_DEFAULT, "MesaGLInteropGLXQueryDeviceInfo");
void* eglinfo = dlsym(RTLD_DEFAULT, "MesaGLInteropEGLQueryDeviceInfo");
if (((glxinfo != GlxInfo) || (eglinfo != EglInfo)) && (refCount != 0))
LogWarning("Warning - Mesa changed while holding interop contexts.");
GlxInfo = (PFNMESAGLINTEROPGLXQUERYDEVICEINFOPROC)glxinfo;
EglInfo = (PFNMESAGLINTEROPEGLQUERYDEVICEINFOPROC)eglinfo;
GlxExport =
(PFNMESAGLINTEROPGLXEXPORTOBJECTPROC)dlsym(RTLD_DEFAULT, "MesaGLInteropGLXExportObject");
EglExport =
(PFNMESAGLINTEROPEGLEXPORTOBJECTPROC)dlsym(RTLD_DEFAULT, "MesaGLInteropEGLExportObject");
uint32_t ret = MESA_INTEROP_NONE;
if (GlxInfo && GlxExport) ret |= MESA_INTEROP_GLX;
if (EglInfo && EglExport) ret |= MESA_INTEROP_EGL;
kind = MESA_INTEROP_KIND(ret & Kind);
display = Display;
context = Context;
if (kind != MESA_INTEROP_NONE) {
refCount++;
return true;
}
return false;
return ((loadedGLAPITypes & Kind) == Kind);
#endif
}
bool MesaInterop::GetInfo(mesa_glinterop_device_info& info) const {
bool GetInfo(mesa_glinterop_device_info& info, MESA_INTEROP_KIND Kind, const DisplayHandle display,
const ContextHandle context) {
#ifdef _WIN32
return false;
#else
switch (kind) {
assert((loadedGLAPITypes & Kind) == Kind && "Requested interop API is not currently loaded.");
int ret;
switch (Kind) {
case MESA_INTEROP_GLX:
return GlxInfo(display.glxDisplay, context.glxContext, &info) == MESA_GLINTEROP_SUCCESS;
ret = GlxInfo(display.glxDisplay, context.glxContext, &info);
break;
case MESA_INTEROP_EGL:
return EglInfo(display.eglDisplay, context.eglContext, &info) == MESA_GLINTEROP_SUCCESS;
ret = EglInfo(display.eglDisplay, context.eglContext, &info);
break;
default:
assert(false && "Invalid interop kind.");
return false;
}
if (ret == MESA_GLINTEROP_SUCCESS) return true;
if (ret < int(sizeof(errorStrings) / sizeof(errorStrings[0])))
LogPrintfError("Mesa interop: GetInfo failed with \"%s\".\n", errorStrings[ret]);
else
LogError("Mesa interop: GetInfo failed with invalid error code.\n");
return false;
#endif
}
bool MesaInterop::Export(mesa_glinterop_export_in& in, mesa_glinterop_export_out& out) const {
bool Export(mesa_glinterop_export_in& in, mesa_glinterop_export_out& out, MESA_INTEROP_KIND Kind,
const DisplayHandle display, const ContextHandle context) {
#ifdef _WIN32
return false;
#else
switch (kind) {
assert((loadedGLAPITypes & Kind) == Kind && "Requested interop API is not currently loaded.");
int ret;
switch (Kind) {
case MESA_INTEROP_GLX:
return GlxExport(display.glxDisplay, context.glxContext, &in, &out) == MESA_GLINTEROP_SUCCESS;
ret = GlxExport(display.glxDisplay, context.glxContext, &in, &out);
break;
case MESA_INTEROP_EGL:
return EglExport(display.eglDisplay, context.eglContext, &in, &out) == MESA_GLINTEROP_SUCCESS;
ret = EglExport(display.eglDisplay, context.eglContext, &in, &out);
break;
default:
assert(false && "Invalid interop kind.");
return false;
}
if (ret == MESA_GLINTEROP_SUCCESS) return true;
if (ret < int(sizeof(errorStrings) / sizeof(errorStrings[0])))
LogPrintfError("Mesa interop: Export failed with \"%s\".\n", errorStrings[ret]);
else
LogError("Mesa interop: Export failed with invalid error code.\n");
return false;
#endif
}
}
}
#endif // WITHOUT_HSA_BACKEND
@@ -20,8 +20,6 @@ typedef void* GLXContext;
#include "device/rocm/rocregisters.hpp"
#include "hsa_ext_amd.h"
#include <atomic>
namespace roc {
// Specific typed container for version 1
@@ -78,63 +76,38 @@ class image_metadata {
}
};
class MesaInterop {
public:
enum MESA_INTEROP_KIND { MESA_INTEROP_NONE = 0, MESA_INTEROP_GLX = 1, MESA_INTEROP_EGL = 2 };
namespace MesaInterop {
enum MESA_INTEROP_KIND { MESA_INTEROP_NONE = 0, MESA_INTEROP_GLX = 1, MESA_INTEROP_EGL = 2 };
union DisplayHandle {
Display* glxDisplay;
EGLDisplay eglDisplay;
};
union ContextHandle {
GLXContext glxContext;
EGLContext eglContext;
};
// True if the configuration supports the indicated interop ability.
static bool Supported();
MesaInterop() { kind = MESA_INTEROP_NONE; }
MesaInterop(const MesaInterop& rhs) { *this = rhs; }
~MesaInterop() { Unbind(); }
const MesaInterop& operator=(const MesaInterop& rhs) {
display = rhs.display;
context = rhs.context;
kind = rhs.kind;
if (kind != MESA_INTEROP_NONE) refCount++;
return *this;
}
/*
Loads Mesa interop APIs and sets this interface object to use the indicated
subsystem (GLX/EGL). Returns true if the required subsystem is found.
*/
bool Bind(MESA_INTEROP_KIND Kind, const DisplayHandle& Display, const ContextHandle& Context);
/*
Releases use of Mesa interop APIs.
Used to check for bad load/unload sequences.
*/
void Unbind() {
if (kind == MESA_INTEROP_NONE) return;
assert(refCount > 0 && "Invalid refCount in MesaInterop.");
refCount--;
kind = MESA_INTEROP_NONE;
}
bool GetInfo(mesa_glinterop_device_info& info) const;
bool Export(mesa_glinterop_export_in& in, mesa_glinterop_export_out& out) const;
private:
static std::atomic<uint32_t> refCount;
DisplayHandle display;
ContextHandle context;
MESA_INTEROP_KIND kind;
union DisplayHandle {
Display* glxDisplay;
EGLDisplay eglDisplay;
DisplayHandle() {}
DisplayHandle(Display* display) : glxDisplay(display) {}
DisplayHandle(EGLDisplay display) : eglDisplay(display) {}
};
union ContextHandle {
GLXContext glxContext;
EGLContext eglContext;
ContextHandle() {}
ContextHandle(GLXContext context) : glxContext(context) {}
ContextHandle(EGLContext context) : eglContext(context) {}
};
// True if the build supports Mesa interop.
bool Supported();
// Returns true if the required subsystem is supported on the GL device.
// Must be called at least once, may be called multiple times.
bool Init(MESA_INTEROP_KIND Kind);
bool GetInfo(mesa_glinterop_device_info& info, MESA_INTEROP_KIND Kind, const DisplayHandle display,
const ContextHandle context);
bool Export(mesa_glinterop_export_in& in, mesa_glinterop_export_out& out, MESA_INTEROP_KIND Kind,
const DisplayHandle display, const ContextHandle context);
}
}
#endif /*WITHOUT_HSA_BACKEND*/
@@ -213,7 +213,16 @@ bool Memory::createInteropBuffer(GLenum targetType, int miplevel) {
in.out_driver_data_size = MaxMetadataSizeBytes;
in.out_driver_data = &amdImageDesc_->data[0];
if (!dev().mesa().Export(in, out)) return false;
const auto& glenv = owner()->getContext().glenv();
if (glenv->isEGL()) {
if (!MesaInterop::Export(in, out, MesaInterop::MESA_INTEROP_EGL, glenv->getEglDpy(),
glenv->getEglOrigCtx()))
return false;
} else {
if (!MesaInterop::Export(in, out, MesaInterop::MESA_INTEROP_GLX, glenv->getDpy(),
glenv->getOrigCtx()))
return false;
}
size_t size;
size_t metadata_size = 0;