372 строки
13 KiB
C++
372 строки
13 KiB
C++
/* Copyright (c) 2010 - 2023 Advanced Micro Devices, Inc.
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
THE SOFTWARE. */
|
|
|
|
#pragma once
|
|
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#else //!_WIN32
|
|
#include <dlfcn.h>
|
|
#endif //!_WIN32
|
|
|
|
#include <GL/gl.h>
|
|
#include <GL/glext.h>
|
|
#include "CL/cl_gl.h"
|
|
#ifndef _WIN32
|
|
#include <GL/glx.h>
|
|
#endif //!_WIN32
|
|
|
|
#include <EGL/egl.h>
|
|
#include <EGL/eglext.h>
|
|
#include <EGL/eglplatform.h>
|
|
|
|
#include "platform/context.hpp"
|
|
#include "platform/command.hpp"
|
|
|
|
namespace amd {
|
|
|
|
//! Class GLObject keeps all the info about the GL object
|
|
//! from which the CL object is created
|
|
class GLObject : public InteropObject {
|
|
protected:
|
|
cl_gl_object_type clGLType_; //!< CL GL object type
|
|
GLenum glTarget_;
|
|
GLuint gluiName_;
|
|
GLint gliMipLevel_;
|
|
GLenum glInternalFormat_;
|
|
GLint gliWidth_;
|
|
GLint gliHeight_;
|
|
GLint gliDepth_;
|
|
GLenum glCubemapFace_;
|
|
GLsizei glNumSamples_;
|
|
|
|
public:
|
|
//! GLObject constructor initializes member variables
|
|
GLObject(GLenum glTarget, GLuint gluiName, GLint gliMipLevel, GLenum glInternalFormat,
|
|
GLint gliWidth, GLint gliHeight, GLint gliDepth, cl_gl_object_type clGLType,
|
|
GLenum glCubemapFace,
|
|
GLsizei glNumSamples)
|
|
: // Initialization of member variables
|
|
clGLType_(clGLType),
|
|
glTarget_(glTarget),
|
|
gluiName_(gluiName),
|
|
gliMipLevel_(gliMipLevel),
|
|
glInternalFormat_(glInternalFormat),
|
|
gliWidth_(gliWidth),
|
|
gliHeight_(gliHeight),
|
|
gliDepth_(gliDepth),
|
|
glCubemapFace_(glCubemapFace),
|
|
glNumSamples_(glNumSamples) {}
|
|
|
|
virtual ~GLObject() {}
|
|
virtual GLObject* asGLObject() { return this; }
|
|
|
|
//! GLObject query functions to get GL info from member variables
|
|
GLenum getGLTarget() const { return glTarget_; }
|
|
GLuint getGLName() const { return gluiName_; }
|
|
GLint getGLMipLevel() const { return gliMipLevel_; }
|
|
GLenum getGLInternalFormat() const { return glInternalFormat_; }
|
|
GLint getGLSize() const { return gliWidth_; }
|
|
GLint getGLWidth() const { return gliWidth_; }
|
|
GLint getGLHeight() const { return gliHeight_; }
|
|
GLint getGLDepth() const { return gliDepth_; }
|
|
cl_gl_object_type getCLGLObjectType() const { return clGLType_; }
|
|
GLenum getCubemapFace() const { return glCubemapFace_; }
|
|
GLsizei getNumSamples() const { return glNumSamples_; }
|
|
};
|
|
|
|
|
|
//! Class BufferGL is drived from classes Buffer and GLObject
|
|
//! where the former keeps all data for CL object and
|
|
//! the latter keeps all data for GL object
|
|
class BufferGL : public Buffer, public GLObject {
|
|
protected:
|
|
//! Initializes the device memory array which is nested
|
|
// after'BufferGL' object in memory layout.
|
|
virtual void initDeviceMemory();
|
|
|
|
public:
|
|
//! BufferGL constructor just calls constructors of base classes
|
|
//! to pass down the parameters
|
|
BufferGL(Context& amdContext, cl_mem_flags clFlags, size_t uiSizeInBytes, GLenum glTarget,
|
|
GLuint gluiName)
|
|
: // Call base classes constructors
|
|
Buffer(amdContext, clFlags, uiSizeInBytes),
|
|
GLObject(glTarget, gluiName,
|
|
0, // Mipmap level default
|
|
GL_ARRAY_BUFFER, // Just init to some value
|
|
(GLint)uiSizeInBytes, 1, 1, CL_GL_OBJECT_BUFFER, 0, 0) {
|
|
setInteropObj(this);
|
|
}
|
|
virtual ~BufferGL() {}
|
|
|
|
virtual BufferGL* asBufferGL() { return this; }
|
|
};
|
|
|
|
|
|
//! Class ImageGL is derived from classes Image and GLObject
|
|
//! where the former keeps all data for CL object and
|
|
//! the latter keeps all data for GL object
|
|
class ImageGL : public Image, public GLObject {
|
|
public:
|
|
//! ImageGL constructor just calls constructors of base classes
|
|
//! to pass down the parameters
|
|
ImageGL(Context& amdContext, cl_mem_object_type clType, cl_mem_flags clFlags,
|
|
const Format& format, size_t width, size_t height, size_t depth, GLenum glTarget,
|
|
GLuint gluiName, GLint gliMipLevel, GLenum glInternalFormat, cl_gl_object_type clGLType,
|
|
GLsizei numSamples, GLenum glCubemapFace = 0)
|
|
: Image(amdContext, clType, clFlags, format, width, height, depth,
|
|
Format(format).getElementSize() * width,
|
|
Format(format).getElementSize() * width * height),
|
|
GLObject(glTarget, gluiName, gliMipLevel, glInternalFormat, static_cast<GLint>(width),
|
|
static_cast<GLint>(height), static_cast<GLint>(depth), clGLType, glCubemapFace,
|
|
numSamples) {
|
|
setInteropObj(this);
|
|
}
|
|
|
|
//! ImageGL constructor for mipmapped image,
|
|
//! just calls constructors of base classes to pass down the parameters
|
|
ImageGL(Context& amdContext, cl_mem_object_type clType, cl_mem_flags clFlags,
|
|
const Format& format, size_t width, size_t height, size_t depth, GLenum glTarget,
|
|
GLuint gluiName, GLint gliMipLevel, GLenum glInternalFormat, cl_gl_object_type clGLType,
|
|
GLsizei numSamples, cl_int num_mip_levels, GLenum glCubemapFace = 0)
|
|
: Image(amdContext, clType, clFlags, format, width, height, depth,
|
|
Format(format).getElementSize() * width,
|
|
Format(format).getElementSize() * width * depth, num_mip_levels),
|
|
GLObject(glTarget, gluiName, gliMipLevel, glInternalFormat, static_cast<GLint>(width),
|
|
static_cast<GLint>(height), static_cast<GLint>(depth), clGLType, glCubemapFace,
|
|
numSamples) {
|
|
setInteropObj(this);
|
|
}
|
|
|
|
virtual ~ImageGL() {}
|
|
|
|
protected:
|
|
//! Initializes the device memory array which is nested
|
|
// after'BufferGL' object in memory layout.
|
|
virtual void initDeviceMemory();
|
|
};
|
|
|
|
typedef EGLContext (*PFN_eglGetCurrentContext)();
|
|
#ifdef _WIN32
|
|
#define APICALL WINAPI
|
|
#define GETPROCADDRESS GetProcAddress
|
|
#define API_GETPROCADDR "wglGetProcAddress"
|
|
#define FCN_STR_TYPE LPCSTR
|
|
typedef PROC(WINAPI* PFN_xxxGetProcAddress)(LPCSTR fcnName);
|
|
typedef HGLRC(APICALL* PFN_wglCreateContext)(HDC hdc);
|
|
typedef HGLRC(APICALL* PFN_wglGetCurrentContext)(void);
|
|
typedef HDC(APICALL* PFN_wglGetCurrentDC)(void);
|
|
typedef BOOL(APICALL* PFN_wglDeleteContext)(HGLRC hglrc);
|
|
typedef BOOL(APICALL* PFN_wglMakeCurrent)(HDC hdc, HGLRC hglrc);
|
|
typedef BOOL(APICALL* PFN_wglShareLists)(HGLRC hglrc1, HGLRC hglrc2);
|
|
#else //!_WIN32
|
|
#define APICALL // __stdcall //??? todo odintsov
|
|
#define API_GETPROCADDR "glXGetProcAddress"
|
|
#define GETPROCADDRESS dlsym
|
|
#define FCN_STR_TYPE const GLubyte*
|
|
#define WINAPI
|
|
#define PROC void*
|
|
typedef void* (*PFN_xxxGetProcAddress)(const GLubyte* procName);
|
|
// X11 typedef
|
|
typedef Display* (*PFNXOpenDisplay)(_Xconst char* display_name);
|
|
typedef int (*PFNXCloseDisplay)(Display* display);
|
|
typedef int (*PFNXFree)(void* data);
|
|
|
|
// glx typedefs
|
|
typedef GLXDrawable (*PFNglXGetCurrentDrawable)();
|
|
typedef Display* (*PFNglXGetCurrentDisplay)();
|
|
typedef GLXContext (*PFNglXGetCurrentContext)(void);
|
|
typedef XVisualInfo* (*PFNglXChooseVisual)(Display* dpy, int screen, int* attribList);
|
|
typedef GLXContext (*PFNglXCreateContext)(Display* dpy, XVisualInfo* vis, GLXContext shareList,
|
|
Bool direct);
|
|
typedef void (*PFNglXDestroyContext)(Display* dpy, GLXContext ctx);
|
|
typedef Bool (*PFNglXMakeCurrent)(Display* dpy, GLXDrawable drawable, GLXContext ctx);
|
|
typedef void* HMODULE;
|
|
#endif //!_WIN32
|
|
|
|
#define GLPREFIX(rtype, fcn, dclargs) typedef rtype(APICALL* PFN_##fcn) dclargs;
|
|
|
|
// Declare prototypes for GL functions
|
|
#include "gl_functions.hpp"
|
|
|
|
class GLFunctions {
|
|
public:
|
|
//! Locks any access to the virtual GPUs
|
|
class SetIntEnv : public amd::StackObject {
|
|
public:
|
|
//! Default constructor
|
|
SetIntEnv(GLFunctions* env);
|
|
|
|
//! Destructor
|
|
~SetIntEnv();
|
|
|
|
//! Checks if the environment setup was successful
|
|
bool isValid() const { return isValid_; }
|
|
|
|
private:
|
|
GLFunctions* env_; //!< GL environment
|
|
bool isValid_; //!< If TRUE, then it's a valid setup
|
|
};
|
|
|
|
//! Locks any access to the virtual GPUs
|
|
class Lock : public amd::StackObject {
|
|
public:
|
|
//! Default constructor
|
|
Lock(GLFunctions* env);
|
|
|
|
//! Destructor
|
|
~Lock();
|
|
|
|
private:
|
|
GLFunctions* env_; //!< GL environment
|
|
};
|
|
|
|
private:
|
|
HMODULE libHandle_;
|
|
int missed_; // Indicates how many GL functions not init'ed, if any
|
|
|
|
amd::Monitor lock_;
|
|
|
|
EGLDisplay eglDisplay_;
|
|
EGLContext eglOriginalContext_;
|
|
EGLContext eglInternalContext_;
|
|
EGLContext eglTempContext_;
|
|
bool isEGL_;
|
|
PFN_eglGetCurrentContext eglGetCurrentContext_;
|
|
|
|
#ifdef _WIN32
|
|
HGLRC hOrigGLRC_;
|
|
HDC hDC_;
|
|
HGLRC hIntGLRC_; // handle for internal GLRC to access shared context
|
|
HDC tempDC_;
|
|
HGLRC tempGLRC_;
|
|
|
|
public:
|
|
PFN_wglCreateContext wglCreateContext_;
|
|
PFN_wglGetCurrentContext wglGetCurrentContext_;
|
|
PFN_wglGetCurrentDC wglGetCurrentDC_;
|
|
PFN_wglDeleteContext wglDeleteContext_;
|
|
PFN_wglMakeCurrent wglMakeCurrent_;
|
|
PFN_wglShareLists wglShareLists_;
|
|
#else
|
|
public:
|
|
Display* Dpy_;
|
|
GLXDrawable Drawable_;
|
|
GLXContext origCtx_;
|
|
Display* intDpy_;
|
|
Window intDrawable_;
|
|
GLXContext intCtx_;
|
|
Display* tempDpy_;
|
|
GLXDrawable tempDrawable_;
|
|
GLXContext tempCtx_;
|
|
|
|
// pointers to X11 functions
|
|
PFNXOpenDisplay XOpenDisplay_;
|
|
PFNXCloseDisplay XCloseDisplay_;
|
|
PFNXFree XFree_;
|
|
|
|
// pointers to GLX functions
|
|
PFNglXGetCurrentDrawable glXGetCurrentDrawable_;
|
|
PFNglXGetCurrentDisplay glXGetCurrentDisplay_;
|
|
PFNglXGetCurrentContext glXGetCurrentContext_;
|
|
PFNglXChooseVisual glXChooseVisual_;
|
|
PFNglXCreateContext glXCreateContext_;
|
|
PFNglXDestroyContext glXDestroyContext_;
|
|
PFNglXMakeCurrent glXMakeCurrent_;
|
|
#endif
|
|
public:
|
|
GLFunctions(HMODULE h, bool isEGL);
|
|
~GLFunctions();
|
|
|
|
bool update(intptr_t hglrc);
|
|
bool IsCurrentGlContext(const amd::Context::Info& info) const {
|
|
if (isEGL_) {
|
|
return ((info.hCtx_ != nullptr) && (eglGetCurrentContext_ != nullptr) &&
|
|
(info.hCtx_ == eglGetCurrentContext_()));
|
|
} else {
|
|
#ifdef _WIN32
|
|
return ((info.hCtx_ != nullptr) && (info.hCtx_ == wglGetCurrentContext_()));
|
|
#else
|
|
return ((info.hCtx_ != nullptr) && (info.hCtx_ == glXGetCurrentContext_()));
|
|
#endif // _WIN32
|
|
}
|
|
}
|
|
|
|
void WaitCurrentGlContext(const amd::Context::Info& info) const;
|
|
|
|
// Query CL-GL context association
|
|
bool isAssociated() const {
|
|
if (isEGL_ && eglDisplay_ && eglOriginalContext_) return true;
|
|
#ifdef _WIN32
|
|
if (hDC_ && hOrigGLRC_) return true;
|
|
#else //!_WIN32
|
|
if (Dpy_ && origCtx_) return true;
|
|
#endif //!_WIN32
|
|
return false;
|
|
}
|
|
bool isEGL() const { return isEGL_; }
|
|
// Accessor methods
|
|
#ifdef _WIN32
|
|
HGLRC getOrigGLRC() const { return hOrigGLRC_; }
|
|
HDC getDC() const { return hDC_; }
|
|
HGLRC getIntGLRC() const { return hIntGLRC_; }
|
|
#else //!_WIN32
|
|
Display* getDpy() const { return Dpy_; }
|
|
GLXDrawable getDrawable() const { return Drawable_; }
|
|
GLXContext getOrigCtx() const { return origCtx_; }
|
|
|
|
Display* getIntDpy() const { return intDpy_; }
|
|
GLXDrawable getIntDrawable() const { return intDrawable_; }
|
|
GLXContext getIntCtx() const { return intCtx_; }
|
|
|
|
EGLDisplay getEglDpy() const { return eglDisplay_; }
|
|
EGLContext getEglOrigCtx() const { return eglOriginalContext_; }
|
|
#endif //!_WIN32
|
|
|
|
// Initialize GL dynamic library and function pointers
|
|
bool init(intptr_t hdc, intptr_t hglrc);
|
|
|
|
// Return true if successful, false - if error occurred
|
|
bool setIntEnv();
|
|
bool restoreEnv();
|
|
|
|
amd::Monitor& getLock() { return lock_; }
|
|
|
|
PFN_xxxGetProcAddress GetProcAddress_;
|
|
|
|
#define GLPREFIX(rtype, fcn, dclargs) PFN_##fcn fcn##_;
|
|
// Declare pointers to GL functions
|
|
#include "gl_functions.hpp"
|
|
};
|
|
|
|
//! Functions for executing the GL related stuff
|
|
cl_mem clCreateFromGLBufferAMD(Context& amdContext, cl_mem_flags flags, GLuint bufobj,
|
|
cl_int* errcode_ret);
|
|
cl_mem clCreateFromGLTextureAMD(Context& amdContext, cl_mem_flags flags, GLenum target,
|
|
GLint miplevel, GLuint texture, int* errcode_ret);
|
|
cl_mem clCreateFromGLRenderbufferAMD(Context& amdContext, cl_mem_flags flags, GLuint renderbuffer,
|
|
int* errcode_ret);
|
|
|
|
bool getCLFormatFromGL(const Context& amdContext, GLint gliInternalFormat,
|
|
cl_image_format* pclImageFormat, int* piBytesPerPixel, cl_mem_flags flags);
|
|
|
|
} // namespace amd
|