[Bf-blender-cvs] [8f0e06a0ca1] master: Metal: GPU_PRIM_LINE_LOOP alternative implementations.

Jason Fielder noreply at git.blender.org
Thu Apr 14 12:05:04 CEST 2022


Commit: 8f0e06a0ca1f4b7f8ea00ec5346a5e55a2620707
Author: Jason Fielder
Date:   Thu Apr 14 12:01:16 2022 +0200
Branches: master
https://developer.blender.org/rB8f0e06a0ca1f4b7f8ea00ec5346a5e55a2620707

Metal: GPU_PRIM_LINE_LOOP alternative implementations.

Prefer using immVertex3f when 3D shaders are used for 2D rendering due to overhead of vertex padding in hardware. CPU overhead is negligible.

Authored by Apple: Michael Parkin-White

Ref T96261

Reviewed By: fclem

Maniphest Tasks: T96261

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

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

M	source/blender/blenlib/intern/math_base_inline.c
M	source/blender/editors/gizmo_library/gizmo_draw_utils.c
M	source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c
M	source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c
M	source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c
M	source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c
M	source/blender/gpu/GPU_immediate_util.h
M	source/blender/gpu/intern/gpu_immediate_util.c

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

diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c
index bb6bc0db00d..a983821f15e 100644
--- a/source/blender/blenlib/intern/math_base_inline.c
+++ b/source/blender/blenlib/intern/math_base_inline.c
@@ -524,6 +524,15 @@ MINLINE uint max_uu(uint a, uint b)
   return (b < a) ? a : b;
 }
 
