[Bf-blender-cvs] [fd3e44492e7] blender-v2.93-release: Fix T81751: Use GLSL for better anim player performance

Richard Antalik noreply at git.blender.org
Fri May 7 10:03:03 CEST 2021


Commit: fd3e44492e7606a741a6d2c42b31687598c7d09a
Author: Richard Antalik
Date:   Fri May 7 09:43:26 2021 +0200
Branches: blender-v2.93-release
https://developer.blender.org/rBfd3e44492e7606a741a6d2c42b31687598c7d09a

Fix T81751: Use GLSL for better anim player performance

Originally colorspace of float images was converted using CPU.
GLSL will render images much faster.

Originally image was converted to `global_role_default_byte` space,
disregarding view transform and also display device, which now is
possible to specify. These parameters could be set via commandline to
settings used in Blender, however if they are to be set by users, these
needs to be sanitized.
Right now defaults are assumed for device given for
`COLOR_ROLE_DEFAULT_BYTE`. This should produce same behavior as
implemented before.

Together with D11167 animation player performance should be much better.

This code was mostly copy-pasted from sequencer.

Reviewed By: sergey

Differential Revision: https://developer.blender.org/D11178

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

M	source/blender/windowmanager/intern/wm_playanim.c

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

diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c
index 0bf6fcd94a0..fc69211c14d 100644
--- a/source/blender/windowmanager/intern/wm_playanim.c
+++ b/source/blender/windowmanager/intern/wm_playanim.c
@@ -47,9 +47,11 @@
 #include "BLI_fileops.h"
 #include "BLI_listbase.h"
 #include "BLI_path_util.h"
+#include "BLI_rect.h"
 #include "BLI_string.h"
 #include "BLI_utildefines.h"
 
+#include "IMB_colormanagement.h"
 #include "IMB_imbuf.h"
 #include "IMB_imbuf_types.h"
 
@@ -138,6 +140,9 @@ typedef struct PlayState {
 
   bool need_frame_update;
   int frame_cursor_x;
+
+  ColorManagedViewSettings view_settings;
+  ColorManagedDisplaySettings display_settings;
 } PlayState;
 
 /* for debugging */
@@ -288,6 +293,144 @@ static int pupdate_time(void)
   return (ptottime < 0);
 }
 
