According to http://adrienb.fr/blog/wp-content/uploads/2013/04/PortingSourceToLinux.pdf,
you want an FBO per-texture, not just format. And indeed, I can measure a very slight
performance improvement on both NVidia and ATI for this.
CHECK(dither_effect->set_int("output_height", height));
}
} else {
CHECK(dither_effect->set_int("output_height", height));
}
} else {
- fbo = resource_pool->create_fbo(context, GL_RGBA16F, phase->output_width, phase->output_height);
+ fbo = resource_pool->create_fbo(context, output_textures[phase]);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
- check_error();
- glFramebufferTexture2D(
- GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D,
- output_textures[phase],
- 0);
- check_error();
- GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
- assert(status == GL_FRAMEBUFFER_COMPLETE);
glViewport(0, 0, phase->output_width, phase->output_height);
}
glViewport(0, 0, phase->output_width, phase->output_height);
}
texture_formats.erase(free_texture_num);
glDeleteTextures(1, &free_texture_num);
check_error();
texture_formats.erase(free_texture_num);
glDeleteTextures(1, &free_texture_num);
check_error();
+
+ // Delete any FBO related to this texture.
+ for (list<GLuint>::iterator fbo_freelist_it = fbo_freelist.begin();
+ fbo_freelist_it != fbo_freelist.end(); ) {
+ GLuint fbo_num = *fbo_freelist_it;
+ map<GLuint, FBO>::const_iterator format_it = fbo_formats.find(fbo_num);
+ assert(format_it != fbo_formats.end());
+ if (format_it->second.texture_num == free_texture_num) {
+ glDeleteFramebuffers(1, &fbo_num);
+ fbo_freelist.erase(fbo_freelist_it++);
+ } else {
+ ++fbo_freelist_it;
+ }
+ }
}
pthread_mutex_unlock(&lock);
}
}
pthread_mutex_unlock(&lock);
}
-GLuint ResourcePool::create_fbo(void *context, GLint internal_format, GLsizei width, GLsizei height)
+GLuint ResourcePool::create_fbo(void *context, GLuint texture_num)
{
pthread_mutex_lock(&lock);
// See if there's an FBO on the freelist we can use.
{
pthread_mutex_lock(&lock);
// See if there's an FBO on the freelist we can use.
map<GLuint, FBO>::const_iterator format_it = fbo_formats.find(fbo_num);
assert(format_it != fbo_formats.end());
if (format_it->second.context == context &&
map<GLuint, FBO>::const_iterator format_it = fbo_formats.find(fbo_num);
assert(format_it != fbo_formats.end());
if (format_it->second.context == context &&
- format_it->second.internal_format == internal_format &&
- format_it->second.width == width &&
- format_it->second.height == height) {
+ format_it->second.texture_num == texture_num) {
fbo_freelist.erase(freelist_it);
pthread_mutex_unlock(&lock);
return fbo_num;
fbo_freelist.erase(freelist_it);
pthread_mutex_unlock(&lock);
return fbo_num;
GLuint fbo_num;
glGenFramebuffers(1, &fbo_num);
check_error();
GLuint fbo_num;
glGenFramebuffers(1, &fbo_num);
check_error();
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo_num);
+ check_error();
+ glFramebufferTexture2D(
+ GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D,
+ texture_num,
+ 0);
+ check_error();
+ GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+ assert(status == GL_FRAMEBUFFER_COMPLETE);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ check_error();
FBO fbo_format;
fbo_format.context = context;
FBO fbo_format;
fbo_format.context = context;
- fbo_format.internal_format = internal_format;
- fbo_format.width = width;
- fbo_format.height = height;
+ fbo_format.texture_num = texture_num;
assert(fbo_formats.count(fbo_num) == 0);
fbo_formats.insert(make_pair(fbo_num, fbo_format));
assert(fbo_formats.count(fbo_num) == 0);
fbo_formats.insert(make_pair(fbo_num, fbo_format));
GLuint create_2d_texture(GLint internal_format, GLsizei width, GLsizei height);
void release_2d_texture(GLuint texture_num);
GLuint create_2d_texture(GLint internal_format, GLsizei width, GLsizei height);
void release_2d_texture(GLuint texture_num);
- // Allocate an FBO used for the given internal format and dimensions,
- // or fetch a previous used if possible. Keeps ownership of the FBO;
- // you must call release_fbo() of deleting it when you no longer want it.
- // You can get an appropriate context pointer from get_gl_context_identifier().
+ // Allocate an FBO with the the given texture bound as a framebuffer attachment,
+ // or fetch a previous used if possible. Unbinds GL_FRAMEBUFFER afterwards.
+ // Keeps ownership of the FBO; you must call release_fbo() of deleting
+ // it when you no longer want it. You can get an appropriate context
+ // pointer from get_gl_context_identifier().
//
// NOTE: In principle, the FBO doesn't have a resolution or pixel format;
// you can bind almost whatever texture you want to it. However, changing
//
// NOTE: In principle, the FBO doesn't have a resolution or pixel format;
// you can bind almost whatever texture you want to it. However, changing
- // resolution or pixel formats can have an adverse effect on performance,
+ // textures can have an adverse effect on performance due to validation,
// in particular on NVidia cards. Also, keep in mind that FBOs are not
// shareable across contexts.
// in particular on NVidia cards. Also, keep in mind that FBOs are not
// shareable across contexts.
- GLuint create_fbo(void *context, GLint internal_format, GLsizei width, GLsizei height);
+ GLuint create_fbo(void *context, GLuint texture_num);
void release_fbo(GLuint fbo_num);
private:
void release_fbo(GLuint fbo_num);
private:
struct FBO {
void *context;
struct FBO {
void *context;
- GLint internal_format;
- GLsizei width, height;
};
// A mapping from FBO number to format details. This is filled if the
};
// A mapping from FBO number to format details. This is filled if the