+MINLINE unsigned long long min_ulul(unsigned long long a, unsigned long long b)
+{
+  return (a < b) ? a : b;
+}
+MINLINE unsigned long long max_ulul(unsigned long long a, unsigned long long b)
+{
+  return (b < a) ? a : b;
+}
+
 MINLINE float min_fff(float a, float b, float c)
 {
   return min_ff(min_ff(a, b), c);
diff --git a/source/blender/editors/gizmo_library/gizmo_draw_utils.c b/source/blender/editors/gizmo_library/gizmo_draw_utils.c
index 8d2aec18451..c6303c197e7 100644
--- a/source/blender/editors/gizmo_library/gizmo_draw_utils.c
+++ b/source/blender/editors/gizmo_library/gizmo_draw_utils.c
@@ -82,9 +82,35 @@ void wm_gizmo_vec_draw(
     const float color[4], const float (*verts)[3], uint vert_count, uint pos, uint primitive_type)
 {
   immUniformColor4fv(color);
-  immBegin(primitive_type, vert_count);
-  for (int i = 0; i < vert_count; i++) {
-    immVertex3fv(pos, verts[i]);
+
+  if (primitive_type == GPU_PRIM_LINE_LOOP) {
+    /* Line loop alternative for Metal/Vulkan. */
+    immBegin(GPU_PRIM_LINES, vert_count * 2);
+    immVertex3fv(pos, verts[0]);
+    for (int i = 1; i < vert_count; i++) {
+      immVertex3fv(pos, verts[i]);
+      immVertex3fv(pos, verts[i]);
+    }
+    immVertex3fv(pos, verts[0]);
+    immEnd();
+  }
+  else if (primitive_type == GPU_PRIM_TRI_FAN) {
+    /* Note(Metal): Tri-fan alternative for Metal. Triangle List is more efficient for small
+     * primitive counts. */
+    int tri_count = vert_count - 2;
+    immBegin(GPU_PRIM_TRIS, tri_count * 3);
+    for (int i = 0; i < tri_count; i++) {
+      immVertex3fv(pos, verts[0]);
+      immVertex3fv(pos, verts[i + 1]);
+      immVertex3fv(pos, verts[i + 2]);
+    }
+    immEnd();
+  }
+  else {
+    immBegin(primitive_type, vert_count);
+    for (int i = 0; i < vert_count; i++) {
+      immVertex3fv(pos, verts[i]);
+    }
+    immEnd();
   }
-  immEnd();
 }
diff --git a/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c
index 5e20cc73f1a..b326d6d1859 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c
@@ -74,20 +74,21 @@ static void button2d_geom_draw_backdrop(const wmGizmo *gz,
   GPU_viewport_size_get_f(viewport);
 
   GPUVertFormat *format = immVertexFormat();
-  uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+  /* Note(Metal): Prefer 3D coordinate for 2D rendering when using 3D shader. */
+  uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
 
   /* TODO: other draw styles. */
   if (color[3] == 1.0 && fill_alpha == 1.0 && select == false) {
     immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
     immUniformColor4fv(color);
-    imm_draw_circle_fill_2d(pos, 0, 0, 1.0f, CIRCLE_RESOLUTION);
+    imm_draw_circle_fill_3d(pos, 0.0f, 0.0f, 1.0f, CIRCLE_RESOLUTION);
     immUnbindProgram();
 
     immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
     immUniform2fv("viewportSize", &viewport[2]);
     immUniform1f("lineWidth", gz->line_width * U.pixelsize);
     immUniformColor4fv(color);
-    imm_draw_circle_wire_2d(pos, 0, 0, 1.0f, CIRCLE_RESOLUTION);
+    imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, 1.0f, CIRCLE_RESOLUTION);
     immUnbindProgram();
   }
   else {
@@ -96,7 +97,7 @@ static void button2d_geom_draw_backdrop(const wmGizmo *gz,
       const float fill_color[4] = {UNPACK3(color), fill_alpha * color[3]};
       immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
       immUniformColor4fv(fill_color);
-      imm_draw_circle_fill_2d(pos, 0, 0, 1.0f, CIRCLE_RESOLUTION);
+      imm_draw_circle_fill_3d(pos, 0.0f, 0.0f, 1.0f, CIRCLE_RESOLUTION);
       immUnbindProgram();
     }
 
@@ -106,7 +107,7 @@ static void button2d_geom_draw_backdrop(const wmGizmo *gz,
       immUniform2fv("viewportSize", &viewport[2]);
       immUniform1f("lineWidth", gz->line_width * U.pixelsize);
       immUniformColor4fv(color);
-      imm_draw_circle_wire_2d(pos, 0, 0, 1.0f, CIRCLE_RESOLUTION);
+      imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, 1.0f, CIRCLE_RESOLUTION);
       immUnbindProgram();
     }
   }
diff --git a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c
index 4c54aa10c33..e4cb6d149f5 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c
@@ -99,7 +99,8 @@ static void cage2d_draw_box_corners(const rctf *r,
                                     const float color[3],
                                     const float line_width)
 {
-  uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+  /* Note(Metal): Prefer using 3D coordinates with 3D shader, even if rendering 2D gizmo's. */
+  uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
 
   immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
   immUniformColor3fv(color);
@@ -112,25 +113,25 @@ static void cage2d_draw_box_corners(const rctf *r,
 
   immBegin(GPU_PRIM_LINES, 16);
 
-  immVertex2f(pos, r->xmin, r->ymin + margin[1]);
-  immVertex2f(pos, r->xmin, r->ymin);
-  immVertex2f(pos, r->xmin, r->ymin);
-  immVertex2f(pos, r->xmin + margin[0], r->ymin);
+  immVertex3f(pos, r->xmin, r->ymin + margin[1], 0.0f);
+  immVertex3f(pos, r->xmin, r->ymin, 0.0f);
+  immVertex3f(pos, r->xmin, r->ymin, 0.0f);
+  immVertex3f(pos, r->xmin + margin[0], r->ymin, 0.0f);
 
-  immVertex2f(pos, r->xmax, r->ymin + margin[1]);
-  immVertex2f(pos, r->xmax, r->ymin);
-  immVertex2f(pos, r->xmax, r->ymin);
-  immVertex2f(pos, r->xmax - margin[0], r->ymin);
+  immVertex3f(pos, r->xmax, r->ymin + margin[1], 0.0f);
+  immVertex3f(pos, r->xmax, r->ymin, 0.0f);
+  immVertex3f(pos, r->xmax, r->ymin, 0.0f);
+  immVertex3f(pos, r->xmax - margin[0], r->ymin, 0.0f);
 
-  immVertex2f(pos, r->xmax, r->ymax - margin[1]);
-  immVertex2f(pos, r->xmax, r->ymax);
-  immVertex2f(pos, r->xmax, r->ymax);
-  immVertex2f(pos, r->xmax - margin[0], r->ymax);
+  immVertex3f(pos, r->xmax, r->ymax - margin[1], 0.0f);
+  immVertex3f(pos, r->xmax, r->ymax, 0.0f);
+  immVertex3f(pos, r->xmax, r->ymax, 0.0f);
+  immVertex3f(pos, r->xmax - margin[0], r->ymax, 0.0f);
 
-  immVertex2f(pos, r->xmin, r->ymax - margin[1]);
-  immVertex2f(pos, r->xmin, r->ymax);
-  immVertex2f(pos, r->xmin, r->ymax);
-  immVertex2f(pos, r->xmin + margin[0], r->ymax);
+  immVertex3f(pos, r->xmin, r->ymax - margin[1], 0.0f);
+  immVertex3f(pos, r->xmin, r->ymax, 0.0f);
+  immVertex3f(pos, r->xmin, r->ymax, 0.0f);
+  immVertex3f(pos, r->xmin + margin[0], r->ymax, 0.0f);
 
   immEnd();
 
@@ -440,12 +441,35 @@ static void cage2d_draw_box_interaction(const float color[4],
 static void imm_draw_point_aspect_2d(
     uint pos, float x, float y, float rad_x, float rad_y, bool solid)
 {
-  immBegin(solid ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, 4);
-  immVertex2f(pos, x - rad_x, y - rad_y);
-  immVertex2f(pos, x - rad_x, y + rad_y);
-  immVertex2f(pos, x + rad_x, y + rad_y);
-  immVertex2f(pos, x + rad_x, y - rad_y);
-  immEnd();
+  if (solid) {
+    /* Note(Metal/AMD): Small Triangle-list primitives more optimal for GPU HW than Trianglestrip.
+     */
+    immBegin(GPU_PRIM_TRIS, 6);
+    immVertex2f(pos, x - rad_x, y - rad_y);
+    immVertex2f(pos, x - rad_x, y + rad_y);
+    immVertex2f(pos, x + rad_x, y + rad_y);
+
+    immVertex2f(pos, x - rad_x, y - rad_y);
+    immVertex2f(pos, x + rad_x, y + rad_y);
+    immVertex2f(pos, x + rad_x, y - rad_y);
+    immEnd();
+  }
+  else {
+    /* Note(Metal/AMD): Small Line-list primitives more optimal for GPU HW than Linestrip. */
+    immBegin(GPU_PRIM_LINES, 8);
+    immVertex2f(pos, x - rad_x, y - rad_y);
+    immVertex2f(pos, x - rad_x, y + rad_y);
+
+    immVertex2f(pos, x - rad_x, y + rad_y);
+    immVertex2f(pos, x + rad_x, y + rad_y);
+
+    immVertex2f(pos, x + rad_x, y + rad_y);
+    immVertex2f(pos, x + rad_x, y - rad_y);
+
+    immVertex2f(pos, x + rad_x, y - rad_y);
+    immVertex2f(pos, x - rad_x, y - rad_y);
+    immEnd();
+  }
 }
 
 static void cage2d_draw_circle_wire(const rctf *r,
@@ -455,7 +479,9 @@ static void cage2d_draw_circle_wire(const rctf *r,
                                     const int draw_options,
                                     const float line_width)
 {
-  uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+  /* Note(Metal): Prefer using 3D coordinates with 3D shader input, even if rendering 2D gizmo's.
+   */
+  uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
 
   immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
   immUniformColor3fv(color);
@@ -465,17 +491,28 @@ static void cage2d_draw_circle_wire(const rctf *r,
   immUniform2fv("viewportSize", &viewport[2]);
   immUniform1f("lineWidth", line_width * U.pixelsize);
 
-  immBegin(GPU_PRIM_LINE_LOOP, 4);
-  immVertex2f(pos, r->xmin, r->ymin);
-  immVertex2f(pos, r->xmax, r->ymin);
-  immVertex2f(pos, r->xmax, r->ymax);
-  immVertex2f(pos, r->xmin, r->ymax);
+  /* Small 'lines' primitives more efficient for hardware processing than linestrip. */
+  immBegin(GPU_PRIM_LINES, 8);
+  immVertex3f(pos, r->xmin, r->ymin, 0.0f);
+  immVertex3f(pos, r->xmax, r->ymin, 0.0f);
+
+  immVertex3f(pos, r->xmax, r->ymin, 0.0f);
+  immVertex3f(pos, r->xmax, r->ymax, 0.0f);
+
+  immVertex3f(pos, r->xmax, r->ymax, 0.0f);
+  immVertex3f(pos, r->xmin, r->ymax, 0.0f);
+
+  immVertex3f(pos, r->xmin, r->ymax, 0.0f);
+  immVertex3f(pos, r->xmin, r->ymin, 0.0f);
   immEnd();
 
   if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE) {
-    immBegin(GPU_PRIM_LINE_LOOP, 2);
-    immVertex2f(pos, BLI_rctf_cent_x(r), r->ymax);
-    immVer

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list