[Bf-blender-cvs] [ab9adf9cdc3] blender2.8: BLF: Use Batch API instead of IMM.

Clément Foucault noreply at git.blender.org
Fri Mar 30 23:34:03 CEST 2018


Commit: ab9adf9cdc3b2fd91dcade32ea4b4359f4897392
Author: Clément Foucault
Date:   Fri Mar 30 19:16:14 2018 +0200
Branches: blender2.8
https://developer.blender.org/rBab9adf9cdc3b2fd91dcade32ea4b4359f4897392

BLF: Use Batch API instead of IMM.

This is not a perfect win just yet. It's now calling glBufferSubData for
every call (instead of using glMapBufferRange which is almost faster), but
with this system we will be able to batch drawcalls together.

See next commit.

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

M	source/blender/blenfont/BLF_api.h
M	source/blender/blenfont/intern/blf.c
M	source/blender/blenfont/intern/blf_font.c
M	source/blender/blenfont/intern/blf_glyph.c
M	source/blender/blenfont/intern/blf_internal.h
M	source/blender/blenfont/intern/blf_internal_types.h
M	source/blender/gpu/GPU_batch.h
M	source/blender/windowmanager/intern/wm_window.c

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

diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h
index cd3a15f1c88..fd0c0362300 100644
--- a/source/blender/blenfont/BLF_api.h
+++ b/source/blender/blenfont/BLF_api.h
@@ -47,6 +47,7 @@ void BLF_exit(void);
 void BLF_default_dpi(int dpi);
 void BLF_default_set(int fontid);
 int BLF_default(void); /* get default font ID so we can pass it to other functions */
+void BLF_batch_reset(void); /* call when changing opengl context. */
 
 void BLF_antialias_set(bool enabled);
 bool BLF_antialias_get(void);
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index 30919f1acda..5b51ecbc047 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -132,6 +132,11 @@ void BLF_exit(void)
 	blf_font_exit();
 }
 
+void BLF_batch_reset(void)
+{
+	blf_batching_vao_clear();
+}
+
 void BLF_cache_clear(void)
 {
 	FontBLF *font;
@@ -561,8 +566,11 @@ static void blf_draw_gl__start(FontBLF *font)
 	 * in BLF_position (old ui_rasterpos_safe).
 	 */
 
-	glEnable(GL_BLEND);
-	glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+	/* always bind the texture for the first glyph */
+	font->tex_bind_state = 0;
+
+	if ((font->flags & (BLF_ROTATION | BLF_MATRIX | BLF_ASPECT)) == 0)
+		return; /* glyphs will be translated individually and batched. */
 
 	gpuPushMatrix();
 
@@ -576,35 +584,12 @@ static void blf_draw_gl__start(FontBLF *font)
 
 	if (font->flags & BLF_ROTATION)
 		gpuRotate2D(RAD2DEG(font->angle));
-
-#ifndef BLF_STANDALONE
-	Gwn_VertFormat *format = immVertexFormat();
-	unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
-	unsigned int texCoord = GWN_vertformat_attr_add(format, "tex", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
-	unsigned int color = GWN_vertformat_attr_add(format, "col", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
-
-	BLI_assert(pos == BLF_POS_ID);
-	BLI_assert(texCoord == BLF_COORD_ID);
-	BLI_assert(color == BLF_COLOR_ID);
-
-	UNUSED_VARS_NDEBUG(pos, texCoord, color);
-
-	immBindBuiltinProgram(GPU_SHADER_TEXT);
-#endif
-
-	/* always bind the texture for the first glyph */
-	font->tex_bind_state = -1;
 }
 
-static void blf_draw_gl__end(void)
+static void blf_draw_gl__end(FontBLF *font)
 {
-	gpuPopMatrix();
-
-#ifndef BLF_STANDALONE
-	immUnbindProgram();
-#endif
-
-	glDisable(GL_BLEND);
+	if ((font->flags & (BLF_ROTATION | BLF_MATRIX | BLF_ASPECT)) != 0)
+		gpuPopMatrix();
 }
 
 void BLF_draw_ex(
@@ -623,7 +608,7 @@ void BLF_draw_ex(
 		else {
 			blf_font_draw(font, str, len, r_info);
 		}
-		blf_draw_gl__end();
+		blf_draw_gl__end(font);
 	}
 }
 void BLF_draw(int fontid, const char *str, size_t len)
@@ -652,7 +637,7 @@ void BLF_draw_ascii_ex(
 		else {
 			blf_font_draw_ascii(font, str, len, r_info);
 		}
-		blf_draw_gl__end();
+		blf_draw_gl__end(font);
 	}
 }
 void BLF_draw_ascii(int fontid, const char *str, size_t len)
@@ -676,7 +661,7 @@ int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth)
 	if (font && font->glyph_cache) {
 		blf_draw_gl__start(font);
 		columns = blf_font_draw_mono(font, str, len, cwidth);
-		blf_draw_gl__end();
+		blf_draw_gl__end(font);
 	}
 
 	return columns;
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index 1f304d208e6..868d8eb775e 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -59,6 +59,8 @@
 #include "BLF_api.h"
 
 #include "GPU_immediate.h"
