Blender V5.0
eevee_test.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include "testing/testing.h"
6
7#include "GPU_batch.hh"
8#include "GPU_context.hh"
9#include "draw_shader.hh"
10#include "draw_testing.hh"
17
18namespace blender::draw {
19
20using namespace blender::eevee;
21
22/* Replace with template version that is not GPU only. */
25
27{
29 ShadowTileMapDataBuf tilemaps_data = {"tilemaps_data"};
30 ShadowTileDataBuf tiles_data = {"tiles_data"};
31 ShadowTileMapClipBuf tilemaps_clip = {"tilemaps_clip"};
32 ShadowPageCacheBuf pages_cached_data_ = {"pages_cached_data_"};
33
34 int tiles_index = 1;
35 int tile_lod0 = tiles_index * SHADOW_TILEDATA_PER_TILEMAP + 5;
36 int tile_lod1 = tile_lod0 + square_i(SHADOW_TILEMAP_RES);
37
38 {
39 ShadowTileMapData tilemap = {};
40 tilemap.tiles_index = tiles_index * SHADOW_TILEDATA_PER_TILEMAP;
43
44 tilemaps_data.append(tilemap);
45
46 tilemaps_data.push_update();
47 }
48 {
50
51 tile.page = uint3(1, 2, 0);
52 tile.is_used = true;
53 tile.do_update = true;
54 tiles_data[tile_lod0] = shadow_tile_pack(tile);
55
56 tile.page = uint3(3, 2, 4);
57 tile.is_used = false;
58 tile.do_update = false;
59 tiles_data[tile_lod1] = shadow_tile_pack(tile);
60
61 tiles_data.push_update();
62 }
63
64 gpu::Shader *sh = GPU_shader_create_from_info_name("eevee_shadow_tilemap_init");
65
66 PassSimple pass("Test");
67 pass.shader_set(sh);
68 pass.bind_ssbo("tilemaps_buf", tilemaps_data);
69 pass.bind_ssbo("tilemaps_clip_buf", tilemaps_clip);
70 pass.bind_ssbo("tiles_buf", tiles_data);
71 pass.bind_ssbo("pages_cached_buf", pages_cached_data_);
72 pass.dispatch(int3(1, 1, tilemaps_data.size()));
74
75 Manager manager;
76 manager.submit(pass);
77
78 tilemaps_data.read();
79 tiles_data.read();
80
81 EXPECT_EQ(tilemaps_data[0].grid_offset, int2(0));
82 EXPECT_EQ(shadow_tile_unpack(tiles_data[tile_lod0]).page, uint3(1, 2, 0));
83 EXPECT_EQ(shadow_tile_unpack(tiles_data[tile_lod0]).is_used, false);
84 EXPECT_EQ(shadow_tile_unpack(tiles_data[tile_lod0]).do_update, true);
85 EXPECT_EQ(shadow_tile_unpack(tiles_data[tile_lod1]).page, uint3(3, 2, 4));
86 EXPECT_EQ(shadow_tile_unpack(tiles_data[tile_lod1]).is_used, false);
87 EXPECT_EQ(shadow_tile_unpack(tiles_data[tile_lod1]).do_update, true);
88
90
94}
95DRAW_TEST(eevee_shadow_shift_clear)
96
98{
100 ShadowTileMapDataBuf tilemaps_data = {"tilemaps_data"};
101 ShadowTileDataBuf tiles_data = {"tiles_data"};
102 StorageArrayBuffer<ShadowTileMapClip, SHADOW_MAX_TILEMAP> tilemaps_clip = {"tilemaps_clip"};
103 ShadowPageCacheBuf pages_cached_data = {"pages_cached_data"};
104
105 auto tile_co_to_page = [](int2 co) {
106 int page = co.x + co.y * SHADOW_TILEMAP_RES;
107 return uint3((page % SHADOW_PAGE_PER_ROW),
109 (page / SHADOW_PAGE_PER_LAYER));
110 };
111
112 {
113 ShadowTileMapClip clip = {};
114 clip.clip_near_stored = 0.0;
115 clip.clip_far_stored = 1.0;
116 clip.clip_near = 0x00000000; /* floatBitsToOrderedInt(0.0) */
117 clip.clip_far = 0x3F800000; /* floatBitsToOrderedInt(1.0) */
118
119 tilemaps_clip[0] = clip;
120
121 tilemaps_clip.push_update();
122 }
123 {
124 ShadowTileMapData tilemap = {};
125 tilemap.tiles_index = 0;
126 tilemap.clip_data_index = 0;
127 tilemap.grid_shift = int2(-1, 2);
129
130 tilemaps_data.append(tilemap);
131
132 tilemaps_data.push_update();
133 }
134 {
135 ShadowTileData tile = {};
136
137 for (auto x : IndexRange(SHADOW_TILEMAP_RES)) {
138 for (auto y : IndexRange(SHADOW_TILEMAP_RES)) {
139 tile.is_allocated = true;
140 tile.is_rendered = true;
141 tile.do_update = true;
142 tile.page = tile_co_to_page(int2(x, y));
143 tiles_data[x + y * SHADOW_TILEMAP_RES] = shadow_tile_pack(tile);
144 }
145 }
146
147 tiles_data.push_update();
148 }
149
150 gpu::Shader *sh = GPU_shader_create_from_info_name("eevee_shadow_tilemap_init");
151
152 PassSimple pass("Test");
153 pass.shader_set(sh);
154 pass.bind_ssbo("tilemaps_buf", tilemaps_data);
155 pass.bind_ssbo("tilemaps_clip_buf", tilemaps_clip);
156 pass.bind_ssbo("tiles_buf", tiles_data);
157 pass.bind_ssbo("pages_cached_buf", pages_cached_data);
158 pass.dispatch(int3(1, 1, tilemaps_data.size()));
160
161 Manager manager;
162 manager.submit(pass);
163
164 tilemaps_data.read();
165 tiles_data.read();
166
167 EXPECT_EQ(tilemaps_data[0].grid_offset, int2(0));
168 EXPECT_EQ(shadow_tile_unpack(tiles_data[0]).page,
169 tile_co_to_page(int2(SHADOW_TILEMAP_RES - 1, 2)));
170 EXPECT_EQ(shadow_tile_unpack(tiles_data[0]).do_update, true);
171 EXPECT_EQ(shadow_tile_unpack(tiles_data[0]).is_rendered, false);
172 EXPECT_EQ(shadow_tile_unpack(tiles_data[0]).is_allocated, true);
173 EXPECT_EQ(shadow_tile_unpack(tiles_data[1]).page, tile_co_to_page(int2(0, 2)));
174 EXPECT_EQ(shadow_tile_unpack(tiles_data[1]).do_update, false);
175 EXPECT_EQ(shadow_tile_unpack(tiles_data[1]).is_rendered, false);
176 EXPECT_EQ(shadow_tile_unpack(tiles_data[1]).is_allocated, true);
177 EXPECT_EQ(shadow_tile_unpack(tiles_data[0 + SHADOW_TILEMAP_RES * 2]).page,
178 tile_co_to_page(int2(SHADOW_TILEMAP_RES - 1, 4)));
179 EXPECT_EQ(shadow_tile_unpack(tiles_data[0 + SHADOW_TILEMAP_RES * 2]).do_update, true);
180 EXPECT_EQ(shadow_tile_unpack(tiles_data[0 + SHADOW_TILEMAP_RES * 2]).is_rendered, false);
181 EXPECT_EQ(shadow_tile_unpack(tiles_data[0 + SHADOW_TILEMAP_RES * 2]).is_allocated, true);
182 EXPECT_EQ(shadow_tile_unpack(tiles_data[1 + SHADOW_TILEMAP_RES * 2]).page,
183 tile_co_to_page(int2(0, 4)));
184 EXPECT_EQ(shadow_tile_unpack(tiles_data[1 + SHADOW_TILEMAP_RES * 2]).do_update, false);
185 EXPECT_EQ(shadow_tile_unpack(tiles_data[1 + SHADOW_TILEMAP_RES * 2]).is_rendered, false);
186 EXPECT_EQ(shadow_tile_unpack(tiles_data[1 + SHADOW_TILEMAP_RES * 2]).is_allocated, true);
187
189
190 GPU_shader_free(sh);
193}
194DRAW_TEST(eevee_shadow_shift)
195
197{
199 using namespace blender::math;
200 StorageVectorBuffer<uint, 128> past_casters_updated = {"PastCastersUpdated"};
201 StorageVectorBuffer<uint, 128> curr_casters_updated = {"CurrCastersUpdated"};
202
203 Manager manager;
204 {
205 /* Simulate 1 object moving and 1 object static with changing resource index. */
208 float3(1.0f), Quaternion::identity(), float3(0.5f));
209 float3 half_extent = float3(0.24f, 0.249f, 0.001f);
210
211 {
212 manager.begin_sync();
213 ResourceHandle hdl = manager.resource_handle(obmat, float3(0.5f, 0.5f, -1.0f), half_extent);
214 manager.resource_handle(obmat2);
215 manager.end_sync();
216 past_casters_updated.append(hdl.resource_index());
217 past_casters_updated.push_update();
218 }
219 {
220 manager.begin_sync();
221 manager.resource_handle(obmat2);
222 ResourceHandle hdl = manager.resource_handle(obmat, float3(-1.0f, 0.5f, -1.0f), half_extent);
223 manager.end_sync();
224 curr_casters_updated.append(hdl.resource_index());
225 curr_casters_updated.push_update();
226 }
227 }
228
229 ShadowTileMapDataBuf tilemaps_data = {"tilemaps_data"};
230 ShadowTileDataBuf tiles_data = {"tiles_data"};
231 tiles_data.clear_to_zero();
232
233 {
236 tilemaps_data.append(tilemap);
237 }
238 {
241 tilemaps_data.append(tilemap);
242 }
243
244 tilemaps_data.push_update();
245
246 gpu::Shader *sh = GPU_shader_create_from_info_name("eevee_shadow_tag_update");
247
248 PassSimple pass("Test");
249 pass.shader_set(sh);
250 pass.bind_ssbo("tilemaps_buf", tilemaps_data);
251 pass.bind_ssbo("tiles_buf", tiles_data);
252 pass.bind_ssbo("bounds_buf", &manager.bounds_buf.previous());
253 pass.bind_ssbo("resource_ids_buf", past_casters_updated);
254 pass.dispatch(int3(past_casters_updated.size(), 1, tilemaps_data.size()));
255 pass.bind_ssbo("bounds_buf", &manager.bounds_buf.current());
256 pass.bind_ssbo("resource_ids_buf", curr_casters_updated);
257 pass.dispatch(int3(curr_casters_updated.size(), 1, tilemaps_data.size()));
259
260 draw::View view("Test");
262 math::projection::orthographic(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f));
263
264 manager.submit(pass, view);
265
266 tiles_data.read();
267
269 StringRefNull expected_lod0 =
270 "--------------------------------"
271 "--------------------------------"
272 "--------------------------------"
273 "--------------------------------"
274 "--------------------------------"
275 "--------------------------------"
276 "--------------------------------"
277 "--------------------------------"
278 "--------------------------------"
279 "--------------------------------"
280 "--------------------------------"
281 "--------------------------------"
282 "--------------------------------"
283 "--------------------------------"
284 "--------------------------------"
285 "--------------------------------"
286 "--------------------------------"
287 "--------------------------------"
288 "--------------------------------"
289 "--------------------------------"
290 "xxxx----------------xxxxxxxx----"
291 "xxxx----------------xxxxxxxx----"
292 "xxxx----------------xxxxxxxx----"
293 "xxxx----------------xxxxxxxx----"
294 "xxxx----------------xxxxxxxx----"
295 "xxxx----------------xxxxxxxx----"
296 "xxxx----------------xxxxxxxx----"
297 "xxxx----------------xxxxxxxx----"
298 "--------------------------------"
299 "--------------------------------"
300 "--------------------------------"
301 "--------------------------------";
302 StringRefNull expected_lod1 =
303 "----------------"
304 "----------------"
305 "----------------"
306 "----------------"
307 "----------------"
308 "----------------"
309 "----------------"
310 "----------------"
311 "----------------"
312 "----------------"
313 "xx--------xxxx--"
314 "xx--------xxxx--"
315 "xx--------xxxx--"
316 "xx--------xxxx--"
317 "----------------"
318 "----------------";
319 StringRefNull expected_lod2 =
320 "--------"
321 "--------"
322 "--------"
323 "--------"
324 "--------"
325 "x----xx-"
326 "x----xx-"
327 "--------";
328 StringRefNull expected_lod3 =
329 "----"
330 "----"
331 "x-xx"
332 "x-xx";
333 StringRefNull expected_lod4 =
334 "--"
335 "xx";
336 StringRefNull expected_lod5 = "x";
337 const uint lod0_len = SHADOW_TILEMAP_LOD0_LEN;
338 const uint lod1_len = SHADOW_TILEMAP_LOD1_LEN;
339 const uint lod2_len = SHADOW_TILEMAP_LOD2_LEN;
340 const uint lod3_len = SHADOW_TILEMAP_LOD3_LEN;
341 const uint lod4_len = SHADOW_TILEMAP_LOD4_LEN;
342 const uint lod5_len = SHADOW_TILEMAP_LOD5_LEN;
343
344 auto stringify_result = [&](uint start, uint len) -> std::string {
345 std::string result;
346 for (auto i : IndexRange(start, len)) {
347 result += (shadow_tile_unpack(tiles_data[i]).do_update) ? "x" : "-";
348 }
349 return result;
350 };
351
352 EXPECT_EQ(stringify_result(0, lod0_len), expected_lod0);
353 EXPECT_EQ(stringify_result(lod0_len, lod1_len), expected_lod1);
354 EXPECT_EQ(stringify_result(lod0_len + lod1_len, lod2_len), expected_lod2);
355 EXPECT_EQ(stringify_result(lod0_len + lod1_len + lod2_len, lod3_len), expected_lod3);
356 EXPECT_EQ(stringify_result(lod0_len + lod1_len + lod2_len + lod3_len, lod4_len), expected_lod4);
357 EXPECT_EQ(stringify_result(lod0_len + lod1_len + lod2_len + lod3_len + lod4_len, lod5_len),
358 expected_lod5);
359
361
362 GPU_shader_free(sh);
365}
366DRAW_TEST(eevee_shadow_tag_update)
367
369{
371 ShadowTileMapDataBuf tilemaps_data = {"tilemaps_data"};
372 ShadowTileDataBuf tiles_data = {"tiles_data"};
373 ShadowPageHeapBuf pages_free_data = {"PagesFreeBuf"};
374 ShadowPageCacheBuf pages_cached_data = {"PagesCachedBuf"};
375 ShadowPagesInfoDataBuf pages_infos_data = {"PagesInfosBuf"};
376
377 int tiles_index = 1;
378 int tile_orphaned_cached = tiles_index * SHADOW_TILEDATA_PER_TILEMAP + 5;
379 int tile_orphaned_allocated = tiles_index * SHADOW_TILEDATA_PER_TILEMAP + 6;
380 int tile_used_cached = tiles_index * SHADOW_TILEDATA_PER_TILEMAP + 260;
381 int tile_used_allocated = tiles_index * SHADOW_TILEDATA_PER_TILEMAP + 32;
382 int tile_used_unallocated = tiles_index * SHADOW_TILEDATA_PER_TILEMAP + 64;
383 int tile_unused_cached = tiles_index * SHADOW_TILEDATA_PER_TILEMAP + 9;
384 int tile_unused_allocated = tiles_index * SHADOW_TILEDATA_PER_TILEMAP + 8;
385 int page_free_count = SHADOW_MAX_PAGE - 6;
386
387 for (uint i : IndexRange(2, page_free_count)) {
388 uint3 page = uint3((i % SHADOW_PAGE_PER_ROW),
391 pages_free_data[i] = shadow_page_pack(page);
392 }
393 pages_free_data.push_update();
394
395 pages_infos_data.page_free_count = page_free_count;
396 pages_infos_data.page_alloc_count = 0;
397 pages_infos_data.page_cached_next = 2u;
398 pages_infos_data.page_cached_start = 0u;
399 pages_infos_data.page_cached_end = 2u;
400 pages_infos_data.push_update();
401
402 for (uint i : IndexRange(pages_cached_data.size())) {
403 pages_cached_data[i] = uint2(-1, -1);
404 }
405 pages_cached_data[0] = uint2(0, tile_orphaned_cached);
406 pages_cached_data[1] = uint2(1, tile_used_cached);
407 pages_cached_data.push_update();
408
409 {
410 ShadowTileData tile = {};
411
412 tiles_data.clear_to_zero();
413 tiles_data.read();
414
415 /* is_orphaned = true */
416 tile.is_used = false;
417 tile.do_update = true;
418
419 tile.is_cached = true;
420 tile.is_allocated = false;
421 tiles_data[tile_orphaned_cached] = shadow_tile_pack(tile);
422
423 tile.is_cached = false;
424 tile.is_allocated = true;
425 tiles_data[tile_orphaned_allocated] = shadow_tile_pack(tile);
426
427 /* is_orphaned = false */
428 tile.do_update = false;
429 tile.is_used = true;
430
431 tile.is_cached = true;
432 tile.is_allocated = false;
433 tiles_data[tile_used_cached] = shadow_tile_pack(tile);
434
435 tile.is_cached = false;
436 tile.is_allocated = true;
437 tiles_data[tile_used_allocated] = shadow_tile_pack(tile);
438
439 tile.is_cached = false;
440 tile.is_allocated = false;
441 tiles_data[tile_used_unallocated] = shadow_tile_pack(tile);
442
443 tile.is_used = false;
444 tile.is_cached = true;
445 tile.is_allocated = false;
446 tiles_data[tile_unused_cached] = shadow_tile_pack(tile);
447
448 tile.is_cached = false;
449 tile.is_allocated = true;
450 tiles_data[tile_unused_allocated] = shadow_tile_pack(tile);
451
452 tiles_data.push_update();
453 }
454 {
455 ShadowTileMapData tilemap = {};
456 tilemap.tiles_index = tiles_index * SHADOW_TILEDATA_PER_TILEMAP;
457 tilemaps_data.append(tilemap);
458 tilemaps_data.push_update();
459 }
460
461 gpu::Shader *sh = GPU_shader_create_from_info_name("eevee_shadow_page_free");
462
463 PassSimple pass("Test");
464 pass.shader_set(sh);
465 pass.bind_ssbo("tilemaps_buf", tilemaps_data);
466 pass.bind_ssbo("tiles_buf", tiles_data);
467 pass.bind_ssbo("pages_infos_buf", pages_infos_data);
468 pass.bind_ssbo("pages_free_buf", pages_free_data);
469 pass.bind_ssbo("pages_cached_buf", pages_cached_data);
470 pass.dispatch(int3(1, 1, tilemaps_data.size()));
472
473 Manager manager;
474 manager.submit(pass);
475
476 tiles_data.read();
477 pages_infos_data.read();
478
479 EXPECT_EQ(shadow_tile_unpack(tiles_data[tile_orphaned_cached]).is_cached, false);
480 EXPECT_EQ(shadow_tile_unpack(tiles_data[tile_orphaned_cached]).is_allocated, false);
481 EXPECT_EQ(shadow_tile_unpack(tiles_data[tile_orphaned_allocated]).is_cached, false);
482 EXPECT_EQ(shadow_tile_unpack(tiles_data[tile_orphaned_allocated]).is_allocated, false);
483 EXPECT_EQ(shadow_tile_unpack(tiles_data[tile_used_cached]).is_cached, false);
484 EXPECT_EQ(shadow_tile_unpack(tiles_data[tile_used_cached]).is_allocated, true);
485 EXPECT_EQ(shadow_tile_unpack(tiles_data[tile_used_allocated]).is_cached, false);
486 EXPECT_EQ(shadow_tile_unpack(tiles_data[tile_used_allocated]).is_allocated, true);
487 EXPECT_EQ(shadow_tile_unpack(tiles_data[tile_used_unallocated]).is_cached, false);
488 EXPECT_EQ(shadow_tile_unpack(tiles_data[tile_used_unallocated]).is_allocated, false);
489 EXPECT_EQ(shadow_tile_unpack(tiles_data[tile_unused_cached]).is_cached, true);
490 EXPECT_EQ(shadow_tile_unpack(tiles_data[tile_unused_cached]).is_allocated, false);
491 EXPECT_EQ(shadow_tile_unpack(tiles_data[tile_unused_allocated]).is_cached, true);
492 EXPECT_EQ(shadow_tile_unpack(tiles_data[tile_unused_allocated]).is_allocated, false);
493 EXPECT_EQ(pages_infos_data.page_alloc_count, 1);
494 EXPECT_EQ(pages_infos_data.page_free_count, page_free_count + 2);
495 EXPECT_EQ(pages_infos_data.page_cached_next, 3);
496 EXPECT_EQ(pages_infos_data.page_cached_end, 2);
497
499
500 GPU_shader_free(sh);
503}
504DRAW_TEST(eevee_shadow_free)
505
507 private:
508 ShadowTileDataBuf tiles_data = {"tiles_data"};
509 ShadowPageHeapBuf pages_free_data = {"PagesFreeBuf"};
510 ShadowPageCacheBuf pages_cached_data = {"PagesCachedBuf"};
511 ShadowPagesInfoDataBuf pages_infos_data = {"PagesInfosBuf"};
512 StorageBuffer<DispatchCommand> clear_dispatch_buf;
513 StorageBuffer<DrawCommand> tile_draw_buf;
514 ShadowStatisticsBuf statistics_buf = {"statistics_buf"};
515
516 public:
517 TestDefrag(int allocation_count,
518 int descriptor_offset,
520 StringRefNull expect)
521 {
524 pages_free_data[i] = page.x | (page.y << 16u);
525 }
526
527 for (uint i : IndexRange(tiles_data.size())) {
528 tiles_data[i] = 0;
529 }
530
531 int free_count = SHADOW_MAX_PAGE;
532 int tile_index = 0;
533
534 for (uint i : IndexRange(pages_cached_data.size())) {
535 pages_cached_data[i] = uint2(-1, -1);
536 }
537
538 int cached_index = descriptor_offset;
539 int hole_count = 0;
540 int inserted_count = 0;
541 ShadowTileData tile = {};
542 tile.is_cached = true;
543 for (char c : descriptor) {
544 switch (c) {
545 case 'c':
546 tile.cache_index = cached_index++ % SHADOW_MAX_PAGE;
547 pages_cached_data[tile.cache_index] = uint2(pages_free_data[--free_count], tile_index);
548 tiles_data[tile_index++] = shadow_tile_pack(tile);
549 break;
550 case 'f':
551 pages_cached_data[cached_index++ % SHADOW_MAX_PAGE] = uint2(-1, -1);
552 hole_count++;
553 break;
554 case 'i':
555 tile.cache_index = (cached_index + inserted_count++) % SHADOW_MAX_PAGE;
556 pages_cached_data[tile.cache_index] = uint2(pages_free_data[--free_count], tile_index);
557 tiles_data[tile_index++] = shadow_tile_pack(tile);
558 break;
559 default:
560 break;
561 }
562 }
563
564 pages_infos_data.page_alloc_count = allocation_count;
565 pages_infos_data.page_cached_next = cached_index + inserted_count;
566 pages_infos_data.page_free_count = free_count;
567 pages_infos_data.page_cached_start = descriptor_offset;
568 pages_infos_data.page_cached_end = cached_index;
569
570 tiles_data.push_update();
571 pages_infos_data.push_update();
572 pages_free_data.push_update();
573 pages_cached_data.push_update();
574
575 gpu::Shader *sh = GPU_shader_create_from_info_name("eevee_shadow_page_defrag");
576
577 PassSimple pass("Test");
578 pass.shader_set(sh);
579 pass.bind_ssbo("tiles_buf", tiles_data);
580 pass.bind_ssbo("pages_infos_buf", pages_infos_data);
581 pass.bind_ssbo("pages_free_buf", pages_free_data);
582 pass.bind_ssbo("pages_cached_buf", pages_cached_data);
583 pass.bind_ssbo("clear_dispatch_buf", clear_dispatch_buf);
584 pass.bind_ssbo("tile_draw_buf", tile_draw_buf);
585 pass.bind_ssbo("statistics_buf", statistics_buf);
586 pass.dispatch(int3(1, 1, 1));
588
589 Manager manager;
590 manager.submit(pass);
591
592 tiles_data.read();
593 pages_cached_data.read();
594 pages_infos_data.read();
595
596 std::string result;
597 int expect_cached_len = 0;
598 for (auto i : IndexRange(descriptor_offset, descriptor.size())) {
599 if (pages_cached_data[i % SHADOW_MAX_PAGE].y != -1) {
600 result += 'c';
601 expect_cached_len++;
602 }
603 else {
604 result += 'f';
605 }
606 }
607 EXPECT_EQ(expect, result);
608
609 allocation_count = min_ii(allocation_count, SHADOW_MAX_PAGE);
610
611 int additional_pages = max_ii(0, allocation_count - free_count);
612 int expected_free_count = max_ii(free_count, allocation_count);
613 int expected_start = descriptor_offset + hole_count + additional_pages;
614 int result_cached_len = pages_infos_data.page_cached_end - pages_infos_data.page_cached_start;
615
616 if (expected_start > SHADOW_MAX_PAGE) {
617 expected_start -= SHADOW_MAX_PAGE;
618 }
619
620 EXPECT_EQ(expected_free_count, pages_infos_data.page_free_count);
621 EXPECT_EQ(expected_start, pages_infos_data.page_cached_start);
622 EXPECT_EQ(expect_cached_len, result_cached_len);
623 EXPECT_EQ(pages_infos_data.page_cached_end, pages_infos_data.page_cached_next);
624
626
627 GPU_shader_free(sh);
629 }
630};
631
633{
634 TestDefrag(0, 0, "cfi", "fcc");
635 TestDefrag(0, 0, "fci", "fcc");
636 TestDefrag(0, 47, "ccfcffccfcfciiiii", "fffffcccccccccccc");
637 TestDefrag(10, SHADOW_MAX_PAGE - 5, "ccfcffccfcfciiiii", "fffffcccccccccccc");
638 TestDefrag(SHADOW_MAX_PAGE - 8, 30, "ccfcffccfcfciiiii", "fffffffffcccccccc");
639 TestDefrag(SHADOW_MAX_PAGE - 4, 30, "ccfcffccfcfciiiii", "fffffffffffffcccc");
640 /* Over allocation but should not crash. */
641 TestDefrag(SHADOW_MAX_PAGE + 4, 30, "ccfcffccfcfciiiii", "fffffffffffffffff");
642}
643DRAW_TEST(eevee_shadow_defrag)
644
646 private:
647 ShadowTileMapDataBuf tilemaps_data = {"tilemaps_data"};
648 ShadowTileDataBuf tiles_data = {"tiles_data"};
649 ShadowPageHeapBuf pages_free_data = {"PagesFreeBuf"};
650 ShadowPageCacheBuf pages_cached_data = {"PagesCachedBuf"};
651 ShadowPagesInfoDataBuf pages_infos_data = {"PagesInfosBuf"};
652 ShadowStatisticsBuf statistics_buf = {"statistics_buf"};
653
654 public:
655 TestAlloc(int page_free_count)
656 {
658 int tiles_index = 1;
659
660 for (int i : IndexRange(SHADOW_MAX_TILE)) {
661 tiles_data[i] = 0;
662 }
663
664 for (uint i : IndexRange(0, page_free_count)) {
666 pages_free_data[i] = page.x | (page.y << 16u);
667 }
668 pages_free_data.push_update();
669 pages_cached_data.push_update();
670
671 pages_infos_data.page_free_count = page_free_count;
672 pages_infos_data.page_alloc_count = 1;
673 pages_infos_data.page_cached_next = 0u;
674 pages_infos_data.page_cached_start = 0u;
675 pages_infos_data.page_cached_end = 0u;
676 pages_infos_data.push_update();
677
678 statistics_buf.view_needed_count = 0;
679 statistics_buf.push_update();
680
681 int tile_allocated = tiles_index * SHADOW_TILEDATA_PER_TILEMAP + 5;
682 int tile_free = tiles_index * SHADOW_TILEDATA_PER_TILEMAP + 6;
683
684 {
685 ShadowTileData tile = {};
686
687 tile.is_used = true;
688 tile.do_update = false;
689
690 tile.is_cached = false;
691 tile.is_allocated = false;
692 tiles_data[tile_free] = shadow_tile_pack(tile);
693
694 tile.is_cached = false;
695 tile.is_allocated = true;
696 tiles_data[tile_allocated] = shadow_tile_pack(tile);
697
698 tiles_data.push_update();
699 }
700 {
701 ShadowTileMapData tilemap = {};
702 tilemap.tiles_index = tiles_index * SHADOW_TILEDATA_PER_TILEMAP;
703 tilemaps_data.append(tilemap);
704 tilemaps_data.push_update();
705 }
706
707 gpu::Shader *sh = GPU_shader_create_from_info_name("eevee_shadow_page_allocate");
708
709 PassSimple pass("Test");
710 pass.shader_set(sh);
711 pass.bind_ssbo("tilemaps_buf", tilemaps_data);
712 pass.bind_ssbo("tiles_buf", tiles_data);
713 pass.bind_ssbo("pages_infos_buf", pages_infos_data);
714 pass.bind_ssbo("pages_free_buf", pages_free_data);
715 pass.bind_ssbo("pages_cached_buf", pages_cached_data);
716 pass.bind_ssbo("statistics_buf", statistics_buf);
717 pass.dispatch(int3(1, 1, tilemaps_data.size()));
719
720 Manager manager;
721 manager.submit(pass);
722
723 tiles_data.read();
724 pages_infos_data.read();
725
726 bool alloc_success = page_free_count >= 1;
727
728 EXPECT_EQ(shadow_tile_unpack(tiles_data[tile_free]).do_update, alloc_success);
729 EXPECT_EQ(shadow_tile_unpack(tiles_data[tile_free]).is_allocated, alloc_success);
730 EXPECT_EQ(shadow_tile_unpack(tiles_data[tile_allocated]).do_update, false);
731 EXPECT_EQ(shadow_tile_unpack(tiles_data[tile_allocated]).is_allocated, true);
732 EXPECT_EQ(pages_infos_data.page_free_count, page_free_count - 1);
733
735
736 GPU_shader_free(sh);
739 }
740};
741
743{
745 TestAlloc(1);
746 TestAlloc(0);
747}
748DRAW_TEST(eevee_shadow_alloc)
749
751{
753 ShadowTileMapDataBuf tilemaps_data = {"tilemaps_data"};
754 ShadowTileDataBuf tiles_data = {"tiles_data"};
755 ShadowPageHeapBuf pages_free_data = {"PagesFreeBuf"};
756 ShadowPageCacheBuf pages_cached_data = {"PagesCachedBuf"};
757 ShadowPagesInfoDataBuf pages_infos_data = {"PagesInfosBuf"};
758 ShadowStatisticsBuf statistics_buf = {"statistics_buf"};
759 ShadowRenderViewBuf render_views_buf = {"render_views_buf"};
761 "tilemaps_clip"};
762
763 const uint lod0_len = SHADOW_TILEMAP_LOD0_LEN;
764 const uint lod1_len = SHADOW_TILEMAP_LOD1_LEN;
765 const uint lod2_len = SHADOW_TILEMAP_LOD2_LEN;
766 const uint lod3_len = SHADOW_TILEMAP_LOD3_LEN;
767 const uint lod4_len = SHADOW_TILEMAP_LOD4_LEN;
768
769 const uint lod0_ofs = 0;
770 const uint lod1_ofs = lod0_len;
771 const uint lod2_ofs = lod1_ofs + lod1_len;
772 const uint lod3_ofs = lod2_ofs + lod2_len;
773 const uint lod4_ofs = lod3_ofs + lod3_len;
774 const uint lod5_ofs = lod4_ofs + lod4_len;
775
777 tiles_data[i] = SHADOW_NO_DATA;
778 }
779
780 {
781 ShadowTileData tile = {};
782 tile.is_used = true;
783 tile.is_allocated = true;
784
785 tile.page = uint3(1, 0, 0);
786 tile.do_update = false;
787 tiles_data[lod0_ofs] = shadow_tile_pack(tile);
788
789 tile.page = uint3(2, 0, 0);
790 tile.do_update = false;
791 tiles_data[lod1_ofs] = shadow_tile_pack(tile);
792
793 tile.page = uint3(3, 0, 0);
794 tile.do_update = true;
795 tiles_data[lod2_ofs] = shadow_tile_pack(tile);
796
797 tile.page = uint3(0, 1, 0);
798 tile.do_update = true;
799 tiles_data[lod3_ofs] = shadow_tile_pack(tile);
800
801 tile.page = uint3(1, 1, 0);
802 tile.do_update = true;
803 tiles_data[lod4_ofs] = shadow_tile_pack(tile);
804
805 tile.page = uint3(2, 1, 0);
806 tile.do_update = true;
807 tiles_data[lod5_ofs] = shadow_tile_pack(tile);
808
809 tile.page = uint3(3, 1, 0);
810 tile.do_update = true;
811 tiles_data[lod0_ofs + 31] = shadow_tile_pack(tile);
812
813 tile.page = uint3(0, 2, 0);
814 tile.do_update = true;
815 tiles_data[lod3_ofs + 8] = shadow_tile_pack(tile);
816
817 tile.page = uint3(1, 2, 0);
818 tile.do_update = true;
819 tiles_data[lod0_ofs + 32 * 16 - 8] = shadow_tile_pack(tile);
820
821 tiles_data.push_update();
822 }
823 {
824 ShadowTileMapData tilemap = {};
825 tilemap.viewmat = float4x4::identity();
826 tilemap.tiles_index = 0;
827 tilemap.clip_data_index = 0;
828 tilemap.clip_far = 10.0f;
829 tilemap.clip_near = 1.0f;
830 tilemap.half_size = 1.0f;
832 tilemaps_data.append(tilemap);
833
834 tilemaps_data.push_update();
835 }
836 {
837 ShadowTileMapClip clip = {};
838 clip.clip_far_stored = 10.0f;
839 clip.clip_near_stored = 1.0f;
840 tilemaps_clip[0] = clip;
841 tilemaps_clip.push_update();
842 }
843 {
844 statistics_buf.view_needed_count = 0;
845 statistics_buf.push_update();
846 }
847 {
848 pages_infos_data.page_free_count = -5;
849 pages_infos_data.page_alloc_count = 0;
850 pages_infos_data.page_cached_next = 0u;
851 pages_infos_data.page_cached_start = 0u;
852 pages_infos_data.page_cached_end = 0u;
853 pages_infos_data.push_update();
854 }
855
856 Texture tilemap_tx = {"tilemap_tx"};
857 tilemap_tx.ensure_2d(blender::gpu::TextureFormat::UINT_32,
861 tilemap_tx.clear(uint4(0));
862
863 StorageArrayBuffer<ViewMatrices, DRW_VIEW_MAX> shadow_multi_view_buf = {"ShadowMultiView"};
864 StorageBuffer<DispatchCommand> clear_dispatch_buf;
865 StorageBuffer<DrawCommand> tile_draw_buf;
866 StorageArrayBuffer<uint, SHADOW_MAX_PAGE> dst_coord_buf = {"dst_coord_buf"};
867 StorageArrayBuffer<uint, SHADOW_MAX_PAGE> src_coord_buf = {"src_coord_buf"};
868 StorageArrayBuffer<uint, SHADOW_RENDER_MAP_SIZE> render_map_buf = {"render_map_buf"};
869 StorageArrayBuffer<uint, SHADOW_VIEW_MAX> viewport_index_buf = {"viewport_index_buf"};
870
871 render_map_buf.clear_to_zero();
872
873 gpu::Shader *sh = GPU_shader_create_from_info_name("eevee_shadow_tilemap_finalize");
874 PassSimple pass("Test");
875 pass.shader_set(sh);
876 pass.bind_ssbo("tilemaps_buf", tilemaps_data);
877 pass.bind_ssbo("tiles_buf", tiles_data);
878 pass.bind_ssbo("pages_infos_buf", pages_infos_data);
879 pass.bind_ssbo("statistics_buf", statistics_buf);
880 pass.bind_ssbo("view_infos_buf", shadow_multi_view_buf);
881 pass.bind_ssbo("render_view_buf", render_views_buf);
882 pass.bind_ssbo("tilemaps_clip_buf", tilemaps_clip);
883 pass.bind_image("tilemaps_img", tilemap_tx);
884 pass.dispatch(int3(1, 1, tilemaps_data.size()));
886
887 gpu::Shader *sh2 = GPU_shader_create_from_info_name("eevee_shadow_tilemap_rendermap");
888 pass.shader_set(sh2);
889 pass.bind_ssbo("statistics_buf", statistics_buf);
890 pass.bind_ssbo("render_view_buf", render_views_buf);
891 pass.bind_ssbo("tiles_buf", tiles_data);
892 pass.bind_ssbo("clear_dispatch_buf", clear_dispatch_buf);
893 pass.bind_ssbo("tile_draw_buf", tile_draw_buf);
894 pass.bind_ssbo("dst_coord_buf", &dst_coord_buf);
895 pass.bind_ssbo("src_coord_buf", &src_coord_buf);
896 pass.bind_ssbo("render_map_buf", &render_map_buf);
897 pass.dispatch(int3(1, 1, SHADOW_VIEW_MAX));
899
900 Manager manager;
901 manager.submit(pass);
902
903 {
904 /* Check output views. */
905 shadow_multi_view_buf.read();
906
907 for (auto i : IndexRange(5)) {
908 EXPECT_EQ(shadow_multi_view_buf[i].viewmat, float4x4::identity());
909 EXPECT_EQ(shadow_multi_view_buf[i].viewinv, float4x4::identity());
910 }
911
912 EXPECT_EQ(shadow_multi_view_buf[0].winmat,
913 math::projection::perspective(-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 10.0f));
914 EXPECT_EQ(shadow_multi_view_buf[1].winmat,
915 math::projection::perspective(-1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 10.0f));
916 EXPECT_EQ(shadow_multi_view_buf[2].winmat,
917 math::projection::perspective(-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 10.0f));
918 EXPECT_EQ(shadow_multi_view_buf[3].winmat,
919 math::projection::perspective(-1.0f, -0.75f, -1.0f, -0.75f, 1.0f, 10.0f));
920 EXPECT_EQ(shadow_multi_view_buf[4].winmat,
921 math::projection::perspective(0.5f, 1.5f, -1.0f, 0.0f, 1.0f, 10.0f));
922 }
923
924 {
925 uint *pixels = tilemap_tx.read<uint32_t>(GPU_DATA_UINT);
926
927 std::string result;
928 for (auto y : IndexRange(SHADOW_TILEMAP_RES)) {
929 for (auto x : IndexRange(SHADOW_TILEMAP_RES)) {
931 result += std::to_string(tile.page.x + tile.page.y * SHADOW_PAGE_PER_ROW);
932 }
933 }
934
935 MEM_SAFE_FREE(pixels);
936
938 StringRefNull expected_pages =
939 "12334444555555556666666666666667"
940 "22334444555555556666666666666666"
941 "33334444555555556666666666666666"
942 "33334444555555556666666666666666"
943 "44444444555555556666666666666666"
944 "44444444555555556666666666666666"
945 "44444444555555556666666666666666"
946 "44444444555555556666666666666666"
947 "55555555555555556666666666666666"
948 "55555555555555556666666666666666"
949 "55555555555555556666666666666666"
950 "55555555555555556666666666666666"
951 "55555555555555556666666666666666"
952 "55555555555555556666666666666666"
953 "55555555555555556666666666666666"
954 "55555555555555556666666696666666"
955 "88888888666666666666666666666666"
956 "88888888666666666666666666666666"
957 "88888888666666666666666666666666"
958 "88888888666666666666666666666666"
959 "88888888666666666666666666666666"
960 "88888888666666666666666666666666"
961 "88888888666666666666666666666666"
962 "88888888666666666666666666666666"
963 "66666666666666666666666666666666"
964 "66666666666666666666666666666666"
965 "66666666666666666666666666666666"
966 "66666666666666666666666666666666"
967 "66666666666666666666666666666666"
968 "66666666666666666666666666666666"
969 "66666666666666666666666666666666"
970 "66666666666666666666666666666666";
971
972 EXPECT_EQ(expected_pages, result);
973 }
974
975 {
976 auto stringify_view = [](Span<uint> data) -> std::string {
977 std::string result;
978 for (auto x : data) {
979 result += (x == 0u) ? '-' : ((x == 0xFFFFFFFFu) ? 'x' : '0' + (x % 10));
980 }
981 return result;
982 };
983
985 StringRefNull expected_view0 =
986 "6-------------------------------"
987 "--------------------------------"
988 "--------------------------------"
989 "--------------------------------"
990 "--------------------------------"
991 "--------------------------------"
992 "--------------------------------"
993 "--------------------------------"
994 "--------------------------------"
995 "--------------------------------"
996 "--------------------------------"
997 "--------------------------------"
998 "--------------------------------"
999 "--------------------------------"
1000 "--------------------------------"
1001 "--------------------------------"
1002 "--------------------------------"
1003 "--------------------------------"
1004 "--------------------------------"
1005 "--------------------------------"
1006 "--------------------------------"
1007 "--------------------------------"
1008 "--------------------------------"
1009 "--------------------------------"
1010 "--------------------------------"
1011 "--------------------------------"
1012 "--------------------------------"
1013 "--------------------------------"
1014 "--------------------------------"
1015 "--------------------------------"
1016 "--------------------------------"
1017 "--------------------------------";
1018
1019 StringRefNull expected_view1 =
1020 "5-------------------------------"
1021 "--------------------------------"
1022 "--------------------------------"
1023 "--------------------------------"
1024 "--------------------------------"
1025 "--------------------------------"
1026 "--------------------------------"
1027 "--------------------------------"
1028 "--------------------------------"
1029 "--------------------------------"
1030 "--------------------------------"
1031 "--------------------------------"
1032 "--------------------------------"
1033 "--------------------------------"
1034 "--------------------------------"
1035 "--------------------------------"
1036 "--------------------------------"
1037 "--------------------------------"
1038 "--------------------------------"
1039 "--------------------------------"
1040 "--------------------------------"
1041 "--------------------------------"
1042 "--------------------------------"
1043 "--------------------------------"
1044 "--------------------------------"
1045 "--------------------------------"
1046 "--------------------------------"
1047 "--------------------------------"
1048 "--------------------------------"
1049 "--------------------------------"
1050 "--------------------------------"
1051 "--------------------------------";
1052
1053 StringRefNull expected_view2 =
1054 "4xxx----------------------------"
1055 "xxxx----------------------------"
1056 "8xxx----------------------------"
1057 "xxxx----------------------------"
1058 "--------------------------------"
1059 "--------------------------------"
1060 "--------------------------------"
1061 "--------------------------------"
1062 "--------------------------------"
1063 "--------------------------------"
1064 "--------------------------------"
1065 "--------------------------------"
1066 "--------------------------------"
1067 "--------------------------------"
1068 "--------------------------------"
1069 "--------------------------------"
1070 "--------------------------------"
1071 "--------------------------------"
1072 "--------------------------------"
1073 "--------------------------------"
1074 "--------------------------------"
1075 "--------------------------------"
1076 "--------------------------------"
1077 "--------------------------------"
1078 "--------------------------------"
1079 "--------------------------------"
1080 "--------------------------------"
1081 "--------------------------------"
1082 "--------------------------------"
1083 "--------------------------------"
1084 "--------------------------------"
1085 "--------------------------------";
1086
1087 StringRefNull expected_view3 =
1088 "3-------------------------------"
1089 "--------------------------------"
1090 "--------------------------------"
1091 "--------------------------------"
1092 "--------------------------------"
1093 "--------------------------------"
1094 "--------------------------------"
1095 "--------------------------------"
1096 "--------------------------------"
1097 "--------------------------------"
1098 "--------------------------------"
1099 "--------------------------------"
1100 "--------------------------------"
1101 "--------------------------------"
1102 "--------------------------------"
1103 "--------------------------------"
1104 "--------------------------------"
1105 "--------------------------------"
1106 "--------------------------------"
1107 "--------------------------------"
1108 "--------------------------------"
1109 "--------------------------------"
1110 "--------------------------------"
1111 "--------------------------------"
1112 "--------------------------------"
1113 "--------------------------------"
1114 "--------------------------------"
1115 "--------------------------------"
1116 "--------------------------------"
1117 "--------------------------------"
1118 "--------------------------------"
1119 "--------------------------------";
1120
1121 StringRefNull expected_view4 =
1122 "xxxxxxx7xxxxxxxx----------------"
1123 "xxxxxxxxxxxxxxxx----------------"
1124 "xxxxxxxxxxxxxxxx----------------"
1125 "xxxxxxxxxxxxxxxx----------------"
1126 "xxxxxxxxxxxxxxxx----------------"
1127 "xxxxxxxxxxxxxxxx----------------"
1128 "xxxxxxxxxxxxxxxx----------------"
1129 "xxxxxxxxxxxxxxxx----------------"
1130 "xxxxxxxxxxxxxxxx----------------"
1131 "xxxxxxxxxxxxxxxx----------------"
1132 "xxxxxxxxxxxxxxxx----------------"
1133 "xxxxxxxxxxxxxxxx----------------"
1134 "xxxxxxxxxxxxxxxx----------------"
1135 "xxxxxxxxxxxxxxxx----------------"
1136 "xxxxxxxxxxxxxxxx----------------"
1137 "9xxxxxxxxxxxxxxx----------------"
1138 "--------------------------------"
1139 "--------------------------------"
1140 "--------------------------------"
1141 "--------------------------------"
1142 "--------------------------------"
1143 "--------------------------------"
1144 "--------------------------------"
1145 "--------------------------------"
1146 "--------------------------------"
1147 "--------------------------------"
1148 "--------------------------------"
1149 "--------------------------------"
1150 "--------------------------------"
1151 "--------------------------------"
1152 "--------------------------------"
1153 "--------------------------------";
1154
1155 render_map_buf.read();
1156
1157 EXPECT_EQ(stringify_view(Span<uint>(&render_map_buf[SHADOW_TILEMAP_LOD0_LEN * 0],
1159 expected_view0);
1160 EXPECT_EQ(stringify_view(Span<uint>(&render_map_buf[SHADOW_TILEMAP_LOD0_LEN * 1],
1162 expected_view1);
1163 EXPECT_EQ(stringify_view(Span<uint>(&render_map_buf[SHADOW_TILEMAP_LOD0_LEN * 2],
1165 expected_view2);
1166 EXPECT_EQ(stringify_view(Span<uint>(&render_map_buf[SHADOW_TILEMAP_LOD0_LEN * 3],
1168 expected_view3);
1169 EXPECT_EQ(stringify_view(Span<uint>(&render_map_buf[SHADOW_TILEMAP_LOD0_LEN * 4],
1171 expected_view4);
1172 }
1173
1174 pages_infos_data.read();
1175 EXPECT_EQ(pages_infos_data.page_free_count, 0);
1176
1177 statistics_buf.read();
1178 EXPECT_EQ(statistics_buf.view_needed_count, 5);
1179
1181
1182 GPU_shader_free(sh);
1183 GPU_shader_free(sh2);
1186}
1187DRAW_TEST(eevee_shadow_finalize)
1188
1190{
1191 Vector<uint> test_values{0x00000000u, 0x00000001u, 0x0000000Fu, 0x000000FFu, 0xABCDEF01u,
1192 0xAAAAAAAAu, 0xBBBBBBBBu, 0xCCCCCCCCu, 0xDDDDDDDDu, 0xEEEEEEEEu,
1193 0xFFFFFFFFu, 0xDEADBEEFu, 0x8BADF00Du, 0xABADCAFEu, 0x0D15EA5Eu,
1194 0xFEE1DEADu, 0xDEADC0DEu, 0xC00010FFu, 0xBBADBEEFu, 0xBAAAAAADu};
1195
1196 for (auto value : test_values) {
1199
1202
1203 ShadowTileData expected_tile = shadow_tile_unpack(value);
1204 ShadowTileData result_tile = shadow_tile_unpack(shadow_tile_pack(expected_tile));
1205 EXPECT_EQ(expected_tile.page, result_tile.page);
1206 EXPECT_EQ(expected_tile.cache_index, result_tile.cache_index);
1207 EXPECT_EQ(expected_tile.is_used, result_tile.is_used);
1208 EXPECT_EQ(expected_tile.do_update, result_tile.do_update);
1209 EXPECT_EQ(expected_tile.is_allocated, result_tile.is_allocated);
1210 EXPECT_EQ(expected_tile.is_rendered, result_tile.is_rendered);
1211 EXPECT_EQ(expected_tile.is_cached, result_tile.is_cached);
1212
1213 ShadowSamplingTile expected_sampling_tile = shadow_sampling_tile_unpack(value);
1214 ShadowSamplingTile result_sampling_tile = shadow_sampling_tile_unpack(
1215 shadow_sampling_tile_pack(expected_sampling_tile));
1216 EXPECT_EQ(expected_sampling_tile.page, result_sampling_tile.page);
1217 EXPECT_EQ(expected_sampling_tile.lod, result_sampling_tile.lod);
1218 EXPECT_EQ(expected_sampling_tile.lod_offset, result_sampling_tile.lod_offset);
1219 EXPECT_EQ(expected_sampling_tile.is_valid, result_sampling_tile.is_valid);
1220 }
1221}
1222DRAW_TEST(eevee_shadow_tile_packing)
1223
1225{
1227
1230 tilemap_data.fill(0);
1231
1232 auto pixel_get = [&](int x, int y, int tilemap_index) -> uint32_t & {
1233 /* NOTE: assumes that tilemap_index is < SHADOW_TILEMAP_PER_ROW. */
1234 return tilemap_data[y * SHADOW_TILEMAP_RES * SHADOW_TILEMAP_PER_ROW + x +
1235 tilemap_index * SHADOW_TILEMAP_RES];
1236 };
1238 tile.lod = 0;
1239 tile.lod_offset = uint2(0);
1240 tile.is_valid = true;
1241 tile.page = uint3(1, 0, 0);
1242 pixel_get(16, 16, 2) = shadow_sampling_tile_pack(tile);
1243 tile.page = uint3(2, 0, 0);
1244 pixel_get(17, 16, 2) = shadow_sampling_tile_pack(tile);
1245 tile.page = uint3(3, 0, 0);
1246 pixel_get(20, 20, 1) = shadow_sampling_tile_pack(tile);
1247 tile.page = uint3(4, 0, 0);
1248 pixel_get(17, 16, 0) = shadow_sampling_tile_pack(tile);
1249
1250 Texture tilemap_tx = {"tilemap_tx"};
1254 tilemap_tx.ensure_2d(blender::gpu::TextureFormat::UINT_32, tilemap_res, usage);
1256 tilemap_tx, GPU_DATA_UINT, tilemap_data.data(), 0, 0, 0, tilemap_res.x, tilemap_res.y, 0);
1257
1258 /* Setup one directional light with 3 tilemaps. Fill only the needed data. */
1259 LightData light;
1260 light.type = LIGHT_SUN;
1261 light.sun.clipmap_lod_min = 0;
1262 light.sun.clipmap_lod_max = 2;
1263 /* Shift LOD0 by 1 tile towards bottom. */
1264 light.sun.clipmap_base_offset_neg = int2(0, 1 << 0);
1265 /* Shift LOD1 by 1 tile towards right. */
1266 light.sun.clipmap_base_offset_pos = int2(1 << 1, 0);
1267 light.tilemap_index = 0;
1268
1269 LightDataBuf culling_light_buf = {"Lights_culled"};
1270 culling_light_buf[0] = light;
1271 culling_light_buf.push_update();
1272
1273 LightCullingDataBuf culling_data_buf = {"LightCull_data"};
1274 culling_data_buf.local_lights_len = 0;
1275 culling_data_buf.sun_lights_len = 1;
1276 culling_data_buf.items_count = 1;
1277 culling_data_buf.push_update();
1278
1279 /* Needed for validation. But not used since we use directionals. */
1280 LightCullingZbinBuf culling_zbin_buf = {"LightCull_zbin"};
1281 LightCullingTileBuf culling_tile_buf = {"LightCull_tile"};
1282 ShadowTileMapDataBuf tilemaps_data = {"tilemaps_data"};
1283
1284 gpu::Shader *sh = GPU_shader_create_from_info_name("eevee_shadow_tilemap_amend");
1285
1286 PassSimple pass("Test");
1287 pass.shader_set(sh);
1288 pass.bind_image("tilemaps_img", tilemap_tx);
1289 pass.bind_ssbo("tilemaps_buf", tilemaps_data);
1290 pass.bind_ssbo(LIGHT_CULL_BUF_SLOT, culling_data_buf);
1291 pass.bind_ssbo(LIGHT_BUF_SLOT, culling_light_buf);
1292 pass.bind_ssbo(LIGHT_ZBIN_BUF_SLOT, culling_zbin_buf);
1293 pass.bind_ssbo(LIGHT_TILE_BUF_SLOT, culling_tile_buf);
1294 pass.dispatch(int3(1));
1296
1297 draw::View view("Test");
1298 view.sync(float4x4::identity(),
1299 math::projection::orthographic(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f));
1300
1301 Manager manager;
1302 manager.submit(pass, view);
1303
1304 {
1305 uint *pixels = tilemap_tx.read<uint32_t>(GPU_DATA_UINT);
1306
1307 auto stringify_tilemap = [&](int tilemap_index) -> std::string {
1308 std::string result;
1309 for (auto y : IndexRange(SHADOW_TILEMAP_RES)) {
1310 for (auto x : IndexRange(SHADOW_TILEMAP_RES)) {
1311 /* NOTE: assumes that tilemap_index is < SHADOW_TILEMAP_PER_ROW. */
1312 int tile_ofs = y * SHADOW_TILEMAP_RES * SHADOW_TILEMAP_PER_ROW + x +
1313 tilemap_index * SHADOW_TILEMAP_RES;
1315 result += std::to_string(tile.page.x + tile.page.y * SHADOW_PAGE_PER_ROW);
1316 if (x + 1 == SHADOW_TILEMAP_RES / 2) {
1317 result += " ";
1318 }
1319 }
1320 result += "\n";
1321 if (y + 1 == SHADOW_TILEMAP_RES / 2) {
1322 result += "\n";
1323 }
1324 }
1325 return result;
1326 };
1327
1328 auto stringify_lod = [&](int tilemap_index) -> std::string {
1329 std::string result;
1330 for (auto y : IndexRange(SHADOW_TILEMAP_RES)) {
1331 for (auto x : IndexRange(SHADOW_TILEMAP_RES)) {
1332 /* NOTE: assumes that tilemap_index is < SHADOW_TILEMAP_PER_ROW. */
1333 int tile_ofs = y * SHADOW_TILEMAP_RES * SHADOW_TILEMAP_PER_ROW + x +
1334 tilemap_index * SHADOW_TILEMAP_RES;
1336 result += std::to_string(tile.lod);
1337 if (x + 1 == SHADOW_TILEMAP_RES / 2) {
1338 result += " ";
1339 }
1340 }
1341 result += "\n";
1342 if (y + 1 == SHADOW_TILEMAP_RES / 2) {
1343 result += "\n";
1344 }
1345 }
1346 return result;
1347 };
1348
1349 auto stringify_offset = [&](int tilemap_index) -> std::string {
1350 std::string result;
1351 for (auto y : IndexRange(SHADOW_TILEMAP_RES)) {
1352 for (auto x : IndexRange(SHADOW_TILEMAP_RES)) {
1353 /* NOTE: assumes that tilemap_index is < SHADOW_TILEMAP_PER_ROW. */
1354 int tile_ofs = y * SHADOW_TILEMAP_RES * SHADOW_TILEMAP_PER_ROW + x +
1355 tilemap_index * SHADOW_TILEMAP_RES;
1357 result += std::to_string(tile.lod_offset.x + tile.lod_offset.y);
1358 if (x + 1 == SHADOW_TILEMAP_RES / 2) {
1359 result += " ";
1360 }
1361 }
1362 result += "\n";
1363 if (y + 1 == SHADOW_TILEMAP_RES / 2) {
1364 result += "\n";
1365 }
1366 }
1367 return result;
1368 };
1369
1371
1372 StringRefNull expected_pages_lod2 =
1373 "0000000000000000 0000000000000000\n"
1374 "0000000000000000 0000000000000000\n"
1375 "0000000000000000 0000000000000000\n"
1376 "0000000000000000 0000000000000000\n"
1377 "0000000000000000 0000000000000000\n"
1378 "0000000000000000 0000000000000000\n"
1379 "0000000000000000 0000000000000000\n"
1380 "0000000000000000 0000000000000000\n"
1381 "0000000000000000 0000000000000000\n"
1382 "0000000000000000 0000000000000000\n"
1383 "0000000000000000 0000000000000000\n"
1384 "0000000000000000 0000000000000000\n"
1385 "0000000000000000 0000000000000000\n"
1386 "0000000000000000 0000000000000000\n"
1387 "0000000000000000 0000000000000000\n"
1388 "0000000000000000 0000000000000000\n"
1389 "\n"
1390 "0000000000000000 1200000000000000\n"
1391 "0000000000000000 0000000000000000\n"
1392 "0000000000000000 0000000000000000\n"
1393 "0000000000000000 0000000000000000\n"
1394 "0000000000000000 0000000000000000\n"
1395 "0000000000000000 0000000000000000\n"
1396 "0000000000000000 0000000000000000\n"
1397 "0000000000000000 0000000000000000\n"
1398 "0000000000000000 0000000000000000\n"
1399 "0000000000000000 0000000000000000\n"
1400 "0000000000000000 0000000000000000\n"
1401 "0000000000000000 0000000000000000\n"
1402 "0000000000000000 0000000000000000\n"
1403 "0000000000000000 0000000000000000\n"
1404 "0000000000000000 0000000000000000\n"
1405 "0000000000000000 0000000000000000\n";
1406
1407 StringRefNull expected_pages_lod1 =
1408 "0000000000000000 0000000000000000\n"
1409 "0000000000000000 0000000000000000\n"
1410 "0000000000000000 0000000000000000\n"
1411 "0000000000000000 0000000000000000\n"
1412 "0000000000000000 0000000000000000\n"
1413 "0000000000000000 0000000000000000\n"
1414 "0000000000000000 0000000000000000\n"
1415 "0000000000000000 0000000000000000\n"
1416 "0000000000000000 0000000000000000\n"
1417 "0000000000000000 0000000000000000\n"
1418 "0000000000000000 0000000000000000\n"
1419 "0000000000000000 0000000000000000\n"
1420 "0000000000000000 0000000000000000\n"
1421 "0000000000000000 0000000000000000\n"
1422 "0000000000000000 0000000000000000\n"
1423 "0000000000000000 0000000000000000\n"
1424 "\n"
1425 "0000000000000001 1220000000000000\n"
1426 "0000000000000001 1220000000000000\n"
1427 "0000000000000000 0000000000000000\n"
1428 "0000000000000000 0000000000000000\n"
1429 "0000000000000000 0000300000000000\n"
1430 "0000000000000000 0000000000000000\n"
1431 "0000000000000000 0000000000000000\n"
1432 "0000000000000000 0000000000000000\n"
1433 "0000000000000000 0000000000000000\n"
1434 "0000000000000000 0000000000000000\n"
1435 "0000000000000000 0000000000000000\n"
1436 "0000000000000000 0000000000000000\n"
1437 "0000000000000000 0000000000000000\n"
1438 "0000000000000000 0000000000000000\n"
1439 "0000000000000000 0000000000000000\n"
1440 "0000000000000000 0000000000000000\n";
1441
1442 StringRefNull expected_pages_lod0 =
1443 "0000000000000000 0000000000000000\n"
1444 "0000000000000000 0000000000000000\n"
1445 "0000000000000000 0000000000000000\n"
1446 "0000000000000000 0000000000000000\n"
1447 "0000000000000000 0000000000000000\n"
1448 "0000000000000000 0000000000000000\n"
1449 "0000000000000000 0000000000000000\n"
1450 "0000000000000000 0000000000000000\n"
1451 "0000000000000000 0000000000000000\n"
1452 "0000000000000000 0000000000000000\n"
1453 "0000000000000000 0000000000000000\n"
1454 "0000000000000000 0000000000000000\n"
1455 "0000000000000000 0000000000000000\n"
1456 "0000000000000000 0000000000000000\n"
1457 "0000000000000000 0000000000000000\n"
1458 "0000000000000000 0000000000000000\n"
1459 "\n"
1460 "0000000000000000 0400000000000000\n"
1461 "0000000000000011 1122220000000000\n"
1462 "0000000000000011 1122220000000000\n"
1463 "0000000000000011 1122220000000000\n"
1464 "0000000000000011 1122220000000000\n"
1465 "0000000000000000 0000000000000000\n"
1466 "0000000000000000 0000000000000000\n"
1467 "0000000000000000 0000000000000000\n"
1468 "0000000000000000 0000000000000000\n"
1469 "0000000000000000 0000000033000000\n"
1470 "0000000000000000 0000000033000000\n"
1471 "0000000000000000 0000000000000000\n"
1472 "0000000000000000 0000000000000000\n"
1473 "0000000000000000 0000000000000000\n"
1474 "0000000000000000 0000000000000000\n"
1475 "0000000000000000 0000000000000000\n";
1476
1477 EXPECT_EQ(expected_pages_lod2, stringify_tilemap(2));
1478 EXPECT_EQ(expected_pages_lod1, stringify_tilemap(1));
1479 EXPECT_EQ(expected_pages_lod0, stringify_tilemap(0));
1480
1481 StringRefNull expected_lod_lod0 =
1482 "0000000000000000 0000000000000000\n"
1483 "0000000000000000 0000000000000000\n"
1484 "0000000000000000 0000000000000000\n"
1485 "0000000000000000 0000000000000000\n"
1486 "0000000000000000 0000000000000000\n"
1487 "0000000000000000 0000000000000000\n"
1488 "0000000000000000 0000000000000000\n"
1489 "0000000000000000 0000000000000000\n"
1490 "0000000000000000 0000000000000000\n"
1491 "0000000000000000 0000000000000000\n"
1492 "0000000000000000 0000000000000000\n"
1493 "0000000000000000 0000000000000000\n"
1494 "0000000000000000 0000000000000000\n"
1495 "0000000000000000 0000000000000000\n"
1496 "0000000000000000 0000000000000000\n"
1497 "0000000000000000 0000000000000000\n"
1498 "\n"
1499 "0000000000000000 0000000000000000\n"
1500 "0000000000000022 2222220000000000\n"
1501 "0000000000000022 2222220000000000\n"
1502 "0000000000000022 2222220000000000\n"
1503 "0000000000000022 2222220000000000\n"
1504 "0000000000000000 0000000000000000\n"
1505 "0000000000000000 0000000000000000\n"
1506 "0000000000000000 0000000000000000\n"
1507 "0000000000000000 0000000000000000\n"
1508 "0000000000000000 0000000011000000\n"
1509 "0000000000000000 0000000011000000\n"
1510 "0000000000000000 0000000000000000\n"
1511 "0000000000000000 0000000000000000\n"
1512 "0000000000000000 0000000000000000\n"
1513 "0000000000000000 0000000000000000\n"
1514 "0000000000000000 0000000000000000\n";
1515
1516 EXPECT_EQ(expected_lod_lod0, stringify_lod(0));
1517
1518 /* Offset for each axis are added together in this test. */
1519 StringRefNull expected_offset_lod0 =
1520 "0000000000000000 0000000000000000\n"
1521 "0000000000000000 0000000000000000\n"
1522 "0000000000000000 0000000000000000\n"
1523 "0000000000000000 0000000000000000\n"
1524 "0000000000000000 0000000000000000\n"
1525 "0000000000000000 0000000000000000\n"
1526 "0000000000000000 0000000000000000\n"
1527 "0000000000000000 0000000000000000\n"
1528 "0000000000000000 0000000000000000\n"
1529 "0000000000000000 0000000000000000\n"
1530 "0000000000000000 0000000000000000\n"
1531 "0000000000000000 0000000000000000\n"
1532 "0000000000000000 0000000000000000\n"
1533 "0000000000000000 0000000000000000\n"
1534 "0000000000000000 0000000000000000\n"
1535 "0000000000000000 0000000000000000\n"
1536 "\n"
1537 "0000000000000000 0000000000000000\n"
1538 "0000000000000055 5555550000000000\n"
1539 "0000000000000055 5555550000000000\n"
1540 "0000000000000055 5555550000000000\n"
1541 "0000000000000055 5555550000000000\n"
1542 "0000000000000000 0000000000000000\n"
1543 "0000000000000000 0000000000000000\n"
1544 "0000000000000000 0000000000000000\n"
1545 "0000000000000000 0000000000000000\n"
1546 "0000000000000000 0000000011000000\n"
1547 "0000000000000000 0000000011000000\n"
1548 "0000000000000000 0000000000000000\n"
1549 "0000000000000000 0000000000000000\n"
1550 "0000000000000000 0000000000000000\n"
1551 "0000000000000000 0000000000000000\n"
1552 "0000000000000000 0000000000000000\n";
1553
1554 EXPECT_EQ(expected_offset_lod0, stringify_offset(0));
1555 MEM_SAFE_FREE(pixels);
1556 }
1557
1559
1560 GPU_shader_free(sh);
1563}
1564DRAW_TEST(eevee_shadow_tilemap_amend)
1565
1566static void test_eevee_shadow_page_mask_ex(int max_view_per_tilemap)
1567{
1569 ShadowTileMapDataBuf tilemaps_data = {"tilemaps_data"};
1570 ShadowTileDataBuf tiles_data = {"tiles_data"};
1571
1572 {
1573 ShadowTileMap tilemap(0);
1574 tilemap.sync_cubeface(LIGHT_OMNI_SPHERE, float4x4::identity(), 0.01f, 1.0f, Z_NEG);
1575 tilemaps_data.append(tilemap);
1576 }
1577
1578 const uint lod0_len = SHADOW_TILEMAP_LOD0_LEN;
1579 const uint lod1_len = SHADOW_TILEMAP_LOD1_LEN;
1580 const uint lod2_len = SHADOW_TILEMAP_LOD2_LEN;
1581 const uint lod3_len = SHADOW_TILEMAP_LOD3_LEN;
1582 const uint lod4_len = SHADOW_TILEMAP_LOD4_LEN;
1583 const uint lod5_len = SHADOW_TILEMAP_LOD5_LEN;
1584
1585 const uint lod0_ofs = 0;
1586 const uint lod1_ofs = lod0_ofs + lod0_len;
1587 const uint lod2_ofs = lod1_ofs + lod1_len;
1588 const uint lod3_ofs = lod2_ofs + lod2_len;
1589 const uint lod4_ofs = lod3_ofs + lod3_len;
1590 const uint lod5_ofs = lod4_ofs + lod4_len;
1591
1592 {
1593 ShadowTileData tile = {};
1594 /* Init all LOD to true. */
1596 tile.is_used = true;
1597 tile.do_update = true;
1598 tiles_data[i] = shadow_tile_pack(tile);
1599 }
1600
1601 /* Init all of LOD0 to false. */
1602 for (auto i : IndexRange(square_i(SHADOW_TILEMAP_RES))) {
1603 tile.is_used = false;
1604 tile.do_update = false;
1605 tiles_data[i] = shadow_tile_pack(tile);
1606 }
1607
1608 /* Bottom Left of the LOD0 to true. */
1609 for (auto y : IndexRange((SHADOW_TILEMAP_RES / 2))) {
1610 for (auto x : IndexRange((SHADOW_TILEMAP_RES / 2) + 1)) {
1611 tile.is_used = true;
1612 tile.do_update = true;
1613 tiles_data[x + y * SHADOW_TILEMAP_RES] = shadow_tile_pack(tile);
1614 }
1615 }
1616
1617 /* All Bottom of the LOD0 to true. */
1618 for (auto x : IndexRange(SHADOW_TILEMAP_RES)) {
1619 tile.is_used = true;
1620 tile.do_update = true;
1621 tiles_data[x] = shadow_tile_pack(tile);
1622 }
1623
1624 /* Bottom Left of the LOD1 to false. */
1625 /* Should still cover bottom LODs since it is itself fully masked */
1626 for (auto y : IndexRange((SHADOW_TILEMAP_RES / 8))) {
1627 for (auto x : IndexRange((SHADOW_TILEMAP_RES / 8))) {
1628 tile.is_used = false;
1629 tile.do_update = false;
1630 tiles_data[x + y * (SHADOW_TILEMAP_RES / 2) + lod0_len] = shadow_tile_pack(tile);
1631 }
1632 }
1633
1634 /* Top right Center of the LOD1 to false. */
1635 /* Should un-cover 1 LOD2 tile. */
1636 {
1637 int x = SHADOW_TILEMAP_RES / 4;
1638 int y = SHADOW_TILEMAP_RES / 4;
1639 tile.is_used = false;
1640 tile.do_update = false;
1641 tiles_data[x + y * (SHADOW_TILEMAP_RES / 2) + lod0_len] = shadow_tile_pack(tile);
1642 }
1643
1644 tiles_data.push_update();
1645 }
1646
1647 tilemaps_data.push_update();
1648
1649 gpu::Shader *sh = GPU_shader_create_from_info_name("eevee_shadow_page_mask");
1650
1651 PassSimple pass("Test");
1652 pass.shader_set(sh);
1653 pass.push_constant("max_view_per_tilemap", max_view_per_tilemap);
1654 pass.bind_ssbo("tilemaps_buf", tilemaps_data);
1655 pass.bind_ssbo("tiles_buf", tiles_data);
1656 pass.dispatch(int3(1, 1, tilemaps_data.size()));
1657
1658 Manager manager;
1659 manager.submit(pass);
1661
1662 tiles_data.read();
1663
1665 StringRefNull expected_lod0 =
1666 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
1667 "xxxxxxxxxxxxxxxxx---------------"
1668 "xxxxxxxxxxxxxxxxx---------------"
1669 "xxxxxxxxxxxxxxxxx---------------"
1670 "xxxxxxxxxxxxxxxxx---------------"
1671 "xxxxxxxxxxxxxxxxx---------------"
1672 "xxxxxxxxxxxxxxxxx---------------"
1673 "xxxxxxxxxxxxxxxxx---------------"
1674 "xxxxxxxxxxxxxxxxx---------------"
1675 "xxxxxxxxxxxxxxxxx---------------"
1676 "xxxxxxxxxxxxxxxxx---------------"
1677 "xxxxxxxxxxxxxxxxx---------------"
1678 "xxxxxxxxxxxxxxxxx---------------"
1679 "xxxxxxxxxxxxxxxxx---------------"
1680 "xxxxxxxxxxxxxxxxx---------------"
1681 "xxxxxxxxxxxxxxxxx---------------"
1682 "--------------------------------"
1683 "--------------------------------"
1684 "--------------------------------"
1685 "--------------------------------"
1686 "--------------------------------"
1687 "--------------------------------"
1688 "--------------------------------"
1689 "--------------------------------"
1690 "--------------------------------"
1691 "--------------------------------"
1692 "--------------------------------"
1693 "--------------------------------"
1694 "--------------------------------"
1695 "--------------------------------"
1696 "--------------------------------"
1697 "--------------------------------";
1698 StringRefNull expected_lod1 =
1699 "--------xxxxxxxx"
1700 "--------xxxxxxxx"
1701 "--------xxxxxxxx"
1702 "--------xxxxxxxx"
1703 "--------xxxxxxxx"
1704 "--------xxxxxxxx"
1705 "--------xxxxxxxx"
1706 "--------xxxxxxxx"
1707 "xxxxxxxx-xxxxxxx"
1708 "xxxxxxxxxxxxxxxx"
1709 "xxxxxxxxxxxxxxxx"
1710 "xxxxxxxxxxxxxxxx"
1711 "xxxxxxxxxxxxxxxx"
1712 "xxxxxxxxxxxxxxxx"
1713 "xxxxxxxxxxxxxxxx"
1714 "xxxxxxxxxxxxxxxx";
1715 StringRefNull expected_lod1_collapsed =
1716 "xxxxxxxxxxxxxxxx"
1717 "xxxxxxxxxxxxxxxx"
1718 "xxxxxxxxxxxxxxxx"
1719 "xxxxxxxxxxxxxxxx"
1720 "xxxxxxxxxxxxxxxx"
1721 "xxxxxxxxxxxxxxxx"
1722 "xxxxxxxxxxxxxxxx"
1723 "xxxxxxxxxxxxxxxx"
1724 "xxxxxxxx-xxxxxxx"
1725 "xxxxxxxxxxxxxxxx"
1726 "xxxxxxxxxxxxxxxx"
1727 "xxxxxxxxxxxxxxxx"
1728 "xxxxxxxxxxxxxxxx"
1729 "xxxxxxxxxxxxxxxx"
1730 "xxxxxxxxxxxxxxxx"
1731 "xxxxxxxxxxxxxxxx";
1732 StringRefNull expected_lod2 =
1733 "--------"
1734 "--------"
1735 "--------"
1736 "--------"
1737 "----x---"
1738 "--------"
1739 "--------"
1740 "--------";
1741 StringRefNull expected_lod2_collapsed =
1742 "xxxxxxxx"
1743 "xxxxxxxx"
1744 "xxxxxxxx"
1745 "xxxxxxxx"
1746 "xxxxxxxx"
1747 "xxxxxxxx"
1748 "xxxxxxxx"
1749 "xxxxxxxx";
1750 StringRefNull expected_lod3 =
1751 "----"
1752 "----"
1753 "----"
1754 "----";
1755 StringRefNull expected_lod4 =
1756 "--"
1757 "--";
1758 StringRefNull expected_lod5 = "-";
1759
1760 auto stringify_result = [&](uint start, uint len) -> std::string {
1761 std::string result;
1762 for (auto i : IndexRange(start, len)) {
1763 result += (shadow_tile_unpack(tiles_data[i]).is_used) ? "x" : "-";
1764 }
1765 return result;
1766 };
1767
1768 auto empty_result = [&](uint len) -> std::string {
1769 std::string result;
1770 for ([[maybe_unused]] const int i : IndexRange(len)) {
1771 result += "-";
1772 }
1773 return result;
1774 };
1775
1776 if (max_view_per_tilemap >= 3) {
1777 EXPECT_EQ(stringify_result(lod0_ofs, lod0_len), expected_lod0);
1778 }
1779 else {
1780 EXPECT_EQ(stringify_result(lod0_ofs, lod0_len), empty_result(lod0_len));
1781 }
1782
1783 if (max_view_per_tilemap > 2) {
1784 EXPECT_EQ(stringify_result(lod1_ofs, lod1_len), expected_lod1);
1785 }
1786 else if (max_view_per_tilemap == 2) {
1787 EXPECT_EQ(stringify_result(lod1_ofs, lod1_len), expected_lod1_collapsed);
1788 }
1789 else {
1790 EXPECT_EQ(stringify_result(lod1_ofs, lod1_len), empty_result(lod1_len));
1791 }
1792
1793 if (max_view_per_tilemap > 1) {
1794 EXPECT_EQ(stringify_result(lod2_ofs, lod2_len), expected_lod2);
1795 }
1796 else if (max_view_per_tilemap == 1) {
1797 EXPECT_EQ(stringify_result(lod2_ofs, lod2_len), expected_lod2_collapsed);
1798 }
1799 else {
1800 EXPECT_EQ(stringify_result(lod2_ofs, lod2_len), empty_result(lod2_len));
1801 }
1802 EXPECT_EQ(stringify_result(lod3_ofs, lod3_len), expected_lod3);
1803 EXPECT_EQ(stringify_result(lod4_ofs, lod4_len), expected_lod4);
1804 EXPECT_EQ(stringify_result(lod5_ofs, lod5_len), expected_lod5);
1805
1807
1808 GPU_shader_free(sh);
1811}
1812
1814{
1815 /* Expect default behavior. */
1817 /* Expect default behavior. */
1819 /* Expect LOD0 merged into LOD1. */
1821 /* Expect LOD0 and LOD1 merged into LOD2. */
1823}
1824DRAW_TEST(eevee_shadow_page_mask)
1825
1827{
1829 StorageArrayBuffer<int> list_start_buf = {"list_start_buf"};
1830 StorageVectorBuffer<Surfel> surfel_buf = {"surfel_buf"};
1831 CaptureInfoBuf capture_info_buf = {"capture_info_buf"};
1832 SurfelListInfoBuf list_info_buf = {"list_info_buf"};
1833 StorageArrayBuffer<int> list_counter_buf = {"list_counter_buf"};
1834 StorageArrayBuffer<int> list_range_buf = {"list_range_buf"};
1835 StorageArrayBuffer<float> list_item_distance_buf = {"list_item_distance_buf"};
1836 StorageArrayBuffer<int> list_item_surfel_id_buf = {"list_item_surfel_id_buf"};
1837 StorageArrayBuffer<int> sorted_surfel_id_buf = {"sorted_surfel_id_buf"};
1838
1842 {
1843 Surfel surfel;
1844 surfel.normal = {0.0f, 0.0f, 1.0f};
1845 /* NOTE: Expected link assumes linear increasing processing order [0->5]. But this is
1846 * multithreaded and we can't know the execution order in advance. */
1847 /* 0: Project to (1, 0) = list 1. Next = -1; Previous = 3. */
1848 surfel.position = {1.1f, 0.1f, 0.1f};
1849 surfel_buf.append(surfel);
1850 /* 1: Project to (1, 0) = list 1. Next = 2; Previous = -1. */
1851 surfel.position = {1.1f, 0.2f, 0.5f};
1852 surfel_buf.append(surfel);
1853 /* 2: Project to (1, 0) = list 1. Next = 3; Previous = 1. */
1854 surfel.position = {1.1f, 0.3f, 0.3f};
1855 surfel_buf.append(surfel);
1856 /* 3: Project to (1, 0) = list 1. Next = 0; Previous = 2. */
1857 surfel.position = {1.2f, 0.4f, 0.2f};
1858 surfel_buf.append(surfel);
1859 /* 4: Project to (1, 1) = list 3. Next = -1; Previous = -1. */
1860 surfel.position = {1.0f, 1.0f, 0.5f};
1861 surfel_buf.append(surfel);
1862 /* 5: Project to (0, 1) = list 2. Next = -1; Previous = -1. */
1863 surfel.position = {0.1f, 1.1f, 0.5f};
1864 surfel_buf.append(surfel);
1865 /* 6: Project to (0, 1) = list 2. Next = -1; Previous = -1. Disconnected because coplanar */
1866 surfel.position = {0.2f, 1.1f, 0.5f};
1867 surfel_buf.append(surfel);
1868
1869 surfel_buf.push_update();
1870 }
1871 {
1872 capture_info_buf.surfel_len = surfel_buf.size();
1873 capture_info_buf.push_update();
1874 }
1875 {
1876 list_info_buf.ray_grid_size = int2(2);
1877 list_info_buf.list_max = list_info_buf.ray_grid_size.x * list_info_buf.ray_grid_size.y;
1878 list_info_buf.push_update();
1879 }
1880 {
1881 list_start_buf.resize(ceil_to_multiple_u(list_info_buf.list_max, 4u));
1882 list_start_buf.push_update();
1883 GPU_storagebuf_clear(list_start_buf, -1);
1884 }
1885 {
1886 list_counter_buf.resize(ceil_to_multiple_u(list_info_buf.list_max, 4u));
1887 list_counter_buf.push_update();
1888 GPU_storagebuf_clear(list_counter_buf, 0);
1889 }
1890 {
1891 list_range_buf.resize(ceil_to_multiple_u(list_info_buf.list_max * 2, 4u));
1892 list_range_buf.push_update();
1893 GPU_storagebuf_clear(list_range_buf, -1);
1894 }
1895 {
1896 list_item_distance_buf.resize(ceil_to_multiple_u(capture_info_buf.surfel_len, 4u));
1897 list_item_surfel_id_buf.resize(ceil_to_multiple_u(capture_info_buf.surfel_len, 4u));
1898 sorted_surfel_id_buf.resize(ceil_to_multiple_u(capture_info_buf.surfel_len, 4u));
1899 GPU_storagebuf_clear(list_item_distance_buf, -1);
1900 GPU_storagebuf_clear(list_item_surfel_id_buf, -1);
1901 GPU_storagebuf_clear(sorted_surfel_id_buf, -1);
1902 }
1903
1904 /* Top-down view. */
1905 View view = {"RayProjectionView"};
1907
1908 gpu::Shader *sh_build = GPU_shader_create_from_info_name("eevee_surfel_list_build");
1909 gpu::Shader *sh_flatten = GPU_shader_create_from_info_name("eevee_surfel_list_flatten");
1910 gpu::Shader *sh_prefix = GPU_shader_create_from_info_name("eevee_surfel_list_prefix");
1911 gpu::Shader *sh_prepare = GPU_shader_create_from_info_name("eevee_surfel_list_prepare");
1912 gpu::Shader *sh_sort = GPU_shader_create_from_info_name("eevee_surfel_list_sort");
1913
1914 PassSimple pass("Build_and_Sort");
1915 pass.shader_set(sh_prepare);
1916 pass.bind_ssbo("list_counter_buf", list_counter_buf);
1917 pass.bind_ssbo("list_info_buf", list_info_buf);
1918 pass.bind_ssbo("surfel_buf", surfel_buf);
1919 pass.bind_ssbo("capture_info_buf", capture_info_buf);
1920 pass.dispatch(int3(1, 1, 1));
1922
1923 pass.shader_set(sh_prefix);
1924 pass.bind_ssbo("list_counter_buf", list_counter_buf);
1925 pass.bind_ssbo("list_range_buf", list_range_buf);
1926 pass.bind_ssbo("list_info_buf", list_info_buf);
1927 pass.bind_ssbo("surfel_buf", surfel_buf);
1928 pass.bind_ssbo("capture_info_buf", capture_info_buf);
1929 pass.dispatch(int3(1, 1, 1));
1931
1932 pass.shader_set(sh_flatten);
1933 pass.bind_ssbo("list_counter_buf", list_counter_buf);
1934 pass.bind_ssbo("list_range_buf", list_range_buf);
1935 pass.bind_ssbo("list_item_distance_buf", list_item_distance_buf);
1936 pass.bind_ssbo("list_item_surfel_id_buf", list_item_surfel_id_buf);
1937 pass.bind_ssbo("list_info_buf", list_info_buf);
1938 pass.bind_ssbo("surfel_buf", surfel_buf);
1939 pass.bind_ssbo("capture_info_buf", capture_info_buf);
1940 pass.dispatch(int3(1, 1, 1));
1942
1943 pass.shader_set(sh_sort);
1944 pass.bind_ssbo("list_range_buf", list_range_buf);
1945 pass.bind_ssbo("list_item_surfel_id_buf", list_item_surfel_id_buf);
1946 pass.bind_ssbo("list_item_distance_buf", list_item_distance_buf);
1947 pass.bind_ssbo("sorted_surfel_id_buf", sorted_surfel_id_buf);
1948 pass.bind_ssbo("list_info_buf", list_info_buf);
1949 pass.bind_ssbo("surfel_buf", surfel_buf);
1950 pass.bind_ssbo("capture_info_buf", capture_info_buf);
1951 pass.dispatch(int3(1, 1, 1));
1953
1954 pass.shader_set(sh_build);
1955 pass.bind_ssbo("list_start_buf", list_start_buf);
1956 pass.bind_ssbo("list_range_buf", list_range_buf);
1957 pass.bind_ssbo("sorted_surfel_id_buf", sorted_surfel_id_buf);
1958 pass.bind_ssbo("list_info_buf", list_info_buf);
1959 pass.bind_ssbo("surfel_buf", surfel_buf);
1960 pass.bind_ssbo("capture_info_buf", capture_info_buf);
1961 pass.dispatch(int3(1, 1, 1));
1963
1964 Manager manager;
1965 manager.submit(pass, view);
1966
1967 list_start_buf.read();
1968 surfel_buf.read();
1969
1970 /* Expect surfel list. */
1971 Vector<int> expect_link_next = {-1, +2, +3, +0, -1, -1, -1};
1972 Vector<int> expect_link_prev = {+3, -1, +1, +2, -1, -1, -1};
1973
1974 Vector<int> link_next, link_prev;
1975 for (const auto &surfel : Span<Surfel>(surfel_buf.data(), surfel_buf.size())) {
1976 link_next.append(surfel.next);
1977 link_prev.append(surfel.prev);
1978 }
1979
1980 Vector<int> expect_list_start = {-1, 1, 5, 4};
1981 EXPECT_EQ_SPAN<int>(expect_list_start, list_start_buf);
1982 EXPECT_EQ_SPAN<int>(expect_link_next, link_next);
1983 EXPECT_EQ_SPAN<int>(expect_link_prev, link_prev);
1984
1986
1987 GPU_shader_free(sh_build);
1988 GPU_shader_free(sh_flatten);
1989 GPU_shader_free(sh_prefix);
1990 GPU_shader_free(sh_prepare);
1991 GPU_shader_free(sh_sort);
1994}
1995DRAW_TEST(eevee_surfel_list)
1996
1998{
2000
2001 Manager manager;
2002
2003 /* Check if LUT generation matches the header version. */
2004 auto brdf_ggx_gen = Precompute(manager, LUT_GGX_BRDF_SPLIT_SUM, {64, 64, 1}).data<float3>();
2005 auto btdf_ggx_gen = Precompute(manager, LUT_GGX_BTDF_IOR_GT_ONE, {64, 64, 16}).data<float1>();
2006 auto bsdf_ggx_gen = Precompute(manager, LUT_GGX_BSDF_SPLIT_SUM, {64, 64, 16}).data<float3>();
2007 auto burley_gen = Precompute(manager, LUT_BURLEY_SSS_PROFILE, {64, 1, 1}).data<float1>();
2008 auto rand_walk_gen = Precompute(manager, LUT_RANDOM_WALK_SSS_PROFILE, {64, 1, 1}).data<float1>();
2009
2010 Span<float3> brdf_ggx_lut((const float3 *)&eevee::lut::brdf_ggx, 64 * 64);
2011 Span<float1> btdf_ggx_lut((const float1 *)&eevee::lut::btdf_ggx, 64 * 64 * 16);
2012 Span<float3> bsdf_ggx_lut((const float3 *)&eevee::lut::bsdf_ggx, 64 * 64 * 16);
2013 Span<float1> burley_sss_lut((const float1 *)&eevee::lut::burley_sss_profile, 64);
2014 Span<float1> rand_walk_lut((const float1 *)&eevee::lut::random_walk_sss_profile, 64);
2015
2016 const float eps = 3e-3f;
2017 EXPECT_NEAR_ARRAY_ND(brdf_ggx_lut.data(), brdf_ggx_gen.data(), brdf_ggx_gen.size(), 3, eps);
2018 EXPECT_NEAR_ARRAY_ND(btdf_ggx_lut.data(), btdf_ggx_gen.data(), btdf_ggx_gen.size(), 1, eps);
2019 EXPECT_NEAR_ARRAY_ND(bsdf_ggx_lut.data(), bsdf_ggx_gen.data(), bsdf_ggx_gen.size(), 3, eps);
2020 EXPECT_NEAR_ARRAY_ND(burley_gen.data(), burley_sss_lut.data(), burley_sss_lut.size(), 1, eps);
2021 EXPECT_NEAR_ARRAY_ND(rand_walk_gen.data(), rand_walk_lut.data(), rand_walk_lut.size(), 1, eps);
2022
2024}
2025DRAW_TEST(eevee_lut_gen)
2026
2027} // namespace blender::draw
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
MINLINE uint ceil_to_multiple_u(uint a, uint b)
MINLINE int min_ii(int a, int b)
MINLINE int square_i(int a)
MINLINE int max_ii(int a, int b)
unsigned int uint
static AppView * view
void GPU_render_end()
void GPU_render_begin()
void GPU_shader_free(blender::gpu::Shader *shader)
blender::gpu::Shader * GPU_shader_create_from_info_name(const char *info_name)
void GPU_shader_unbind()
@ GPU_BARRIER_SHADER_STORAGE
Definition GPU_state.hh:48
@ GPU_BARRIER_BUFFER_UPDATE
Definition GPU_state.hh:56
@ GPU_BARRIER_TEXTURE_UPDATE
Definition GPU_state.hh:39
void GPU_memory_barrier(GPUBarrier barrier)
Definition gpu_state.cc:326
void GPU_storagebuf_clear(blender::gpu::StorageBuf *ssbo, uint32_t clear_value)
void GPU_texture_update_sub(blender::gpu::Texture *texture, eGPUDataFormat data_format, const void *pixels, int offset_x, int offset_y, int offset_z, int width, int height, int depth)
@ GPU_DATA_UINT
eGPUTextureUsage
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_SHADER_WRITE
@ GPU_TEXTURE_USAGE_HOST_READ
#define MEM_SAFE_FREE(v)
BMesh const char void * data
constexpr const T * data() const
Definition BLI_span.hh:215
constexpr int64_t size() const
Definition BLI_span.hh:252
void append(const T &value)
void fill(const T &value) const
void begin_sync(Object *object_active=nullptr)
SwapChain< ObjectBoundsBuf, 2 > bounds_buf
void submit(PassSimple &pass, View &view)
ResourceHandleRange resource_handle(const ObjectRef &ref, float inflate_bounds=0.0f)
TestAlloc(int page_free_count)
TestDefrag(int allocation_count, int descriptor_offset, StringRefNull descriptor, StringRefNull expect)
void clear(float4 values)
T * read(eGPUDataFormat format, int miplvl=0)
bool ensure_2d(blender::gpu::TextureFormat format, int2 extent, eGPUTextureUsage usage=GPU_TEXTURE_USAGE_GENERAL, const float *data=nullptr, int mip_len=1)
void shader_set(gpu::Shader *shader)
void bind_image(const char *name, gpu::Texture *image)
void dispatch(int group_len)
void barrier(GPUBarrier type)
void push_constant(const char *name, const float &data)
void bind_ssbo(const char *name, gpu::StorageBuf *buffer)
void DRW_shaders_free()
#define DRAW_TEST(test_name)
#define SHADOW_TILEMAP_LOD2_LEN
#define SHADOW_TILEMAP_RES
#define SHADOW_TILEMAP_LOD4_LEN
#define LIGHT_BUF_SLOT
#define SHADOW_TILEMAP_PER_ROW
#define SHADOW_TILEMAP_LOD1_LEN
#define SHADOW_PAGE_PER_ROW
#define SHADOW_TILEMAP_LOD0_LEN
#define SHADOW_VIEW_MAX
#define LIGHT_ZBIN_BUF_SLOT
#define SHADOW_MAX_TILE
#define SHADOW_TILEDATA_PER_TILEMAP
#define SHADOW_PAGE_PER_COL
#define SHADOW_PAGE_PER_LAYER
#define SHADOW_MAX_PAGE
#define LIGHT_TILE_BUF_SLOT
#define SHADOW_TILEMAP_LOD5_LEN
#define LIGHT_CULL_BUF_SLOT
#define SHADOW_TILEMAP_LOD3_LEN
const ccl_global KernelWorkTile * tile
const int tile_index
descriptor
detail::Pass< command::DrawCommandBuf > PassSimple
static void test_eevee_shadow_free()
static void test_eevee_surfel_list()
static void test_eevee_shadow_tilemap_amend()
static void test_eevee_lut_gen()
static void test_eevee_shadow_defrag()
static void test_eevee_shadow_finalize()
static void test_eevee_shadow_tag_update()
static void test_eevee_shadow_shift()
Definition eevee_test.cc:97
static void test_eevee_shadow_alloc()
static void test_eevee_shadow_page_mask()
static void test_eevee_shadow_page_mask_ex(int max_view_per_tilemap)
static void test_eevee_shadow_shift_clear()
Definition eevee_test.cc:26
static void test_eevee_shadow_tile_packing()
const float burley_sss_profile[64][1]
const float brdf_ggx[64][64][3]
const float random_walk_sss_profile[64][1]
const float btdf_ggx[16][64][64][1]
const float bsdf_ggx[16][64][64][3]
draw::StorageArrayBuffer< LightData, LIGHT_CHUNK > LightDataBuf
draw::StorageBuffer< ShadowPagesInfoData > ShadowPagesInfoDataBuf
draw::StorageArrayBuffer< ShadowTileDataPacked, SHADOW_MAX_TILE, true > ShadowTileDataBuf
draw::StorageArrayBuffer< ShadowTileMapClip, SHADOW_MAX_TILEMAP, true > ShadowTileMapClipBuf
draw::StorageArrayBuffer< uint, CULLING_ZBIN_COUNT, true > LightCullingZbinBuf
draw::StorageArrayBuffer< uint2, SHADOW_MAX_PAGE, true > ShadowPageCacheBuf
draw::StorageArrayBuffer< uint, LIGHT_CHUNK, true > LightCullingTileBuf
draw::StorageArrayBuffer< ShadowRenderView, SHADOW_VIEW_MAX, true > ShadowRenderViewBuf
draw::StorageBuffer< LightCullingData > LightCullingDataBuf
static ShadowTileDataPacked shadow_tile_pack(ShadowTileData tile)
static ShadowSamplingTilePacked shadow_sampling_tile_pack(ShadowSamplingTile tile)
draw::StorageBuffer< SurfelListInfoData > SurfelListInfoBuf
static ShadowTileData shadow_tile_unpack(ShadowTileDataPacked data)
static uint2 shadow_lod_offset_unpack(uint data)
static uint3 shadow_page_unpack(uint data)
draw::StorageBuffer< CaptureInfoData > CaptureInfoBuf
static uint shadow_page_pack(uint3 page)
static uint shadow_lod_offset_pack(uint2 ofs)
draw::StorageBuffer< ShadowStatistics > ShadowStatisticsBuf
draw::StorageVectorBuffer< ShadowTileMapData, SHADOW_MAX_TILEMAP > ShadowTileMapDataBuf
static ShadowSamplingTile shadow_sampling_tile_unpack(ShadowSamplingTilePacked data)
draw::StorageVectorBuffer< uint, SHADOW_MAX_PAGE > ShadowPageHeapBuf
MatBase< T, 4, 4 > orthographic(T left, T right, T bottom, T top, T near_clip, T far_clip)
Create an orthographic projection matrix using OpenGL coordinate convention: Maps each axis range to ...
MatBase< T, 4, 4 > perspective(T left, T right, T bottom, T top, T near_clip, T far_clip)
Create a perspective projection matrix using OpenGL coordinate convention: Maps each axis range to [-...
MatT from_loc_rot_scale(const typename MatT::loc_type &location, const RotationT &rotation, const VecBase< typename MatT::base_type, ScaleDim > &scale)
VecBase< uint32_t, 2 > uint2
VecBase< float, 1 > float1
VecBase< uint32_t, 4 > uint4
VecBase< uint32_t, 3 > uint3
MatBase< float, 4, 4 > float4x4
VecBase< int32_t, 2 > int2
VecBase< int32_t, 3 > int3
VecBase< float, 3 > float3
const btScalar eps
Definition poly34.cpp:11
void sync_orthographic(const float4x4 &object_mat_, int2 origin_offset, int clipmap_level, eShadowProjectionType projection_type_, uint2 shadow_set_membership_=~uint2(0))
void sync_cubeface(eLightType light_type_, const float4x4 &object_mat, float near, float far, eCubeFace face, uint2 shadow_set_membership_=~uint2(0))
i
Definition text_draw.cc:230
uint len