GPU: Panel Drag Widget Drawing Performance

The 10g Intel/Win driver doesn't work well with our emulated
intermediate mode. This patch alters the drawing of the drag widget of
the panels to reduce unneeded drawing.

The previous method would draw 16 boxes per widget. This new way would
cache this drawing in a GPU batch and just move the matrix around.

Reviewed By: Clément Foucault

Differential Revision: https://developer.blender.org/D7345
This commit is contained in:
Jeroen Bakker 2020-04-06 16:31:22 +02:00
parent 71b1ee940b
commit 60d873bd22
Notes: blender-bot 2023-02-14 11:42:40 +01:00
Referenced by commit 58e20b432a, Fix memory leak in recent panel drag widget cache
Referenced by issue #70922, Intel IRS / Ice lake GPU slow viewport performance
3 changed files with 154 additions and 64 deletions

View File

@ -56,7 +56,9 @@
#include "UI_resources.h"
#include "UI_view2d.h"
#include "GPU_batch_presets.h"
#include "GPU_immediate.h"
#include "GPU_matrix.h"
#include "GPU_state.h"
#include "interface_intern.h"
@ -544,59 +546,6 @@ static void ui_draw_panel_scalewidget(uint pos, const rcti *rect)
GPU_blend(false);
}
static void immRectf_tris_color_ex(
uint pos, float x1, float y1, float x2, float y2, uint col, const float color[3])
{
immAttr4fv(col, color);
immVertex2f(pos, x1, y1);
immAttr4fv(col, color);
immVertex2f(pos, x2, y1);
immAttr4fv(col, color);
immVertex2f(pos, x2, y2);
immAttr4fv(col, color);
immVertex2f(pos, x1, y1);
immAttr4fv(col, color);
immVertex2f(pos, x2, y2);
immAttr4fv(col, color);
immVertex2f(pos, x1, y2);
}
static void ui_draw_panel_dragwidget(uint pos, uint col, const rctf *rect)
{
float col_high[4], col_dark[4];
const int col_tint = 84;
const int px = (int)U.pixelsize;
const int px_zoom = max_ii(round_fl_to_int(BLI_rctf_size_y(rect) / 22.0f), 1);
const int box_margin = max_ii(round_fl_to_int((float)(px_zoom * 2.0f)), px);
const int box_size = max_ii(round_fl_to_int((BLI_rctf_size_y(rect) / 8.0f) - px), px);
const int x_min = rect->xmin;
const int y_min = rect->ymin;
const int y_ofs = max_ii(round_fl_to_int(BLI_rctf_size_y(rect) / 2.5f), px);
const int x_ofs = y_ofs;
int i_x, i_y;
UI_GetThemeColorShade4fv(TH_PANEL_HEADER, col_tint, col_high);
UI_GetThemeColorShade4fv(TH_PANEL_BACK, -col_tint, col_dark);
/* draw multiple boxes */
immBegin(GPU_PRIM_TRIS, 4 * 2 * (6 * 2));
for (i_x = 0; i_x < 4; i_x++) {
for (i_y = 0; i_y < 2; i_y++) {
const int x_co = (x_min + x_ofs) + (i_x * (box_size + box_margin));
const int y_co = (y_min + y_ofs) + (i_y * (box_size + box_margin));
immRectf_tris_color_ex(
pos, x_co - box_size, y_co - px_zoom, x_co, (y_co + box_size) - px_zoom, col, col_dark);
immRectf_tris_color_ex(pos, x_co - box_size, y_co, x_co, y_co + box_size, col, col_high);
}
}
immEnd();
}
/* For button layout next to label. */
void UI_panel_label_offset(uiBlock *block, int *r_x, int *r_y)
{
@ -755,24 +704,27 @@ void ui_draw_aligned_panel(uiStyle *style,
ui_draw_aligned_panel_header(style, block, &titlerect, 'h', show_background);
if (show_drag) {
uint col;
GPUVertFormat *format = immVertexFormat();
pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
/* itemrect smaller */
const float scale = 0.7;
itemrect.xmax = headrect.xmax - (0.2f * UI_UNIT_X);
itemrect.xmin = itemrect.xmax - BLI_rcti_size_y(&headrect);
itemrect.ymin = headrect.ymin;
itemrect.ymax = headrect.ymax;
BLI_rctf_scale(&itemrect, scale);
BLI_rctf_scale(&itemrect, 0.7f);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
ui_draw_panel_dragwidget(pos, col, &itemrect);
immUnbindProgram();
GPU_matrix_push();
GPU_matrix_translate_2f(itemrect.xmin, itemrect.ymin);
/* Restore format for the following draws. */
pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
const int col_tint = 84;
float col_high[4], col_dark[4];
UI_GetThemeColorShade4fv(TH_PANEL_HEADER, col_tint, col_high);
UI_GetThemeColorShade4fv(TH_PANEL_BACK, -col_tint, col_dark);
GPUBatch *batch = GPU_batch_preset_panel_drag_widget(
U.pixelsize, col_high, col_dark, BLI_rcti_size_y(&headrect) * scale);
GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_FLAT_COLOR);
GPU_batch_draw(batch);
GPU_matrix_pop();
}
}

