Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2019-06-13 22:31:46 +0300
committerClément Foucault <foucault.clem@gmail.com>2019-06-13 22:32:02 +0300
commit5e626e76645905e71182a9379f0bf86ae3010203 (patch)
tree74b35e9008b8dbb0e8aa5408e32c8e518c315763 /source/blender/gpu/intern/gpu_framebuffer.c
parent1688a57a8e68a71bf16acea1f78395b19406e601 (diff)
Fix T61768 Eevee Offscreen rendering
The issue was caused by a bad usage of GPUOffscreen. The Framebuffer was created using a window framebuffer and used in a viewport callback when another GPUContext was bound. This change allows up to 3 framebuffers per GPUOffscreen. Most common case will be using 2 framebuffers (one for init and one for drawing) but in the case of more (bad usage) it will just degrade performance a bit.
Diffstat (limited to 'source/blender/gpu/intern/gpu_framebuffer.c')
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.c68
1 files changed, 58 insertions, 10 deletions
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
index e4d083947b4..5950027a103 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.c
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -801,12 +801,55 @@ void GPU_framebuffer_recursive_downsample(GPUFrameBuffer *fb,
/* GPUOffScreen */
+#define MAX_CTX_FB_LEN 3
+
struct GPUOffScreen {
- GPUFrameBuffer *fb;
+ struct {
+ GPUContext *ctx;
+ GPUFrameBuffer *fb;
+ } framebuffers[MAX_CTX_FB_LEN];
+
GPUTexture *color;
GPUTexture *depth;
};
+/* Returns the correct framebuffer for the current context. */
+static GPUFrameBuffer *gpu_offscreen_fb_get(GPUOffScreen *ofs)
+{
+ GPUContext *ctx = GPU_context_active_get();
+ BLI_assert(ctx);
+
+ for (int i = 0; i < MAX_CTX_FB_LEN; i++) {
+ if (ofs->framebuffers[i].fb == NULL) {
+ ofs->framebuffers[i].ctx = ctx;
+ GPU_framebuffer_ensure_config(
+ &ofs->framebuffers[i].fb,
+ {GPU_ATTACHMENT_TEXTURE(ofs->depth), GPU_ATTACHMENT_TEXTURE(ofs->color)});
+ }
+
+ if (ofs->framebuffers[i].ctx == ctx) {
+ return ofs->framebuffers[i].fb;
+ }
+ }
+
+ /* List is full, this should never happen or
+ * it might just slow things down if it happens
+ * regulary. In this case we just empty the list
+ * and start over. This is most likely never going
+ * to happen under normal usage. */
+ BLI_assert(0);
+ printf(
+ "Warning: GPUOffscreen used in more than 3 GPUContext. "
+ "This may create performance drop.\n");
+
+ for (int i = 0; i < MAX_CTX_FB_LEN; i++) {
+ GPU_framebuffer_free(ofs->framebuffers[i].fb);
+ ofs->framebuffers[i].fb = NULL;
+ }
+
+ return gpu_offscreen_fb_get(ofs);
+}
+
GPUOffScreen *GPU_offscreen_create(
int width, int height, int samples, bool depth, bool high_bitdepth, char err_out[256])
{
@@ -834,11 +877,10 @@ GPUOffScreen *GPU_offscreen_create(
gpuPushAttr(GPU_VIEWPORT_BIT);
- GPU_framebuffer_ensure_config(
- &ofs->fb, {GPU_ATTACHMENT_TEXTURE(ofs->depth), GPU_ATTACHMENT_TEXTURE(ofs->color)});
+ GPUFrameBuffer *fb = gpu_offscreen_fb_get(ofs);
/* check validity at the very end! */
- if (!GPU_framebuffer_check_valid(ofs->fb, err_out)) {
+ if (!GPU_framebuffer_check_valid(fb, err_out)) {
GPU_offscreen_free(ofs);
gpuPopAttr();
return NULL;
@@ -853,8 +895,10 @@ GPUOffScreen *GPU_offscreen_create(
void GPU_offscreen_free(GPUOffScreen *ofs)
{
- if (ofs->fb) {
- GPU_framebuffer_free(ofs->fb);
+ for (int i = 0; i < MAX_CTX_FB_LEN; i++) {
+ if (ofs->framebuffers[i].fb) {
+ GPU_framebuffer_free(ofs->framebuffers[i].fb);
+ }
}
if (ofs->color) {
GPU_texture_free(ofs->color);
@@ -874,7 +918,8 @@ void GPU_offscreen_bind(GPUOffScreen *ofs, bool save)
gpuPushFrameBuffer(fb);
}
glDisable(GL_SCISSOR_TEST);
- GPU_framebuffer_bind(ofs->fb);
+ GPUFrameBuffer *ofs_fb = gpu_offscreen_fb_get(ofs);
+ GPU_framebuffer_bind(ofs_fb);
}
void GPU_offscreen_unbind(GPUOffScreen *UNUSED(ofs), bool restore)
@@ -899,7 +944,9 @@ void GPU_offscreen_draw_to_screen(GPUOffScreen *ofs, int x, int y)
const int w = GPU_texture_width(ofs->color);
const int h = GPU_texture_height(ofs->color);
- glBindFramebuffer(GL_READ_FRAMEBUFFER, ofs->fb->object);
+ GPUFrameBuffer *ofs_fb = gpu_offscreen_fb_get(ofs);
+
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, ofs_fb->object);
GLenum status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
if (status == GL_FRAMEBUFFER_COMPLETE) {
@@ -950,7 +997,8 @@ void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
/* restore the original frame-bufer */
- glBindFramebuffer(GL_FRAMEBUFFER, ofs->fb->object);
+ GPUFrameBuffer *ofs_fb = gpu_offscreen_fb_get(ofs);
+ glBindFramebuffer(GL_FRAMEBUFFER, ofs_fb->object);
finally:
/* cleanup */
@@ -983,7 +1031,7 @@ void GPU_offscreen_viewport_data_get(GPUOffScreen *ofs,
GPUTexture **r_color,
GPUTexture **r_depth)
{
- *r_fb = ofs->fb;
+ *r_fb = gpu_offscreen_fb_get(ofs);
*r_color = ofs->color;
*r_depth = ofs->depth;
}