diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2022-08-25 12:08:40 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2022-08-25 12:08:45 +0300 |
commit | 92827491c4d9305ed65a7b19d3e0f25734019dac (patch) | |
tree | 43f48d61a105f3d596b05f4a3f60449f56d6eafd | |
parent | e8fddb326ea7731d1e3b9af70f5372ac932c5a38 (diff) |
Add GPU command creation
-rw-r--r-- | source/blender/draw/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_command.hh | 12 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_command_shared.hh | 5 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_defines.h | 3 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_shader.cc | 10 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_shader.h | 1 | ||||
-rw-r--r-- | source/blender/draw/intern/shaders/draw_command_generate_comp.glsl | 84 | ||||
-rw-r--r-- | source/blender/draw/intern/shaders/draw_view_info.hh | 13 |
8 files changed, 122 insertions, 8 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 377baeb8361..d0735540068 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -487,6 +487,7 @@ set(GLSL_SRC intern/shaders/common_subdiv_vbo_sculpt_data_comp.glsl intern/shaders/common_view_clipping_lib.glsl intern/shaders/common_view_lib.glsl + intern/shaders/draw_command_generate_comp.glsl intern/shaders/draw_debug_draw_display_frag.glsl intern/shaders/draw_debug_draw_display_vert.glsl intern/shaders/draw_debug_info.hh @@ -496,6 +497,7 @@ set(GLSL_SRC intern/shaders/draw_visibility_comp.glsl intern/draw_common_shader_shared.h + intern/draw_command_shared.hh intern/draw_shader_shared.h intern/draw_defines.h diff --git a/source/blender/draw/intern/draw_command.hh b/source/blender/draw/intern/draw_command.hh index 39c66d2ad6f..a73d35e48bf 100644 --- a/source/blender/draw/intern/draw_command.hh +++ b/source/blender/draw/intern/draw_command.hh @@ -529,16 +529,16 @@ class DrawMultiBuf { void bind(Vector<Header> &, Vector<Undetermined> &, ResourceIdBuf &resource_id_buf) { - uint prefix_sum = 0u; + uint instance_sum = 0u; for (DrawGroup &group : group_buf_) { /* Compute prefix sum of all instance of previous group. */ - group.start = prefix_sum; - prefix_sum += group.len; + group.start = instance_sum; + instance_sum += group.len; int batch_inst_len; /* Now that GPUBatches are guaranteed to be finished, extract their parameters. */ GPU_batch_draw_parameter_get(group.gpu_batch, &group.vertex_len, &batch_inst_len); - /* Tag group as using index draw (changes indirect drawcall structure). */ + /* Tag group as using index draw (changes indirect draw call structure). */ if (group.gpu_batch->elem != nullptr) { group.vertex_len = -group.vertex_len; } @@ -552,8 +552,10 @@ class DrawMultiBuf { } group_buf_.push_update(); + prototype_buf_.push_update(); /* Allocate enough for the expansion pass. */ - resource_id_buf.get_or_resize(prefix_sum); + resource_id_buf.get_or_resize(instance_sum); + command_buf_.get_or_resize(group_count_); // GPU_compute_dispatch(resource_id_expand_shader, n, 1, 1); } diff --git a/source/blender/draw/intern/draw_command_shared.hh b/source/blender/draw/intern/draw_command_shared.hh index f73e38cb8cc..afd3e06deb7 100644 --- a/source/blender/draw/intern/draw_command_shared.hh +++ b/source/blender/draw/intern/draw_command_shared.hh @@ -49,15 +49,15 @@ struct DrawGroup { /** GPUBatch values to be copied to DrawCommand after sorting (if not overriden). */ int vertex_len; /** NOTE: Negative if using indexed draw. */ /** Atomic counters used during command sorting. */ - uint total_counter; uint front_facing_counter; uint back_facing_counter; + uint total_counter; #ifndef GPU_SHADER }; }; #endif }; -BLI_STATIC_ASSERT(sizeof(DrawGroup) == 32, "DrawGroup might not have the same size on GPU and CPU") +BLI_STATIC_ASSERT_ALIGN(DrawGroup, 16) /** * Representation of a future draw call inside a DrawGroup. This #DrawPrototype is then @@ -73,6 +73,7 @@ struct DrawPrototype { uint instance_len; uint _pad0; }; +BLI_STATIC_ASSERT_ALIGN(DrawPrototype, 16) /** \} */ diff --git a/source/blender/draw/intern/draw_defines.h b/source/blender/draw/intern/draw_defines.h index a8731dedaf8..2769f5f71d1 100644 --- a/source/blender/draw/intern/draw_defines.h +++ b/source/blender/draw/intern/draw_defines.h @@ -18,6 +18,7 @@ #define DRW_OBJ_INFOS_SLOT 5 #define DRW_OBJ_ATTR_SLOT 4 +#define DRW_COMMAND_GROUP_SIZE 64 #define DRW_FINALIZE_GROUP_SIZE 64 /* Must be multiple of 32. Set to 64 for optimal scheduling on GCN hardware. */ -#define DRW_VISIBILITY_GROUP_SIZE 64
\ No newline at end of file +#define DRW_VISIBILITY_GROUP_SIZE 64 diff --git a/source/blender/draw/intern/draw_shader.cc b/source/blender/draw/intern/draw_shader.cc index 24ecd4efe00..960348b4a94 100644 --- a/source/blender/draw/intern/draw_shader.cc +++ b/source/blender/draw/intern/draw_shader.cc @@ -25,6 +25,7 @@ static struct { struct GPUShader *debug_draw_display_sh; struct GPUShader *draw_visibility_compute_sh; struct GPUShader *draw_resource_finalize_sh; + struct GPUShader *draw_command_generate_sh; } e_data = {{nullptr}}; /* -------------------------------------------------------------------- */ @@ -143,6 +144,14 @@ GPUShader *DRW_shader_draw_resource_finalize_get() return e_data.draw_resource_finalize_sh; } +GPUShader *DRW_shader_draw_command_generate_get() +{ + if (e_data.draw_command_generate_sh == nullptr) { + e_data.draw_command_generate_sh = GPU_shader_create_from_info_name("draw_command_generate"); + } + return e_data.draw_command_generate_sh; +} + /** \} */ void DRW_shaders_free() @@ -154,4 +163,5 @@ void DRW_shaders_free() DRW_SHADER_FREE_SAFE(e_data.debug_draw_display_sh); DRW_SHADER_FREE_SAFE(e_data.draw_visibility_compute_sh); DRW_SHADER_FREE_SAFE(e_data.draw_resource_finalize_sh); + DRW_SHADER_FREE_SAFE(e_data.draw_command_generate_sh); } diff --git a/source/blender/draw/intern/draw_shader.h b/source/blender/draw/intern/draw_shader.h index 77c3410eb98..3b8c0425fa9 100644 --- a/source/blender/draw/intern/draw_shader.h +++ b/source/blender/draw/intern/draw_shader.h @@ -34,6 +34,7 @@ struct GPUShader *DRW_shader_debug_print_display_get(void); struct GPUShader *DRW_shader_debug_draw_display_get(void); struct GPUShader *DRW_shader_draw_visibility_compute_get(void); struct GPUShader *DRW_shader_draw_resource_finalize_get(void); +struct GPUShader *DRW_shader_draw_command_generate_get(void); void DRW_shaders_free(void); diff --git a/source/blender/draw/intern/shaders/draw_command_generate_comp.glsl b/source/blender/draw/intern/shaders/draw_command_generate_comp.glsl new file mode 100644 index 00000000000..2c736996d60 --- /dev/null +++ b/source/blender/draw/intern/shaders/draw_command_generate_comp.glsl @@ -0,0 +1,84 @@ + +/** + * Convert DrawPrototype into draw commands. + */ + +#pragma BLENDER_REQUIRE(common_math_lib.glsl) + +#define atomicAddAndGet(dst, val) (atomicAdd(dst, val) + val) + +/* This is only called by the last thread executed over the group's prototype draws. */ +void write_draw_call(DrawGroup group, uint group_id) +{ + DrawCommand cmd; + cmd.vertex_len = abs(group.vertex_len); + cmd.vertex_first = 0; + if (group.vertex_len < 0) { + cmd.base_index = 0; + cmd.instance_first_indexed = group.start; + } + else { + cmd._instance_first_array = group.start; + } + /* Back-facing command. */ + cmd.instance_len = group_buf[group_id].back_facing_counter; + command_buf[group_id * 2 + 0] = cmd; + /* Front-facing command. */ + cmd.instance_len = group_buf[group_id].front_facing_counter; + command_buf[group_id * 2 + 1] = cmd; + + /* Reset the counters for a next command gen dispatch. Avoids resending the whole data just + * for this purpose. Only the last thread will execute this so it is threadsafe. */ + group_buf[group_id].front_facing_counter = 0u; + group_buf[group_id].back_facing_counter = 0u; + group_buf[group_id].total_counter = 0u; +} + +void main() +{ + uint proto_id = gl_GlobalInvocationID.x; + if (proto_id >= prototype_len) { + return; + } + + DrawPrototype proto = prototype_buf[proto_id]; + uint group_id = proto.group_id; + bool is_inverted = (proto.resource_handle & 0x80000000u) != 0; + uint resource_index = (proto.resource_handle & 0x7FFFFFFFu); + + /* Visibility test result. */ + bool is_visible = ((visibility_buf[resource_index / 32u] & (1u << (resource_index % 32u)))) != 0; + + DrawGroup group = group_buf[group_id]; + + if (!is_visible || proto.instance_len == 0) { + /* Skip the draw but still count towards the completion. */ + if (atomicAddAndGet(group_buf[group_id].total_counter, proto.instance_len) == group.len) { + write_draw_call(group, group_id); + } + return; + } + + uint back_facing_len = group.len - group.front_facing_len; + uint front_facing_len = group.front_facing_len; + uint dst_index = group.start; + if (is_inverted) { + uint offset = atomicAdd(group_buf[group_id].back_facing_counter, proto.instance_len); + dst_index += offset; + if (atomicAddAndGet(group_buf[group_id].total_counter, proto.instance_len) == group.len) { + write_draw_call(group, group_id); + } + } + else { + uint offset = atomicAdd(group_buf[group_id].front_facing_counter, proto.instance_len); + dst_index += back_facing_len + offset; + if (atomicAddAndGet(group_buf[group_id].total_counter, proto.instance_len) == group.len) { + write_draw_call(group, group_id); + } + } + + for (uint i = dst_index; i < dst_index + proto.instance_len; i++) { + /* Fill resource_id buffer for each instance of this draw */ + resource_id_buf[i] = resource_index; + } +}
\ No newline at end of file diff --git a/source/blender/draw/intern/shaders/draw_view_info.hh b/source/blender/draw/intern/shaders/draw_view_info.hh index 6149812a644..e2c6a806ac2 100644 --- a/source/blender/draw/intern/shaders/draw_view_info.hh +++ b/source/blender/draw/intern/shaders/draw_view_info.hh @@ -162,6 +162,19 @@ GPU_SHADER_CREATE_INFO(draw_visibility_compute) .compute_source("draw_visibility_comp.glsl") .additional_info("draw_view"); +GPU_SHADER_CREATE_INFO(draw_command_generate) + .do_static_compilation(true) + .typedef_source("draw_shader_shared.h") + .typedef_source("draw_command_shared.hh") + .local_group_size(DRW_COMMAND_GROUP_SIZE) + .storage_buf(0, Qualifier::READ_WRITE, "DrawGroup", "group_buf[]") + .storage_buf(1, Qualifier::READ, "DrawPrototype", "prototype_buf[]") + .storage_buf(2, Qualifier::WRITE, "DrawCommand", "command_buf[]") + .storage_buf(3, Qualifier::WRITE, "uint", "resource_id_buf[]") + .storage_buf(4, Qualifier::READ, "uint", "visibility_buf[]") + .push_constant(Type::UINT, "prototype_len") + .compute_source("draw_command_generate_comp.glsl"); + /** \} */ /* -------------------------------------------------------------------- */ |