Eevee-next: Use compute shader to clear clipmaps

Clearing of clipmaps is the only place in Blender that uses non
uniform data (not all components of the cleared data to be exact
the same).

Vulkan has only the possibility to clear buffers using a single
uint32_t. There were two solutions:
- Add compute shader to Vulkan backend.
- Make Eevee-next responsible to clear the clipmaps.

When fixing this in the Vulkan backend it could lead to other issues
as the backend isn't aware what is exactly required and might overwrite
active bindings. We chose to make it a responsibility of Eevee-next
as there it is clear what is needed.

Related issue: #105492

Pull Request: https://projects.blender.org/blender/blender/pulls/105560
This commit is contained in:
Jeroen Bakker
2023-03-09 18:28:05 +01:00
parent 28a581d6cb
commit ffcd8e6b02
7 changed files with 37 additions and 11 deletions

View File

@@ -467,6 +467,7 @@ set(GLSL_SRC
engines/eevee_next/shaders/eevee_sampling_lib.glsl
engines/eevee_next/shaders/eevee_shadow_debug_frag.glsl
engines/eevee_next/shaders/eevee_shadow_lib.glsl
engines/eevee_next/shaders/eevee_shadow_clipmap_clear_comp.glsl
engines/eevee_next/shaders/eevee_shadow_page_allocate_comp.glsl
engines/eevee_next/shaders/eevee_shadow_page_clear_comp.glsl
engines/eevee_next/shaders/eevee_shadow_page_defrag_comp.glsl

View File

@@ -54,6 +54,7 @@
#define SHADOW_PAGE_PER_ROW 64
#define SHADOW_ATLAS_SLOT 5
#define SHADOW_BOUNDS_GROUP_SIZE 64
#define SHADOW_CLIPMAP_GROUP_SIZE 64
#define SHADOW_VIEW_MAX 64 /* Must match DRW_VIEW_MAX. */
/* Ray-tracing. */

View File

@@ -142,6 +142,8 @@ const char *ShaderModule::static_shader_create_info_name_get(eShaderType shader_
return "eevee_light_culling_tile";
case LIGHT_CULLING_ZBIN:
return "eevee_light_culling_zbin";
case SHADOW_CLIPMAP_CLEAR:
return "eevee_shadow_clipmap_clear";
case SHADOW_DEBUG:
return "eevee_shadow_debug";
case SHADOW_PAGE_ALLOCATE:

View File

@@ -62,6 +62,7 @@ enum eShaderType {
MOTION_BLUR_TILE_FLATTEN_RENDER,
MOTION_BLUR_TILE_FLATTEN_VIEWPORT,
SHADOW_CLIPMAP_CLEAR,
SHADOW_DEBUG,
SHADOW_PAGE_ALLOCATE,
SHADOW_PAGE_CLEAR,

View File

@@ -835,17 +835,6 @@ void ShadowModule::end_sync()
/* Clear tiles to not reference any page. */
tilemap_pool.tiles_data.clear_to_zero();
/* Clear tile-map clip buffer. */
union {
ShadowTileMapClip clip;
int4 i;
} u;
u.clip.clip_near_stored = 0.0f;
u.clip.clip_far_stored = 0.0f;
u.clip.clip_near = int(0xFF7FFFFFu ^ 0x7FFFFFFFu); /* floatBitsToOrderedInt(-FLT_MAX) */
u.clip.clip_far = 0x7F7FFFFF; /* floatBitsToOrderedInt(FLT_MAX) */
GPU_storagebuf_clear(tilemap_pool.tilemaps_clip, GPU_RGBA32I, GPU_DATA_INT, &u.i);
/* Clear cached page buffer. */
int2 data = {-1, -1};
GPU_storagebuf_clear(pages_cached_data_, GPU_RG32I, GPU_DATA_INT, &data);
@@ -867,6 +856,17 @@ void ShadowModule::end_sync()
PassSimple &pass = tilemap_setup_ps_;
pass.init();
{
/** Clear tile-map clip buffer. */
PassSimple::Sub &sub = pass.sub("ClearClipmap");
sub.shader_set(inst_.shaders.static_shader_get(SHADOW_CLIPMAP_CLEAR));
sub.bind_ssbo("tilemaps_clip_buf", tilemap_pool.tilemaps_clip);
sub.push_constant("tilemaps_clip_buf_len", int(tilemap_pool.tilemaps_clip.size()));
sub.dispatch(int3(
divide_ceil_u(tilemap_pool.tilemaps_clip.size(), SHADOW_CLIPMAP_GROUP_SIZE), 1, 1));
sub.barrier(GPU_BARRIER_SHADER_STORAGE);
}
{
/** Compute near/far clip distances for directional shadows based on casters bounds. */
PassSimple::Sub &sub = pass.sub("DirectionalBounds");

View File

@@ -0,0 +1,13 @@
#pragma BLENDER_REQUIRE(gpu_shader_utildefines_lib.glsl)
void main()
{
int index = int(gl_GlobalInvocationID.x);
if (index < tilemaps_clip_buf_len) {
tilemaps_clip_buf[index].clip_near_stored = 0;
tilemaps_clip_buf[index].clip_far_stored = 0;
tilemaps_clip_buf[index].clip_near = floatBitsToOrderedInt(-FLT_MAX);
tilemaps_clip_buf[index].clip_far = floatBitsToOrderedInt(FLT_MAX);
}
}

View File

@@ -8,6 +8,14 @@
/** \name Shadow pipeline
* \{ */
GPU_SHADER_CREATE_INFO(eevee_shadow_clipmap_clear)
.do_static_compilation(true)
.local_group_size(SHADOW_CLIPMAP_GROUP_SIZE)
.storage_buf(0, Qualifier::WRITE, "ShadowTileMapClip", "tilemaps_clip_buf[]")
.push_constant(Type::INT, "tilemaps_clip_buf_len")
.additional_info("eevee_shared")
.compute_source("eevee_shadow_clipmap_clear_comp.glsl");
GPU_SHADER_CREATE_INFO(eevee_shadow_tilemap_bounds)
.do_static_compilation(true)
.local_group_size(SHADOW_BOUNDS_GROUP_SIZE)