Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2020-09-18 20:59:51 +0300
committerClément Foucault <foucault.clem@gmail.com>2020-09-18 23:41:49 +0300
commit649b0ccac8b514b471cdeede97b1a2839c2176b9 (patch)
treec76ff75bb16c3e022d1df201639d407ea531611d /source/blender/gpu
parentf17302be6b716ea5bc6b1ddfd09a2cf3b4969e37 (diff)
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.
Diffstat (limited to 'source/blender/gpu')
-rw-r--r--source/blender/gpu/GPU_state.h1
-rw-r--r--source/blender/gpu/intern/gpu_immediate.cc83
-rw-r--r--source/blender/gpu/intern/gpu_immediate_private.hh9
-rw-r--r--source/blender/gpu/intern/gpu_state.cc7
4 files changed, 100 insertions, 0 deletions
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);