Skip to content

Commit 15b832d

Browse files
committed
voxel improvements
1 parent 76d8880 commit 15b832d

4 files changed

Lines changed: 54 additions & 58 deletions

File tree

sources/RenderSystem/Effects/VoxelGI/VoxelGIGraph.cpp

Lines changed: 22 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -504,52 +504,40 @@ VoxelGI::VoxelGI(Scene::ptr& scene) :scene(scene), VariableContext(L"VoxelGI")
504504
compute.set_signature(Layouts::DefaultLayout);
505505
context.graph->set_slot(SlotID::VoxelInfo, compute);
506506

507-
compute.set_pipeline<PSOS::VoxelZero>();
507+
const uint mip_levels = tex_lighting.tex_result->get_desc().as_texture().MipLevels;
508+
508509
{
509-
PROFILE_GPU(L"ZERO");
510-
for (uint i = 1; i < tex_lighting.tex_result->get_desc().as_texture().MipLevels; i++)
511-
{
510+
// Only the tail mips without a tile list (packed) still need a
511+
// clear — they are never downsampled and the cone trace samples
512+
// them at high LODs. Tiny textures, cost is negligible.
513+
PROFILE_GPU(L"clear tail mips");
514+
for (uint i = 1; i < mip_levels; i++)
512515
if (i >= gpu_tiles_buffer.size() || !gpu_tiles_buffer[i])
513-
{
514516
list.clear_uav(tex_lighting.tex_result->texture_3d().mips[i].rwTexture3D,
515517
vec4(0, 0, 0, 0));
516-
continue;
517-
}
518-
519-
{
520-
Slots::VoxelZero utils;
521-
utils.GetTarget() = tex_lighting.tex_result->texture_3d().mips[i].rwTexture3D;
522-
auto& params = utils.GetParams();
523-
params.GetTiles() = gpu_tiles_buffer[i]->buffer;
524-
params.GetVoxels_per_tile().xyz =
525-
tex_lighting.tex_result->resource->get_tiled_manager().get_tile_shape();
526-
compute.set(utils);
527-
}
528-
529-
compute.exec_indirect(gpu_tiles_buffer[i]->dispatch_buffer, 1);
530-
}
531518
}
532519

533520
{
521+
// One dispatch per mip over that mip's OWN tile list: every texel
522+
// of every loaded tile is written, and unmapped source tiles read
523+
// as 0 — so the old per-tile VoxelZero pre-pass is unnecessary.
524+
// (The old 3-mips-per-dispatch batches covered mips 2,3,5,6 only
525+
// under loaded finer tiles, which is what the zero pass patched.)
534526
PROFILE_GPU(L"EXEC");
535-
unsigned int mip_count = 1;
536-
while (mip_count < tex_lighting.tex_result->get_desc().as_texture().MipLevels)
527+
compute.set_pipeline<PSOS::VoxelDownsample>(PSOS::VoxelDownsample::Count(1));
528+
529+
for (uint mip = 1; mip < mip_levels; mip++)
537530
{
538-
if (!gpu_tiles_buffer[mip_count]) break;
539-
unsigned int current_mips = std::min(
540-
3u, tex_lighting.tex_result->get_desc().as_texture().MipLevels - mip_count);
541-
compute.set_pipeline<PSOS::VoxelDownsample>(
542-
PSOS::VoxelDownsample::Count(current_mips));
531+
if (mip >= gpu_tiles_buffer.size() || !gpu_tiles_buffer[mip]) break;
543532

544533
{
545534
Slots::VoxelMipMap mipmapping;
546535
mipmapping.GetSrcMip() =
547-
tex_lighting.tex_result->texture_3d().mips[mip_count - 1].texture3D;
548-
for (unsigned int i = 0; i < current_mips; i++)
549-
mipmapping.GetOutMips()[i] =
550-
tex_lighting.tex_result->texture_3d().mips[mip_count + i].rwTexture3D;
536+
tex_lighting.tex_result->texture_3d().mips[mip - 1].texture3D;
537+
mipmapping.GetOutMips()[0] =
538+
tex_lighting.tex_result->texture_3d().mips[mip].rwTexture3D;
551539
auto& params = mipmapping.GetParams();
552-
params.GetTiles() = gpu_tiles_buffer[mip_count]->buffer;
540+
params.GetTiles() = gpu_tiles_buffer[mip]->buffer;
553541
params.GetVoxels_per_tile().xyz =
554542
tex_lighting.tex_result->resource->get_tiled_manager().get_tile_shape();
555543
compute.set(mipmapping);
@@ -560,9 +548,8 @@ VoxelGI::VoxelGI(Scene::ptr& scene) :scene(scene), VariableContext(L"VoxelGI")
560548
L"mip_8", L"mip_9", L"mip_10", L"mip_11",
561549
L"mip_12", L"mip_13", L"mip_14", L"mip_15",
562550
};
563-
PROFILE_GPU(mip_names[mip_count < 16 ? mip_count : 0]);
564-
compute.exec_indirect(gpu_tiles_buffer[mip_count]->dispatch_buffer, 1);
565-
mip_count += current_mips;
551+
PROFILE_GPU(mip_names[mip < 16 ? mip : 0]);
552+
compute.exec_indirect(gpu_tiles_buffer[mip]->dispatch_buffer, 1);
566553
}
567554
}
568555
};