View File

@ -39,6 +39,10 @@ extern "C" {
/* Replacement for gluSphere */
struct GPUBatch *GPU_batch_preset_sphere(int lod) ATTR_WARN_UNUSED_RESULT;
struct GPUBatch *GPU_batch_preset_sphere_wire(int lod) ATTR_WARN_UNUSED_RESULT;
struct GPUBatch *GPU_batch_preset_panel_drag_widget(const float pixelsize,
const float col_high[4],
const float col_dark[4],
const float width) ATTR_WARN_UNUSED_RESULT;
void gpu_batch_presets_init(void);
void gpu_batch_presets_register(struct GPUBatch *preset_batch);

View File

@ -27,7 +27,10 @@
#include "BLI_utildefines.h"
#include "MEM_guardedalloc.h"
#include "DNA_userdef_types.h"
#include "UI_interface.h"
#include "UI_resources.h"
#include "GPU_batch.h"
#include "GPU_batch_presets.h" /* own include */
@ -53,6 +56,23 @@ static struct {
ThreadMutex mutex;
} g_presets_3d = {{0}};
static struct {
struct {
GPUBatch *panel_drag_widget;
} batch;
float panel_drag_widget_pixelsize;
float panel_drag_widget_width;
float panel_drag_widget_col_high[4];
float panel_drag_widget_col_dark[4];
GPUVertFormat format;
struct {
uint pos, col;
} attr_id;
} g_presets_2d = {{0}};
static ListBase presets_list = {NULL, NULL};
/* -------------------------------------------------------------------- */
@ -71,6 +91,18 @@ static GPUVertFormat *preset_3d_format(void)
return &g_presets_3d.format;
}
static GPUVertFormat *preset_2d_format(void)
{
if (g_presets_2d.format.attr_len == 0) {
GPUVertFormat *format = &g_presets_2d.format;
g_presets_2d.attr_id.pos = GPU_vertformat_attr_add(
format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
g_presets_2d.attr_id.col = GPU_vertformat_attr_add(
format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
}
return &g_presets_2d.format;
}
static void batch_sphere_lat_lon_vert(GPUVertBufRaw *pos_step,
GPUVertBufRaw *nor_step,
float lat,
@ -193,6 +225,108 @@ static GPUBatch *batch_sphere_wire(int lat_res, int lon_res)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Panel Drag Widget
* \{ */
static void gpu_batch_preset_rectf_tris_color_ex(GPUVertBufRaw *pos_step,
float x1,
float y1,
float x2,
float y2,
GPUVertBufRaw *col_step,
const float color[4])
{
copy_v2_v2(GPU_vertbuf_raw_step(pos_step), (const float[2]){x1, y1});
copy_v4_v4(GPU_vertbuf_raw_step(col_step), color);
copy_v2_v2(GPU_vertbuf_raw_step(pos_step), (const float[2]){x2, y1});
copy_v4_v4(GPU_vertbuf_raw_step(col_step), color);
copy_v2_v2(GPU_vertbuf_raw_step(pos_step), (const float[2]){x2, y2});
copy_v4_v4(GPU_vertbuf_raw_step(col_step), color);
copy_v2_v2(GPU_vertbuf_raw_step(pos_step), (const float[2]){x1, y1});
copy_v4_v4(GPU_vertbuf_raw_step(col_step), color);
copy_v2_v2(GPU_vertbuf_raw_step(pos_step), (const float[2]){x2, y2});
copy_v4_v4(GPU_vertbuf_raw_step(col_step), color);
copy_v2_v2(GPU_vertbuf_raw_step(pos_step), (const float[2]){x1, y2});
copy_v4_v4(GPU_vertbuf_raw_step(col_step), color);
}
static GPUBatch *gpu_batch_preset_panel_drag_widget(float pixelsize,
const float col_high[4],
const float col_dark[4],
const float width)
{
GPUVertBuf *vbo = GPU_vertbuf_create_with_format(preset_2d_format());
const uint vbo_len = 4 * 2 * (6 * 2);
GPU_vertbuf_data_alloc(vbo, vbo_len);
GPUVertBufRaw pos_step, col_step;
GPU_vertbuf_attr_get_raw_data(vbo, g_presets_2d.attr_id.pos, &pos_step);
GPU_vertbuf_attr_get_raw_data(vbo, g_presets_2d.attr_id.col, &col_step);
const int px = (int)pixelsize;
const int px_zoom = max_ii(round_fl_to_int(width / 22.0f), 1);
const int box_margin = max_ii(round_fl_to_int((float)(px_zoom * 2.0f)), px);
const int box_size = max_ii(round_fl_to_int((width / 8.0f) - px), px);
const int y_ofs = max_ii(round_fl_to_int(width / 2.5f), px);
const int x_ofs = y_ofs;
int i_x, i_y;
for (i_x = 0; i_x < 4; i_x++) {
for (i_y = 0; i_y < 2; i_y++) {
const int x_co = (x_ofs) + (i_x * (box_size + box_margin));
const int y_co = (y_ofs) + (i_y * (box_size + box_margin));
gpu_batch_preset_rectf_tris_color_ex(&pos_step,
x_co - box_size,
y_co - px_zoom,
x_co,
(y_co + box_size) - px_zoom,
&col_step,
col_dark);
gpu_batch_preset_rectf_tris_color_ex(
&pos_step, x_co - box_size, y_co, x_co, y_co + box_size, &col_step, col_high);
}
}
return GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
GPUBatch *GPU_batch_preset_panel_drag_widget(const float pixelsize,
const float col_high[4],
const float col_dark[4],
const float width)
{
const bool parameters_changed = (g_presets_2d.panel_drag_widget_pixelsize != pixelsize) ||
(g_presets_2d.panel_drag_widget_width != width) ||
!equals_v4v4(g_presets_2d.panel_drag_widget_col_high,
col_high) ||
!equals_v4v4(g_presets_2d.panel_drag_widget_col_dark, col_dark);
if (g_presets_2d.batch.panel_drag_widget && parameters_changed) {
gpu_batch_presets_unregister(g_presets_2d.batch.panel_drag_widget);
g_presets_2d.batch.panel_drag_widget = NULL;
}
if (!g_presets_2d.batch.panel_drag_widget) {
g_presets_2d.batch.panel_drag_widget = gpu_batch_preset_panel_drag_widget(
pixelsize, col_high, col_dark, width);
gpu_batch_presets_register(g_presets_2d.batch.panel_drag_widget);
g_presets_2d.panel_drag_widget_pixelsize = pixelsize;
g_presets_2d.panel_drag_widget_width = width;
copy_v4_v4(g_presets_2d.panel_drag_widget_col_high, col_high);
copy_v4_v4(g_presets_2d.panel_drag_widget_col_dark, col_dark);
}
return g_presets_2d.batch.panel_drag_widget;
}
/** \} */
void gpu_batch_presets_init(void)
{
BLI_mutex_init(&g_presets_3d.mutex);