diff options
author | mano-wii <germano.costa@ig.com.br> | 2018-12-06 01:59:22 +0300 |
---|---|---|
committer | mano-wii <germano.costa@ig.com.br> | 2018-12-06 02:00:08 +0300 |
commit | c0a71b8369a19cba05765af828ba014e67d05bc5 (patch) | |
tree | be55678abba25183b245e9b6631c050f238fca89 /source/blender/gpu/intern | |
parent | 75b739c969ce851495ce28a7f92decc8c24de733 (diff) |
Fix problem with unused color slot in framebuffer on some bugged AMD GPUs
Differential Revision: https://developer.blender.org/D4035
Diffstat (limited to 'source/blender/gpu/intern')
-rw-r--r-- | source/blender/gpu/intern/gpu_framebuffer.c | 69 |
1 files changed, 67 insertions, 2 deletions
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c index f92899f91a0..d5762700b0f 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.c +++ b/source/blender/gpu/intern/gpu_framebuffer.c @@ -416,6 +416,64 @@ static void gpu_framebuffer_update_attachments(GPUFrameBuffer *fb) glDrawBuffer(GL_NONE); } +/** + * Hack to solve the problem of some bugged AMD GPUs (see `GPU_unused_fb_slot_workaround`). + * If there is an empty color slot between the color slots, + * all textures after this slot are apparently skipped/discarded. + **/ +static void gpu_framebuffer_update_attachments_and_fill_empty_slots(GPUFrameBuffer *fb) +{ + GLenum gl_attachments[GPU_FB_MAX_COLOR_ATTACHMENT]; + bool fill_empty_slot = false; + int dummy_tex = 0; + + BLI_assert(GPU_framebuffer_active_get() == fb); + + /* Update attachments */ + for (GPUAttachmentType type = GPU_FB_MAX_ATTACHEMENT; type--;) { + GPUTexture *tex = fb->attachments[type].tex; + + if (type >= GPU_FB_COLOR_ATTACHMENT0) { + int slot = type - GPU_FB_COLOR_ATTACHMENT0; + if (tex != NULL || fill_empty_slot) { + gl_attachments[slot] = convert_attachment_type_to_gl(type); + + if (!fill_empty_slot) { + fill_empty_slot = true; + dummy_tex = GPU_texture_opengl_bindcode(tex); + } + } + else { + gl_attachments[slot] = GL_NONE; + } + } + else { + fill_empty_slot = false; + dummy_tex = 0; + } + + if ((fill_empty_slot && tex == NULL) || GPU_FB_ATTACHEMENT_IS_DIRTY(fb->dirty_flag, type)) { + if (tex != NULL) { + gpu_framebuffer_attachment_attach(&fb->attachments[type], type); + + fb->multisample = (GPU_texture_samples(tex) > 0); + fb->width = GPU_texture_width(tex); + fb->height = GPU_texture_height(tex); + + fill_empty_slot = dummy_tex != 0; + } + else { + glFramebufferTexture(GL_FRAMEBUFFER, convert_attachment_type_to_gl(type), dummy_tex, 0); + } + } + } + fb->dirty_flag = 0; + + /* Update draw buffers (color targets) + * This state is saved in the FBO */ + glDrawBuffers(GPU_FB_MAX_COLOR_ATTACHMENT, gl_attachments); +} + #define FRAMEBUFFER_STACK_DEPTH 16 @@ -451,8 +509,15 @@ void GPU_framebuffer_bind(GPUFrameBuffer *fb) gpu_framebuffer_current_set(fb); - if (fb->dirty_flag != 0) - gpu_framebuffer_update_attachments(fb); + if (fb->dirty_flag != 0) { + if (GPU_unused_fb_slot_workaround()) { + /* XXX: Please AMD, fix this. */ + gpu_framebuffer_update_attachments_and_fill_empty_slots(fb); + } + else { + gpu_framebuffer_update_attachments(fb); + } + } /* TODO manually check for errors? */ #if 0 |