sources/RenderSystem/TiledTextures/DynamicTileGenerator.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ void TileDynamicGenerator::set_scene_volume(vec3 min, vec3 max)
4343
this->min = min;
4444
this->max = max;
4545

46-
one_tile_size = (max - min) / tile_count;
46+
one_tile_size = (max - min) / vec3(tile_count);
4747
}
4848

4949
void TileDynamicGenerator::begin(vec3 min, vec3 max)
@@ -63,6 +63,12 @@ void TileDynamicGenerator::add(vec3 min, vec3 max)
6363
ivec3 from = (min - this->min) / one_tile_size;
6464
ivec3 to = (max - this->min + one_tile_size ) / one_tile_size;
6565

66+
// Clamp to the tile grid: an AABB at/outside the scene volume produces
67+
// negative or past-end indices, and all_tiles[pos] would index the grid
68+
// out of bounds. Fully-outside objects end up with from >= to (no tiles).
69+
from = ivec3::max(from, ivec3(0, 0, 0));
70+
to = ivec3::min(to, ivec3(tile_count));
71+
6672
for (int x = from.x; x < to.x; x++)
6773
for (int y = from.y; y < to.y; y++)
6874
for (int z = from.z; z < to.z; z++)

sources/RenderSystem/TiledTextures/DynamicTileGenerator.ixx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ export {
88
uint3 tile_count;
99
vec3 min, max;
1010

11-
uint3 one_tile_size;
11+
// World-space tile extent. MUST stay float: scene_size/tile_count is
12+
// fractional (e.g. 200/16 = 12.5) and integer truncation makes the
13+
// tile ranges in add() drift with distance from the scene min —
14+
// dynamic objects far from the origin mark the wrong tiles.
15+
vec3 one_tile_size;
1216
grid<uint3, uint64> all_tiles;
1317
std::list<uint3> old_tiles;
1418

workdir/shaders/voxel_mipmap.hlsl

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,21 @@ static const Texture3D<float4> SrcMip = GetVoxelMipMap().GetSrcMip();
1212
static const VoxelInfo voxel_info = GetVoxelInfo();
1313

1414

15-
void calc(inout float4 color)
15+
// For the first stage the /8 average is done by the trilinear fetch itself;
16+
// the groupshared stages below still sum 8 values and need the divide.
17+
void calc_avg(inout float4 color)
1618
{
17-
// color.rgb/= color.w ;//+ 1;
18-
//color.w = saturate(color.w/4);
19-
20-
color /= 8;
2119
color.w=saturate(color.w*1.3f);
2220
//todo: investigate negative values
2321
color = max(0, color);
2422
}
2523

24+
void calc(inout float4 color)
25+
{
26+
color /= 8;
27+
calc_avg(color);
28+
}
29+
2630
void add_color(inout float4 result, float4 c)
2731
{
2832
result += float4(c.rgb,c.w);
@@ -43,27 +47,22 @@ void CS(
4347
uint local_index = groupThreadID.x+groupThreadID.y*4+groupThreadID.z*16;
4448
uint3 index = GetVoxelMipMap().GetParams().get_voxel_pos(dispatchID);
4549

50+
float3 dims;
51+
SrcMip.GetDimensions(dims.x, dims.y, dims.z);
4652

53+
// One trilinear fetch at the 2x2x2 block corner IS the 8-texel average —
54+
// the filtering hardware does the 8 loads + divide. Unmapped source tiles
55+
// read as 0, so loaded output tiles over unloaded input regions come out
56+
// zero without a separate clear pass.
57+
float4 c = SrcMip.SampleLevel(linearClampSampler, (2 * index + 1) / dims, 0);
4758

48-
// float4 color = SrcMip.SampleLevel(linearSampler,(2*index+1)/dims,0);
49-
float4 c = 0;
50-
51-
int4 tc = int4(2 * index , 0);
52-
53-
add_color(c, SrcMip.Load(tc, int3(0, 0, 0)));
54-
add_color(c, SrcMip.Load(tc, int3(0, 0, 1)));
55-
add_color(c, SrcMip.Load(tc, int3(0, 1, 0)));
56-
add_color(c, SrcMip.Load(tc, int3(0, 1, 1)));
57-
58-
add_color(c, SrcMip.Load(tc, int3(1, 0, 0)));
59-
add_color(c, SrcMip.Load(tc, int3(1, 0, 1)));
60-
add_color(c, SrcMip.Load(tc, int3(1, 1, 0)));
61-
add_color(c, SrcMip.Load(tc, int3(1, 1, 1)));
59+
calc_avg(c);
6260

63-
calc(c);
64-
6561
OutMip1[index] = c;
62+
63+
#if COUNT >= 2
6664
data[local_index] = c;
65+
#endif
6766

6867
#if COUNT >=2
6968
GroupMemoryBarrierWithGroupSync();

0 commit comments

Comments
 (0)