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_manager.cc')
-rw-r--r--source/blender/draw/intern/draw_manager.cc214
1 files changed, 214 insertions, 0 deletions
diff --git a/source/blender/draw/intern/draw_manager.cc b/source/blender/draw/intern/draw_manager.cc
new file mode 100644
index 00000000000..169d86b2ea1
--- /dev/null
+++ b/source/blender/draw/intern/draw_manager.cc
@@ -0,0 +1,214 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. */
+
+/** \file
+ * \ingroup draw
+ */
+
+#include "BKE_global.h"
+#include "GPU_compute.h"
+
+#include "draw_debug.hh"
+#include "draw_defines.h"
+#include "draw_manager.h"
+#include "draw_manager.hh"
+#include "draw_pass.hh"
+#include "draw_shader.h"
+
+namespace blender::draw {
+
+Manager::~Manager()
+{
+ for (GPUTexture *texture : acquired_textures) {
+ /* Decrease refcount and free if 0. */
+ GPU_texture_free(texture);
+ }
+}
+
+void Manager::begin_sync()
+{
+ /* TODO: This means the reference is kept until further redraw or manager tear-down. Instead,
+ * they should be released after each draw loop. But for now, mimics old DRW behavior. */
+ for (GPUTexture *texture : acquired_textures) {
+ /* Decrease refcount and free if 0. */
+ GPU_texture_free(texture);
+ }
+
+ acquired_textures.clear();
+
+#ifdef DEBUG
+ /* Detect uninitialized data. */
+ memset(matrix_buf.data(), 0xF0, resource_len_ * sizeof(*matrix_buf.data()));
+ memset(bounds_buf.data(), 0xF0, resource_len_ * sizeof(*bounds_buf.data()));
+ memset(infos_buf.data(), 0xF0, resource_len_ * sizeof(*infos_buf.data()));
+#endif
+ resource_len_ = 0;
+ attribute_len_ = 0;
+ /* TODO(fclem): Resize buffers if too big, but with an hysteresis threshold. */
+
+ object_active = DST.draw_ctx.obact;
+
+ /* Init the 0 resource. */
+ resource_handle(float4x4::identity());
+}
+
+void Manager::end_sync()
+{
+ GPU_debug_group_begin("Manager.end_sync");
+
+ matrix_buf.push_update();
+ bounds_buf.push_update();
+ infos_buf.push_update();
+ attributes_buf.push_update();
+ attributes_buf_legacy.push_update();
+
+ /* Useful for debugging the following resource finalize. But will trigger the drawing of the GPU
+ * debug draw/print buffers for every frame. Not nice for performance. */
+ // debug_bind();
+
+ /* Dispatch compute to finalize the resources on GPU. Save a bit of CPU time. */
+ uint thread_groups = divide_ceil_u(resource_len_, DRW_FINALIZE_GROUP_SIZE);
+ GPUShader *shader = DRW_shader_draw_resource_finalize_get();
+ GPU_shader_bind(shader);
+ GPU_shader_uniform_1i(shader, "resource_len", resource_len_);
+ GPU_storagebuf_bind(matrix_buf, GPU_shader_get_ssbo(shader, "matrix_buf"));
+ GPU_storagebuf_bind(bounds_buf, GPU_shader_get_ssbo(shader, "bounds_buf"));
+ GPU_storagebuf_bind(infos_buf, GPU_shader_get_ssbo(shader, "infos_buf"));
+ GPU_compute_dispatch(shader, thread_groups, 1, 1);
+ GPU_memory_barrier(GPU_BARRIER_SHADER_STORAGE);
+
+ GPU_debug_group_end();
+}
+
+void Manager::debug_bind()
+{
+#ifdef DEBUG
+ if (DST.debug == nullptr) {
+ return;
+ }
+ GPU_storagebuf_bind(drw_debug_gpu_draw_buf_get(), DRW_DEBUG_DRAW_SLOT);
+ GPU_storagebuf_bind(drw_debug_gpu_print_buf_get(), DRW_DEBUG_PRINT_SLOT);
+# ifndef DISABLE_DEBUG_SHADER_PRINT_BARRIER
+ /* Add a barrier to allow multiple shader writing to the same buffer. */
+ GPU_memory_barrier(GPU_BARRIER_SHADER_STORAGE);
+# endif
+#endif
+}
+
+void Manager::resource_bind()
+{
+ GPU_storagebuf_bind(matrix_buf, DRW_OBJ_MAT_SLOT);
+ GPU_storagebuf_bind(infos_buf, DRW_OBJ_INFOS_SLOT);
+ GPU_storagebuf_bind(attributes_buf, DRW_OBJ_ATTR_SLOT);
+ /* 2 is the hardcoded location of the uniform attr UBO. */
+ /* TODO(@fclem): Remove this workaround. */
+ GPU_uniformbuf_bind(attributes_buf_legacy, 2);
+}
+
+void Manager::submit(PassSimple &pass, View &view)
+{
+ view.bind();
+
+ debug_bind();
+
+ command::RecordingState state;
+ state.inverted_view = view.is_inverted();
+
+ pass.draw_commands_buf_.bind(state, pass.headers_, pass.commands_);
+
+ resource_bind();
+
+ pass.submit(state);
+
+ state.cleanup();
+}
+
+void Manager::submit(PassMain &pass, View &view)
+{
+ view.bind();
+
+ debug_bind();
+
+ bool freeze_culling = (U.experimental.use_viewport_debug && DST.draw_ctx.v3d &&
+ (DST.draw_ctx.v3d->debug_flag & V3D_DEBUG_FREEZE_CULLING) != 0);
+
+ view.compute_visibility(bounds_buf, resource_len_, freeze_culling);
+
+ command::RecordingState state;
+ state.inverted_view = view.is_inverted();
+
+ pass.draw_commands_buf_.bind(state, pass.headers_, pass.commands_, view.visibility_buf_);
+
+ resource_bind();
+
+ pass.submit(state);
+
+ state.cleanup();
+}
+
+void Manager::submit(PassSortable &pass, View &view)
+{
+ pass.sort();
+
+ this->submit(static_cast<PassMain &>(pass), view);
+}
+
+void Manager::submit(PassSimple &pass)
+{
+ debug_bind();
+
+ command::RecordingState state;
+
+ pass.draw_commands_buf_.bind(state, pass.headers_, pass.commands_);
+
+ resource_bind();
+
+ pass.submit(state);
+
+ state.cleanup();
+}
+
+Manager::SubmitDebugOutput Manager::submit_debug(PassSimple &pass, View &view)
+{
+ submit(pass, view);
+
+ pass.draw_commands_buf_.resource_id_buf_.read();
+
+ Manager::SubmitDebugOutput output;
+ output.resource_id = {pass.draw_commands_buf_.resource_id_buf_.data(),
+ pass.draw_commands_buf_.resource_id_count_};
+ /* There is no visibility data for PassSimple. */
+ output.visibility = {(uint *)view.visibility_buf_.data(), 0};
+ return output;
+}
+
+Manager::SubmitDebugOutput Manager::submit_debug(PassMain &pass, View &view)
+{
+ submit(pass, view);
+
+ GPU_finish();
+
+ pass.draw_commands_buf_.resource_id_buf_.read();
+ view.visibility_buf_.read();
+
+ Manager::SubmitDebugOutput output;
+ output.resource_id = {pass.draw_commands_buf_.resource_id_buf_.data(),
+ pass.draw_commands_buf_.resource_id_count_};
+ output.visibility = {(uint *)view.visibility_buf_.data(), divide_ceil_u(resource_len_, 32)};
+ return output;
+}
+
+Manager::DataDebugOutput Manager::data_debug()
+{
+ matrix_buf.read();
+ bounds_buf.read();
+ infos_buf.read();
+
+ Manager::DataDebugOutput output;
+ output.matrices = {matrix_buf.data(), resource_len_};
+ output.bounds = {bounds_buf.data(), resource_len_};
+ output.infos = {infos_buf.data(), resource_len_};
+ return output;
+}
+
+} // namespace blender::draw