+#include "GPU_matrix.h"
+#include "GPU_batch.h"
 
 #include "blf_internal_types.h"
 #include "blf_internal.h"
@@ -69,12 +71,104 @@
 #  define FT_New_Face FT_New_Face__win32_compat
 #endif
 
+/* Batching buffer for drawing. */
+BatchBLF g_batch;
+
 /* freetype2 handle ONLY for this file!. */
 static FT_Library ft_lib;
 static SpinLock ft_lib_mutex;
 
+/* -------------------------------------------------------------------- */
+/** \name Glyph Batching
+ * \{ */
+/**
+ * Drawcalls are precious! make them count!
+ * Since most of the Text elems are not covered by other UI elements, we can
+ * group some strings together and render them in one drawcall. This behaviour
+ * is on demand only, between BLF_batch_start() and BLF_batch_end().
+ **/
+static void blf_batching_init(void)
+{
+	Gwn_VertFormat format = {0};
+	g_batch.pos_loc = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+	g_batch.tex_loc = GWN_vertformat_attr_add(&format, "tex", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+	g_batch.col_loc = GWN_vertformat_attr_add(&format, "col", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+	g_batch.verts = GWN_vertbuf_create_with_format_ex(&format, GWN_USAGE_STREAM);
+	GWN_vertbuf_data_alloc(g_batch.verts, BLF_BATCHING_SIZE);
+
+	g_batch.batch = GWN_batch_create_ex(GWN_PRIM_POINTS, g_batch.verts, NULL, GWN_BATCH_OWNS_VBO);
+}
+
+static void blf_batching_exit(void)
+{
+	GWN_BATCH_DISCARD_SAFE(g_batch.batch);
+}
+
+void blf_batching_vao_clear(void)
+{
+	if (g_batch.batch) {
+		gwn_batch_vao_cache_clear(g_batch.batch);
+	}
+}
+
+void blf_batching_start(FontBLF *font)
+{
+	if (g_batch.batch == NULL) {
+		blf_batching_init();
+	}
+
+	zero_v2(g_batch.ofs);
+	if ((font->flags & (BLF_ROTATION | BLF_MATRIX | BLF_ASPECT)) == 0) {
+		copy_v2_v2(g_batch.ofs, font->pos);
+	}
+
+	/* restart to 1st vertex data pointers */
+	GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.pos_loc, &g_batch.pos_step);
+	GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.tex_loc, &g_batch.tex_step);
+	GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.col_loc, &g_batch.col_step);
+	g_batch.glyph_ct = 0;
+	g_batch.font = font;
+}
+
+void blf_batching_draw(void)
+{
+	if (g_batch.glyph_ct == 0)
+		return;
+
+	glEnable(GL_BLEND);
+	glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+	BLI_assert(g_batch.font->tex_bind_state != 0); /* must still be valid */
+	glActiveTexture(GL_TEXTURE0);
+	glBindTexture(GL_TEXTURE_2D, g_batch.font->tex_bind_state);
+
+	GWN_vertbuf_vertex_count_set(g_batch.verts, g_batch.glyph_ct);
+	GWN_vertbuf_use(g_batch.verts); /* send data */
+
+	GWN_batch_program_set_builtin(g_batch.batch, GPU_SHADER_TEXT);
+	GWN_batch_uniform_1i(g_batch.batch, "glyph", 0);
+	GWN_batch_draw(g_batch.batch);
+
+	glDisable(GL_BLEND);
+
+	g_batch.glyph_ct = 0;
+}
+
+static void blf_batching_end(void)
+{
+	if (!g_batch.enabled) {
+		blf_batching_draw();
+	}
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
 int blf_font_init(void)
 {
+	memset(&g_batch, 0, sizeof(g_batch));
 	BLI_spin_init(&ft_lib_mutex);
 	return FT_Init_FreeType(&ft_lib);
 }
@@ -83,6 +177,7 @@ void blf_font_exit(void)
 {
 	FT_Done_FreeType(ft_lib);
 	BLI_spin_end(&ft_lib_mutex);
+	blf_batching_exit();
 }
 
 void blf_font_size(FontBLF *font, unsigned int size, unsigned int dpi)
@@ -174,24 +269,6 @@ static void blf_font_ensure_ascii_table(FontBLF *font)
 	}                                                                            \
 } (void)0
 
-static unsigned int verts_needed(const FontBLF *font, const char *str, size_t len)
-{
-	size_t str_len = (len > 50) ? strlen(str) : INT_MAX; /* Arbitrary. */
-	unsigned int length = (unsigned int)MIN2(str_len, len);
-	unsigned int quad_ct = 1;
-
-	if (font->flags & BLF_SHADOW) {
-		if (font->shadow == 0)
-			quad_ct += 1;
-		if (font->shadow <= 4)
-			quad_ct += 9; /* 3x3 kernel */
-		else
-			quad_ct += 25; /* 5x5 kernel */
-	}
-
-	return length * quad_ct; /* Only one vert per quad */
-}
-
 static void blf_font_draw_ex(
         FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info,
         int pen_y)
@@ -212,8 +289,7 @@ static void blf_font_draw_ex(
 
 	blf_font_ensure_ascii_table(font);
 
-	immBeginAtMost(GWN_PRIM_POINTS, verts_needed(font, str, len));
-	/* at most because some glyphs might be clipped & not drawn */
+	blf_batching_start(font);
 
 	while ((i < len) && str[i]) {
 		BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
@@ -232,7 +308,7 @@ static void blf_font_draw_ex(
 		g_prev = g;
 	}
 
-	immEnd();
+	blf_batching_end();
 
 	if (r_info) {
 		r_info->lines = 1;
@@ -259,7 +335,7 @@ static void blf_font_draw_ascii_ex(
 
 	blf_font_ensure_ascii_table(font);
 
-	immBeginAtMost(GWN_PRIM_POINTS, verts_needed(font, str, len));
+	blf_batching_start(font);
 
 	while ((c = *(str++)) && len--) {
 		BLI_assert(c < 128);
@@ -275,7 +351,7 @@ static void blf_font_draw_ascii_ex(
 		g_prev = g;
 	}
 
-	immEnd();
+	blf_batching_end();
 
 	if (r_info) {
 		r_info->lines = 1;
@@ -299,7 +375,7 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
 
 	blf_font_ensure_ascii_table(font);
 
-	immBeginAtMost(GWN_PRIM_POINTS, verts_needed(font, str, len));
+	blf_batching_start(font);
 
 	while ((i < len) && str[i]) {
 		BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
@@ -320,7 +396,7 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
 		pen_x += cwidth * col;
 	}
 
-	immEnd();
+	blf_batching_end();
 
 	return columns;
 }
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index 5e1debf1501..b91eceac817 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -63,6 +63,7 @@
 #include "blf_internal.h"
 
 #include "BLI_strict_flags.h"
+#include "BLI_math_vector.h"
 
 GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font, unsigned int size, unsigned int dpi)
 {
@@ -316,13 +317,19 @@ void blf_glyph_free(GlyphBLF *g)
 	MEM_freeN(g);
 }
 
-static void blf_texture_draw(const unsigned char color[4], float uv[2][2], float dx, float y1, float dx1, float y2)
+static void blf_texture_draw(const unsigned char color[4], float uv[2][2], float x1, float y1, float x2, float y2)
 {
+	if (g_batch.glyph_ct == BLF_BATCHING_SIZE) {
+		blf_batching_draw();
+		blf_batching_start(g_batch.font);
+	}
+	g_batch.glyph_ct++;
 	/* Only one vertex per glyph, geometry shader expand it into a quad. */
 	/* TODO Get rid of Geom Shader because it's not optimal AT ALL for the GPU */
-	immAttrib4ubv(BLF_COLOR_ID, color);
-	immAttrib4fv(BLF_COORD_ID, (float *)uv);

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list