From ce34a6b0d727bbde6ae373afa8ec6c42bc8980ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Fri, 31 May 2019 01:45:41 +0200 Subject: DRW: Refactor to support draw call batching Reviewers: brecht Differential Revision: D4997 --- source/blender/draw/modes/edit_curve_mode.c | 2 +- source/blender/draw/modes/object_mode.c | 329 ++++++--------------- source/blender/draw/modes/overlay_mode.c | 26 +- .../draw/modes/shaders/common_view_lib.glsl | 67 +++++ .../modes/shaders/object_lightprobe_grid_vert.glsl | 12 +- .../modes/shaders/object_outline_detect_frag.glsl | 40 ++- .../modes/shaders/object_outline_prepass_frag.glsl | 14 +- .../modes/shaders/object_outline_prepass_geom.glsl | 7 +- .../modes/shaders/object_outline_prepass_vert.glsl | 17 +- 9 files changed, 218 insertions(+), 296 deletions(-) (limited to 'source/blender/draw/modes') diff --git a/source/blender/draw/modes/edit_curve_mode.c b/source/blender/draw/modes/edit_curve_mode.c index e68e03c2438..8933767bda8 100644 --- a/source/blender/draw/modes/edit_curve_mode.c +++ b/source/blender/draw/modes/edit_curve_mode.c @@ -126,7 +126,7 @@ static void EDIT_CURVE_engine_init(void *UNUSED(vedata)) datatoc_edit_curve_overlay_normals_vert_glsl, NULL}, .frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, NULL}, + .defs = (const char *[]){sh_cfg_data->def, "#define IN_PLACE_INSTANCES\n", NULL}, }); } diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c index 2b87e04b6b4..5c529892206 100644 --- a/source/blender/draw/modes/object_mode.c +++ b/source/blender/draw/modes/object_mode.c @@ -286,15 +286,10 @@ typedef struct OBJECT_PrivateData { DRWShadingGroup *outlines_transform; /* Lightprobes */ - DRWCallBuffer *lightprobes_cube_select; - DRWCallBuffer *lightprobes_cube_select_dupli; - DRWCallBuffer *lightprobes_cube_active; - DRWCallBuffer *lightprobes_cube_transform; - - DRWCallBuffer *lightprobes_planar_select; - DRWCallBuffer *lightprobes_planar_select_dupli; - DRWCallBuffer *lightprobes_planar_active; - DRWCallBuffer *lightprobes_planar_transform; + DRWShadingGroup *probe_outlines_transform; + DRWShadingGroup *probe_outlines_select; + DRWShadingGroup *probe_outlines_select_dupli; + DRWShadingGroup *probe_outlines_active; /* Objects Centers */ DRWCallBuffer *center_active; @@ -303,17 +298,6 @@ typedef struct OBJECT_PrivateData { DRWCallBuffer *center_selected_lib; DRWCallBuffer *center_deselected_lib; - /* Outlines id offset (accessed as an array) */ - int id_ofs_active; - int id_ofs_select; - int id_ofs_select_dupli; - int id_ofs_transform; - - int id_ofs_prb_active; - int id_ofs_prb_select; - int id_ofs_prb_select_dupli; - int id_ofs_prb_transform; - bool xray_enabled; bool xray_enabled_and_not_wire; } OBJECT_PrivateData; /* Transient data */ @@ -417,7 +401,10 @@ static void OBJECT_engine_init(void *vedata) if (!sh_data->outline_resolve) { /* Outline */ sh_data->outline_prepass = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_gpu_shader_3D_vert_glsl, NULL}, + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_view_lib_glsl, + datatoc_object_outline_prepass_vert_glsl, + NULL}, .frag = (const char *[]){datatoc_object_outline_prepass_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg_data->def, NULL}, }); @@ -431,7 +418,7 @@ static void OBJECT_engine_init(void *vedata) datatoc_object_outline_prepass_geom_glsl, NULL}, .frag = (const char *[]){datatoc_object_outline_prepass_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, NULL}, + .defs = (const char *[]){sh_cfg_data->def, "#define USE_GEOM\n", NULL}, }); sh_data->outline_resolve = DRW_shader_create_fullscreen( @@ -539,10 +526,11 @@ static void OBJECT_engine_init(void *vedata) /* Lightprobes */ sh_data->lightprobe_grid = GPU_shader_create_from_arrays({ .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_view_lib_glsl, datatoc_common_globals_lib_glsl, datatoc_object_lightprobe_grid_vert_glsl, NULL}, - .frag = (const char *[]){datatoc_gpu_shader_flat_id_frag_glsl, NULL}, + .frag = (const char *[]){datatoc_object_outline_prepass_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg_data->def, NULL}, }); @@ -697,12 +685,12 @@ static void OBJECT_engine_free(void) } static DRWShadingGroup *shgroup_outline(DRWPass *pass, - const int *ofs, + int outline_id, GPUShader *sh, eGPUShaderConfig sh_cfg) { DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); - DRW_shgroup_uniform_int(grp, "baseId", ofs, 1); + DRW_shgroup_uniform_int_copy(grp, "outlineId", outline_id); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); @@ -741,128 +729,89 @@ static DRWShadingGroup *shgroup_points(DRWPass *pass, return grp; } -static int *shgroup_theme_id_to_probe_outline_counter(OBJECT_StorageList *stl, - int theme_id, - const int base_flag) -{ - if (UNLIKELY(base_flag & BASE_FROM_DUPLI)) { - switch (theme_id) { - case TH_ACTIVE: - case TH_SELECT: - return &stl->g_data->id_ofs_prb_select_dupli; - case TH_TRANSFORM: - default: - return &stl->g_data->id_ofs_prb_transform; - } - } - - switch (theme_id) { - case TH_ACTIVE: - return &stl->g_data->id_ofs_prb_active; - case TH_SELECT: - return &stl->g_data->id_ofs_prb_select; - case TH_TRANSFORM: - default: - return &stl->g_data->id_ofs_prb_transform; - } -} - -static int *shgroup_theme_id_to_outline_counter(OBJECT_StorageList *stl, - int theme_id, - const int base_flag) +static DRWShadingGroup *shgroup_theme_id_to_outline_or_null(OBJECT_StorageList *stl, + int theme_id, + const int base_flag) { if (UNLIKELY(base_flag & BASE_FROM_DUPLI)) { switch (theme_id) { case TH_ACTIVE: case TH_SELECT: - return &stl->g_data->id_ofs_select_dupli; + return stl->g_data->outlines_select_dupli; case TH_TRANSFORM: + return stl->g_data->outlines_transform; default: - return &stl->g_data->id_ofs_transform; + return NULL; } } switch (theme_id) { case TH_ACTIVE: - return &stl->g_data->id_ofs_active; - case TH_SELECT: - return &stl->g_data->id_ofs_select; - case TH_TRANSFORM: - default: - return &stl->g_data->id_ofs_transform; - } -} - -static DRWCallBuffer *buffer_theme_id_to_probe_planar_outline_shgrp(OBJECT_StorageList *stl, - int theme_id) -{ - /* does not increment counter */ - switch (theme_id) { - case TH_ACTIVE: - return stl->g_data->lightprobes_planar_active; + return stl->g_data->outlines_active; case TH_SELECT: - return stl->g_data->lightprobes_planar_select; + return stl->g_data->outlines_select; case TH_TRANSFORM: + return stl->g_data->outlines_transform; default: - return stl->g_data->lightprobes_planar_transform; + return NULL; } } -static DRWCallBuffer *buffer_theme_id_to_probe_cube_outline_shgrp(OBJECT_StorageList *stl, +static DRWShadingGroup *shgroup_theme_id_to_probe_outline_or_null(OBJECT_StorageList *stl, int theme_id, const int base_flag) { - /* does not increment counter */ + if (UNLIKELY(DRW_state_is_select())) { + return stl->g_data->probe_outlines_select; + } + if (UNLIKELY(base_flag & BASE_FROM_DUPLI)) { switch (theme_id) { case TH_ACTIVE: case TH_SELECT: - return stl->g_data->lightprobes_cube_select_dupli; + return stl->g_data->probe_outlines_select_dupli; case TH_TRANSFORM: + return stl->g_data->probe_outlines_transform; default: - return stl->g_data->lightprobes_cube_transform; + return NULL; } } switch (theme_id) { case TH_ACTIVE: - return stl->g_data->lightprobes_cube_active; + return stl->g_data->probe_outlines_active; case TH_SELECT: - return stl->g_data->lightprobes_cube_select; + return stl->g_data->probe_outlines_select; case TH_TRANSFORM: + return stl->g_data->probe_outlines_transform; default: - return stl->g_data->lightprobes_cube_transform; + return NULL; } } -static DRWShadingGroup *shgroup_theme_id_to_outline_or_null(OBJECT_StorageList *stl, - int theme_id, - const int base_flag) +static int shgroup_theme_id_to_outline_id(int theme_id, const int base_flag) { - int *counter = shgroup_theme_id_to_outline_counter(stl, theme_id, base_flag); - *counter += 1; - if (UNLIKELY(base_flag & BASE_FROM_DUPLI)) { switch (theme_id) { case TH_ACTIVE: case TH_SELECT: - return stl->g_data->outlines_select_dupli; + return 2; case TH_TRANSFORM: - return stl->g_data->outlines_transform; + return 0; default: - return NULL; + return -1; } } switch (theme_id) { case TH_ACTIVE: - return stl->g_data->outlines_active; + return 3; case TH_SELECT: - return stl->g_data->outlines_select; + return 1; case TH_TRANSFORM: - return stl->g_data->outlines_transform; + return 0; default: - return NULL; + return -1; } } @@ -1346,7 +1295,8 @@ static void OBJECT_cache_init(void *vedata) DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); OBJECT_PrivateData *g_data; const DRWContextState *draw_ctx = DRW_context_state_get(); - OBJECT_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; + eGPUShaderConfig cfg = draw_ctx->sh_cfg; + OBJECT_Shaders *sh_data = &e_data.sh_data[cfg]; const float outline_width = UI_GetThemeValuef(TH_OUTLINE_WIDTH); const bool do_outline_expand = (U.pixelsize > 1.0) || (outline_width > 2.0f); @@ -1367,59 +1317,25 @@ static void OBJECT_cache_init(void *vedata) { DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; - psl->outlines = DRW_pass_create("Outlines Depth Pass", state); + psl->lightprobes = DRW_pass_create("Outlines Probe Pass", state); GPUShader *sh = sh_data->outline_prepass; + g_data->probe_outlines_transform = shgroup_outline(psl->lightprobes, 0, sh, cfg); + g_data->probe_outlines_select = shgroup_outline(psl->lightprobes, 1, sh, cfg); + g_data->probe_outlines_select_dupli = shgroup_outline(psl->lightprobes, 2, sh, cfg); + g_data->probe_outlines_active = shgroup_outline(psl->lightprobes, 3, sh, cfg); + + psl->outlines = DRW_pass_create("Outlines Depth Pass", state); + if (g_data->xray_enabled_and_not_wire) { sh = sh_data->outline_prepass_wire; } - g_data->outlines_select = shgroup_outline( - psl->outlines, &g_data->id_ofs_select, sh, draw_ctx->sh_cfg); - g_data->outlines_select_dupli = shgroup_outline( - psl->outlines, &g_data->id_ofs_select_dupli, sh, draw_ctx->sh_cfg); - g_data->outlines_transform = shgroup_outline( - psl->outlines, &g_data->id_ofs_transform, sh, draw_ctx->sh_cfg); - g_data->outlines_active = shgroup_outline( - psl->outlines, &g_data->id_ofs_active, sh, draw_ctx->sh_cfg); - - g_data->id_ofs_select = 0; - g_data->id_ofs_select_dupli = 0; - g_data->id_ofs_active = 0; - g_data->id_ofs_transform = 0; - } - - { - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; - DRWPass *pass = psl->lightprobes = DRW_pass_create("Object Probe Pass", state); - struct GPUBatch *sphere = DRW_cache_sphere_get(); - struct GPUBatch *quad = DRW_cache_quad_get(); - - /* Cubemap */ - g_data->lightprobes_cube_select = buffer_instance_outline( - pass, sphere, &g_data->id_ofs_prb_select, draw_ctx->sh_cfg); - g_data->lightprobes_cube_select_dupli = buffer_instance_outline( - pass, sphere, &g_data->id_ofs_prb_select_dupli, draw_ctx->sh_cfg); - g_data->lightprobes_cube_active = buffer_instance_outline( - pass, sphere, &g_data->id_ofs_prb_active, draw_ctx->sh_cfg); - g_data->lightprobes_cube_transform = buffer_instance_outline( - pass, sphere, &g_data->id_ofs_prb_transform, draw_ctx->sh_cfg); - - /* Planar */ - g_data->lightprobes_planar_select = buffer_instance_outline( - pass, quad, &g_data->id_ofs_prb_select, draw_ctx->sh_cfg); - g_data->lightprobes_planar_select_dupli = buffer_instance_outline( - pass, quad, &g_data->id_ofs_prb_select_dupli, draw_ctx->sh_cfg); - g_data->lightprobes_planar_active = buffer_instance_outline( - pass, quad, &g_data->id_ofs_prb_active, draw_ctx->sh_cfg); - g_data->lightprobes_planar_transform = buffer_instance_outline( - pass, quad, &g_data->id_ofs_prb_transform, draw_ctx->sh_cfg); - - g_data->id_ofs_prb_select = 0; - g_data->id_ofs_prb_select_dupli = 0; - g_data->id_ofs_prb_active = 0; - g_data->id_ofs_prb_transform = 0; + g_data->outlines_transform = shgroup_outline(psl->outlines, 0, sh, cfg); + g_data->outlines_select = shgroup_outline(psl->outlines, 1, sh, cfg); + g_data->outlines_select_dupli = shgroup_outline(psl->outlines, 2, sh, cfg); + g_data->outlines_active = shgroup_outline(psl->outlines, 3, sh, cfg); } { @@ -1438,7 +1354,6 @@ static void OBJECT_cache_init(void *vedata) DRW_shgroup_uniform_texture_ref(grp, "sceneDepth", &dtxl->depth); DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); DRW_shgroup_uniform_float_copy(grp, "alphaOcclu", alphaOcclu); - DRW_shgroup_uniform_int(grp, "idOffsets", &stl->g_data->id_ofs_active, 4); DRW_shgroup_call(grp, quad, NULL); /* This is the bleed pass if do_outline_expand is false. */ @@ -2766,15 +2681,6 @@ static void DRW_shgroup_speaker(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLa DRW_buffer_add_entry(sgl->speaker, color, &one, ob->obmat); } -typedef struct OBJECT_LightProbeEngineData { - DrawData dd; - - float increment_x[3]; - float increment_y[3]; - float increment_z[3]; - float corner[3]; -} OBJECT_LightProbeEngineData; - static void DRW_shgroup_lightprobe(OBJECT_Shaders *sh_data, OBJECT_StorageList *stl, OBJECT_PassList *psl, @@ -2791,13 +2697,10 @@ static void DRW_shgroup_lightprobe(OBJECT_Shaders *sh_data, OBJECT_ShadingGroupList *sgl = (ob->dtx & OB_DRAWXRAY) ? &stl->g_data->sgl_ghost : &stl->g_data->sgl; - OBJECT_LightProbeEngineData *prb_data = (OBJECT_LightProbeEngineData *)DRW_drawdata_ensure( - &ob->id, &draw_engine_object_type, sizeof(OBJECT_LightProbeEngineData), NULL, NULL); - if (DRW_state_is_select() || do_outlines) { - int *call_id = shgroup_theme_id_to_probe_outline_counter(stl, theme_id, ob->base_flag); - if (prb->type == LIGHTPROBE_TYPE_GRID) { + float corner[3]; + float increment[3][3]; /* Update transforms */ float cell_dim[3], half_cell_dim[3]; cell_dim[0] = 2.0f / (float)(prb->grid_resolution_x); @@ -2807,65 +2710,40 @@ static void DRW_shgroup_lightprobe(OBJECT_Shaders *sh_data, mul_v3_v3fl(half_cell_dim, cell_dim, 0.5f); /* First cell. */ - copy_v3_fl(prb_data->corner, -1.0f); - add_v3_v3(prb_data->corner, half_cell_dim); - mul_m4_v3(ob->obmat, prb_data->corner); + copy_v3_fl(corner, -1.0f); + add_v3_v3(corner, half_cell_dim); + mul_m4_v3(ob->obmat, corner); /* Opposite neighbor cell. */ - copy_v3_fl3(prb_data->increment_x, cell_dim[0], 0.0f, 0.0f); - add_v3_v3(prb_data->increment_x, half_cell_dim); - add_v3_fl(prb_data->increment_x, -1.0f); - mul_m4_v3(ob->obmat, prb_data->increment_x); - sub_v3_v3(prb_data->increment_x, prb_data->corner); - - copy_v3_fl3(prb_data->increment_y, 0.0f, cell_dim[1], 0.0f); - add_v3_v3(prb_data->increment_y, half_cell_dim); - add_v3_fl(prb_data->increment_y, -1.0f); - mul_m4_v3(ob->obmat, prb_data->increment_y); - sub_v3_v3(prb_data->increment_y, prb_data->corner); - - copy_v3_fl3(prb_data->increment_z, 0.0f, 0.0f, cell_dim[2]); - add_v3_v3(prb_data->increment_z, half_cell_dim); - add_v3_fl(prb_data->increment_z, -1.0f); - mul_m4_v3(ob->obmat, prb_data->increment_z); - sub_v3_v3(prb_data->increment_z, prb_data->corner); + copy_v3_fl3(increment[0], cell_dim[0], 0.0f, 0.0f); + copy_v3_fl3(increment[1], 0.0f, cell_dim[1], 0.0f); + copy_v3_fl3(increment[2], 0.0f, 0.0f, cell_dim[2]); + for (int i = 0; i < 3; i++) { + add_v3_v3(increment[i], half_cell_dim); + add_v3_fl(increment[i], -1.0f); + mul_m4_v3(ob->obmat, increment[i]); + sub_v3_v3(increment[i], corner); + } + + int outline_id = shgroup_theme_id_to_outline_id(theme_id, ob->base_flag); uint cell_count = prb->grid_resolution_x * prb->grid_resolution_y * prb->grid_resolution_z; DRWShadingGroup *grp = DRW_shgroup_create(sh_data->lightprobe_grid, psl->lightprobes); - DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); - DRW_shgroup_uniform_int_copy(grp, "call_id", *call_id); - DRW_shgroup_uniform_int(grp, "baseId", call_id, 1); /* that's correct */ - DRW_shgroup_uniform_vec3(grp, "corner", prb_data->corner, 1); - DRW_shgroup_uniform_vec3(grp, "increment_x", prb_data->increment_x, 1); - DRW_shgroup_uniform_vec3(grp, "increment_y", prb_data->increment_y, 1); - DRW_shgroup_uniform_vec3(grp, "increment_z", prb_data->increment_z, 1); - DRW_shgroup_uniform_ivec3(grp, "grid_resolution", &prb->grid_resolution_x, 1); + DRW_shgroup_uniform_int_copy(grp, "outlineId", outline_id); + DRW_shgroup_uniform_vec3_copy(grp, "corner", corner); + DRW_shgroup_uniform_vec3_copy(grp, "increment_x", increment[0]); + DRW_shgroup_uniform_vec3_copy(grp, "increment_y", increment[1]); + DRW_shgroup_uniform_vec3_copy(grp, "increment_z", increment[2]); + DRW_shgroup_uniform_ivec3_copy(grp, "grid_resolution", &prb->grid_resolution_x); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } DRW_shgroup_call_procedural_points(grp, NULL, cell_count); - *call_id += 1; } - else if (prb->type == LIGHTPROBE_TYPE_CUBE) { - float draw_size = 1.0f; - float probe_cube_mat[4][4]; - // prb_data->draw_size = prb->data_draw_size * 0.1f; - // unit_m4(prb_data->probe_cube_mat); - // copy_v3_v3(prb_data->probe_cube_mat[3], ob->obmat[3]); - - DRWCallBuffer *buf = buffer_theme_id_to_probe_cube_outline_shgrp( + else if (prb->type == LIGHTPROBE_TYPE_PLANAR && (prb->flag & LIGHTPROBE_FLAG_SHOW_DATA)) { + DRWShadingGroup *grp = shgroup_theme_id_to_probe_outline_or_null( stl, theme_id, ob->base_flag); - /* TODO remove or change the drawing of the cube probes. This line draws nothing on purpose - * to keep the call ids correct. */ - zero_m4(probe_cube_mat); - DRW_buffer_add_entry(buf, call_id, &draw_size, probe_cube_mat); - *call_id += 1; - } - else if (prb->flag & LIGHTPROBE_FLAG_SHOW_DATA) { - float draw_size = 1.0f; - DRWCallBuffer *buf = buffer_theme_id_to_probe_planar_outline_shgrp(stl, theme_id); - DRW_buffer_add_entry(buf, call_id, &draw_size, ob->obmat); - *call_id += 1; + DRW_shgroup_call_no_cull(grp, DRW_cache_quad_get(), ob); } } @@ -3782,19 +3660,7 @@ static void OBJECT_draw_scene(void *vedata) DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - int id_len_select = g_data->id_ofs_select; - int id_len_select_dupli = g_data->id_ofs_select_dupli; - int id_len_active = g_data->id_ofs_active; - int id_len_transform = g_data->id_ofs_transform; - - int id_len_prb_select = g_data->id_ofs_prb_select; - int id_len_prb_select_dupli = g_data->id_ofs_prb_select_dupli; - int id_len_prb_active = g_data->id_ofs_prb_active; - int id_len_prb_transform = g_data->id_ofs_prb_transform; - - int outline_calls = id_len_select + id_len_select_dupli + id_len_active + id_len_transform; - outline_calls += id_len_prb_select + id_len_prb_select_dupli + id_len_prb_active + - id_len_prb_transform; + int do_outlines = !DRW_pass_is_empty(psl->outlines) || !DRW_pass_is_empty(psl->lightprobes); float clearcol[4] = {0.0f, 0.0f, 0.0f, 0.0f}; @@ -3802,35 +3668,24 @@ static void OBJECT_draw_scene(void *vedata) /* Don't draw Transparent passes in MSAA buffer. */ // DRW_draw_pass(psl->bone_envelope); /* Never drawn in Object mode currently. */ - DRW_draw_pass(stl->g_data->sgl.transp_shapes); + DRW_draw_pass(g_data->sgl.transp_shapes); MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl); - DRW_draw_pass(stl->g_data->sgl.bone_solid); - DRW_draw_pass(stl->g_data->sgl.bone_wire); - DRW_draw_pass(stl->g_data->sgl.bone_outline); - DRW_draw_pass(stl->g_data->sgl.non_meshes); + DRW_draw_pass(g_data->sgl.bone_solid); + DRW_draw_pass(g_data->sgl.bone_wire); + DRW_draw_pass(g_data->sgl.bone_outline); + DRW_draw_pass(g_data->sgl.non_meshes); DRW_draw_pass(psl->particle); - DRW_draw_pass(stl->g_data->sgl.bone_axes); + DRW_draw_pass(g_data->sgl.bone_axes); MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl); - DRW_draw_pass(stl->g_data->sgl.image_empties); + DRW_draw_pass(g_data->sgl.image_empties); - if (DRW_state_is_fbo() && outline_calls > 0) { + if (DRW_state_is_fbo() && do_outlines) { DRW_stats_group_start("Outlines"); - g_data->id_ofs_active = 1; - g_data->id_ofs_select = g_data->id_ofs_active + id_len_active + id_len_prb_active + 1; - g_data->id_ofs_select_dupli = g_data->id_ofs_select + id_len_select + id_len_prb_select + 1; - g_data->id_ofs_transform = g_data->id_ofs_select_dupli + id_len_select_dupli + - id_len_prb_select_dupli + 1; - - g_data->id_ofs_prb_active = g_data->id_ofs_active + id_len_active; - g_data->id_ofs_prb_select = g_data->id_ofs_select + id_len_select; - g_data->id_ofs_prb_select_dupli = g_data->id_ofs_select_dupli + id_len_select_dupli; - g_data->id_ofs_prb_transform = g_data->id_ofs_transform + id_len_transform; - /* Render filled polygon on a separate framebuffer */ GPU_framebuffer_bind(fbl->outlines_fb); GPU_framebuffer_clear_color_depth(fbl->outlines_fb, clearcol, 1.0f); @@ -3865,7 +3720,7 @@ static void OBJECT_draw_scene(void *vedata) } /* Combine with scene buffer last */ - if (outline_calls > 0) { + if (do_outlines) { DRW_draw_pass(psl->outlines_resolve); } } diff --git a/source/blender/draw/modes/overlay_mode.c b/source/blender/draw/modes/overlay_mode.c index a5b1133abf4..2433f4c1df5 100644 --- a/source/blender/draw/modes/overlay_mode.c +++ b/source/blender/draw/modes/overlay_mode.c @@ -23,8 +23,6 @@ #include "DNA_mesh_types.h" #include "DNA_view3d_types.h" -#include "BIF_glutil.h" - #include "BKE_editmesh.h" #include "BKE_global.h" #include "BKE_object.h" @@ -77,7 +75,6 @@ typedef struct OVERLAY_PrivateData { DRWShadingGroup *face_wires_shgrp; DRWShadingGroup *face_wires_xray_shgrp; DRWView *view_wires; - BLI_mempool *wire_color_mempool; View3DOverlay overlay; float wire_step_param; bool clear_stencil; @@ -208,10 +205,6 @@ static void overlay_cache_init(void *vedata) if (v3d->shading.type == OB_WIRE) { g_data->overlay.flag |= V3D_OVERLAY_WIREFRAMES; - - if (ELEM(v3d->shading.wire_color_type, V3D_SHADING_OBJECT_COLOR, V3D_SHADING_RANDOM_COLOR)) { - g_data->wire_color_mempool = BLI_mempool_create(sizeof(float[3]), 0, 512, 0); - } } { @@ -256,7 +249,6 @@ static void overlay_cache_init(void *vedata) } static void overlay_wire_color_get(const View3D *v3d, - const OVERLAY_PrivateData *pd, const Object *ob, const bool use_coloring, float **rim_col, @@ -305,8 +297,10 @@ static void overlay_wire_color_get(const View3D *v3d, if (v3d->shading.type == OB_WIRE) { if (ELEM(v3d->shading.wire_color_type, V3D_SHADING_OBJECT_COLOR, V3D_SHADING_RANDOM_COLOR)) { - *wire_col = BLI_mempool_alloc(pd->wire_color_mempool); - *rim_col = BLI_mempool_alloc(pd->wire_color_mempool); + /* Theses stays valid until next call. So we need to copy them when using them as uniform. */ + static float wire_col_val[3], rim_col_val[3]; + *wire_col = wire_col_val; + *rim_col = rim_col_val; if (v3d->shading.wire_color_type == V3D_SHADING_OBJECT_COLOR) { linearrgb_to_srgb_v3_v3(*wire_col, ob->color); @@ -427,9 +421,9 @@ static void overlay_cache_populate(void *vedata, Object *ob) if (!(DRW_state_is_select() || DRW_state_is_depth())) { float *rim_col, *wire_col; - overlay_wire_color_get(v3d, pd, ob, use_coloring, &rim_col, &wire_col); - DRW_shgroup_uniform_vec3(shgrp, "wireColor", wire_col, 1); - DRW_shgroup_uniform_vec3(shgrp, "rimColor", rim_col, 1); + overlay_wire_color_get(v3d, ob, use_coloring, &rim_col, &wire_col); + DRW_shgroup_uniform_vec3_copy(shgrp, "wireColor", wire_col); + DRW_shgroup_uniform_vec3_copy(shgrp, "rimColor", rim_col); DRW_shgroup_stencil_mask(shgrp, (is_xray && (is_wire || !pd->clear_stencil)) ? 0x00 : 0xFF); } @@ -506,12 +500,6 @@ static void overlay_draw_scene(void *vedata) /* TODO(fclem): find a way to unify the multisample pass together * (non meshes + armature + wireframe) */ MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl); - - /* XXX TODO(fclem) do not discard data after drawing! Store them per viewport. */ - if (stl->g_data->wire_color_mempool) { - BLI_mempool_destroy(stl->g_data->wire_color_mempool); - stl->g_data->wire_color_mempool = NULL; - } } static void overlay_engine_free(void) diff --git a/source/blender/draw/modes/shaders/common_view_lib.glsl b/source/blender/draw/modes/shaders/common_view_lib.glsl index 20a54947db7..a554db7d4a4 100644 --- a/source/blender/draw/modes/shaders/common_view_lib.glsl +++ b/source/blender/draw/modes/shaders/common_view_lib.glsl @@ -1,4 +1,5 @@ #define COMMON_VIEW_LIB +#define DRW_RESOURCE_CHUNK_LEN 512 /* keep in sync with DRWManager.view_data */ layout(std140) uniform viewBlock @@ -23,8 +24,74 @@ layout(std140) uniform viewBlock _world_clip_planes_calc_clip_distance(p, clipPlanes) #endif +uniform int resourceChunk; + +#ifdef GPU_VERTEX_SHADER +# ifdef GL_ARB_shader_draw_parameters +# define baseInstance gl_BaseInstanceARB +# else /* no ARB_shader_draw_parameters */ +uniform int baseInstance; +# endif + +# ifdef IN_PLACE_INSTANCES +/* When drawing instances of an object at the same position. */ +# define instanceId 0 +# elif defined(GPU_CRAPPY_AMD_DRIVER) +/* NOTE: This does contain the baseInstance ofset */ +in int _instanceId; +# define instanceId (_instanceId - baseInstance) +# else +# define instanceId gl_InstanceID +# endif + +# define resource_id (baseInstance + instanceId) + +/* Use this to declare and pass the value if + * the fragment shader uses the resource_id. */ +# define RESOURCE_ID_VARYING flat out int resourceIDFrag; +# define RESOURCE_ID_VARYING_GEOM flat out int resourceIDGeom; +# define PASS_RESOURCE_ID resourceIDFrag = resource_id; +# define PASS_RESOURCE_ID_GEOM resourceIDGeom = resource_id; +#endif + +/* If used in a fragment / geometry shader, we pass + * resource_id as varying. */ +#ifdef GPU_GEOMETRY_SHADER +# define RESOURCE_ID_VARYING \ + flat out int resourceIDFrag; \ + flat in int resourceIDGeom[]; + +# define resource_id resourceIDGeom +# define PASS_RESOURCE_ID(i) resourceIDFrag = resource_id[i]; +#endif + +#ifdef GPU_FRAGMENT_SHADER +flat in int resourceIDFrag; +# define resource_id resourceIDFrag +#endif + +#ifndef GPU_INTEL +struct ObjectMatrices { + mat4 drw_modelMatrix; + mat4 drw_modelMatrixInverse; +}; + +layout(std140) uniform modelBlock +{ + ObjectMatrices drw_matrices[DRW_RESOURCE_CHUNK_LEN]; +}; + +# define ModelMatrix (drw_matrices[resource_id].drw_modelMatrix) +# define ModelMatrixInverse (drw_matrices[resource_id].drw_modelMatrixInverse) + +#else /* GPU_INTEL */ +/* Intel GPU seems to suffer performance impact when the model matrix is in UBO storage. + * So for now we just force using the legacy path. */ uniform mat4 ModelMatrix; uniform mat4 ModelMatrixInverse; +#endif + +#define resource_handle (resourceChunk * DRW_RESOURCE_CHUNK_LEN + resource_id) /** Transform shortcuts. */ /* Rule of thumb: Try to reuse world positions and normals because converting though viewspace diff --git a/source/blender/draw/modes/shaders/object_lightprobe_grid_vert.glsl b/source/blender/draw/modes/shaders/object_lightprobe_grid_vert.glsl index d27d55c3fd6..144024a7d5d 100644 --- a/source/blender/draw/modes/shaders/object_lightprobe_grid_vert.glsl +++ b/source/blender/draw/modes/shaders/object_lightprobe_grid_vert.glsl @@ -1,18 +1,11 @@ -uniform mat4 ViewProjectionMatrix; - -uniform float sphere_size; uniform ivec3 grid_resolution; uniform vec3 corner; uniform vec3 increment_x; uniform vec3 increment_y; uniform vec3 increment_z; -uniform vec3 screen_vecs[2]; - -uniform int call_id; /* we don't want the builtin callId which would be 0. */ -uniform int baseId; -flat out uint finalId; +flat out int objectId; void main() { @@ -29,7 +22,8 @@ void main() gl_Position = ViewProjectionMatrix * vec4(ws_cell_location, 1.0); gl_PointSize = 2.0f; - finalId = uint(baseId + call_id); + /* ID 0 is nothing (background) */ + objectId = resource_handle + 1; #ifdef USE_WORLD_CLIP_PLANES world_clip_planes_calc_clip_distance(ws_cell_location); diff --git a/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl b/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl index 7668a0c2c94..7b86d477a39 100644 --- a/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl +++ b/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl @@ -7,30 +7,9 @@ uniform usampler2D outlineId; uniform sampler2D outlineDepth; uniform sampler2D sceneDepth; -uniform int idOffsets[4]; - uniform float alphaOcclu; uniform vec2 viewportSize; -vec4 convert_id_to_color(int id) -{ - if (id == 0) { - return vec4(0.0); - } - if (id < idOffsets[1]) { - return colorActive; - } - else if (id < idOffsets[2]) { - return colorSelect; - } - else if (id < idOffsets[3]) { - return colorDupliSelect; - } - else { - return colorTransform; - } -} - void main() { ivec2 texel = ivec2(gl_FragCoord.xy); @@ -85,7 +64,24 @@ void main() const float epsilon = 3.0 / 8388608.0; bool occluded = (ref_depth > scene_depth + epsilon); - FragColor = convert_id_to_color(int(ref_id)); + /* WATCH: Keep in sync with outlineId of the prepass. */ + uint color_id = ref_id >> 14u; + if (ref_id == 0u) { + FragColor = vec4(0.0); + } + else if (color_id == 1u) { + FragColor = colorSelect; + } + else if (color_id == 2u) { + FragColor = colorDupliSelect; + } + else if (color_id == 3u) { + FragColor = colorActive; + } + else { + FragColor = colorTransform; + } + FragColor.a *= (occluded) ? alphaOcclu : 1.0; FragColor.a = (outline) ? FragColor.a : 0.0; } diff --git a/source/blender/draw/modes/shaders/object_outline_prepass_frag.glsl b/source/blender/draw/modes/shaders/object_outline_prepass_frag.glsl index c3447456ea6..5d6c4881b5b 100644 --- a/source/blender/draw/modes/shaders/object_outline_prepass_frag.glsl +++ b/source/blender/draw/modes/shaders/object_outline_prepass_frag.glsl @@ -1,10 +1,18 @@ -uniform int callId; -uniform int baseId; + +/* Should be 2 bits only [0..3]. */ +uniform int outlineId; + +flat in int objectId; /* using uint because 16bit uint can contain more ids than int. */ out uint outId; +/* Replace top 2 bits (of the 16bit output) by outlineId. + * This leaves 16K different IDs to create outlines between objects. + * SHIFT = (32 - (16 - 2)) */ +#define SHIFT 18u + void main() { - outId = uint(baseId + callId); + outId = (uint(outlineId) << 14u) | ((uint(objectId) << SHIFT) >> SHIFT); } diff --git a/source/blender/draw/modes/shaders/object_outline_prepass_geom.glsl b/source/blender/draw/modes/shaders/object_outline_prepass_geom.glsl index 5a3eb38fb6b..b32913dcd60 100644 --- a/source/blender/draw/modes/shaders/object_outline_prepass_geom.glsl +++ b/source/blender/draw/modes/shaders/object_outline_prepass_geom.glsl @@ -2,12 +2,15 @@ layout(lines_adjacency) in; layout(line_strip, max_vertices = 2) out; -in vec4 pPos[]; in vec3 vPos[]; +in int objectId_g[]; + +flat out int objectId; void vert_from_gl_in(int v) { - gl_Position = pPos[v]; + gl_Position = gl_in[v].gl_Position; + objectId = objectId_g[v]; #ifdef USE_WORLD_CLIP_PLANES world_clip_planes_set_clip_distance(gl_in[v].gl_ClipDistance); #endif diff --git a/source/blender/draw/modes/shaders/object_outline_prepass_vert.glsl b/source/blender/draw/modes/shaders/object_outline_prepass_vert.glsl index e34afe95b5e..7740f9a4af2 100644 --- a/source/blender/draw/modes/shaders/object_outline_prepass_vert.glsl +++ b/source/blender/draw/modes/shaders/object_outline_prepass_vert.glsl @@ -1,16 +1,27 @@ in vec3 pos; -out vec4 pPos; +#ifdef USE_GEOM out vec3 vPos; +out int objectId_g; +# define objectId objectId_g +#else + +flat out int objectId; +#endif void main() { vec3 world_pos = point_object_to_world(pos); +#ifdef USE_GEOM vPos = point_world_to_view(world_pos); - pPos = point_world_to_ndc(world_pos); +#endif + gl_Position = point_world_to_ndc(world_pos); /* Small bias to always be on top of the geom. */ - pPos.z -= 1e-3; + gl_Position.z -= 1e-3; + + /* ID 0 is nothing (background) */ + objectId = resource_handle + 1; #ifdef USE_WORLD_CLIP_PLANES world_clip_planes_calc_clip_distance(world_pos); -- cgit v1.2.3