[Bf-blender-cvs] [649b0ccac8b] master: GPUImmediate: Add system wide workaround for wide line

Clément Foucault noreply at git.blender.org
Fri Sep 18 22:41:53 CEST 2020


Commit: 649b0ccac8b514b471cdeede97b1a2839c2176b9
Author: Clément Foucault
Date:   Fri Sep 18 19:59:51 2020 +0200
Branches: master
https://developer.blender.org/rB649b0ccac8b514b471cdeede97b1a2839c2176b9

GPUImmediate: Add system wide workaround for wide line

This makes wide line supported on MacOS and other implementation that
does not support wide line by default.

This workaround works for all Line types but only if using one of the 5
default shaders.

The workaround is completely isolated and invisible to the outside. It has
no side effect.

Note: This does not affect the GPUBatch drawing.

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

M	source/blender/gpu/GPU_state.h
M	source/blender/gpu/intern/gpu_immediate.cc
M	source/blender/gpu/intern/gpu_immediate_private.hh
M	source/blender/gpu/intern/gpu_state.cc

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

diff --git a/source/blender/gpu/GPU_state.h b/source/blender/gpu/GPU_state.h
index a857736acd5..04cf7bc54ba 100644
--- a/source/blender/gpu/GPU_state.h
+++ b/source/blender/gpu/GPU_state.h
@@ -156,6 +156,7 @@ eGPUDepthTest GPU_depth_test_get(void);
 eGPUWriteMask GPU_write_mask_get(void);
 uint GPU_stencil_mask_get(void);
 eGPUStencilTest GPU_stencil_test_get(void);
+float GPU_line_width_get(void);
 
 void GPU_flush(void);
 void GPU_finish(void);
diff --git a/source/blender/gpu/intern/gpu_immediate.cc b/source/blender/gpu/intern/gpu_immediate.cc
index 8d781978857..38d206ec3ad 100644
--- a/source/blender/gpu/intern/gpu_immediate.cc
+++ b/source/blender/gpu/intern/gpu_immediate.cc
@@ -62,6 +62,7 @@ void immBindShader(GPUShader *shader)
   BLI_assert(imm->shader == NULL);
 
   imm->shader = shader;
