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:
authorClément Foucault <foucault.clem@gmail.com>2021-12-10 19:25:37 +0300
committerClément Foucault <foucault.clem@gmail.com>2021-12-10 19:25:37 +0300
commit36bec765e2edbe07d8137fc019f7db7d3292875d (patch)
tree9b9990d75da978fa36f277e7042bd819e7c32da3 /source/blender/draw/engines
parent0a7c4afd211416df90f910f861f38acc43793d33 (diff)
EEVEE: Shadow: Add defrag shader and page debug buffer generator
The defrag shader make sure the free heap is free of holes. Making the allocation more straightforward. Since we now only reference the pages using the tiles, we introduce a debug shader that produces an image with page data in a visual way. This replaces the debug 8 option. This also fixes some bug that were still present in the pipeline.
Diffstat (limited to 'source/blender/draw/engines')
-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
16 files changed, 373 insertions, 203 deletions
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)));
}
}