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>2018-03-29 17:35:45 +0300
committerClément Foucault <foucault.clem@gmail.com>2018-03-29 17:36:01 +0300
commitd93e7e643031448dad7f407ccb285c3b9cf91034 (patch)
tree1f0e484a380459cf2ac0cc001fff962243109be5
parent26b9c502edced5142e4c2e0151566b31b524bbab (diff)
UI: Perf: Group fill/border/emboss batches together.
This roughly halves the number of drawcalls from widgetbase_draw.
-rw-r--r--source/blender/editors/interface/interface_widgets.c181
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl62
2 files changed, 132 insertions, 111 deletions
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 183ab6cfbac..3e74f881cfd 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -129,7 +129,8 @@ typedef struct uiWidgetBase {
float radi, rad;
float facxi, facyi;
float round_corners[4];
- float color1[4], color2[4];
+ float color_inner1[4], color_inner2[4];
+ float color_outline[4], color_emboss[4];
float shade_dir, clamp, pad[2];
} uniform_params;
} uiWidgetBase;
@@ -225,10 +226,7 @@ static const uint g_shape_preset_hold_action_face[2][3] = {{2, 0, 1}, {3, 5, 4}}
* TODO: find a better place. Maybe it's own file?
**/
static struct {
- Gwn_Batch *roundbox_inner;
- Gwn_Batch *roundbox_edges;
- Gwn_Batch *roundbox_emboss;
- Gwn_Batch *anti_tria;
+ Gwn_Batch *roundbox;
Gwn_VertFormat format;
uint vflag_id;
@@ -243,99 +241,102 @@ static Gwn_VertFormat *vflag_format(void)
return &g_ui_batch_cache.format;
}
-static void set_roundbox_vertex(
+#define INNER 0
+#define OUTLINE 1
+#define EMBOSS 2
+#define NO_AA WIDGET_AA_JITTER
+
+static void set_roundbox_vertex_data(
+ Gwn_VertBufRaw *vflag_step, uint32_t d)
+{
+ uint32_t *data = GWN_vertbuf_raw_step(vflag_step);
+ *data = d;
+}
+
+static uint32_t set_roundbox_vertex(
Gwn_VertBufRaw *vflag_step,
- int corner_id, int corner_v, int jit_v, bool inner, bool emboss)
+ int corner_id, int corner_v, int jit_v, bool inner, bool emboss, int color)
{
uint32_t *data = GWN_vertbuf_raw_step(vflag_step);
*data = corner_id;
*data |= corner_v << 2;
*data |= jit_v << 6;
+ *data |= color << 12;
*data |= (inner) ? (1 << 10) : 0; /* is inner vert */
*data |= (emboss) ? (1 << 11) : 0; /* is emboss vert */
+ return *data;
}
-static Gwn_Batch *ui_batch_roundbox_inner_get(void)
+static Gwn_Batch *ui_batch_roundbox_get(void)
{
- if (g_ui_batch_cache.roundbox_inner == NULL) {
+ if (g_ui_batch_cache.roundbox == NULL) {
+ uint32_t last_data;
Gwn_VertBufRaw vflag_step;
Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(vflag_format());
- GWN_vertbuf_data_alloc(vbo, WIDGET_SIZE_MAX);
+ int vcount = WIDGET_SIZE_MAX; /* inner */
+ vcount += 2; /* restart */
+ vcount += ((WIDGET_SIZE_MAX + 1) * 2) * WIDGET_AA_JITTER; /* outline (edges) */
+ vcount += 2; /* restart */
+ vcount += ((WIDGET_CURVE_RESOLU * 2) * 2) * WIDGET_AA_JITTER; /* emboss */
+ GWN_vertbuf_data_alloc(vbo, vcount);
GWN_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step);
- for (int c = 0; c < 4; c++) {
- for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) {
- set_roundbox_vertex(&vflag_step, c, a, WIDGET_AA_JITTER, true, false);
+ /* Inner */
+ for (int c1 = 0, c2 = 3; c1 < 2; c1++, c2--) {
+ for (int a1 = 0, a2 = WIDGET_CURVE_RESOLU -1; a2 >= 0; a1++, a2--) {
+ last_data = set_roundbox_vertex(&vflag_step, c1, a1, NO_AA, true, false, INNER);
+ last_data = set_roundbox_vertex(&vflag_step, c2, a2, NO_AA, true, false, INNER);
}
}
- g_ui_batch_cache.roundbox_inner = GWN_batch_create_ex(GWN_PRIM_TRI_FAN, vbo, NULL, GWN_BATCH_OWNS_VBO);
- }
- return g_ui_batch_cache.roundbox_inner;
-}
-
-static Gwn_Batch *ui_batch_roundbox_edges_get(void)
-{
- if (g_ui_batch_cache.roundbox_edges == NULL) {
- Gwn_VertBufRaw vflag_step;
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(vflag_format());
- GWN_vertbuf_data_alloc(vbo, ((WIDGET_SIZE_MAX + 1) * 2) * WIDGET_AA_JITTER);
- GWN_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step);
+ /* restart */
+ set_roundbox_vertex_data(&vflag_step, last_data);
+ set_roundbox_vertex(&vflag_step, 0, 0, 0, true, false, OUTLINE);
+ /* Outlines */
for (int j = 0; j < WIDGET_AA_JITTER; j++) {
for (int c = 0; c < 4; c++) {
for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) {
- set_roundbox_vertex(&vflag_step, c, a, j, true, false);
- set_roundbox_vertex(&vflag_step, c, a, j, false, false);
+ set_roundbox_vertex(&vflag_step, c, a, j, true, false, OUTLINE);
+ set_roundbox_vertex(&vflag_step, c, a, j, false, false, OUTLINE);
}
}
/* Close the loop. */
- set_roundbox_vertex(&vflag_step, 0, 0, j, true, false);
- set_roundbox_vertex(&vflag_step, 0, 0, j, false, false);
+ set_roundbox_vertex(&vflag_step, 0, 0, j, true, false, OUTLINE);
+ last_data = set_roundbox_vertex(&vflag_step, 0, 0, j, false, false, OUTLINE);
}
- g_ui_batch_cache.roundbox_edges = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
- }
- return g_ui_batch_cache.roundbox_edges;
-}
-
-static Gwn_Batch *ui_batch_roundbox_emboss_get(void)
-{
- if (g_ui_batch_cache.roundbox_emboss == NULL) {
- Gwn_VertBufRaw vflag_step;
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(vflag_format());
- GWN_vertbuf_data_alloc(vbo, ((WIDGET_CURVE_RESOLU * 2) * 2) * WIDGET_AA_JITTER);
- GWN_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step);
+ /* restart */
+ set_roundbox_vertex_data(&vflag_step, last_data);
+ set_roundbox_vertex(&vflag_step, 0, 0, 0, false, false, EMBOSS);
+ /* Emboss */
bool rev = false; /* go back and forth : avoid degenerate triangle (beware of backface cull) */
for (int j = 0; j < WIDGET_AA_JITTER; j++, rev = !rev) {
for (int c = (rev) ? 1 : 0; (rev) ? c >= 0 : c < 2; (rev) ? c-- : c++) {
int sta = (rev) ? WIDGET_CURVE_RESOLU - 1 : 0;
int end = WIDGET_CURVE_RESOLU;
for (int a = sta; (rev) ? a >= 0 : a < end; (rev) ? a-- : a++) {
- set_roundbox_vertex(&vflag_step, c, a, j, false, false);
- set_roundbox_vertex(&vflag_step, c, a, j, false, true);
+ set_roundbox_vertex(&vflag_step, c, a, j, false, false, EMBOSS);
+ set_roundbox_vertex(&vflag_step, c, a, j, false, true, EMBOSS);
}
}
}
- g_ui_batch_cache.roundbox_emboss = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ g_ui_batch_cache.roundbox = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
}
- return g_ui_batch_cache.roundbox_emboss;
+ return g_ui_batch_cache.roundbox;
}
+#undef INNER
+#undef OUTLINE
+#undef EMBOSS
+#undef NO_AA
+
void ui_widget_batch_preset_reset(void)
{
- if (g_ui_batch_cache.roundbox_inner) {
- gwn_batch_vao_cache_clear(g_ui_batch_cache.roundbox_inner);
- }
- if (g_ui_batch_cache.roundbox_edges) {
- gwn_batch_vao_cache_clear(g_ui_batch_cache.roundbox_edges);
- }
- if (g_ui_batch_cache.roundbox_emboss) {
- gwn_batch_vao_cache_clear(g_ui_batch_cache.roundbox_emboss);
+ if (g_ui_batch_cache.roundbox) {
+ gwn_batch_vao_cache_clear(g_ui_batch_cache.roundbox);
}
}
void ui_widget_batch_preset_exit(void)
{
- GWN_BATCH_DISCARD_SAFE(g_ui_batch_cache.roundbox_inner);
- GWN_BATCH_DISCARD_SAFE(g_ui_batch_cache.roundbox_edges);
- GWN_BATCH_DISCARD_SAFE(g_ui_batch_cache.roundbox_emboss);
+ GWN_BATCH_DISCARD_SAFE(g_ui_batch_cache.roundbox);
}
/* ************************************************* */
@@ -834,22 +835,32 @@ static void widgetbase_outline(uiWidgetBase *wtb, unsigned int pos)
widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip, NULL, wtb->totvert * 2 + 2);
}
-static void widgetbase_set_uniform_colors_ubv(uiWidgetBase *wtb, const unsigned char *col1, const unsigned char *col2)
+static void widgetbase_set_uniform_colors_ubv(
+ uiWidgetBase *wtb,
+ const unsigned char *col1, const unsigned char *col2,
+ const unsigned char *outline,
+ const unsigned char *emboss)
{
- rgba_float_args_set_ch(wtb->uniform_params.color1, col1[0], col1[1], col1[2], col1[3]);
- rgba_float_args_set_ch(wtb->uniform_params.color2, col2[0], col2[1], col2[2], col2[3]);
+ rgba_float_args_set_ch(wtb->uniform_params.color_inner1, col1[0], col1[1], col1[2], col1[3]);
+ rgba_float_args_set_ch(wtb->uniform_params.color_inner2, col2[0], col2[1], col2[2], col2[3]);
+ rgba_float_args_set_ch(wtb->uniform_params.color_outline, outline[0], outline[1], outline[2], outline[3]);
+ rgba_float_args_set_ch(wtb->uniform_params.color_emboss, emboss[0], emboss[1], emboss[2], emboss[3]);
}
static void draw_widgetbase_batch(Gwn_Batch *batch, uiWidgetBase *wtb)
{
GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
- GWN_batch_uniform_4fv_array(batch, "parameters", 7, (float *)&wtb->uniform_params);
+ GWN_batch_uniform_4fv_array(batch, "parameters", 9, (float *)&wtb->uniform_params);
GWN_batch_draw(batch);
}
static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
{
int a;
+ unsigned char inner_col1[4] = {0};
+ unsigned char inner_col2[4] = {0};
+ unsigned char emboss_col[4] = {0};
+ unsigned char outline_col[4] = {0};
glEnable(GL_BLEND);
/* backdrop non AA */
@@ -899,49 +910,39 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
}
else {
/* simple fill */
- widgetbase_set_uniform_colors_ubv(wtb, (unsigned char *)wcol->inner, (unsigned char *)wcol->inner);
-
- Gwn_Batch *inner_batch = ui_batch_roundbox_inner_get();
- draw_widgetbase_batch(inner_batch, wtb);
+ inner_col1[0] = inner_col2[0] = (unsigned char)wcol->inner[0];
+ inner_col1[1] = inner_col2[1] = (unsigned char)wcol->inner[1];
+ inner_col1[2] = inner_col2[2] = (unsigned char)wcol->inner[2];
+ inner_col1[3] = inner_col2[3] = (unsigned char)wcol->inner[3];
}
}
else {
- char col1[4], col2[4];
- shadecolors4(col1, col2, wcol->inner, wcol->shadetop, wcol->shadedown);
- widgetbase_set_uniform_colors_ubv(wtb, (unsigned char *)col1, (unsigned char *)col2);
-
- Gwn_Batch *inner_batch = ui_batch_roundbox_inner_get();
- draw_widgetbase_batch(inner_batch, wtb);
+ /* gradient fill */
+ shadecolors4((char *)inner_col1, (char *)inner_col2, wcol->inner, wcol->shadetop, wcol->shadedown);
}
}
- /* for each AA step */
if (wtb->draw_outline) {
- BLI_assert(wtb->totvert != 0);
- const unsigned char tcol[4] = {wcol->outline[0],
- wcol->outline[1],
- wcol->outline[2],
- wcol->outline[3] / WIDGET_AA_JITTER};
-
- /* outline */
- widgetbase_set_uniform_colors_ubv(wtb, tcol, tcol);
-
- Gwn_Batch *edges_batch = ui_batch_roundbox_edges_get();
- draw_widgetbase_batch(edges_batch, wtb);
+ outline_col[0] = wcol->outline[0];
+ outline_col[1] = wcol->outline[1];
+ outline_col[2] = wcol->outline[2];
+ outline_col[3] = wcol->outline[3] / WIDGET_AA_JITTER;
/* emboss bottom shadow */
if (wtb->draw_emboss) {
- unsigned char emboss[4];
- UI_GetThemeColor4ubv(TH_WIDGET_EMBOSS, emboss);
- if (emboss[3]) {
- widgetbase_set_uniform_colors_ubv(wtb, emboss, emboss);
-
- Gwn_Batch *emboss_batch = ui_batch_roundbox_emboss_get();
- draw_widgetbase_batch(emboss_batch, wtb);
- }
+ UI_GetThemeColor4ubv(TH_WIDGET_EMBOSS, emboss_col);
}
}
+ /* Draw everything in one drawcall */
+ if (inner_col1[3] || inner_col2[3] || outline_col[3] || emboss_col[4]) {
+ widgetbase_set_uniform_colors_ubv(wtb, inner_col1, inner_col2, outline_col, emboss_col);
+
+ Gwn_Batch *roundbox_batch = ui_batch_roundbox_get();
+ draw_widgetbase_batch(roundbox_batch, wtb);
+ }
+
+ /* TODO OPTI: Put this inside a batch too. */
/* decoration */
if (wtb->tria1.tot || wtb->tria2.tot) {
const unsigned char tcol[4] = {wcol->item[0],
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl
index 78fbc4b132b..1920184aefe 100644
--- a/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl
@@ -1,3 +1,5 @@
+#define BIT_RANGE(x) ((1u << x) - 1u)
+
/* 2 bits for corner */
/* Attention! Not the same order as in UI_interface.h!
* Ordered by drawing order. */
@@ -5,11 +7,11 @@
#define BOTTOM_RIGHT 1u
#define TOP_RIGHT 2u
#define TOP_LEFT 3u
-#define CNR_FLAG_RANGE ((1u << 2u) - 1u)
+#define CNR_FLAG_RANGE BIT_RANGE(2u)
/* 4bits for corner id */
#define CORNER_VEC_OFS 2u
-#define CORNER_VEC_RANGE ((1u << 4u) - 1u)
+#define CORNER_VEC_RANGE BIT_RANGE(4u)
const vec2 cornervec[36] = vec2[36](
vec2(0.0, 1.0), vec2(0.02, 0.805), vec2(0.067, 0.617), vec2(0.169, 0.45), vec2(0.293, 0.293), vec2(0.45, 0.169), vec2(0.617, 0.076), vec2(0.805, 0.02), vec2(1.0, 0.0),
vec2(-1.0, 0.0), vec2(-0.805, 0.02), vec2(-0.617, 0.067), vec2(-0.45, 0.169), vec2(-0.293, 0.293), vec2(-0.169, 0.45), vec2(-0.076, 0.617), vec2(-0.02, 0.805), vec2(0.0, 1.0),
@@ -19,7 +21,7 @@ const vec2 cornervec[36] = vec2[36](
/* 4bits for jitter id */
#define JIT_OFS 6u
-#define JIT_RANGE ((1u << 4u) - 1u)
+#define JIT_RANGE BIT_RANGE(4u)
const vec2 jit[9] = vec2[9](
vec2( 0.468813, -0.481430), vec2(-0.155755, -0.352820),
vec2( 0.219306, -0.238501), vec2(-0.393286, -0.110949),
@@ -28,23 +30,32 @@ const vec2 jit[9] = vec2[9](
vec2( 0.0, 0.0)
);
-/* 2bits for other flag */
-#define INNER_FLAG (1u << 10u) /* is inner vert */
-#define EMBOSS_FLAG (1u << 11u) /* is emboss vert */
+/* 2bits for other flags */
+#define INNER_FLAG (1u << 10u) /* is inner vert */
+#define EMBOSS_FLAG (1u << 11u) /* is emboss vert */
+
+/* 2bits for color */
+#define COLOR_OFS 12u
+#define COLOR_RANGE BIT_RANGE(2u)
+#define COLOR_INNER 0u
+#define COLOR_EDGE 1u
+#define COLOR_EMBOSS 2u
uniform mat4 ModelViewProjectionMatrix;
-uniform vec4 parameters[7];
+uniform vec4 parameters[9];
/* radi and rad per corner */
-#define recti parameters[0]
-#define rect parameters[1]
-#define radsi parameters[2].x
-#define rads parameters[2].y
-#define faci parameters[2].zw
+#define recti parameters[0]
+#define rect parameters[1]
+#define radsi parameters[2].x
+#define rads parameters[2].y
+#define faci parameters[2].zw
#define roundCorners parameters[3]
-#define color1 parameters[4]
-#define color2 parameters[5]
-#define shadeDir parameters[6].x
+#define colorInner1 parameters[4]
+#define colorInner2 parameters[5]
+#define colorEdge parameters[6]
+#define colorEmboss parameters[7]
+#define shadeDir parameters[8].x
in uint vflag;
@@ -57,7 +68,7 @@ void main()
vec2 v = cornervec[cflag * 9u + vofs];
- bool is_inner = (vflag & INNER_FLAG) != 0.0;
+ bool is_inner = (vflag & INNER_FLAG) != 0u;
/* Scale by corner radius */
v *= roundCorners[cflag] * ((is_inner) ? radsi : rads);
@@ -74,11 +85,20 @@ void main()
v += rct.xw;
/* compute uv and color gradient */
- vec2 uv = faci * (v - recti.xz);
- float fac = clamp((shadeDir > 0.0) ? uv.y : uv.x, 0.0, 1.0);
- finalColor = mix(color2, color1, fac);
-
- bool is_emboss = (vflag & EMBOSS_FLAG) != 0.0;
+ uint color_id = (vflag >> COLOR_OFS) & COLOR_RANGE;
+ if (color_id == COLOR_INNER) {
+ vec2 uv = faci * (v - recti.xz);
+ float fac = clamp((shadeDir > 0.0) ? uv.y : uv.x, 0.0, 1.0);
+ finalColor = mix(colorInner2, colorInner1, fac);
+ }
+ else if (color_id == COLOR_EDGE) {
+ finalColor = colorEdge;
+ }
+ else /* (color_id == COLOR_EMBOSS) */ {
+ finalColor = colorEmboss;
+ }
+
+ bool is_emboss = (vflag & EMBOSS_FLAG) != 0u;
v.y -= (is_emboss) ? 1.0f : 0.0;
/* Antialiasing offset */