Wireframe: Optimization for intel GPUs.
authorClément Foucault <foucault.clem@gmail.com>
Sun, 3 Jun 2018 13:13:33 +0000 (15:13 +0200)
committerClément Foucault <foucault.clem@gmail.com>
Sun, 3 Jun 2018 13:26:37 +0000 (15:26 +0200)
Intel GPU take more advantage of the geometry shader than other vendors.

Using a simple geom shader approach in this case is more performant.

source/blender/draw/CMakeLists.txt
source/blender/draw/modes/overlay_mode.c
source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl [new file with mode: 0644]
source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl

index 2b6d261..40fd876 100644 (file)
@@ -279,6 +279,7 @@ data_to_c_simple(modes/shaders/edit_normals_geom.glsl SRC)
 data_to_c_simple(modes/shaders/overlay_face_orientation_frag.glsl SRC)
 data_to_c_simple(modes/shaders/overlay_face_orientation_vert.glsl SRC)
 data_to_c_simple(modes/shaders/overlay_face_wireframe_vert.glsl SRC)
+data_to_c_simple(modes/shaders/overlay_face_wireframe_geom.glsl SRC)
 data_to_c_simple(modes/shaders/overlay_face_wireframe_frag.glsl SRC)
 data_to_c_simple(modes/shaders/object_empty_image_frag.glsl SRC)
 data_to_c_simple(modes/shaders/object_empty_image_vert.glsl SRC)
index 5054724..131a9bc 100644 (file)
@@ -28,6 +28,7 @@
 #include "BKE_object.h"
 
 #include "GPU_shader.h"
+#include "GPU_extensions.h"
 #include "DRW_render.h"
 
 #include "draw_mode_engines.h"
@@ -68,6 +69,7 @@ extern char datatoc_overlay_face_orientation_frag_glsl[];
 extern char datatoc_overlay_face_orientation_vert_glsl[];
 
 extern char datatoc_overlay_face_wireframe_vert_glsl[];
+extern char datatoc_overlay_face_wireframe_geom_glsl[];
 extern char datatoc_overlay_face_wireframe_frag_glsl[];
 
 extern struct GlobalsUboStorage ts; /* draw_common.c */
@@ -91,8 +93,13 @@ static void overlay_engine_init(void *vedata)
        }
 
        if (!e_data.face_wireframe_sh) {
+               char *wireframe_geom = NULL;
+               if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) {
+                       wireframe_geom = datatoc_overlay_face_wireframe_geom_glsl;
+               }
                e_data.face_wireframe_sh = DRW_shader_create(
-                       datatoc_overlay_face_wireframe_vert_glsl, NULL,
+                       datatoc_overlay_face_wireframe_vert_glsl,
+                       wireframe_geom,
                        datatoc_overlay_face_wireframe_frag_glsl, NULL);
        }
 }
diff --git a/source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl b/source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl
new file mode 100644 (file)
index 0000000..1cea418
--- /dev/null
@@ -0,0 +1,42 @@
+
+layout(triangles) in;
+layout(triangle_strip, max_vertices = 3) out;
+
+in vec2 ssPos[];
+in float facingOut[];
+
+flat out vec3 ssVec0;
+flat out vec3 ssVec1;
+flat out vec3 ssVec2;
+out float facing;
+
+#define NO_EDGE vec3(10000.0);
+
+vec3 compute_vec(vec2 v0, vec2 v1)
+{
+       vec2 v = normalize(v1 - v0);
+       v = vec2(-v.y, v.x);
+       return vec3(v, -dot(v, v0));
+}
+
+void main(void)
+{
+       vec3 facings = vec3(facingOut[0], facingOut[1], facingOut[2]);
+       bvec3 do_edge = greaterThan(abs(facings), vec3(1.0));
+       facings = fract(facings) - clamp(-sign(facings), 0.0, 1.0);
+
+       ssVec0 = do_edge.x ? compute_vec(ssPos[0], ssPos[1]) : NO_EDGE;
+       ssVec1 = do_edge.y ? compute_vec(ssPos[1], ssPos[2]) : NO_EDGE;
+       ssVec2 = do_edge.z ? compute_vec(ssPos[2], ssPos[0]) : NO_EDGE;
+
+       gl_Position = gl_in[0].gl_Position;
+       facing = facings.x;
+       EmitVertex();
+       gl_Position = gl_in[1].gl_Position;
+       facing = facings.y;
+       EmitVertex();
+       gl_Position = gl_in[2].gl_Position;
+       facing = facings.z;
+       EmitVertex();
+       EndPrimitive();
+}
index 67f4a5c..2cd888e 100644 (file)
@@ -1,3 +1,8 @@
+
+#ifdef GPU_INTEL
+#define USE_GEOM_SHADER
+#endif
+
 uniform mat4 ModelViewProjectionMatrix;
 uniform mat4 ModelViewMatrix;
 uniform mat4 ProjectionMatrix;
@@ -9,10 +14,15 @@ uniform float nearDist;
 uniform samplerBuffer vertData;
 uniform isamplerBuffer faceIds;
 
+#ifdef USE_GEOM_SHADER
+out vec2 ssPos;
+out float facingOut; /* abs(facing) > 1.0 if we do edge */
+#else
 flat out vec3 ssVec0;
 flat out vec3 ssVec1;
 flat out vec3 ssVec2;
 out float facing;
+#endif
 
 /* project to screen space */
 vec2 proj(vec4 pos)
@@ -67,6 +77,21 @@ vec3 get_vertex_pos(int v_id)
 
 void main()
 {
+#ifdef USE_GEOM_SHADER
+       int v_id = texelFetch(faceIds, gl_VertexID).r;
+
+       bool do_edge = v_id < 0;
+       v_id = abs(v_id) - 1;
+
+       vec3 pos = get_vertex_pos(v_id);
+       vec3 nor = get_vertex_nor(v_id);
+       facingOut = normalize(NormalMatrix * nor).z;
+       facingOut += (do_edge) ? ((facingOut > 0.0) ? 2.0 : -2.0) : 0.0;
+
+       gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+       ssPos = proj(gl_Position);
+
+#else
 
        int v_0 = (gl_VertexID / 3) * 3;
        int v_n = gl_VertexID % 3;
@@ -102,5 +127,6 @@ void main()
        gl_Position = p_pos[v_n];
 
        vec3 nor = get_vertex_nor(v_id[v_n]);
-       facing = (NormalMatrix * nor).z;
+       facing = normalize(NormalMatrix * nor).z;
+#endif
 }