当前位置:网站首页>OpenGL es shared context for multi-threaded rendering
OpenGL es shared context for multi-threaded rendering
2022-06-24 12:15:00 【Byte flow】
OpenGL ES When sharing context , What resources can be shared ?
EGL Review the concept
EGL yes OpenGL ES And the local window system (Native Window System) Communication interface between , Its main function :
- Communicate with the native window system of the device ;
- Query the available types and configurations of the drawing surface ;
- Create drawing surface ;
- stay OpenGL ES And other graphics rendering API Synchronous rendering between ;
- Manage rendering resources such as texture maps .
OpenGL ES It's with the help of EGL Realized ,EGL Shielding the differences between different platforms (Apple Provide your own EGL API Of iOS Realization , Claim to be EAGL).
Local window related API Provides access to the local window system interface , and EGL You can create a rendered surface EGLSurface , At the same time, it provides a graphics rendering context EGLContext, For state management , Next OpenGL ES You can draw on this rendered surface .
In the picture :
- Display(EGLDisplay) It's an abstraction of the actual display device ;
- Surface(EGLSurface) The memory area used to store images FrameBuffer The abstraction of , Include Color Buffer( Color buffer ), Stencil Buffer( Template buffer ) ,Depth Buffer( Deep buffer );
- Context (EGLContext) Storage OpenGL ES Some status information of the drawing ;
stay Android Development on the platform OpenGL ES When applied , class GLSurfaceView Has provided us with the right Display , Surface , Context Management of , namely GLSurfaceView Internal implementation of EGL Encapsulation , It's easy to use interfaces GLSurfaceView.Renderer The implementation of the , Use OpenGL ES API Render and draw , To a large extent, it has improved OpenGLES The convenience of development .
Of course, we can do it ourselves EGL Encapsulation , This article is about Native Layer pair EGL encapsulate , Without the help of GLSurfaceView , Realize background rendering of pictures , utilize GPU Complete efficient image processing .
About EGL More detailed use ends , You can refer to OpenGL ES 3.0 Development ( 6、 ... and ):EGL
What resources can be shared when context is shared
When sharing context , What resources can be shared across threads ? This is the focus of this article .
To take care of the patience of some readers , Here is the conclusion .
Resources that can be shared :
- texture ;
- shader;
- program Shader program ;
- buffer Class object , Such as VBO、 EBO、 RBO etc. .
Resources that cannot be shared :
- FBO Framebuffer object ( Do not belong to buffer class );
- VAO Vertex array object ( Do not belong to buffer class ).
Here's the explanation , In resources that cannot be shared ,FBO and VAO It's a resource management object ,FBO Responsible for managing several buffers , It doesn't take up resources ,VAO Responsible for managing the VBO or EBO , It doesn't take up resources .
That's the conclusion , The conclusion verification will be carried out in the next section , We're going to open up a new rendering thread in addition to the main rendering thread , Then the main rendering thread generates the texture 、 program And other resources are shared with new rendering threads .
Shared context multithreaded rendering
This section Will be shared outside the main rendering thread EGLContext The way to open up a new off screen rendering thread , After that, the texture generated by the main rendering thread 、 program 、VBO Resources are shared with new rendering threads , Finally, it will be saved ( New rendering thread ) The texture of the rendered result is returned to the main thread for screen rendering .
Shared context
stay EGL_VERSION_1_4 (Android 5.0) edition , Called directly in the current rendering thread eglGetCurrentContext You can get the context object directly EGLContext .
C++ ,Java Each layer has its own context object API Realization :
//Java EGL14.eglGetCurrentContext(); //C++ #include "egl.h" eglGetCurrentContext();
We use in New Threads EGL When creating a rendering environment , From the main rendering thread sharedContext To create a context object for the new thread .
EGLContext context = eglCreateContext(mEGLDisplay, config,
sharedContext, attrib2_list);Because we are in the new thread to render to the area outside the screen , Need to create PbufferSurface .
EGLSurface eglSurface = eglCreatePbufferSurface(mEGLDisplay, mEGLConfig, surfaceAttribs);
International practice , We will EGL All operations are encapsulated in a class EglCore It's easy to use , Specific code can refer to the project at the end of the article .
Multithreaded rendering
analogy Android Java Layer of Looper class , We are C++ Realization Looper Used to create new threads and manage messages in threads .
class Looper {
public:
Looper();
Looper&operator=(const Looper& ) = delete;
Looper(Looper&) = delete;
virtual ~Looper();
void postMessage(int what, bool flush = false);
void postMessage(int what, void *obj, bool flush = false);
void postMessage(int what, int arg1, int arg2, bool flush = false);
void postMessage(int what, int arg1, int arg2, void *obj, bool flush = false);
void quit();
virtual void handleMessage(LooperMessage *msg);
private:
void addMessage(LooperMessage *msg, bool flush);
static void *trampoline(void *p);
void loop(void);
LooperMessage *head;
pthread_t worker;
sem_t headWriteProtect;
sem_t headDataAvailable;
bool running;
};stay GLRenderLooper Class OnSurfaceCreated、 OnSurfaceChanged、 OnDrawFrame Used to handle corresponding events .
enum {
MSG_SurfaceCreated,
MSG_SurfaceChanged,
MSG_DrawFrame,
MSG_SurfaceDestroyed,
};
class GLRenderLooper : public Looper {
public:
GLRenderLooper();
virtual ~GLRenderLooper();
static GLRenderLooper* GetInstance();
static void ReleaseInstance();
private:
virtual void handleMessage(LooperMessage *msg);
void OnSurfaceCreated();
void OnSurfaceChanged(int w, int h);
void OnDrawFrame();
void OnSurfaceDestroyed();
bool CreateFrameBufferObj();
private:
static mutex m_Mutex;
static GLRenderLooper* m_Instance;
GLEnv *m_GLEnv;
EglCore *m_EglCore = nullptr;
OffscreenSurface *m_OffscreenSurface = nullptr;
GLuint m_VaoId;
GLuint m_FboTextureId;
GLuint m_FboId;
};In function GLRenderLooper::OnSurfaceCreated in , utilize sharedContext establish OpenGL Rendering environment .
void GLRenderLooper::OnSurfaceCreated() {
// utilize sharedContext establish OpenGL Off screen rendering environment
m_EglCore = new EglCore(m_GLEnv->sharedCtx, FLAG_RECORDABLE);
SizeF imgSizeF = m_GLEnv->imgSize;
m_OffscreenSurface = new OffscreenSurface(m_EglCore, imgSizeF.width, imgSizeF.height);
m_OffscreenSurface->makeCurrent();
glGenVertexArrays(1, &m_VaoId);
glBindVertexArray(m_VaoId);
glBindBuffer(GL_ARRAY_BUFFER, m_GLEnv->vboIds[0]);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (const void *)0);
glBindBuffer(GL_ARRAY_BUFFER, GL_NONE);
glBindBuffer(GL_ARRAY_BUFFER, m_GLEnv->vboIds[1]);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (const void *)0);
glBindBuffer(GL_ARRAY_BUFFER, GL_NONE);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_GLEnv->vboIds[2]);
GO_CHECK_GL_ERROR();
glBindVertexArray(GL_NONE);
if (!CreateFrameBufferObj())
{
LOGCATE("GLRenderLooper::OnSurfaceCreated CreateFrameBufferObj fail");
}
}GLRenderLooper::OnDrawFrame Function , When the drawing is finished, pay attention to the swap buffer , Then the texture of the drawn result will be saved , Pass the callback function to the main thread for screen rendering .
void GLRenderLooper::OnDrawFrame() {
LOGCATE("GLRenderLooper::OnDrawFrame");
SizeF imgSizeF = m_GLEnv->imgSize;
glBindFramebuffer(GL_FRAMEBUFFER, m_FboId);
glViewport(0, 0, imgSizeF.width, imgSizeF.height);
glUseProgram(m_GLEnv->program);
glBindVertexArray(m_VaoId);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_GLEnv->inputTexId);
GLUtils::setInt(m_GLEnv->program, "s_TextureMap", 0);
float offset = (sin(m_FrameIndex * MATH_PI / 80) + 1.0f) / 2.0f;
GLUtils::setFloat(m_GLEnv->program, "u_Offset", offset);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (const void *)0);
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
// Note the swap buffer
m_OffscreenSurface->swapBuffers();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// The texture of the drawn result will be saved m_FboTextureId Pass it to the main thread for screen rendering
m_GLEnv->renderDone(m_GLEnv->callbackCtx, m_FboTextureId);
m_FrameIndex++;
}Back to the main rendering thread ,Init The resulting texture will be rendered in the main when 、 program 、VBO Resources and EGLContext To the new thread .
m_GLEnv.sharedCtx = eglGetCurrentContext(); m_GLEnv.program = m_FboProgramObj; m_GLEnv.inputTexId = m_ImageTextureId; m_GLEnv.vboIds[0] = m_VboIds[0]; m_GLEnv.vboIds[1] = m_VboIds[2]; m_GLEnv.vboIds[2] = m_VboIds[3]; m_GLEnv.imgSize = imgSize; m_GLEnv.renderDone = OnAsyncRenderDone;// Main thread callback function m_GLEnv.callbackCtx = this; // Send shared resources to New Threads GLRenderLooper::GetInstance()->postMessage(MSG_SurfaceCreated, &m_GLEnv); GLRenderLooper::GetInstance()->postMessage(MSG_SurfaceChanged, m_RenderImage.width, m_RenderImage.height);
When the main thread is rendering , First send rendering instructions to the new thread , Then wait for its rendering to finish , When the new thread finishes rendering, it calls OnAsyncRenderDone Function to inform the main thread to render on screen .
void SharedEGLContextSample::Draw(int screenW, int screenH)
{
{
// Send render instructions to the new thread , Then wait for its rendering to finish
unique_lock<mutex> lock(m_Mutex);
GLRenderLooper::GetInstance()->postMessage(MSG_DrawFrame);
m_Cond.wait(lock);
}
// The main thread is rendering on the screen
glViewport(0, 0, screenW, screenH);
glUseProgram(m_ProgramObj);
GO_CHECK_GL_ERROR();
glBindVertexArray(m_VaoId);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_FboTextureId);
GLUtils::setInt(m_ProgramObj, "s_TextureMap", 0);
GO_CHECK_GL_ERROR();
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (const void *)0);
GO_CHECK_GL_ERROR();
glBindTexture(GL_TEXTURE_2D, GL_NONE);
glBindVertexArray(GL_NONE);
}
void SharedEGLContextSample::OnAsyncRenderDone(void *callback, int fboTexId) {
// When the new thread finishes rendering, it calls OnAsyncRenderDone Function to inform the main thread to render on screen
SharedEGLContextSample *ctx = static_cast<SharedEGLContextSample *>(callback);
unique_lock<mutex> lock(ctx->m_Mutex);
ctx->m_FboTextureId = fboTexId;
ctx->m_Cond.notify_all();
}The last thing to note is this : Multithreaded rendering should ensure that shared resources such as textures will not be accessed at the same time , Otherwise, rendering errors will occur .
Refer to the following project for the complete code , choice Multi-Thread Render:
https://github.com/githubhaohao/NDK_OpenGLES_3_0
边栏推荐
- Opencv learning notes - matrix normalization normalize() function
- 我在深圳,到哪里开户比较好?现在网上开户安全么?
- 【老卫搞机】090期:键盘?主机?全功能键盘主机!
- Clickhouse deployment and basic usage 1
- Example of PHP observer mode [useful in the laravel framework]
- [cloud based co creation] interpretation of harmonyos application and service ecology
- mRNA疫苗的研制怎么做?27+ 胰腺癌抗原和免疫亚型的解析来告诉你答案!
- 哪个商业保险养老险好?2022年商业养老保险产品排名
- 计组-总复习
- Why does the virtual machine Ping the host but not the virtual machine
猜你喜欢

