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:
authorJeroen Bakker <jbakker>2020-04-09 08:51:51 +0300
committerJeroen Bakker <j.bakker@atmind.nl>2020-04-09 20:12:51 +0300
commit862ec829422241878b3345661476d8551935aed2 (patch)
treea092bd6743180db8477e093935783b35f9326a63
parentbf68e1a54795bbe54badfbe6f97c2c2ee22c6e70 (diff)
GPUViewport: Use GPUBatch for viewport drawing
When drawing the viewport to the screen the draw calls were not batched. This resulted in measurable slowdown on Windows Intel 10th gen platforms. This patch would cache the last draw calls per viewport. Our API does support partial redrawing of the viewport, but that isn't used anywhere. This patch does not include stereoscopy rendering. This still uses the imm approach and would still be slow on certain hardware. Reviewed By: Clément Foucault Differential Revision: https://developer.blender.org/D7357
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c131
1 files changed, 103 insertions, 28 deletions
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index b2e1cb17946..fdbfa16a365 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -65,6 +65,24 @@ typedef struct ViewportTempTexture {
GPUTexture *texture;
} ViewportTempTexture;
+/* Struct storing a viewport specific GPUBatch.
+ * The end-goal is to have a single batch shared across viewport and use a model matrix to place
+ * the batch. Due to OCIO and Image/UV editor we are not able to use an model matrix yet. */
+struct GPUViewportBatch {
+ GPUBatch *batch;
+ struct {
+ rctf rect_pos;
+ rctf rect_uv;
+ } last_used_parameters;
+} GPUViewportBatch;
+
+static struct {
+ GPUVertFormat format;
+ struct {
+ uint pos, tex_coord;
+ } attr_id;
+} g_viewport = {{0}};
+
struct GPUViewport {
int size[2];
int flag;
@@ -97,6 +115,7 @@ struct GPUViewport {
/* TODO(fclem) the uvimage display use the viewport but do not set any view transform for the
* moment. The end goal would be to let the GPUViewport do the color management. */
bool do_color_management;
+ struct GPUViewportBatch batch;
};
enum {
@@ -625,6 +644,76 @@ void GPU_viewport_stereo_composite(GPUViewport *viewport, Stereo3dFormat *stereo
GPU_framebuffer_restore();
}
+/* -------------------------------------------------------------------- */
+/** \name Viewport Batches
+ * \{ */
+
+static GPUVertFormat *gpu_viewport_batch_format(void)
+{
+ if (g_viewport.format.attr_len == 0) {
+ GPUVertFormat *format = &g_viewport.format;
+ g_viewport.attr_id.pos = GPU_vertformat_attr_add(
+ format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ g_viewport.attr_id.tex_coord = GPU_vertformat_attr_add(
+ format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ }
+ return &g_viewport.format;
+}
+
+static GPUBatch *gpu_viewport_batch_create(const rctf *rect_pos, const rctf *rect_uv)
+{
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(gpu_viewport_batch_format());
+ const uint vbo_len = 4;
+ GPU_vertbuf_data_alloc(vbo, vbo_len);
+
+ GPUVertBufRaw pos_step, tex_coord_step;
+ GPU_vertbuf_attr_get_raw_data(vbo, g_viewport.attr_id.pos, &pos_step);
+ GPU_vertbuf_attr_get_raw_data(vbo, g_viewport.attr_id.tex_coord, &tex_coord_step);
+
+ copy_v2_fl2(GPU_vertbuf_raw_step(&pos_step), rect_pos->xmin, rect_pos->ymin);
+ copy_v2_fl2(GPU_vertbuf_raw_step(&tex_coord_step), rect_uv->xmin, rect_uv->ymin);
+ copy_v2_fl2(GPU_vertbuf_raw_step(&pos_step), rect_pos->xmax, rect_pos->ymin);
+ copy_v2_fl2(GPU_vertbuf_raw_step(&tex_coord_step), rect_uv->xmax, rect_uv->ymin);
+ copy_v2_fl2(GPU_vertbuf_raw_step(&pos_step), rect_pos->xmin, rect_pos->ymax);
+ copy_v2_fl2(GPU_vertbuf_raw_step(&tex_coord_step), rect_uv->xmin, rect_uv->ymax);
+ copy_v2_fl2(GPU_vertbuf_raw_step(&pos_step), rect_pos->xmax, rect_pos->ymax);
+ copy_v2_fl2(GPU_vertbuf_raw_step(&tex_coord_step), rect_uv->xmax, rect_uv->ymax);
+
+ return GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
+}
+
+static GPUBatch *gpu_viewport_batch_get(GPUViewport *viewport,
+ const rctf *rect_pos,
+ const rctf *rect_uv)
+{
+ const float compare_limit = 0.0001f;
+ const bool parameters_changed =
+ (!BLI_rctf_compare(
+ &viewport->batch.last_used_parameters.rect_pos, rect_pos, compare_limit) ||
+ !BLI_rctf_compare(&viewport->batch.last_used_parameters.rect_uv, rect_uv, compare_limit));
+
+ if (viewport->batch.batch && parameters_changed) {
+ GPU_batch_discard(viewport->batch.batch);
+ viewport->batch.batch = NULL;
+ }
+
+ if (!viewport->batch.batch) {
+ viewport->batch.batch = gpu_viewport_batch_create(rect_pos, rect_uv);
+ viewport->batch.last_used_parameters.rect_pos = *rect_pos;
+ viewport->batch.last_used_parameters.rect_uv = *rect_uv;
+ }
+ return viewport->batch.batch;
+}
+
+static void gpu_viewport_batch_free(GPUViewport *viewport)
+{
+ if (viewport->batch.batch) {
+ GPU_batch_discard(viewport->batch.batch);
+ viewport->batch.batch = NULL;
+ }
+}
+
+/** \} */
static void gpu_viewport_draw_colormanaged(GPUViewport *viewport,
const rctf *rect_pos,
@@ -635,10 +724,6 @@ static void gpu_viewport_draw_colormanaged(GPUViewport *viewport,
GPUTexture *color = dtxl->color;
GPUTexture *color_overlay = dtxl->color_overlay;
- GPUVertFormat *vert_format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(vert_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- uint texco = GPU_vertformat_attr_add(vert_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
bool use_ocio = false;
if (viewport->do_color_management && display_colorspace) {
@@ -650,38 +735,26 @@ static void gpu_viewport_draw_colormanaged(GPUViewport *viewport,
true);
}
- if (!use_ocio) {
- immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE);
- immUniform1i("display_transform", display_colorspace);
- immUniform1i("image_texture", 0);
- immUniform1i("overlays_texture", 1);
+ GPUBatch *batch = gpu_viewport_batch_get(viewport, rect_pos, rect_uv);
+ if (use_ocio) {
+ GPU_batch_program_set_imm_shader(batch);
+ }
+ else {
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE);
+ GPU_batch_uniform_1i(batch, "display_transform", display_colorspace);
+ GPU_batch_uniform_1i(batch, "image_texture", 0);
+ GPU_batch_uniform_1i(batch, "overlays_texture", 1);
}
GPU_texture_bind(color, 0);
GPU_texture_bind(color_overlay, 1);
-
- immBegin(GPU_PRIM_TRI_STRIP, 4);
-
- immAttr2f(texco, rect_uv->xmin, rect_uv->ymin);
- immVertex2f(pos, rect_pos->xmin, rect_pos->ymin);
- immAttr2f(texco, rect_uv->xmax, rect_uv->ymin);
- immVertex2f(pos, rect_pos->xmax, rect_pos->ymin);
- immAttr2f(texco, rect_uv->xmin, rect_uv->ymax);
- immVertex2f(pos, rect_pos->xmin, rect_pos->ymax);
- immAttr2f(texco, rect_uv->xmax, rect_uv->ymax);
- immVertex2f(pos, rect_pos->xmax, rect_pos->ymax);
-
- immEnd();
-
+ GPU_batch_draw(batch);
GPU_texture_unbind(color);
GPU_texture_unbind(color_overlay);
if (use_ocio) {
IMB_colormanagement_finish_glsl_draw();
}
- else {
- immUnbindProgram();
- }
}
/**
@@ -745,8 +818,8 @@ void GPU_viewport_draw_to_screen_ex(GPUViewport *viewport,
* Merge and draw the buffers of \a viewport into the currently active framebuffer, performing
* color transform to display space.
*
- * \param rect: Coordinates to draw into. By swapping min and max values, drawing can be done with
- * inversed axis coordinates (upside down or sideways).
+ * \param rect: Coordinates to draw into. By swapping min and max values, drawing can be done
+ * with inversed axis coordinates (upside down or sideways).
*/
void GPU_viewport_draw_to_screen(GPUViewport *viewport, int view, const rcti *rect)
{
@@ -923,5 +996,7 @@ void GPU_viewport_free(GPUViewport *viewport)
DRW_instance_data_list_free(viewport->idatalist);
MEM_freeN(viewport->idatalist);
+ gpu_viewport_batch_free(viewport);
+
MEM_freeN(viewport);
}