+static void *ocio_transform_ibuf(PlayState *ps,
+                                 ImBuf *ibuf,
+                                 bool *r_glsl_used,
+                                 eGPUTextureFormat *r_format,
+                                 eGPUDataFormat *r_data,
+                                 void **r_buffer_cache_handle)
+{
+  void *display_buffer;
+  bool force_fallback = false;
+  *r_glsl_used = false;
+  force_fallback |= (ED_draw_imbuf_method(ibuf) != IMAGE_DRAW_METHOD_GLSL);
+  force_fallback |= (ibuf->dither != 0.0f);
+
+  /* Default */
+  *r_format = GPU_RGBA8;
+  *r_data = GPU_DATA_UBYTE;
+
+  /* Fallback to CPU based color space conversion. */
+  if (force_fallback) {
+    *r_glsl_used = false;
+    display_buffer = NULL;
+  }
+  else if (ibuf->rect_float) {
+    display_buffer = ibuf->rect_float;
+
+    *r_data = GPU_DATA_FLOAT;
+    if (ibuf->channels == 4) {
+      *r_format = GPU_RGBA16F;
+    }
+    else if (ibuf->channels == 3) {
+      /* Alpha is implicitly 1. */
+      *r_format = GPU_RGB16F;
+    }
+
+    if (ibuf->float_colorspace) {
+      *r_glsl_used = IMB_colormanagement_setup_glsl_draw_from_space(&ps->view_settings,
+                                                                    &ps->display_settings,
+                                                                    ibuf->float_colorspace,
+                                                                    ibuf->dither,
+                                                                    false,
+                                                                    false);
+    }
+    else {
+      *r_glsl_used = IMB_colormanagement_setup_glsl_draw(
+          &ps->view_settings, &ps->display_settings, ibuf->dither, false);
+    }
+  }
+  else if (ibuf->rect) {
+    display_buffer = ibuf->rect;
+    *r_glsl_used = IMB_colormanagement_setup_glsl_draw_from_space(&ps->view_settings,
+                                                                  &ps->display_settings,
+                                                                  ibuf->float_colorspace,
+                                                                  ibuf->dither,
+                                                                  false,
+                                                                  false);
+  }
+  else {
+    display_buffer = NULL;
+  }
+
+  /* There is data to be displayed, but GLSL is not initialized
+   * properly, in this case we fallback to CPU-based display transform. */
+  if ((ibuf->rect || ibuf->rect_float) && !*r_glsl_used) {
+    display_buffer = IMB_display_buffer_acquire(
+        ibuf, &ps->view_settings, &ps->display_settings, r_buffer_cache_handle);
+    *r_format = GPU_RGBA8;
+    *r_data = GPU_DATA_UBYTE;
+  }
+
+  return display_buffer;
+}
+
+static void draw_display_buffer(PlayState *ps, ImBuf *ibuf)
+{
+  void *display_buffer;
+
+  /* Format needs to be created prior to any #immBindShader call.
+   * Do it here because OCIO binds its own shader. */
+  eGPUTextureFormat format;
+  eGPUDataFormat data;
+  bool glsl_used = false;
+  GPUVertFormat *imm_format = immVertexFormat();
+  uint pos = GPU_vertformat_attr_add(imm_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+  uint texCoord = GPU_vertformat_attr_add(
+      imm_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+  void *buffer_cache_handle = NULL;
+  display_buffer = ocio_transform_ibuf(ps, ibuf, &glsl_used, &format, &data, &buffer_cache_handle);
+
+  GPUTexture *texture = GPU_texture_create_2d("display_buf", ibuf->x, ibuf->y, 1, format, NULL);
+  GPU_texture_update(texture, data, display_buffer);
+  GPU_texture_filter_mode(texture, false);
+
+  GPU_texture_bind(texture, 0);
+
+  if (!glsl_used) {
+    immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
+    immUniformColor3f(1.0f, 1.0f, 1.0f);
+    immUniform1i("image", 0);
+  }
+
+  immBegin(GPU_PRIM_TRI_FAN, 4);
+
+  rctf preview;
+  rctf canvas;
+
+  BLI_rctf_init(&canvas, 0.0f, 1.0f, 0.0f, 1.0f);
+  BLI_rctf_init(&preview, 0.0f, 1.0f, 0.0f, 1.0f);
+
+  immAttr2f(texCoord, canvas.xmin, canvas.ymin);
+  immVertex2f(pos, preview.xmin, preview.ymin);
+
+  immAttr2f(texCoord, canvas.xmin, canvas.ymax);
+  immVertex2f(pos, preview.xmin, preview.ymax);
+
+  immAttr2f(texCoord, canvas.xmax, canvas.ymax);
+  immVertex2f(pos, preview.xmax, preview.ymax);
+
+  immAttr2f(texCoord, canvas.xmax, canvas.ymin);
+  immVertex2f(pos, preview.xmax, preview.ymin);
+
+  immEnd();
+
+  GPU_texture_unbind(texture);
+  GPU_texture_free(texture);
+
+  if (!glsl_used) {
+    immUnbindProgram();
+  }
+  else {
+    IMB_colormanagement_finish_glsl_draw();
+  }
+
+  if (buffer_cache_handle) {
+    IMB_display_buffer_release(buffer_cache_handle);
+  }
+}
+
 static void playanim_toscreen(
     PlayState *ps, PlayAnimPict *picture, struct ImBuf *ibuf, int fontid, int fstep)
 {
@@ -295,13 +438,6 @@ static void playanim_toscreen(
     printf("%s: no ibuf for picture '%s'\n", __func__, picture ? picture->name : "<NIL>");
     return;
   }
-  if (ibuf->rect == NULL && ibuf->rect_float) {
-    IMB_rect_from_float(ibuf);
-    imb_freerectfloatImBuf(ibuf);
-  }
-  if (ibuf->rect == NULL) {
-    return;
-  }
 
   GHOST_ActivateWindowDrawingContext(g_WS.ghost_window);
 
@@ -331,19 +467,7 @@ static void playanim_toscreen(
                                8);
   }
 
-  IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
-
-  immDrawPixelsTex(&state,
-                   offs_x + (ps->draw_flip[0] ? span_x : 0.0f),
-                   offs_y + (ps->draw_flip[1] ? span_y : 0.0f),
-                   ibuf->x,
-                   ibuf->y,
-                   GPU_RGBA8,
-                   false,
-                   ibuf->rect,
-                   ((ps->draw_flip[0] ? -1.0f : 1.0f)) * (ps->zoom / (float)ps->win_x),
-                   ((ps->draw_flip[1] ? -1.0f : 1.0f)) * (ps->zoom / (float)ps->win_y),
-                   NULL);
+  draw_display_buffer(ps, ibuf);
 
   GPU_blend(GPU_BLEND_NONE);
 
@@ -1178,6 +1302,10 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
 
   ps.fontid = -1;
 
+  STRNCPY(ps.display_settings.display_device,
+          IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_BYTE));
+  IMB_colormanagement_init_default_view_settings(&ps.view_settings, &ps.display_settings);
+
   while (argc > 1) {
     if (argv[1][0] == '-') {
       switch (argv[1][1]) {



More information about the Bf-blender-cvs mailing list