+  imm->builtin_shader_bound = GPU_SHADER_TEXT; /* Default value. */
 
   if (!imm->vertex_format.packed) {
     VertexFormat_pack(&imm->vertex_format);
@@ -77,6 +78,7 @@ void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
 {
   GPUShader *shader = GPU_shader_get_builtin_shader(shader_id);
   immBindShader(shader);
+  imm->builtin_shader_bound = shader_id;
 }
 
 void immUnbindProgram(void)
@@ -122,11 +124,88 @@ static bool vertex_count_makes_sense_for_primitive(uint vertex_len, GPUPrimType
 }
 #endif
 
+/* -------------------------------------------------------------------- */
+/** \name Wide line workaround
+ *
+ * Some systems do not support wide lines.
+ * We workaround this by using specialized shaders.
+ * \{ */
+
+static void wide_line_workaround_start(GPUPrimType prim_type)
+{
+  if (!ELEM(prim_type, GPU_PRIM_LINES, GPU_PRIM_LINE_STRIP, GPU_PRIM_LINE_LOOP)) {
+    return;
+  }
+
+  float line_width = GPU_line_width_get();
+
+  if (line_width == 1.0f) {
+    /* No need to change the shader. */
+    return;
+  }
+
+  eGPUBuiltinShader polyline_sh;
+  switch (imm->builtin_shader_bound) {
+    case GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR:
+      polyline_sh = GPU_SHADER_3D_POLYLINE_CLIPPED_UNIFORM_COLOR;
+      break;
+    case GPU_SHADER_2D_UNIFORM_COLOR:
+    case GPU_SHADER_3D_UNIFORM_COLOR:
+      polyline_sh = GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR;
+      break;
+    case GPU_SHADER_2D_FLAT_COLOR:
+    case GPU_SHADER_3D_FLAT_COLOR:
+      polyline_sh = GPU_SHADER_3D_POLYLINE_FLAT_COLOR;
+      break;
+    case GPU_SHADER_2D_SMOOTH_COLOR:
+    case GPU_SHADER_3D_SMOOTH_COLOR:
+      polyline_sh = GPU_SHADER_3D_POLYLINE_SMOOTH_COLOR;
+      break;
+    default:
+      /* Cannot replace the current shader with a polyline shader. */
+      return;
+  }
+
+  imm->prev_shader = imm->shader;
+
+  immUnbindProgram();
+
+  /* TODO(fclem) Don't use geometry shader and use quad instancing with double load. */
+  // GPU_vertformat_multiload_enable(imm->vertex_format, 2);
+
+  immBindBuiltinProgram(polyline_sh);
+
+  float viewport[4];
+  GPU_viewport_size_get_f(viewport);
+  immUniform2fv("viewportSize", &viewport[2]);
+  immUniform1f("lineWidth", line_width);
+
+  if (ELEM(polyline_sh,
+           GPU_SHADER_3D_POLYLINE_CLIPPED_UNIFORM_COLOR,
+           GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR)) {
+    immUniformColor4fv(imm->uniform_color);
+  }
+}
+
+static void wide_line_workaround_end(void)
+{
+  if (imm->prev_shader) {
+    immUnbindProgram();
+
+    immBindShader(imm->prev_shader);
+    imm->prev_shader = NULL;
+  }
+}
+
+/** \} */
+
 void immBegin(GPUPrimType prim_type, uint vertex_len)
 {
   BLI_assert(imm->prim_type == GPU_PRIM_NONE); /* Make sure we haven't already begun. */
   BLI_assert(vertex_count_makes_sense_for_primitive(vertex_len, prim_type));
 
+  wide_line_workaround_start(prim_type);
+
   imm->prim_type = prim_type;
   imm->vertex_len = vertex_len;
   imm->vertex_idx = 0;
@@ -201,6 +280,8 @@ void immEnd(void)
   imm->prim_type = GPU_PRIM_NONE;
   imm->strict_vertex_len = true;
   imm->vertex_data = NULL;
+
+  wide_line_workaround_end();
 }
 
 static void setAttrValueBit(uint attr_id)
@@ -549,6 +630,8 @@ void immUniformColor4f(float r, float g, float b, float a)
   BLI_assert(uniform_loc != -1);
   float data[4] = {r, g, b, a};
   GPU_shader_uniform_vector(imm->shader, uniform_loc, 4, 1, data);
+  /* For wide Line workaround. */
+  copy_v4_v4(imm->uniform_color, data);
 }
 
 void immUniformColor4fv(const float rgba[4])
diff --git a/source/blender/gpu/intern/gpu_immediate_private.hh b/source/blender/gpu/intern/gpu_immediate_private.hh
index 38db8131942..b867a85bb8b 100644
--- a/source/blender/gpu/intern/gpu_immediate_private.hh
+++ b/source/blender/gpu/intern/gpu_immediate_private.hh
@@ -55,6 +55,15 @@ class Immediate {
   /** Batch in construction when using immBeginBatch. */
   GPUBatch *batch = NULL;
 
+  /** Wide Line workaround. */
+
+  /** Previously bound shader to restore after drawing. */
+  GPUShader *prev_shader = NULL;
+  /** Builtin shader index. Used to test if the workaround can be done. */
+  eGPUBuiltinShader builtin_shader_bound = GPU_SHADER_TEXT;
+  /** Uniform color: Kept here to update the wideline shader just before immBegin. */
+  float uniform_color[4];
+
  public:
   Immediate(){};
   virtual ~Immediate(){};
diff --git a/source/blender/gpu/intern/gpu_state.cc b/source/blender/gpu/intern/gpu_state.cc
index 1dc8b106029..9621aeeda7c 100644
--- a/source/blender/gpu/intern/gpu_state.cc
+++ b/source/blender/gpu/intern/gpu_state.cc
@@ -258,6 +258,13 @@ eGPUStencilTest GPU_stencil_test_get()
   return (eGPUStencilTest)state.stencil_test;
 }
 
+/* NOTE: Already premultiplied by U.pixelsize. */
+float GPU_line_width_get(void)
+{
+  GPUStateMutable &state = Context::get()->state_manager->mutable_state;
+  return state.line_width;
+}
+
 void GPU_scissor_get(int coords[4])
 {
   Context::get()->active_fb->scissor_get(coords);



More information about the Bf-blender-cvs mailing list