diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2022-07-30 14:30:59 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2022-08-02 22:53:17 +0300 |
commit | 9a52f1f72035ffdd40ef56e938dcb540086b3463 (patch) | |
tree | a06dbeba65275b2b2b9f2b4e08dd529e0a89752f | |
parent | 710609a2e0d7ef63711940f746392b30dd8bbc7b (diff) |
DRW: Add DRW_shgroup_call_procedural_triangles_indirect
Just like the name suggest, this adds a way to draw a series of proceduraly
positioned triangles using and indirect buffer.
-rw-r--r-- | source/blender/draw/intern/DRW_render.h | 3 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager.h | 10 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager_data.c | 24 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager_exec.c | 29 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_shader_shared.h | 33 |
5 files changed, 97 insertions, 2 deletions
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index c2d26badc4c..701b395e0d7 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -454,6 +454,9 @@ void DRW_shgroup_call_compute_indirect(DRWShadingGroup *shgroup, GPUStorageBuf * void DRW_shgroup_call_procedural_points(DRWShadingGroup *sh, Object *ob, uint point_count); void DRW_shgroup_call_procedural_lines(DRWShadingGroup *sh, Object *ob, uint line_count); void DRW_shgroup_call_procedural_triangles(DRWShadingGroup *sh, Object *ob, uint tri_count); +void DRW_shgroup_call_procedural_triangles_indirect(DRWShadingGroup *shgroup, + Object *ob, + GPUStorageBuf *indirect_buf); /** * \warning Only use with Shaders that have `IN_PLACE_INSTANCES` defined. * TODO: Should be removed. diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h index 419b13edf1f..9e28169dcc4 100644 --- a/source/blender/draw/intern/draw_manager.h +++ b/source/blender/draw/intern/draw_manager.h @@ -188,6 +188,7 @@ typedef enum { DRW_CMD_DRAW_INSTANCE = 2, DRW_CMD_DRAW_INSTANCE_RANGE = 3, DRW_CMD_DRAW_PROCEDURAL = 4, + DRW_CMD_DRAW_INDIRECT = 5, /* Compute Commands. */ DRW_CMD_COMPUTE = 8, @@ -203,7 +204,7 @@ typedef enum { /* Needs to fit in 4bits */ } eDRWCommandType; -#define DRW_MAX_DRAW_CMD_TYPE DRW_CMD_DRAW_PROCEDURAL +#define DRW_MAX_DRAW_CMD_TYPE DRW_CMD_DRAW_INDIRECT typedef struct DRWCommandDraw { GPUBatch *batch; @@ -232,6 +233,12 @@ typedef struct DRWCommandDrawInstanceRange { uint inst_count; } DRWCommandDrawInstanceRange; +typedef struct DRWCommandDrawIndirect { + GPUBatch *batch; + DRWResourceHandle handle; + GPUStorageBuf *indirect_buf; +} DRWCommandDrawIndirect; + typedef struct DRWCommandCompute { int groups_x_len; int groups_y_len; @@ -286,6 +293,7 @@ typedef union DRWCommand { DRWCommandDrawInstance instance; DRWCommandDrawInstanceRange instance_range; DRWCommandDrawProcedural procedural; + DRWCommandDrawIndirect draw_indirect; DRWCommandCompute compute; DRWCommandComputeRef compute_ref; DRWCommandComputeIndirect compute_indirect; diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index 188d9114cd7..0535273d144 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -878,6 +878,17 @@ static void drw_command_draw_procedural(DRWShadingGroup *shgroup, cmd->vert_count = vert_count; } +static void drw_command_draw_indirect(DRWShadingGroup *shgroup, + GPUBatch *batch, + DRWResourceHandle handle, + GPUStorageBuf *indirect_buf) +{ + DRWCommandDrawIndirect *cmd = drw_command_create(shgroup, DRW_CMD_DRAW_INDIRECT); + cmd->batch = batch; + cmd->handle = handle; + cmd->indirect_buf = indirect_buf; +} + static void drw_command_set_select_id(DRWShadingGroup *shgroup, GPUVertBuf *buf, uint select_id) { /* Only one can be valid. */ @@ -1005,6 +1016,7 @@ void DRW_shgroup_call_compute_indirect(DRWShadingGroup *shgroup, GPUStorageBuf * drw_command_compute_indirect(shgroup, indirect_buf); } + void DRW_shgroup_barrier(DRWShadingGroup *shgroup, eGPUBarrier type) { BLI_assert(GPU_compute_shader_support()); @@ -1044,6 +1056,18 @@ void DRW_shgroup_call_procedural_triangles(DRWShadingGroup *shgroup, Object *ob, drw_shgroup_call_procedural_add_ex(shgroup, geom, ob, tri_count * 3); } +void DRW_shgroup_call_procedural_triangles_indirect(DRWShadingGroup *shgroup, + Object *ob, + GPUStorageBuf *indirect_buf) +{ + struct GPUBatch *geom = drw_cache_procedural_triangles_get(); + if (G.f & G_FLAG_PICKSEL) { + drw_command_set_select_id(shgroup, NULL, DST.select_id); + } + DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : NULL, ob); + drw_command_draw_indirect(shgroup, geom, handle, indirect_buf); +} + void DRW_shgroup_call_instances(DRWShadingGroup *shgroup, Object *ob, struct GPUBatch *geom, diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index e7e0e0ce41f..03c68ee532f 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -874,6 +874,25 @@ static void draw_call_single_do(DRWShadingGroup *shgroup, state->baseinst_loc); } +/* Not to be mistaken with draw_indirect_call which does batch many drawcalls together. This one + * only execute an indirect drawcall with user indirect buffer. */ +static void draw_call_indirect(DRWShadingGroup *shgroup, + DRWCommandsState *state, + GPUBatch *batch, + DRWResourceHandle handle, + GPUStorageBuf *indirect_buf) +{ + draw_call_batching_flush(shgroup, state); + draw_call_resource_bind(state, &handle); + + if (G.f & G_FLAG_PICKSEL) { + GPU_select_load_id(state->select_id); + } + + GPU_batch_set_shader(batch, shgroup->shader); + GPU_batch_draw_indirect(batch, indirect_buf); +} + static void draw_call_batching_start(DRWCommandsState *state) { state->neg_scale = false; @@ -996,12 +1015,13 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) while ((cmd = draw_command_iter_step(&iter, &cmd_type))) { switch (cmd_type) { + case DRW_CMD_DRAW_PROCEDURAL: case DRW_CMD_DRWSTATE: case DRW_CMD_STENCIL: draw_call_batching_flush(shgroup, &state); break; case DRW_CMD_DRAW: - case DRW_CMD_DRAW_PROCEDURAL: + case DRW_CMD_DRAW_INDIRECT: case DRW_CMD_DRAW_INSTANCE: if (draw_call_is_culled(&cmd->instance.handle, DST.view_active)) { continue; @@ -1055,6 +1075,13 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) 1, true); break; + case DRW_CMD_DRAW_INDIRECT: + draw_call_indirect(shgroup, + &state, + cmd->draw_indirect.batch, + cmd->draw_indirect.handle, + cmd->draw_indirect.indirect_buf); + break; case DRW_CMD_DRAW_INSTANCE: draw_call_single_do(shgroup, &state, diff --git a/source/blender/draw/intern/draw_shader_shared.h b/source/blender/draw/intern/draw_shader_shared.h index 266db22a84f..fbcc78e52f9 100644 --- a/source/blender/draw/intern/draw_shader_shared.h +++ b/source/blender/draw/intern/draw_shader_shared.h @@ -11,6 +11,9 @@ typedef struct ObjectMatrices ObjectMatrices; typedef struct ObjectInfos ObjectInfos; typedef struct VolumeInfos VolumeInfos; typedef struct CurvesInfos CurvesInfos; +typedef struct DrawCommand DrawCommand; +typedef struct DrawCommandIndexed DrawCommandIndexed; +typedef struct DispatchCommand DispatchCommand; #endif #define DRW_SHADER_SHARED_H @@ -98,3 +101,33 @@ BLI_STATIC_ASSERT_ALIGN(CurvesInfos, 16) #define OrcoTexCoFactors (drw_infos[resource_id].drw_OrcoTexCoFactors) #define ObjectInfo (drw_infos[resource_id].drw_Infos) #define ObjectColor (drw_infos[resource_id].drw_ObjectColor) + +/* Indirect commands structures. */ + +struct DrawCommand { + uint v_count; + uint i_count; + uint v_first; + uint i_first; +}; +BLI_STATIC_ASSERT_ALIGN(DrawCommand, 16) + +struct DrawCommandIndexed { + uint v_count; + uint i_count; + uint v_first; + uint base_index; + uint i_first; + uint _pad0; + uint _pad1; + uint _pad2; +}; +BLI_STATIC_ASSERT_ALIGN(DrawCommandIndexed, 16) + +struct DispatchCommand { + uint num_groups_x; + uint num_groups_y; + uint num_groups_z; + uint _pad0; +}; +BLI_STATIC_ASSERT_ALIGN(DispatchCommand, 16) |