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:
-rw-r--r--source/blender/draw/CMakeLists.txt2
-rw-r--r--source/blender/draw/engines/eevee/eevee_shader.cc4
-rw-r--r--source/blender/draw/engines/eevee/eevee_shader.hh2
-rw-r--r--source/blender/draw/engines/eevee/eevee_shader_shared.hh11
-rw-r--r--source/blender/draw/engines/eevee/eevee_shadow.cc67
-rw-r--r--source/blender/draw/engines/eevee/eevee_shadow.hh9
-rw-r--r--source/blender/draw/engines/eevee/shaders/eevee_shadow_debug_frag.glsl42
-rw-r--r--source/blender/draw/engines/eevee/shaders/eevee_shadow_lib.glsl7
-rw-r--r--source/blender/draw/engines/eevee/shaders/eevee_shadow_page_alloc_comp.glsl67
-rw-r--r--source/blender/draw/engines/eevee/shaders/eevee_shadow_page_debug_comp.glsl113
-rw-r--r--source/blender/draw/engines/eevee/shaders/eevee_shadow_page_defrag_comp.glsl59
-rw-r--r--source/blender/draw/engines/eevee/shaders/eevee_shadow_page_free_comp.glsl50
-rw-r--r--source/blender/draw/engines/eevee/shaders/eevee_shadow_page_init_comp.glsl41
-rw-r--r--source/blender/draw/engines/eevee/shaders/eevee_shadow_page_lib.glsl38
-rw-r--r--source/blender/draw/engines/eevee/shaders/eevee_shadow_tilemap_depth_scan_comp.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/eevee_shadow_tilemap_lib.glsl26
-rw-r--r--source/blender/draw/engines/eevee/shaders/eevee_shadow_tilemap_setup_comp.glsl38
-rw-r--r--source/blender/draw/intern/draw_manager_data.c1
-rw-r--r--source/blender/draw/intern/shaders/common_math_lib.glsl10
19 files changed, 386 insertions, 203 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index cb25a459534..8d27a492156 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -334,6 +334,8 @@ data_to_c_simple(engines/eevee/shaders/eevee_shadow_debug_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/eevee_shadow_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/eevee_shadow_page_alloc_comp.glsl SRC)
data_to_c_simple(engines/eevee/shaders/eevee_shadow_page_copy_comp.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/eevee_shadow_page_debug_comp.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/eevee_shadow_page_defrag_comp.glsl SRC)
data_to_c_simple(engines/eevee/shaders/eevee_shadow_page_free_comp.glsl SRC)
data_to_c_simple(engines/eevee/shaders/eevee_shadow_page_init_comp.glsl SRC)
data_to_c_simple(engines/eevee/shaders/eevee_shadow_page_lib.glsl SRC)
diff --git a/source/blender/draw/engines/eevee/eevee_shader.cc b/source/blender/draw/engines/eevee/eevee_shader.cc
index 6585b3c48b3..e04e3d0bd21 100644
--- a/source/blender/draw/engines/eevee/eevee_shader.cc
+++ b/source/blender/draw/engines/eevee/eevee_shader.cc
@@ -117,6 +117,8 @@ extern char datatoc_eevee_shadow_debug_frag_glsl[];
extern char datatoc_eevee_shadow_lib_glsl[];
extern char datatoc_eevee_shadow_page_alloc_comp_glsl[];
extern char datatoc_eevee_shadow_page_copy_comp_glsl[];
+extern char datatoc_eevee_shadow_page_debug_comp_glsl[];
+extern char datatoc_eevee_shadow_page_defrag_comp_glsl[];
extern char datatoc_eevee_shadow_page_free_comp_glsl[];
extern char datatoc_eevee_shadow_page_init_comp_glsl[];
extern char datatoc_eevee_shadow_page_lib_glsl[];
@@ -398,6 +400,8 @@ ShaderModule::ShaderModule()
SHADER_FULLSCREEN(SHADOW_DEBUG, eevee_shadow_debug_frag);
SHADER_COMPUTE(SHADOW_PAGE_ALLOC, eevee_shadow_page_alloc_comp, nullptr);
SHADER_COMPUTE(SHADOW_PAGE_COPY, eevee_shadow_page_copy_comp, nullptr);
+ SHADER_COMPUTE(SHADOW_PAGE_DEBUG, eevee_shadow_page_debug_comp, nullptr);
+ SHADER_COMPUTE(SHADOW_PAGE_DEFRAG, eevee_shadow_page_defrag_comp, nullptr);
SHADER_COMPUTE(SHADOW_PAGE_FREE, eevee_shadow_page_free_comp, nullptr);
SHADER_COMPUTE(SHADOW_PAGE_INIT, eevee_shadow_page_init_comp, nullptr);
SHADER(SHADOW_PAGE_MARK, eevee_shadow_page_mark_vert, nullptr, eevee_depth_clear_frag, nullptr);
diff --git a/source/blender/draw/engines/eevee/eevee_shader.hh b/source/blender/draw/engines/eevee/eevee_shader.hh
index 49193a63322..ec7601b97c9 100644
--- a/source/blender/draw/engines/eevee/eevee_shader.hh
+++ b/source/blender/draw/engines/eevee/eevee_shader.hh
@@ -112,6 +112,8 @@ enum eShaderType {
SHADOW_DEBUG,
SHADOW_PAGE_ALLOC,
SHADOW_PAGE_COPY,
+ SHADOW_PAGE_DEBUG,
+ SHADOW_PAGE_DEFRAG,
SHADOW_PAGE_FREE,
SHADOW_PAGE_INIT,
SHADOW_PAGE_MARK,
diff --git a/source/blender/draw/engines/eevee/eevee_shader_shared.hh b/source/blender/draw/engines/eevee/eevee_shader_shared.hh
index cc5a52ea545..746087ad232 100644
--- a/source/blender/draw/engines/eevee/eevee_shader_shared.hh
+++ b/source/blender/draw/engines/eevee/eevee_shader_shared.hh
@@ -483,10 +483,10 @@ BLI_STATIC_ASSERT_ALIGN(ShadowData, 16)
* IMPORTANT: Some data packing are tweaked for these values.
* Be sure to update them accordingly.
* SHADOW_TILEMAP_RES max is 32 because of the shared bitmaps used for LOD tagging.
- * It is also limited by the maximum thread group size (1024)
+ * It is also limited by the maximum thread group size (1024).
*/
-#define SHADOW_TILEMAP_RES 32
-#define SHADOW_TILEMAP_LOD 5 /* LOG2(SHADOW_TILEMAP_RES) */
+#define SHADOW_TILEMAP_RES 16
+#define SHADOW_TILEMAP_LOD 4 /* LOG2(SHADOW_TILEMAP_RES) */
#define SHADOW_TILEMAP_PER_ROW 64
#define SHADOW_PAGE_COPY_GROUP_SIZE 32
#define SHADOW_DEPTH_SCAN_GROUP_SIZE 32
@@ -515,9 +515,6 @@ static inline vec2 shadow_tile_coord_to_ndc(ivec2 tile)
return co * 2.0f - 1.0f;
}
-/** Expands to ShadowPageData. */
-#define ShadowPagePacked int
-
/**
* Small descriptor used for the tile update phase.
*/
@@ -932,7 +929,7 @@ using RaytraceDataBuf = StructBuffer<RaytraceData>;
using ShadowDataBuf = StorageArrayBuffer<ShadowData, CULLING_BATCH_SIZE>;
using ShadowDebugDataBuf = StructBuffer<ShadowDebugData>;
using ShadowPagesInfoDataBuf = StorageBuffer<ShadowPagesInfoData, true>;
-using ShadowPageHeapBuf = StorageArrayBuffer<ShadowPagePacked, SHADOW_MAX_PAGE, true>;
+using ShadowPageHeapBuf = StorageArrayBuffer<uint, SHADOW_MAX_PAGE, true>;
using ShadowTileMapDataBuf = StorageArrayBuffer<ShadowTileMapData, SHADOW_MAX_TILEMAP>;
using SubsurfaceDataBuf = StructBuffer<SubsurfaceData>;
using VelocityObjectBuf = StructBuffer<VelocityObjectData>;
diff --git a/source/blender/draw/engines/eevee/eevee_shadow.cc b/source/blender/draw/engines/eevee/eevee_shadow.cc
index 0b2b0e991e5..ae026db0efb 100644
--- a/source/blender/draw/engines/eevee/eevee_shadow.cc
+++ b/source/blender/draw/engines/eevee/eevee_shadow.cc
@@ -610,6 +610,7 @@ void ShadowModule::sync_object(Object *ob,
}
if (is_alpha_blend) {
+ printf("receivers_non_opaque_\n");
DRW_buffer_add_entry_struct(receivers_non_opaque_, &shadow_ob.aabb);
}
}
@@ -707,15 +708,19 @@ void ShadowModule::end_sync(void)
GPUShader *sh = inst_.shaders.static_shader_get(SHADOW_TILE_SETUP);
DRWShadingGroup *grp = DRW_shgroup_create(sh, tilemap_setup_ps_);
DRW_shgroup_vertex_buffer(grp, "pages_infos_buf", pages_infos_data_);
- DRW_shgroup_vertex_buffer(grp, "pages_buf", pages_data_);
+ DRW_shgroup_vertex_buffer(grp, "pages_free_buf", pages_free_data_);
DRW_shgroup_vertex_buffer(grp, "tilemaps_buf", tilemap_allocator.tilemaps_data);
DRW_shgroup_uniform_image(grp, "tilemaps_img", tilemap_allocator.tilemap_tx);
int64_t tilemaps_updated_len = tilemaps_len + tilemap_allocator.deleted_maps_len;
if (tilemaps_updated_len > 0) {
DRW_shgroup_call_compute(grp, 1, 1, tilemaps_updated_len);
- DRW_shgroup_barrier(grp, GPU_BARRIER_SHADER_IMAGE_ACCESS);
+ DRW_shgroup_barrier(grp, GPU_BARRIER_SHADER_IMAGE_ACCESS | GPU_BARRIER_SHADER_STORAGE);
}
do_tilemap_setup_ = true;
+
+ if (G.debug & G_DEBUG_GPU) {
+ debug_page_map_call(tilemap_setup_ps_);
+ }
}
{
tilemap_visibility_ps_ = DRW_pass_create("ShadowVisibilityTag", (DRWState)0);
@@ -809,9 +814,13 @@ void ShadowModule::end_sync(void)
DRWShadingGroup *grp = DRW_shgroup_create(sh, page_init_ps_);
DRW_shgroup_vertex_buffer(grp, "pages_infos_buf", pages_infos_data_);
DRW_shgroup_vertex_buffer(grp, "pages_free_buf", pages_free_data_);
- DRW_shgroup_vertex_buffer(grp, "pages_buf", pages_data_);
+ DRW_shgroup_uniform_image(grp, "tilemaps_img", tilemap_allocator.tilemap_tx);
DRW_shgroup_call_compute(grp, SHADOW_MAX_PAGE / SHADOW_PAGE_PER_ROW, 1, 1);
- DRW_shgroup_barrier(grp, GPU_BARRIER_SHADER_STORAGE);
+ DRW_shgroup_barrier(grp, GPU_BARRIER_SHADER_IMAGE_ACCESS | GPU_BARRIER_SHADER_STORAGE);
+
+ if (G.debug & G_DEBUG_GPU) {
+ debug_page_map_call(page_init_ps_);
+ }
}
{
page_free_ps_ = DRW_pass_create("ShadowPageFree", (DRWState)0);
@@ -820,7 +829,6 @@ void ShadowModule::end_sync(void)
DRWShadingGroup *grp = DRW_shgroup_create(sh, page_free_ps_);
DRW_shgroup_vertex_buffer(grp, "pages_infos_buf", pages_infos_data_);
DRW_shgroup_vertex_buffer(grp, "pages_free_buf", pages_free_data_);
- DRW_shgroup_vertex_buffer(grp, "pages_buf", pages_data_);
DRW_shgroup_vertex_buffer(grp, "tilemaps_buf", tilemap_allocator.tilemaps_data);
DRW_shgroup_uniform_image(grp, "tilemaps_img", tilemap_allocator.tilemap_tx);
int64_t tilemaps_updated_len = tilemaps_len + tilemap_allocator.deleted_maps_len;
@@ -828,6 +836,21 @@ void ShadowModule::end_sync(void)
DRW_shgroup_call_compute(grp, 1, 1, tilemaps_updated_len);
DRW_shgroup_barrier(grp, GPU_BARRIER_SHADER_IMAGE_ACCESS | GPU_BARRIER_SHADER_STORAGE);
}
+
+ if (G.debug & G_DEBUG_GPU) {
+ debug_page_map_call(page_free_ps_);
+ }
+ }
+ {
+ page_defrag_ps_ = DRW_pass_create("ShadowPageDefrag", (DRWState)0);
+
+ GPUShader *sh = inst_.shaders.static_shader_get(SHADOW_PAGE_DEFRAG);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, page_defrag_ps_);
+ DRW_shgroup_vertex_buffer(grp, "pages_free_buf", pages_free_data_);
+ DRW_shgroup_vertex_buffer(grp, "pages_infos_buf", pages_infos_data_);
+ DRW_shgroup_uniform_image(grp, "tilemaps_img", tilemap_allocator.tilemap_tx);
+ DRW_shgroup_call_compute(grp, 1, 1, 1);
+ DRW_shgroup_barrier(grp, GPU_BARRIER_SHADER_IMAGE_ACCESS | GPU_BARRIER_SHADER_STORAGE);
}
{
page_alloc_ps_ = DRW_pass_create("ShadowPageAllocate", (DRWState)0);
@@ -836,7 +859,6 @@ void ShadowModule::end_sync(void)
DRWShadingGroup *grp = DRW_shgroup_create(sh, page_alloc_ps_);
DRW_shgroup_vertex_buffer(grp, "pages_infos_buf", pages_infos_data_);
DRW_shgroup_vertex_buffer(grp, "pages_free_buf", pages_free_data_);
- DRW_shgroup_vertex_buffer(grp, "pages_buf", pages_data_);
DRW_shgroup_vertex_buffer(grp, "tilemaps_buf", tilemap_allocator.tilemaps_data);
DRW_shgroup_uniform_image(grp, "tilemaps_img", tilemap_allocator.tilemap_tx);
DRW_shgroup_uniform_image(grp, "tilemap_rects_img", tilemap_allocator.tilemap_rects_tx);
@@ -847,6 +869,10 @@ void ShadowModule::end_sync(void)
barrier |= GPU_BARRIER_TEXTURE_UPDATE; /* Needed for readback. */
DRW_shgroup_barrier(grp, barrier);
}
+
+ if (G.debug & G_DEBUG_GPU) {
+ debug_page_map_call(page_alloc_ps_);
+ }
}
{
DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS;
@@ -877,6 +903,22 @@ void ShadowModule::end_sync(void)
debug_end_sync();
}
+void ShadowModule::debug_page_map_call(DRWPass *pass)
+{
+ if (debug_data_.type == SHADOW_DEBUG_NONE) {
+ return;
+ }
+ debug_page_tx_.ensure(SHADOW_PAGE_PER_ROW, SHADOW_PAGE_PER_ROW, 0, GPU_R32UI);
+
+ GPUShader *sh = inst_.shaders.static_shader_get(SHADOW_PAGE_DEBUG);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
+ DRW_shgroup_vertex_buffer(grp, "pages_free_buf", pages_free_data_);
+ DRW_shgroup_uniform_image(grp, "tilemaps_img", tilemap_allocator.tilemap_tx);
+ DRW_shgroup_uniform_image(grp, "debug_img", debug_page_tx_);
+ DRW_shgroup_call_compute(grp, 1, 1, 1);
+ DRW_shgroup_barrier(grp, GPU_BARRIER_SHADER_IMAGE_ACCESS | GPU_BARRIER_TEXTURE_FETCH);
+}
+
void ShadowModule::debug_end_sync(void)
{
debug_draw_ps_ = nullptr;
@@ -931,14 +973,23 @@ void ShadowModule::debug_end_sync(void)
DRW_STATE_BLEND_CUSTOM;
debug_draw_ps_ = DRW_pass_create("ShadowDebugDraw", state);
+ if (debug_data_.type == SHADOW_DEBUG_PAGE_ALLOCATION) {
+ debug_page_map_call(debug_draw_ps_);
+ }
+
GPUShader *sh = inst_.shaders.static_shader_get(SHADOW_DEBUG);
DRWShadingGroup *grp = DRW_shgroup_create(sh, debug_draw_ps_);
DRW_shgroup_vertex_buffer(grp, "tilemaps_buf", tilemap_allocator.tilemaps_data);
- DRW_shgroup_vertex_buffer(grp, "pages_buf", pages_data_);
DRW_shgroup_uniform_texture(grp, "tilemaps_tx", tilemap_allocator.tilemap_tx);
DRW_shgroup_uniform_texture_ref(grp, "depth_tx", &input_depth_tx_);
DRW_shgroup_uniform_texture(grp, "atlas_tx", atlas_tx_);
DRW_shgroup_uniform_block(grp, "debug_block", debug_data_.ubo_get());
+ if (debug_data_.type == SHADOW_DEBUG_PAGE_ALLOCATION) {
+ DRW_shgroup_uniform_texture(grp, "debug_page_tx", debug_page_tx_);
+ }
+ else {
+ DRW_shgroup_uniform_texture(grp, "debug_page_tx", tilemap_allocator.tilemap_tx);
+ }
DRW_shgroup_call_procedural_triangles(grp, nullptr, 1);
}
}
@@ -1020,6 +1071,7 @@ void ShadowModule::set_view(const DRWView *view, GPUTexture *depth_tx)
#ifndef SHADOW_DEBUG_NO_CACHING
do_page_init_ = false;
#endif
+ tilemap_allocator.tilemap_tx.clear((uint)0);
DRW_draw_pass(page_init_ps_);
}
do_tilemap_setup_ = false;
@@ -1037,6 +1089,7 @@ void ShadowModule::set_view(const DRWView *view, GPUTexture *depth_tx)
#endif
DRW_draw_pass(tilemap_lod_mask_ps_);
DRW_draw_pass(page_free_ps_);
+ DRW_draw_pass(page_defrag_ps_);
DRW_draw_pass(page_alloc_ps_);
}
DRW_stats_group_end();
diff --git a/source/blender/draw/engines/eevee/eevee_shadow.hh b/source/blender/draw/engines/eevee/eevee_shadow.hh
index acd6fb61fd3..2bc252d4f8e 100644
--- a/source/blender/draw/engines/eevee/eevee_shadow.hh
+++ b/source/blender/draw/engines/eevee/eevee_shadow.hh
@@ -241,7 +241,7 @@ struct ShadowTileMap : public ShadowTileMapData {
void set_dirty()
{
- grid_shift = int2(16);
+ grid_shift = int2(SHADOW_TILEMAP_RES);
}
void set_updated()
@@ -487,8 +487,6 @@ class ShadowModule {
eevee::Texture atlas_tx_ = Texture("shadow_atlas_tx_");
- /** Contains mapping from pages to pixel inside the tilemap. */
- ShadowPageHeapBuf pages_data_;
/** Pool of unallocated pages waiting to be assigned to specific tiles in the tilemap atlas. */
ShadowPageHeapBuf pages_free_data_;
/** Infos for book keeping and debug. */
@@ -496,6 +494,8 @@ class ShadowModule {
/** Page buffer clear. This is only done if shadow atlas is reallocated. */
DRWPass *page_init_ps_;
+ /** Defragment the page free array. */
+ DRWPass *page_defrag_ps_;
/** Free pages of deleted tiles. You can think of a garbage collection. */
DRWPass *page_free_ps_;
/** Allocate pages for new tiles. */
@@ -527,6 +527,8 @@ class ShadowModule {
DRWView *debug_view_;
/** Debug data sent to GPU. */
ShadowDebugDataBuf debug_data_;
+ /** Debug texture to check page status. */
+ Texture debug_page_tx_ = Texture("debug_page_tx_");
/** \} */
@@ -577,6 +579,7 @@ class ShadowModule {
private:
void remove_unused(void);
+ void debug_page_map_call(DRWPass *pass);
};
/** \} */
diff --git a/source/blender/draw/engines/eevee/shaders/eevee_shadow_debug_frag.glsl b/source/blender/draw/engines/eevee/shaders/eevee_shadow_debug_frag.glsl
index 986f13e6643..99dc6d5ee56 100644
--- a/source/blender/draw/engines/eevee/shaders/eevee_shadow_debug_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/eevee_shadow_debug_frag.glsl
@@ -25,11 +25,7 @@ layout(std430, binding = 0) readonly buffer tilemaps_buf
ShadowTileMapData tilemaps[];
};
-layout(std430, binding = 1) readonly buffer pages_buf
-{
- ShadowPagePacked pages[];
-};
-
+uniform usampler2D debug_page_tx;
uniform usampler2D tilemaps_tx;
uniform sampler2D depth_tx;
uniform sampler2D atlas_tx;
@@ -52,9 +48,6 @@ vec3 debug_random_color(int v)
vec3 debug_tile_state_color(ShadowTileData tile)
{
- if (tile.is_error) {
- return vec3(1, 0, 1);
- }
if (tile.lod > 0) {
return vec3(1, 0.5, 0) * float(tile.lod) / float(SHADOW_TILEMAP_LOD);
}
@@ -185,24 +178,21 @@ void debug_tile_state(vec3 P)
void debug_page_allocation(void)
{
- ivec2 page = ivec2(gl_FragCoord.xy / pixel_scale);
-
- if (in_range_inclusive(page, ivec2(0), ivec2(SHADOW_PAGE_PER_ROW - 1))) {
- uint page_index = shadow_page_to_index(page);
- if (pages[page_index] != SHADOW_PAGE_NO_DATA) {
- ShadowPageData page = shadow_page_data_unpack(pages[page_index]);
- ShadowTileData tile = shadow_tile_data_unpack(texelFetch(tilemaps_tx, page.tile, 0).x);
- if (tile.is_allocated) {
- out_color_add = vec4(1, 1, 1, 0);
- }
- else {
- /* There is an error. Page points to a tile that isn't its owner. */
- out_color_add = vec4(1, 0, 0, 0);
- }
- }
- else {
- out_color_add = vec4(0, 0, 0, 0);
- }
+ ivec2 page = ivec2(gl_FragCoord.xy / pixel_scale) - 1;
+
+ if (in_range_inclusive(page, ivec2(0), textureSize(debug_page_tx, 0).xy - 1)) {
+ uint page = texelFetch(debug_page_tx, page, 0).x;
+
+ bool error = (page & 0xFFFFu) != 1u;
+ bool is_cached = (page & SHADOW_PAGE_IS_CACHED) != 0u;
+ bool is_needed = (page & SHADOW_PAGE_IS_NEEDED) != 0u;
+ bool in_heap = (page & SHADOW_PAGE_IN_FREE_HEAP) != 0u;
+ error = error || (is_cached && !in_heap);
+ error = error || (is_needed && is_cached);
+
+ vec3 col = vec3(error, is_cached, is_needed);
+
+ out_color_add = vec4(col, 0);
out_color_mul = vec4(0);
/* Write depth to overlap overlays. */
gl_FragDepth = 0.0;
diff --git a/source/blender/draw/engines/eevee/shaders/eevee_shadow_lib.glsl b/source/blender/draw/engines/eevee/shaders/eevee_shadow_lib.glsl
index e02ab0817fa..a1657a830ff 100644
--- a/source/blender/draw/engines/eevee/shaders/eevee_shadow_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/eevee_shadow_lib.glsl
@@ -54,6 +54,13 @@ float shadow_punctual_depth_get(
int tilemap_index = shadow.tilemap_index + face_id;
ShadowTileData tile = shadow_tile_load(tilemaps_tx, tile_co, 0, tilemap_index);
+ /* TODO(fclem): Remove this indirection. But this means having to store another indirection
+ * table for the pages. */
+ if (tile.lod > 0u) {
+ tile_co >>= int(tile.lod);
+ tile.page = shadow_tile_load(tilemaps_tx, tile_co, int(tile.lod), tilemap_index).page;
+ }
+
float depth = 1.0;
if ((tilemap_index <= shadow.tilemap_last) && (tile.is_allocated || tile.lod > 0)) {
vec2 shadow_uv = shadow_page_uv_transform(tile.page, tile.lod, uv);
diff --git a/source/blender/draw/engines/eevee/shaders/eevee_shadow_page_alloc_comp.glsl b/source/blender/draw/engines/eevee/shaders/eevee_shadow_page_alloc_comp.glsl
index a50dd495c05..3d217cdfc95 100644
--- a/source/blender/draw/engines/eevee/shaders/eevee_shadow_page_alloc_comp.glsl
+++ b/source/blender/draw/engines/eevee/shaders/eevee_shadow_page_alloc_comp.glsl
@@ -29,12 +29,7 @@ layout(std430, binding = 0) restrict readonly buffer tilemaps_buf
layout(std430, binding = 1) restrict buffer pages_free_buf
{
- int pages_free[];
-};
-
-layout(std430, binding = 2) restrict buffer pages_buf
-{
- ShadowPagePacked pages[];
+ uint free_page_owners[];
};
layout(std430, binding = 3) restrict buffer pages_infos_buf
@@ -51,11 +46,7 @@ void main()
int tilemap_idx = tilemap_data.index;
int lod_max = tilemap_data.is_cubeface ? SHADOW_TILEMAP_LOD : 0;
- /* Used to broadcast the first valid page to all LOD 0 tiles covered by a LOD > 0 page. */
- shared uint page_map[(SHADOW_TILEMAP_RES / 2) * (SHADOW_TILEMAP_RES / 2)];
-
- int lod_valid = -1;
- uvec2 page_valid;
+ int lod_valid = 0;
for (int lod = lod_max; lod >= 0; lod--) {
ivec2 tile_co = ivec2(gl_GlobalInvocationID.xy) >> lod;
int tile_index = (SHADOW_TILEMAP_RES / 2) * tile_co.y + tile_co.x;
@@ -73,56 +64,38 @@ void main()
/** Tile allocation. */
int free_index = atomicAdd(infos.page_free_next, -1);
if (free_index >= 0) {
- ShadowPageData page;
- page.tile = texel;
+ ivec2 owner_texel = ivec2(unpackUvec2x16(free_page_owners[free_index]));
+ free_page_owners[free_index] = uint(-1);
- int page_index = pages_free[free_index];
- pages[page_index] = shadow_page_data_pack(page);
-
- pages_free[free_index] = -1;
-
- tile.page = shadow_page_from_index(page_index);
+ tile.page = shadow_tile_data_unpack(imageLoad(tilemaps_img, owner_texel).x).page;
tile.do_update = true;
tile.is_allocated = true;
-
- if (page_index == -1) {
- tile.is_error = true;
- tile.is_allocated = false;
- }
-
+ tile.is_cached = false;
imageStore(tilemaps_img, texel, uvec4(shadow_tile_data_pack(tile)));
- }
- else {
- /* Well, hum ... you blew up your budget! */
- }
- }
- if (lod > 0) {
- /* Use shared variable to broadcast the page. */
- if (tile.is_allocated) {
- page_map[tile_index] = shadow_page_to_index(tile.page);
+ const uint flag = SHADOW_TILE_IS_ALLOCATED | SHADOW_TILE_IS_CACHED;
+ imageAtomicAnd(tilemaps_img, owner_texel, ~flag);
}
else {
- page_map[tile_index] = uint(-1);
+ /* Well, hum ... you blew up your budget! */
}
}
}
barrier();
- if (lod > 0) {
- /* Save highest quality valid lod for this thread. */
- if (page_map[tile_index] != uint(-1)) {
- lod_valid = lod;
- page_valid = shadow_page_from_index(int(page_map[tile_index]));
- }
+ /* Save highest quality valid lod for this thread. */
+ if (tile.is_visible && tile.is_used) {
+ lod_valid = lod;
}
- else if (tile.is_allocated == false && lod_valid != -1) {
- /* If the LOD 0 tile is not allocated and one of the lower level is,
- * we save a reference to it to avoid 2 load at shading time. */
- tile.lod = uint(lod_valid);
- tile.page = page_valid;
- imageStore(tilemaps_img, texel, uvec4(shadow_tile_data_pack(tile)));
+ else if (lod == 0) {
+ /* If the tile is not used, store the valid LOD level. */
+ /* This is tricky because the tile might be processed by another thread doing an allocation.
+ * So we need to set the LOD using atomics. */
+ uint lod_mask = 7u << 12u;
+ uint lod_store = uint(lod_valid) << 12u;
+ imageAtomicAnd(tilemaps_img, texel, ~lod_mask);
+ imageAtomicOr(tilemaps_img, texel, lod_store);
}
/** Compute area to render and write to buffer for CPU to read. */
diff --git a/source/blender/draw/engines/eevee/shaders/eevee_shadow_page_debug_comp.glsl b/source/blender/draw/engines/eevee/shaders/eevee_shadow_page_debug_comp.glsl
new file mode 100644
index 00000000000..a2ef545248a
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/eevee_shadow_page_debug_comp.glsl
@@ -0,0 +1,113 @@
+
+/**
+ * Virtual shadowmapping: Debug pages.
+ *
+ * Since pages are only existing if they are attached to a tilemap or the free list,
+ * this shader will scan every possible position and create a debug map out of it.
+ * This is nice to inspect the state of the page allocation during the pipeline.
+ */
+
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(common_math_lib.glsl)
+#pragma BLENDER_REQUIRE(eevee_shadow_page_lib.glsl)
+#pragma BLENDER_REQUIRE(eevee_shadow_tilemap_lib.glsl)
+
+layout(local_size_x = 8, local_size_y = 8) in;
+
+layout(std430, binding = 1) readonly restrict buffer pages_free_buf
+{
+ uint free_page_owners[];
+};
+
+layout(r32ui) restrict uniform uimage2D tilemaps_img;
+
+layout(r32ui) restrict uniform uimage2D debug_img;
+
+/* Use this as custom channel viewer in renderdoc to inspect debug_img. */
+#if 0
+
+layout(binding = 2) uniform usampler2D texUInt2D;
+in vec2 uv;
+out vec4 color_out;
+
+void main()
+{
+ uint page = texture(texUInt2D, uv).x;
+
+ bool error = (page & 0xFFFFu) != 1u;
+ bool is_cached = (page & SHADOW_PAGE_IS_CACHED) != 0u;
+ bool is_needed = (page & SHADOW_PAGE_IS_NEEDED) != 0u;
+ bool in_heap = (page & SHADOW_PAGE_IN_FREE_HEAP) != 0u;
+ error = error || (is_cached && !in_heap);
+ error = error || (is_needed && is_cached);
+
+ color_out = vec4(error, is_cached, is_needed, in_heap);
+}
+
+#endif
+
+void main()
+{
+ for (int y = 0; y < imageSize(debug_img).y / int(gl_WorkGroupSize.y); y++) {
+ for (int x = 0; x < imageSize(debug_img).x / int(gl_WorkGroupSize.x); x++) {
+ ivec2 co = ivec2(x, y) * ivec2(gl_WorkGroupSize.xy) + ivec2(gl_LocalInvocationID.xy);
+ imageStore(debug_img, co, uvec4(0));
+ }
+ }
+
+ barrier();
+
+ /* TODO(fclem): We only scan the first line of tilemap, otherwise it is too slow.
+ * Finish and do it properly one day... */
+ for (int y = 0; y < imageSize(tilemaps_img).y / int(gl_WorkGroupSize.y); y++) {
+ for (int x = 0; x < imageSize(tilemaps_img).x / int(gl_WorkGroupSize.x); x++) {
+ ivec2 co = ivec2(x, y) * ivec2(gl_WorkGroupSize.xy) + ivec2(gl_LocalInvocationID.xy);
+ ShadowTileData tile = shadow_tile_data_unpack(imageLoad(tilemaps_img, co).x);
+
+ if (tile.is_allocated) {
+ /* User count. */
+ imageAtomicAdd(debug_img, ivec2(tile.page), 1u);
+ }
+ }
+ }
+
+ barrier();
+
+ for (int y = 0; y < imageSize(tilemaps_img).y / int(gl_WorkGroupSize.y); y++) {
+ for (int x = 0; x < imageSize(tilemaps_img).x / int(gl_WorkGroupSize.x); x++) {
+ ivec2 co = ivec2(x, y) * ivec2(gl_WorkGroupSize.xy) + ivec2(gl_LocalInvocationID.xy);
+ ShadowTileData tile = shadow_tile_data_unpack(imageLoad(tilemaps_img, co).x);
+
+ if (tile.is_allocated) {
+ imageAtomicOr(debug_img, ivec2(tile.page), SHADOW_PAGE_ALLOCATED);
+ if (tile.is_cached) {
+ imageAtomicOr(debug_img, ivec2(tile.page), SHADOW_PAGE_IS_CACHED);
+ /* Verify reference. */
+ ivec2 ref = ivec2(unpackUvec2x16(free_page_owners[tile.free_page_owner_index]));
+ if (ref == co) {
+ imageAtomicOr(debug_img, ivec2(tile.page), SHADOW_PAGE_IN_FREE_HEAP);
+ }
+ }
+ if (tile.is_used && tile.is_visible) {
+ imageAtomicOr(debug_img, ivec2(tile.page), SHADOW_PAGE_IS_NEEDED);
+ }
+ if (tile.do_update) {
+ imageAtomicOr(debug_img, ivec2(tile.page), SHADOW_PAGE_DO_UPDATE);
+ }
+ }
+ }
+ }
+
+#if 0
+ for (int x = 0; x < SHADOW_MAX_PAGE; x++) {
+ if (free_page_owners[x] != uint(-1)) {
+ uvec2 owner = unpackUvec2x16(free_page_owners[x]);
+ uvec2 page = shadow_tile_data_unpack(imageLoad(tilemaps_img, ivec2(owner)).x).page;
+ /* User count. */
+ imageAtomicAdd(debug_img, ivec2(page), 1u);
+
+ imageAtomicOr(debug_img, ivec2(page), SHADOW_PAGE_IN_FREE_HEAP);
+ }
+ }
+#endif
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/eevee_shadow_page_defrag_comp.glsl b/source/blender/draw/engines/eevee/shaders/eevee_shadow_page_defrag_comp.glsl
new file mode 100644
index 00000000000..30f0f1e8925
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/eevee_shadow_page_defrag_comp.glsl
@@ -0,0 +1,59 @@
+
+/**
+ * Virtual shadowmapping: Defrag.
+ *
+ * Defragment the free page owner heap making one continuous array.
+ */
+
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(common_math_lib.glsl)
+#pragma BLENDER_REQUIRE(eevee_shadow_page_lib.glsl)
+#pragma BLENDER_REQUIRE(eevee_shadow_tilemap_lib.glsl)
+
+layout(local_size_x = 1) in;
+
+layout(std430, binding = 1) restrict buffer pages_free_buf
+{
+ uint free_page_owners[];
+};
+
+layout(std430, binding = 3) restrict buffer pages_infos_buf
+{
+ ShadowPagesInfoData infos;
+};
+
+layout(r32ui) restrict uniform uimage2D tilemaps_img;
+
+void find_last_valid(inout uint last_valid)
+{
+ for (uint i = last_valid; i > 0u; i--) {
+ if (free_page_owners[i] != uint(-1)) {
+ last_valid = i;
+ break;
+ }
+ }
+}
+
+void main()
+{
+ uint last_valid = uint(infos.page_free_next);
+
+ find_last_valid(last_valid);
+
+ for (uint i = 0u; i < last_valid; i++) {
+ if (free_page_owners[i] == uint(-1)) {
+ free_page_owners[i] = free_page_owners[last_valid];
+
+ /* Update corresponding reference in tile. */
+ ivec2 texel = ivec2(unpackUvec2x16(free_page_owners[last_valid]));
+ ShadowTileData tile = shadow_tile_data_unpack(imageLoad(tilemaps_img, texel).x);
+ tile.free_page_owner_index = i;
+ imageStore(tilemaps_img, texel, uvec4(shadow_tile_data_pack(tile)));
+
+ free_page_owners[last_valid] = uint(-1);
+ find_last_valid(last_valid);
+ }
+ }
+
+ infos.page_free_next = int(last_valid);
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/eevee_shadow_page_free_comp.glsl b/source/blender/draw/engines/eevee/shaders/eevee_shadow_page_free_comp.glsl
index 03e56fe2f5d..4c013ab526c 100644
--- a/source/blender/draw/engines/eevee/shaders/eevee_shadow_page_free_comp.glsl
+++ b/source/blender/draw/engines/eevee/shaders/eevee_shadow_page_free_comp.glsl
@@ -19,12 +19,7 @@ layout(std430, binding = 0) restrict readonly buffer tilemaps_buf
layout(std430, binding = 1) restrict buffer pages_free_buf
{
- int pages_free[];
-};
-
-layout(std430, binding = 2) restrict writeonly buffer pages_buf
-{
- ShadowPagePacked pages[];
+ uint free_page_owners[];
};
layout(std430, binding = 3) restrict buffer pages_infos_buf
@@ -51,31 +46,28 @@ void main()
ivec2 texel = shadow_tile_coord_in_atlas(tile_co, tilemap_idx, lod);
ShadowTileData tile = shadow_tile_data_unpack(imageLoad(tilemaps_img, texel).x);
- if (tile.is_allocated && (!tile.is_visible || !tile.is_used)) {
- /* Push page to the free page heap. */
- uint page_index = shadow_page_to_index(tile.page);
-#ifdef SHADOW_DEBUG_PAGE_ALLOCATION_ENABLED
- pages[page_index] = SHADOW_PAGE_NO_DATA;
-#endif
-
- int free_index = atomicAdd(infos.page_free_next, 1) + 1;
- if (free_index < SHADOW_MAX_PAGE) {
- pages_free[free_index] = int(page_index);
+ if (tile.is_allocated) {
+ if (tile.is_visible && tile.is_used && tile.is_cached) {
+ /* Try to recover cached tiles. Update flag is kept untouched as content might be valid. */
+ free_page_owners[tile.free_page_owner_index] = uint(-1);
+ tile.is_cached = false;
+ tile.free_page_owner_index = uint(-1);
+ imageStore(tilemaps_img, texel, uvec4(shadow_tile_data_pack(tile)));
}
- else {
- /* Well, this should never happen. This would mean some pages were marked
- * for deletion multiple times. */
- infos.page_free_next = SHADOW_MAX_PAGE - 1;
+ else if ((!tile.is_visible || !tile.is_used) && !tile.is_cached) {
+ /* Push page to the free page heap. */
+ int free_index = atomicAdd(infos.page_free_next, 1) + 1;
+ if (free_index < SHADOW_MAX_PAGE) {
+ free_page_owners[free_index] = packUvec2x16(uvec2(texel));
+ tile.is_cached = true;
+ tile.free_page_owner_index = uint(free_index);
+ imageStore(tilemaps_img, texel, uvec4(shadow_tile_data_pack(tile)));
+ }
+ else {
+ /* Well, this should never happen. This would mean some pages were marked
+ * for deletion multiple times. */
+ }
}
-
- tile.is_allocated = false;
-#ifdef SHADOW_DEBUG_TILE_ALLOCATION_ENABLED
- tile.page = uvec2(0);
- tile.is_visible = false;
- tile.do_update = false;
- tile.is_used = false;
-#endif
- imageStore(tilemaps_img, texel, uvec4(shadow_tile_data_pack(tile)));
}
}
} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/eevee_shadow_page_init_comp.glsl b/source/blender/draw/engines/eevee/shaders/eevee_shadow_page_init_comp.glsl
index 0075bd2be92..adc00a18948 100644
--- a/source/blender/draw/engines/eevee/shaders/eevee_shadow_page_init_comp.glsl
+++ b/source/blender/draw/engines/eevee/shaders/eevee_shadow_page_init_comp.glsl
@@ -2,21 +2,18 @@
/**
* Virtual shadowmapping: Init page buffer.
*
+ * All pages are always owned by tiles. This step init all owners.
* This avoid mapping the buffer to host memory.
*/
#pragma BLENDER_REQUIRE(eevee_shadow_page_lib.glsl)
+#pragma BLENDER_REQUIRE(eevee_shadow_tilemap_lib.glsl)
layout(local_size_x = SHADOW_PAGE_PER_ROW) in;
layout(std430, binding = 1) restrict writeonly buffer pages_free_buf
{
- int pages_free[];
-};
-
-layout(std430, binding = 2) restrict writeonly buffer pages_buf
-{
- ShadowPagePacked pages[];
+ uint free_page_owners[];
};
layout(std430, binding = 3) restrict writeonly buffer pages_infos_buf
@@ -24,15 +21,29 @@ layout(std430, binding = 3) restrict writeonly buffer pages_infos_buf
ShadowPagesInfoData infos;
};
+layout(r32ui) restrict uniform uimage2D tilemaps_img;
+
void main()
{
- infos.page_free_next = SHADOW_MAX_PAGE - 1;
- infos.page_free_next_prev = 0;
- infos.page_updated_count = 0;
-
- pages_free[gl_GlobalInvocationID.x] = ShadowPagePacked(gl_GlobalInvocationID.x);
-
-#ifdef SHADOW_DEBUG_PAGE_ALLOCATION_ENABLED
- pages[gl_GlobalInvocationID.x] = SHADOW_PAGE_NO_DATA;
-#endif
+ if (gl_GlobalInvocationID == uvec3(0)) {
+ infos.page_free_next = SHADOW_MAX_PAGE - 1;
+ infos.page_free_next_prev = 0;
+ infos.page_updated_count = 0;
+ }
+
+ uint page_index = gl_GlobalInvocationID.x;
+
+ ivec2 texel = ivec2(page_index % (SHADOW_TILEMAP_PER_ROW * SHADOW_TILEMAP_RES),
+ page_index / (SHADOW_TILEMAP_PER_ROW * SHADOW_TILEMAP_RES));
+ free_page_owners[page_index] = packUvec2x16(uvec2(texel));
+
+ /* Start with a blank tile. */
+ ShadowTileData tile = shadow_tile_data_unpack(0u);
+ tile.page = uvec2(page_index % uint(SHADOW_PAGE_PER_ROW),
+ page_index / uint(SHADOW_PAGE_PER_ROW));
+ tile.free_page_owner_index = page_index;
+ tile.is_allocated = true;
+ tile.is_cached = true;
+ tile.do_update = true;
+ imageStore(tilemaps_img, texel, uvec4(shadow_tile_data_pack(tile)));
} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/eevee_shadow_page_lib.glsl b/source/blender/draw/engines/eevee/shaders/eevee_shadow_page_lib.glsl
index a4c3d5fd981..4dc95dfd011 100644
--- a/source/blender/draw/engines/eevee/shaders/eevee_shadow_page_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/eevee_shadow_page_lib.glsl
@@ -2,39 +2,11 @@
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_shader_shared.hh)
-/** Decoded page data structure. */
-struct ShadowPageData {
- /** Tile inside the tilemap atlas. */
- ivec2 tile;
-};
-
-#define SHADOW_PAGE_NO_DATA 0xFFFFFFFF
-
-uvec2 shadow_page_from_index(ShadowPagePacked index)
-{
- return uvec2(index % SHADOW_PAGE_PER_ROW, index / SHADOW_PAGE_PER_ROW);
-}
-
-uint shadow_page_to_index(uvec2 page)
-{
- return page.y * uint(SHADOW_PAGE_PER_ROW) + page.x;
-}
-
-ShadowPageData shadow_page_data_unpack(ShadowPagePacked data)
-{
- ShadowPageData page;
- page.tile.x = data & 0xFFF;
- page.tile.y = (data >> 12) & 0xFFF;
- return page;
-}
-
-ShadowPagePacked shadow_page_data_pack(ShadowPageData page)
-{
- ShadowPagePacked data;
- data = page.tile.x;
- data |= page.tile.y << 12;
- return data;
-}
+#define SHADOW_PAGE_ALLOCATED (1u << 16u)
+#define SHADOW_PAGE_IS_CACHED (1u << 17u)
+#define SHADOW_PAGE_IS_NEEDED (1u << 18u)
+#define SHADOW_PAGE_IN_FREE_HEAP (1u << 19u)
+#define SHADOW_PAGE_DO_UPDATE (1u << 20u)
/** \a unormalized_uv is the uv coordinates for the whole tilemap [0..SHADOW_TILEMAP_RES]. */
vec2 shadow_page_uv_transform(uvec2 page, uint lod, vec2 unormalized_uv)
diff --git a/source/blender/draw/engines/eevee/shaders/eevee_shadow_tilemap_depth_scan_comp.glsl b/source/blender/draw/engines/eevee/shaders/eevee_shadow_tilemap_depth_scan_comp.glsl
index 4f4abc6579a..cdb9a1a4bad 100644
--- a/source/blender/draw/engines/eevee/shaders/eevee_shadow_tilemap_depth_scan_comp.glsl
+++ b/source/blender/draw/engines/eevee/shaders/eevee_shadow_tilemap_depth_scan_comp.glsl
@@ -97,7 +97,7 @@ void tag_tilemap(uint l_idx, vec3 P, float dist_to_cam, const bool is_directiona
tilemap_index += face_id;
}
- const uint flag = SHADOW_TILE_IS_VISIBLE | SHADOW_TILE_IS_USED;
+ const uint flag = SHADOW_TILE_IS_USED;
shadow_tile_set_flag(tilemaps_img, tile_co, lod, tilemap_index, flag);
}
diff --git a/source/blender/draw/engines/eevee/shaders/eevee_shadow_tilemap_lib.glsl b/source/blender/draw/engines/eevee/shaders/eevee_shadow_tilemap_lib.glsl
index 7c8e58f1c78..39553d5eb92 100644
--- a/source/blender/draw/engines/eevee/shaders/eevee_shadow_tilemap_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/eevee_shadow_tilemap_lib.glsl
@@ -11,6 +11,8 @@
struct ShadowTileData {
/** Page inside the virtual shadow map atlas. */
uvec2 page;
+ /** Page owner index inside free_page_owners heap. Only valid if is_cached is true. */
+ uint free_page_owner_index;
/** Lod pointed to by LOD 0 tile page. (cubemap only) */
uint lod;
/** Set to true during the setup phase if the tile is inside the view frustum. */
@@ -21,11 +23,12 @@ struct ShadowTileData {
bool is_allocated;
/** True if an update is needed. */
bool do_update;
- bool is_error;
+ /** True if the tile is indexed inside the free_page_owners heap. */
+ bool is_cached;
};
#define SHADOW_TILE_NO_DATA 0u
-#define SHADOW_TILE_IS_ERROR (1u << 27u)
+#define SHADOW_TILE_IS_CACHED (1u << 27u)
#define SHADOW_TILE_IS_ALLOCATED (1u << 28u)
#define SHADOW_TILE_DO_UPDATE (1u << 29u)
#define SHADOW_TILE_IS_VISIBLE (1u << 30u)
@@ -34,13 +37,17 @@ struct ShadowTileData {
ShadowTileData shadow_tile_data_unpack(uint data)
{
ShadowTileData tile;
- tile.page.x = data & 0xFFu;
- tile.page.y = (data >> 8u) & 0xFFu;
- tile.lod = (data >> 16u) & 0xFu;
+ /* Tweaked for SHADOW_PAGE_PER_ROW = 64. */
+ tile.page.x = data & 63u;
+ tile.page.y = (data >> 6u) & 63u;
+ /* Tweaked for SHADOW_TILEMAP_LOD < 8. */
+ tile.lod = (data >> 12u) & 7u;
+ /* Tweaked for SHADOW_MAX_TILEMAP = 4096. */
+ tile.free_page_owner_index = (data >> 15u) & 4095u;
tile.is_visible = flag_test(data, SHADOW_TILE_IS_VISIBLE);
tile.is_used = flag_test(data, SHADOW_TILE_IS_USED);
+ tile.is_cached = flag_test(data, SHADOW_TILE_IS_CACHED);
tile.is_allocated = flag_test(data, SHADOW_TILE_IS_ALLOCATED);
- tile.is_error = flag_test(data, SHADOW_TILE_IS_ERROR);
tile.do_update = flag_test(data, SHADOW_TILE_DO_UPDATE);
return tile;
}
@@ -49,12 +56,13 @@ uint shadow_tile_data_pack(ShadowTileData tile)
{
uint data;
data = tile.page.x;
- data |= tile.page.y << 8u;
- data |= tile.lod << 16u;
+ data |= tile.page.y << 6u;
+ data |= tile.lod << 12u;
+ data |= tile.free_page_owner_index << 15u;
set_flag_from_test(data, tile.is_visible, SHADOW_TILE_IS_VISIBLE);
set_flag_from_test(data, tile.is_used, SHADOW_TILE_IS_USED);
set_flag_from_test(data, tile.is_allocated, SHADOW_TILE_IS_ALLOCATED);
- set_flag_from_test(data, tile.is_error, SHADOW_TILE_IS_ERROR);
+ set_flag_from_test(data, tile.is_cached, SHADOW_TILE_IS_CACHED);
set_flag_from_test(data, tile.do_update, SHADOW_TILE_DO_UPDATE);
return data;
}
diff --git a/source/blender/draw/engines/eevee/shaders/eevee_shadow_tilemap_setup_comp.glsl b/source/blender/draw/engines/eevee/shaders/eevee_shadow_tilemap_setup_comp.glsl
index f4a17662dee..92a0c3d6d14 100644
--- a/source/blender/draw/engines/eevee/shaders/eevee_shadow_tilemap_setup_comp.glsl
+++ b/source/blender/draw/engines/eevee/shaders/eevee_shadow_tilemap_setup_comp.glsl
@@ -17,9 +17,9 @@ layout(std430, binding = 0) readonly buffer tilemaps_buf
ShadowTileMapData tilemaps[];
};
-layout(std430, binding = 2) restrict writeonly buffer pages_buf
+layout(std430, binding = 1) restrict buffer pages_free_buf
{
- ShadowPagePacked pages[];
+ uint free_page_owners[];
};
layout(std430, binding = 3) restrict buffer pages_infos_buf
@@ -39,56 +39,42 @@ void main()
* This way the tile can even be reused if it is needed. Also avoid negative modulo. */
ivec2 tile_wrapped = (tile_shifted + SHADOW_TILEMAP_RES) % SHADOW_TILEMAP_RES;
- ivec2 texel = shadow_tile_coord_in_atlas(tile_wrapped, tilemap.index, 0);
- ShadowTileData tile_data = shadow_tile_data_unpack(imageLoad(tilemaps_img, texel).x);
- /* Reset all flags but keep the allocated page. */
+ ivec2 texel_out = shadow_tile_coord_in_atlas(tile_co, tilemap.index, 0);
+ ivec2 texel_in = shadow_tile_coord_in_atlas(tile_wrapped, tilemap.index, 0);
+
+ ShadowTileData tile_data = shadow_tile_data_unpack(imageLoad(tilemaps_img, texel_in).x);
tile_data.is_visible = false;
tile_data.is_used = false;
- tile_data.do_update = false;
tile_data.lod = 0;
-#ifdef SHADOW_DEBUG_NO_CACHING
- tile_data.page = uvec2(0);
- tile_data.is_allocated = false;
-#endif
if (!in_range_inclusive(tile_shifted, ivec2(0), ivec2(SHADOW_TILEMAP_RES - 1))) {
/* This tile was shifted in. */
tile_data.do_update = true;
}
- if (tilemap.grid_shift.x != 0) {
+ if (tilemap.grid_shift != ivec2(0) && tile_data.is_cached) {
/* Update page location after shift. */
- ShadowPageData page;
- page.tile = texel;
- pages[shadow_page_to_index(tile_data.page)] = shadow_page_data_pack(page);
+ free_page_owners[tile_data.free_page_owner_index] = packUvec2x16(uvec2(texel_out));
}
- shadow_tile_store(tilemaps_img, tile_co, tilemap.index, tile_data);
+ imageStore(tilemaps_img, texel_out, uvec4(shadow_tile_data_pack(tile_data)));
if (tilemap.is_cubeface) {
/* Cubemap shift update is always all or nothing. */
bool do_update = (tilemap.grid_shift.x != 0);
/* Number of lod0 tiles covered by the current lod level (in one dimension). */
- uint lod_stride = 1u;
- uint lod_size = uint(SHADOW_TILEMAP_RES);
- for (int lod = 1; lod <= SHADOW_TILEMAP_LOD; lod++) {
- lod_size >>= 1;
- lod_stride <<= 1;
-
+ uint lod_stride = 1u << 1u;
+ uint lod_size = uint(SHADOW_TILEMAP_RES) >> 1u;
+ for (int lod = 1; lod <= SHADOW_TILEMAP_LOD; lod++, lod_size >>= 1u, lod_stride <<= 1u) {
if (all(lessThan(tile_co, ivec2(lod_size)))) {
ivec2 texel = shadow_tile_coord_in_atlas(tile_co, tilemap.index, lod);
ShadowTileData tile_data = shadow_tile_data_unpack(imageLoad(tilemaps_img, texel).x);
- /* Reset all flags but keep the allocated page. */
tile_data.is_visible = false;
tile_data.is_used = false;
tile_data.do_update = do_update;
tile_data.lod = 0;
-#ifdef SHADOW_DEBUG_NO_CACHING
- tile_data.page = uvec2(0);
- tile_data.is_allocated = false;
-#endif
imageStore(tilemaps_img, texel, uvec4(shadow_tile_data_pack(tile_data)));
}
}
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index 9982a84fabe..58271eba509 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -1208,6 +1208,7 @@ DRWCallBuffer *DRW_call_buffer_create(struct GPUVertFormat *format)
GPUVertBuf *DRW_call_buffer_as_vertbuf(DRWCallBuffer *callbuf)
{
+ GPU_vertbuf_data_len_set(callbuf->buf, callbuf->count);
return callbuf->buf;
}
diff --git a/source/blender/draw/intern/shaders/common_math_lib.glsl b/source/blender/draw/intern/shaders/common_math_lib.glsl
index 28943b99929..e2941f1b049 100644
--- a/source/blender/draw/intern/shaders/common_math_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_math_lib.glsl
@@ -139,6 +139,16 @@ uint bit_field_mask(uint bit_width, uint bit_min)
return ~mask << bit_min;
}
+uvec2 unpackUvec2x16(uint data)
+{
+ return uvec2(data >> 16u, data & 0xFFFFu);
+}
+
+uint packUvec2x16(uvec2 data)
+{
+ return (data.x << 16u) | (data.y & 0xFFFFu);
+}
+
float distance_squared(vec2 a, vec2 b)
{
a -= b;