diff --git a/source/blender/draw/intern/draw_command.cc b/source/blender/draw/intern/draw_command.cc index 06d503d0f2a..7da1a27d484 100644 --- a/source/blender/draw/intern/draw_command.cc +++ b/source/blender/draw/intern/draw_command.cc @@ -777,7 +777,7 @@ void DrawMultiBuf::bind(RecordingState &state, for (DrawGroup &group : MutableSpan(group_buf_.data(), group_count_)) { /* Compute prefix sum of all instance of previous group. */ group.start = resource_id_count_; - resource_id_count_ += group.len * view_len; + resource_id_count_ += group.len; int batch_vert_len, batch_vert_first, batch_base_index, batch_inst_len; /* Now that GPUBatches are guaranteed to be finished, extract their parameters. */ @@ -833,7 +833,7 @@ void DrawMultiBuf::bind(RecordingState &state, group_buf_.push_update(); prototype_buf_.push_update(); /* Allocate enough for the expansion pass. */ - resource_id_buf_.get_or_resize(resource_id_count_ * (use_custom_ids ? 2 : 1)); + resource_id_buf_.get_or_resize(resource_id_count_ * view_len * (use_custom_ids ? 2 : 1)); /* Two commands per group (inverted and non-inverted scale). */ command_buf_.get_or_resize(group_count_ * 2); @@ -842,6 +842,7 @@ void DrawMultiBuf::bind(RecordingState &state, GPU_shader_bind(shader); GPU_shader_uniform_1i(shader, "prototype_len", prototype_count_); GPU_shader_uniform_1i(shader, "visibility_word_per_draw", visibility_word_per_draw); + GPU_shader_uniform_1i(shader, "view_len", view_len); GPU_shader_uniform_1i(shader, "view_shift", log2_ceil_u(view_len)); GPU_shader_uniform_1b(shader, "use_custom_ids", use_custom_ids); GPU_storagebuf_bind(group_buf_, GPU_shader_get_ssbo_binding(shader, "group_buf")); diff --git a/source/blender/draw/intern/draw_command_shared.hh b/source/blender/draw/intern/draw_command_shared.hh index 64bb552bb2b..13f19805320 100644 --- a/source/blender/draw/intern/draw_command_shared.hh +++ b/source/blender/draw/intern/draw_command_shared.hh @@ -26,6 +26,12 @@ struct DrawGroup { /** Index of next #DrawGroup from the same header. */ uint next; + /** + * IMPORTANT: All the following 3 members do not take multi-view into account. + * They only count the number of input instances. The command generation shader must multiply + * them by view_len to get the correct indices for resource ids. + */ + /** Index of the first instances after sorting. */ uint start; /** Total number of instances (including inverted facing). Needed to issue the draw call. */ @@ -39,9 +45,11 @@ struct DrawGroup { /* Set to -1 if not an indexed draw. */ int base_index; - /** Atomic counters used during command sorting. */ - uint total_counter; + /** Atomic counters used during command sorting. GPU only. Reset on CPU. */ + /* Counts visible and invisble instances. Create drawcalls when it reaches `DrawGroup::len`. */ + uint total_counter; + /* Counts only visible instance (counting multi-view). Used to issue the drawcalls. */ uint front_facing_counter; uint back_facing_counter; diff --git a/source/blender/draw/intern/shaders/draw_command_generate_comp.glsl b/source/blender/draw/intern/shaders/draw_command_generate_comp.glsl index 29bc3d4e246..a2194f60d33 100644 --- a/source/blender/draw/intern/shaders/draw_command_generate_comp.glsl +++ b/source/blender/draw/intern/shaders/draw_command_generate_comp.glsl @@ -17,19 +17,21 @@ void write_draw_call(DrawGroup group, uint group_id) cmd.vertex_len = group.vertex_len; cmd.vertex_first = group.vertex_first; bool indexed_draw = group.base_index != -1; + + /* Back-facing command. */ + uint back_facing_start = group.start * view_len; if (indexed_draw) { cmd.base_index = group.base_index; - cmd.instance_first_indexed = group.start; + cmd.instance_first_indexed = back_facing_start; } else { - cmd._instance_first_array = group.start; + cmd._instance_first_array = back_facing_start; } - /* Back-facing command. */ cmd.instance_len = group_buf[group_id].back_facing_counter; command_buf[group_id * 2 + 0] = cmd; /* Front-facing command. */ - uint front_facing_start = group.start + (group.len - group.front_facing_len); + uint front_facing_start = (group.start + (group.len - group.front_facing_len)) * view_len; if (indexed_draw) { cmd.instance_first_indexed = front_facing_start; } @@ -85,9 +87,8 @@ void main() return; } - uint back_facing_len = group.len - group.front_facing_len; - uint front_facing_len = group.front_facing_len; - uint dst_index = group.start; + uint back_facing_len = (group.len - group.front_facing_len) * view_len; + uint dst_index = group.start * view_len; if (is_inverted) { uint offset = atomicAdd(group_buf[group_id].back_facing_counter, visible_instance_len); dst_index += offset; diff --git a/source/blender/draw/intern/shaders/draw_view_info.hh b/source/blender/draw/intern/shaders/draw_view_info.hh index ac9a5e5c696..018b4bf6e9b 100644 --- a/source/blender/draw/intern/shaders/draw_view_info.hh +++ b/source/blender/draw/intern/shaders/draw_view_info.hh @@ -230,6 +230,7 @@ GPU_SHADER_CREATE_INFO(draw_command_generate) .push_constant(Type::INT, "prototype_len") .push_constant(Type::INT, "visibility_word_per_draw") .push_constant(Type::INT, "view_shift") + .push_constant(Type::INT, "view_len") .push_constant(Type::BOOL, "use_custom_ids") .compute_source("draw_command_generate_comp.glsl");