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
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2022-08-25 12:08:40 +0300
committerClément Foucault <foucault.clem@gmail.com>2022-08-25 12:08:45 +0300
commit92827491c4d9305ed65a7b19d3e0f25734019dac (patch)
tree43f48d61a105f3d596b05f4a3f60449f56d6eafd
parente8fddb326ea7731d1e3b9af70f5372ac932c5a38 (diff)
Add GPU command creation
-rw-r--r--source/blender/draw/CMakeLists.txt2
-rw-r--r--source/blender/draw/intern/draw_command.hh12
-rw-r--r--source/blender/draw/intern/draw_command_shared.hh5
-rw-r--r--source/blender/draw/intern/draw_defines.h3
-rw-r--r--source/blender/draw/intern/draw_shader.cc10
-rw-r--r--source/blender/draw/intern/draw_shader.h1
-rw-r--r--source/blender/draw/intern/shaders/draw_command_generate_comp.glsl84
-rw-r--r--source/blender/draw/intern/shaders/draw_view_info.hh13
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");
+
/** \} */
/* -------------------------------------------------------------------- */