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:
authorGermano Cavalcante <germano.costa@ig.com.br>2020-02-23 23:30:27 +0300
committerGermano Cavalcante <germano.costa@ig.com.br>2020-02-24 14:01:22 +0300
commit001f7c92d1452e01622f066d37bd42545b650a27 (patch)
treec31f0067b2b6399b7c2b2f55ded1af244e67e248 /source/blender/gpu
parenta31bd3f7b5cf27166ccdf3b33890533c5366eb4f (diff)
BLF: Optimize text rendering and caching
The current code allocates and transfers a lot of memory to the GPU, but only a small portion of this memory is actually used. In addition, the code calls many costly gl operations during the caching process. This commit significantly reduce the amount of memory by allocating and transferring a flat array without pads to the GPU. It also calls as little as possible the gl operations during the cache. This code also simulate a billinear filter `GL_LINEAR` using a 1D texture. **Average drawing time:** |before:|0.00003184 sec |now:|0.00001943 sec |fac:|1.6385156675048407 **5 worst times:** |before:|[0.001075, 0.001433, 0.002143, 0.002915, 0.003242] |now:|[0.00094, 0.000993, 0.001502, 0.002284, 0.002328] Differential Revision: https://developer.blender.org/D6886
Diffstat (limited to 'source/blender/gpu')
-rw-r--r--source/blender/gpu/shaders/gpu_shader_text_frag.glsl119
-rw-r--r--source/blender/gpu/shaders/gpu_shader_text_vert.glsl21
2 files changed, 105 insertions, 35 deletions
diff --git a/source/blender/gpu/shaders/gpu_shader_text_frag.glsl b/source/blender/gpu/shaders/gpu_shader_text_frag.glsl
index f9f195c31d6..554596fa9ae 100644
--- a/source/blender/gpu/shaders/gpu_shader_text_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_text_frag.glsl
@@ -1,9 +1,13 @@
flat in vec4 color_flat;
noperspective in vec2 texCoord_interp;
+flat in int glyph_offset;
+flat in ivec2 glyph_dim;
+flat in int interp_size;
+
out vec4 fragColor;
-uniform sampler2D glyph;
+uniform sampler1DArray glyph;
const vec2 offsets4[4] = vec2[4](
vec2(-0.5, 0.5), vec2(0.5, 0.5), vec2(-0.5, -0.5), vec2(-0.5, -0.5));
@@ -25,54 +29,107 @@ const vec2 offsets16[16] = vec2[16](vec2(-1.5, 1.5),
vec2(0.5, -1.5),
vec2(1.5, -1.5));
-#define sample_glyph_offset(texco, texel, ofs) texture(glyph, texco + ofs * texel).r
+//#define GPU_NEAREST
+#define sample_glyph_offset(texel, ofs) texture_1D_custom_bilinear_filter(texCoord_interp + ofs * texel)
+
+float texel_fetch(int index)
+{
+ int size_x = textureSize(glyph, 0).r;
+ if (index >= size_x) {
+ return texelFetch(glyph, ivec2(index % size_x, index / size_x), 0).r;
+ }
+ return texelFetch(glyph, ivec2(index, 0), 0).r;
+}
+
+bool is_inside_box(ivec2 v)
+{
+ return all(greaterThanEqual(v, ivec2(0))) && all(lessThan(v, glyph_dim));
+}
+
+float texture_1D_custom_bilinear_filter(vec2 uv)
+{
+ vec2 texel_2d = uv * glyph_dim + 0.5;
+ ivec2 texel_2d_near = ivec2(texel_2d) - 1;
+ int frag_offset = glyph_offset + texel_2d_near.y * glyph_dim.x + texel_2d_near.x;
+
+ float tl = 0.0;
+
+ if (is_inside_box(texel_2d_near)) {
+ tl = texel_fetch(frag_offset);
+ }
+
+#ifdef GPU_NEAREST
+ return tl;
+#else //GPU_LINEAR
+ int offset_x = 1;
+ int offset_y = glyph_dim.x;
+
+ float tr = 0.0;
+ float bl = 0.0;
+ float br = 0.0;
+
+ if (is_inside_box(texel_2d_near + ivec2(1, 0))) {
+ tr = texel_fetch(frag_offset + offset_x);
+ }
+ if (is_inside_box(texel_2d_near + ivec2(0, 1))) {
+ bl = texel_fetch(frag_offset + offset_y);
+ }
+ if (is_inside_box(texel_2d_near + ivec2(1, 1))) {
+ br = texel_fetch(frag_offset + offset_x + offset_y);
+ }
+
+ vec2 f = fract(texel_2d);
+ float tA = mix(tl, tr, f.x);
+ float tB = mix(bl, br, f.x);
+
+ return mix(tA, tB, f.y);
+#endif
+}
void main()
{
// input color replaces texture color
fragColor.rgb = color_flat.rgb;
- vec2 texel = 1.0 / vec2(textureSize(glyph, 0));
- vec2 texco = abs(texCoord_interp);
-
// modulate input alpha & texture alpha
- if (texCoord_interp.x > 0) {
- fragColor.a = texture(glyph, texco).r;
+ if (interp_size == 0) {
+ fragColor.a = texture_1D_custom_bilinear_filter(texCoord_interp);
}
else {
+ vec2 texel = 1.0 / glyph_dim;
fragColor.a = 0.0;
- if (texCoord_interp.y > 0) {
+ if (interp_size == 1) {
/* 3x3 blur */
/* Manual unroll for perf. (stupid glsl compiler) */
- fragColor.a += sample_glyph_offset(texco, texel, offsets4[0]);
- fragColor.a += sample_glyph_offset(texco, texel, offsets4[1]);
- fragColor.a += sample_glyph_offset(texco, texel, offsets4[2]);
- fragColor.a += sample_glyph_offset(texco, texel, offsets4[3]);
+ fragColor.a += sample_glyph_offset(texel, offsets4[0]);
+ fragColor.a += sample_glyph_offset(texel, offsets4[1]);
+ fragColor.a += sample_glyph_offset(texel, offsets4[2]);
+ fragColor.a += sample_glyph_offset(texel, offsets4[3]);
fragColor.a *= (1.0 / 4.0);
}
else {
/* 5x5 blur */
/* Manual unroll for perf. (stupid glsl compiler) */
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[0]);
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[1]);
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[2]);
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[3]);
-
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[4]);
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[5]) * 2.0;
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[6]) * 2.0;
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[7]);
-
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[8]);
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[9]) * 2.0;
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[10]) * 2.0;
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[11]);
-
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[12]);
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[13]);
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[14]);
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[15]);
+ fragColor.a += sample_glyph_offset(texel, offsets16[0]);
+ fragColor.a += sample_glyph_offset(texel, offsets16[1]);
+ fragColor.a += sample_glyph_offset(texel, offsets16[2]);
+ fragColor.a += sample_glyph_offset(texel, offsets16[3]);
+
+ fragColor.a += sample_glyph_offset(texel, offsets16[4]);
+ fragColor.a += sample_glyph_offset(texel, offsets16[5]) * 2.0;
+ fragColor.a += sample_glyph_offset(texel, offsets16[6]) * 2.0;
+ fragColor.a += sample_glyph_offset(texel, offsets16[7]);
+
+ fragColor.a += sample_glyph_offset(texel, offsets16[8]);
+ fragColor.a += sample_glyph_offset(texel, offsets16[9]) * 2.0;
+ fragColor.a += sample_glyph_offset(texel, offsets16[10]) * 2.0;
+ fragColor.a += sample_glyph_offset(texel, offsets16[11]);
+
+ fragColor.a += sample_glyph_offset(texel, offsets16[12]);
+ fragColor.a += sample_glyph_offset(texel, offsets16[13]);
+ fragColor.a += sample_glyph_offset(texel, offsets16[14]);
+ fragColor.a += sample_glyph_offset(texel, offsets16[15]);
fragColor.a *= (1.0 / 20.0);
}
}
diff --git a/source/blender/gpu/shaders/gpu_shader_text_vert.glsl b/source/blender/gpu/shaders/gpu_shader_text_vert.glsl
index 28437208e91..768638e5229 100644
--- a/source/blender/gpu/shaders/gpu_shader_text_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_text_vert.glsl
@@ -2,20 +2,33 @@
uniform mat4 ModelViewProjectionMatrix;
in vec4 pos; /* rect */
-in vec4 tex; /* rect */
in vec4 col;
+in int offset;
+in ivec2 glyph_size;
flat out vec4 color_flat;
noperspective out vec2 texCoord_interp;
+flat out int glyph_offset;
+flat out ivec2 glyph_dim;
+flat out int interp_size;
void main()
{
+ color_flat = col;
+ glyph_offset = offset;
+ glyph_dim = abs(glyph_size);
+ interp_size = int(glyph_size.x < 0) + int(glyph_size.y < 0);
+
/* Quad expension using instanced rendering. */
float x = float(gl_VertexID % 2);
float y = float(gl_VertexID / 2);
vec2 quad = vec2(x, y);
- gl_Position = ModelViewProjectionMatrix * vec4(mix(pos.xy, pos.zw, quad), 0.0, 1.0);
- texCoord_interp = mix(abs(tex.xy), abs(tex.zw), quad) * sign(tex.xw);
- color_flat = col;
+ vec2 interp_offset = float(interp_size) / abs(pos.zw - pos.xy);
+ texCoord_interp = mix(-interp_offset, 1.0 + interp_offset, quad);
+
+ vec2 final_pos = mix(
+ pos.xy + ivec2(-interp_size, interp_size), pos.zw + ivec2(interp_size, -interp_size), quad);
+
+ gl_Position = ModelViewProjectionMatrix * vec4(final_pos, 0.0, 1.0);
}