[Bf-blender-cvs] [05b94c9c545] blender-v2.83-release: GPU: Add better support for texture copy fallback

Clément Foucault noreply at git.blender.org
Sun Apr 26 11:46:50 CEST 2020


Commit: 05b94c9c5457ac119f52fa9db6e41a218b64c477
Author: Clément Foucault
Date:   Sun Apr 26 12:25:32 2020 +0200
Branches: blender-v2.83-release
https://developer.blender.org/rB05b94c9c5457ac119f52fa9db6e41a218b64c477

GPU: Add better support for texture copy fallback

Depth texture copy using glCopyTexSubImage2D is undefined behavior since
you cannot bind GL_DEPTH_ATTACHMENT to glReadBuffer.

Using glBlitFramebuffer as a fallback.

===================================================================

M	source/blender/gpu/intern/gpu_texture.c

===================================================================

diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index 69ede4a9e13..686a20d05a8 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -1722,6 +1722,32 @@ void GPU_texture_generate_mipmap(GPUTexture *tex)
   gpu_texture_memory_footprint_add(tex);
 }
 
+static GLenum gpu_texture_default_attachment(GPUTexture *tex)
+{
+  return !GPU_texture_depth(tex) ?
+             GL_COLOR_ATTACHMENT0 :
+             (GPU_texture_stencil(tex) ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT);
+}
+
+static void gpu_texture_framebuffer_ensure(GPUTexture *tex)
+{
+  if (tex->copy_fb == 0) {
+    tex->copy_fb = GPU_fbo_alloc();
+    tex->copy_fb_ctx = GPU_context_active_get();
+
+    GLenum attachment = gpu_texture_default_attachment(tex);
+
+    glBindFramebuffer(GL_FRAMEBUFFER, tex->copy_fb);
+    glFramebufferTexture(GL_FRAMEBUFFER, attachment, tex->bindcode, 0);
+    if (!GPU_texture_depth(tex)) {
+      glReadBuffer(GL_COLOR_ATTACHMENT0);
+      glDrawBuffer(GL_COLOR_ATTACHMENT0);
+    }
+    BLI_assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+  }
+}
+
 /* Copy a texture content to a similar texture. Only Mip 0 is copied. */
 void GPU_texture_copy(GPUTexture *dst, GPUTexture *src)
 {
@@ -1753,33 +1779,34 @@ void GPU_texture_copy(GPUTexture *dst, GPUTexture *src)
   }
   else {
     /* Fallback for older GL. */
-    GLenum attachment = !GPU_texture_depth(src) ?
-                            GL_COLOR_ATTACHMENT0 :
-                            (GPU_texture_stencil(src) ? GL_DEPTH_STENCIL_ATTACHMENT :
-                                                        GL_DEPTH_ATTACHMENT);
-
-    if (src->copy_fb == 0) {
-      src->copy_fb = GPU_fbo_alloc();
-      src->copy_fb_ctx = GPU_context_active_get();
+    GPUFrameBuffer *prev_fb = GPU_framebuffer_active_get();
 
-      glBindFramebuffer(GL_READ_FRAMEBUFFER, src->copy_fb);
-      glFramebufferTexture(GL_READ_FRAMEBUFFER, attachment, src->bindcode, 0);
+    gpu_texture_framebuffer_ensure(src);
+    gpu_texture_framebuffer_ensure(dst);
 
-      BLI_assert(glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
-    }
     /* This means that this function can only be used in one context for each texture. */
     BLI_assert(src->copy_fb_ctx == GPU_context_active_get());
+    BLI_assert(dst->copy_fb_ctx == GPU_context_active_get());
 
     glBindFramebuffer(GL_READ_FRAMEBUFFER, src->copy_fb);
-    glReadBuffer(attachment);
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dst->copy_fb);
 
-    /* WATCH: glCopyTexSubImage2D might clamp the values to the [0,1] range
-     * where glCopyImageSubData would not. */
-    glBindTexture(dst->target, dst->bindcode);
-    glCopyTexSubImage2D(dst->target, 0, 0, 0, 0, 0, src->w, src->h);
+    GLbitfield mask = 0;
+    if (GPU_texture_stencil(src)) {
+      mask |= GL_STENCIL_BUFFER_BIT;
+    }
+    if (GPU_texture_depth(src)) {
+      mask |= GL_DEPTH_BUFFER_BIT;
+    }
+    else {
+      mask |= GL_COLOR_BUFFER_BIT;
+    }
 
-    glBindTexture(dst->target, 0);
-    glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
+    glBlitFramebuffer(0, 0, src->w, src->h, 0, 0, src->w, src->h, mask, GL_NEAREST);
+
+    if (prev_fb) {
+      GPU_framebuffer_bind(prev_fb);
+    }
   }
 }



More information about the Bf-blender-cvs mailing list