diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2018-02-14 20:59:15 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2018-02-14 20:59:42 +0300 |
commit | 0ef981f603a0d03a1b187995c91282c73ed50bd7 (patch) | |
tree | 0957ed900ee82ed6d2bfc3b6e9513cefc61fe50b | |
parent | 629a87481769d8886fcbe66ca4e4e4b60c767627 (diff) |
DRW: Refactor: Less feature duplication with Gwn.
This removes the need of custom attribs for instancing.
Instancing works fully with dynamic batches & Gwn_VertFormat now.
This is in prevision of the VAO manager patch.
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_effects.c | 3 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_lightprobes.c | 52 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_lights.c | 8 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_render.c | 3 | ||||
-rw-r--r-- | source/blender/draw/intern/DRW_render.h | 28 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_common.c | 170 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_common.h | 1 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager.c | 327 | ||||
-rw-r--r-- | source/blender/draw/modes/object_mode.c | 45 |
9 files changed, 389 insertions, 248 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index be39e06bac9..9afe54d08fc 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -241,7 +241,8 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { static int zero = 0; psl->color_downsample_cube_ps = DRW_pass_create("Downsample Cube", DRW_STATE_WRITE_COLOR); - DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.downsample_cube_sh, psl->color_downsample_cube_ps, quad); + DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.downsample_cube_sh, psl->color_downsample_cube_ps, + quad, NULL); DRW_shgroup_uniform_buffer(grp, "source", &e_data.color_src); DRW_shgroup_uniform_float(grp, "texelSize", &e_data.cube_texel_size, 1); DRW_shgroup_uniform_int(grp, "Layer", &zero, 1); diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c index 6fd20233784..beed1416715 100644 --- a/source/blender/draw/engines/eevee/eevee_lightprobes.c +++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c @@ -36,6 +36,7 @@ #include "DNA_view3d_types.h" #include "BKE_object.h" +#include "MEM_guardedalloc.h" #include "GPU_material.h" #include "GPU_texture.h" @@ -82,6 +83,9 @@ static struct { struct GPUTexture *depth_array_placeholder; struct GPUTexture *cube_face_minmaxz; + struct Gwn_VertFormat *format_probe_display_cube; + struct Gwn_VertFormat *format_probe_display_planar; + int update_world; } e_data = {NULL}; /* Engine data */ @@ -433,9 +437,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat { psl->probe_glossy_compute = DRW_pass_create("LightProbe Glossy Compute", DRW_STATE_WRITE_COLOR); - struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get(); - - DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.probe_filter_glossy_sh, psl->probe_glossy_compute, geom); + DRWShadingGroup *grp = DRW_shgroup_create(e_data.probe_filter_glossy_sh, psl->probe_glossy_compute); DRW_shgroup_uniform_float(grp, "intensityFac", &pinfo->intensity_fac, 1); DRW_shgroup_uniform_float(grp, "sampleCount", &pinfo->samples_ct, 1); DRW_shgroup_uniform_float(grp, "invSampleCount", &pinfo->invsamples_ct, 1); @@ -448,8 +450,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley); // DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter); DRW_shgroup_uniform_texture(grp, "probeHdr", sldata->probe_rt); - - DRW_shgroup_set_instance_count(grp, 1); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); } { @@ -505,18 +506,30 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CULL_BACK; psl->probe_display = DRW_pass_create("LightProbe Display", state); - struct Gwn_Batch *geom = DRW_cache_sphere_get(); - DRWShadingGroup *grp = stl->g_data->cube_display_shgrp = DRW_shgroup_instance_create(e_data.probe_cube_display_sh, psl->probe_display, geom); - DRW_shgroup_attrib_float(grp, "probe_id", 1); /* XXX this works because we are still uploading 4bytes and using the right stride */ - DRW_shgroup_attrib_float(grp, "probe_location", 3); - DRW_shgroup_attrib_float(grp, "sphere_size", 1); + DRW_shgroup_instance_format(e_data.format_probe_display_cube, { + {"probe_id" , DRW_ATTRIB_INT, 1}, + {"probe_location", DRW_ATTRIB_FLOAT, 3}, + {"sphere_size" , DRW_ATTRIB_FLOAT, 1}, + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.probe_cube_display_sh, + psl->probe_display, + DRW_cache_sphere_get(), + e_data.format_probe_display_cube); + stl->g_data->cube_display_shgrp = grp; DRW_shgroup_uniform_buffer(grp, "probeCubes", &sldata->probe_pool); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - geom = DRW_cache_quad_get(); - grp = stl->g_data->planar_display_shgrp = DRW_shgroup_instance_create(e_data.probe_planar_display_sh, psl->probe_display, geom); - DRW_shgroup_attrib_float(grp, "probe_id", 1); /* XXX this works because we are still uploading 4bytes and using the right stride */ - DRW_shgroup_attrib_float(grp, "probe_mat", 16); + DRW_shgroup_instance_format(e_data.format_probe_display_planar, { + {"probe_id" , DRW_ATTRIB_INT, 1}, + {"probe_mat", DRW_ATTRIB_FLOAT, 16}, + }); + + grp = DRW_shgroup_instance_create(e_data.probe_planar_display_sh, + psl->probe_display, + DRW_cache_quad_get(), + e_data.format_probe_display_planar); + stl->g_data->planar_display_shgrp = grp; DRW_shgroup_uniform_buffer(grp, "probePlanars", &txl->planar_pool); } @@ -524,7 +537,10 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat psl->probe_planar_downsample_ps = DRW_pass_create("LightProbe Planar Downsample", DRW_STATE_WRITE_COLOR); struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get(); - DRWShadingGroup *grp = stl->g_data->planar_downsample = DRW_shgroup_instance_create(e_data.probe_planar_downsample_sh, psl->probe_planar_downsample_ps, geom); + DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.probe_planar_downsample_sh, + psl->probe_planar_downsample_ps, + geom, NULL); + stl->g_data->planar_downsample = grp; DRW_shgroup_uniform_buffer(grp, "source", &txl->planar_pool); DRW_shgroup_uniform_float(grp, "fireflyFactor", &sldata->common_data.ssr_firefly_fac, 1); } @@ -827,7 +843,9 @@ static void EEVEE_lightprobes_updates(EEVEE_ViewLayerData *sldata, EEVEE_PassLis (probe->flag & LIGHTPROBE_FLAG_SHOW_DATA)) { struct Gwn_Batch *geom = DRW_cache_sphere_get(); - DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.probe_grid_display_sh, psl->probe_display, geom); + DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.probe_grid_display_sh, + psl->probe_display, + geom, NULL); DRW_shgroup_set_instance_count(grp, ped->num_cell); DRW_shgroup_uniform_int(grp, "offset", &egrid->offset, 1); DRW_shgroup_uniform_ivec3(grp, "grid_resolution", egrid->resolution, 1); @@ -1695,6 +1713,8 @@ void EEVEE_lightprobes_refresh(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) void EEVEE_lightprobes_free(void) { + MEM_SAFE_FREE(e_data.format_probe_display_cube); + MEM_SAFE_FREE(e_data.format_probe_display_planar); DRW_SHADER_FREE_SAFE(e_data.probe_default_sh); DRW_SHADER_FREE_SAFE(e_data.probe_filter_glossy_sh); DRW_SHADER_FREE_SAFE(e_data.probe_filter_diffuse_sh); diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c index 69b58bf9670..6f96d1af3ed 100644 --- a/source/blender/draw/engines/eevee/eevee_lights.c +++ b/source/blender/draw/engines/eevee/eevee_lights.c @@ -380,12 +380,12 @@ void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, Object *ob) void EEVEE_lights_cache_shcaster_add( EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl, struct Gwn_Batch *geom, float (*obmat)[4]) { - DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.shadow_sh, psl->shadow_cube_pass, geom); + DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.shadow_sh, psl->shadow_cube_pass, geom, NULL); DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo); DRW_shgroup_uniform_mat4(grp, "ShadowModelMatrix", (float *)obmat); DRW_shgroup_set_instance_count(grp, 6); - grp = DRW_shgroup_instance_create(e_data.shadow_sh, psl->shadow_cascade_pass, geom); + grp = DRW_shgroup_instance_create(e_data.shadow_sh, psl->shadow_cascade_pass, geom, NULL); DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo); DRW_shgroup_uniform_mat4(grp, "ShadowModelMatrix", (float *)obmat); DRW_shgroup_set_instance_count(grp, MAX_CASCADE_NUM); @@ -395,7 +395,7 @@ void EEVEE_lights_cache_shcaster_material_add( EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl, struct GPUMaterial *gpumat, struct Gwn_Batch *geom, struct Object *ob, float (*obmat)[4], float *alpha_threshold) { - DRWShadingGroup *grp = DRW_shgroup_material_instance_create(gpumat, psl->shadow_cube_pass, geom, ob); + DRWShadingGroup *grp = DRW_shgroup_material_instance_create(gpumat, psl->shadow_cube_pass, geom, ob, NULL); if (grp == NULL) return; @@ -407,7 +407,7 @@ void EEVEE_lights_cache_shcaster_material_add( DRW_shgroup_set_instance_count(grp, 6); - grp = DRW_shgroup_material_instance_create(gpumat, psl->shadow_cascade_pass, geom, ob); + grp = DRW_shgroup_material_instance_create(gpumat, psl->shadow_cascade_pass, geom, ob, NULL); DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo); DRW_shgroup_uniform_mat4(grp, "ShadowModelMatrix", (float *)obmat); diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c index 33c8e2602d4..4524ac397e7 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -394,6 +394,9 @@ void EEVEE_render_draw(EEVEE_Data *vedata, struct RenderEngine *engine, struct D /* Sort transparents before the loop. */ DRW_pass_sort_shgroup_z(psl->transparent_pass); + /* Push instances attribs to the GPU. */ + DRW_render_instance_buffer_finish(); + if ((view_layer->passflag & (SCE_PASS_SUBSURFACE_COLOR | SCE_PASS_SUBSURFACE_DIRECT | SCE_PASS_SUBSURFACE_INDIRECT)) != 0) diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index ab09586861d..49f244d4268 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -305,13 +305,33 @@ typedef enum { #define DRW_STATE_DEFAULT (DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS) +typedef enum { + DRW_ATTRIB_INT, + DRW_ATTRIB_FLOAT, +} DRWAttribType; + +typedef struct DRWInstanceAttribFormat { + char name[32]; + DRWAttribType type; + int components; +} DRWInstanceAttribFormat; + +struct Gwn_VertFormat *DRW_shgroup_instance_format_array(const DRWInstanceAttribFormat attribs[], int arraysize); +#define DRW_shgroup_instance_format(format, ...) do { \ + if (format == NULL) { \ + DRWInstanceAttribFormat drw_format[] = __VA_ARGS__;\ + format = DRW_shgroup_instance_format_array(drw_format, (sizeof(drw_format) / sizeof(DRWInstanceAttribFormat))); \ + } \ +} while (0) DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass); DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPass *pass); DRWShadingGroup *DRW_shgroup_material_instance_create( - struct GPUMaterial *material, DRWPass *pass, struct Gwn_Batch *geom, struct Object *ob); + struct GPUMaterial *material, DRWPass *pass, struct Gwn_Batch *geom, struct Object *ob, + struct Gwn_VertFormat *format); DRWShadingGroup *DRW_shgroup_material_empty_tri_batch_create(struct GPUMaterial *material, DRWPass *pass, int size); -DRWShadingGroup *DRW_shgroup_instance_create(struct GPUShader *shader, DRWPass *pass, struct Gwn_Batch *geom); +DRWShadingGroup *DRW_shgroup_instance_create( + struct GPUShader *shader, DRWPass *pass, struct Gwn_Batch *geom, struct Gwn_VertFormat *format); DRWShadingGroup *DRW_shgroup_point_batch_create(struct GPUShader *shader, DRWPass *pass); DRWShadingGroup *DRW_shgroup_line_batch_create(struct GPUShader *shader, DRWPass *pass); DRWShadingGroup *DRW_shgroup_empty_tri_batch_create(struct GPUShader *shader, DRWPass *pass, int size); @@ -335,13 +355,12 @@ void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, const void *at DRW_shgroup_call_dynamic_add_array(shgroup, array, (sizeof(array) / sizeof(*array))); \ } while (0) /* Use this to set a high number of instances. */ -void DRW_shgroup_set_instance_count(DRWShadingGroup *shgroup, int count); +void DRW_shgroup_set_instance_count(DRWShadingGroup *shgroup, unsigned int count); unsigned int DRW_shgroup_get_instance_count(const DRWShadingGroup *shgroup); 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, unsigned int mask); -void DRW_shgroup_attrib_float(DRWShadingGroup *shgroup, const char *name, int size); void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const struct GPUTexture *tex); void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, const char *name, const struct GPUUniformBuffer *ubo); @@ -394,6 +413,7 @@ void DRW_render_to_image(struct RenderEngine *re, struct Depsgraph *depsgraph); void DRW_render_object_iter( void *vedata, struct RenderEngine *engine, struct Depsgraph *graph, void (*callback)(void *vedata, struct Object *ob, struct RenderEngine *engine, struct Depsgraph *graph)); +void DRW_render_instance_buffer_finish(void); /* ViewLayers */ void *DRW_view_layer_engine_data_get(DrawEngineType *engine_type); diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c index 4bd138e80f5..3b2c74e8032 100644 --- a/source/blender/draw/intern/draw_common.c +++ b/source/blender/draw/intern/draw_common.c @@ -156,6 +156,29 @@ void DRW_globals_update(void) /* ********************************* SHGROUP ************************************* */ +static struct { + struct Gwn_VertFormat *instance_screenspace; + struct Gwn_VertFormat *instance_color; + struct Gwn_VertFormat *instance_screen_aligned; + struct Gwn_VertFormat *instance_scaled; + struct Gwn_VertFormat *instance_sized; + struct Gwn_VertFormat *instance; + struct Gwn_VertFormat *instance_camera; + struct Gwn_VertFormat *instance_distance_lines; + struct Gwn_VertFormat *instance_spot; + struct Gwn_VertFormat *instance_bone_envelope_wire; + struct Gwn_VertFormat *instance_bone_envelope_solid; + struct Gwn_VertFormat *instance_mball_helpers; +} g_formats = {NULL}; + +void DRW_globals_free(void) +{ + struct Gwn_VertFormat **format = &g_formats.instance_screenspace; + for (int i = 0; i < sizeof(g_formats) / sizeof(void*); ++i, ++format) { + MEM_SAFE_FREE(*format); + } +} + DRWShadingGroup *shgroup_dynlines_uniform_color(DRWPass *pass, float color[4]) { GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); @@ -203,9 +226,12 @@ DRWShadingGroup *shgroup_instance_screenspace(DRWPass *pass, struct Gwn_Batch *g { GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR); - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom); - DRW_shgroup_attrib_float(grp, "world_pos", 3); - DRW_shgroup_attrib_float(grp, "color", 3); + DRW_shgroup_instance_format(g_formats.instance_screenspace, { + {"world_pos", DRW_ATTRIB_FLOAT, 3}, + {"color" , DRW_ATTRIB_FLOAT, 3} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_screenspace); DRW_shgroup_uniform_float(grp, "size", size, 1); DRW_shgroup_uniform_float(grp, "pixel_size", DRW_viewport_pixelsize_get(), 1); DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2); @@ -219,9 +245,12 @@ DRWShadingGroup *shgroup_instance_solid(DRWPass *pass, struct Gwn_Batch *geom) static float light[3] = {0.0f, 0.0f, 1.0f}; GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR); - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom); - DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); - DRW_shgroup_attrib_float(grp, "color", 4); + DRW_shgroup_instance_format(g_formats.instance_color, { + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, + {"color" , DRW_ATTRIB_FLOAT, 4} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_color); DRW_shgroup_uniform_vec3(grp, "light", light, 1); return grp; @@ -231,9 +260,12 @@ DRWShadingGroup *shgroup_instance_wire(DRWPass *pass, struct Gwn_Batch *geom) { GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_OBJECTSPACE_VARIYING_COLOR); - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom); - DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); - DRW_shgroup_attrib_float(grp, "color", 4); + DRW_shgroup_instance_format(g_formats.instance_color, { + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, + {"color" , DRW_ATTRIB_FLOAT, 4} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_color); return grp; } @@ -242,10 +274,13 @@ DRWShadingGroup *shgroup_instance_screen_aligned(DRWPass *pass, struct Gwn_Batch { GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED); - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom); - DRW_shgroup_attrib_float(grp, "color", 3); - DRW_shgroup_attrib_float(grp, "size", 1); - DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); + DRW_shgroup_instance_format(g_formats.instance_screen_aligned, { + {"color" , DRW_ATTRIB_FLOAT, 3}, + {"size" , DRW_ATTRIB_FLOAT, 1}, + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_screen_aligned); DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2); return grp; @@ -255,10 +290,13 @@ DRWShadingGroup *shgroup_instance_axis_names(DRWPass *pass, struct Gwn_Batch *ge { GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS); - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom); - DRW_shgroup_attrib_float(grp, "color", 3); - DRW_shgroup_attrib_float(grp, "size", 1); - DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); + DRW_shgroup_instance_format(g_formats.instance_screen_aligned, { + {"color" , DRW_ATTRIB_FLOAT, 3}, + {"size" , DRW_ATTRIB_FLOAT, 1}, + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_screen_aligned); DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2); return grp; @@ -268,10 +306,13 @@ DRWShadingGroup *shgroup_instance_scaled(DRWPass *pass, struct Gwn_Batch *geom) { GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE); - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom); - DRW_shgroup_attrib_float(grp, "color", 3); - DRW_shgroup_attrib_float(grp, "size", 3); - DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); + DRW_shgroup_instance_format(g_formats.instance_scaled, { + {"color" , DRW_ATTRIB_FLOAT, 3}, + {"size" , DRW_ATTRIB_FLOAT, 3}, + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom, g_formats.instance_scaled); return grp; } @@ -280,10 +321,13 @@ DRWShadingGroup *shgroup_instance(DRWPass *pass, struct Gwn_Batch *geom) { GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE); - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom); - DRW_shgroup_attrib_float(grp, "color", 3); - DRW_shgroup_attrib_float(grp, "size", 1); - DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); + DRW_shgroup_instance_format(g_formats.instance_sized, { + {"color" , DRW_ATTRIB_FLOAT, 3}, + {"size" , DRW_ATTRIB_FLOAT, 1}, + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom, g_formats.instance_sized); return grp; } @@ -292,12 +336,15 @@ DRWShadingGroup *shgroup_camera_instance(DRWPass *pass, struct Gwn_Batch *geom) { GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_CAMERA); - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom); - DRW_shgroup_attrib_float(grp, "color", 3); - DRW_shgroup_attrib_float(grp, "corners", 8); - DRW_shgroup_attrib_float(grp, "depth", 1); - DRW_shgroup_attrib_float(grp, "tria", 4); - DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); + DRW_shgroup_instance_format(g_formats.instance_camera, { + {"color" , DRW_ATTRIB_FLOAT, 3}, + {"corners" , DRW_ATTRIB_FLOAT, 8}, + {"depth" , DRW_ATTRIB_FLOAT, 1}, + {"tria" , DRW_ATTRIB_FLOAT, 4}, + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom, g_formats.instance_camera); return grp; } @@ -307,11 +354,14 @@ DRWShadingGroup *shgroup_distance_lines_instance(DRWPass *pass, struct Gwn_Batch GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_DISTANCE_LINES); static float point_size = 4.0f; - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom); - DRW_shgroup_attrib_float(grp, "color", 3); - DRW_shgroup_attrib_float(grp, "start", 1); - DRW_shgroup_attrib_float(grp, "end", 1); - DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); + DRW_shgroup_instance_format(g_formats.instance_distance_lines, { + {"color" , DRW_ATTRIB_FLOAT, 3}, + {"start" , DRW_ATTRIB_FLOAT, 1}, + {"end" , DRW_ATTRIB_FLOAT, 1}, + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom, g_formats.instance_distance_lines); DRW_shgroup_uniform_float(grp, "size", &point_size, 1); return grp; @@ -323,9 +373,12 @@ DRWShadingGroup *shgroup_spot_instance(DRWPass *pass, struct Gwn_Batch *geom) static const int True = true; static const int False = false; - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom); - DRW_shgroup_attrib_float(grp, "color", 3); - DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); + DRW_shgroup_instance_format(g_formats.instance_spot, { + {"color" , DRW_ATTRIB_FLOAT, 3}, + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom, g_formats.instance_spot); DRW_shgroup_uniform_bool(grp, "drawFront", &False, 1); DRW_shgroup_uniform_bool(grp, "drawBack", &False, 1); DRW_shgroup_uniform_bool(grp, "drawSilhouette", &True, 1); @@ -337,12 +390,15 @@ DRWShadingGroup *shgroup_instance_bone_envelope_wire(DRWPass *pass, struct Gwn_B { GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_WIRE); - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom); - DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); - DRW_shgroup_attrib_float(grp, "color", 4); - DRW_shgroup_attrib_float(grp, "radius_head", 1); - DRW_shgroup_attrib_float(grp, "radius_tail", 1); - DRW_shgroup_attrib_float(grp, "distance", 1); + DRW_shgroup_instance_format(g_formats.instance_bone_envelope_wire, { + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, + {"color" , DRW_ATTRIB_FLOAT, 4}, + {"radius_head" , DRW_ATTRIB_FLOAT, 1}, + {"radius_tail" , DRW_ATTRIB_FLOAT, 1}, + {"distance" , DRW_ATTRIB_FLOAT, 1} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_bone_envelope_wire); return grp; } @@ -352,11 +408,14 @@ DRWShadingGroup *shgroup_instance_bone_envelope_solid(DRWPass *pass, struct Gwn_ static float light[3] = {0.0f, 0.0f, 1.0f}; GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_SOLID); - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom); - DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); - DRW_shgroup_attrib_float(grp, "color", 4); - DRW_shgroup_attrib_float(grp, "radius_head", 1); - DRW_shgroup_attrib_float(grp, "radius_tail", 1); + DRW_shgroup_instance_format(g_formats.instance_bone_envelope_solid, { + {"InstanceModelMatrix" , DRW_ATTRIB_FLOAT, 16}, + {"color" , DRW_ATTRIB_FLOAT, 4}, + {"radius_head" , DRW_ATTRIB_FLOAT, 1}, + {"radius_tail" , DRW_ATTRIB_FLOAT, 1} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_bone_envelope_solid); DRW_shgroup_uniform_vec3(grp, "light", light, 1); return grp; @@ -366,10 +425,13 @@ DRWShadingGroup *shgroup_instance_mball_helpers(DRWPass *pass, struct Gwn_Batch { GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_MBALL_HELPERS); - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom); - DRW_shgroup_attrib_float(grp, "ScaleTranslationMatrix", 12); - DRW_shgroup_attrib_float(grp, "radius", 1); - DRW_shgroup_attrib_float(grp, "color", 3); + DRW_shgroup_instance_format(g_formats.instance_mball_helpers, { + {"ScaleTranslationMatrix" , DRW_ATTRIB_FLOAT, 16}, + {"radius" , DRW_ATTRIB_FLOAT, 1}, + {"color" , DRW_ATTRIB_FLOAT, 3} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_mball_helpers); DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2); return grp; diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h index 7ff11f5f069..68ab7e055f5 100644 --- a/source/blender/draw/intern/draw_common.h +++ b/source/blender/draw/intern/draw_common.h @@ -100,6 +100,7 @@ typedef struct GlobalsUboStorage { /* Keep in sync with globalsBlock in shaders */ void DRW_globals_update(void); +void DRW_globals_free(void); struct DRWShadingGroup *shgroup_dynlines_uniform_color(struct DRWPass *pass, float color[4]); struct DRWShadingGroup *shgroup_dynpoints_uniform_color(struct DRWPass *pass, float color[4], float *size); diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 96fdc132842..622fbe968d2 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -172,24 +172,30 @@ typedef enum { DRW_UNIFORM_BLOCK } DRWUniformType; -typedef enum { - DRW_ATTRIB_INT, - DRW_ATTRIB_FLOAT, -} DRWAttribType; - #define MAX_UNIFORM_DATA_SIZE 16 struct DRWUniform { struct DRWUniform *next; + const void *value; int location; char type; /* DRWUniformType */ char length; /* cannot be more than 16 */ char arraysize; /* cannot be more than 16 too */ - const void *value; }; struct DRWInterface { DRWUniform *uniforms; /* DRWUniform, single-linked list */ + /* Dynamic batch */ +#ifdef USE_GPU_SELECT + struct DRWInstanceData *inst_selectid; + /* Override for single object instances. */ + int override_selectid; +#endif + Gwn_VertBuf *instance_vbo; + unsigned int instance_count; +#ifndef NDEBUG + char attribs_count; +#endif /* matrices locations */ int model; int modelinverse; @@ -208,18 +214,6 @@ struct DRWInterface { int orcotexfac; int eye; int clipplanes; - /* Dynamic batch */ - struct DRWInstanceData *inst_data; -#ifdef USE_GPU_SELECT - struct DRWInstanceData *inst_selectid; - /* Override for single object instances. */ - int override_selectid; -#endif - unsigned int instance_count; - unsigned char attribs_count; - unsigned char attribs_stride; - unsigned char attribs_size[MAX_ATTRIB_COUNT]; - Gwn_VertFormat vbo_format; }; struct DRWPass { @@ -352,6 +346,8 @@ static struct DRWGlobalState { ListBase enabled_engines; /* RenderEngineType */ + bool buffer_finish_called; /* Avoid bad usage of DRW_render_instance_buffer_finish */ + /* Profiling */ double cache_time; } DST = {NULL}; @@ -638,7 +634,7 @@ void DRW_shader_free(GPUShader *shader) /** \name Interface (DRW_interface) * \{ */ -static void drw_interface_create(DRWInterface *interface, GPUShader *shader) +static void drw_interface_init(DRWInterface *interface, GPUShader *shader) { interface->model = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODEL); interface->modelinverse = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODEL_INV); @@ -658,18 +654,56 @@ static void drw_interface_create(DRWInterface *interface, GPUShader *shader) interface->clipplanes = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_CLIPPLANES); interface->eye = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_EYE); interface->instance_count = 0; +#ifndef NDEBUG interface->attribs_count = 0; - interface->attribs_stride = 0; - interface->inst_data = NULL; +#endif interface->uniforms = NULL; #ifdef USE_GPU_SELECT interface->inst_selectid = NULL; interface->override_selectid = -1; #endif - - memset(&interface->vbo_format, 0, sizeof(Gwn_VertFormat)); } +static void drw_interface_instance_init( + DRWShadingGroup *shgroup, GPUShader *shader, Gwn_VertFormat *format) +{ + DRWInterface *interface = &shgroup->interface; + drw_interface_init(interface, shader); + +#ifndef NDEBUG + interface->attribs_count = (format != NULL) ? format->attrib_ct : 0; +#endif + + Gwn_PrimType type; + Gwn_Batch **r_batch = NULL; + switch (shgroup->type) { + case DRW_SHG_INSTANCE: + r_batch = &shgroup->instancing_geom; + type = GWN_PRIM_POINTS; + break; + case DRW_SHG_POINT_BATCH: + r_batch = &shgroup->batch_geom; + type = GWN_PRIM_POINTS; + break; + case DRW_SHG_LINE_BATCH: + r_batch = &shgroup->batch_geom; + type = GWN_PRIM_LINES; + break; + case DRW_SHG_TRIANGLE_BATCH: + r_batch = &shgroup->batch_geom; + type = GWN_PRIM_TRIS; + break; + default: + BLI_assert(0); + } + + if (format != NULL) { + DRW_instance_buffer_request(DST.idatalist, format, shgroup, r_batch, &interface->instance_vbo, type); + } + else { + *r_batch = NULL; + } +} static void drw_interface_uniform(DRWShadingGroup *shgroup, const char *name, DRWUniformType type, const void *value, int length, int arraysize) @@ -706,19 +740,17 @@ static void drw_interface_uniform(DRWShadingGroup *shgroup, const char *name, shgroup->interface.uniforms = uni; } -static void drw_interface_attrib(DRWShadingGroup *shgroup, const char *name, DRWAttribType UNUSED(type), int size, bool dummy) +Gwn_VertFormat *DRW_shgroup_instance_format_array(const DRWInstanceAttribFormat attribs[], int arraysize) { - unsigned int attrib_id = shgroup->interface.attribs_count; - shgroup->interface.attribs_size[attrib_id] = size; - shgroup->interface.attribs_stride += size; - shgroup->interface.attribs_count += 1; - - BLI_assert(ELEM(shgroup->type, DRW_SHG_INSTANCE, DRW_SHG_POINT_BATCH, DRW_SHG_LINE_BATCH, DRW_SHG_TRIANGLE_BATCH)); - BLI_assert(shgroup->interface.attribs_count < MAX_ATTRIB_COUNT); + Gwn_VertFormat *format = MEM_callocN(sizeof(Gwn_VertFormat), "Gwn_VertFormat"); - GWN_vertformat_attr_add(&shgroup->interface.vbo_format, name, GWN_COMP_F32, size, GWN_FETCH_FLOAT); - - UNUSED_VARS(dummy); + for (int i = 0; i < arraysize; ++i) { + GWN_vertformat_attr_add(format, attribs[i].name, + (attribs[i].type == DRW_ATTRIB_INT) ? GWN_COMP_I32 : GWN_COMP_F32, + attribs[i].components, + (attribs[i].type == DRW_ATTRIB_INT) ? GWN_FETCH_INT : GWN_FETCH_FLOAT); + } + return format; } /** \} */ @@ -729,7 +761,7 @@ static void drw_interface_attrib(DRWShadingGroup *shgroup, const char *name, DRW /** \name Shading Group (DRW_shgroup) * \{ */ -DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass) +static DRWShadingGroup *drw_shgroup_create_ex(struct GPUShader *shader, DRWPass *pass) { DRWShadingGroup *shgroup = BLI_mempool_alloc(DST.vmempool->shgroups); @@ -742,9 +774,6 @@ DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass) } pass->shgroups_last = shgroup; shgroup->next = NULL; - - drw_interface_create(&shgroup->interface, shader); - shgroup->type = DRW_SHG_NORMAL; shgroup->shader = shader; shgroup->state_extra = 0; @@ -765,7 +794,8 @@ DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass) return shgroup; } -DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPass *pass) +static DRWShadingGroup *drw_shgroup_material_create_ex( + struct GPUMaterial *material, DRWPass *pass, Gwn_VertFormat *format, bool use_instancing) { double time = 0.0; /* TODO make time variable */ @@ -780,7 +810,14 @@ DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPa struct GPUShader *shader = GPU_pass_shader(gpupass); - DRWShadingGroup *grp = DRW_shgroup_create(shader, pass); + DRWShadingGroup *grp = drw_shgroup_create_ex(shader, pass); + + if (use_instancing) { + drw_interface_instance_init(grp, shader, format); + } + else { + drw_interface_init(&grp->interface, shader); + } /* Converting dynamic GPUInput to DRWUniform */ ListBase *inputs = &gpupass->inputs; @@ -828,10 +865,17 @@ DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPa return grp; } +DRWShadingGroup *DRW_shgroup_material_create( + struct GPUMaterial *material, DRWPass *pass) +{ + DRWShadingGroup *shgroup = drw_shgroup_material_create_ex(material, pass, NULL, false); + return shgroup; +} + DRWShadingGroup *DRW_shgroup_material_instance_create( - struct GPUMaterial *material, DRWPass *pass, Gwn_Batch *geom, Object *ob) + struct GPUMaterial *material, DRWPass *pass, Gwn_Batch *geom, Object *ob, Gwn_VertFormat *format) { - DRWShadingGroup *shgroup = DRW_shgroup_material_create(material, pass); + DRWShadingGroup *shgroup = drw_shgroup_material_create_ex(material, pass, format, true); if (shgroup) { shgroup->type = DRW_SHG_INSTANCE; @@ -845,43 +889,61 @@ DRWShadingGroup *DRW_shgroup_material_instance_create( DRWShadingGroup *DRW_shgroup_material_empty_tri_batch_create( struct GPUMaterial *material, DRWPass *pass, int size) { - DRWShadingGroup *shgroup = DRW_shgroup_material_create(material, pass); +#ifdef USE_GPU_SELECT + BLI_assert((G.f & G_PICKSEL) == 0); +#endif + /* Calling drw_interface_init because we don't need instancing_geom. */ + DRWShadingGroup *shgroup = drw_shgroup_material_create_ex(material, pass, NULL, false); if (shgroup) { shgroup->type = DRW_SHG_TRIANGLE_BATCH; shgroup->interface.instance_count = size * 3; - drw_interface_attrib(shgroup, "dummy", DRW_ATTRIB_FLOAT, 1, true); } return shgroup; } -DRWShadingGroup *DRW_shgroup_instance_create(struct GPUShader *shader, DRWPass *pass, Gwn_Batch *geom) +DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass) { - DRWShadingGroup *shgroup = DRW_shgroup_create(shader, pass); + DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass); + drw_interface_init(&shgroup->interface, shader); + return shgroup; +} +DRWShadingGroup *DRW_shgroup_instance_create( + struct GPUShader *shader, DRWPass *pass, Gwn_Batch *geom, Gwn_VertFormat *format) +{ + DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass); shgroup->type = DRW_SHG_INSTANCE; shgroup->instance_geom = geom; + drw_interface_instance_init(shgroup, shader, format); + return shgroup; } +static Gwn_VertFormat *g_pos_format = NULL; + DRWShadingGroup *DRW_shgroup_point_batch_create(struct GPUShader *shader, DRWPass *pass) { - DRWShadingGroup *shgroup = DRW_shgroup_create(shader, pass); + DRW_shgroup_instance_format(g_pos_format, {{"pos", DRW_ATTRIB_FLOAT, 3}}); + DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass); shgroup->type = DRW_SHG_POINT_BATCH; - DRW_shgroup_attrib_float(shgroup, "pos", 3); + + drw_interface_instance_init(shgroup, shader, g_pos_format); return shgroup; } DRWShadingGroup *DRW_shgroup_line_batch_create(struct GPUShader *shader, DRWPass *pass) { - DRWShadingGroup *shgroup = DRW_shgroup_create(shader, pass); + DRW_shgroup_instance_format(g_pos_format, {{"pos", DRW_ATTRIB_FLOAT, 3}}); + DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass); shgroup->type = DRW_SHG_LINE_BATCH; - DRW_shgroup_attrib_float(shgroup, "pos", 3); + + drw_interface_instance_init(shgroup, shader, g_pos_format); return shgroup; } @@ -891,21 +953,23 @@ DRWShadingGroup *DRW_shgroup_line_batch_create(struct GPUShader *shader, DRWPass * and dont need any VBO attrib */ DRWShadingGroup *DRW_shgroup_empty_tri_batch_create(struct GPUShader *shader, DRWPass *pass, int size) { - DRWShadingGroup *shgroup = DRW_shgroup_create(shader, pass); +#ifdef USE_GPU_SELECT + BLI_assert((G.f & G_PICKSEL) == 0); +#endif + DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass); + + /* Calling drw_interface_init because we don't need instancing_geom. */ + drw_interface_init(&shgroup->interface, shader); shgroup->type = DRW_SHG_TRIANGLE_BATCH; shgroup->interface.instance_count = size * 3; - drw_interface_attrib(shgroup, "dummy", DRW_ATTRIB_FLOAT, 1, true); return shgroup; } -void DRW_shgroup_free(struct DRWShadingGroup *shgroup) +void DRW_shgroup_free(struct DRWShadingGroup *UNUSED(shgroup)) { - if (shgroup->type != DRW_SHG_INSTANCE_EXTERNAL) { - GWN_BATCH_DISCARD_SAFE(shgroup->instancing_geom); - } - GWN_BATCH_DISCARD_SAFE(shgroup->batch_geom); + return; } #define CALL_PREPEND(shgroup, call) { \ @@ -1041,24 +1105,18 @@ void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, const void *at BLI_assert(attr_len == interface->attribs_count); UNUSED_VARS_NDEBUG(attr_len); - if (interface->attribs_stride > 0) { - if (interface->inst_data == NULL) { - interface->inst_data = DRW_instance_data_request(DST.idatalist, interface->attribs_stride, 16); - } - - float *data = DRW_instance_data_next(interface->inst_data); - - for (int i = 0; i < interface->attribs_count; ++i) { - memcpy(data, attr[i], sizeof(float) * interface->attribs_size[i]); - data = data + interface->attribs_size[i]; + for (int i = 0; i < attr_len; ++i) { + if (interface->instance_count == interface->instance_vbo->vertex_ct) { + GWN_vertbuf_data_resize(interface->instance_vbo, interface->instance_count + 32); } + GWN_vertbuf_attr_set(interface->instance_vbo, i, interface->instance_count, attr[i]); } interface->instance_count += 1; } /* Used for instancing with no attributes */ -void DRW_shgroup_set_instance_count(DRWShadingGroup *shgroup, int count) +void DRW_shgroup_set_instance_count(DRWShadingGroup *shgroup, unsigned int count) { DRWInterface *interface = &shgroup->interface; @@ -1076,6 +1134,8 @@ void DRW_shgroup_set_instance_count(DRWShadingGroup *shgroup, int count) unsigned int DRW_shgroup_get_instance_count(const DRWShadingGroup *shgroup) { + BLI_assert(shgroup->type != DRW_SHG_NORMAL && shgroup->type != DRW_SHG_INSTANCE_EXTERNAL); + return shgroup->interface.instance_count; } @@ -1099,11 +1159,6 @@ void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, unsigned int mask) shgroup->stencil_mask = mask; } -void DRW_shgroup_attrib_float(DRWShadingGroup *shgroup, const char *name, int size) -{ - drw_interface_attrib(shgroup, name, DRW_ATTRIB_FLOAT, size, false); -} - void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex) { drw_interface_uniform(shgroup, name, DRW_UNIFORM_TEXTURE, tex, 0, 1); @@ -1179,67 +1234,6 @@ void DRW_shgroup_uniform_mat4(DRWShadingGroup *shgroup, const char *name, const drw_interface_uniform(shgroup, name, DRW_UNIFORM_MAT4, value, 16, 1); } -/* Creates a VBO containing OGL primitives for all DRWCallDynamic */ -static void shgroup_dynamic_batch(DRWShadingGroup *shgroup) -{ - DRWInterface *interface = &shgroup->interface; - int nbr = interface->instance_count; - - Gwn_PrimType type = (shgroup->type == DRW_SHG_POINT_BATCH) ? GWN_PRIM_POINTS : - (shgroup->type == DRW_SHG_TRIANGLE_BATCH) ? GWN_PRIM_TRIS : GWN_PRIM_LINES; - - if (nbr == 0) - return; - - /* Upload Data */ - Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&interface->vbo_format); - /* Use unitialized memory. This is for dummy vertex buffers. */ - /* XXX TODO do not alloc at all. */ - GWN_vertbuf_data_alloc(vbo, nbr); - - /* TODO make the batch dynamic instead of freeing it every times */ - if (shgroup->batch_geom) - GWN_batch_discard(shgroup->batch_geom); - - shgroup->batch_geom = GWN_batch_create_ex(type, vbo, NULL, GWN_BATCH_OWNS_VBO); -} - -static void shgroup_dynamic_instance(DRWShadingGroup *shgroup) -{ - DRWInterface *interface = &shgroup->interface; - int nbr = interface->instance_count; - - if (nbr == 0) - return; - - /* XXX Add a dummy attr for simple instancing. */ - if (interface->attribs_count == 0) { - drw_interface_attrib(shgroup, "dummy", DRW_ATTRIB_FLOAT, 1, true); - } - - /* Upload Data */ - Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&interface->vbo_format); - /* Use unitialized memory. This is for dummy vertex buffers. */ - /* XXX TODO do not alloc at all. */ - GWN_vertbuf_data_alloc(vbo, nbr); - - /* TODO make the batch dynamic instead of freeing it every times */ - if (shgroup->instancing_geom) - GWN_batch_discard(shgroup->instancing_geom); - - shgroup->instancing_geom = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo, NULL, GWN_BATCH_OWNS_VBO); -} - -static void shgroup_dynamic_batch_from_calls(DRWShadingGroup *shgroup) -{ - if (shgroup->type == DRW_SHG_INSTANCE) { - shgroup_dynamic_instance(shgroup); - } - else { - shgroup_dynamic_batch(shgroup); - } -} - /** \} */ @@ -1761,9 +1755,18 @@ static void draw_geometry_prepare( static void draw_geometry_execute_ex( DRWShadingGroup *shgroup, Gwn_Batch *geom, unsigned int start, unsigned int count) { + /* Special case: empty drawcall, placement is done via shader, don't bind anything. */ + if (geom == NULL) { + BLI_assert(shgroup->type == DRW_SHG_TRIANGLE_BATCH); /* Add other type if needed. */ + /* Shader is already bound. */ + Gwn_Batch *batch = DRW_cache_fullscreen_quad_get(); + GWN_batch_draw_procedural(batch, GWN_PRIM_TRIS, count); + return; + } + /* step 2 : bind vertex array & draw */ GWN_batch_program_set(geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader)); - if (shgroup->instancing_geom) { + if (ELEM(shgroup->type, DRW_SHG_INSTANCE, DRW_SHG_INSTANCE_EXTERNAL)) { GWN_batch_draw_stupid_instanced(geom, shgroup->instancing_geom, start, count); } else { @@ -1831,6 +1834,7 @@ static void bind_texture(GPUTexture *tex) GPU_texture_bind(tex, RST.bind_tex_inc); RST.bound_texs[RST.bind_tex_inc] = tex; RST.bound_tex_slots[RST.bind_tex_inc] = true; + // printf("Binds Texture %d %p\n", RST.bind_tex_inc, tex); return; } } @@ -1882,12 +1886,6 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) DST.shader = shgroup->shader; } - const bool is_normal = ELEM(shgroup->type, DRW_SHG_NORMAL); - - if (!is_normal) { - shgroup_dynamic_batch_from_calls(shgroup); - } - release_texture_slots(); release_ubo_slots(); @@ -1985,30 +1983,32 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) #endif /* Rendering Calls */ - if (!is_normal) { + if (!ELEM(shgroup->type, DRW_SHG_NORMAL)) { /* Replacing multiple calls with only one */ float obmat[4][4]; unit_m4(obmat); - if (ELEM(shgroup->type, DRW_SHG_INSTANCE, DRW_SHG_INSTANCE_EXTERNAL) && - (shgroup->instancing_geom != NULL)) - { + if (ELEM(shgroup->type, DRW_SHG_INSTANCE, DRW_SHG_INSTANCE_EXTERNAL)) { if (shgroup->type == DRW_SHG_INSTANCE_EXTERNAL) { - GPU_SELECT_LOAD_IF_PICKSEL((DRWCall *)shgroup->calls_first); - draw_geometry(shgroup, shgroup->instance_geom, obmat, shgroup->instance_data, 0, 0); + if (shgroup->instancing_geom != NULL) { + GPU_SELECT_LOAD_IF_PICKSEL((DRWCall *)shgroup->calls_first); + draw_geometry(shgroup, shgroup->instance_geom, obmat, shgroup->instance_data, 0, 0); + } } else { - unsigned int count, start; - GPU_SELECT_LOAD_IF_PICKSEL_LIST(shgroup, start, count) - { - draw_geometry(shgroup, shgroup->instance_geom, obmat, shgroup->instance_data, start, count); + if (shgroup->interface.instance_count > 0) { + unsigned int count, start; + GPU_SELECT_LOAD_IF_PICKSEL_LIST(shgroup, start, count) + { + draw_geometry(shgroup, shgroup->instance_geom, obmat, shgroup->instance_data, start, count); + } + GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count) } - GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count) } } else { /* Some dynamic batch can have no geom (no call to aggregate) */ - if (shgroup->batch_geom) { + if (shgroup->interface.instance_count > 0) { unsigned int count, start; GPU_SELECT_LOAD_IF_PICKSEL_LIST(shgroup, start, count) { @@ -2055,6 +2055,8 @@ static void drw_draw_pass_ex(DRWPass *pass, DRWShadingGroup *start_group, DRWSha /* Start fresh */ DST.shader = NULL; + BLI_assert(DST.buffer_finish_called && "DRW_render_instance_buffer_finish had not been called before drawing"); + drw_state_set(pass->state); DRW_stats_query_start(pass->name); @@ -3462,6 +3464,8 @@ void DRW_draw_render_loop_ex( DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END drw_engines_cache_finish(); + + DRW_render_instance_buffer_finish(); PROFILE_END_ACCUM(DST.cache_time, stime); } @@ -3644,6 +3648,8 @@ void DRW_render_to_image(RenderEngine *re, struct Depsgraph *depsgraph) engine_type->draw_engine->render_to_image(data, re, depsgraph); } + DST.buffer_finish_called = false; + /* TODO grease pencil */ GPU_viewport_free(DST.viewport); @@ -3677,6 +3683,14 @@ void DRW_render_object_iter( DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END } +/* Must run after all instance datas have been added. */ +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); +} + /** * object mode select-loop, see: ED_view3d_draw_select_loop (legacy drawing). */ @@ -3773,6 +3787,8 @@ void DRW_draw_select_loop( } drw_engines_cache_finish(); + + DRW_render_instance_buffer_finish(); } /* Start Drawing */ @@ -3862,6 +3878,8 @@ void DRW_draw_depth_loop( DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END drw_engines_cache_finish(); + + DRW_render_instance_buffer_finish(); } /* Start Drawing */ @@ -4076,6 +4094,7 @@ void DRW_engines_free(void) { DRW_shape_cache_free(); DRW_stats_free(); + DRW_globals_free(); DrawEngineType *next; for (DrawEngineType *type = DRW_engines.first; type; type = next) { @@ -4093,6 +4112,8 @@ void DRW_engines_free(void) if (globals_ramp) GPU_texture_free(globals_ramp); + MEM_SAFE_FREE(g_pos_format); + MEM_SAFE_FREE(RST.bound_texs); MEM_SAFE_FREE(RST.bound_tex_slots); diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c index 7ed81366341..ec43316240e 100644 --- a/source/blender/draw/modes/object_mode.c +++ b/source/blender/draw/modes/object_mode.c @@ -55,6 +55,8 @@ #include "GPU_shader.h" #include "GPU_texture.h" +#include "MEM_guardedalloc.h" + #include "UI_resources.h" #include "draw_mode_engines.h" @@ -215,6 +217,10 @@ typedef struct OBJECT_PrivateData { } OBJECT_PrivateData; /* Transient data */ static struct { + /* Instance Data format */ + struct Gwn_VertFormat *empty_image_format; + struct Gwn_VertFormat *empty_image_wire_format; + /* fullscreen shaders */ GPUShader *outline_resolve_sh; GPUShader *outline_resolve_aa_sh; @@ -531,6 +537,8 @@ static void OBJECT_engine_init(void *vedata) static void OBJECT_engine_free(void) { + MEM_SAFE_FREE(e_data.empty_image_format); + MEM_SAFE_FREE(e_data.empty_image_wire_format); DRW_SHADER_FREE_SAFE(e_data.outline_resolve_sh); DRW_SHADER_FREE_SAFE(e_data.outline_resolve_aa_sh); DRW_SHADER_FREE_SAFE(e_data.outline_detect_sh); @@ -663,14 +671,16 @@ static void DRW_shgroup_empty_image( image_calc_aspect(ob->data, ob->iuser, empty_image_data->image_aspect); if (tex) { + DRW_shgroup_instance_format(e_data.empty_image_format, { + {"objectColor" , DRW_ATTRIB_FLOAT, 4}, + {"size" , DRW_ATTRIB_FLOAT, 1}, + {"offset" , DRW_ATTRIB_FLOAT, 2}, + {"InstanceModelMatrix" , DRW_ATTRIB_FLOAT, 16}, + }); + struct Gwn_Batch *geom = DRW_cache_image_plane_get(); DRWShadingGroup *grp = DRW_shgroup_instance_create( - e_data.object_empty_image_sh, psl->non_meshes, geom); - DRW_shgroup_attrib_float(grp, "objectColor", 4); - DRW_shgroup_attrib_float(grp, "size", 1); - DRW_shgroup_attrib_float(grp, "offset", 2); - DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); - + e_data.object_empty_image_sh, psl->non_meshes, geom, e_data.empty_image_format); DRW_shgroup_uniform_texture(grp, "image", tex); DRW_shgroup_uniform_vec2(grp, "aspect", empty_image_data->image_aspect, 1); @@ -681,14 +691,16 @@ static void DRW_shgroup_empty_image( } { + DRW_shgroup_instance_format(e_data.empty_image_wire_format, { + {"objectColor" , DRW_ATTRIB_FLOAT, 4}, + {"size" , DRW_ATTRIB_FLOAT, 1}, + {"offset" , DRW_ATTRIB_FLOAT, 2}, + {"InstanceModelMatrix" , DRW_ATTRIB_FLOAT, 16} + }); + struct Gwn_Batch *geom = DRW_cache_image_plane_wire_get(); DRWShadingGroup *grp = DRW_shgroup_instance_create( - e_data.object_empty_image_wire_sh, psl->non_meshes, geom); - DRW_shgroup_attrib_float(grp, "color", 3); - DRW_shgroup_attrib_float(grp, "size", 1); - DRW_shgroup_attrib_float(grp, "offset", 2); - DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); - + e_data.object_empty_image_wire_sh, psl->non_meshes, geom, e_data.empty_image_wire_format); DRW_shgroup_uniform_vec2(grp, "aspect", empty_image_data->image_aspect, 1); empty_image_data->shgrp_wire = grp; @@ -1533,7 +1545,8 @@ static void DRW_shgroup_lightprobe(OBJECT_StorageList *stl, OBJECT_PassList *psl mul_m4_v3(ob->obmat, prb_data->increment_z); sub_v3_v3(prb_data->increment_z, prb_data->corner); - DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.lightprobe_grid_sh, psl->lightprobes, DRW_cache_sphere_get()); + DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.lightprobe_grid_sh, psl->lightprobes, + DRW_cache_sphere_get(), NULL); DRW_shgroup_set_instance_count(grp, prb->grid_resolution_x * prb->grid_resolution_y * prb->grid_resolution_z); DRW_shgroup_uniform_vec4(grp, "color", color, 1); DRW_shgroup_uniform_vec3(grp, "corner", prb_data->corner, 1); @@ -1753,21 +1766,21 @@ static void OBJECT_cache_populate_particles(Object *ob, break; case PART_DRAW_CROSS: shgrp = DRW_shgroup_instance_create( - e_data.part_prim_sh, psl->particle, DRW_cache_particles_get_prim(PART_DRAW_CROSS)); + e_data.part_prim_sh, psl->particle, DRW_cache_particles_get_prim(PART_DRAW_CROSS), NULL); DRW_shgroup_uniform_texture(shgrp, "ramp", globals_ramp); DRW_shgroup_uniform_vec3(shgrp, "color", ma ? &ma->r : def_prim_col, 1); DRW_shgroup_uniform_int(shgrp, "screen_space", &screen_space[0], 1); break; case PART_DRAW_CIRC: shgrp = DRW_shgroup_instance_create( - e_data.part_prim_sh, psl->particle, DRW_cache_particles_get_prim(PART_DRAW_CIRC)); + e_data.part_prim_sh, psl->particle, DRW_cache_particles_get_prim(PART_DRAW_CIRC), NULL); DRW_shgroup_uniform_texture(shgrp, "ramp", globals_ramp); DRW_shgroup_uniform_vec3(shgrp, "color", ma ? &ma->r : def_prim_col, 1); DRW_shgroup_uniform_int(shgrp, "screen_space", &screen_space[1], 1); break; case PART_DRAW_AXIS: shgrp = DRW_shgroup_instance_create( - e_data.part_axis_sh, psl->particle, DRW_cache_particles_get_prim(PART_DRAW_AXIS)); + e_data.part_axis_sh, psl->particle, DRW_cache_particles_get_prim(PART_DRAW_AXIS), NULL); DRW_shgroup_uniform_int(shgrp, "screen_space", &screen_space[0], 1); break; default: |