How to write controller layer code gracefully?

PHP SMS notification + voice broadcast automatic double call

保险APP适老化服务评测分析2022第06期

How is the e-commerce red envelope realized? For interview (typical high concurrency)

TP-LINK 1208路由器教程(2)

Basic path test of software test on the function of the previous day

《梦华录》要大结局了,看超前点映不如先来学学它!

Qt: judge whether the string is in numeric format

Beauty of script │ VBS introduction interactive practice

"Meng Hua Lu" is about to have a grand finale. It's better to learn it first than to look ahead!
随机推荐
How to open a new bond? Is it safe to open an account
ahk实现闹钟
Nacos source code - Interface read configuration
怎么可以打新债 开户是安全的吗
[Architect (Part 41)] installation of server development and connection to redis database
Oxylabs live online: website capture demo
ArrayList # sublist these four holes, you get caught accidentally
《opencv学习笔记》-- CV::Mat类
Axi low power interface
Jenkins remote publishing products
Fizz gateway secondary development integration tutorial
Is it safe to apply for new bonds to open an account
PHP SMS notification + voice broadcast automatic double call
链接器 --- Linker
深圳市人民医院程立新课题组提出多组学数据在肝细胞癌的诊断与预后分析的新方法meGPS
嵌入式必学!硬件资源接口详解——基于ARM AM335X开发板 (下)
Give you a server. Can you deploy your code online?
Turn 2D photos into 3D models to see NVIDIA's new AI "magic"!
Single gene pan cancer + simple experiment can be published 7 points+
Install Kali on the U disk and persist it