[Bf-blender-cvs] [97b0719f7dc] tmp-workbench-rewrite2: WIP: Compute based culling for workbench shadows
Miguel Pozo
noreply at git.blender.org
Mon Dec 12 12:34:53 CET 2022
Commit: 97b0719f7dc10159ca45fabc54496647ff070e6f
Author: Miguel Pozo
Date: Mon Dec 12 12:33:50 2022 +0100
Branches: tmp-workbench-rewrite2
https://developer.blender.org/rB97b0719f7dc10159ca45fabc54496647ff070e6f
WIP: Compute based culling for workbench shadows
===================================================================
M source/blender/draw/engines/workbench/shaders/infos/workbench_shadow_info.hh
A source/blender/draw/engines/workbench/shaders/workbench_shadow_visibility_comp.glsl
M source/blender/draw/engines/workbench/workbench_shadow.cc
M source/blender/draw/intern/draw_view.hh
===================================================================
diff --git a/source/blender/draw/engines/workbench/shaders/infos/workbench_shadow_info.hh b/source/blender/draw/engines/workbench/shaders/infos/workbench_shadow_info.hh
index a77af467ec8..ad6b3560117 100644
--- a/source/blender/draw/engines/workbench/shaders/infos/workbench_shadow_info.hh
+++ b/source/blender/draw/engines/workbench/shaders/infos/workbench_shadow_info.hh
@@ -1,5 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
+#include "draw_defines.h"
+
#include "gpu_shader_create_info.hh"
/* -------------------------------------------------------------------- */
@@ -29,6 +31,20 @@ GPU_SHADER_CREATE_INFO(workbench_next_shadow_common)
.additional_info("draw_modelmat_new")
.additional_info("draw_resource_handle_new");
+GPU_SHADER_CREATE_INFO(workbench_next_shadow_visibility_compute)
+ .do_static_compilation(true)
+ .local_group_size(DRW_VISIBILITY_GROUP_SIZE)
+ .define("DRW_VIEW_LEN", "64")
+ .storage_buf(0, Qualifier::READ, "ObjectBounds", "bounds_buf[]")
+ .storage_buf(1, Qualifier::READ_WRITE, "uint", "visibility_buf[]")
+ .storage_buf(2, Qualifier::READ, "uint", "pass_technique_buf[]")
+ .push_constant(Type::INT, "resource_len")
+ .push_constant(Type::INT, "view_len")
+ .push_constant(Type::INT, "visibility_word_per_draw")
+ .push_constant(Type::VEC3, "shadow_direction")
+ .compute_source("draw_visibility_comp.glsl")
+ .additional_info("draw_view", "draw_view_culling");
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shadow_visibility_comp.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shadow_visibility_comp.glsl
new file mode 100644
index 00000000000..7e89120a79f
--- /dev/null
+++ b/source/blender/draw/engines/workbench/shaders/workbench_shadow_visibility_comp.glsl
@@ -0,0 +1,53 @@
+
+/**
+ * Compute visibility of each resource bounds for a given view.
+ */
+/* TODO(fclem): This could be augmented by a 2 pass occlusion culling system. */
+
+#pragma BLENDER_REQUIRE(common_math_lib.glsl)
+#pragma BLENDER_REQUIRE(common_intersect_lib.glsl)
+
+shared uint shared_result;
+
+void mask_visibility_bit(uint view_id)
+{
+ if (view_len > 1) {
+ uint index = gl_GlobalInvocationID.x * uint(visibility_word_per_draw) + (view_id / 32u);
+ visibility_buf[index] &= ~(1u << view_id);
+ }
+ else {
+ atomicAnd(visibility_buf[gl_WorkGroupID.x], ~(1u << gl_LocalInvocationID.x));
+ }
+}
+
+void main()
+{
+ if (gl_GlobalInvocationID.x >= resource_len) {
+ return;
+ }
+
+ ObjectBounds bounds = bounds_buf[gl_GlobalInvocationID.x];
+
+ if (bounds.bounding_sphere.w != -1.0) {
+ IsectBox box = isect_data_setup(bounds.bounding_corners[0].xyz,
+ bounds.bounding_corners[1].xyz,
+ bounds.bounding_corners[2].xyz,
+ bounds.bounding_corners[3].xyz);
+ Sphere bounding_sphere = Sphere(bounds.bounding_sphere.xyz, bounds.bounding_sphere.w);
+ Sphere inscribed_sphere = Sphere(bounds.bounding_sphere.xyz, bounds._inner_sphere_radius);
+
+ for (drw_view_id = 0; drw_view_id < view_len; drw_view_id++) {
+ if (intersect_view(inscribed_sphere) == true) {
+ /* Visible. */
+ }
+ else if (intersect_view(bounding_sphere) == false) {
+ /* Not visible. */
+ mask_visibility_bit(drw_view_id);
+ }
+ else if (intersect_view(box) == false) {
+ /* Not visible. */
+ mask_visibility_bit(drw_view_id);
+ }
+ }
+ }
+}
diff --git a/source/blender/draw/engines/workbench/workbench_shadow.cc b/source/blender/draw/engines/workbench/workbench_shadow.cc
index 3632cc54f5a..21d092eaba9 100644
--- a/source/blender/draw/engines/workbench/workbench_shadow.cc
+++ b/source/blender/draw/engines/workbench/workbench_shadow.cc
@@ -17,13 +17,117 @@
#include "BKE_object.h"
#include "BLI_math.h"
#include "DRW_render.h"
+#include "GPU_compute.h"
#include "workbench_private.hh"
+#include "draw_shader.h" //REMOVE!
+
#define DEBUG_SHADOW_VOLUME 0
+#define GPU_CULLING 0
namespace blender::workbench {
+class ShadowView : public View {
+ float3 direction_;
+
+ public:
+ ShadowView(const char *name, View &view, float3 direction) : View(name)
+ {
+ // TODO(Miguel Pozo): view_len_ ?
+ direction = direction_;
+ sync(view.viewmat(), view.winmat());
+ }
+
+ protected:
+ std::array<float3, 8> frustum_corners(float4x4 view_from_world_matrix, float near, float far)
+ {
+ float4x4 matrix = view_from_world_matrix.inverted();
+ std::array<float3, 8> corners = {};
+
+ int i = 0;
+ for (float x : {-1, 1}) {
+ for (float y : {-1, 1}) {
+ for (float z : {near, far}) {
+ float4 corner = float4(x, y, z, 1);
+ mul_m4_v4(matrix.ptr(), corner);
+ corner /= corner.w;
+ corners[i++] = float3(corner);
+ }
+ }
+ }
+
+ return corners;
+ }
+
+ float4x4 shadow_projection_matrix(float4x4 light_from_world_matrix,
+ float4x4 view_from_world_matrix,
+ float near,
+ float far)
+ {
+ /* WIP: Should be replaced with an extruded frustum */
+ float3 min, max;
+ INIT_MINMAX(min, max);
+
+ BoundBox frustum_corners;
+ DRW_culling_frustum_corners_get(nullptr, &frustum_corners);
+
+ for (float3 corner : frustum_corners.vec) {
+ corner = light_from_world_matrix * corner;
+ math::min_max(corner, min, max);
+ }
+
+ float4x4 world_from_light_space = light_from_world_matrix.inverted();
+
+ float3 size = max - min;
+ float3 scale = 1.0 / (size / 2.0);
+
+ float4x4 scale_matrix;
+ size_to_mat4(scale_matrix.ptr(), scale);
+
+ min = world_from_light_space * min;
+ max = world_from_light_space * max;
+ float3 center = (min + max) / 2.0;
+
+ float4x4 translate_matrix = float4x4::from_location(-center);
+
+ return scale_matrix * translate_matrix * light_from_world_matrix;
+ }
+
+ virtual void compute_visibility(ObjectBoundsBuf &bounds, uint resource_len, bool debug_freeze)
+ {
+ GPU_debug_group_begin("ShadowView.compute_visibility");
+
+ uint word_per_draw = this->visibility_word_per_draw();
+ /* Switch between tightly packed and set of whole word per instance. */
+ uint words_len = (view_len_ == 1) ? divide_ceil_u(resource_len, 32) :
+ resource_len * word_per_draw;
+ words_len = ceil_to_multiple_u(max_ii(1, words_len), 4);
+ /* TODO(fclem): Resize to nearest pow2 to reduce fragmentation. */
+ visibility_buf_.resize(words_len);
+
+ uint32_t data = 0xFFFFFFFFu;
+ GPU_storagebuf_clear(visibility_buf_, GPU_R32UI, GPU_DATA_UINT, &data);
+
+ if (do_visibility_) {
+ static GPUShader *shader = GPU_shader_create_from_info_name(
+ "workbench_next_shadow_visibility_compute");
+ GPU_shader_bind(shader);
+ GPU_shader_uniform_1i(shader, "resource_len", resource_len);
+ GPU_shader_uniform_1i(shader, "view_len", view_len_);
+ GPU_shader_uniform_1i(shader, "visibility_word_per_draw", word_per_draw);
+ GPU_shader_uniform_3fv(shader, "shadow_direction", direction_);
+ GPU_storagebuf_bind(bounds, GPU_shader_get_ssbo(shader, "bounds_buf"));
+ GPU_storagebuf_bind(visibility_buf_, GPU_shader_get_ssbo(shader, "visibility_buf"));
+ GPU_uniformbuf_bind(data_, DRW_VIEW_UBO_SLOT);
+ GPU_compute_dispatch(shader, divide_ceil_u(resource_len, DRW_VISIBILITY_GROUP_SIZE), 1, 1);
+ GPU_memory_barrier(GPU_BARRIER_SHADER_STORAGE);
+ }
+
+ GPU_debug_group_end();
+ }
+};
+
static void compute_parallel_lines_nor_and_dist(const float2 v1,
const float2 v2,
const float2 v3,
@@ -206,6 +310,18 @@ void ShadowPass::object_sync(Manager &manager,
return;
}
+#if GPU_CULLING
+ /* WIP: Everything is drawn with the Pass method */
+ PassMain::Sub &ps = *get_pass_ptr(true, is_manifold);
+ ps.push_constant("lightDirection", float4x4(ob->world_to_object).ref_3x3() * direction_ws);
+ ps.push_constant("lightDistance", 1e5f);
+ ResourceHandle handle = manager.resource_handle(ob_ref);
+ ps.draw(geom_shadow, handle);
+# if DEBUG_SHADOW_VOLUME
+ DRW_debug_bbox(&object_data.bbox, float4(1.0f, 0.0f, 0.0f, 1.0f));
+# endif
+#else
+
ObjectData *engine_object_data = (ObjectData *)DRW_drawdata_ensure(
&ob->id, &draw_engine_workbench_next, sizeof(ObjectData), &ObjectData::init, nullptr);
@@ -236,9 +352,9 @@ void ShadowPass::object_sync(Manager &manager,
ps.push_constant("lightDistance", 1e5f);
ResourceHandle handle = manager.resource_handle(ob_ref);
ps.draw(geom_shadow, handle);
-#if DEBUG_SHADOW_VOLUME
+# if DEBUG_SHADOW_VOLUME
DRW_debug_bbox(&object_data.bbox, float4(1.0f, 0.0f, 0.0f, 1.0f));
-#endif
+# endif
}
else {
float extrude_distance = object_data.shadow_distance(ob, *this);
@@ -258,11 +374,12 @@ void ShadowPass::object_sync(Manager &manager,
ps.push_constant("lightDistance", extrude_distance);
ResourceHandle handle = manager.resource_handle(ob_ref);
ps.draw(geom_shadow, handle);
-#if DEBUG_SHADOW_VOLUME
+# if DEBUG_SHADOW_VOLUME
DRW_debug_bbox(&object_data.bbox, float4(1.0f, 0.0f, 0.0f, 1.0f));
-#endif
+# endif
}
}
+#endif
}
void ShadowPass::draw(Manager &manager, View &view, SceneResources &resources, int2 resolution)
@@ -276,8 +393,15 @@ void ShadowPass::draw(Manager &manager, View &view, SceneResources &resources, i
GPU_ATTACHMENT_TEXTURE(resources.color_tx));
fb.bind();
+#if GPU_CULLING
+ ShadowView shadow_view = ShadowView("ShadowView", view, direction_ws);
+
+ manager.submit(pass_ps, shadow_view);
+ manager.submit(fail_ps, shadow_view);
+#else
manager.submit(pass_ps, view);
manager.submit(fail_ps, view);
+#endif
}
void ObjectShadowData::init()
diff --git a/source/blender/draw/intern/draw_view.hh b/source/blender/draw/intern/draw_view.hh
index 5c5f20df1c3..fb21be511ad 100644
--- a/source/blend
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list