terrain: in-place mipgenerator for virtual texture update

This commit is contained in:
Turánszki János
2022-10-03 18:29:44 +02:00
parent 1eba681e74
commit e0db197981
3 changed files with 213 additions and 28 deletions
@@ -9,17 +9,34 @@ struct Terrain
};
ConstantBuffer<Terrain> terrain : register(b0);
// These are expected to be in the same bind slots as corresponding MaterialComponent::TEXTURESLOT enums
RWTexture2D<unorm float4> output_baseColorMap : register(u0);
RWTexture2D<unorm float4> output_normalMap : register(u1);
RWTexture2D<unorm float4> output_surfaceMap : register(u2);
RWTexture2D<unorm float4> output_baseColorMap_mip0 : register(u0);
RWTexture2D<unorm float4> output_baseColorMap_mip1 : register(u1);
RWTexture2D<unorm float4> output_baseColorMap_mip2 : register(u2);
RWTexture2D<unorm float4> output_baseColorMap_mip3 : register(u3);
RWTexture2D<unorm float4> output_normalMap_mip0 : register(u4);
RWTexture2D<unorm float4> output_normalMap_mip1 : register(u5);
RWTexture2D<unorm float4> output_normalMap_mip2 : register(u6);
RWTexture2D<unorm float4> output_normalMap_mip3 : register(u7);
RWTexture2D<unorm float4> output_surfaceMap_mip0 : register(u8);
RWTexture2D<unorm float4> output_surfaceMap_mip1 : register(u9);
RWTexture2D<unorm float4> output_surfaceMap_mip2 : register(u10);
RWTexture2D<unorm float4> output_surfaceMap_mip3 : register(u11);
groupshared float lds_r[8][8];
groupshared float lds_g[8][8];
groupshared float lds_b[8][8];
groupshared float lds_a[8][8];
[numthreads(8, 8, 1)]
void main(uint3 DTid : SV_DispatchThreadID)
void main(uint3 DTid : SV_DispatchThreadID, uint2 GTid : SV_GroupThreadID)
{
const uint2 pixel = DTid.xy;
float2 output_dim = 0;
output_baseColorMap.GetDimensions(output_dim.x, output_dim.y);
const float2 uv = (DTid.xy + 0.5f) / output_dim;
output_baseColorMap_mip0.GetDimensions(output_dim.x, output_dim.y);
const float2 uv = (pixel + 0.5f) / output_dim;
float4 region_weights = region_weights_texture.SampleLevel(sampler_linear_clamp, uv, 0);
@@ -84,7 +101,181 @@ void main(uint3 DTid : SV_DispatchThreadID)
total_surface /= weight_sum;
total_normal /= weight_sum;
output_baseColorMap[DTid.xy] = total_baseColor;
output_surfaceMap[DTid.xy] = total_surface;
output_normalMap[DTid.xy] = float4(total_normal, 1, 1);
output_baseColorMap_mip0[pixel] = total_baseColor;
output_surfaceMap_mip0[pixel] = total_surface;
output_normalMap_mip0[pixel] = float4(total_normal, 1, 1);
// Mip writes:
// Basecolormap:
lds_r[GTid.x][GTid.y] = total_baseColor.r;
lds_g[GTid.x][GTid.y] = total_baseColor.g;
lds_b[GTid.x][GTid.y] = total_baseColor.b;
GroupMemoryBarrierWithGroupSync();
if (GTid.x % 2 == 0 && GTid.y % 2 == 0)
{
float4 value = (
float4(lds_r[GTid.x + 0][GTid.y + 0], lds_g[GTid.x + 0][GTid.y + 0], lds_b[GTid.x + 0][GTid.y + 0], 1) +
float4(lds_r[GTid.x + 1][GTid.y + 0], lds_g[GTid.x + 1][GTid.y + 0], lds_b[GTid.x + 1][GTid.y + 0], 1) +
float4(lds_r[GTid.x + 0][GTid.y + 1], lds_g[GTid.x + 0][GTid.y + 1], lds_b[GTid.x + 0][GTid.y + 1], 1) +
float4(lds_r[GTid.x + 1][GTid.y + 1], lds_g[GTid.x + 1][GTid.y + 1], lds_b[GTid.x + 1][GTid.y + 1], 1)
) / 4.0f;
output_baseColorMap_mip1[pixel / 2] = value;
lds_r[GTid.x][GTid.y] = value.r;
lds_g[GTid.x][GTid.y] = value.g;
lds_b[GTid.x][GTid.y] = value.b;
}
GroupMemoryBarrierWithGroupSync();
if (GTid.x % 4 == 0 && GTid.y % 4 == 0)
{
float4 value = (
float4(lds_r[GTid.x + 0][GTid.y + 0], lds_g[GTid.x + 0][GTid.y + 0], lds_b[GTid.x + 0][GTid.y + 0], 1) +
float4(lds_r[GTid.x + 2][GTid.y + 0], lds_g[GTid.x + 2][GTid.y + 0], lds_b[GTid.x + 2][GTid.y + 0], 1) +
float4(lds_r[GTid.x + 0][GTid.y + 2], lds_g[GTid.x + 0][GTid.y + 2], lds_b[GTid.x + 0][GTid.y + 2], 1) +
float4(lds_r[GTid.x + 2][GTid.y + 2], lds_g[GTid.x + 2][GTid.y + 2], lds_b[GTid.x + 2][GTid.y + 2], 1)
) / 4.0f;
output_baseColorMap_mip2[pixel / 4] = value;
lds_r[GTid.x][GTid.y] = value.r;
lds_g[GTid.x][GTid.y] = value.g;
lds_b[GTid.x][GTid.y] = value.b;
}
GroupMemoryBarrierWithGroupSync();
if (GTid.x % 8 == 0 && GTid.y % 8 == 0)
{
float4 value = (
float4(lds_r[GTid.x + 0][GTid.y + 0], lds_g[GTid.x + 0][GTid.y + 0], lds_b[GTid.x + 0][GTid.y + 0], 1) +
float4(lds_r[GTid.x + 4][GTid.y + 0], lds_g[GTid.x + 4][GTid.y + 0], lds_b[GTid.x + 4][GTid.y + 0], 1) +
float4(lds_r[GTid.x + 0][GTid.y + 4], lds_g[GTid.x + 0][GTid.y + 4], lds_b[GTid.x + 0][GTid.y + 4], 1) +
float4(lds_r[GTid.x + 4][GTid.y + 4], lds_g[GTid.x + 4][GTid.y + 4], lds_b[GTid.x + 4][GTid.y + 4], 1)
) / 4.0f;
output_baseColorMap_mip3[pixel / 8] = value;
}
GroupMemoryBarrierWithGroupSync();
// Normalmap:
lds_r[GTid.x][GTid.y] = total_normal.r;
lds_g[GTid.x][GTid.y] = total_normal.g;
GroupMemoryBarrierWithGroupSync();
if (GTid.x % 2 == 0 && GTid.y % 2 == 0)
{
float4 value = (
float4(lds_r[GTid.x + 0][GTid.y + 0], lds_g[GTid.x + 0][GTid.y + 0], 1, 1) +
float4(lds_r[GTid.x + 1][GTid.y + 0], lds_g[GTid.x + 1][GTid.y + 0], 1, 1) +
float4(lds_r[GTid.x + 0][GTid.y + 1], lds_g[GTid.x + 0][GTid.y + 1], 1, 1) +
float4(lds_r[GTid.x + 1][GTid.y + 1], lds_g[GTid.x + 1][GTid.y + 1], 1, 1)
) / 4.0f;
output_normalMap_mip1[pixel / 2] = value;
lds_r[GTid.x][GTid.y] = value.r;
lds_g[GTid.x][GTid.y] = value.g;
lds_b[GTid.x][GTid.y] = value.b;
}
GroupMemoryBarrierWithGroupSync();
if (GTid.x % 4 == 0 && GTid.y % 4 == 0)
{
float4 value = (
float4(lds_r[GTid.x + 0][GTid.y + 0], lds_g[GTid.x + 0][GTid.y + 0], 1, 1) +
float4(lds_r[GTid.x + 2][GTid.y + 0], lds_g[GTid.x + 2][GTid.y + 0], 1, 1) +
float4(lds_r[GTid.x + 0][GTid.y + 2], lds_g[GTid.x + 0][GTid.y + 2], 1, 1) +
float4(lds_r[GTid.x + 2][GTid.y + 2], lds_g[GTid.x + 2][GTid.y + 2], 1, 1)
) / 4.0f;
output_normalMap_mip2[pixel / 4] = value;
lds_r[GTid.x][GTid.y] = value.r;
lds_g[GTid.x][GTid.y] = value.g;
lds_b[GTid.x][GTid.y] = value.b;
}
GroupMemoryBarrierWithGroupSync();
if (GTid.x % 8 == 0 && GTid.y % 8 == 0)
{
float4 value = (
float4(lds_r[GTid.x + 0][GTid.y + 0], lds_g[GTid.x + 0][GTid.y + 0], 1, 1) +
float4(lds_r[GTid.x + 4][GTid.y + 0], lds_g[GTid.x + 4][GTid.y + 0], 1, 1) +
float4(lds_r[GTid.x + 0][GTid.y + 4], lds_g[GTid.x + 0][GTid.y + 4], 1, 1) +
float4(lds_r[GTid.x + 4][GTid.y + 4], lds_g[GTid.x + 4][GTid.y + 4], 1, 1)
) / 4.0f;
output_normalMap_mip3[pixel / 8] = value;
}
GroupMemoryBarrierWithGroupSync();
// Surfacemap:
lds_r[GTid.x][GTid.y] = total_surface.r;
lds_g[GTid.x][GTid.y] = total_surface.g;
lds_b[GTid.x][GTid.y] = total_surface.b;
lds_a[GTid.x][GTid.y] = total_surface.a;
GroupMemoryBarrierWithGroupSync();
if (GTid.x % 2 == 0 && GTid.y % 2 == 0)
{
float4 value = (
float4(lds_r[GTid.x + 0][GTid.y + 0], lds_g[GTid.x + 0][GTid.y + 0], lds_b[GTid.x + 0][GTid.y + 0], lds_a[GTid.x + 0][GTid.y + 0]) +
float4(lds_r[GTid.x + 1][GTid.y + 0], lds_g[GTid.x + 1][GTid.y + 0], lds_b[GTid.x + 1][GTid.y + 0], lds_a[GTid.x + 1][GTid.y + 0]) +
float4(lds_r[GTid.x + 0][GTid.y + 1], lds_g[GTid.x + 0][GTid.y + 1], lds_b[GTid.x + 0][GTid.y + 1], lds_a[GTid.x + 0][GTid.y + 1]) +
float4(lds_r[GTid.x + 1][GTid.y + 1], lds_g[GTid.x + 1][GTid.y + 1], lds_b[GTid.x + 1][GTid.y + 1], lds_a[GTid.x + 1][GTid.y + 1])
) / 4.0f;
output_surfaceMap_mip1[pixel / 2] = value;
lds_r[GTid.x][GTid.y] = value.r;
lds_g[GTid.x][GTid.y] = value.g;
lds_b[GTid.x][GTid.y] = value.b;
}
GroupMemoryBarrierWithGroupSync();
if (GTid.x % 4 == 0 && GTid.y % 4 == 0)
{
float4 value = (
float4(lds_r[GTid.x + 0][GTid.y + 0], lds_g[GTid.x + 0][GTid.y + 0], lds_b[GTid.x + 0][GTid.y + 0], lds_a[GTid.x + 0][GTid.y + 0]) +
float4(lds_r[GTid.x + 2][GTid.y + 0], lds_g[GTid.x + 2][GTid.y + 0], lds_b[GTid.x + 2][GTid.y + 0], lds_a[GTid.x + 2][GTid.y + 0]) +
float4(lds_r[GTid.x + 0][GTid.y + 2], lds_g[GTid.x + 0][GTid.y + 2], lds_b[GTid.x + 0][GTid.y + 2], lds_a[GTid.x + 0][GTid.y + 2]) +
float4(lds_r[GTid.x + 2][GTid.y + 2], lds_g[GTid.x + 2][GTid.y + 2], lds_b[GTid.x + 2][GTid.y + 2], lds_a[GTid.x + 2][GTid.y + 2])
) / 4.0f;
output_surfaceMap_mip2[pixel / 4] = value;
lds_r[GTid.x][GTid.y] = value.r;
lds_g[GTid.x][GTid.y] = value.g;
lds_b[GTid.x][GTid.y] = value.b;
}
GroupMemoryBarrierWithGroupSync();
if (GTid.x % 8 == 0 && GTid.y % 8 == 0)
{
float4 value = (
float4(lds_r[GTid.x + 0][GTid.y + 0], lds_g[GTid.x + 0][GTid.y + 0], lds_b[GTid.x + 0][GTid.y + 0], lds_a[GTid.x + 0][GTid.y + 0]) +
float4(lds_r[GTid.x + 4][GTid.y + 0], lds_g[GTid.x + 4][GTid.y + 0], lds_b[GTid.x + 4][GTid.y + 0], lds_a[GTid.x + 4][GTid.y + 0]) +
float4(lds_r[GTid.x + 0][GTid.y + 4], lds_g[GTid.x + 0][GTid.y + 4], lds_b[GTid.x + 0][GTid.y + 4], lds_a[GTid.x + 0][GTid.y + 4]) +
float4(lds_r[GTid.x + 4][GTid.y + 4], lds_g[GTid.x + 4][GTid.y + 4], lds_b[GTid.x + 4][GTid.y + 4], lds_a[GTid.x + 4][GTid.y + 4])
) / 4.0f;
output_surfaceMap_mip3[pixel / 8] = value;
}
}
+11 -17
View File
@@ -518,16 +518,17 @@ namespace wi::terrain
TextureDesc desc;
desc.width = chunk_data.required_texture_resolution;
desc.height = chunk_data.required_texture_resolution;
desc.format = Format::R8G8B8A8_UNORM;
desc.bind_flags = BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS;
if (desc.width > 64)
if (i == MaterialComponent::TEXTURESLOT::NORMALMAP)
{
desc.mip_levels = (uint32_t)log2(std::max(desc.width, desc.height)) + 1;
desc.format = Format::R8G8_UNORM;
}
else
{
desc.mip_levels = 1;
desc.format = Format::R8G8B8A8_UNORM;
}
desc.bind_flags = BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS;
desc.layout = ResourceState::SHADER_RESOURCE_COMPUTE;
desc.mip_levels = 4;
Texture texture;
bool success = device->CreateTexture(&desc, nullptr, &texture);
assert(success);
@@ -536,10 +537,7 @@ namespace wi::terrain
{
for (uint32_t i = 0; i < texture.desc.mip_levels; ++i)
{
int subresource_index;
subresource_index = device->CreateSubresource(&texture, SubresourceType::SRV, 0, 1, i, 1);
assert(subresource_index == i);
subresource_index = device->CreateSubresource(&texture, SubresourceType::UAV, 0, 1, i, 1);
int subresource_index = device->CreateSubresource(&texture, SubresourceType::UAV, 0, 1, i, 1);
assert(subresource_index == i);
}
}
@@ -955,12 +953,10 @@ namespace wi::terrain
{
const Texture& texture = material->textures[i].resource.GetTexture();
device->BindUAV(&texture, i, cmd);
if (texture.GetDesc().mip_levels > 1)
{
wi::renderer::AddDeferredMIPGen(material->textures[i].resource.GetTexture());
}
device->BindUAV(&texture, i * 4 + 0, cmd, 0);
device->BindUAV(&texture, i * 4 + 1, cmd, 1);
device->BindUAV(&texture, i * 4 + 2, cmd, 2);
device->BindUAV(&texture, i * 4 + 3, cmd, 3);
}
}
}
@@ -970,8 +966,6 @@ namespace wi::terrain
device->Barrier(virtual_texture_barriers_end.data(), (uint32_t)virtual_texture_barriers_end.size(), cmd);
wi::renderer::ProcessDeferredMipGenRequests(cmd);
wi::profiler::EndRange(range);
device->EventEnd(cmd);
}
+1 -1
View File
@@ -9,7 +9,7 @@ namespace wi::version
// minor features, major updates, breaking compatibility changes
const int minor = 71;
// minor bug fixes, alterations, refactors, updates
const int revision = 67;
const int revision = 68;
const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);