Merge pull request #55281 from bruvzg/mvk_fog_volumes

This commit is contained in:
Rémi Verschelde 2021-11-24 16:59:20 +01:00 committed by GitHub
commit 3e3300637e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 113 additions and 0 deletions

View file

@ -3796,6 +3796,18 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
rb->volumetric_fog->fog_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
RD::get_singleton()->set_resource_name(rb->volumetric_fog->fog_map, "Fog map");
#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
Vector<uint8_t> dm;
dm.resize(target_width * target_height * volumetric_fog_depth * 4);
dm.fill(0);
rb->volumetric_fog->density_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
RD::get_singleton()->set_resource_name(rb->volumetric_fog->density_map, "Fog density map");
rb->volumetric_fog->light_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
RD::get_singleton()->set_resource_name(rb->volumetric_fog->light_map, "Fog light map");
rb->volumetric_fog->emissive_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
RD::get_singleton()->set_resource_name(rb->volumetric_fog->emissive_map, "Fog emissive map");
#else
tf.format = RD::DATA_FORMAT_R32_UINT;
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
rb->volumetric_fog->density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
@ -3807,6 +3819,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
rb->volumetric_fog->emissive_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
RD::get_singleton()->set_resource_name(rb->volumetric_fog->emissive_map, "Fog emissive map");
RD::get_singleton()->texture_clear(rb->volumetric_fog->emissive_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
#endif
Vector<RD::Uniform> uniforms;
{
@ -3872,7 +3885,11 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
{
RD::Uniform u;
#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
#else
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
#endif
u.binding = 1;
u.ids.push_back(rb->volumetric_fog->emissive_map);
uniforms.push_back(u);
@ -3888,7 +3905,11 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
{
RD::Uniform u;
#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
#else
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
#endif
u.binding = 3;
u.ids.push_back(rb->volumetric_fog->density_map);
uniforms.push_back(u);
@ -3896,7 +3917,11 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
{
RD::Uniform u;
#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
#else
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
#endif
u.binding = 4;
u.ids.push_back(rb->volumetric_fog->light_map);
uniforms.push_back(u);
@ -4163,14 +4188,22 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
}
{
RD::Uniform u;
#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
#else
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
#endif
u.binding = 16;
u.ids.push_back(rb->volumetric_fog->density_map);
uniforms.push_back(u);
}
{
RD::Uniform u;
#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
#else
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
#endif
u.binding = 17;
u.ids.push_back(rb->volumetric_fog->light_map);
uniforms.push_back(u);
@ -4178,7 +4211,11 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
{
RD::Uniform u;
#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
#else
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
#endif
u.binding = 18;
u.ids.push_back(rb->volumetric_fog->emissive_map);
uniforms.push_back(u);

View file

@ -177,6 +177,9 @@ void ShaderRD::_build_variant_code(StringBuilder &builder, uint32_t p_variant, c
for (const KeyValue<StringName, CharString> &E : p_version->code_sections) {
builder.append(String("#define ") + String(E.key) + "_CODE_USED\n");
}
#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
builder.append("#define MOLTENVK_USED\n");
#endif
} break;
case StageTemplate::Chunk::TYPE_MATERIAL_UNIFORMS: {
builder.append(p_version->uniforms.get_data()); //uniforms (same for vertex and fragment)

View file

@ -47,7 +47,13 @@ layout(push_constant, binding = 0, std430) uniform Params {
}
params;
#ifdef MOLTENVK_USED
layout(set = 1, binding = 1) volatile buffer emissive_only_map_buffer {
uint emissive_only_map[];
};
#else
layout(r32ui, set = 1, binding = 1) uniform volatile uimage3D emissive_only_map;
#endif
layout(set = 1, binding = 2, std140) uniform SceneParams {
vec2 fog_frustum_size_begin;
@ -71,8 +77,17 @@ layout(set = 1, binding = 2, std140) uniform SceneParams {
}
scene_params;
#ifdef MOLTENVK_USED
layout(set = 1, binding = 3) volatile buffer density_only_map_buffer {
uint density_only_map[];
};
layout(set = 1, binding = 4) volatile buffer light_only_map_buffer {
uint light_only_map[];
};
#else
layout(r32ui, set = 1, binding = 3) uniform volatile uimage3D density_only_map;
layout(r32ui, set = 1, binding = 4) uniform volatile uimage3D light_only_map;
#endif
#ifdef MATERIAL_UNIFORMS_USED
layout(set = 2, binding = 0, std140) uniform MaterialUniforms{
@ -115,6 +130,9 @@ void main() {
if (any(greaterThanEqual(pos, scene_params.fog_volume_size))) {
return; //do not compute
}
#ifdef MOLTENVK_USED
uint lpos = pos.z * scene_params.fog_volume_size.x * scene_params.fog_volume_size.y + pos.y * scene_params.fog_volume_size.x + pos.x;
#endif
vec3 posf = vec3(pos);
@ -197,7 +215,11 @@ void main() {
density *= cull_mask;
if (abs(density) > 0.001) {
int final_density = int(density * DENSITY_SCALE);
#ifdef MOLTENVK_USED
atomicAdd(density_only_map[lpos], uint(final_density));
#else
imageAtomicAdd(density_only_map, pos, uint(final_density));
#endif
#ifdef EMISSION_USED
{
@ -207,7 +229,11 @@ void main() {
uvec3 emission_u = uvec3(emission.r * 511.0, emission.g * 511.0, emission.b * 255.0);
// R and G have 11 bits each and B has 10. Then pack them into a 32 bit uint
uint final_emission = emission_u.r << 21 | emission_u.g << 10 | emission_u.b;
#ifdef MOLTENVK_USED
uint prev_emission = atomicAdd(emissive_only_map[lpos], final_emission);
#else
uint prev_emission = imageAtomicAdd(emissive_only_map, pos, final_emission);
#endif
// Adding can lead to colors overflowing, so validate
uvec3 prev_emission_u = uvec3(prev_emission >> 21, (prev_emission << 11) >> 21, prev_emission % 1024);
@ -219,7 +245,11 @@ void main() {
if (any(overflowing)) {
uvec3 overflow_factor = mix(uvec3(0), uvec3(2047 << 21, 2047 << 10, 1023), overflowing);
uint force_max = overflow_factor.r | overflow_factor.g | overflow_factor.b;
#ifdef MOLTENVK_USED
atomicOr(emissive_only_map[lpos], force_max);
#else
imageAtomicOr(emissive_only_map, pos, force_max);
#endif
}
}
#endif
@ -230,7 +260,11 @@ void main() {
uvec3 scattering_u = uvec3(scattering.r * 2047.0, scattering.g * 2047.0, scattering.b * 1023.0);
// R and G have 11 bits each and B has 10. Then pack them into a 32 bit uint
uint final_scattering = scattering_u.r << 21 | scattering_u.g << 10 | scattering_u.b;
#ifdef MOLTENVK_USED
uint prev_scattering = atomicAdd(light_only_map[lpos], final_scattering);
#else
uint prev_scattering = imageAtomicAdd(light_only_map, pos, final_scattering);
#endif
// Adding can lead to colors overflowing, so validate
uvec3 prev_scattering_u = uvec3(prev_scattering >> 21, (prev_scattering << 11) >> 21, prev_scattering % 1024);
@ -242,7 +276,11 @@ void main() {
if (any(overflowing)) {
uvec3 overflow_factor = mix(uvec3(0), uvec3(2047 << 21, 2047 << 10, 1023), overflowing);
uint force_max = overflow_factor.r | overflow_factor.g | overflow_factor.b;
#ifdef MOLTENVK_USED
atomicOr(light_only_map[lpos], force_max);
#else
imageAtomicOr(light_only_map, pos, force_max);
#endif
}
}
#endif // ALBEDO_USED

View file

@ -190,9 +190,22 @@ params;
#ifndef MODE_COPY
layout(set = 0, binding = 15) uniform texture3D prev_density_texture;
#ifdef MOLTENVK_USED
layout(set = 0, binding = 16) buffer density_only_map_buffer {
uint density_only_map[];
};
layout(set = 0, binding = 17) buffer light_only_map_buffer {
uint light_only_map[];
};
layout(set = 0, binding = 18) buffer emissive_only_map_buffer {
uint emissive_only_map[];
};
#else
layout(r32ui, set = 0, binding = 16) uniform uimage3D density_only_map;
layout(r32ui, set = 0, binding = 17) uniform uimage3D light_only_map;
layout(r32ui, set = 0, binding = 18) uniform uimage3D emissive_only_map;
#endif
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
layout(set = 0, binding = 19) uniform textureCubeArray sky_texture;
#else
@ -272,6 +285,9 @@ void main() {
if (any(greaterThanEqual(pos, params.fog_volume_size))) {
return; //do not compute
}
#ifdef MOLTENVK_USED
uint lpos = pos.z * params.fog_volume_size.x * params.fog_volume_size.y + pos.y * params.fog_volume_size.x + pos.x;
#endif
vec3 posf = vec3(pos);
@ -335,15 +351,28 @@ void main() {
vec3 total_light = vec3(0.0);
float total_density = params.base_density;
#ifdef MOLTENVK_USED
uint local_density = density_only_map[lpos];
#else
uint local_density = imageLoad(density_only_map, pos).x;
#endif
total_density += float(int(local_density)) / DENSITY_SCALE;
total_density = max(0.0, total_density);
#ifdef MOLTENVK_USED
uint scattering_u = light_only_map[lpos];
#else
uint scattering_u = imageLoad(light_only_map, pos).x;
#endif
vec3 scattering = vec3(scattering_u >> 21, (scattering_u << 11) >> 21, scattering_u % 1024) / vec3(2047.0, 2047.0, 1023.0);
scattering += params.base_scattering * params.base_density;
#ifdef MOLTENVK_USED
uint emission_u = emissive_only_map[lpos];
#else
uint emission_u = imageLoad(emissive_only_map, pos).x;
#endif
vec3 emission = vec3(emission_u >> 21, (emission_u << 11) >> 21, emission_u % 1024) / vec3(511.0, 511.0, 255.0);
emission += params.base_emission * params.base_density;
@ -673,10 +702,16 @@ void main() {
final_density = mix(final_density, reprojected_density, reproject_amount);
imageStore(density_map, pos, final_density);
#ifdef MOLTENVK_USED
density_only_map[lpos] = 0;
light_only_map[lpos] = 0;
emissive_only_map[lpos] = 0;
#else
imageStore(density_only_map, pos, uvec4(0));
imageStore(light_only_map, pos, uvec4(0));
imageStore(emissive_only_map, pos, uvec4(0));
#endif
#endif
#ifdef MODE_FOG