Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2018-02-14 20:59:15 +0300
committerClément Foucault <foucault.clem@gmail.com>2018-02-14 20:59:42 +0300
commit0ef981f603a0d03a1b187995c91282c73ed50bd7 (patch)
tree0957ed900ee82ed6d2bfc3b6e9513cefc61fe50b /source
parent629a87481769d8886fcbe66ca4e4e4b60c767627 (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.
Diffstat (limited to 'source')
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c3
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c52
-rw-r--r--source/blender/draw/engines/eevee/eevee_lights.c8
-rw-r--r--source/blender/draw/engines/eevee/eevee_render.c3
-rw-r--r--source/blender/draw/intern/DRW_render.h28
-rw-r--r--source/blender/draw/intern/draw_common.c170
-rw-r--r--source/blender/draw/intern/draw_common.h1
-rw-r--r--source/blender/draw/intern/draw_manager.c327
-rw-r--r--source/blender/draw/modes/object_mode.c45
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: