diff options
Diffstat (limited to 'source')
57 files changed, 1241 insertions, 2263 deletions
diff --git a/source/blender/blenlib/BLI_memblock.h b/source/blender/blenlib/BLI_memblock.h index 8bd8642a4e8..c5ef26ffb91 100644 --- a/source/blender/blenlib/BLI_memblock.h +++ b/source/blender/blenlib/BLI_memblock.h @@ -30,20 +30,16 @@ extern "C" { #include "BLI_compiler_attrs.h" -#define BLI_MEM_BLOCK_CHUNK_SIZE (1 << 15) /* 32KiB */ - struct BLI_memblock; typedef struct BLI_memblock BLI_memblock; typedef void (*MemblockValFreeFP)(void *val); -BLI_memblock *BLI_memblock_create_ex(uint elem_size, uint chunk_size) ATTR_WARN_UNUSED_RESULT; -void *BLI_memblock_alloc(BLI_memblock *mblk) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); +BLI_memblock *BLI_memblock_create(uint elem_size) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; +void *BLI_memblock_alloc(BLI_memblock *mblk) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); void BLI_memblock_clear(BLI_memblock *mblk, MemblockValFreeFP valfreefp) ATTR_NONNULL(1); void BLI_memblock_destroy(BLI_memblock *mblk, MemblockValFreeFP free_callback) ATTR_NONNULL(1); -#define BLI_memblock_create(elem_size) BLI_memblock_create_ex(elem_size, BLI_MEM_BLOCK_CHUNK_SIZE) - typedef struct BLI_memblock_iter { void **chunk_list; int cur_index; @@ -57,9 +53,6 @@ typedef struct BLI_memblock_iter { void BLI_memblock_iternew(BLI_memblock *pool, BLI_memblock_iter *iter) ATTR_NONNULL(); void *BLI_memblock_iterstep(BLI_memblock_iter *iter) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -void *BLI_memblock_elem_get(BLI_memblock *mblk, int chunk, int elem) ATTR_WARN_UNUSED_RESULT - ATTR_NONNULL(); - #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/intern/BLI_memblock.c b/source/blender/blenlib/intern/BLI_memblock.c index f7239f1b9d1..f26860afe77 100644 --- a/source/blender/blenlib/intern/BLI_memblock.c +++ b/source/blender/blenlib/intern/BLI_memblock.c @@ -37,6 +37,7 @@ #include "BLI_strict_flags.h" /* keep last */ +#define BLI_MEM_BLOCK_CHUNK_SIZE (1 << 15) /* 32KiB */ #define CHUNK_LIST_SIZE 16 struct BLI_memblock { @@ -60,19 +61,18 @@ struct BLI_memblock { int chunk_len; }; -BLI_memblock *BLI_memblock_create_ex(uint elem_size, uint chunk_size) +BLI_memblock *BLI_memblock_create(uint elem_size) { - BLI_assert(elem_size < chunk_size); + BLI_assert(elem_size < BLI_MEM_BLOCK_CHUNK_SIZE); BLI_memblock *mblk = MEM_mallocN(sizeof(BLI_memblock), "BLI_memblock"); mblk->elem_size = (int)elem_size; mblk->elem_next = 0; mblk->elem_last = -1; - mblk->chunk_size = (int)chunk_size; + mblk->chunk_size = BLI_MEM_BLOCK_CHUNK_SIZE; mblk->chunk_len = CHUNK_LIST_SIZE; mblk->chunk_list = MEM_callocN(sizeof(void *) * (uint)mblk->chunk_len, "chunk list"); - mblk->chunk_list[0] = MEM_mallocN_aligned((uint)mblk->chunk_size, 32, "BLI_memblock chunk"); - memset(mblk->chunk_list[0], 0x0, (uint)mblk->chunk_size); + mblk->chunk_list[0] = MEM_callocN((uint)mblk->chunk_size, "BLI_memblock chunk"); mblk->chunk_max_ofs = (mblk->chunk_size / mblk->elem_size) * mblk->elem_size; mblk->elem_next_ofs = 0; mblk->chunk_next = 0; @@ -143,9 +143,8 @@ void *BLI_memblock_alloc(BLI_memblock *mblk) } if (UNLIKELY(mblk->chunk_list[mblk->chunk_next] == NULL)) { - mblk->chunk_list[mblk->chunk_next] = MEM_mallocN_aligned( - (uint)mblk->chunk_size, 32, "BLI_memblock chunk"); - memset(mblk->chunk_list[mblk->chunk_next], 0x0, (uint)mblk->chunk_size); + mblk->chunk_list[mblk->chunk_next] = MEM_callocN((uint)mblk->chunk_size, + "BLI_memblock chunk"); } } return ptr; @@ -181,11 +180,3 @@ void *BLI_memblock_iterstep(BLI_memblock_iter *iter) } return ptr; } - -/* Direct access. elem is element index inside the chosen chunk. */ -void *BLI_memblock_elem_get(BLI_memblock *mblk, int chunk, int elem) -{ - BLI_assert(chunk < mblk->chunk_len); - BLI_assert(elem < (mblk->chunk_size / mblk->elem_size)); - return (char *)(mblk->chunk_list[chunk]) + mblk->elem_size * elem; -} diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index 2158d395d84..712bcc43f52 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -48,9 +48,6 @@ static struct { char *frag_shader_lib; char *vert_shader_str; char *vert_shadow_shader_str; - char *vert_background_shader_str; - char *vert_volume_shader_str; - char *geom_volume_shader_str; char *volume_shader_lib; struct GPUShader *default_prepass_sh; @@ -568,15 +565,6 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, e_data.vert_shadow_shader_str = BLI_string_joinN( datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_shadow_vert_glsl); - e_data.vert_background_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_background_vert_glsl); - - e_data.vert_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_volumetric_vert_glsl); - - e_data.geom_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_volumetric_geom_glsl); - e_data.default_background = DRW_shader_create_with_lib(datatoc_background_vert_glsl, NULL, datatoc_default_world_frag_glsl, @@ -649,7 +637,7 @@ struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, Wor wo, engine, options, - e_data.vert_background_shader_str, + datatoc_background_vert_glsl, NULL, e_data.frag_shader_lib, SHADER_DEFINES "#define PROBE_CAPTURE\n", @@ -669,7 +657,7 @@ struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, Wor wo, engine, options, - e_data.vert_background_shader_str, + datatoc_background_vert_glsl, NULL, e_data.frag_shader_lib, SHADER_DEFINES "#define WORLD_BACKGROUND\n", @@ -692,8 +680,8 @@ struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, World * wo, engine, options, - e_data.vert_volume_shader_str, - e_data.geom_volume_shader_str, + datatoc_volumetric_vert_glsl, + datatoc_volumetric_geom_glsl, e_data.volume_shader_lib, defines, true); @@ -753,8 +741,8 @@ struct GPUMaterial *EEVEE_material_mesh_volume_get(struct Scene *scene, Material ma, engine, options, - e_data.vert_volume_shader_str, - e_data.geom_volume_shader_str, + datatoc_volumetric_vert_glsl, + datatoc_volumetric_geom_glsl, e_data.volume_shader_lib, defines, true); @@ -1350,24 +1338,6 @@ static void material_transparent(Material *ma, const float *spec_p = &ma->spec; const float *rough_p = &ma->roughness; - const bool use_prepass = ((ma->blend_flag & MA_BL_HIDE_BACKFACE) != 0); - - DRWState cur_state; - DRWState all_state = (DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_CULL_BACK | - DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_DEPTH_EQUAL | - DRW_STATE_BLEND_CUSTOM); - - /* Depth prepass */ - if (use_prepass) { - *shgrp_depth = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->transparent_pass); - - cur_state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; - cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0; - - DRW_shgroup_state_disable(*shgrp_depth, all_state); - DRW_shgroup_state_enable(*shgrp_depth, cur_state); - } - if (ma->use_nodes && ma->nodetree) { static float error_col[3] = {1.0f, 0.0f, 1.0f}; static float compile_col[3] = {0.5f, 0.5f, 0.5f}; @@ -1424,13 +1394,30 @@ static void material_transparent(Material *ma, DRW_shgroup_uniform_float(*shgrp, "roughness", rough_p, 1); } - cur_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM; + const bool use_prepass = ((ma->blend_flag & MA_BL_HIDE_BACKFACE) != 0); + + DRWState all_state = (DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_CULL_BACK | + DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_DEPTH_EQUAL | + DRW_STATE_BLEND_CUSTOM); + + DRWState cur_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM; cur_state |= (use_prepass) ? DRW_STATE_DEPTH_EQUAL : DRW_STATE_DEPTH_LESS_EQUAL; cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0; /* Disable other blend modes and use the one we want. */ DRW_shgroup_state_disable(*shgrp, all_state); DRW_shgroup_state_enable(*shgrp, cur_state); + + /* Depth prepass */ + if (use_prepass) { + *shgrp_depth = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->transparent_pass); + + cur_state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; + cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0; + + DRW_shgroup_state_disable(*shgrp_depth, all_state); + DRW_shgroup_state_enable(*shgrp_depth, cur_state); + } } /* Return correct material or &defmaterial if slot is empty. */ @@ -1747,9 +1734,6 @@ void EEVEE_materials_free(void) MEM_SAFE_FREE(e_data.frag_shader_lib); MEM_SAFE_FREE(e_data.vert_shader_str); MEM_SAFE_FREE(e_data.vert_shadow_shader_str); - MEM_SAFE_FREE(e_data.vert_background_shader_str); - MEM_SAFE_FREE(e_data.vert_volume_shader_str); - MEM_SAFE_FREE(e_data.geom_volume_shader_str); MEM_SAFE_FREE(e_data.volume_shader_lib); DRW_SHADER_FREE_SAFE(e_data.default_hair_prepass_sh); DRW_SHADER_FREE_SAFE(e_data.default_hair_prepass_clip_sh); diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c index 9cf4a72dc31..882f2285296 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c @@ -415,7 +415,6 @@ static DRWShadingGroup *gpencil_shgroup_fill_create(GPENCIL_Data *vedata, DRWPass *pass, GPUShader *shader, Object *ob, - float (*obmat)[4], bGPdata *gpd, bGPDlayer *gpl, MaterialGPencilStyle *gp_style, @@ -429,8 +428,6 @@ static DRWShadingGroup *gpencil_shgroup_fill_create(GPENCIL_Data *vedata, /* e_data.gpencil_fill_sh */ DRWShadingGroup *grp = DRW_shgroup_create(shader, pass); - DRW_shgroup_uniform_mat4(grp, "gpModelMatrix", obmat); - DRW_shgroup_uniform_vec4(grp, "color2", gp_style->mix_rgba, 1); /* set style type */ @@ -564,7 +561,6 @@ DRWShadingGroup *gpencil_shgroup_stroke_create(GPENCIL_Data *vedata, DRWPass *pass, GPUShader *shader, Object *ob, - float (*obmat)[4], bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps, @@ -586,8 +582,6 @@ DRWShadingGroup *gpencil_shgroup_stroke_create(GPENCIL_Data *vedata, DRW_shgroup_uniform_float(grp, "pixsize", stl->storage->pixsize, 1); - DRW_shgroup_uniform_mat4(grp, "gpModelMatrix", obmat); - /* avoid wrong values */ if ((gpd) && (gpd->pixfactor == 0.0f)) { gpd->pixfactor = GP_DEFAULT_PIX_FACTOR; @@ -730,7 +724,6 @@ static DRWShadingGroup *gpencil_shgroup_point_create(GPENCIL_Data *vedata, DRWPass *pass, GPUShader *shader, Object *ob, - float (*obmat)[4], bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps, @@ -751,8 +744,6 @@ static DRWShadingGroup *gpencil_shgroup_point_create(GPENCIL_Data *vedata, DRW_shgroup_uniform_vec2(grp, "Viewport", viewport_size, 1); DRW_shgroup_uniform_float(grp, "pixsize", stl->storage->pixsize, 1); - DRW_shgroup_uniform_mat4(grp, "gpModelMatrix", obmat); - /* avoid wrong values */ if ((gpd) && (gpd->pixfactor == 0.0f)) { gpd->pixfactor = GP_DEFAULT_PIX_FACTOR; @@ -1577,9 +1568,6 @@ void gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, copy_v2_v2(stl->storage->gradient_s, brush->gpencil_settings->gradient_s); stl->storage->alignment_mode = (gp_style) ? gp_style->alignment_mode : GP_STYLE_FOLLOW_PATH; - float unit_mat[4][4]; - unit_m4(unit_mat); - /* if only one point, don't need to draw buffer because the user has no time to see it */ if (gpd->runtime.sbuffer_used > 1) { if ((gp_style) && (gp_style->mode == GP_STYLE_MODE_LINE)) { @@ -1588,7 +1576,6 @@ void gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, psl->drawing_pass, e_data->gpencil_stroke_sh, NULL, - unit_mat, gpd, NULL, NULL, @@ -1613,7 +1600,6 @@ void gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, psl->drawing_pass, e_data->gpencil_point_sh, NULL, - unit_mat, gpd, NULL, NULL, @@ -1800,7 +1786,6 @@ static void gpencil_shgroups_create(GPENCIL_e_data *e_data, stroke_pass, e_data->gpencil_stroke_sh, ob, - obmat, gpd, gpl, gps, @@ -1809,26 +1794,23 @@ static void gpencil_shgroups_create(GPENCIL_e_data *e_data, elm->onion, scale, cache_ob->shading_type); + if ((do_onion) || (elm->onion == false)) { + DRW_shgroup_call_range_obmat(shgrp, cache->b_stroke.batch, obmat, start_stroke, len); + } + stl->storage->shgroup_id++; + start_stroke = elm->vertex_idx; /* set stencil mask id */ if (gpencil_is_stencil_required(gp_style)) { - if (stencil_id == 1) { - /* Clear previous stencils. */ - DRW_shgroup_clear_framebuffer(shgrp, GPU_STENCIL_BIT, 0, 0, 0, 0, 0.0f, 0x0); - } DRW_shgroup_stencil_mask(shgrp, stencil_id); stencil_id++; } else { /* Disable stencil for this type */ DRW_shgroup_state_disable(shgrp, DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_NEQUAL); + /* set stencil mask id as not used */ + DRW_shgroup_stencil_mask(shgrp, 0x0); } - - if ((do_onion) || (elm->onion == false)) { - DRW_shgroup_call_range(shgrp, cache->b_stroke.batch, start_stroke, len); - } - stl->storage->shgroup_id++; - start_stroke = elm->vertex_idx; break; } case eGpencilBatchGroupType_Point: { @@ -1838,7 +1820,6 @@ static void gpencil_shgroups_create(GPENCIL_e_data *e_data, stroke_pass, e_data->gpencil_point_sh, ob, - obmat, gpd, gpl, gps, @@ -1848,14 +1829,16 @@ static void gpencil_shgroups_create(GPENCIL_e_data *e_data, scale, cache_ob->shading_type); - /* Disable stencil for this type */ - DRW_shgroup_state_disable(shgrp, DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_NEQUAL); - if ((do_onion) || (elm->onion == false)) { - DRW_shgroup_call_range(shgrp, cache->b_point.batch, start_point, len); + DRW_shgroup_call_range_obmat(shgrp, cache->b_point.batch, obmat, start_point, len); } stl->storage->shgroup_id++; start_point = elm->vertex_idx; + + /* Disable stencil for this type */ + DRW_shgroup_state_disable(shgrp, DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_NEQUAL); + /* set stencil mask id as not used */ + DRW_shgroup_stencil_mask(shgrp, 0x0); break; } case eGpencilBatchGroupType_Fill: { @@ -1865,32 +1848,30 @@ static void gpencil_shgroups_create(GPENCIL_e_data *e_data, stroke_pass, e_data->gpencil_fill_sh, ob, - obmat, gpd, gpl, gp_style, stl->storage->shgroup_id, cache_ob->shading_type); - /* Disable stencil for this type */ - DRW_shgroup_state_disable(shgrp, DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_NEQUAL); - if ((do_onion) || (elm->onion == false)) { - DRW_shgroup_call_range(shgrp, cache->b_fill.batch, start_fill, len); + DRW_shgroup_call_range_obmat(shgrp, cache->b_fill.batch, obmat, start_fill, len); } stl->storage->shgroup_id++; start_fill = elm->vertex_idx; + + /* Disable stencil for this type */ + DRW_shgroup_state_disable(shgrp, DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_NEQUAL); + /* set stencil mask id as not used */ + DRW_shgroup_stencil_mask(shgrp, 0x0); break; } case eGpencilBatchGroupType_Edit: { if (stl->g_data->shgrps_edit_point) { const int len = elm->vertex_idx - start_edit; - - shgrp = DRW_shgroup_create_sub(stl->g_data->shgrps_edit_point); - DRW_shgroup_uniform_mat4(shgrp, "gpModelMatrix", obmat); /* use always the same group */ - DRW_shgroup_call_range( - stl->g_data->shgrps_edit_point, cache->b_edit.batch, start_edit, len); + DRW_shgroup_call_range_obmat( + stl->g_data->shgrps_edit_point, cache->b_edit.batch, obmat, start_edit, len); start_edit = elm->vertex_idx; } @@ -1899,12 +1880,9 @@ static void gpencil_shgroups_create(GPENCIL_e_data *e_data, case eGpencilBatchGroupType_Edlin: { if (stl->g_data->shgrps_edit_line) { const int len = elm->vertex_idx - start_edlin; - - shgrp = DRW_shgroup_create_sub(stl->g_data->shgrps_edit_line); - DRW_shgroup_uniform_mat4(shgrp, "gpModelMatrix", obmat); /* use always the same group */ - DRW_shgroup_call_range( - stl->g_data->shgrps_edit_line, cache->b_edlin.batch, start_edlin, len); + DRW_shgroup_call_range_obmat( + stl->g_data->shgrps_edit_line, cache->b_edlin.batch, obmat, start_edlin, len); start_edlin = elm->vertex_idx; } diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index b2e8cef1db2..9efae54b376 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -61,8 +61,6 @@ extern char datatoc_gpencil_edit_point_geom_glsl[]; extern char datatoc_gpencil_edit_point_frag_glsl[]; extern char datatoc_gpencil_blend_frag_glsl[]; -extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[]; - extern char datatoc_common_colormanagement_lib_glsl[]; extern char datatoc_common_view_lib_glsl[]; @@ -223,12 +221,7 @@ static void GPENCIL_create_shaders(void) /* used for edit lines for edit modes */ if (!e_data.gpencil_line_sh) { - e_data.gpencil_line_sh = DRW_shader_create_with_lib( - datatoc_gpencil_edit_point_vert_glsl, - NULL, - datatoc_gpu_shader_3D_smooth_color_frag_glsl, - datatoc_common_view_lib_glsl, - NULL); + e_data.gpencil_line_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_FLAT_COLOR); } /* used to filling during drawing */ @@ -286,7 +279,6 @@ static void GPENCIL_engine_free(void) DRW_SHADER_FREE_SAFE(e_data.gpencil_stroke_sh); DRW_SHADER_FREE_SAFE(e_data.gpencil_point_sh); DRW_SHADER_FREE_SAFE(e_data.gpencil_edit_point_sh); - DRW_SHADER_FREE_SAFE(e_data.gpencil_line_sh); DRW_SHADER_FREE_SAFE(e_data.gpencil_fullscreen_sh); DRW_SHADER_FREE_SAFE(e_data.gpencil_simple_fullscreen_sh); DRW_SHADER_FREE_SAFE(e_data.gpencil_blend_fullscreen_sh); @@ -842,13 +834,76 @@ static void gpencil_draw_pass_range(GPENCIL_FramebufferList *fbl, const bool do_antialiasing = ((!stl->storage->is_mat_preview) && (multi)); + DRWShadingGroup *shgrp = init_shgrp; + DRWShadingGroup *from_shgrp = init_shgrp; + DRWShadingGroup *to_shgrp = init_shgrp; + int stencil_tot = 0; + bool do_last = true; + if (do_antialiasing) { MULTISAMPLE_GP_SYNC_ENABLE(stl->storage->multisamples, fbl); } - DRW_draw_pass_subset(GPENCIL_3D_DRAWMODE(ob, gpd) ? psl->stroke_pass_3d : psl->stroke_pass_2d, - init_shgrp, - end_shgrp); + /* Loop all shading groups to separate by stencil groups. */ + while ((shgrp) && (shgrp != end_shgrp)) { + do_last = true; + /* Count number of groups using stencil. */ + if (DRW_shgroup_stencil_mask_get(shgrp) != 0) { + stencil_tot++; + } + + /* Draw stencil group and clear stencil bit. This is required because the number of + * shading groups can be greater than the limit of 255 stencil values. + * Only count as stencil if the shading group has an stencil value assigned. This reduces + * the number of clears because Dots, Fills and some Line strokes don't need stencil. + */ + if (stencil_tot == 255) { + DRW_draw_pass_subset(GPENCIL_3D_DRAWMODE(ob, gpd) ? psl->stroke_pass_3d : + psl->stroke_pass_2d, + from_shgrp, + to_shgrp); + /* Clear Stencil and prepare for next group. */ + if (do_antialiasing) { + GPU_framebuffer_clear_stencil(fbl->multisample_fb, 0x0); + } + else { + GPU_framebuffer_clear_stencil(fb, 0x0); + } + + /* Set new init group and reset. */ + do_last = false; + + shgrp = DRW_shgroup_get_next(shgrp); + if (shgrp) { + from_shgrp = to_shgrp = shgrp; + stencil_tot = 0; + if (shgrp != end_shgrp) { + continue; + } + else { + do_last = true; + break; + } + } + else { + /* No more groups. */ + break; + } + } + + /* Still below stencil group limit. */ + shgrp = DRW_shgroup_get_next(shgrp); + if (shgrp) { + to_shgrp = shgrp; + } + } + + /* Draw last pending groups. */ + if (do_last) { + DRW_draw_pass_subset(GPENCIL_3D_DRAWMODE(ob, gpd) ? psl->stroke_pass_3d : psl->stroke_pass_2d, + from_shgrp, + to_shgrp); + } if (do_antialiasing) { MULTISAMPLE_GP_SYNC_DISABLE(stl->storage->multisamples, fbl, fb, txl); diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h index 27d537c9a20..79bcffac512 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.h +++ b/source/blender/draw/engines/gpencil/gpencil_engine.h @@ -390,7 +390,6 @@ struct DRWShadingGroup *gpencil_shgroup_stroke_create(struct GPENCIL_Data *vedat struct DRWPass *pass, struct GPUShader *shader, struct Object *ob, - float (*obmat)[4], struct bGPdata *gpd, struct bGPDlayer *gpl, struct bGPDstroke *gps, diff --git a/source/blender/draw/engines/gpencil/gpencil_render.c b/source/blender/draw/engines/gpencil/gpencil_render.c index 8ceecbb359d..7ee86bcc392 100644 --- a/source/blender/draw/engines/gpencil/gpencil_render.c +++ b/source/blender/draw/engines/gpencil/gpencil_render.c @@ -308,9 +308,6 @@ void GPENCIL_render_to_image(void *vedata, DRW_render_object_iter(vedata, engine, draw_ctx->depsgraph, GPENCIL_render_cache); GPENCIL_cache_finish(vedata); - - DRW_render_instance_buffer_finish(); - GPENCIL_draw_scene(vedata); /* combined data */ diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_vert.glsl index f75322f90e2..a1cfb2ae4ae 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_vert.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_vert.glsl @@ -1,6 +1,4 @@ -uniform mat4 gpModelMatrix; - in vec3 pos; in vec4 color; in float size; @@ -10,7 +8,7 @@ out float finalThickness; void main() { - gl_Position = point_world_to_ndc((gpModelMatrix * vec4(pos, 1.0)).xyz); + gl_Position = point_object_to_ndc(pos); finalColor = color; finalThickness = size; } diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_vert.glsl index 263dc570423..eb452f4c660 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_vert.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_vert.glsl @@ -1,6 +1,4 @@ -uniform mat4 gpModelMatrix; - in vec3 pos; in vec4 color; in vec2 texCoord; @@ -10,7 +8,7 @@ out vec2 texCoord_interp; void main(void) { - gl_Position = point_world_to_ndc((gpModelMatrix * vec4(pos, 1.0)).xyz); + gl_Position = point_object_to_ndc(pos); finalColor = color; texCoord_interp = texCoord; } diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl index 87963c66858..ef8b361373f 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl @@ -6,7 +6,6 @@ uniform float pixfactor; uniform int viewport_xray; uniform int shading_type[2]; uniform vec4 wire_color; -uniform mat4 gpModelMatrix; in vec3 pos; in vec4 color; @@ -31,8 +30,8 @@ float defaultpixsize = pixsize * (1000.0 / pixfactor); void main() { - gl_Position = point_world_to_ndc((gpModelMatrix * vec4(pos, 1.0)).xyz); - finalprev_pos = point_world_to_ndc((gpModelMatrix * vec4(prev_pos, 1.0)).xyz); + gl_Position = point_object_to_ndc(pos); + finalprev_pos = point_object_to_ndc(prev_pos); finalColor = color; if (keep_size == TRUE) { diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl index 582b9a7f249..c7089f357f9 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl @@ -6,7 +6,6 @@ uniform float pixfactor; uniform int viewport_xray; uniform int shading_type[2]; uniform vec4 wire_color; -uniform mat4 gpModelMatrix; in vec3 pos; in vec4 color; @@ -29,7 +28,7 @@ float defaultpixsize = pixsize * (1000.0 / pixfactor); void main(void) { - gl_Position = point_world_to_ndc((gpModelMatrix * vec4(pos, 1.0)).xyz); + gl_Position = point_object_to_ndc(pos); finalColor = color; if (keep_size == TRUE) { diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_depth_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_depth_frag.glsl index abd8c1f6579..505b4822ad6 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_forward_depth_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_forward_depth_frag.glsl @@ -1,6 +1,5 @@ - +uniform int object_id = 0; layout(location = 0) out uint objectId; - uniform float ImageTransparencyCutoff = 0.1; #ifdef V3D_SHADING_TEXTURE_COLOR uniform sampler2D image; @@ -11,10 +10,11 @@ in vec2 uv_interp; void main() { #ifdef V3D_SHADING_TEXTURE_COLOR - if (texture(image, uv_interp).a < ImageTransparencyCutoff) { + vec4 diffuse_color = texture(image, uv_interp); + if (diffuse_color.a < ImageTransparencyCutoff) { discard; } #endif - objectId = uint(resource_id + 1) & 0xFFu; + objectId = uint(object_id); } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl index f799ce41cb2..3333dfeff38 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl @@ -8,7 +8,8 @@ uniform float alpha = 0.5; uniform vec2 invertedViewportSize; uniform vec4 viewvecs[3]; -uniform vec4 materialColorAndMetal; +uniform vec3 materialDiffuseColor; +uniform vec3 materialSpecularColor; uniform float materialRoughness; uniform float shadowMultiplier = 0.5; @@ -41,17 +42,17 @@ layout(location = 1) out void main() { - vec4 base_color; + vec4 diffuse_color; #if defined(V3D_SHADING_TEXTURE_COLOR) - base_color = workbench_sample_texture(image, uv_interp, imageNearest, imagePremultiplied); - if (base_color.a < ImageTransparencyCutoff) { + diffuse_color = workbench_sample_texture(image, uv_interp, imageNearest, imagePremultiplied); + if (diffuse_color.a < ImageTransparencyCutoff) { discard; } #elif defined(V3D_SHADING_VERTEX_COLOR) - base_color.rgb = vertexColor; + diffuse_color = vec4(vertexColor, 1.0); #else - base_color.rgb = materialColorAndMetal.rgb; + diffuse_color = vec4(materialDiffuseColor, 1.0); #endif /* V3D_SHADING_TEXTURE_COLOR */ vec2 uv_viewport = gl_FragCoord.xy * invertedViewportSize; @@ -63,7 +64,7 @@ void main() /* -------- SHADING --------- */ #ifdef V3D_LIGHTING_FLAT - vec3 shaded_color = base_color.rgb; + vec3 shaded_color = diffuse_color.rgb; #elif defined(V3D_LIGHTING_MATCAP) bool flipped = world_data.matcap_orientation != 0; @@ -74,20 +75,11 @@ void main() # else vec3 matcap_specular = vec3(0.0); # endif - vec3 shaded_color = matcap_diffuse * base_color.rgb + matcap_specular; + vec3 shaded_color = matcap_diffuse * diffuse_color.rgb + matcap_specular; #elif defined(V3D_LIGHTING_STUDIO) -# ifdef V3D_SHADING_SPECULAR_HIGHLIGHT - float metallic = materialColorAndMetal.a; - vec3 specular_color = mix(vec3(0.05), base_color.rgb, metallic); - vec3 diffuse_color = mix(base_color.rgb, vec3(0.0), metallic); -# else - vec3 specular_color = vec3(0.0); - vec3 diffuse_color = base_color.rgb; -# endif - vec3 shaded_color = get_world_lighting( - world_data, diffuse_color, specular_color, materialRoughness, nor, I_vs); + world_data, diffuse_color.rgb, materialSpecularColor, materialRoughness, nor, I_vs); #endif #ifdef V3D_SHADING_SHADOW diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl index b5f95f2dcf8..c673b2484de 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl @@ -1,5 +1,7 @@ +uniform int object_id = 0; -uniform vec4 materialColorAndMetal; +uniform vec3 materialDiffuseColor; +uniform float materialMetallic; uniform float materialRoughness; uniform sampler2D image; @@ -46,7 +48,7 @@ void main() # elif defined(V3D_SHADING_VERTEX_COLOR) color.rgb = vertexColor; # else - color.rgb = materialColorAndMetal.rgb; + color.rgb = materialDiffuseColor; # endif # ifdef V3D_LIGHTING_MATCAP @@ -54,7 +56,7 @@ void main() metallic = float(gl_FrontFacing); roughness = 0.0; # else - metallic = materialColorAndMetal.a; + metallic = materialMetallic; roughness = materialRoughness; # endif @@ -62,7 +64,7 @@ void main() /* Add some variation to the hairs to avoid uniform look. */ float hair_variation = hair_rand * 0.1; color = clamp(color - hair_variation, 0.0, 1.0); - metallic = clamp(materialColorAndMetal.a - hair_variation, 0.0, 1.0); + metallic = clamp(materialMetallic - hair_variation, 0.0, 1.0); roughness = clamp(materialRoughness - hair_variation, 0.0, 1.0); # endif @@ -71,7 +73,7 @@ void main() #endif /* MATDATA_PASS_ENABLED */ #ifdef OBJECT_ID_PASS_ENABLED - objectId = uint(resource_id + 1) & 0xFFu; + objectId = uint(object_id); #endif #ifdef NORMAL_VIEWPORT_PASS_ENABLED diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl index 04dd9ab85bb..7eb12dbdeb9 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl @@ -25,10 +25,6 @@ out vec2 uv_interp; out vec3 vertexColor; #endif -#ifdef OBJECT_ID_PASS_ENABLED -RESOURCE_ID_VARYING -#endif - /* From http://libnoise.sourceforge.net/noisegen/index.html */ float integer_noise(int n) { @@ -95,18 +91,12 @@ void main() #endif #ifdef NORMAL_VIEWPORT_PASS_ENABLED -# ifndef HAIR_SHADER normal_viewport = normal_object_to_view(nor); +# ifndef HAIR_SHADER normal_viewport = normalize(normal_viewport); -# else - normal_viewport = normal_world_to_view(nor); # endif #endif -#ifdef OBJECT_ID_PASS_ENABLED - PASS_RESOURCE_ID -#endif - #ifdef USE_WORLD_CLIP_PLANES world_clip_planes_calc_clip_distance(world_pos); #endif diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl index c24c335189e..4a9b0ae3b7d 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl @@ -1,4 +1,6 @@ +uniform vec3 OrcoTexCoFactors[2]; + uniform sampler2D depthBuffer; uniform sampler3D densityTexture; @@ -214,13 +216,13 @@ void main() vs_ray_dir /= abs(vs_ray_dir.z); /* TODO(fclem) Precompute the matrix/ */ - vec3 ls_ray_dir = mat3(ViewMatrixInverse) * vs_ray_dir * OrcoTexCoFactors[1].xyz * 2.0; + vec3 ls_ray_dir = mat3(ViewMatrixInverse) * vs_ray_dir * OrcoTexCoFactors[1] * 2.0; ls_ray_dir = mat3(ModelMatrixInverse) * ls_ray_dir; vec3 ls_ray_ori = point_view_to_object(vs_ray_ori); vec3 ls_ray_end = point_view_to_object(vs_ray_end); - ls_ray_ori = (OrcoTexCoFactors[0].xyz + ls_ray_ori * OrcoTexCoFactors[1].xyz) * 2.0 - 1.0; - ls_ray_end = (OrcoTexCoFactors[0].xyz + ls_ray_end * OrcoTexCoFactors[1].xyz) * 2.0 - 1.0; + ls_ray_ori = (OrcoTexCoFactors[0] + ls_ray_ori * OrcoTexCoFactors[1]) * 2.0 - 1.0; + ls_ray_end = (OrcoTexCoFactors[0] + ls_ray_end * OrcoTexCoFactors[1]) * 2.0 - 1.0; /* TODO: Align rays to volume center so that it mimics old behaviour of slicing the volume. */ diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl index 3542a1a91fc..6f0bb56fafd 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl @@ -1,11 +1,10 @@ +uniform vec3 OrcoTexCoFactors[2]; uniform float slicePosition; uniform int sliceAxis; /* -1 is no slice, 0 is X, 1 is Y, 2 is Z. */ in vec3 pos; -RESOURCE_ID_VARYING - #ifdef VOLUME_SLICE in vec3 uvs; @@ -28,8 +27,6 @@ void main() #else vec3 final_pos = pos; #endif - final_pos = ((final_pos * 0.5 + 0.5) - OrcoTexCoFactors[0].xyz) / OrcoTexCoFactors[1].xyz; + final_pos = ((final_pos * 0.5 + 0.5) - OrcoTexCoFactors[0]) / OrcoTexCoFactors[1]; gl_Position = point_object_to_ndc(final_pos); - - PASS_RESOURCE_ID } diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c index e41cba1d3bd..262ea7110a4 100644 --- a/source/blender/draw/engines/workbench/workbench_deferred.c +++ b/source/blender/draw/engines/workbench/workbench_deferred.c @@ -83,6 +83,7 @@ static struct { struct GPUTexture *composite_buffer_tx; /* ref only, not alloced */ SceneDisplay display; /* world light direction for shadows */ + int next_object_id; struct GPUUniformBuffer *sampling_ubo; struct GPUTexture *jitter_tx; @@ -146,7 +147,6 @@ static char *workbench_build_prepass_frag(void) { DynStr *ds = BLI_dynstr_new(); - BLI_dynstr_append(ds, datatoc_common_view_lib_glsl); BLI_dynstr_append(ds, datatoc_workbench_data_lib_glsl); BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl); BLI_dynstr_append(ds, datatoc_workbench_prepass_frag_glsl); @@ -330,6 +330,7 @@ static struct GPUTexture *create_jitter_texture(int num_samples) static void workbench_init_object_data(DrawData *dd) { WORKBENCH_ObjectData *data = (WORKBENCH_ObjectData *)dd; + data->object_id = ((e_data.next_object_id++) & 0xff) + 1; data->shadow_bbox_dirty = true; } @@ -378,10 +379,11 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata) workbench_effect_info_init(stl->effects); } - if (!e_data.shadow_pass_sh) { + if (!e_data.next_object_id) { WORKBENCH_DEFERRED_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; memset(sh_data->prepass_sh_cache, 0, sizeof(sh_data->prepass_sh_cache)); memset(e_data.composite_sh_cache, 0, sizeof(e_data.composite_sh_cache)); + e_data.next_object_id = 1; #ifdef DEBUG_SHADOW_VOLUME const char *shadow_frag = datatoc_workbench_shadow_debug_frag_glsl; #else @@ -866,11 +868,18 @@ static WORKBENCH_MaterialData *get_or_create_material_data(WORKBENCH_Data *vedat WORKBENCH_PassList *psl = vedata->psl; WORKBENCH_PrivateData *wpd = stl->g_data; WORKBENCH_MaterialData *material; + WORKBENCH_ObjectData *engine_object_data = (WORKBENCH_ObjectData *)DRW_drawdata_ensure( + &ob->id, + &draw_engine_workbench_solid, + sizeof(WORKBENCH_ObjectData), + &workbench_init_object_data, + NULL); WORKBENCH_MaterialData material_template; const bool is_ghost = (ob->dtx & OB_DRAWXRAY); /* Solid */ workbench_material_update_data(wpd, ob, mat, &material_template, color_type); + material_template.object_id = OBJECT_ID_PASS_ENABLED(wpd) ? engine_object_data->object_id : 1; material_template.color_type = color_type; material_template.ima = ima; material_template.iuser = iuser; @@ -890,7 +899,8 @@ static WORKBENCH_MaterialData *get_or_create_material_data(WORKBENCH_Data *vedat shader, (ob->dtx & OB_DRAWXRAY) ? psl->ghost_prepass_pass : psl->prepass_pass); workbench_material_copy(material, &material_template); DRW_shgroup_stencil_mask(material->shgrp, (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF); - workbench_material_shgroup_uniform(wpd, material->shgrp, material, ob, true, interp); + DRW_shgroup_uniform_int(material->shgrp, "object_id", &material->object_id, 1); + workbench_material_shgroup_uniform(wpd, material->shgrp, material, ob, true, true, interp); BLI_ghash_insert(wpd->material_hash, POINTER_FROM_UINT(hash), material); } return material; @@ -933,7 +943,8 @@ static void workbench_cache_populate_particles(WORKBENCH_Data *vedata, Object *o (ob->dtx & OB_DRAWXRAY) ? psl->ghost_prepass_hair_pass : psl->prepass_hair_pass, shader); DRW_shgroup_stencil_mask(shgrp, (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF); - workbench_material_shgroup_uniform(wpd, shgrp, material, ob, true, interp); + DRW_shgroup_uniform_int(shgrp, "object_id", &material->object_id, 1); + workbench_material_shgroup_uniform(wpd, shgrp, material, ob, true, true, interp); } } } diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c index 890359e8fda..1cbc60ef858 100644 --- a/source/blender/draw/engines/workbench/workbench_forward.c +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -63,6 +63,8 @@ static struct { struct GPUTexture *transparent_accum_tx; /* ref only, not alloced */ struct GPUTexture *transparent_revealage_tx; /* ref only, not alloced */ struct GPUTexture *composite_buffer_tx; /* ref only, not alloced */ + + int next_object_id; } e_data = {{{{NULL}}}}; /* Shaders */ @@ -96,18 +98,6 @@ static char *workbench_build_forward_vert(bool is_hair) return str; } -static char *workbench_build_forward_outline_frag(void) -{ - DynStr *ds = BLI_dynstr_new(); - - BLI_dynstr_append(ds, datatoc_common_view_lib_glsl); - BLI_dynstr_append(ds, datatoc_workbench_forward_depth_frag_glsl); - - char *str = BLI_dynstr_get_cstring(ds); - BLI_dynstr_free(ds); - return str; -} - static char *workbench_build_forward_transparent_accum_frag(void) { DynStr *ds = BLI_dynstr_new(); @@ -139,6 +129,12 @@ static char *workbench_build_forward_composite_frag(void) return str; } +static void workbench_init_object_data(DrawData *dd) +{ + WORKBENCH_ObjectData *data = (WORKBENCH_ObjectData *)dd; + data->object_id = ((e_data.next_object_id++) & 0xff) + 1; +} + WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_Data *vedata, Object *ob, Material *mat, @@ -153,11 +149,18 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_ WORKBENCH_PassList *psl = vedata->psl; WORKBENCH_PrivateData *wpd = stl->g_data; WORKBENCH_MaterialData *material; + WORKBENCH_ObjectData *engine_object_data = (WORKBENCH_ObjectData *)DRW_drawdata_ensure( + &ob->id, + &draw_engine_workbench_solid, + sizeof(WORKBENCH_ObjectData), + &workbench_init_object_data, + NULL); WORKBENCH_MaterialData material_template; DRWShadingGroup *grp; /* Solid */ workbench_material_update_data(wpd, ob, mat, &material_template, color_type); + material_template.object_id = OBJECT_ID_PASS_ENABLED(wpd) ? engine_object_data->object_id : 1; material_template.color_type = color_type; material_template.ima = ima; material_template.iuser = iuser; @@ -202,7 +205,7 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_ DRW_shgroup_uniform_float_copy(grp, "shadowFocus", wpd->shadow_focus); } - workbench_material_shgroup_uniform(wpd, grp, material, ob, false, interp); + workbench_material_shgroup_uniform(wpd, grp, material, ob, false, false, interp); material->shgrp = grp; /* Depth */ @@ -216,6 +219,8 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_ material->shgrp_object_outline = DRW_shgroup_create(sh_data->object_outline_sh, psl->object_outline_pass); } + material->object_id = engine_object_data->object_id; + DRW_shgroup_uniform_int(material->shgrp_object_outline, "object_id", &material->object_id, 1); if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_state_enable(material->shgrp_object_outline, DRW_STATE_CLIP_PLANES); } @@ -287,30 +292,26 @@ void workbench_forward_outline_shaders_ensure(WORKBENCH_PrivateData *wpd, eGPUSh char *defines_texture = workbench_material_build_defines(wpd, true, false, false); char *defines_hair = workbench_material_build_defines(wpd, false, true, false); char *forward_vert = workbench_build_forward_vert(false); - char *forward_frag = workbench_build_forward_outline_frag(); char *forward_hair_vert = workbench_build_forward_vert(true); - const char *define_id_pass = "#define OBJECT_ID_PASS_ENABLED\n"; - sh_data->object_outline_sh = GPU_shader_create_from_arrays({ .vert = (const char *[]){sh_cfg_data->lib, forward_vert, NULL}, - .frag = (const char *[]){forward_frag, NULL}, - .defs = (const char *[]){sh_cfg_data->def, defines, define_id_pass, NULL}, + .frag = (const char *[]){datatoc_workbench_forward_depth_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, defines, NULL}, }); sh_data->object_outline_texture_sh = GPU_shader_create_from_arrays({ .vert = (const char *[]){sh_cfg_data->lib, forward_vert, NULL}, - .frag = (const char *[]){forward_frag, NULL}, - .defs = (const char *[]){sh_cfg_data->def, defines_texture, define_id_pass, NULL}, + .frag = (const char *[]){datatoc_workbench_forward_depth_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, defines_texture, NULL}, }); sh_data->object_outline_hair_sh = GPU_shader_create_from_arrays({ .vert = (const char *[]){sh_cfg_data->lib, forward_hair_vert, NULL}, - .frag = (const char *[]){forward_frag, NULL}, - .defs = (const char *[]){sh_cfg_data->def, defines_hair, define_id_pass, NULL}, + .frag = (const char *[]){datatoc_workbench_forward_depth_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, defines_hair, NULL}, }); MEM_freeN(forward_hair_vert); MEM_freeN(forward_vert); - MEM_freeN(forward_frag); MEM_freeN(defines); MEM_freeN(defines_texture); MEM_freeN(defines_hair); @@ -526,7 +527,7 @@ static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, O DRWShadingGroup *shgrp = DRW_shgroup_hair_create( ob, psys, md, psl->transparent_accum_pass, shader); DRW_shgroup_uniform_block(shgrp, "world_block", wpd->world_ubo); - workbench_material_shgroup_uniform(wpd, shgrp, material, ob, false, interp); + workbench_material_shgroup_uniform(wpd, shgrp, material, ob, false, false, interp); DRW_shgroup_uniform_vec4(shgrp, "viewvecs[0]", (float *)wpd->viewvecs, 3); /* Hairs have lots of layer and can rapidly become the most prominent surface. * So lower their alpha artificially. */ @@ -550,6 +551,7 @@ static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, O WORKBENCH_FORWARD_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; shgrp = DRW_shgroup_hair_create( ob, psys, md, vedata->psl->object_outline_pass, sh_data->object_outline_hair_sh); + DRW_shgroup_uniform_int(shgrp, "object_id", &material->object_id, 1); } } } diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c index c90604678db..e050877187e 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.c +++ b/source/blender/draw/engines/workbench/workbench_materials.c @@ -44,15 +44,20 @@ void workbench_material_update_data(WORKBENCH_PrivateData *wpd, WORKBENCH_MaterialData *data, int color_type) { + copy_v3_fl3(data->diffuse_color, 0.8f, 0.8f, 0.8f); + copy_v3_v3(data->base_color, data->diffuse_color); + copy_v3_fl3(data->specular_color, 0.05f, 0.05f, 0.05f); /* Dielectric: 5% reflective. */ data->metallic = 0.0f; data->roughness = 0.632455532f; /* sqrtf(0.4f); */ data->alpha = wpd->shading.xray_alpha; if (color_type == V3D_SHADING_SINGLE_COLOR) { - copy_v3_v3(data->base_color, wpd->shading.single_color); + copy_v3_v3(data->diffuse_color, wpd->shading.single_color); + copy_v3_v3(data->base_color, data->diffuse_color); } else if (color_type == V3D_SHADING_ERROR_COLOR) { - copy_v3_fl3(data->base_color, 0.8, 0.0, 0.8); + copy_v3_fl3(data->diffuse_color, 0.8, 0.0, 0.8); + copy_v3_v3(data->base_color, data->diffuse_color); } else if (color_type == V3D_SHADING_RANDOM_COLOR) { uint hash = BLI_ghashutil_strhash_p_murmur(ob->id.name); @@ -62,24 +67,30 @@ void workbench_material_update_data(WORKBENCH_PrivateData *wpd, float hue = BLI_hash_int_01(hash); float hsv[3] = {hue, HSV_SATURATION, HSV_VALUE}; - hsv_to_rgb_v(hsv, data->base_color); + hsv_to_rgb_v(hsv, data->diffuse_color); + copy_v3_v3(data->base_color, data->diffuse_color); } else if (ELEM(color_type, V3D_SHADING_OBJECT_COLOR, V3D_SHADING_VERTEX_COLOR)) { + copy_v3_v3(data->diffuse_color, ob->color); + copy_v3_v3(data->base_color, data->diffuse_color); data->alpha *= ob->color[3]; - copy_v3_v3(data->base_color, ob->color); } else { /* V3D_SHADING_MATERIAL_COLOR or V3D_SHADING_TEXTURE_COLOR */ if (mat) { data->alpha *= mat->a; - copy_v3_v3(data->base_color, &mat->r); if (workbench_is_specular_highlight_enabled(wpd)) { + copy_v3_v3(data->base_color, &mat->r); + mul_v3_v3fl(data->diffuse_color, &mat->r, 1.0f - mat->metallic); + mul_v3_v3fl(data->specular_color, &mat->r, mat->metallic); + add_v3_fl(data->specular_color, 0.05f * (1.0f - mat->metallic)); data->metallic = mat->metallic; data->roughness = sqrtf(mat->roughness); /* Remap to disney roughness. */ } - } - else { - copy_v3_fl(data->base_color, 0.8f); + else { + copy_v3_v3(data->base_color, &mat->r); + copy_v3_v3(data->diffuse_color, &mat->r); + } } } } @@ -149,40 +160,34 @@ char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, return str; } -uint workbench_material_get_hash(WORKBENCH_MaterialData *mat, bool is_ghost) +uint workbench_material_get_hash(WORKBENCH_MaterialData *material_template, bool is_ghost) { - union { - struct { - /* WHATCH: Keep in sync with View3DShading.color_type max value. */ - uchar color_type; - uchar diff_r; - uchar diff_g; - uchar diff_b; - - uchar alpha; - uchar ghost; - uchar metal; - uchar roughness; - - void *ima; - }; - /* HACK to ensure input is 4 uint long. */ - uint a[4]; - } input = {.color_type = (uchar)(mat->color_type), - .diff_r = (uchar)(mat->base_color[0] * 0xFF), - .diff_g = (uchar)(mat->base_color[1] * 0xFF), - .diff_b = (uchar)(mat->base_color[2] * 0xFF), - - .alpha = (uint)(mat->alpha * 0xFF), - .ghost = (uchar)is_ghost, - .metal = (uchar)(mat->metallic * 0xFF), - .roughness = (uchar)(mat->roughness * 0xFF), - - .ima = mat->ima}; - - BLI_assert(sizeof(input) == sizeof(uint) * 4); - - return BLI_ghashutil_uinthash_v4((uint *)&input); + uint input[4]; + uint result; + float *color = material_template->diffuse_color; + input[0] = (uint)(color[0] * 512); + input[1] = (uint)(color[1] * 512); + input[2] = (uint)(color[2] * 512); + input[3] = material_template->object_id; + result = BLI_ghashutil_uinthash_v4_murmur(input); + + color = material_template->specular_color; + input[0] = (uint)(color[0] * 512); + input[1] = (uint)(color[1] * 512); + input[2] = (uint)(color[2] * 512); + input[3] = (uint)(material_template->roughness * 512); + result += BLI_ghashutil_uinthash_v4_murmur(input); + + result += BLI_ghashutil_uinthash((uint)(material_template->alpha * 512)); + result += BLI_ghashutil_uinthash((uint)is_ghost); + result += BLI_ghashutil_uinthash(material_template->color_type); + + /* add texture reference */ + if (material_template->ima) { + result += BLI_ghashutil_inthash_p_murmur(material_template->ima); + } + + return result; } int workbench_material_get_composite_shader_index(WORKBENCH_PrivateData *wpd) @@ -310,28 +315,35 @@ void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp, WORKBENCH_MaterialData *material, Object *ob, + const bool use_metallic, const bool deferred, const int interp) { - if (!(!deferred || workbench_is_matdata_pass_enabled(wpd))) { - return; - } - - const bool use_highlight = workbench_is_specular_highlight_enabled(wpd); - const bool use_texture = (V3D_SHADING_TEXTURE_COLOR == workbench_material_determine_color_type( - wpd, material->ima, ob, false)); - if (use_texture) { - GPUTexture *tex = GPU_texture_from_blender(material->ima, material->iuser, GL_TEXTURE_2D); - DRW_shgroup_uniform_texture(grp, "image", tex); - DRW_shgroup_uniform_bool_copy( - grp, "imagePremultiplied", (material->ima->alpha_mode == IMA_ALPHA_PREMUL)); - DRW_shgroup_uniform_bool_copy(grp, "imageNearest", (interp == SHD_INTERP_CLOSEST)); - } - - DRW_shgroup_uniform_vec4(grp, "materialColorAndMetal", material->base_color, 1); + if (!deferred || workbench_is_matdata_pass_enabled(wpd)) { + if (workbench_material_determine_color_type(wpd, material->ima, ob, false) == + V3D_SHADING_TEXTURE_COLOR) { + GPUTexture *tex = GPU_texture_from_blender(material->ima, material->iuser, GL_TEXTURE_2D); + DRW_shgroup_uniform_texture(grp, "image", tex); + DRW_shgroup_uniform_bool_copy( + grp, "imagePremultiplied", (material->ima->alpha_mode == IMA_ALPHA_PREMUL)); + DRW_shgroup_uniform_bool_copy(grp, "imageNearest", (interp == SHD_INTERP_CLOSEST)); + } + else { + DRW_shgroup_uniform_vec3(grp, + "materialDiffuseColor", + (use_metallic) ? material->base_color : material->diffuse_color, + 1); + } - if (use_highlight) { - DRW_shgroup_uniform_float(grp, "materialRoughness", &material->roughness, 1); + if (workbench_is_specular_highlight_enabled(wpd)) { + if (use_metallic) { + DRW_shgroup_uniform_float(grp, "materialMetallic", &material->metallic, 1); + } + else { + DRW_shgroup_uniform_vec3(grp, "materialSpecularColor", material->specular_color, 1); + } + DRW_shgroup_uniform_float(grp, "materialRoughness", &material->roughness, 1); + } } if (WORLD_CLIPPING_ENABLED(wpd)) { @@ -342,7 +354,10 @@ void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd, void workbench_material_copy(WORKBENCH_MaterialData *dest_material, const WORKBENCH_MaterialData *source_material) { + dest_material->object_id = source_material->object_id; copy_v3_v3(dest_material->base_color, source_material->base_color); + copy_v3_v3(dest_material->diffuse_color, source_material->diffuse_color); + copy_v3_v3(dest_material->specular_color, source_material->specular_color); dest_material->metallic = source_material->metallic; dest_material->roughness = source_material->roughness; dest_material->ima = source_material->ima; diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index f51da581827..d880d5d58b5 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -281,8 +281,13 @@ typedef struct WORKBENCH_EffectInfo { } WORKBENCH_EffectInfo; typedef struct WORKBENCH_MaterialData { - float base_color[3], metallic; - float roughness, alpha; + float base_color[3]; + float diffuse_color[3]; + float specular_color[3]; + float alpha; + float metallic; + float roughness; + int object_id; int color_type; int interp; Image *ima; @@ -303,6 +308,8 @@ typedef struct WORKBENCH_ObjectData { float shadow_min[3], shadow_max[3]; BoundBox shadow_bbox; bool shadow_bbox_dirty; + + int object_id; } WORKBENCH_ObjectData; /* inline helper functions */ @@ -493,6 +500,7 @@ void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp, WORKBENCH_MaterialData *material, Object *ob, + const bool use_metallic, const bool deferred, const int interp); void workbench_material_copy(WORKBENCH_MaterialData *dest_material, diff --git a/source/blender/draw/engines/workbench/workbench_volume.c b/source/blender/draw/engines/workbench/workbench_volume.c index e017661b6cd..7ae9d90daff 100644 --- a/source/blender/draw/engines/workbench/workbench_volume.c +++ b/source/blender/draw/engines/workbench/workbench_volume.c @@ -27,7 +27,6 @@ #include "BLI_rand.h" #include "BLI_dynstr.h" -#include "BLI_string_utils.h" #include "DNA_modifier_types.h" #include "DNA_object_force_types.h" @@ -55,7 +54,6 @@ static struct { extern char datatoc_workbench_volume_vert_glsl[]; extern char datatoc_workbench_volume_frag_glsl[]; extern char datatoc_common_view_lib_glsl[]; -extern char datatoc_gpu_shader_common_obinfos_lib_glsl[]; static GPUShader *volume_shader_get(bool slice, bool coba, bool cubic) { @@ -80,16 +78,12 @@ static GPUShader *volume_shader_get(bool slice, bool coba, bool cubic) char *defines = BLI_dynstr_get_cstring(ds); BLI_dynstr_free(ds); - char *libs = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_gpu_shader_common_obinfos_lib_glsl); - e_data.volume_sh[id] = DRW_shader_create_with_lib(datatoc_workbench_volume_vert_glsl, NULL, datatoc_workbench_volume_frag_glsl, - libs, + datatoc_common_view_lib_glsl, defines); - MEM_freeN(libs); MEM_freeN(defines); } diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 935920310dd..e3713fdee8f 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -80,6 +80,8 @@ typedef struct DRWPass DRWPass; typedef struct DRWShadingGroup DRWShadingGroup; typedef struct DRWUniform DRWUniform; typedef struct DRWView DRWView; + +/* Opaque type to avoid usage as a DRWCall but it is exactly the same thing. */ typedef struct DRWCallBuffer DRWCallBuffer; /* TODO Put it somewhere else? */ @@ -402,29 +404,35 @@ void DRW_shgroup_call_ex(DRWShadingGroup *shgroup, Object *ob, float (*obmat)[4], struct GPUBatch *geom, + uint v_sta, + uint v_ct, bool bypass_culling, void *user_data); /* If ob is NULL, unit modelmatrix is assumed and culling is bypassed. */ -#define DRW_shgroup_call(shgrp, geom, ob) DRW_shgroup_call_ex(shgrp, ob, NULL, geom, false, NULL) +#define DRW_shgroup_call(shgrp, geom, ob) \ + DRW_shgroup_call_ex(shgrp, ob, NULL, geom, 0, 0, false, NULL) /* Same as DRW_shgroup_call but override the obmat. Not culled. */ #define DRW_shgroup_call_obmat(shgrp, geom, obmat) \ - DRW_shgroup_call_ex(shgrp, NULL, obmat, geom, false, NULL) + DRW_shgroup_call_ex(shgrp, NULL, obmat, geom, 0, 0, false, NULL) /* TODO(fclem) remove this when we have DRWView */ /* user_data is used by DRWCallVisibilityFn defined in DRWView. */ #define DRW_shgroup_call_with_callback(shgrp, geom, ob, user_data) \ - DRW_shgroup_call_ex(shgrp, ob, NULL, geom, false, user_data) + DRW_shgroup_call_ex(shgrp, ob, NULL, geom, 0, 0, false, user_data) /* Same as DRW_shgroup_call but bypass culling even if ob is not NULL. */ #define DRW_shgroup_call_no_cull(shgrp, geom, ob) \ - DRW_shgroup_call_ex(shgrp, ob, NULL, geom, true, NULL) + DRW_shgroup_call_ex(shgrp, ob, NULL, geom, 0, 0, true, NULL) + +/* Only draw a certain range of geom. */ +#define DRW_shgroup_call_range(shgrp, geom, ob, v_sta, v_ct) \ + DRW_shgroup_call_ex(shgrp, ob, NULL, geom, v_sta, v_ct, false, NULL) -void DRW_shgroup_call_range(DRWShadingGroup *shgroup, - struct GPUBatch *geom, - uint v_sta, - uint v_ct); +/* Same as DRW_shgroup_call_range but override the obmat. Special for gpencil. */ +#define DRW_shgroup_call_range_obmat(shgrp, geom, obmat, v_sta, v_ct) \ + DRW_shgroup_call_ex(shgrp, NULL, obmat, geom, v_sta, v_ct, false, NULL) void DRW_shgroup_call_procedural_points(DRWShadingGroup *sh, Object *ob, uint point_ct); void DRW_shgroup_call_procedural_lines(DRWShadingGroup *sh, Object *ob, uint line_ct); @@ -461,16 +469,6 @@ void DRW_shgroup_state_enable(DRWShadingGroup *shgroup, DRWState state); void DRW_shgroup_state_disable(DRWShadingGroup *shgroup, DRWState state); void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, uint mask); -/* Issue a clear command. */ -void DRW_shgroup_clear_framebuffer(DRWShadingGroup *shgroup, - eGPUFrameBufferBits channels, - uchar r, - uchar g, - uchar b, - uchar a, - float depth, - uchar stencil); - void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const struct GPUTexture *tex); @@ -527,17 +525,17 @@ void DRW_shgroup_uniform_mat3(DRWShadingGroup *shgroup, const char *name, const void DRW_shgroup_uniform_mat4(DRWShadingGroup *shgroup, const char *name, const float (*value)[4]); /* Store value instead of referencing it. */ void DRW_shgroup_uniform_int_copy(DRWShadingGroup *shgroup, const char *name, const int value); -void DRW_shgroup_uniform_ivec2_copy(DRWShadingGroup *shgrp, const char *name, const int *value); -void DRW_shgroup_uniform_ivec3_copy(DRWShadingGroup *shgrp, const char *name, const int *value); -void DRW_shgroup_uniform_ivec4_copy(DRWShadingGroup *shgrp, const char *name, const int *value); void DRW_shgroup_uniform_bool_copy(DRWShadingGroup *shgroup, const char *name, const bool value); void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name, const float value); void DRW_shgroup_uniform_vec2_copy(DRWShadingGroup *shgroup, const char *name, const float *value); -void DRW_shgroup_uniform_vec3_copy(DRWShadingGroup *shgroup, const char *name, const float *value); -void DRW_shgroup_uniform_vec4_copy(DRWShadingGroup *shgroup, const char *name, const float *value); bool DRW_shgroup_is_empty(DRWShadingGroup *shgroup); +/* TODO: workaround functions waiting for the clearing operation to be available inside the + * shgroups. */ +DRWShadingGroup *DRW_shgroup_get_next(DRWShadingGroup *shgroup); +uint DRW_shgroup_stencil_mask_get(DRWShadingGroup *shgroup); + /* Passes */ DRWPass *DRW_pass_create(const char *name, DRWState state); /* TODO Replace with passes inheritance. */ diff --git a/source/blender/draw/intern/draw_anim_viz.c b/source/blender/draw/intern/draw_anim_viz.c index 2d71fdf0782..72459309133 100644 --- a/source/blender/draw/intern/draw_anim_viz.c +++ b/source/blender/draw/intern/draw_anim_viz.c @@ -215,7 +215,7 @@ static void MPATH_cache_motion_path(MPATH_PassList *psl, DRW_shgroup_uniform_vec3(shgrp, "customColor", mpath->color, 1); } /* Only draw the required range. */ - DRW_shgroup_call_range(shgrp, mpath_batch_line_get(mpath), start_index, len); + DRW_shgroup_call_range(shgrp, mpath_batch_line_get(mpath), NULL, start_index, len); } /* Draw points. */ @@ -231,7 +231,7 @@ static void MPATH_cache_motion_path(MPATH_PassList *psl, DRW_shgroup_uniform_vec3(shgrp, "customColor", mpath->color, 1); } /* Only draw the required range. */ - DRW_shgroup_call_range(shgrp, mpath_batch_points_get(mpath), start_index, len); + DRW_shgroup_call_range(shgrp, mpath_batch_points_get(mpath), NULL, start_index, len); /* Draw frame numbers at each framestep value */ bool show_kf_no = (avs->path_viewflag & MOTIONPATH_VIEW_KFNOS) != 0; diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c index 7f679dd5581..8e0f713add6 100644 --- a/source/blender/draw/intern/draw_common.c +++ b/source/blender/draw/intern/draw_common.c @@ -1095,7 +1095,7 @@ struct GPUShader *volume_velocity_shader_get(bool use_needle) NULL, datatoc_gpu_shader_flat_color_frag_glsl, datatoc_common_view_lib_glsl, - "#define USE_NEEDLE\n"); + "#define USE_NEEDLE"); } return sh_data->volume_velocity_needle_sh; } diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c index 58085cf08c6..f77243ca9f1 100644 --- a/source/blender/draw/intern/draw_hair.c +++ b/source/blender/draw/intern/draw_hair.c @@ -201,33 +201,30 @@ static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object, /* Transform Feedback subdiv. */ if (need_ft_update) { int final_points_len = hair_cache->final[subdiv].strands_res * hair_cache->strands_len; - if (final_points_len) { - GPUShader *tf_shader = hair_refine_shader_get(PART_REFINE_CATMULL_ROM); + GPUShader *tf_shader = hair_refine_shader_get(PART_REFINE_CATMULL_ROM); #ifdef USE_TRANSFORM_FEEDBACK - DRWShadingGroup *tf_shgrp = DRW_shgroup_transform_feedback_create( - tf_shader, g_tf_pass, hair_cache->final[subdiv].proc_buf); + DRWShadingGroup *tf_shgrp = DRW_shgroup_transform_feedback_create( + tf_shader, g_tf_pass, hair_cache->final[subdiv].proc_buf); #else - DRWShadingGroup *tf_shgrp = DRW_shgroup_create(tf_shader, g_tf_pass); - - ParticleRefineCall *pr_call = MEM_mallocN(sizeof(*pr_call), __func__); - pr_call->next = g_tf_calls; - pr_call->vbo = hair_cache->final[subdiv].proc_buf; - pr_call->shgrp = tf_shgrp; - pr_call->vert_len = final_points_len; - g_tf_calls = pr_call; - DRW_shgroup_uniform_int(tf_shgrp, "targetHeight", &g_tf_target_height, 1); - DRW_shgroup_uniform_int(tf_shgrp, "targetWidth", &g_tf_target_width, 1); - DRW_shgroup_uniform_int(tf_shgrp, "idOffset", &g_tf_id_offset, 1); + DRWShadingGroup *tf_shgrp = DRW_shgroup_create(tf_shader, g_tf_pass); + + ParticleRefineCall *pr_call = MEM_mallocN(sizeof(*pr_call), __func__); + pr_call->next = g_tf_calls; + pr_call->vbo = hair_cache->final[subdiv].proc_buf; + pr_call->shgrp = tf_shgrp; + pr_call->vert_len = final_points_len; + g_tf_calls = pr_call; + DRW_shgroup_uniform_int(tf_shgrp, "targetHeight", &g_tf_target_height, 1); + DRW_shgroup_uniform_int(tf_shgrp, "targetWidth", &g_tf_target_width, 1); + DRW_shgroup_uniform_int(tf_shgrp, "idOffset", &g_tf_id_offset, 1); #endif - DRW_shgroup_uniform_texture(tf_shgrp, "hairPointBuffer", hair_cache->point_tex); - DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandBuffer", hair_cache->strand_tex); - DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandSegBuffer", hair_cache->strand_seg_tex); - DRW_shgroup_uniform_int( - tf_shgrp, "hairStrandsRes", &hair_cache->final[subdiv].strands_res, 1); - DRW_shgroup_call_procedural_points(tf_shgrp, NULL, final_points_len); - } + DRW_shgroup_uniform_texture(tf_shgrp, "hairPointBuffer", hair_cache->point_tex); + DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandBuffer", hair_cache->strand_tex); + DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandSegBuffer", hair_cache->strand_seg_tex); + DRW_shgroup_uniform_int(tf_shgrp, "hairStrandsRes", &hair_cache->final[subdiv].strands_res, 1); + DRW_shgroup_call_procedural_points(tf_shgrp, NULL, final_points_len); } return shgrp; diff --git a/source/blender/draw/intern/draw_instance_data.c b/source/blender/draw/intern/draw_instance_data.c index 81b10e095c3..69756203d66 100644 --- a/source/blender/draw/intern/draw_instance_data.c +++ b/source/blender/draw/intern/draw_instance_data.c @@ -64,7 +64,7 @@ typedef struct DRWTempBufferHandle { /** Format pointer for reuse. */ GPUVertFormat *format; /** Touched vertex length for resize. */ - int *vert_len; + uint *vert_len; } DRWTempBufferHandle; static ListBase g_idatalists = {NULL, NULL}; @@ -112,7 +112,7 @@ static void instance_batch_free(GPUBatch *geom, void *UNUSED(user_data)) */ GPUVertBuf *DRW_temp_buffer_request(DRWInstanceDataList *idatalist, GPUVertFormat *format, - int *vert_len) + uint *vert_len) { BLI_assert(format != NULL); BLI_assert(vert_len != NULL); diff --git a/source/blender/draw/intern/draw_instance_data.h b/source/blender/draw/intern/draw_instance_data.h index 524c4cd96d8..2ede68e16d8 100644 --- a/source/blender/draw/intern/draw_instance_data.h +++ b/source/blender/draw/intern/draw_instance_data.h @@ -40,7 +40,7 @@ DRWInstanceData *DRW_instance_data_request(DRWInstanceDataList *idatalist, uint GPUVertBuf *DRW_temp_buffer_request(DRWInstanceDataList *idatalist, GPUVertFormat *format, - int *vert_len); + uint *vert_len); GPUBatch *DRW_temp_batch_instance_request(DRWInstanceDataList *idatalist, GPUVertBuf *buf, GPUBatch *geom); diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 66e3905b212..fde7fdfa222 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -537,11 +537,8 @@ static void drw_viewport_cache_resize(void) GPU_texture_free(*tex); } - BLI_memblock_clear(DST.vmempool->commands, NULL); - BLI_memblock_clear(DST.vmempool->commands_small, NULL); - BLI_memblock_clear(DST.vmempool->callbuffers, NULL); - BLI_memblock_clear(DST.vmempool->obmats, NULL); - BLI_memblock_clear(DST.vmempool->obinfos, NULL); + BLI_memblock_clear(DST.vmempool->calls, NULL); + BLI_memblock_clear(DST.vmempool->states, NULL); BLI_memblock_clear(DST.vmempool->cullstates, NULL); BLI_memblock_clear(DST.vmempool->shgroups, NULL); BLI_memblock_clear(DST.vmempool->uniforms, NULL); @@ -589,28 +586,28 @@ static void drw_context_state_init(void) } } -static void draw_unit_state_create(void) +static DRWCallState *draw_unit_state_create(void) { - DRWObjectInfos *infos = BLI_memblock_alloc(DST.vmempool->obinfos); - DRWObjectMatrix *mats = BLI_memblock_alloc(DST.vmempool->obmats); - DRWCullingState *culling = BLI_memblock_alloc(DST.vmempool->cullstates); + DRWCallState *state = BLI_memblock_alloc(DST.vmempool->states); + state->flag = 0; + state->matflag = 0; - unit_m4(mats->model); - unit_m4(mats->modelinverse); + unit_m4(state->model); + unit_m4(state->modelinverse); - copy_v3_fl(infos->orcotexfac[0], 0.0f); - copy_v3_fl(infos->orcotexfac[1], 1.0f); + copy_v3_fl(state->orcotexfac[0], 0.0f); + copy_v3_fl(state->orcotexfac[1], 1.0f); - infos->ob_index = 0; - infos->ob_random = 0.0f; - infos->ob_neg_scale = 1.0f; - copy_v3_fl(infos->ob_color, 1.0f); + state->ob_index = 0; + state->ob_random = 0.0f; + copy_v3_fl(state->ob_color, 1.0f); /* TODO(fclem) get rid of this. */ - culling->bsphere.radius = -1.0f; - culling->user_data = NULL; + state->culling = BLI_memblock_alloc(DST.vmempool->cullstates); + state->culling->bsphere.radius = -1.0f; + state->culling->user_data = NULL; - DRW_handle_increment(&DST.resource_handle); + return state; } /* It also stores viewport variable to an immutable place: DST @@ -635,48 +632,33 @@ static void drw_viewport_var_init(void) DST.vmempool = GPU_viewport_mempool_get(DST.viewport); - if (DST.vmempool->commands == NULL) { - DST.vmempool->commands = BLI_memblock_create(sizeof(DRWCommandChunk)); + if (DST.vmempool->calls == NULL) { + DST.vmempool->calls = BLI_memblock_create(sizeof(DRWCall)); } - if (DST.vmempool->commands_small == NULL) { - DST.vmempool->commands_small = BLI_memblock_create(sizeof(DRWCommandSmallChunk)); - } - if (DST.vmempool->callbuffers == NULL) { - DST.vmempool->callbuffers = BLI_memblock_create(sizeof(DRWCallBuffer)); - } - if (DST.vmempool->obmats == NULL) { - uint chunk_len = sizeof(DRWObjectMatrix) * DRW_RESOURCE_CHUNK_LEN; - DST.vmempool->obmats = BLI_memblock_create_ex(sizeof(DRWObjectMatrix), chunk_len); - } - if (DST.vmempool->obinfos == NULL) { - uint chunk_len = sizeof(DRWObjectInfos) * DRW_RESOURCE_CHUNK_LEN; - DST.vmempool->obinfos = BLI_memblock_create_ex(sizeof(DRWObjectInfos), chunk_len); + if (DST.vmempool->states == NULL) { + DST.vmempool->states = BLI_memblock_create(sizeof(DRWCallState)); } if (DST.vmempool->cullstates == NULL) { - uint chunk_len = sizeof(DRWCullingState) * DRW_RESOURCE_CHUNK_LEN; - DST.vmempool->cullstates = BLI_memblock_create_ex(sizeof(DRWCullingState), chunk_len); + DST.vmempool->cullstates = BLI_memblock_create(sizeof(DRWCullingState)); } if (DST.vmempool->shgroups == NULL) { DST.vmempool->shgroups = BLI_memblock_create(sizeof(DRWShadingGroup)); } if (DST.vmempool->uniforms == NULL) { - DST.vmempool->uniforms = BLI_memblock_create(sizeof(DRWUniformChunk)); + DST.vmempool->uniforms = BLI_memblock_create(sizeof(DRWUniform)); } if (DST.vmempool->views == NULL) { DST.vmempool->views = BLI_memblock_create(sizeof(DRWView)); } if (DST.vmempool->passes == NULL) { - uint chunk_len = sizeof(DRWPass) * DRW_RESOURCE_CHUNK_LEN; - DST.vmempool->passes = BLI_memblock_create_ex(sizeof(DRWPass), chunk_len); + DST.vmempool->passes = BLI_memblock_create(sizeof(DRWPass)); } if (DST.vmempool->images == NULL) { DST.vmempool->images = BLI_memblock_create(sizeof(GPUTexture *)); } - DST.resource_handle = 0; - DST.pass_handle = 0; - - draw_unit_state_create(); + /* Alloc default unit state */ + DST.unit_state = draw_unit_state_create(); DST.idatalist = GPU_viewport_instance_data_list_get(DST.viewport); DRW_instance_data_list_reset(DST.idatalist); @@ -690,6 +672,8 @@ static void drw_viewport_var_init(void) DST.default_framebuffer = NULL; DST.vmempool = NULL; + + DST.unit_state = NULL; } DST.primary_view_ct = 0; @@ -732,10 +716,6 @@ static void drw_viewport_var_init(void) G_draw.view_ubo = DRW_uniformbuffer_create(sizeof(DRWViewUboStorage), NULL); } - if (DST.draw_list == NULL) { - DST.draw_list = GPU_draw_list_create(DRW_DRAWLIST_LEN); - } - memset(DST.object_instance_data, 0x0, sizeof(DST.object_instance_data)); } @@ -1119,7 +1099,7 @@ static void drw_engines_world_update(Scene *scene) static void drw_engines_cache_populate(Object *ob) { - DST.ob_handle = 0; + DST.ob_state = NULL; /* HACK: DrawData is copied by COW from the duplicated object. * This is valid for IDs that cannot be instantiated but this @@ -1937,8 +1917,6 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph RenderResult *render_result = RE_engine_get_result(engine); RenderLayer *render_layer = RE_GetRenderLayer(render_result, view_layer->name); - DST.buffer_finish_called = false; - DRW_render_gpencil_to_image(engine, render_layer, &render_rect); /* Force cache to reset. */ @@ -2049,15 +2027,13 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) RE_SetActiveRenderView(render, render_view->name); drw_view_reset(); engine_type->draw_engine->render_to_image(data, engine, render_layer, &render_rect); - DST.buffer_finish_called = false; - /* grease pencil: render result is merged in the previous render result. */ if (DRW_render_check_grease_pencil(depsgraph)) { DRW_state_reset(); drw_view_reset(); DRW_render_gpencil_to_image(engine, render_layer, &render_rect); - DST.buffer_finish_called = false; } + DST.buffer_finish_called = false; } RE_engine_end_result(engine, render_result, false, false, false); @@ -2103,7 +2079,7 @@ void DRW_render_object_iter( if ((object_type_exclude_viewport & (1 << ob->type)) == 0) { DST.dupli_parent = data_.dupli_parent; DST.dupli_source = data_.dupli_object_current; - DST.ob_handle = 0; + DST.ob_state = NULL; drw_duplidata_load(DST.dupli_source); if (!DST.dupli_source) { @@ -2210,7 +2186,6 @@ void DRW_render_instance_buffer_finish(void) BLI_assert(!DST.buffer_finish_called && "DRW_render_instance_buffer_finish called twice!"); DST.buffer_finish_called = true; DRW_instance_buffer_finish(DST.idatalist); - drw_resource_buffer_finish(DST.vmempool); } /** @@ -2234,7 +2209,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, Object *obact = OBACT(view_layer); Object *obedit = OBEDIT_FROM_OBACT(obact); #ifndef USE_GPU_SELECT - UNUSED_VARS(scene, view_layer, v3d, ar, rect); + UNUSED_VARS(vc, scene, view_layer, v3d, ar, rect); #else RegionView3D *rv3d = ar->regiondata; @@ -2959,10 +2934,6 @@ void DRW_engines_free(void) MEM_SAFE_FREE(DST.uniform_names.buffer); - if (DST.draw_list) { - GPU_draw_list_discard(DST.draw_list); - } - DRW_opengl_context_disable(); } diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h index b55a84b2765..85f6cf05e83 100644 --- a/source/blender/draw/intern/draw_manager.h +++ b/source/blender/draw/intern/draw_manager.h @@ -28,10 +28,8 @@ #include "DRW_engine.h" #include "DRW_render.h" -#include "BLI_assert.h" #include "BLI_linklist.h" #include "BLI_threads.h" -#include "BLI_memblock.h" #include "GPU_batch.h" #include "GPU_context.h" @@ -45,9 +43,6 @@ /* Use draw manager to call GPU_select, see: DRW_draw_select_loop */ #define USE_GPU_SELECT -/* Use drawcall batching using instanced rendering. */ -#define USE_BATCHING 1 - // #define DRW_DEBUG_CULLING #define DRW_DEBUG_USE_UNIFORM_NAME 0 #define DRW_UNIFORM_BUFFER_NAME 64 @@ -95,6 +90,20 @@ * > DRWUniform */ +/* Used by DRWCallState.flag */ +enum { + DRW_CALL_NEGSCALE = (1 << 1), +}; + +/* Used by DRWCallState.matflag */ +enum { + DRW_CALL_MODELINVERSE = (1 << 0), + DRW_CALL_MODELVIEWPROJECTION = (1 << 1), + DRW_CALL_ORCOTEXFAC = (1 << 2), + DRW_CALL_OBJECTINFO = (1 << 3), + DRW_CALL_OBJECTCOLOR = (1 << 4), +}; + typedef struct DRWCullingState { uint32_t mask; /* Culling: Using Bounding Sphere for now for faster culling. @@ -104,161 +113,38 @@ typedef struct DRWCullingState { void *user_data; } DRWCullingState; -/* Minimum max UBO size is 64KiB. We take the largest - * UBO struct and alloc the max number. - * ((1 << 16) / sizeof(DRWObjectMatrix)) = 512 - * Keep in sync with common_view_lib.glsl */ -#define DRW_RESOURCE_CHUNK_LEN 512 - -/** - * Identifier used to sort similar drawcalls together. - * Also used to reference elements inside memory blocks. - * - * From MSB to LSB - * 1 bit for negative scale. - * 22 bits for chunk id. - * 9 bits for resource id inside the chunk. (can go up to 511) - * |-|----------------------|---------| - * - * Use manual bitsift and mask instead of bitfields to avoid - * compiler dependant behavior that would mess the ordering of - * the members thus changing the sorting order. - */ -typedef uint32_t DRWResourceHandle; - -BLI_INLINE uint32_t DRW_handle_negative_scale_get(const DRWResourceHandle *handle) -{ - return (*handle & 0x80000000) != 0; -} - -BLI_INLINE uint32_t DRW_handle_chunk_get(const DRWResourceHandle *handle) -{ - return (*handle & 0x7FFFFFFF) >> 9; -} - -BLI_INLINE uint32_t DRW_handle_id_get(const DRWResourceHandle *handle) -{ - return (*handle & 0x000001FF); -} - -BLI_INLINE void DRW_handle_increment(DRWResourceHandle *handle) -{ - *handle += 1; -} - -BLI_INLINE void DRW_handle_negative_scale_enable(DRWResourceHandle *handle) -{ - *handle |= 0x80000000; -} - -BLI_INLINE void *DRW_memblock_elem_from_handle(struct BLI_memblock *memblock, - const DRWResourceHandle *handle) -{ - int elem = DRW_handle_id_get(handle); - int chunk = DRW_handle_chunk_get(handle); - return BLI_memblock_elem_get(memblock, chunk, elem); -} - -typedef struct DRWObjectMatrix { +typedef struct DRWCallState { + DRWCullingState *culling; + uchar flag; + uchar matflag; /* Which matrices to compute. */ + short ob_index; + /* Matrices */ float model[4][4]; float modelinverse[4][4]; -} DRWObjectMatrix; - -typedef struct DRWObjectInfos { - float orcotexfac[2][4]; - float ob_color[4]; - float ob_index; - float pad; /* UNUSED*/ + float orcotexfac[2][3]; float ob_random; - float ob_neg_scale; -} DRWObjectInfos; - -BLI_STATIC_ASSERT_ALIGN(DRWObjectMatrix, 16) -BLI_STATIC_ASSERT_ALIGN(DRWObjectInfos, 16) + float ob_color[4]; +} DRWCallState; -typedef enum { - /* Draw Commands */ - DRW_CMD_DRAW = 0, /* Only sortable type. Must be 0. */ - DRW_CMD_DRAW_RANGE = 1, - DRW_CMD_DRAW_INSTANCE = 2, - DRW_CMD_DRAW_PROCEDURAL = 3, - /* Other Commands */ - DRW_CMD_CLEAR = 12, - DRW_CMD_DRWSTATE = 13, - DRW_CMD_STENCIL = 14, - DRW_CMD_SELECTID = 15, - /* Needs to fit in 4bits */ -} eDRWCommandType; - -#define DRW_MAX_DRAW_CMD_TYPE DRW_CMD_DRAW_PROCEDURAL - -typedef struct DRWCommandDraw { - GPUBatch *batch; - DRWResourceHandle handle; -} DRWCommandDraw; +typedef struct DRWCall { + struct DRWCall *next; + DRWCallState *state; -/* Assume DRWResourceHandle to be 0. */ -typedef struct DRWCommandDrawRange { GPUBatch *batch; uint vert_first; uint vert_count; -} DRWCommandDrawRange; - -typedef struct DRWCommandDrawInstance { - GPUBatch *batch; - DRWResourceHandle handle; uint inst_count; -} DRWCommandDrawInstance; - -typedef struct DRWCommandDrawProcedural { - GPUBatch *batch; - DRWResourceHandle handle; - uint vert_count; -} DRWCommandDrawProcedural; -typedef struct DRWCommandSetMutableState { - /** State changes (or'd or and'd with the pass's state) */ - DRWState enable; - DRWState disable; -} DRWCommandSetMutableState; - -typedef struct DRWCommandSetStencil { - uint mask; -} DRWCommandSetStencil; - -typedef struct DRWCommandSetSelectID { - GPUVertBuf *select_buf; - uint select_id; -} DRWCommandSetSelectID; - -typedef struct DRWCommandClear { - eGPUFrameBufferBits clear_channels; - uchar r, g, b, a; /* [0..1] for each channels. Normalized. */ - float depth; /* [0..1] for depth. Normalized. */ - uchar stencil; /* Stencil value [0..255] */ -} DRWCommandClear; - -typedef union DRWCommand { - DRWCommandDraw draw; - DRWCommandDrawRange range; - DRWCommandDrawInstance instance; - DRWCommandDrawProcedural procedural; - DRWCommandSetMutableState state; - DRWCommandSetStencil stencil; - DRWCommandSetSelectID select_id; - DRWCommandClear clear; -} DRWCommand; - -/* Used for agregating calls into GPUVertBufs. */ -struct DRWCallBuffer { - GPUVertBuf *buf; - GPUVertBuf *buf_select; - int count; -}; +#ifdef USE_GPU_SELECT + /* TODO(fclem) remove once we have a dedicated selection engine. */ + int select_id; + GPUVertBuf *inst_selectid; +#endif +} DRWCall; /* Used by DRWUniform.type */ typedef enum { - DRW_UNIFORM_INT = 0, + DRW_UNIFORM_INT, DRW_UNIFORM_INT_COPY, DRW_UNIFORM_FLOAT, DRW_UNIFORM_FLOAT_COPY, @@ -267,56 +153,55 @@ typedef enum { DRW_UNIFORM_TEXTURE_REF, DRW_UNIFORM_BLOCK, DRW_UNIFORM_BLOCK_PERSIST, - DRW_UNIFORM_TFEEDBACK_TARGET, - /** Per drawcall uniforms/UBO */ - DRW_UNIFORM_BLOCK_OBMATS, - DRW_UNIFORM_BLOCK_OBINFOS, - DRW_UNIFORM_RESOURCE_CHUNK, - /** Legacy / Fallback */ - DRW_UNIFORM_BASE_INSTANCE, - DRW_UNIFORM_MODEL_MATRIX, - DRW_UNIFORM_MODEL_MATRIX_INVERSE, - DRW_UNIFORM_MODELVIEWPROJECTION_MATRIX, - /* WARNING: set DRWUniform->type - * bit length accordingly. */ } DRWUniformType; struct DRWUniform { + DRWUniform *next; /* single-linked list */ union { /* For reference or array/vector types. */ const void *pvalue; /* Single values. */ - float fvalue[4]; - int ivalue[4]; + float fvalue[2]; + int ivalue[2]; }; + int name_ofs; /* name offset in name buffer. */ int location; - uint32_t type : 5; /* DRWUniformType */ - uint32_t length : 5; /* cannot be more than 16 */ - uint32_t arraysize : 5; /* cannot be more than 16 too */ - uint32_t name_ofs : 17; /* name offset in name buffer. */ + char type; /* DRWUniformType */ + char length; /* cannot be more than 16 */ + char arraysize; /* cannot be more than 16 too */ }; struct DRWShadingGroup { DRWShadingGroup *next; - GPUShader *shader; /* Shader to bind */ - struct DRWUniformChunk *uniforms; /* Uniforms pointers */ + GPUShader *shader; /* Shader to bind */ + DRWUniform *uniforms; /* Uniforms pointers */ struct { - /* Chunks of draw calls. */ - struct DRWCommandChunk *first, *last; - } cmd; + DRWCall *first, *last; /* Linked list of DRWCall */ + } calls; - union { - struct { - int objectinfo; /* Equal to 1 if the shader needs obinfos. */ - DRWResourceHandle pass_handle; /* Memblock key to parent pass. */ - }; - struct { - float distance; /* Distance from camera. */ - uint original_index; /* Original position inside the shgroup list. */ - } z_sorting; - }; + /** TODO Maybe remove from here */ + struct GPUVertBuf *tfeedback_target; + + /** State changes for this batch only (or'd with the pass's state) */ + DRWState state_extra; + /** State changes for this batch only (and'd with the pass's state) */ + DRWState state_extra_disable; + /** Stencil mask to use for stencil test / write operations */ + uint stencil_mask; + + /* Builtin matrices locations */ + int model; + int modelinverse; + int modelviewprojection; + int orcotexfac; + int callid; + int objectinfo; + int objectcolor; + uchar matflag; /* Matrices needed, same as DRWCall.flag */ + + DRWPass *pass_parent; /* backlink to pass we're in */ }; #define MAX_PASS_NAME 32 @@ -328,7 +213,6 @@ struct DRWPass { DRWShadingGroup *last; } shgroups; - DRWResourceHandle handle; DRWState state; char name[MAX_PASS_NAME]; }; @@ -348,8 +232,6 @@ typedef struct DRWViewUboStorage { float viewcamtexcofac[4]; } DRWViewUboStorage; -BLI_STATIC_ASSERT_ALIGN(DRWViewUboStorage, 16) - #define MAX_CULLED_VIEWS 32 struct DRWView { @@ -371,45 +253,13 @@ struct DRWView { void *user_data; }; -/* ------------ Data Chunks --------------- */ -/** - * In order to keep a cache friendly data structure, - * we alloc most of our little data into chunks of multiple item. - * Iteration, allocation and memory usage are better. - * We loose a bit of memory by allocating more than what we need - * but it's counterbalanced by not needing the linked-list pointers - * for each item. - **/ - -typedef struct DRWUniformChunk { - struct DRWUniformChunk *next; /* single-linked list */ - uint32_t uniform_len; - uint32_t uniform_used; - DRWUniform uniforms[10]; -} DRWUniformChunk; - -typedef struct DRWCommandChunk { - struct DRWCommandChunk *next; - uint32_t command_len; - uint32_t command_used; - /* 4bits for each command. */ - uint64_t command_type[6]; - /* -- 64 bytes aligned -- */ - DRWCommand commands[96]; - /* -- 64 bytes aligned -- */ -} DRWCommandChunk; - -typedef struct DRWCommandSmallChunk { - struct DRWCommandChunk *next; - uint32_t command_len; - uint32_t command_used; - /* 4bits for each command. */ - /* TODO reduce size of command_type. */ - uint64_t command_type[6]; - DRWCommand commands[6]; -} DRWCommandSmallChunk; - -BLI_STATIC_ASSERT_ALIGN(DRWCommandChunk, 16); +/* TODO(fclem): Future awaits */ +#if 0 +typedef struct ModelUboStorage { + float model[4][4]; + float modelinverse[4][4]; +} ModelUboStorage; +#endif /* ------------- DRAW DEBUG ------------ */ @@ -430,31 +280,21 @@ typedef struct DRWDebugSphere { #define DST_MAX_SLOTS 64 /* Cannot be changed without modifying RST.bound_tex_slots */ #define MAX_CLIP_PLANES 6 /* GL_MAX_CLIP_PLANES is at least 6 */ #define STENCIL_UNDEFINED 256 -#define DRW_DRAWLIST_LEN 256 typedef struct DRWManager { /* TODO clean up this struct a bit */ /* Cache generation */ ViewportMemoryPool *vmempool; DRWInstanceDataList *idatalist; + DRWInstanceData *object_instance_data[MAX_INSTANCE_DATA_SIZE]; + /* Default Unit model matrix state without culling. */ + DRWCallState *unit_state; /* State of the object being evaluated if already allocated. */ - DRWResourceHandle ob_handle; - /** True if current DST.ob_state has its matching DRWObjectInfos init. */ - bool ob_state_obinfo_init; - /** Handle of current object resource in object resource arrays (DRWObjectMatrices/Infos). */ - DRWResourceHandle resource_handle; - /** Handle of next DRWPass to be allocated. */ - DRWResourceHandle pass_handle; - - /** Dupli state. NULL if not dupli. */ + DRWCallState *ob_state; struct DupliObject *dupli_source; struct Object *dupli_parent; struct Object *dupli_origin; - /** Ghash containing original objects. */ struct GHash *dupli_ghash; - /** TODO(fclem) try to remove usage of this. */ - DRWInstanceData *object_instance_data[MAX_INSTANCE_DATA_SIZE]; - /* Array of dupli_data (one for each enabled engine) to handle duplis. */ - void **dupli_datas; + void **dupli_datas; /* Array of dupli_data (one for each enabled engine) to handle duplis. */ /* Rendering state */ GPUShader *shader; @@ -517,8 +357,6 @@ typedef struct DRWManager { /** Mutex to lock the drw manager and avoid concurrent context usage. */ TicketMutex *gl_context_mutex; - GPUDrawList *draw_list; - /** GPU Resource State: Memory storage between drawing. */ struct { /* High end GPUs supports up to 32 binds per shader stage. @@ -559,13 +397,9 @@ void drw_state_set(DRWState state); void drw_debug_draw(void); void drw_debug_init(void); -eDRWCommandType command_type_get(uint64_t *command_type_bits, int index); - void drw_batch_cache_validate(Object *ob); void drw_batch_cache_generate_requested(struct Object *ob); -void drw_resource_buffer_finish(ViewportMemoryPool *vmempool); - /* Procedural Drawing */ GPUBatch *drw_cache_procedural_points_get(void); GPUBatch *drw_cache_procedural_lines_get(void); diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index cdf2c208351..cd174e899d4 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -34,7 +34,6 @@ #include "DNA_mesh_types.h" #include "DNA_meta_types.h" -#include "BLI_alloca.h" #include "BLI_hash.h" #include "BLI_link_utils.h" #include "BLI_mempool.h" @@ -52,35 +51,6 @@ /** \name Uniform Buffer Object (DRW_uniformbuffer) * \{ */ -static void draw_call_sort(DRWCommand *array, DRWCommand *array_tmp, int array_len) -{ - /* Count unique batches. Tt's not really important if - * there is colisions. If there is a lot of different batches, - * the sorting benefit will be negligeable. So at least - * sort fast! */ - uchar idx[128] = {0}; - /* Shift by 6 positions knowing each GPUBatch is > 64 bytes */ -#define KEY(a) ((((size_t)((a).draw.batch)) >> 6) % ARRAY_SIZE(idx)) - BLI_assert(array_len <= ARRAY_SIZE(idx)); - - for (int i = 0; i < array_len; i++) { - /* Early out if nothing to sort. */ - if (++idx[KEY(array[i])] == array_len) - return; - } - /* Cumulate batch indices */ - for (int i = 1; i < ARRAY_SIZE(idx); i++) { - idx[i] += idx[i - 1]; - } - /* Traverse in reverse to not change the order of the resource ids. */ - for (int src = array_len - 1; src >= 0; src--) { - array_tmp[--idx[KEY(array[src])]] = array[src]; - } -#undef KEY - - memcpy(array, array_tmp, sizeof(*array) * array_len); -} - GPUUniformBuffer *DRW_uniformbuffer_create(int size, const void *data) { return GPU_uniformbuffer_create(size, data, NULL); @@ -96,94 +66,20 @@ void DRW_uniformbuffer_free(GPUUniformBuffer *ubo) GPU_uniformbuffer_free(ubo); } -void drw_resource_buffer_finish(ViewportMemoryPool *vmempool) -{ - int chunk_id = DRW_handle_chunk_get(&DST.resource_handle); - int elem_id = DRW_handle_id_get(&DST.resource_handle); - int ubo_len = 1 + chunk_id - ((elem_id == 0) ? 1 : 0); - size_t list_size = sizeof(GPUUniformBuffer *) * ubo_len; - - /* TODO find a better system. currently a lot of obinfos UBO are going to be unused - * if not rendering with Eevee. */ - - if (vmempool->matrices_ubo == NULL) { - vmempool->matrices_ubo = MEM_callocN(list_size, __func__); - vmempool->obinfos_ubo = MEM_callocN(list_size, __func__); - vmempool->ubo_len = ubo_len; - } - - /* Remove unecessary buffers */ - for (int i = ubo_len; i < vmempool->ubo_len; i++) { - GPU_uniformbuffer_free(vmempool->matrices_ubo[i]); - GPU_uniformbuffer_free(vmempool->obinfos_ubo[i]); - } - - if (ubo_len != vmempool->ubo_len) { - vmempool->matrices_ubo = MEM_recallocN(vmempool->matrices_ubo, list_size); - vmempool->obinfos_ubo = MEM_recallocN(vmempool->obinfos_ubo, list_size); - vmempool->ubo_len = ubo_len; - } - - /* Create/Update buffers. */ - for (int i = 0; i < ubo_len; i++) { - void *data_obmat = BLI_memblock_elem_get(vmempool->obmats, i, 0); - void *data_infos = BLI_memblock_elem_get(vmempool->obinfos, i, 0); - if (vmempool->matrices_ubo[i] == NULL) { - vmempool->matrices_ubo[i] = GPU_uniformbuffer_create( - sizeof(DRWObjectMatrix) * DRW_RESOURCE_CHUNK_LEN, data_obmat, NULL); - vmempool->obinfos_ubo[i] = GPU_uniformbuffer_create( - sizeof(DRWObjectInfos) * DRW_RESOURCE_CHUNK_LEN, data_infos, NULL); - } - else { - GPU_uniformbuffer_update(vmempool->matrices_ubo[i], data_obmat); - GPU_uniformbuffer_update(vmempool->obinfos_ubo[i], data_infos); - } - } - - /* Aligned alloc to avoid unaligned memcpy. */ - DRWCommandChunk *chunk_tmp = MEM_mallocN_aligned(sizeof(DRWCommandChunk), 16, "tmp call chunk"); - DRWCommandChunk *chunk; - BLI_memblock_iter iter; - BLI_memblock_iternew(vmempool->commands, &iter); - while ((chunk = BLI_memblock_iterstep(&iter))) { - bool sortable = true; - /* We can only sort chunks that contain DRWCommandDraw only. */ - for (int i = 0; i < ARRAY_SIZE(chunk->command_type) && sortable; i++) { - if (chunk->command_type[i] != 0) { - sortable = false; - } - } - if (sortable) { - draw_call_sort(chunk->commands, chunk_tmp->commands, chunk->command_used); - } - } - MEM_freeN(chunk_tmp); -} - /** \} */ /* -------------------------------------------------------------------- */ /** \name Uniforms (DRW_shgroup_uniform) * \{ */ -static DRWUniform *drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup, - int loc, - DRWUniformType type, - const void *value, - int length, - int arraysize) +static void drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup, + int loc, + DRWUniformType type, + const void *value, + int length, + int arraysize) { - DRWUniformChunk *unichunk = shgroup->uniforms; - /* Happens on first uniform or if chunk is full. */ - if (!unichunk || unichunk->uniform_used == unichunk->uniform_len) { - unichunk = BLI_memblock_alloc(DST.vmempool->uniforms); - unichunk->uniform_len = ARRAY_SIZE(shgroup->uniforms->uniforms); - unichunk->uniform_used = 0; - BLI_LINKS_PREPEND(shgroup->uniforms, unichunk); - } - - DRWUniform *uni = unichunk->uniforms + unichunk->uniform_used++; - + DRWUniform *uni = BLI_memblock_alloc(DST.vmempool->uniforms); uni->location = loc; uni->type = type; uni->length = length; @@ -191,11 +87,11 @@ static DRWUniform *drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup, switch (type) { case DRW_UNIFORM_INT_COPY: - BLI_assert(length <= 4); + BLI_assert(length <= 2); memcpy(uni->ivalue, value, sizeof(int) * length); break; case DRW_UNIFORM_FLOAT_COPY: - BLI_assert(length <= 4); + BLI_assert(length <= 2); memcpy(uni->fvalue, value, sizeof(float) * length); break; default: @@ -203,7 +99,7 @@ static DRWUniform *drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup, break; } - return uni; + BLI_LINKS_PREPEND(shgroup->uniforms, uni); } static void drw_shgroup_builtin_uniform( @@ -240,8 +136,7 @@ static void drw_shgroup_uniform(DRWShadingGroup *shgroup, BLI_assert(arraysize > 0 && arraysize <= 16); BLI_assert(length >= 0 && length <= 16); - DRWUniform *uni = drw_shgroup_uniform_create_ex( - shgroup, location, type, value, length, arraysize); + drw_shgroup_uniform_create_ex(shgroup, location, type, value, length, arraysize); /* If location is -2, the uniform has not yet been queried. * We save the name for query just before drawing. */ @@ -260,7 +155,7 @@ static void drw_shgroup_uniform(DRWShadingGroup *shgroup, memcpy(dst, name, len); /* Copies NULL terminator. */ DST.uniform_names.buffer_ofs += len; - uni->name_ofs = ofs; + shgroup->uniforms->name_ofs = ofs; } } @@ -391,21 +286,6 @@ void DRW_shgroup_uniform_int_copy(DRWShadingGroup *shgroup, const char *name, co drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_INT_COPY, &value, 1, 1); } -void DRW_shgroup_uniform_ivec2_copy(DRWShadingGroup *shgroup, const char *name, const int *value) -{ - drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_INT_COPY, value, 2, 1); -} - -void DRW_shgroup_uniform_ivec3_copy(DRWShadingGroup *shgroup, const char *name, const int *value) -{ - drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_INT_COPY, value, 3, 1); -} - -void DRW_shgroup_uniform_ivec4_copy(DRWShadingGroup *shgroup, const char *name, const int *value) -{ - drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_INT_COPY, value, 4, 1); -} - void DRW_shgroup_uniform_bool_copy(DRWShadingGroup *shgroup, const char *name, const bool value) { int ival = value; @@ -422,23 +302,13 @@ void DRW_shgroup_uniform_vec2_copy(DRWShadingGroup *shgroup, const char *name, c drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT_COPY, value, 2, 1); } -void DRW_shgroup_uniform_vec3_copy(DRWShadingGroup *shgroup, const char *name, const float *value) -{ - drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT_COPY, value, 3, 1); -} - -void DRW_shgroup_uniform_vec4_copy(DRWShadingGroup *shgroup, const char *name, const float *value) -{ - drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT_COPY, value, 4, 1); -} - /** \} */ /* -------------------------------------------------------------------- */ /** \name Draw Call (DRW_calls) * \{ */ -static void drw_call_calc_orco(Object *ob, float (*r_orcofacs)[4]) +static void drw_call_calc_orco(Object *ob, float (*r_orcofacs)[3]) { ID *ob_data = (ob) ? ob->data : NULL; float *texcoloc = NULL; @@ -481,283 +351,159 @@ static void drw_call_calc_orco(Object *ob, float (*r_orcofacs)[4]) } } -BLI_INLINE void drw_call_matrix_init(DRWObjectMatrix *ob_mats, Object *ob, float (*obmat)[4]) +static void drw_call_state_update_matflag(DRWCallState *state, + DRWShadingGroup *shgroup, + Object *ob) { - copy_m4_m4(ob_mats->model, obmat); - if (ob) { - copy_m4_m4(ob_mats->modelinverse, ob->imat); + uchar new_flags = ((state->matflag ^ shgroup->matflag) & shgroup->matflag); + + /* HACK: Here we set the matflags bit to 1 when computing the value + * so that it's not recomputed for other drawcalls. + * This is the opposite of what draw_matrices_model_prepare() does. */ + state->matflag |= shgroup->matflag; + + if (new_flags & DRW_CALL_MODELINVERSE) { + if (ob) { + copy_m4_m4(state->modelinverse, ob->imat); + } + else { + invert_m4_m4(state->modelinverse, state->model); + } } - else { - /* WATCH: Can be costly. */ - invert_m4_m4(ob_mats->modelinverse, ob_mats->model); + + /* Orco factors: We compute this at creation to not have to save the *ob_data */ + if (new_flags & DRW_CALL_ORCOTEXFAC) { + drw_call_calc_orco(ob, state->orcotexfac); } -} -static void drw_call_obinfos_init(DRWObjectInfos *ob_infos, Object *ob) -{ - BLI_assert(ob); - /* Index. */ - ob_infos->ob_index = ob->index; - /* Orco factors. */ - drw_call_calc_orco(ob, ob_infos->orcotexfac); - /* Random float value. */ - uint random = (DST.dupli_source) ? - DST.dupli_source->random_id : - /* TODO(fclem) this is rather costly to do at runtime. Maybe we can - * put it in ob->runtime and make depsgraph ensure it is up to date. */ - BLI_hash_int_2d(BLI_hash_string(ob->id.name + 2), 0); - ob_infos->ob_random = random * (1.0f / (float)0xFFFFFFFF); - /* Negative scalling. */ - ob_infos->ob_neg_scale = (ob->transflag & OB_NEG_SCALE) ? -1.0f : 1.0f; - /* Object Color. */ - copy_v4_v4(ob_infos->ob_color, ob->color); + if (new_flags & DRW_CALL_OBJECTINFO) { + state->ob_index = ob ? ob->index : 0; + uint random; + if (DST.dupli_source) { + random = DST.dupli_source->random_id; + } + else { + random = BLI_hash_int_2d(BLI_hash_string(ob->id.name + 2), 0); + } + state->ob_random = random * (1.0f / (float)0xFFFFFFFF); + } + + if (new_flags & DRW_CALL_OBJECTCOLOR) { + copy_v4_v4(state->ob_color, ob->color); + } } -static void drw_call_culling_init(DRWCullingState *cull, Object *ob) +static DRWCallState *drw_call_state_create(DRWShadingGroup *shgroup, float (*obmat)[4], Object *ob) { + DRWCallState *state = BLI_memblock_alloc(DST.vmempool->states); + state->flag = 0; + state->matflag = 0; + + /* Matrices */ + copy_m4_m4(state->model, obmat); + + if (ob && (ob->transflag & OB_NEG_SCALE)) { + state->flag |= DRW_CALL_NEGSCALE; + } + + drw_call_state_update_matflag(state, shgroup, ob); + + DRWCullingState *cull = BLI_memblock_alloc(DST.vmempool->cullstates); + state->culling = cull; + BoundBox *bbox; if (ob != NULL && (bbox = BKE_object_boundbox_get(ob))) { float corner[3]; /* Get BoundSphere center and radius from the BoundBox. */ mid_v3_v3v3(cull->bsphere.center, bbox->vec[0], bbox->vec[6]); - mul_v3_m4v3(corner, ob->obmat, bbox->vec[0]); - mul_m4_v3(ob->obmat, cull->bsphere.center); + mul_v3_m4v3(corner, obmat, bbox->vec[0]); + mul_m4_v3(obmat, cull->bsphere.center); cull->bsphere.radius = len_v3v3(cull->bsphere.center, corner); } else { + /* TODO(fclem) Bypass alloc if we can (see if eevee's + * probe visibility collection still works). */ /* Bypass test. */ cull->bsphere.radius = -1.0f; } - /* Reset user data */ - cull->user_data = NULL; -} - -static DRWResourceHandle drw_resource_handle_new(float (*obmat)[4], Object *ob) -{ - DRWCullingState *culling = BLI_memblock_alloc(DST.vmempool->cullstates); - DRWObjectMatrix *ob_mats = BLI_memblock_alloc(DST.vmempool->obmats); - /* FIXME Meh, not always needed but can be accessed after creation. - * Also it needs to have the same resource handle. */ - DRWObjectInfos *ob_infos = BLI_memblock_alloc(DST.vmempool->obinfos); - UNUSED_VARS(ob_infos); - - DRWResourceHandle handle = DST.resource_handle; - DRW_handle_increment(&DST.resource_handle); - if (ob && (ob->transflag & OB_NEG_SCALE)) { - DRW_handle_negative_scale_enable(&handle); - } - - drw_call_matrix_init(ob_mats, ob, obmat); - drw_call_culling_init(culling, ob); - /* ob_infos is init only if needed. */ - - return handle; + return state; } -static DRWResourceHandle drw_resource_handle(DRWShadingGroup *shgroup, - float (*obmat)[4], - Object *ob) +static DRWCallState *drw_call_state_object(DRWShadingGroup *shgroup, float (*obmat)[4], Object *ob) { if (ob == NULL) { if (obmat == NULL) { - DRWResourceHandle handle = 0; - return handle; + BLI_assert(DST.unit_state); + return DST.unit_state; } else { - return drw_resource_handle_new(obmat, NULL); + return drw_call_state_create(shgroup, obmat, ob); } } else { - if (DST.ob_handle == 0) { - DST.ob_handle = drw_resource_handle_new(obmat, ob); - DST.ob_state_obinfo_init = false; + if (DST.ob_state == NULL) { + DST.ob_state = drw_call_state_create(shgroup, obmat, ob); } - - if (shgroup->objectinfo) { - if (!DST.ob_state_obinfo_init) { - DST.ob_state_obinfo_init = true; - DRWObjectInfos *ob_infos = DRW_memblock_elem_from_handle(DST.vmempool->obinfos, - &DST.ob_handle); - - drw_call_obinfos_init(ob_infos, ob); - } + else { + /* If the DRWCallState is reused, add necessary matrices. */ + drw_call_state_update_matflag(DST.ob_state, shgroup, ob); } - return DST.ob_handle; - } -} - -static void command_type_set(uint64_t *command_type_bits, int index, eDRWCommandType type) -{ - command_type_bits[index / 16] |= ((uint64_t)type) << ((index % 16) * 4); -} - -eDRWCommandType command_type_get(uint64_t *command_type_bits, int index) -{ - return ((command_type_bits[index / 16] >> ((index % 16) * 4)) & 0xF); -} - -static void *drw_command_create(DRWShadingGroup *shgroup, eDRWCommandType type) -{ - DRWCommandChunk *chunk = shgroup->cmd.last; - - if (chunk == NULL) { - DRWCommandSmallChunk *smallchunk = BLI_memblock_alloc(DST.vmempool->commands_small); - smallchunk->command_len = ARRAY_SIZE(smallchunk->commands); - smallchunk->command_used = 0; - smallchunk->command_type[0] = 0x0lu; - chunk = (DRWCommandChunk *)smallchunk; - BLI_LINKS_APPEND(&shgroup->cmd, chunk); + return DST.ob_state; } - else if (chunk->command_used == chunk->command_len) { - chunk = BLI_memblock_alloc(DST.vmempool->commands); - chunk->command_len = ARRAY_SIZE(chunk->commands); - chunk->command_used = 0; - memset(chunk->command_type, 0x0, sizeof(chunk->command_type)); - BLI_LINKS_APPEND(&shgroup->cmd, chunk); - } - - command_type_set(chunk->command_type, chunk->command_used, type); - - return chunk->commands + chunk->command_used++; -} - -static void drw_command_draw(DRWShadingGroup *shgroup, GPUBatch *batch, DRWResourceHandle handle) -{ - DRWCommandDraw *cmd = drw_command_create(shgroup, DRW_CMD_DRAW); - cmd->batch = batch; - cmd->handle = handle; -} - -static void drw_command_draw_range(DRWShadingGroup *shgroup, - GPUBatch *batch, - uint start, - uint count) -{ - DRWCommandDrawRange *cmd = drw_command_create(shgroup, DRW_CMD_DRAW_RANGE); - cmd->batch = batch; - cmd->vert_first = start; - cmd->vert_count = count; -} - -static void drw_command_draw_instance(DRWShadingGroup *shgroup, - GPUBatch *batch, - DRWResourceHandle handle, - uint count) -{ - DRWCommandDrawInstance *cmd = drw_command_create(shgroup, DRW_CMD_DRAW_INSTANCE); - cmd->batch = batch; - cmd->handle = handle; - cmd->inst_count = count; -} - -static void drw_command_draw_procedural(DRWShadingGroup *shgroup, - GPUBatch *batch, - DRWResourceHandle handle, - uint vert_count) -{ - DRWCommandDrawProcedural *cmd = drw_command_create(shgroup, DRW_CMD_DRAW_PROCEDURAL); - cmd->batch = batch; - cmd->handle = handle; - cmd->vert_count = vert_count; -} - -static void drw_command_set_select_id(DRWShadingGroup *shgroup, GPUVertBuf *buf, uint select_id) -{ - /* Only one can be valid. */ - BLI_assert(buf == NULL || select_id == -1); - DRWCommandSetSelectID *cmd = drw_command_create(shgroup, DRW_CMD_SELECTID); - cmd->select_buf = buf; - cmd->select_id = select_id; -} - -static void drw_command_set_stencil_mask(DRWShadingGroup *shgroup, uint mask) -{ - BLI_assert(mask <= 0xFF); - DRWCommandSetStencil *cmd = drw_command_create(shgroup, DRW_CMD_STENCIL); - cmd->mask = mask; -} - -static void drw_command_clear(DRWShadingGroup *shgroup, - eGPUFrameBufferBits channels, - uchar r, - uchar g, - uchar b, - uchar a, - float depth, - uchar stencil) -{ - DRWCommandClear *cmd = drw_command_create(shgroup, DRW_CMD_CLEAR); - cmd->clear_channels = channels; - cmd->r = r; - cmd->g = g; - cmd->b = b; - cmd->a = a; - cmd->depth = depth; - cmd->stencil = stencil; -} - -static void drw_command_set_mutable_state(DRWShadingGroup *shgroup, - DRWState enable, - DRWState disable) -{ - /* TODO Restrict what state can be changed. */ - DRWCommandSetMutableState *cmd = drw_command_create(shgroup, DRW_CMD_DRWSTATE); - cmd->enable = enable; - cmd->disable = disable; } void DRW_shgroup_call_ex(DRWShadingGroup *shgroup, Object *ob, float (*obmat)[4], struct GPUBatch *geom, + uint v_sta, + uint v_ct, bool bypass_culling, void *user_data) { BLI_assert(geom != NULL); - if (G.f & G_FLAG_PICKSEL) { - drw_command_set_select_id(shgroup, NULL, DST.select_id); - } - DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : obmat, ob); - drw_command_draw(shgroup, geom, handle); - /* Culling data. */ - if (user_data || bypass_culling) { - DRWCullingState *culling = DRW_memblock_elem_from_handle(DST.vmempool->cullstates, - &DST.ob_handle); - - if (user_data) { - culling->user_data = user_data; - } + DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls); + BLI_LINKS_APPEND(&shgroup->calls, call); + + call->state = drw_call_state_object(shgroup, ob ? ob->obmat : obmat, ob); + call->batch = geom; + call->vert_first = v_sta; + call->vert_count = v_ct; /* 0 means auto from batch. */ + call->inst_count = 0; +#ifdef USE_GPU_SELECT + call->select_id = DST.select_id; + call->inst_selectid = NULL; +#endif + if (call->state->culling) { + call->state->culling->user_data = user_data; if (bypass_culling) { /* NOTE this will disable culling for the whole object. */ - culling->bsphere.radius = -1.0f; + call->state->culling->bsphere.radius = -1.0f; } } } -void DRW_shgroup_call_range(DRWShadingGroup *shgroup, struct GPUBatch *geom, uint v_sta, uint v_ct) -{ - BLI_assert(geom != NULL); - if (G.f & G_FLAG_PICKSEL) { - drw_command_set_select_id(shgroup, NULL, DST.select_id); - } - drw_command_draw_range(shgroup, geom, v_sta, v_ct); -} - static void drw_shgroup_call_procedural_add_ex(DRWShadingGroup *shgroup, GPUBatch *geom, Object *ob, uint vert_count) { - BLI_assert(vert_count > 0); - BLI_assert(geom != NULL); - if (G.f & G_FLAG_PICKSEL) { - drw_command_set_select_id(shgroup, NULL, DST.select_id); - } - DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : NULL, ob); - drw_command_draw_procedural(shgroup, geom, handle, vert_count); + + DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls); + BLI_LINKS_APPEND(&shgroup->calls, call); + + call->state = drw_call_state_object(shgroup, ob ? ob->obmat : NULL, ob); + call->batch = geom; + call->vert_first = 0; + call->vert_count = vert_count; + call->inst_count = 0; +#ifdef USE_GPU_SELECT + call->select_id = DST.select_id; + call->inst_selectid = NULL; +#endif } void DRW_shgroup_call_procedural_points(DRWShadingGroup *shgroup, Object *ob, uint point_len) @@ -778,18 +524,25 @@ void DRW_shgroup_call_procedural_triangles(DRWShadingGroup *shgroup, Object *ob, drw_shgroup_call_procedural_add_ex(shgroup, geom, ob, tria_count * 3); } -/* Should be removed */ void DRW_shgroup_call_instances(DRWShadingGroup *shgroup, Object *ob, struct GPUBatch *geom, uint count) { BLI_assert(geom != NULL); - if (G.f & G_FLAG_PICKSEL) { - drw_command_set_select_id(shgroup, NULL, DST.select_id); - } - DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : NULL, ob); - drw_command_draw_instance(shgroup, geom, handle, count); + + DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls); + BLI_LINKS_APPEND(&shgroup->calls, call); + + call->state = drw_call_state_object(shgroup, ob ? ob->obmat : NULL, ob); + call->batch = geom; + call->vert_first = 0; + call->vert_count = 0; /* Auto from batch. */ + call->inst_count = count; +#ifdef USE_GPU_SELECT + call->select_id = DST.select_id; + call->inst_selectid = NULL; +#endif } void DRW_shgroup_call_instances_with_attribs(DRWShadingGroup *shgroup, @@ -799,13 +552,21 @@ void DRW_shgroup_call_instances_with_attribs(DRWShadingGroup *shgroup, { BLI_assert(geom != NULL); BLI_assert(inst_attributes->verts[0] != NULL); - if (G.f & G_FLAG_PICKSEL) { - drw_command_set_select_id(shgroup, NULL, DST.select_id); - } - DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : NULL, ob); + GPUVertBuf *buf_inst = inst_attributes->verts[0]; - GPUBatch *batch = DRW_temp_batch_instance_request(DST.idatalist, buf_inst, geom); - drw_command_draw(shgroup, batch, handle); + + DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls); + BLI_LINKS_APPEND(&shgroup->calls, call); + + call->state = drw_call_state_object(shgroup, ob ? ob->obmat : NULL, ob); + call->batch = DRW_temp_batch_instance_request(DST.idatalist, buf_inst, geom); + call->vert_first = 0; + call->vert_count = 0; /* Auto from batch. */ + call->inst_count = buf_inst->vertex_len; +#ifdef USE_GPU_SELECT + call->select_id = DST.select_id; + call->inst_selectid = NULL; +#endif } // #define SCULPT_DEBUG_BUFFERS @@ -958,26 +719,27 @@ DRWCallBuffer *DRW_shgroup_call_buffer(DRWShadingGroup *shgroup, BLI_assert(ELEM(prim_type, GPU_PRIM_POINTS, GPU_PRIM_LINES, GPU_PRIM_TRI_FAN)); BLI_assert(format != NULL); - DRWCallBuffer *callbuf = BLI_memblock_alloc(DST.vmempool->callbuffers); - callbuf->buf = DRW_temp_buffer_request(DST.idatalist, format, &callbuf->count); - callbuf->buf_select = NULL; - callbuf->count = 0; + DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls); + BLI_LINKS_APPEND(&shgroup->calls, call); + call->state = drw_call_state_object(shgroup, NULL, NULL); + GPUVertBuf *buf = DRW_temp_buffer_request(DST.idatalist, format, &call->vert_count); + call->batch = DRW_temp_batch_request(DST.idatalist, buf, prim_type); + call->vert_first = 0; + call->vert_count = 0; + call->inst_count = 0; + +#ifdef USE_GPU_SELECT if (G.f & G_FLAG_PICKSEL) { /* Not actually used for rendering but alloced in one chunk. */ if (inst_select_format.attr_len == 0) { GPU_vertformat_attr_add(&inst_select_format, "selectId", GPU_COMP_I32, 1, GPU_FETCH_INT); } - callbuf->buf_select = DRW_temp_buffer_request( - DST.idatalist, &inst_select_format, &callbuf->count); - drw_command_set_select_id(shgroup, callbuf->buf_select, -1); + call->inst_selectid = DRW_temp_buffer_request( + DST.idatalist, &inst_select_format, &call->vert_count); } - - DRWResourceHandle handle = drw_resource_handle(shgroup, NULL, NULL); - GPUBatch *batch = DRW_temp_batch_request(DST.idatalist, callbuf->buf, prim_type); - drw_command_draw(shgroup, batch, handle); - - return callbuf; +#endif + return (DRWCallBuffer *)call; } DRWCallBuffer *DRW_shgroup_call_buffer_instance(DRWShadingGroup *shgroup, @@ -987,52 +749,56 @@ DRWCallBuffer *DRW_shgroup_call_buffer_instance(DRWShadingGroup *shgroup, BLI_assert(geom != NULL); BLI_assert(format != NULL); - DRWCallBuffer *callbuf = BLI_memblock_alloc(DST.vmempool->callbuffers); - callbuf->buf = DRW_temp_buffer_request(DST.idatalist, format, &callbuf->count); - callbuf->buf_select = NULL; - callbuf->count = 0; + DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls); + BLI_LINKS_APPEND(&shgroup->calls, call); + call->state = drw_call_state_object(shgroup, NULL, NULL); + GPUVertBuf *buf = DRW_temp_buffer_request(DST.idatalist, format, &call->inst_count); + call->batch = DRW_temp_batch_instance_request(DST.idatalist, buf, geom); + call->vert_first = 0; + call->vert_count = 0; /* Auto from batch. */ + call->inst_count = 0; + +#ifdef USE_GPU_SELECT if (G.f & G_FLAG_PICKSEL) { /* Not actually used for rendering but alloced in one chunk. */ if (inst_select_format.attr_len == 0) { GPU_vertformat_attr_add(&inst_select_format, "selectId", GPU_COMP_I32, 1, GPU_FETCH_INT); } - callbuf->buf_select = DRW_temp_buffer_request( - DST.idatalist, &inst_select_format, &callbuf->count); - drw_command_set_select_id(shgroup, callbuf->buf_select, -1); + call->inst_selectid = DRW_temp_buffer_request( + DST.idatalist, &inst_select_format, &call->inst_count); } - - DRWResourceHandle handle = drw_resource_handle(shgroup, NULL, NULL); - GPUBatch *batch = DRW_temp_batch_instance_request(DST.idatalist, callbuf->buf, geom); - drw_command_draw(shgroup, batch, handle); - - return callbuf; +#endif + return (DRWCallBuffer *)call; } void DRW_buffer_add_entry_array(DRWCallBuffer *callbuf, const void *attr[], uint attr_len) { - GPUVertBuf *buf = callbuf->buf; - const bool resize = (callbuf->count == buf->vertex_alloc); + DRWCall *call = (DRWCall *)callbuf; + const bool is_instance = call->batch->inst != NULL; + GPUVertBuf *buf = is_instance ? call->batch->inst : call->batch->verts[0]; + uint count = is_instance ? call->inst_count++ : call->vert_count++; + const bool resize = (count == buf->vertex_alloc); BLI_assert(attr_len == buf->format.attr_len); UNUSED_VARS_NDEBUG(attr_len); if (UNLIKELY(resize)) { - GPU_vertbuf_data_resize(buf, callbuf->count + DRW_BUFFER_VERTS_CHUNK); + GPU_vertbuf_data_resize(buf, count + DRW_BUFFER_VERTS_CHUNK); } for (int i = 0; i < attr_len; i++) { - GPU_vertbuf_attr_set(buf, i, callbuf->count, attr[i]); + GPU_vertbuf_attr_set(buf, i, count, attr[i]); } +#ifdef USE_GPU_SELECT if (G.f & G_FLAG_PICKSEL) { if (UNLIKELY(resize)) { - GPU_vertbuf_data_resize(callbuf->buf_select, callbuf->count + DRW_BUFFER_VERTS_CHUNK); + GPU_vertbuf_data_resize(call->inst_selectid, count + DRW_BUFFER_VERTS_CHUNK); } - GPU_vertbuf_attr_set(callbuf->buf_select, 0, callbuf->count, &DST.select_id); + GPU_vertbuf_attr_set(call->inst_selectid, 0, count, &DST.select_id); } - - callbuf->count++; +#endif } /** \} */ @@ -1045,54 +811,7 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader) { shgroup->uniforms = NULL; - /* TODO(fclem) make them builtin. */ int view_ubo_location = GPU_shader_get_uniform_block(shader, "viewBlock"); - int model_ubo_location = GPU_shader_get_uniform_block(shader, "modelBlock"); - int info_ubo_location = GPU_shader_get_uniform_block(shader, "infoBlock"); - int baseinst_location = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_BASE_INSTANCE); - int chunkid_location = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_RESOURCE_CHUNK); - - if (chunkid_location != -1) { - drw_shgroup_uniform_create_ex( - shgroup, chunkid_location, DRW_UNIFORM_RESOURCE_CHUNK, NULL, 0, 1); - } - - if (baseinst_location != -1) { - drw_shgroup_uniform_create_ex( - shgroup, baseinst_location, DRW_UNIFORM_BASE_INSTANCE, NULL, 0, 1); - } - - if (model_ubo_location != -1) { - drw_shgroup_uniform_create_ex( - shgroup, model_ubo_location, DRW_UNIFORM_BLOCK_OBMATS, NULL, 0, 1); - } - else { - int model = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODEL); - int modelinverse = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODEL_INV); - int modelviewprojection = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MVP); - if (model != -1) { - drw_shgroup_uniform_create_ex(shgroup, model, DRW_UNIFORM_MODEL_MATRIX, NULL, 0, 1); - } - if (modelinverse != -1) { - drw_shgroup_uniform_create_ex( - shgroup, modelinverse, DRW_UNIFORM_MODEL_MATRIX_INVERSE, NULL, 0, 1); - } - if (modelviewprojection != -1) { - drw_shgroup_uniform_create_ex( - shgroup, modelviewprojection, DRW_UNIFORM_MODELVIEWPROJECTION_MATRIX, NULL, 0, 1); - } - } - - if (info_ubo_location != -1) { - drw_shgroup_uniform_create_ex( - shgroup, info_ubo_location, DRW_UNIFORM_BLOCK_OBINFOS, NULL, 0, 1); - - /* Abusing this loc to tell shgroup we need the obinfos. */ - shgroup->objectinfo = 1; - } - else { - shgroup->objectinfo = 0; - } if (view_ubo_location != -1) { drw_shgroup_uniform_create_ex( @@ -1115,6 +834,31 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader) BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW_INV) == -1); BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW) == -1); BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_NORMAL) == -1); + + shgroup->model = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODEL); + shgroup->modelinverse = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODEL_INV); + shgroup->modelviewprojection = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MVP); + shgroup->orcotexfac = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_ORCO); + shgroup->objectinfo = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_OBJECT_INFO); + shgroup->objectcolor = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_OBJECT_COLOR); + shgroup->callid = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_CALLID); + + shgroup->matflag = 0; + if (shgroup->modelinverse > -1) { + shgroup->matflag |= DRW_CALL_MODELINVERSE; + } + if (shgroup->modelviewprojection > -1) { + shgroup->matflag |= DRW_CALL_MODELVIEWPROJECTION; + } + if (shgroup->orcotexfac > -1) { + shgroup->matflag |= DRW_CALL_ORCOTEXFAC; + } + if (shgroup->objectinfo > -1) { + shgroup->matflag |= DRW_CALL_OBJECTINFO; + } + if (shgroup->objectcolor > -1) { + shgroup->matflag |= DRW_CALL_OBJECTCOLOR; + } } static DRWShadingGroup *drw_shgroup_create_ex(struct GPUShader *shader, DRWPass *pass) @@ -1124,9 +868,13 @@ static DRWShadingGroup *drw_shgroup_create_ex(struct GPUShader *shader, DRWPass BLI_LINKS_APPEND(&pass->shgroups, shgroup); shgroup->shader = shader; - shgroup->cmd.first = NULL; - shgroup->cmd.last = NULL; - shgroup->pass_handle = pass->handle; + shgroup->state_extra = 0; + shgroup->state_extra_disable = ~0x0; + shgroup->stencil_mask = 0; + shgroup->calls.first = NULL; + shgroup->calls.last = NULL; + shgroup->tfeedback_target = NULL; + shgroup->pass_parent = pass; return shgroup; } @@ -1227,7 +975,7 @@ DRWShadingGroup *DRW_shgroup_transform_feedback_create(struct GPUShader *shader, BLI_assert(tf_target != NULL); DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass); drw_shgroup_init(shgroup, shader); - drw_shgroup_uniform_create_ex(shgroup, 0, DRW_UNIFORM_TFEEDBACK_TARGET, tf_target, 0, 1); + shgroup->tfeedback_target = tf_target; return shgroup; } @@ -1237,42 +985,37 @@ DRWShadingGroup *DRW_shgroup_transform_feedback_create(struct GPUShader *shader, */ void DRW_shgroup_state_enable(DRWShadingGroup *shgroup, DRWState state) { - drw_command_set_mutable_state(shgroup, state, 0x0); + shgroup->state_extra |= state; } void DRW_shgroup_state_disable(DRWShadingGroup *shgroup, DRWState state) { - drw_command_set_mutable_state(shgroup, 0x0, state); + shgroup->state_extra_disable &= ~state; } void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, uint mask) { - drw_command_set_stencil_mask(shgroup, mask); + BLI_assert(mask <= 255); + shgroup->stencil_mask = mask; } -void DRW_shgroup_clear_framebuffer(DRWShadingGroup *shgroup, - eGPUFrameBufferBits channels, - uchar r, - uchar g, - uchar b, - uchar a, - float depth, - uchar stencil) +bool DRW_shgroup_is_empty(DRWShadingGroup *shgroup) { - drw_command_clear(shgroup, channels, r, g, b, a, depth, stencil); + return shgroup->calls.first == NULL; } -bool DRW_shgroup_is_empty(DRWShadingGroup *shgroup) +/* This is a workaround function waiting for the clearing operation to be available inside the + * shgroups. */ +DRWShadingGroup *DRW_shgroup_get_next(DRWShadingGroup *shgroup) { - DRWCommandChunk *chunk = shgroup->cmd.first; - for (; chunk; chunk = chunk->next) { - for (int i = 0; i < chunk->command_used; i++) { - if (command_type_get(chunk->command_type, i) <= DRW_MAX_DRAW_CMD_TYPE) { - return false; - } - } - } - return true; + return shgroup->next; +} + +/* This is a workaround function waiting for the clearing operation to be available inside the + * shgroups. */ +uint DRW_shgroup_stencil_mask_get(DRWShadingGroup *shgroup) +{ + return shgroup->stencil_mask; } DRWShadingGroup *DRW_shgroup_create_sub(DRWShadingGroup *shgroup) @@ -1280,14 +1023,11 @@ DRWShadingGroup *DRW_shgroup_create_sub(DRWShadingGroup *shgroup) DRWShadingGroup *shgroup_new = BLI_memblock_alloc(DST.vmempool->shgroups); *shgroup_new = *shgroup; - drw_shgroup_init(shgroup_new, shgroup_new->shader); - shgroup_new->cmd.first = NULL; - shgroup_new->cmd.last = NULL; + shgroup_new->uniforms = NULL; + shgroup_new->calls.first = NULL; + shgroup_new->calls.last = NULL; - DRWPass *parent_pass = DRW_memblock_elem_from_handle(DST.vmempool->passes, - &shgroup->pass_handle); - - BLI_LINKS_INSERT_AFTER(&parent_pass->shgroups, shgroup, shgroup_new); + BLI_LINKS_INSERT_AFTER(&shgroup->pass_parent->shgroups, shgroup, shgroup_new); return shgroup_new; } @@ -1782,8 +1522,6 @@ DRWPass *DRW_pass_create(const char *name, DRWState state) pass->shgroups.first = NULL; pass->shgroups.last = NULL; - pass->handle = DST.pass_handle; - DRW_handle_increment(&DST.pass_handle); return pass; } @@ -1827,22 +1565,42 @@ typedef struct ZSortData { const float *origin; } ZSortData; -static int pass_shgroup_dist_sort(const void *a, const void *b) +static int pass_shgroup_dist_sort(void *thunk, const void *a, const void *b) { + const ZSortData *zsortdata = (ZSortData *)thunk; const DRWShadingGroup *shgrp_a = (const DRWShadingGroup *)a; const DRWShadingGroup *shgrp_b = (const DRWShadingGroup *)b; - if (shgrp_a->z_sorting.distance < shgrp_b->z_sorting.distance) { + const DRWCall *call_a = (DRWCall *)shgrp_a->calls.first; + const DRWCall *call_b = (DRWCall *)shgrp_b->calls.first; + + if (call_a == NULL) { + return -1; + } + if (call_b == NULL) { + return -1; + } + + float tmp[3]; + sub_v3_v3v3(tmp, zsortdata->origin, call_a->state->model[3]); + const float a_sq = dot_v3v3(zsortdata->axis, tmp); + sub_v3_v3v3(tmp, zsortdata->origin, call_b->state->model[3]); + const float b_sq = dot_v3v3(zsortdata->axis, tmp); + + if (a_sq < b_sq) { return 1; } - else if (shgrp_a->z_sorting.distance > shgrp_b->z_sorting.distance) { + else if (a_sq > b_sq) { return -1; } else { - /* If distances are the same, keep original order. */ - if (shgrp_a->z_sorting.original_index > shgrp_b->z_sorting.original_index) { + /* If there is a depth prepass put it before */ + if ((shgrp_a->state_extra & DRW_STATE_WRITE_DEPTH) != 0) { return -1; } + else if ((shgrp_b->state_extra & DRW_STATE_WRITE_DEPTH) != 0) { + return 1; + } else { return 0; } @@ -1853,61 +1611,35 @@ static int pass_shgroup_dist_sort(const void *a, const void *b) #define SORT_IMPL_LINKTYPE DRWShadingGroup +#define SORT_IMPL_USE_THUNK #define SORT_IMPL_FUNC shgroup_sort_fn_r #include "../../blenlib/intern/list_sort_impl.h" #undef SORT_IMPL_FUNC +#undef SORT_IMPL_USE_THUNK #undef SORT_IMPL_LINKTYPE /** * Sort Shading groups by decreasing Z of their first draw call. - * This is useful for order dependent effect such as alpha-blending. + * This is useful for order dependent effect such as transparency. */ void DRW_pass_sort_shgroup_z(DRWPass *pass) { const float(*viewinv)[4] = DST.view_active->storage.viewinv; - if (!(pass->shgroups.first && pass->shgroups.first->next)) { - /* Nothing to sort */ - return; - } + ZSortData zsortdata = {viewinv[2], viewinv[3]}; - uint index = 0; - DRWShadingGroup *shgroup = pass->shgroups.first; - do { - DRWResourceHandle handle = 0; - /* Find first DRWCommandDraw. */ - DRWCommandChunk *cmd_chunk = shgroup->cmd.first; - for (; cmd_chunk && handle == 0; cmd_chunk = cmd_chunk->next) { - for (int i = 0; i < cmd_chunk->command_used && handle == 0; i++) { - if (DRW_CMD_DRAW == command_type_get(cmd_chunk->command_type, i)) { - handle = cmd_chunk->commands[i].draw.handle; - } - } - } - /* To be sorted a shgroup needs to have at least one draw command. */ - BLI_assert(handle != 0); - - DRWObjectMatrix *obmats = DRW_memblock_elem_from_handle(DST.vmempool->obmats, &handle); - - /* Compute distance to camera. */ - float tmp[3]; - sub_v3_v3v3(tmp, viewinv[3], obmats->model[3]); - shgroup->z_sorting.distance = dot_v3v3(viewinv[2], tmp); - shgroup->z_sorting.original_index = index++; + if (pass->shgroups.first && pass->shgroups.first->next) { + pass->shgroups.first = shgroup_sort_fn_r( + pass->shgroups.first, pass_shgroup_dist_sort, &zsortdata); - } while ((shgroup = shgroup->next)); - - /* Sort using computed distances. */ - pass->shgroups.first = shgroup_sort_fn_r(pass->shgroups.first, pass_shgroup_dist_sort); - - /* Find the new last */ - DRWShadingGroup *last = pass->shgroups.first; - while ((last = last->next)) { - /* Reset the pass id for debugging. */ - last->pass_handle = pass->handle; + /* Find the next last */ + DRWShadingGroup *last = pass->shgroups.first; + while ((last = last->next)) { + /* Do nothing */ + } + pass->shgroups.last = last; } - pass->shgroups.last = last; } /** \} */ diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index 6bb11a7d4ce..1dcaf39fc19 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -36,41 +36,16 @@ # include "GPU_select.h" #endif +#ifdef USE_GPU_SELECT void DRW_select_load_id(uint id) { -#ifdef USE_GPU_SELECT BLI_assert(G.f & G_FLAG_PICKSEL); DST.select_id = id; -#endif } +#endif #define DEBUG_UBO_BINDING -typedef struct DRWCommandsState { - GPUBatch *batch; - int resource_chunk; - int base_inst; - int inst_count; - int v_first; - int v_count; - bool neg_scale; - /* Resource location. */ - int obmats_loc; - int obinfos_loc; - int baseinst_loc; - int chunkid_loc; - /* Legacy matrix support. */ - int obmat_loc; - int obinv_loc; - int mvp_loc; - /* Selection ID state. */ - GPUVertBuf *select_buf; - uint select_id; - /* Drawing State */ - DRWState drw_state_enabled; - DRWState drw_state_disabled; -} DRWCommandsState; - /* -------------------------------------------------------------------- */ /** \name Draw State (DRW_state) * \{ */ @@ -432,10 +407,9 @@ void DRW_state_reset(void) /** \name Culling (DRW_culling) * \{ */ -static bool draw_call_is_culled(const DRWResourceHandle *handle, DRWView *view) +static bool draw_call_is_culled(DRWCall *call, DRWView *view) { - DRWCullingState *culling = DRW_memblock_elem_from_handle(DST.vmempool->cullstates, handle); - return (culling->mask & view->culling_mask) != 0; + return (call->state->culling->mask & view->culling_mask) != 0; } /* Set active view for rendering. */ @@ -614,96 +588,66 @@ static void draw_compute_culling(DRWView *view) /** \name Draw (DRW_draw) * \{ */ -BLI_INLINE void draw_legacy_matrix_update(DRWShadingGroup *shgroup, - DRWResourceHandle *handle, - float obmat_loc, - float obinv_loc, - float mvp_loc) +static void draw_geometry_prepare(DRWShadingGroup *shgroup, DRWCall *call) { - /* Still supported for compatibility with gpu_shader_* but should be forbidden. */ - DRWObjectMatrix *ob_mats = DRW_memblock_elem_from_handle(DST.vmempool->obmats, handle); - if (obmat_loc != -1) { - GPU_shader_uniform_vector(shgroup->shader, obmat_loc, 16, 1, (float *)ob_mats->model); + BLI_assert(call); + DRWCallState *state = call->state; + + if (shgroup->model != -1) { + GPU_shader_uniform_vector(shgroup->shader, shgroup->model, 16, 1, (float *)state->model); + } + if (shgroup->modelinverse != -1) { + GPU_shader_uniform_vector( + shgroup->shader, shgroup->modelinverse, 16, 1, (float *)state->modelinverse); + } + if (shgroup->objectinfo != -1) { + float infos[4]; + infos[0] = state->ob_index; + // infos[1]; /* UNUSED. */ + infos[2] = state->ob_random; + infos[3] = (state->flag & DRW_CALL_NEGSCALE) ? -1.0f : 1.0f; + GPU_shader_uniform_vector(shgroup->shader, shgroup->objectinfo, 4, 1, (float *)infos); + } + if (shgroup->objectcolor != -1) { + GPU_shader_uniform_vector( + shgroup->shader, shgroup->objectcolor, 4, 1, (float *)state->ob_color); } - if (obinv_loc != -1) { - GPU_shader_uniform_vector(shgroup->shader, obinv_loc, 16, 1, (float *)ob_mats->modelinverse); + if (shgroup->orcotexfac != -1) { + GPU_shader_uniform_vector( + shgroup->shader, shgroup->orcotexfac, 3, 2, (float *)state->orcotexfac); } /* Still supported for compatibility with gpu_shader_* but should be forbidden * and is slow (since it does not cache the result). */ - if (mvp_loc != -1) { + if (shgroup->modelviewprojection != -1) { float mvp[4][4]; - mul_m4_m4m4(mvp, DST.view_active->storage.persmat, ob_mats->model); - GPU_shader_uniform_vector(shgroup->shader, mvp_loc, 16, 1, (float *)mvp); + mul_m4_m4m4(mvp, DST.view_active->storage.persmat, state->model); + GPU_shader_uniform_vector(shgroup->shader, shgroup->modelviewprojection, 16, 1, (float *)mvp); } } -BLI_INLINE void draw_geometry_bind(DRWShadingGroup *shgroup, GPUBatch *geom) -{ - /* XXX hacking #GPUBatch. we don't want to call glUseProgram! (huge performance loss) */ - if (DST.batch) { - DST.batch->program_in_use = false; - } - - DST.batch = geom; - - GPU_batch_program_set_no_use( - geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader)); - - geom->program_in_use = true; /* XXX hacking #GPUBatch */ - - GPU_batch_bind(geom); -} - BLI_INLINE void draw_geometry_execute(DRWShadingGroup *shgroup, GPUBatch *geom, - int vert_first, - int vert_count, - int inst_first, - int inst_count, - int baseinst_loc) + uint vert_first, + uint vert_count, + uint inst_first, + uint inst_count) { - /* inst_count can be -1. */ - inst_count = max_ii(0, inst_count); - - if (baseinst_loc != -1) { - /* Fallback when ARB_shader_draw_parameters is not supported. */ - GPU_shader_uniform_vector_int(shgroup->shader, baseinst_loc, 1, 1, (int *)&inst_first); - /* Avoids VAO reconfiguration on older hardware. (see GPU_batch_draw_advanced) */ - inst_first = 0; - } - /* bind vertex array */ if (DST.batch != geom) { - draw_geometry_bind(shgroup, geom); + DST.batch = geom; + + GPU_batch_program_set_no_use( + geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader)); + + GPU_batch_bind(geom); } + /* XXX hacking #GPUBatch. we don't want to call glUseProgram! (huge performance loss) */ + geom->program_in_use = true; + GPU_batch_draw_advanced(geom, vert_first, vert_count, inst_first, inst_count); -} -BLI_INLINE void draw_indirect_call(DRWShadingGroup *shgroup, DRWCommandsState *state) -{ - if (state->inst_count == 0) { - return; - } - if (state->baseinst_loc == -1) { - /* bind vertex array */ - if (DST.batch != state->batch) { - GPU_draw_list_submit(DST.draw_list); - draw_geometry_bind(shgroup, state->batch); - } - GPU_draw_list_command_add( - DST.draw_list, state->v_first, state->v_count, state->base_inst, state->inst_count); - } - /* Fallback when unsupported */ - else { - draw_geometry_execute(shgroup, - state->batch, - state->v_first, - state->v_count, - state->base_inst, - state->inst_count, - state->baseinst_loc); - } + geom->program_in_use = false; /* XXX hacking #GPUBatch */ } enum { @@ -775,9 +719,6 @@ static void bind_ubo(GPUUniformBuffer *ubo, char bind_type) /* UBO isn't bound yet. Find an empty slot and bind it. */ idx = get_empty_slot_index(DST.RST.bound_ubo_slots); - /* [0..1] are reserved ubo slots. */ - idx += 2; - if (idx < GPU_max_ubo_binds()) { GPUUniformBuffer **gpu_ubo_slot = &DST.RST.bound_ubos[idx]; /* Unbind any previous UBO. */ @@ -797,13 +738,10 @@ static void bind_ubo(GPUUniformBuffer *ubo, char bind_type) } } else { - BLI_assert(idx < 64); /* This UBO slot was released but the UBO is * still bound here. Just flag the slot again. */ BLI_assert(DST.RST.bound_ubos[idx] == ubo); } - /* Remove offset for flag bitfield. */ - idx -= 2; set_bound_flags(&DST.RST.bound_ubo_slots, &DST.RST.bound_ubo_slots_persist, idx, bind_type); } @@ -847,12 +785,8 @@ static bool ubo_bindings_validate(DRWShadingGroup *shgroup) printf("Trying to draw with missing UBO binding.\n"); valid = false; } - - DRWPass *parent_pass = DRW_memblock_elem_from_handle(DST.vmempool->passes, - &shgroup->pass_handle); - printf("Pass : %s, Shader : %s, Block : %s\n", - parent_pass->name, + shgroup->pass_parent->name, shgroup->shader->name, blockname); } @@ -884,330 +818,119 @@ static void release_ubo_slots(bool with_persist) } } -static void draw_update_uniforms(DRWShadingGroup *shgroup, - DRWCommandsState *state, - bool *use_tfeedback) +static void draw_update_uniforms(DRWShadingGroup *shgroup) { - for (DRWUniformChunk *unichunk = shgroup->uniforms; unichunk; unichunk = unichunk->next) { - DRWUniform *uni = unichunk->uniforms; - for (int i = 0; i < unichunk->uniform_used; i++, uni++) { - GPUTexture *tex; - GPUUniformBuffer *ubo; - if (uni->location == -2) { - uni->location = GPU_shader_get_uniform_ensure(shgroup->shader, - DST.uniform_names.buffer + uni->name_ofs); - if (uni->location == -1) { - continue; - } - } - const void *data = uni->pvalue; - if (ELEM(uni->type, DRW_UNIFORM_INT_COPY, DRW_UNIFORM_FLOAT_COPY)) { - data = uni->fvalue; - } - switch (uni->type) { - case DRW_UNIFORM_INT_COPY: - case DRW_UNIFORM_INT: - GPU_shader_uniform_vector_int( - shgroup->shader, uni->location, uni->length, uni->arraysize, data); - break; - case DRW_UNIFORM_FLOAT_COPY: - case DRW_UNIFORM_FLOAT: - GPU_shader_uniform_vector( - shgroup->shader, uni->location, uni->length, uni->arraysize, data); - break; - case DRW_UNIFORM_TEXTURE: - tex = (GPUTexture *)uni->pvalue; - BLI_assert(tex); - bind_texture(tex, BIND_TEMP); - GPU_shader_uniform_texture(shgroup->shader, uni->location, tex); - break; - case DRW_UNIFORM_TEXTURE_PERSIST: - tex = (GPUTexture *)uni->pvalue; - BLI_assert(tex); - bind_texture(tex, BIND_PERSIST); - GPU_shader_uniform_texture(shgroup->shader, uni->location, tex); - break; - case DRW_UNIFORM_TEXTURE_REF: - tex = *((GPUTexture **)uni->pvalue); - BLI_assert(tex); - bind_texture(tex, BIND_TEMP); - GPU_shader_uniform_texture(shgroup->shader, uni->location, tex); - break; - case DRW_UNIFORM_BLOCK: - ubo = (GPUUniformBuffer *)uni->pvalue; - bind_ubo(ubo, BIND_TEMP); - GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo); - break; - case DRW_UNIFORM_BLOCK_PERSIST: - ubo = (GPUUniformBuffer *)uni->pvalue; - bind_ubo(ubo, BIND_PERSIST); - GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo); - break; - case DRW_UNIFORM_BLOCK_OBMATS: - state->obmats_loc = uni->location; - ubo = DST.vmempool->matrices_ubo[0]; - GPU_uniformbuffer_bind(ubo, 0); - GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo); - break; - case DRW_UNIFORM_BLOCK_OBINFOS: - state->obinfos_loc = uni->location; - ubo = DST.vmempool->obinfos_ubo[0]; - GPU_uniformbuffer_bind(ubo, 1); - GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo); - break; - case DRW_UNIFORM_RESOURCE_CHUNK: - state->chunkid_loc = uni->location; - GPU_shader_uniform_int(shgroup->shader, uni->location, 0); - break; - case DRW_UNIFORM_TFEEDBACK_TARGET: - BLI_assert(data && (*use_tfeedback == false)); - *use_tfeedback = GPU_shader_transform_feedback_enable(shgroup->shader, - ((GPUVertBuf *)data)->vbo_id); - break; - /* Legacy/Fallback support. */ - case DRW_UNIFORM_BASE_INSTANCE: - state->baseinst_loc = uni->location; - break; - case DRW_UNIFORM_MODEL_MATRIX: - state->obmat_loc = uni->location; - break; - case DRW_UNIFORM_MODEL_MATRIX_INVERSE: - state->obinv_loc = uni->location; - break; - case DRW_UNIFORM_MODELVIEWPROJECTION_MATRIX: - state->mvp_loc = uni->location; - break; + for (DRWUniform *uni = shgroup->uniforms; uni; uni = uni->next) { + GPUTexture *tex; + GPUUniformBuffer *ubo; + if (uni->location == -2) { + uni->location = GPU_shader_get_uniform_ensure(shgroup->shader, + DST.uniform_names.buffer + uni->name_ofs); + if (uni->location == -1) { + continue; } } - } - - BLI_assert(ubo_bindings_validate(shgroup)); -} - -BLI_INLINE void draw_select_buffer(DRWShadingGroup *shgroup, - DRWCommandsState *state, - GPUBatch *batch, - const DRWResourceHandle *handle) -{ - const bool is_instancing = (batch->inst != NULL); - int start = 0; - int count = 1; - int tot = is_instancing ? batch->inst->vertex_len : batch->verts[0]->vertex_len; - /* Hack : get "vbo" data without actually drawing. */ - int *select_id = (void *)state->select_buf->data; - - /* Batching */ - if (!is_instancing) { - /* FIXME: Meh a bit nasty. */ - if (batch->gl_prim_type == convert_prim_type_to_gl(GPU_PRIM_TRIS)) { - count = 3; - } - else if (batch->gl_prim_type == convert_prim_type_to_gl(GPU_PRIM_LINES)) { - count = 2; - } - } - - while (start < tot) { - GPU_select_load_id(select_id[start]); - if (is_instancing) { - draw_geometry_execute(shgroup, batch, 0, 0, start, count, state->baseinst_loc); + const void *data = uni->pvalue; + if (ELEM(uni->type, DRW_UNIFORM_INT_COPY, DRW_UNIFORM_FLOAT_COPY)) { + data = uni->fvalue; } - else { - draw_geometry_execute( - shgroup, batch, start, count, DRW_handle_id_get(handle), 0, state->baseinst_loc); + switch (uni->type) { + case DRW_UNIFORM_INT_COPY: + case DRW_UNIFORM_INT: + GPU_shader_uniform_vector_int( + shgroup->shader, uni->location, uni->length, uni->arraysize, data); + break; + case DRW_UNIFORM_FLOAT_COPY: + case DRW_UNIFORM_FLOAT: + GPU_shader_uniform_vector( + shgroup->shader, uni->location, uni->length, uni->arraysize, data); + break; + case DRW_UNIFORM_TEXTURE: + tex = (GPUTexture *)uni->pvalue; + BLI_assert(tex); + bind_texture(tex, BIND_TEMP); + GPU_shader_uniform_texture(shgroup->shader, uni->location, tex); + break; + case DRW_UNIFORM_TEXTURE_PERSIST: + tex = (GPUTexture *)uni->pvalue; + BLI_assert(tex); + bind_texture(tex, BIND_PERSIST); + GPU_shader_uniform_texture(shgroup->shader, uni->location, tex); + break; + case DRW_UNIFORM_TEXTURE_REF: + tex = *((GPUTexture **)uni->pvalue); + BLI_assert(tex); + bind_texture(tex, BIND_TEMP); + GPU_shader_uniform_texture(shgroup->shader, uni->location, tex); + break; + case DRW_UNIFORM_BLOCK: + ubo = (GPUUniformBuffer *)uni->pvalue; + bind_ubo(ubo, BIND_TEMP); + GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo); + break; + case DRW_UNIFORM_BLOCK_PERSIST: + ubo = (GPUUniformBuffer *)uni->pvalue; + bind_ubo(ubo, BIND_PERSIST); + GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo); + break; } - start += count; } -} - -typedef struct DRWCommandIterator { - int cmd_index; - DRWCommandChunk *curr_chunk; -} DRWCommandIterator; -static void draw_command_iter_begin(DRWCommandIterator *iter, DRWShadingGroup *shgroup) -{ - iter->curr_chunk = shgroup->cmd.first; - iter->cmd_index = 0; -} - -static DRWCommand *draw_command_iter_step(DRWCommandIterator *iter, eDRWCommandType *cmd_type) -{ - if (iter->curr_chunk) { - if (iter->cmd_index == iter->curr_chunk->command_len) { - iter->curr_chunk = iter->curr_chunk->next; - iter->cmd_index = 0; - } - if (iter->curr_chunk) { - *cmd_type = command_type_get(iter->curr_chunk->command_type, iter->cmd_index); - if (iter->cmd_index < iter->curr_chunk->command_used) { - return iter->curr_chunk->commands + iter->cmd_index++; - } - } - } - return NULL; + BLI_assert(ubo_bindings_validate(shgroup)); } -static void draw_call_resource_bind(DRWCommandsState *state, const DRWResourceHandle *handle) +BLI_INLINE bool draw_select_do_call(DRWShadingGroup *shgroup, DRWCall *call) { - /* Front face is not a resource but it is inside the resource handle. */ - bool neg_scale = DRW_handle_negative_scale_get(handle); - if (neg_scale != state->neg_scale) { - glFrontFace((neg_scale) ? GL_CW : GL_CCW); - state->neg_scale = neg_scale; +#ifdef USE_GPU_SELECT + if ((G.f & G_FLAG_PICKSEL) == 0) { + return false; } - - int chunk = DRW_handle_chunk_get(handle); - if (state->resource_chunk != chunk) { - if (state->chunkid_loc != -1) { - GPU_shader_uniform_int(NULL, state->chunkid_loc, chunk); - } - if (state->obmats_loc != -1) { - GPU_uniformbuffer_unbind(DST.vmempool->matrices_ubo[state->resource_chunk]); - GPU_uniformbuffer_bind(DST.vmempool->matrices_ubo[chunk], 0); - } - if (state->obinfos_loc != -1) { - GPU_uniformbuffer_unbind(DST.vmempool->obinfos_ubo[state->resource_chunk]); - GPU_uniformbuffer_bind(DST.vmempool->obinfos_ubo[chunk], 1); + if (call->inst_selectid != NULL) { + const bool is_instancing = (call->inst_count != 0); + uint start = 0; + uint count = 1; + uint tot = is_instancing ? call->inst_count : call->vert_count; + /* Hack : get vbo data without actually drawing. */ + GPUVertBufRaw raw; + GPU_vertbuf_attr_get_raw_data(call->inst_selectid, 0, &raw); + int *select_id = GPU_vertbuf_raw_step(&raw); + + /* Batching */ + if (!is_instancing) { + /* FIXME: Meh a bit nasty. */ + if (call->batch->gl_prim_type == convert_prim_type_to_gl(GPU_PRIM_TRIS)) { + count = 3; + } + else if (call->batch->gl_prim_type == convert_prim_type_to_gl(GPU_PRIM_LINES)) { + count = 2; + } } - state->resource_chunk = chunk; - } -} - -static void draw_call_batching_flush(DRWShadingGroup *shgroup, DRWCommandsState *state) -{ - draw_indirect_call(shgroup, state); - GPU_draw_list_submit(DST.draw_list); - - state->batch = NULL; - state->inst_count = 0; - state->base_inst = -1; -} - -static void draw_call_single_do(DRWShadingGroup *shgroup, - DRWCommandsState *state, - GPUBatch *batch, - DRWResourceHandle handle, - int vert_first, - int vert_count, - int inst_count) -{ - draw_call_batching_flush(shgroup, state); - - draw_call_resource_bind(state, &handle); - /* TODO This is Legacy. Need to be removed. */ - if (state->obmats_loc == -1 && - (state->obmat_loc != -1 || state->obinv_loc != -1 || state->mvp_loc != -1)) { - draw_legacy_matrix_update( - shgroup, &handle, state->obmat_loc, state->obinv_loc, state->mvp_loc); - } - - if (G.f & G_FLAG_PICKSEL) { - if (state->select_buf != NULL) { - draw_select_buffer(shgroup, state, batch, &handle); - return; - } - else { - GPU_select_load_id(state->select_id); + while (start < tot) { + GPU_select_load_id(select_id[start]); + if (is_instancing) { + draw_geometry_execute(shgroup, call->batch, 0, 0, start, count); + } + else { + draw_geometry_execute(shgroup, call->batch, start, count, 0, 0); + } + start += count; } + return true; } - - draw_geometry_execute(shgroup, - batch, - vert_first, - vert_count, - DRW_handle_id_get(&handle), - inst_count, - state->baseinst_loc); -} - -static void draw_call_batching_start(DRWCommandsState *state) -{ - state->neg_scale = false; - state->resource_chunk = 0; - state->base_inst = 0; - state->inst_count = 0; - state->v_first = 0; - state->v_count = 0; - state->batch = NULL; - - state->select_id = -1; - state->select_buf = NULL; -} - -static void draw_call_batching_do(DRWShadingGroup *shgroup, - DRWCommandsState *state, - DRWCommandDraw *call) -{ - /* If any condition requires to interupt the merging. */ - bool neg_scale = DRW_handle_negative_scale_get(&call->handle); - int chunk = DRW_handle_chunk_get(&call->handle); - int id = DRW_handle_id_get(&call->handle); - if ((state->neg_scale != neg_scale) || /* Need to change state. */ - (state->resource_chunk != chunk) || /* Need to change UBOs. */ - (state->batch != call->batch) /* Need to change VAO. */ - ) { - draw_call_batching_flush(shgroup, state); - - state->batch = call->batch; - state->v_first = (call->batch->elem) ? call->batch->elem->index_start : 0; - state->v_count = (call->batch->elem) ? call->batch->elem->index_len : - call->batch->verts[0]->vertex_len; - state->inst_count = 1; - state->base_inst = id; - - draw_call_resource_bind(state, &call->handle); - - GPU_draw_list_init(DST.draw_list, state->batch); - } - /* Is the id consecutive? */ - else if (id != state->base_inst + state->inst_count) { - /* We need to add a draw command for the pending instances. */ - draw_indirect_call(shgroup, state); - state->inst_count = 1; - state->base_inst = id; - } - /* We avoid a drawcall by merging with the precedent - * drawcall using instancing. */ else { - state->inst_count++; - } -} - -/* Flush remaining pending drawcalls. */ -static void draw_call_batching_finish(DRWShadingGroup *shgroup, DRWCommandsState *state) -{ - draw_call_batching_flush(shgroup, state); - - /* Reset state */ - if (state->neg_scale) { - glFrontFace(GL_CCW); - } - if (state->obmats_loc != -1) { - GPU_uniformbuffer_unbind(DST.vmempool->matrices_ubo[state->resource_chunk]); - } - if (state->obinfos_loc != -1) { - GPU_uniformbuffer_unbind(DST.vmempool->obinfos_ubo[state->resource_chunk]); + GPU_select_load_id(call->select_id); + return false; } +#else + return false; +#endif } static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) { BLI_assert(shgroup->shader); - DRWCommandsState state = { - .obmats_loc = -1, - .obinfos_loc = -1, - .baseinst_loc = -1, - .chunkid_loc = -1, - .obmat_loc = -1, - .obinv_loc = -1, - .mvp_loc = -1, - .drw_state_enabled = 0, - .drw_state_disabled = 0, - }; - const bool shader_changed = (DST.shader != shgroup->shader); bool use_tfeedback = false; @@ -1217,115 +940,56 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) } GPU_shader_bind(shgroup->shader); DST.shader = shgroup->shader; - /* XXX hacking gawain */ - if (DST.batch) { - DST.batch->program_in_use = false; - } DST.batch = NULL; } + if (shgroup->tfeedback_target != NULL) { + use_tfeedback = GPU_shader_transform_feedback_enable(shgroup->shader, + shgroup->tfeedback_target->vbo_id); + } + release_ubo_slots(shader_changed); release_texture_slots(shader_changed); - draw_update_uniforms(shgroup, &state, &use_tfeedback); + drw_state_set((pass_state & shgroup->state_extra_disable) | shgroup->state_extra); + drw_stencil_set(shgroup->stencil_mask); - drw_state_set(pass_state); + draw_update_uniforms(shgroup); /* Rendering Calls */ { - DRWCommandIterator iter; - DRWCommand *cmd; - eDRWCommandType cmd_type; - - draw_command_iter_begin(&iter, shgroup); - - draw_call_batching_start(&state); - - while ((cmd = draw_command_iter_step(&iter, &cmd_type))) { - - switch (cmd_type) { - case DRW_CMD_DRWSTATE: - case DRW_CMD_STENCIL: - draw_call_batching_flush(shgroup, &state); - break; - case DRW_CMD_DRAW: - case DRW_CMD_DRAW_PROCEDURAL: - case DRW_CMD_DRAW_INSTANCE: - if (draw_call_is_culled(&cmd->instance.handle, DST.view_active)) { - continue; - } - break; - default: - break; + bool prev_neg_scale = false; + int callid = 0; + for (DRWCall *call = shgroup->calls.first; call; call = call->next) { + + if (draw_call_is_culled(call, DST.view_active)) { + continue; } - switch (cmd_type) { - case DRW_CMD_CLEAR: - GPU_framebuffer_clear( -#ifndef NDEBUG - GPU_framebuffer_active_get(), -#else - NULL, -#endif - cmd->clear.clear_channels, - (float[4]){cmd->clear.r / 255.0f, - cmd->clear.g / 255.0f, - cmd->clear.b / 255.0f, - cmd->clear.a / 255.0f}, - cmd->clear.depth, - cmd->clear.stencil); - break; - case DRW_CMD_DRWSTATE: - state.drw_state_enabled |= cmd->state.enable; - state.drw_state_disabled |= cmd->state.disable; - drw_state_set((pass_state & ~state.drw_state_disabled) | state.drw_state_enabled); - break; - case DRW_CMD_STENCIL: - drw_stencil_set(cmd->stencil.mask); - break; - case DRW_CMD_SELECTID: - state.select_id = cmd->select_id.select_id; - state.select_buf = cmd->select_id.select_buf; - break; - case DRW_CMD_DRAW: - if (!USE_BATCHING || state.obmats_loc == -1 || (G.f & G_FLAG_PICKSEL)) { - draw_call_single_do(shgroup, &state, cmd->draw.batch, cmd->draw.handle, 0, 0, 0); - } - else { - draw_call_batching_do(shgroup, &state, &cmd->draw); - } - break; - case DRW_CMD_DRAW_PROCEDURAL: - draw_call_single_do(shgroup, - &state, - cmd->procedural.batch, - cmd->procedural.handle, - 0, - cmd->procedural.vert_count, - 1); - break; - case DRW_CMD_DRAW_INSTANCE: - draw_call_single_do(shgroup, - &state, - cmd->instance.batch, - cmd->instance.handle, - 0, - 0, - cmd->instance.inst_count); - break; - case DRW_CMD_DRAW_RANGE: - draw_call_single_do(shgroup, - &state, - cmd->range.batch, - (DRWResourceHandle)0, - cmd->range.vert_first, - cmd->range.vert_count, - 1); - break; + /* XXX small exception/optimisation for outline rendering. */ + if (shgroup->callid != -1) { + GPU_shader_uniform_vector_int(shgroup->shader, shgroup->callid, 1, 1, &callid); + callid += 1; } - } - draw_call_batching_finish(shgroup, &state); + /* Negative scale objects */ + bool neg_scale = call->state->flag & DRW_CALL_NEGSCALE; + if (neg_scale != prev_neg_scale) { + glFrontFace((neg_scale) ? GL_CW : GL_CCW); + prev_neg_scale = neg_scale; + } + + draw_geometry_prepare(shgroup, call); + + if (draw_select_do_call(shgroup, call)) { + continue; + } + + draw_geometry_execute( + shgroup, call->batch, call->vert_first, call->vert_count, 0, call->inst_count); + } + /* Reset state */ + glFrontFace(GL_CCW); } if (use_tfeedback) { @@ -1401,11 +1065,6 @@ static void drw_draw_pass_ex(DRWPass *pass, DST.shader = NULL; } - if (DST.batch) { - DST.batch->program_in_use = false; - DST.batch = NULL; - } - /* HACK: Rasterized discard can affect clear commands which are not * part of a DRWPass (as of now). So disable rasterized discard here * if it has been enabled. */ diff --git a/source/blender/draw/modes/edit_curve_mode.c b/source/blender/draw/modes/edit_curve_mode.c index 8933767bda8..e68e03c2438 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, "#define IN_PLACE_INSTANCES\n", NULL}, + .defs = (const char *[]){sh_cfg_data->def, NULL}, }); } diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c index 5c529892206..2b87e04b6b4 100644 --- a/source/blender/draw/modes/object_mode.c +++ b/source/blender/draw/modes/object_mode.c @@ -286,10 +286,15 @@ typedef struct OBJECT_PrivateData { DRWShadingGroup *outlines_transform; /* Lightprobes */ - DRWShadingGroup *probe_outlines_transform; - DRWShadingGroup *probe_outlines_select; - DRWShadingGroup *probe_outlines_select_dupli; - DRWShadingGroup *probe_outlines_active; + 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; /* Objects Centers */ DRWCallBuffer *center_active; @@ -298,6 +303,17 @@ 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 */ @@ -401,10 +417,7 @@ 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_common_view_lib_glsl, - datatoc_object_outline_prepass_vert_glsl, - NULL}, + .vert = (const char *[]){sh_cfg_data->lib, datatoc_gpu_shader_3D_vert_glsl, NULL}, .frag = (const char *[]){datatoc_object_outline_prepass_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg_data->def, NULL}, }); @@ -418,7 +431,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, "#define USE_GEOM\n", NULL}, + .defs = (const char *[]){sh_cfg_data->def, NULL}, }); sh_data->outline_resolve = DRW_shader_create_fullscreen( @@ -526,11 +539,10 @@ 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_object_outline_prepass_frag_glsl, NULL}, + .frag = (const char *[]){datatoc_gpu_shader_flat_id_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg_data->def, NULL}, }); @@ -685,12 +697,12 @@ static void OBJECT_engine_free(void) } static DRWShadingGroup *shgroup_outline(DRWPass *pass, - int outline_id, + const int *ofs, GPUShader *sh, eGPUShaderConfig sh_cfg) { DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); - DRW_shgroup_uniform_int_copy(grp, "outlineId", outline_id); + DRW_shgroup_uniform_int(grp, "baseId", ofs, 1); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); @@ -729,89 +741,128 @@ static DRWShadingGroup *shgroup_points(DRWPass *pass, return grp; } -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_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->outlines_select_dupli; + return &stl->g_data->id_ofs_prb_select_dupli; case TH_TRANSFORM: - return stl->g_data->outlines_transform; default: - return NULL; + return &stl->g_data->id_ofs_prb_transform; } } switch (theme_id) { case TH_ACTIVE: - return stl->g_data->outlines_active; + return &stl->g_data->id_ofs_prb_active; case TH_SELECT: - return stl->g_data->outlines_select; + return &stl->g_data->id_ofs_prb_select; case TH_TRANSFORM: - return stl->g_data->outlines_transform; default: - return NULL; + return &stl->g_data->id_ofs_prb_transform; } } -static DRWShadingGroup *shgroup_theme_id_to_probe_outline_or_null(OBJECT_StorageList *stl, - int theme_id, - const int base_flag) +static int *shgroup_theme_id_to_outline_counter(OBJECT_StorageList *stl, + int theme_id, + const int base_flag) { - 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->id_ofs_select_dupli; + case TH_TRANSFORM: + default: + return &stl->g_data->id_ofs_transform; + } + } + + 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; + case TH_SELECT: + return stl->g_data->lightprobes_planar_select; + case TH_TRANSFORM: + default: + return stl->g_data->lightprobes_planar_transform; } +} +static DRWCallBuffer *buffer_theme_id_to_probe_cube_outline_shgrp(OBJECT_StorageList *stl, + int theme_id, + const int base_flag) +{ + /* does not increment counter */ if (UNLIKELY(base_flag & BASE_FROM_DUPLI)) { switch (theme_id) { case TH_ACTIVE: case TH_SELECT: - return stl->g_data->probe_outlines_select_dupli; + return stl->g_data->lightprobes_cube_select_dupli; case TH_TRANSFORM: - return stl->g_data->probe_outlines_transform; default: - return NULL; + return stl->g_data->lightprobes_cube_transform; } } switch (theme_id) { case TH_ACTIVE: - return stl->g_data->probe_outlines_active; + return stl->g_data->lightprobes_cube_active; case TH_SELECT: - return stl->g_data->probe_outlines_select; + return stl->g_data->lightprobes_cube_select; case TH_TRANSFORM: - return stl->g_data->probe_outlines_transform; default: - return NULL; + return stl->g_data->lightprobes_cube_transform; } } -static int shgroup_theme_id_to_outline_id(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) { + 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 2; + return stl->g_data->outlines_select_dupli; case TH_TRANSFORM: - return 0; + return stl->g_data->outlines_transform; default: - return -1; + return NULL; } } switch (theme_id) { case TH_ACTIVE: - return 3; + return stl->g_data->outlines_active; case TH_SELECT: - return 1; + return stl->g_data->outlines_select; case TH_TRANSFORM: - return 0; + return stl->g_data->outlines_transform; default: - return -1; + return NULL; } } @@ -1295,8 +1346,7 @@ 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(); - eGPUShaderConfig cfg = draw_ctx->sh_cfg; - OBJECT_Shaders *sh_data = &e_data.sh_data[cfg]; + OBJECT_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; const float outline_width = UI_GetThemeValuef(TH_OUTLINE_WIDTH); const bool do_outline_expand = (U.pixelsize > 1.0) || (outline_width > 2.0f); @@ -1317,25 +1367,59 @@ static void OBJECT_cache_init(void *vedata) { DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; - psl->lightprobes = DRW_pass_create("Outlines Probe Pass", state); + psl->outlines = DRW_pass_create("Outlines Depth 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_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); + 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; } { @@ -1354,6 +1438,7 @@ 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. */ @@ -2681,6 +2766,15 @@ 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, @@ -2697,10 +2791,13 @@ 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); @@ -2710,40 +2807,65 @@ static void DRW_shgroup_lightprobe(OBJECT_Shaders *sh_data, mul_v3_v3fl(half_cell_dim, cell_dim, 0.5f); /* First cell. */ - copy_v3_fl(corner, -1.0f); - add_v3_v3(corner, half_cell_dim); - mul_m4_v3(ob->obmat, corner); + 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); /* Opposite neighbor cell. */ - 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]); + 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); - 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_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); + 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); 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_PLANAR && (prb->flag & LIGHTPROBE_FLAG_SHOW_DATA)) { - DRWShadingGroup *grp = shgroup_theme_id_to_probe_outline_or_null( + 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( stl, theme_id, ob->base_flag); - DRW_shgroup_call_no_cull(grp, DRW_cache_quad_get(), ob); + /* 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; } } @@ -3660,7 +3782,19 @@ static void OBJECT_draw_scene(void *vedata) DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - int do_outlines = !DRW_pass_is_empty(psl->outlines) || !DRW_pass_is_empty(psl->lightprobes); + 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; float clearcol[4] = {0.0f, 0.0f, 0.0f, 0.0f}; @@ -3668,24 +3802,35 @@ 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(g_data->sgl.transp_shapes); + DRW_draw_pass(stl->g_data->sgl.transp_shapes); MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl); - 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(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(psl->particle); - DRW_draw_pass(g_data->sgl.bone_axes); + DRW_draw_pass(stl->g_data->sgl.bone_axes); MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl); - DRW_draw_pass(g_data->sgl.image_empties); + DRW_draw_pass(stl->g_data->sgl.image_empties); - if (DRW_state_is_fbo() && do_outlines) { + if (DRW_state_is_fbo() && outline_calls > 0) { 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); @@ -3720,7 +3865,7 @@ static void OBJECT_draw_scene(void *vedata) } /* Combine with scene buffer last */ - if (do_outlines) { + if (outline_calls > 0) { 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 2433f4c1df5..a5b1133abf4 100644 --- a/source/blender/draw/modes/overlay_mode.c +++ b/source/blender/draw/modes/overlay_mode.c @@ -23,6 +23,8 @@ #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" @@ -75,6 +77,7 @@ 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; @@ -205,6 +208,10 @@ 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); + } } { @@ -249,6 +256,7 @@ 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, @@ -297,10 +305,8 @@ 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)) { - /* 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; + *wire_col = BLI_mempool_alloc(pd->wire_color_mempool); + *rim_col = BLI_mempool_alloc(pd->wire_color_mempool); if (v3d->shading.wire_color_type == V3D_SHADING_OBJECT_COLOR) { linearrgb_to_srgb_v3_v3(*wire_col, ob->color); @@ -421,9 +427,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, 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); + 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); DRW_shgroup_stencil_mask(shgrp, (is_xray && (is_wire || !pd->clear_stencil)) ? 0x00 : 0xFF); } @@ -500,6 +506,12 @@ 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 a554db7d4a4..20a54947db7 100644 --- a/source/blender/draw/modes/shaders/common_view_lib.glsl +++ b/source/blender/draw/modes/shaders/common_view_lib.glsl @@ -1,5 +1,4 @@ #define COMMON_VIEW_LIB -#define DRW_RESOURCE_CHUNK_LEN 512 /* keep in sync with DRWManager.view_data */ layout(std140) uniform viewBlock @@ -24,74 +23,8 @@ 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 144024a7d5d..d27d55c3fd6 100644 --- a/source/blender/draw/modes/shaders/object_lightprobe_grid_vert.glsl +++ b/source/blender/draw/modes/shaders/object_lightprobe_grid_vert.glsl @@ -1,11 +1,18 @@ +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 int objectId; +flat out uint finalId; void main() { @@ -22,8 +29,7 @@ void main() gl_Position = ViewProjectionMatrix * vec4(ws_cell_location, 1.0); gl_PointSize = 2.0f; - /* ID 0 is nothing (background) */ - objectId = resource_handle + 1; + finalId = uint(baseId + call_id); #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 7b86d477a39..7668a0c2c94 100644 --- a/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl +++ b/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl @@ -7,9 +7,30 @@ 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); @@ -64,24 +85,7 @@ void main() const float epsilon = 3.0 / 8388608.0; bool occluded = (ref_depth > scene_depth + epsilon); - /* 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 = convert_id_to_color(int(ref_id)); 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 5d6c4881b5b..c3447456ea6 100644 --- a/source/blender/draw/modes/shaders/object_outline_prepass_frag.glsl +++ b/source/blender/draw/modes/shaders/object_outline_prepass_frag.glsl @@ -1,18 +1,10 @@ - -/* Should be 2 bits only [0..3]. */ -uniform int outlineId; - -flat in int objectId; +uniform int callId; +uniform int baseId; /* 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(outlineId) << 14u) | ((uint(objectId) << SHIFT) >> SHIFT); + outId = uint(baseId + callId); } 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 b32913dcd60..5a3eb38fb6b 100644 --- a/source/blender/draw/modes/shaders/object_outline_prepass_geom.glsl +++ b/source/blender/draw/modes/shaders/object_outline_prepass_geom.glsl @@ -2,15 +2,12 @@ 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 = gl_in[v].gl_Position; - objectId = objectId_g[v]; + gl_Position = pPos[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 7740f9a4af2..e34afe95b5e 100644 --- a/source/blender/draw/modes/shaders/object_outline_prepass_vert.glsl +++ b/source/blender/draw/modes/shaders/object_outline_prepass_vert.glsl @@ -1,27 +1,16 @@ in vec3 pos; -#ifdef USE_GEOM +out vec4 pPos; 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); -#endif - gl_Position = point_world_to_ndc(world_pos); + pPos = point_world_to_ndc(world_pos); /* Small bias to always be on top of the geom. */ - gl_Position.z -= 1e-3; - - /* ID 0 is nothing (background) */ - objectId = resource_handle + 1; + pPos.z -= 1e-3; #ifdef USE_WORLD_CLIP_PLANES world_clip_planes_calc_clip_distance(world_pos); diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c index ec740447f93..370cc6a2a6d 100644 --- a/source/blender/editors/mesh/editmesh_intersect.c +++ b/source/blender/editors/mesh/editmesh_intersect.c @@ -101,19 +101,17 @@ static int bm_face_isect_pair_swap(BMFace *f, void *UNUSED(user_data)) /** * Use for intersect and boolean. */ -static void edbm_intersect_select(BMEditMesh *em, bool do_select) +static void edbm_intersect_select(BMEditMesh *em) { - if (do_select) { - BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false); + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false); - if (em->bm->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) { - BMIter iter; - BMEdge *e; + if (em->bm->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) { + BMIter iter; + BMEdge *e; - BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e, BM_ELEM_TAG)) { - BM_edge_select_set(em->bm, e, true); - } + BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_TAG)) { + BM_edge_select_set(em->bm, e, true); } } } @@ -212,9 +210,10 @@ static int edbm_intersect_exec(bContext *C, wmOperator *op) em->bm, BM_elem_cb_check_hflag_enabled_simple(const BMFace *, BM_ELEM_SELECT)); } - edbm_intersect_select(em, has_isect); - - if (!has_isect) { + if (has_isect) { + edbm_intersect_select(em); + } + else { isect_len++; } } @@ -318,9 +317,10 @@ static int edbm_intersect_boolean_exec(bContext *C, wmOperator *op) boolean_operation, eps); - edbm_intersect_select(em, has_isect); - - if (!has_isect) { + if (has_isect) { + edbm_intersect_select(em); + } + else { isect_len++; } } diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index bc08da4b2cb..8d2355ff5ac 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -330,8 +330,6 @@ data_to_c_simple(shaders/gpu_shader_gpencil_fill_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_cfg_world_clip_lib.glsl SRC) -data_to_c_simple(shaders/gpu_shader_common_obinfos_lib.glsl SRC) - if(WITH_MOD_SMOKE) add_definitions(-DWITH_SMOKE) diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h index 7d8c3347eb4..175033f70d9 100644 --- a/source/blender/gpu/GPU_batch.h +++ b/source/blender/gpu/GPU_batch.h @@ -193,17 +193,6 @@ GPUBatch *create_BatchInGeneral(GPUPrimType, VertexBufferStuff, ElementListStuff #endif /* future plans */ -/* GPUDrawList is an API to do lots of similar drawcalls very fast using multidrawindirect. - * There is a fallback if the feature is not supported. */ -typedef struct GPUDrawList GPUDrawList; - -GPUDrawList *GPU_draw_list_create(int length); -void GPU_draw_list_discard(GPUDrawList *list); -void GPU_draw_list_init(GPUDrawList *list, GPUBatch *batch); -void GPU_draw_list_command_add( - GPUDrawList *list, int v_first, int v_count, int i_first, int i_count); -void GPU_draw_list_submit(GPUDrawList *list); - void gpu_batch_init(void); void gpu_batch_exit(void); diff --git a/source/blender/gpu/GPU_shader_interface.h b/source/blender/gpu/GPU_shader_interface.h index e336aa53d24..ec97e1b085e 100644 --- a/source/blender/gpu/GPU_shader_interface.h +++ b/source/blender/gpu/GPU_shader_interface.h @@ -45,12 +45,13 @@ typedef enum { GPU_UNIFORM_VIEWPROJECTION_INV, /* mat4 ViewProjectionMatrixInverse */ GPU_UNIFORM_NORMAL, /* mat3 NormalMatrix */ - GPU_UNIFORM_ORCO, /* vec4 OrcoTexCoFactors[] */ + GPU_UNIFORM_ORCO, /* vec3 OrcoTexCoFactors[] */ GPU_UNIFORM_CLIPPLANES, /* vec4 WorldClipPlanes[] */ - GPU_UNIFORM_COLOR, /* vec4 color */ - GPU_UNIFORM_BASE_INSTANCE, /* int baseInstance */ - GPU_UNIFORM_RESOURCE_CHUNK, /* int resourceChunk */ + GPU_UNIFORM_COLOR, /* vec4 color */ + GPU_UNIFORM_CALLID, /* int callId */ + GPU_UNIFORM_OBJECT_INFO, /* vec3 objectInfo */ + GPU_UNIFORM_OBJECT_COLOR, /* vec4 objectColor */ GPU_UNIFORM_CUSTOM, /* custom uniform, not one of the above built-ins */ diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h index 4bbcb6a4335..e7600279d6f 100644 --- a/source/blender/gpu/GPU_viewport.h +++ b/source/blender/gpu/GPU_viewport.h @@ -37,20 +37,14 @@ typedef struct GPUViewport GPUViewport; /* Contains memory pools information */ typedef struct ViewportMemoryPool { - struct BLI_memblock *commands; - struct BLI_memblock *commands_small; - struct BLI_memblock *callbuffers; - struct BLI_memblock *obmats; - struct BLI_memblock *obinfos; + struct BLI_memblock *calls; + struct BLI_memblock *states; struct BLI_memblock *cullstates; struct BLI_memblock *shgroups; struct BLI_memblock *uniforms; struct BLI_memblock *views; struct BLI_memblock *passes; struct BLI_memblock *images; - struct GPUUniformBuffer **matrices_ubo; - struct GPUUniformBuffer **obinfos_ubo; - uint ubo_len; } ViewportMemoryPool; /* All FramebufferLists are just the same pointers with different names */ diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c index 697bf37f34d..e0c0aea576c 100644 --- a/source/blender/gpu/intern/gpu_batch.c +++ b/source/blender/gpu/intern/gpu_batch.c @@ -39,9 +39,8 @@ #include <stdlib.h> #include <string.h> -#include <limits.h> -static void batch_update_program_bindings(GPUBatch *batch, uint i_first); +static void batch_update_program_bindings(GPUBatch *batch, uint v_first); void GPU_batch_vao_cache_clear(GPUBatch *batch) { @@ -447,51 +446,20 @@ static void create_bindings(GPUVertBuf *verts, } } -static void instance_id_workaround(GPUBatch *batch) -{ - /** - * A driver bug make it so that when using an attribute with GL_INT_2_10_10_10_REV as format, - * the gl_InstanceID is incremented by the 2 bit component of the attrib. To workaround this, - * we create a new vertex attrib containing the expected value of gl_InstanceID. - **/ - const GPUShaderInput *input = GPU_shaderinterface_attr(batch->interface, "_instanceId"); - if (input) { -#define DRW_RESOURCE_CHUNK_LEN 512 /* Keep in sync. */ - static GLint vbo_id = 0; - if (vbo_id == 0) { - short data[DRW_RESOURCE_CHUNK_LEN]; - for (int i = 0; i < DRW_RESOURCE_CHUNK_LEN; i++) { - data[i] = i; - } - /* GPU_context takes care of deleting `vbo_id` at the end. */ - vbo_id = GPU_buf_alloc(); - glBindBuffer(GL_ARRAY_BUFFER, vbo_id); - glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW); - } - glBindBuffer(GL_ARRAY_BUFFER, vbo_id); - glEnableVertexAttribArray(input->location); - glVertexAttribIPointer(input->location, 1, GL_SHORT, 0, NULL); - glVertexAttribDivisor(input->location, 1); - } -} - -static void batch_update_program_bindings(GPUBatch *batch, uint i_first) +static void batch_update_program_bindings(GPUBatch *batch, uint v_first) { /* Reverse order so first vbos have more prevalence (in term of attrib override). */ for (int v = GPU_BATCH_VBO_MAX_LEN - 1; v > -1; v--) { if (batch->verts[v] != NULL) { - create_bindings(batch->verts[v], batch->interface, 0, false); + create_bindings(batch->verts[v], batch->interface, (batch->inst) ? 0 : v_first, false); } } if (batch->inst) { - create_bindings(batch->inst, batch->interface, i_first, true); + create_bindings(batch->inst, batch->interface, v_first, true); } if (batch->elem) { GPU_indexbuf_use(batch->elem); } - if (GPU_crappy_amd_driver()) { - instance_id_workaround(batch); - } } void GPU_batch_program_use_begin(GPUBatch *batch) @@ -650,14 +618,6 @@ void GPU_batch_draw(GPUBatch *batch) GPU_batch_program_use_end(batch); } -#if GPU_TRACK_INDEX_RANGE -# define BASE_INDEX(el) ((el)->base_index) -# define INDEX_TYPE(el) ((el)->gl_index_type) -#else -# define BASE_INDEX(el) 0 -# define INDEX_TYPE(el) GL_UNSIGNED_INT -#endif - void GPU_batch_draw_advanced(GPUBatch *batch, int v_first, int v_count, int i_first, int i_count) { #if TRUST_NO_ONE @@ -672,13 +632,8 @@ void GPU_batch_draw_advanced(GPUBatch *batch, int v_first, int v_count, int i_fi i_count = (batch->inst) ? batch->inst->vertex_len : 1; } - if (v_count == 0 || i_count == 0) { - /* Nothing to draw. */ - return; - } - if (!GPU_arb_base_instance_is_supported()) { - if (i_first > 0) { + if (i_first > 0 && i_count > 0) { /* If using offset drawing with instancing, we must * use the default VAO and redo bindings. */ glBindVertexArray(GPU_vao_default()); @@ -693,8 +648,13 @@ void GPU_batch_draw_advanced(GPUBatch *batch, int v_first, int v_count, int i_fi if (batch->elem) { const GPUIndexBuf *el = batch->elem; - GLenum index_type = INDEX_TYPE(el); - GLint base_index = BASE_INDEX(el); +#if GPU_TRACK_INDEX_RANGE + GLenum index_type = el->gl_index_type; + GLint base_index = el->base_index; +#else + GLenum index_type = GL_UNSIGNED_INT; + GLint base_index = 0; +#endif void *v_first_ofs = elem_offset(el, v_first); if (GPU_arb_base_instance_is_supported()) { @@ -737,179 +697,6 @@ void GPU_draw_primitive(GPUPrimType prim_type, int v_count) } /* -------------------------------------------------------------------- */ -/** \name Indirect Draw Calls - * \{ */ - -#if 0 -# define USE_MULTI_DRAW_INDIRECT 0 -#else -# define USE_MULTI_DRAW_INDIRECT \ - (GL_ARB_multi_draw_indirect && GPU_arb_base_instance_is_supported()) -#endif - -typedef struct GPUDrawCommand { - uint v_count; - uint i_count; - uint v_first; - uint i_first; -} GPUDrawCommand; - -typedef struct GPUDrawCommandIndexed { - uint v_count; - uint i_count; - uint v_first; - uint base_index; - uint i_first; -} GPUDrawCommandIndexed; - -struct GPUDrawList { - GPUBatch *batch; - uint base_index; /* Avoid dereferencing batch. */ - uint cmd_offset; /* in bytes, offset inside indirect command buffer. */ - uint cmd_len; /* Number of used command for the next call. */ - uint buffer_size; /* in bytes, size of indirect command buffer. */ - GLuint buffer_id; /* Draw Indirect Buffer id */ - union { - GPUDrawCommand *commands; - GPUDrawCommandIndexed *commands_indexed; - }; -}; - -GPUDrawList *GPU_draw_list_create(int length) -{ - GPUDrawList *list = MEM_callocN(sizeof(GPUDrawList), "GPUDrawList"); - /* Alloc the biggest possible command list which is indexed. */ - list->buffer_size = sizeof(GPUDrawCommandIndexed) * length; - if (USE_MULTI_DRAW_INDIRECT) { - list->buffer_id = GPU_buf_alloc(); - glBindBuffer(GL_DRAW_INDIRECT_BUFFER, list->buffer_id); - glBufferData(GL_DRAW_INDIRECT_BUFFER, list->buffer_size, NULL, GL_DYNAMIC_DRAW); - } - else { - list->commands = MEM_mallocN(list->buffer_size, "GPUDrawList data"); - } - return list; -} - -void GPU_draw_list_discard(GPUDrawList *list) -{ - if (list->buffer_id) { - GPU_buf_free(list->buffer_id); - } - else { - MEM_SAFE_FREE(list->commands); - } - MEM_freeN(list); -} - -void GPU_draw_list_init(GPUDrawList *list, GPUBatch *batch) -{ - BLI_assert(batch->phase == GPU_BATCH_READY_TO_DRAW); - list->batch = batch; - list->base_index = batch->elem ? BASE_INDEX(batch->elem) : UINT_MAX; - list->cmd_len = 0; - - if (USE_MULTI_DRAW_INDIRECT) { - if (list->commands == NULL) { - glBindBuffer(GL_DRAW_INDIRECT_BUFFER, list->buffer_id); - if (list->cmd_offset >= list->buffer_size) { - /* Orphan buffer data and start fresh. */ - glBufferData(GL_DRAW_INDIRECT_BUFFER, list->buffer_size, NULL, GL_DYNAMIC_DRAW); - list->cmd_offset = 0; - } - GLenum flags = GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_FLUSH_EXPLICIT_BIT; - list->commands = glMapBufferRange( - GL_DRAW_INDIRECT_BUFFER, list->cmd_offset, list->buffer_size - list->cmd_offset, flags); - } - } - else { - list->cmd_offset = 0; - } -} - -void GPU_draw_list_command_add( - GPUDrawList *list, int v_first, int v_count, int i_first, int i_count) -{ - BLI_assert(list->commands); - - if (list->base_index != UINT_MAX) { - GPUDrawCommandIndexed *cmd = list->commands_indexed + list->cmd_len; - cmd->v_first = v_first; - cmd->v_count = v_count; - cmd->i_count = i_count; - cmd->base_index = list->base_index; - cmd->i_first = i_first; - } - else { - GPUDrawCommand *cmd = list->commands + list->cmd_len; - cmd->v_first = v_first; - cmd->v_count = v_count; - cmd->i_count = i_count; - cmd->i_first = i_first; - } - - list->cmd_len++; - uint offset = list->cmd_offset + list->cmd_len * sizeof(GPUDrawCommandIndexed); - - if (offset == list->buffer_size) { - GPU_draw_list_submit(list); - GPU_draw_list_init(list, list->batch); - } -} - -void GPU_draw_list_submit(GPUDrawList *list) -{ - GPUBatch *batch = list->batch; - - if (list->cmd_len == 0) - return; - - BLI_assert(list->commands); - BLI_assert(batch->program_in_use); - /* TODO could assert that VAO is bound. */ - - /* TODO We loose a bit of memory here if we only draw arrays. Fix that. */ - uintptr_t offset = list->cmd_offset; - uint cmd_len = list->cmd_len; - size_t bytes_used = cmd_len * sizeof(GPUDrawCommandIndexed); - list->cmd_offset += bytes_used; - list->cmd_len = 0; /* Avoid reuse. */ - - if (USE_MULTI_DRAW_INDIRECT) { - GLenum prim = batch->gl_prim_type; - - glBindBuffer(GL_DRAW_INDIRECT_BUFFER, list->buffer_id); - glFlushMappedBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, bytes_used); - glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER); - list->commands = NULL; /* Unmapped */ - - if (batch->elem) { - glMultiDrawElementsIndirect(prim, INDEX_TYPE(batch->elem), (void *)offset, cmd_len, 0); - } - else { - glMultiDrawArraysIndirect(prim, (void *)offset, cmd_len, 0); - } - } - else { - /* Fallback */ - if (batch->elem) { - GPUDrawCommandIndexed *cmd = list->commands_indexed; - for (int i = 0; i < cmd_len; i++, cmd++) { - GPU_batch_draw_advanced(batch, cmd->v_first, cmd->v_count, cmd->i_first, cmd->i_count); - } - } - else { - GPUDrawCommand *cmd = list->commands; - for (int i = 0; i < cmd_len; i++, cmd++) { - GPU_batch_draw_advanced(batch, cmd->v_first, cmd->v_count, cmd->i_first, cmd->i_count); - } - } - } -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Utilities * \{ */ diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 410e23c9576..7483be74e01 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -55,12 +55,6 @@ #include <string.h> #include <stdarg.h> -extern char datatoc_gpu_shader_material_glsl[]; -extern char datatoc_gpu_shader_geometry_glsl[]; - -extern char datatoc_gpu_shader_common_obinfos_lib_glsl[]; -extern char datatoc_common_view_lib_glsl[]; - /* -------------------- GPUPass Cache ------------------ */ /** * Internal shader cache: This prevent the shader recompilation / stall when @@ -784,12 +778,6 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final else if (input->builtin == GPU_OBJECT_MATRIX) { BLI_dynstr_append(ds, "objmat"); } - else if (input->builtin == GPU_OBJECT_INFO) { - BLI_dynstr_append(ds, "ObjectInfo"); - } - else if (input->builtin == GPU_OBJECT_COLOR) { - BLI_dynstr_append(ds, "ObjectColor"); - } else if (input->builtin == GPU_INVERSE_OBJECT_MATRIX) { BLI_dynstr_append(ds, "objinv"); } @@ -852,10 +840,6 @@ static char *code_generate_fragment(GPUMaterial *material, codegen_set_unique_ids(nodes); *rbuiltins = builtins = codegen_process_uniforms_functions(material, ds, nodes); - if (builtins & (GPU_OBJECT_INFO | GPU_OBJECT_COLOR)) { - BLI_dynstr_append(ds, datatoc_gpu_shader_common_obinfos_lib_glsl); - } - if (builtins & GPU_BARYCENTRIC_TEXCO) { BLI_dynstr_append(ds, "in vec2 barycentricTexCo;\n"); } @@ -1004,7 +988,7 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u /* NOTE : Replicate changes to mesh_render_data_create() in draw_cache_impl_mesh.c */ if (input->attr_type == CD_ORCO) { /* OPTI : orco is computed from local positions, but only if no modifier is present. */ - BLI_dynstr_append(ds, datatoc_gpu_shader_common_obinfos_lib_glsl); + BLI_dynstr_append(ds, "uniform vec3 OrcoTexCoFactors[2];\n"); BLI_dynstr_append(ds, "DEFINE_ATTR(vec4, orco);\n"); } else if (input->attr_name[0] == '\0') { @@ -1086,8 +1070,6 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u BLI_dynstr_append(ds, "\n"); - BLI_dynstr_append(ds, use_geom ? "RESOURCE_ID_VARYING_GEOM\n" : "RESOURCE_ID_VARYING\n"); - BLI_dynstr_append(ds, "#define USE_ATTR\n" "vec3 srgb_to_linear_attr(vec3 c) {\n" @@ -1117,8 +1099,6 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u BLI_dynstr_append(ds, "void pass_attr(in vec3 position) {\n"); - BLI_dynstr_append(ds, use_geom ? "\tPASS_RESOURCE_ID_GEOM\n" : "\tPASS_RESOURCE_ID\n"); - BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n"); if (builtins & GPU_BARYCENTRIC_TEXCO) { @@ -1145,8 +1125,8 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u } else if (input->attr_type == CD_ORCO) { BLI_dynstr_appendf(ds, - "\tvar%d%s = OrcoTexCoFactors[0].xyz + (ModelMatrixInverse * " - "vec4(hair_get_strand_pos(), 1.0)).xyz * OrcoTexCoFactors[1].xyz;\n", + "\tvar%d%s = OrcoTexCoFactors[0] + (ModelMatrixInverse * " + "vec4(hair_get_strand_pos(), 1.0)).xyz * OrcoTexCoFactors[1];\n", input->attr_id, use_geom ? "g" : ""); /* TODO: fix ORCO with modifiers. */ @@ -1201,8 +1181,7 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u } else if (input->attr_type == CD_ORCO) { BLI_dynstr_appendf(ds, - "\tvar%d%s = OrcoTexCoFactors[0].xyz + position *" - " OrcoTexCoFactors[1].xyz;\n", + "\tvar%d%s = OrcoTexCoFactors[0] + position * OrcoTexCoFactors[1];\n", input->attr_id, use_geom ? "g" : ""); /* See mesh_create_loop_orco() for explanation. */ @@ -1317,8 +1296,6 @@ static char *code_generate_geometry(ListBase *nodes, const char *geom_code, cons BLI_dynstr_append(ds, "out vec3 worldNormal;\n"); BLI_dynstr_append(ds, "out vec3 viewNormal;\n"); - BLI_dynstr_append(ds, datatoc_common_view_lib_glsl); - BLI_dynstr_append(ds, "void main(){\n"); if (builtins & GPU_BARYCENTRIC_DIST) { @@ -1363,13 +1340,9 @@ static char *code_generate_geometry(ListBase *nodes, const char *geom_code, cons BLI_dynstr_append(ds, "}\n"); } - BLI_dynstr_append(ds, "RESOURCE_ID_VARYING\n"); - /* Generate varying assignments. */ BLI_dynstr_append(ds, "void pass_attr(in int vert) {\n"); - BLI_dynstr_append(ds, "\tPASS_RESOURCE_ID(vert)\n"); - /* XXX HACK: Eevee specific. */ if (geom_code == NULL) { BLI_dynstr_append(ds, "\tworldPosition = worldPositiong[vert];\n"); diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c index 7e8cb8a4fa0..42c21626c05 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -248,9 +248,6 @@ static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH]) /* a #version 400 feature, but we use #version 330 maximum so use extension */ strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n"); } - if (GLEW_ARB_shader_draw_parameters) { - strcat(defines, "#extension GL_ARB_shader_draw_parameters : enable\n"); - } } static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH]) @@ -258,9 +255,6 @@ static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH]) /* some useful defines to detect GPU type */ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) { strcat(defines, "#define GPU_ATI\n"); - if (GPU_crappy_amd_driver()) { - strcat(defines, "#define GPU_CRAPPY_AMD_DRIVER\n"); - } } else if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY)) { strcat(defines, "#define GPU_NVIDIA\n"); diff --git a/source/blender/gpu/intern/gpu_shader_interface.c b/source/blender/gpu/intern/gpu_shader_interface.c index 983c5dfc27a..083c5bf2b60 100644 --- a/source/blender/gpu/intern/gpu_shader_interface.c +++ b/source/blender/gpu/intern/gpu_shader_interface.c @@ -65,8 +65,9 @@ static const char *BuiltinUniform_name(GPUUniformBuiltin u) [GPU_UNIFORM_CLIPPLANES] = "WorldClipPlanes", [GPU_UNIFORM_COLOR] = "color", - [GPU_UNIFORM_BASE_INSTANCE] = "baseInstance", - [GPU_UNIFORM_RESOURCE_CHUNK] = "resourceChunk", + [GPU_UNIFORM_CALLID] = "callId", + [GPU_UNIFORM_OBJECT_INFO] = "unfobjectinfo", + [GPU_UNIFORM_OBJECT_COLOR] = "unfobjectcolor", [GPU_UNIFORM_CUSTOM] = NULL, [GPU_NUM_UNIFORMS] = NULL, diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index 615af57c1bd..fcb1a008226 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -39,7 +39,6 @@ #include "GPU_immediate.h" #include "GPU_texture.h" #include "GPU_viewport.h" -#include "GPU_uniformbuffer.h" #include "DRW_engine.h" @@ -620,20 +619,11 @@ void GPU_viewport_free(GPUViewport *viewport) MEM_freeN(viewport->fbl); MEM_freeN(viewport->txl); - if (viewport->vmempool.commands != NULL) { - BLI_memblock_destroy(viewport->vmempool.commands, NULL); + if (viewport->vmempool.calls != NULL) { + BLI_memblock_destroy(viewport->vmempool.calls, NULL); } - if (viewport->vmempool.commands_small != NULL) { - BLI_memblock_destroy(viewport->vmempool.commands_small, NULL); - } - if (viewport->vmempool.callbuffers != NULL) { - BLI_memblock_destroy(viewport->vmempool.callbuffers, NULL); - } - if (viewport->vmempool.obmats != NULL) { - BLI_memblock_destroy(viewport->vmempool.obmats, NULL); - } - if (viewport->vmempool.obinfos != NULL) { - BLI_memblock_destroy(viewport->vmempool.obinfos, NULL); + if (viewport->vmempool.states != NULL) { + BLI_memblock_destroy(viewport->vmempool.states, NULL); } if (viewport->vmempool.cullstates != NULL) { BLI_memblock_destroy(viewport->vmempool.cullstates, NULL); @@ -660,13 +650,6 @@ void GPU_viewport_free(GPUViewport *viewport) BLI_memblock_destroy(viewport->vmempool.images, NULL); } - for (int i = 0; i < viewport->vmempool.ubo_len; i++) { - GPU_uniformbuffer_free(viewport->vmempool.matrices_ubo[i]); - GPU_uniformbuffer_free(viewport->vmempool.obinfos_ubo[i]); - } - MEM_SAFE_FREE(viewport->vmempool.matrices_ubo); - MEM_SAFE_FREE(viewport->vmempool.obinfos_ubo); - DRW_instance_data_list_free(viewport->idatalist); MEM_freeN(viewport->idatalist); diff --git a/source/blender/gpu/shaders/gpu_shader_common_obinfos_lib.glsl b/source/blender/gpu/shaders/gpu_shader_common_obinfos_lib.glsl deleted file mode 100644 index aa1d437c307..00000000000 --- a/source/blender/gpu/shaders/gpu_shader_common_obinfos_lib.glsl +++ /dev/null @@ -1,19 +0,0 @@ - -/* Need to be included after common_view_lib.glsl for resource_id. */ -#ifndef GPU_OBINFOS_UBO -#define GPU_OBINFOS_UBO -struct ObjectInfos { - vec4 drw_OrcoTexCoFactors[2]; - vec4 drw_ObjectColor; - vec4 drw_Infos; -}; - -layout(std140) uniform infoBlock -{ - /* DRW_RESOURCE_CHUNK_LEN = 512 */ - ObjectInfos drw_infos[512]; -}; -#define OrcoTexCoFactors (drw_infos[resource_id].drw_OrcoTexCoFactors) -#define ObjectInfo (drw_infos[resource_id].drw_Infos) -#define ObjectColor (drw_infos[resource_id].drw_ObjectColor) -#endif diff --git a/source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl index f32c47bcec3..31b359dbe6d 100644 --- a/source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl @@ -1,5 +1,8 @@ uniform mat4 ViewProjectionMatrix; +#ifdef USE_WORLD_CLIP_PLANES +uniform mat4 ModelMatrix; +#endif /* ---- Instantiated Attrs ---- */ in float pos; @@ -44,12 +47,11 @@ void main() pPos = vec3(0.0); } - vec4 wPos = InstanceModelMatrix * vec4(pPos, 1.0); - gl_Position = ViewProjectionMatrix * wPos; + gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pPos, 1.0); finalColor = vec4(color, 1.0); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance(wPos.xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * InstanceModelMatrix * vec4(pPos, 1.0)).xyz); #endif } diff --git a/source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl index 5bd29c55e42..d9a0ffbbdac 100644 --- a/source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl @@ -18,14 +18,13 @@ void main() { float len = end - start; vec3 sta = vec3(0.0, 0.0, -start); + vec4 pos_4d = vec4(pos * -len + sta, 1.0); - vec4 wPos = InstanceModelMatrix * vec4(pos * -len + sta, 1.0); - - gl_Position = ViewProjectionMatrix * wPos; + gl_Position = ViewProjectionMatrix * InstanceModelMatrix * pos_4d; gl_PointSize = size; finalColor = vec4(color, 1.0); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance(wPos.xyz); + world_clip_planes_calc_clip_distance((InstanceModelMatrix * pos_4d).xyz); #endif } diff --git a/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl index 10228a1e985..3e52e43beae 100644 --- a/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl @@ -1,5 +1,6 @@ uniform mat4 ViewProjectionMatrix; +uniform mat4 ModelMatrix; /* ---- Instantiated Attrs ---- */ in vec3 pos; @@ -19,10 +20,10 @@ void main() { finalColor = color; - vec4 wPos = InstanceModelMatrix * vec4(pos * size, 1.0); - gl_Position = ViewProjectionMatrix * wPos; + vec4 pos_4d = vec4(pos * size, 1.0); + gl_Position = ViewProjectionMatrix * InstanceModelMatrix * pos_4d; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance(wPos.xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * InstanceModelMatrix * pos_4d).xyz); #endif } diff --git a/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_id_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_id_vert.glsl index 32db8d17572..130f46e1e33 100644 --- a/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_id_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_id_vert.glsl @@ -1,6 +1,8 @@ uniform mat4 ViewProjectionMatrix; - +#ifdef USE_WORLD_CLIP_PLANES +uniform mat4 ModelMatrix; +#endif uniform int baseId; /* ---- Instantiated Attrs ---- */ @@ -19,11 +21,11 @@ flat out uint finalId; void main() { - vec4 wPos = InstanceModelMatrix * vec4(pos * size, 1.0); - gl_Position = ViewProjectionMatrix * wPos; + vec4 pos_4d = vec4(pos * size, 1.0); + gl_Position = ViewProjectionMatrix * InstanceModelMatrix * pos_4d; finalId = uint(baseId + callId); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance(wPos.xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * InstanceModelMatrix * pos_4d).xyz); #endif } diff --git a/source/blender/gpu/shaders/gpu_shader_instance_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_vert.glsl index b8d31f5540a..eeca6e972fa 100644 --- a/source/blender/gpu/shaders/gpu_shader_instance_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_instance_vert.glsl @@ -9,5 +9,5 @@ in mat4 InstanceModelMatrix; void main() { - gl_Position = ViewProjectionMatrix * (InstanceModelMatrix * vec4(pos, 1.0)); + gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pos, 1.0); } |