render implement thread, wrap GL commands into tasks

This commit is contained in:
2019-07-06 22:25:07 +02:00
parent db27334ce5
commit 0012e2ce9b
18 changed files with 1252 additions and 904 deletions

View File

@@ -2,6 +2,7 @@
#include "log.h"
#include "rtt.h"
#include "util.h"
#include "app.h"
RTT::RTT()
{
@@ -38,19 +39,22 @@ void RTT::resize(int width, int height)
{
RTT new_rtt;
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldDFboID);
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &oldRFboID);
App::I.render_task([&]
{
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldDFboID);
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &oldRFboID);
new_rtt.create(width, height, -1, int_fmt, rboID != 0);
new_rtt.create(width, height, -1, int_fmt, rboID != 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, new_rtt.fboID);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fboID);
glBlitFramebuffer(0, 0, w, h, 0, 0, new_rtt.w, new_rtt.h, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, new_rtt.fboID);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fboID);
glBlitFramebuffer(0, 0, w, h, 0, 0, new_rtt.w, new_rtt.h, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, oldDFboID);
glBindFramebuffer(GL_READ_FRAMEBUFFER, oldRFboID);
destroy();
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, oldDFboID);
glBindFramebuffer(GL_READ_FRAMEBUFFER, oldRFboID);
destroy();
});
oldRFboID = 0;
oldDFboID = 0;
@@ -64,22 +68,25 @@ void RTT::resize(int width, int height)
void RTT::destroy()
{
if (rboID)
App::I.render_task_async([rboID=rboID, texID=texID, fboID=fboID]
{
glDeleteRenderbuffers(1, &rboID);
}
if (texID)
{
unbindTexture();
glDeleteTextures(1, &texID);
//LOG("TEX rtt destroy %d", texID)
}
if (fboID)
{
unbindFramebuffer();
glDeleteFramebuffers(1, &fboID);
//LOG("RTT DESTROY %d", fboID);
}
if (rboID)
{
glDeleteRenderbuffers(1, &rboID);
}
if (texID)
{
//unbindTexture();
glDeleteTextures(1, &texID);
//LOG("TEX rtt destroy %d", texID)
}
if (fboID)
{
//unbindFramebuffer();
glDeleteFramebuffers(1, &fboID);
//LOG("RTT DESTROY %d", fboID);
}
});
texID = 0;
fboID = 0;
rboID = 0;
@@ -89,101 +96,109 @@ void RTT::destroy()
void RTT::copy(const RTT & source)
{
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldDFboID);
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &oldRFboID);
App::I.render_task([&]
{
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldDFboID);
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &oldRFboID);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboID);
glBindFramebuffer(GL_READ_FRAMEBUFFER, source.fboID);
glBlitFramebuffer(0, 0, source.w, source.h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboID);
glBindFramebuffer(GL_READ_FRAMEBUFFER, source.fboID);
glBlitFramebuffer(0, 0, source.w, source.h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, oldDFboID);
glBindFramebuffer(GL_READ_FRAMEBUFFER, oldRFboID);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, oldDFboID);
glBindFramebuffer(GL_READ_FRAMEBUFFER, oldRFboID);
});
}
bool RTT::create(int width, int height, int tex/* = -1*/, GLint internal_format, bool depth_buffer /*= false*/)
{
// Destroy any previously created object
destroy();
w = width;
h = height;
int_fmt = internal_format;
if (tex == -1)
GLenum status = 0;
App::I.render_task([&]
{
glGenTextures(1, &texID);
//LOG("TEX rtt create %d", texID);
}
else
{
texID = tex;
}
// Destroy any previously created object
destroy();
auto ifmt = GL_UNSIGNED_BYTE;
if (internal_format == GL_RGBA32F) ifmt = GL_FLOAT;
if (internal_format == GL_RGBA16F) ifmt = GL_HALF_FLOAT;
glBindTexture(GL_TEXTURE_2D, texID);
if (tex == -1)
glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width, height, 0, GL_RGBA, ifmt, 0);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_2D, 0);
w = width;
h = height;
int_fmt = internal_format;
// Create a renderbuffer object to store depth info
if (depth_buffer)
{
glGenRenderbuffers(1, &rboID);
glBindRenderbuffer(GL_RENDERBUFFER, rboID);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
}
GLint oldFboID;
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldFboID);
// Create a framebuffer object
glGenFramebuffers(1, &fboID);
glBindFramebuffer(GL_FRAMEBUFFER, fboID);
//LOG("RTT CREATE %d - tex %d", fboID, texID);
// Attach the texture to FBO color attachment point
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texID, 0);
if (depth_buffer)
{
// Attach the renderbuffer to depth attachment point
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboID);
}
auto err2str = [](GLenum err) {
switch (err)
if (tex == -1)
{
case GL_FRAMEBUFFER_UNDEFINED: return "GL_FRAMEBUFFER_UNDEFINED";
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
case GL_FRAMEBUFFER_UNSUPPORTED: return "GL_FRAMEBUFFER_UNSUPPORTED";
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: return "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE";
default: return "UNKNOWN";
glGenTextures(1, &texID);
//LOG("TEX rtt create %d", texID);
}
else
{
texID = tex;
}
};
// Check FBO status
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
LOG("RTT::create failed because: %s", err2str(status));
auto ifmt = GL_UNSIGNED_BYTE;
if (internal_format == GL_RGBA32F) ifmt = GL_FLOAT;
if (internal_format == GL_RGBA16F) ifmt = GL_HALF_FLOAT;
// Switch back to window-system-provided framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, oldFboID);
oldRFboID = 0;
oldDFboID = 0;
glBindTexture(GL_TEXTURE_2D, texID);
if (tex == -1)
glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width, height, 0, GL_RGBA, ifmt, 0);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_2D, 0);
// Create a renderbuffer object to store depth info
if (depth_buffer)
{
glGenRenderbuffers(1, &rboID);
glBindRenderbuffer(GL_RENDERBUFFER, rboID);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
}
GLint oldFboID;
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldFboID);
// Create a framebuffer object
glGenFramebuffers(1, &fboID);
glBindFramebuffer(GL_FRAMEBUFFER, fboID);
//LOG("RTT CREATE %d - tex %d", fboID, texID);
// Attach the texture to FBO color attachment point
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texID, 0);
if (depth_buffer)
{
// Attach the renderbuffer to depth attachment point
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboID);
}
auto err2str = [](GLenum err) {
switch (err)
{
case GL_FRAMEBUFFER_UNDEFINED: return "GL_FRAMEBUFFER_UNDEFINED";
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
case GL_FRAMEBUFFER_UNSUPPORTED: return "GL_FRAMEBUFFER_UNSUPPORTED";
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: return "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE";
default: return "UNKNOWN";
}
};
// Check FBO status
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
LOG("RTT::create failed because: %s", err2str(status));
// Switch back to window-system-provided framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, oldFboID);
oldRFboID = 0;
oldDFboID = 0;
});
return status == GL_FRAMEBUFFER_COMPLETE;
}
void RTT::bindFramebuffer()
{
assert(App::I.is_render_thread());
#ifdef _DEBUG
if (bound)
{
@@ -193,15 +208,16 @@ void RTT::bindFramebuffer()
#endif
}
#endif // _DEBUG
bound = true;
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldDFboID);
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &oldRFboID);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboID);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fboID);
bound = true;
}
void RTT::unbindFramebuffer()
{
assert(App::I.is_render_thread());
if (!bound)
return;
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, oldDFboID);
@@ -213,6 +229,7 @@ void RTT::unbindFramebuffer()
void RTT::clear(glm::vec4 color)
{
assert(App::I.is_render_thread());
glClearColor(color.r, color.g, color.b, color.a);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
@@ -240,11 +257,14 @@ uint8_t* RTT::readTextureData(uint8_t* buffer)
{
if (!buffer)
buffer = createBuffer();
GLint old;
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fboID);
glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
glBindFramebuffer(GL_READ_FRAMEBUFFER, old);
App::I.render_task([&]
{
GLint old;
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fboID);
glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
glBindFramebuffer(GL_READ_FRAMEBUFFER, old);
});
return buffer;
}
@@ -252,11 +272,14 @@ float* RTT::readTextureDataFloat(float* buffer)
{
if (!buffer)
buffer = createBufferFloat();
GLint old;
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fboID);
glReadPixels(0, 0, w, h, GL_RGBA, GL_FLOAT, buffer);
glBindFramebuffer(GL_READ_FRAMEBUFFER, old);
App::I.render_task([&]
{
GLint old;
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fboID);
glReadPixels(0, 0, w, h, GL_RGBA, GL_FLOAT, buffer);
glBindFramebuffer(GL_READ_FRAMEBUFFER, old);
});
return buffer;
}
@@ -272,11 +295,13 @@ float * RTT::createBufferFloat()
void RTT::bindTexture()
{
assert(App::I.is_render_thread());
glBindTexture(GL_TEXTURE_2D, texID);
}
void RTT::unbindTexture()
{
assert(App::I.is_render_thread());
glBindTexture(GL_TEXTURE_2D, 0);
}