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.
This commit is contained in:
Clément Foucault 2018-02-14 18:59:15 +01:00
parent 629a874817
commit 0ef981f603
9 changed files with 390 additions and 249 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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;
Gwn_VertFormat *format = MEM_callocN(sizeof(Gwn_VertFormat), "Gwn_VertFormat");
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_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_instance_create(
struct GPUMaterial *material, DRWPass *pass, Gwn_Batch *geom, Object *ob)
DRWShadingGroup *DRW_shgroup_material_create(
struct GPUMaterial *material, DRWPass *pass)
{
DRWShadingGroup *shgroup = DRW_shgroup_material_create(material, 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, Gwn_VertFormat *format)
{
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);

View File

@ -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: