[Bf-blender-cvs] [862ec829422] master: GPUViewport: Use GPUBatch for viewport drawing

Jeroen Bakker noreply at git.blender.org
Thu Apr 9 19:13:43 CEST 2020


Commit: 862ec829422241878b3345661476d8551935aed2
Author: Jeroen Bakker
Date:   Thu Apr 9 07:51:51 2020 +0200
Branches: master
https://developer.blender.org/rB862ec829422241878b3345661476d8551935aed2

GPUViewport: Use GPUBatch for viewport drawing

When drawing the viewport to the screen the draw calls were not batched.
This resulted in measurable slowdown on Windows Intel 10th gen
platforms.

This patch would cache the last draw calls per viewport. Our API does
support partial redrawing of the viewport, but that isn't used anywhere.

This patch does not include stereoscopy rendering. This still uses the
imm approach and would still be slow on certain hardware.

Reviewed By: Clément Foucault

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

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

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

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

diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index b2e1cb17946..fdbfa16a365 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -65,6 +65,24 @@ typedef struct ViewportTempTexture {
   GPUTexture *texture;
 } ViewportTempTexture;
 
+/* Struct storing a viewport specific GPUBatch.
+ * The end-goal is to have a single batch shared across viewport and use a model matrix to place
+ * the batch. Due to OCIO and Image/UV editor we are not able to use an model matrix yet. */
+struct GPUViewportBatch {
+  GPUBatch *batch;
+  struct {
+    rctf rect_pos;
+    rctf rect_uv;
+  } last_used_parameters;
+} GPUViewportBatch;
+
+static struct {
+  GPUVertFormat format;
+  struct {
+    uint pos, tex_coord;
+  } attr_id;
+} g_viewport = {{0}};
+
 struct GPUViewport {
   int size[2];
   int flag;
@@ -97,6 +115,7 @@ struct GPUViewport {
   /* TODO(fclem) the uvimage display use the viewport but do not set any view transform for the
    * moment. The end goal would be to let the GPUViewport do the color management. */
   bool do_color_management;
+  struct GPUViewportBatch batch;
 };
 
 enum {
@@ -625,6 +644,76 @@ void GPU_viewport_stereo_composite(GPUViewport *viewport, Stereo3dFormat *stereo
 
   GPU_framebuffer_restore();
 }
+/* -------------------------------------------------------------------- */
+/** \name Viewport Batches
+ * \{ */
+
+static GPUVertFormat *gpu_viewport_batch_format(void)
+{
+  if (g_viewport.format.attr_len == 0) {
+    GPUVertFormat *format = &g_viewport.format;
+    g_viewport.attr_id.pos = GPU_vertformat_attr_add(
+        format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+    g_viewport.attr_id.tex_coord = GPU_vertformat_attr_add(
+        format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+  }
+  return &g_viewport.format;
+}
+
+static GPUBatch *gpu_viewport_batch_create(const rctf *rect_pos, const rctf *rect_uv)
+{
+  GPUVertBuf *vbo = GPU_vertbuf_create_with_format(gpu_viewport_batch_format());
+  const uint vbo_len = 4;
+  GPU_vertbuf_data_alloc(vbo, vbo_len);
+
+  GPUVertBufRaw pos_step, tex_coord_step;
+  GPU_vertbuf_attr_get_raw_data(vbo, g_viewport.attr_id.pos, &pos_step);
+  GPU_vertbuf_attr_get_raw_data(vbo, g_viewport.attr_id.tex_coord, &tex_coord_step);
+
+  copy_v2_fl2(GPU_vertbuf_raw_step(&pos_step), rect_pos->xmin, rect_pos->ymin);
+  copy_v2_fl2(GPU_vertbuf_raw_step(&tex_coord_step), rect_uv->xmin, rect_uv->ymin);
+  copy_v2_fl2(GPU_vertbuf_raw_step(&pos_step), rect_pos->xmax, rect_pos->ymin);
+  copy_v2_fl2(GPU_vertbuf_raw_step(&tex_coord_step), rect_uv->xmax, rect_uv->ymin);
+  copy_v2_fl2(GPU_vertbuf_raw_step(&pos_step), rect_pos->xmin, rect_pos->ymax);
+  copy_v2_fl2(GPU_vertbuf_raw_step(&tex_coord_step), rect_uv->xmin, rect_uv->ymax);
+  copy_v2_fl2(GPU_vertbuf_raw_step(&pos_step), rect_pos->xmax, rect_pos->ymax);
+  copy_v2_fl2(GPU_vertbuf_raw_step(&tex_coord_step), rect_uv->xmax, rect_uv->ymax);
+
+  return GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
+}
+
+static GPUBatch *gpu_viewport_batch_get(GPUViewport *viewport,
+                                        const rctf *rect_pos,
+                                        const rctf *rect_uv)
+{
+  const float compare_limit = 0.0001f;
+  const bool parameters_changed =
+      (!BLI_rctf_compare(
+           &viewport->batch.last_used_parameters.rect_pos, rect_pos, compare_limit) ||
+       !BLI_rctf_compare(&viewport->batch.last_used_parameters.rect_uv, rect_uv, compare_limit));
+
+  if (viewport->batch.batch && parameters_changed) {
+    GPU_batch_discard(viewport->batch.batch);
+    viewport->batch.batch = NULL;
+  }
+
+  if (!viewport->batch.batch) {
+    viewport->batch.batch = gpu_viewport_batch_create(rect_pos, rect_uv);
+    viewport->batch.last_used_parameters.rect_pos = *rect_pos;
+    viewport->batch.last_used_parameters.rect_uv = *rect_uv;
+  }
+  return viewport->batch.batch;
+}
+
+static void gpu_viewport_batch_free(GPUViewport *viewport)
+{
+  if (viewport->batch.batch) {
+    GPU_batch_discard(viewport->batch.batch);
+    viewport->batch.batch = NULL;
+  }
+}
+
+/** \} */
 
 static void gpu_viewport_draw_colormanaged(GPUViewport *viewport,
                                            const rctf *rect_pos,
@@ -635,10 +724,6 @@ static void gpu_viewport_draw_colormanaged(GPUViewport *viewport,
   GPUTexture *color = dtxl->color;
   GPUTexture *color_overlay = dtxl->color_overlay;
 
-  GPUVertFormat *vert_format = immVertexFormat();
-  uint pos = GPU_vertformat_attr_add(vert_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-  uint texco = GPU_vertformat_attr_add(vert_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
   bool use_ocio = false;
 
   if (viewport->do_color_management && display_colorspace) {
@@ -650,38 +735,26 @@ static void gpu_viewport_draw_colormanaged(GPUViewport *viewport,
                                                               true);
   }
 
-  if (!use_ocio) {
-    immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE);
-    immUniform1i("display_transform", display_colorspace);
-    immUniform1i("image_texture", 0);
-    immUniform1i("overlays_texture", 1);
+  GPUBatch *batch = gpu_viewport_batch_get(viewport, rect_pos, rect_uv);
+  if (use_ocio) {
+    GPU_batch_program_set_imm_shader(batch);
+  }
+  else {
+    GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE);
+    GPU_batch_uniform_1i(batch, "display_transform", display_colorspace);
+    GPU_batch_uniform_1i(batch, "image_texture", 0);
+    GPU_batch_uniform_1i(batch, "overlays_texture", 1);
   }
 
   GPU_texture_bind(color, 0);
   GPU_texture_bind(color_overlay, 1);
-
-  immBegin(GPU_PRIM_TRI_STRIP, 4);
-
-  immAttr2f(texco, rect_uv->xmin, rect_uv->ymin);
-  immVertex2f(pos, rect_pos->xmin, rect_pos->ymin);
-  immAttr2f(texco, rect_uv->xmax, rect_uv->ymin);
-  immVertex2f(pos, rect_pos->xmax, rect_pos->ymin);
-  immAttr2f(texco, rect_uv->xmin, rect_uv->ymax);
-  immVertex2f(pos, rect_pos->xmin, rect_pos->ymax);
-  immAttr2f(texco, rect_uv->xmax, rect_uv->ymax);
-  immVertex2f(pos, rect_pos->xmax, rect_pos->ymax);
-
-  immEnd();
-
+  GPU_batch_draw(batch);
   GPU_texture_unbind(color);
   GPU_texture_unbind(color_overlay);
 
   if (use_ocio) {
     IMB_colormanagement_finish_glsl_draw();
   }
-  else {
-    immUnbindProgram();
-  }
 }
 
 /**
@@ -745,8 +818,8 @@ void GPU_viewport_draw_to_screen_ex(GPUViewport *viewport,
  * Merge and draw the buffers of \a viewport into the currently active framebuffer, performing
  * color transform to display space.
  *
- * \param rect: Coordinates to draw into. By swapping min and max values, drawing can be done with
- *              inversed axis coordinates (upside down or sideways).
+ * \param rect: Coordinates to draw into. By swapping min and max values, drawing can be done
+ * with inversed axis coordinates (upside down or sideways).
  */
 void GPU_viewport_draw_to_screen(GPUViewport *viewport, int view, const rcti *rect)
 {
@@ -923,5 +996,7 @@ void GPU_viewport_free(GPUViewport *viewport)
   DRW_instance_data_list_free(viewport->idatalist);
   MEM_freeN(viewport->idatalist);
 
+  gpu_viewport_batch_free(viewport);
+
   MEM_freeN(viewport);
 }



More information about the Bf-blender-cvs mailing list