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:
Diffstat (limited to 'source/blender/draw/intern/draw_command.cc')
-rw-r--r--source/blender/draw/intern/draw_command.cc128
1 files changed, 97 insertions, 31 deletions
diff --git a/source/blender/draw/intern/draw_command.cc b/source/blender/draw/intern/draw_command.cc
index fb1a8a8dc2a..453898f4e2d 100644
--- a/source/blender/draw/intern/draw_command.cc
+++ b/source/blender/draw/intern/draw_command.cc
@@ -70,6 +70,39 @@ void Draw::execute(RecordingState &state) const
GPU_batch_draw_advanced(batch, vertex_first, vertex_len, 0, instance_len);
}
+void DrawMulti::execute(RecordingState &state) const
+{
+ DrawMultiBuf::DrawCommandBuf &indirect_buf = multi_draw_buf->command_buf_;
+ DrawMultiBuf::DrawGroupBuf &groups = multi_draw_buf->group_buf_;
+
+ uint group_index = this->group_first;
+ while (group_index != (uint)-1) {
+ const DrawGroup &grp = groups[group_index];
+
+ /** IMPORTANT: We cannot use grp.gpu_batch here since it has been overriden by the atomic
+ * counters. Use the DrawMulti.batch instead. */
+
+ GPU_batch_set_shader(batch, state.shader);
+
+ constexpr intptr_t stride = sizeof(DrawCommand);
+ /* We have 2 indirect command reserved per draw group. */
+ intptr_t offset = stride * group_index * 2;
+
+ /* Draw negatively scaled geometry first. */
+ if (grp.len - grp.front_facing_len > 0) {
+ state.front_facing_set(false);
+ GPU_batch_draw_indirect(batch, indirect_buf, offset);
+ }
+
+ if (grp.front_facing_len > 0) {
+ state.front_facing_set(true);
+ GPU_batch_draw_indirect(batch, indirect_buf, offset + stride);
+ }
+
+ group_index = grp.next;
+ }
+}
+
void DrawIndirect::execute(RecordingState &state) const
{
state.front_facing_set(handle.has_inverted_handedness());
@@ -168,37 +201,6 @@ void StencilSet::execute() const
GPU_stencil_reference_set(reference);
}
-void DrawMulti::execute(RecordingState &state) const
-{
- DrawMultiBuf::DrawCommandBuf &indirect_buf = multi_draw_buf->command_buf_;
- DrawMultiBuf::DrawGroupBuf &groups = multi_draw_buf->group_buf_;
-
- uint group_index = this->group_first;
- while (group_index != (uint)-1) {
- const DrawGroup &grp = groups[group_index];
-
- GPU_batch_set_shader(grp.gpu_batch, state.shader);
-
- constexpr intptr_t stride = sizeof(DrawCommand);
- intptr_t offset = stride * grp.command_start;
-
- /* Draw negatively scaled geometry first. */
- uint back_facing_len = grp.command_len - grp.front_facing_len;
- if (back_facing_len > 0) {
- state.front_facing_set(false);
- GPU_batch_draw_indirect(grp.gpu_batch, indirect_buf, offset);
- offset += stride * back_facing_len;
- }
-
- if (grp.front_facing_len > 0) {
- state.front_facing_set(true);
- GPU_batch_draw_indirect(grp.gpu_batch, indirect_buf, offset);
- }
-
- group_index = grp.next;
- }
-}
-
/** \} */
/* -------------------------------------------------------------------- */
@@ -335,6 +337,70 @@ std::string Draw::serialize() const
")";
}
+std::string DrawMulti::serialize(std::string line_prefix) const
+{
+ DrawMultiBuf::DrawGroupBuf &groups = multi_draw_buf->group_buf_;
+
+ MutableSpan<DrawPrototype> prototypes(multi_draw_buf->prototype_buf_.data(),
+ multi_draw_buf->prototype_count_);
+
+ /* This emulates the GPU sorting but without the unstable draw order. */
+ std::sort(
+ prototypes.begin(), prototypes.end(), [](const DrawPrototype &a, const DrawPrototype &b) {
+ return (a.group_id < b.group_id) ||
+ (a.group_id == b.group_id && a.resource_handle > b.resource_handle);
+ });
+
+ /* Compute prefix sum to have correct offsets. */
+ uint prefix_sum = 0u;
+ for (DrawGroup &group : groups) {
+ group.start = prefix_sum;
+ prefix_sum += group.front_proto_len + group.back_proto_len;
+ }
+
+ std::stringstream ss;
+
+ uint group_len = 0;
+ uint group_index = this->group_first;
+ while (group_index != (uint)-1) {
+ const DrawGroup &grp = groups[group_index];
+
+ ss << std::endl << line_prefix << " .group(id=" << group_index << ", len=" << grp.len << ")";
+
+ intptr_t offset = grp.start;
+
+ if (grp.back_proto_len > 0) {
+ for (DrawPrototype &proto : prototypes.slice({offset, grp.back_proto_len})) {
+ // BLI_assert(proto.group_id == group_index);
+ ResourceHandle handle(proto.resource_handle);
+ // BLI_assert(handle.has_inverted_handedness());
+ ss << std::endl
+ << line_prefix << " .proto(instance_len=" << std::to_string(proto.instance_len)
+ << ", resource_id=" << std::to_string(handle.resource_index()) << ", back_face)";
+ }
+ offset += grp.back_proto_len;
+ }
+
+ if (grp.front_proto_len > 0) {
+ for (DrawPrototype &proto : prototypes.slice({offset, grp.front_proto_len})) {
+ // BLI_assert(proto.group_id == group_index);
+ ResourceHandle handle(proto.resource_handle);
+ // BLI_assert(!handle.has_inverted_handedness());
+ ss << std::endl
+ << line_prefix << " .proto(instance_len=" << std::to_string(proto.instance_len)
+ << ", resource_id=" << std::to_string(handle.resource_index()) << ", front_face)";
+ }
+ }
+
+ group_index = grp.next;
+ group_len++;
+ }
+
+ ss << std::endl;
+
+ return line_prefix + ".draw_multi(" + std::to_string(group_len) + ")" + ss.str();
+}
+
std::string DrawIndirect::serialize() const
{
return std::string(".draw_indirect()");