Skip to content

Commit

Permalink
Merge pull request #76437 from RandomShaper/fix_vol_fog_voxel_gi
Browse files Browse the repository at this point in the history
Fix voxel GI issues
  • Loading branch information
akien-mga committed Apr 27, 2023
2 parents cedd337 + 09aa1bb commit 359b494
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 30 deletions.
8 changes: 8 additions & 0 deletions doc/classes/RenderingDevice.xml
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,14 @@
<description>
</description>
</method>
<method name="sampler_is_format_supported_for_filter" qualifiers="const">
<return type="bool" />
<param index="0" name="format" type="int" enum="RenderingDevice.DataFormat" />
<param index="1" name="sampler_filter" type="int" enum="RenderingDevice.SamplerFilter" />
<description>
Returns [code]true[/code] if implementation supports using a texture of [param format] with the given [param sampler_filter].
</description>
</method>
<method name="screen_get_framebuffer_format" qualifiers="const">
<return type="int" />
<description>
Expand Down
12 changes: 12 additions & 0 deletions drivers/vulkan/rendering_device_vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4305,6 +4305,18 @@ RID RenderingDeviceVulkan::sampler_create(const SamplerState &p_state) {
return id;
}

bool RenderingDeviceVulkan::sampler_is_format_supported_for_filter(DataFormat p_format, SamplerFilter p_sampler_filter) const {
ERR_FAIL_INDEX_V(p_format, DATA_FORMAT_MAX, false);

_THREAD_SAFE_METHOD_

// Validate that this image is supported for the intended filtering.
VkFormatProperties properties;
vkGetPhysicalDeviceFormatProperties(context->get_physical_device(), vulkan_formats[p_format], &properties);

return p_sampler_filter == RD::SAMPLER_FILTER_NEAREST || (p_sampler_filter == RD::SAMPLER_FILTER_LINEAR && (properties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT));
}

/**********************/
/**** VERTEX ARRAY ****/
/**********************/
Expand Down
1 change: 1 addition & 0 deletions drivers/vulkan/rendering_device_vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -1084,6 +1084,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
/*****************/

virtual RID sampler_create(const SamplerState &p_state);
virtual bool sampler_is_format_supported_for_filter(DataFormat p_format, SamplerFilter p_sampler_filter) const;

/**********************/
/**** VERTEX ARRAY ****/
Expand Down
45 changes: 27 additions & 18 deletions servers/rendering/renderer_rd/environment/fog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -463,15 +463,19 @@ Fog::VolumetricFog::~VolumetricFog() {
if (fog_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(fog_uniform_set)) {
RD::get_singleton()->free(fog_uniform_set);
}
if (process_uniform_set_density.is_valid() && RD::get_singleton()->uniform_set_is_valid(process_uniform_set_density)) {
RD::get_singleton()->free(process_uniform_set_density);
}
if (process_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(process_uniform_set)) {
RD::get_singleton()->free(process_uniform_set);
}
if (process_uniform_set2.is_valid() && RD::get_singleton()->uniform_set_is_valid(process_uniform_set2)) {
RD::get_singleton()->free(process_uniform_set2);

// At this point, due to cascade deletions, the sets may no longer be valid, but still they must work as a group.
gi_dependent_sets.valid = RD::get_singleton()->uniform_set_is_valid(gi_dependent_sets.process_uniform_set_density);
#ifdef DEV_ENABLED
gi_dependent_sets.assert_actual_validity();
#endif
if (gi_dependent_sets.valid) {
RD::get_singleton()->free(gi_dependent_sets.copy_uniform_set);
RD::get_singleton()->free(gi_dependent_sets.process_uniform_set_density);
RD::get_singleton()->free(gi_dependent_sets.process_uniform_set);
RD::get_singleton()->free(gi_dependent_sets.process_uniform_set2);
}

if (sdfgi_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sdfgi_uniform_set)) {
RD::get_singleton()->free(sdfgi_uniform_set);
}
Expand Down Expand Up @@ -713,7 +717,10 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
RD::get_singleton()->compute_list_end();
}

if (fog->process_uniform_set_density.is_null() || !RD::get_singleton()->uniform_set_is_valid(fog->process_uniform_set_density)) {
#ifdef DEV_ENABLED
fog->gi_dependent_sets.assert_actual_validity();
#endif
if (!fog->gi_dependent_sets.valid) {
//re create uniform set if needed
Vector<RD::Uniform> uniforms;
Vector<RD::Uniform> copy_uniforms;
Expand Down Expand Up @@ -910,21 +917,23 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
uniforms.push_back(u);
}

fog->copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0);
fog->gi_dependent_sets.copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0);

fog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0);
fog->gi_dependent_sets.process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0);

RID aux7 = uniforms.write[7].get_id(0);
RID aux8 = uniforms.write[8].get_id(0);

uniforms.write[7].set_id(0, aux8);
uniforms.write[8].set_id(0, aux7);

fog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0);
fog->gi_dependent_sets.process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0);

uniforms.remove_at(8);
uniforms.write[7].set_id(0, aux7);
fog->process_uniform_set_density = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0);
fog->gi_dependent_sets.process_uniform_set_density = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0);

fog->gi_dependent_sets.valid = true;
}

bool using_sdfgi = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_gi_inject(p_settings.env) > 0.0001 && RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_enabled(p_settings.env) && (p_settings.sdfgi.is_valid());
Expand Down Expand Up @@ -1067,7 +1076,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P

RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[using_sdfgi ? VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI : VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY]);

RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set_density, 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->gi_dependent_sets.process_uniform_set_density, 0);

if (using_sdfgi) {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->sdfgi_uniform_set, 1);
Expand All @@ -1078,7 +1087,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
// Copy fog to history buffer
if (RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env)) {
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->copy_uniform_set, 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->gi_dependent_sets.copy_uniform_set, 0);
RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth);
RD::get_singleton()->compute_list_add_barrier(compute_list);
}
Expand All @@ -1090,7 +1099,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
RENDER_TIMESTAMP("Filter Fog");

RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set, 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->gi_dependent_sets.process_uniform_set, 0);
RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth);

RD::get_singleton()->compute_list_end();
Expand All @@ -1101,7 +1110,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P

compute_list = RD::get_singleton()->compute_list_begin();
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set2, 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->gi_dependent_sets.process_uniform_set2, 0);
RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth);

RD::get_singleton()->compute_list_add_barrier(compute_list);
Expand All @@ -1112,7 +1121,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
RD::get_singleton()->draw_command_begin_label("Integrate Fog");

RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set, 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->gi_dependent_sets.process_uniform_set, 0);
RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, 1);

RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_RASTER);
Expand Down
23 changes: 19 additions & 4 deletions servers/rendering/renderer_rd/environment/fog.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,10 +301,25 @@ class Fog : public RendererFog {
RID emissive_map;

RID fog_uniform_set;
RID copy_uniform_set;
RID process_uniform_set_density;
RID process_uniform_set;
RID process_uniform_set2;

struct {
bool valid = false;
RID copy_uniform_set;
RID process_uniform_set_density;
RID process_uniform_set;
RID process_uniform_set2;

#ifdef DEV_ENABLED
void assert_actual_validity() {
// It's all-or-nothing, or something else has changed that requires dev attention.
DEV_ASSERT(valid == RD::get_singleton()->uniform_set_is_valid(copy_uniform_set));
DEV_ASSERT(valid == RD::get_singleton()->uniform_set_is_valid(process_uniform_set_density));
DEV_ASSERT(valid == RD::get_singleton()->uniform_set_is_valid(process_uniform_set));
DEV_ASSERT(valid == RD::get_singleton()->uniform_set_is_valid(process_uniform_set2));
}
#endif
} gi_dependent_sets;

RID sdfgi_uniform_set;
RID sky_uniform_set;

Expand Down
20 changes: 12 additions & 8 deletions servers/rendering/renderer_rd/environment/gi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3493,6 +3493,9 @@ void GI::init(SkyRD *p_sky) {
if (RendererSceneRenderRD::get_singleton()->is_vrs_supported()) {
defines += "\n#define USE_VRS\n";
}
if (!RD::get_singleton()->sampler_is_format_supported_for_filter(RD::DATA_FORMAT_R8G8_UINT, RD::SAMPLER_FILTER_LINEAR)) {
defines += "\n#define SAMPLE_VOXEL_GI_NEAREST\n";
}

Vector<String> gi_modes;

Expand Down Expand Up @@ -3695,14 +3698,16 @@ void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, Ref<RenderSceneBu
if (p_render_buffers->has_custom_data(RB_SCOPE_FOG)) {
Ref<Fog::VolumetricFog> fog = p_render_buffers->get_custom_data(RB_SCOPE_FOG);

if (RD::get_singleton()->uniform_set_is_valid(fog->fog_uniform_set)) {
RD::get_singleton()->free(fog->fog_uniform_set);
RD::get_singleton()->free(fog->process_uniform_set);
RD::get_singleton()->free(fog->process_uniform_set2);
#ifdef DEV_ENABLED
fog->gi_dependent_sets.assert_actual_validity();
#endif
if (fog->gi_dependent_sets.valid) {
RD::get_singleton()->free(fog->gi_dependent_sets.copy_uniform_set);
RD::get_singleton()->free(fog->gi_dependent_sets.process_uniform_set_density);
RD::get_singleton()->free(fog->gi_dependent_sets.process_uniform_set);
RD::get_singleton()->free(fog->gi_dependent_sets.process_uniform_set2);
fog->gi_dependent_sets.valid = false;
}
fog->fog_uniform_set = RID();
fog->process_uniform_set = RID();
fog->process_uniform_set2 = RID();
}
}

Expand Down Expand Up @@ -3929,7 +3934,6 @@ void GI::process_gi(Ref<RenderSceneBuffersRD> p_render_buffers, const RID *p_nor
u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
}

{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
Expand Down
8 changes: 8 additions & 0 deletions servers/rendering/renderer_rd/shaders/environment/gi.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

#VERSION_DEFINES

#ifdef SAMPLE_VOXEL_GI_NEAREST
#extension GL_EXT_samplerless_texture_functions : enable
#endif

layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;

#define M_PI 3.141592
Expand Down Expand Up @@ -625,7 +629,11 @@ void process_gi(ivec2 pos, vec3 vertex, inout vec4 ambient_light, inout vec4 ref

#ifdef USE_VOXEL_GI_INSTANCES
{
#ifdef SAMPLE_VOXEL_GI_NEAREST
uvec2 voxel_gi_tex = texelFetch(voxel_gi_buffer, pos, 0).rg;
#else
uvec2 voxel_gi_tex = texelFetch(usampler2D(voxel_gi_buffer, linear_sampler), pos, 0).rg;
#endif
roughness *= roughness;
//find arbitrary tangent and bitangent, then build a matrix
vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
Expand Down
1 change: 1 addition & 0 deletions servers/rendering/rendering_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,7 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("framebuffer_is_valid", "framebuffer"), &RenderingDevice::framebuffer_is_valid);

ClassDB::bind_method(D_METHOD("sampler_create", "state"), &RenderingDevice::_sampler_create);
ClassDB::bind_method(D_METHOD("sampler_is_format_supported_for_filter", "format", "sampler_filter"), &RenderingDevice::sampler_is_format_supported_for_filter);

ClassDB::bind_method(D_METHOD("vertex_buffer_create", "size_bytes", "data", "use_as_storage"), &RenderingDevice::vertex_buffer_create, DEFVAL(Vector<uint8_t>()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("vertex_format_create", "vertex_descriptions"), &RenderingDevice::_vertex_format_create);
Expand Down
1 change: 1 addition & 0 deletions servers/rendering/rendering_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,7 @@ class RenderingDevice : public Object {
};

virtual RID sampler_create(const SamplerState &p_state) = 0;
virtual bool sampler_is_format_supported_for_filter(DataFormat p_format, SamplerFilter p_sampler_filter) const = 0;

/**********************/
/**** VERTEX ARRAY ****/
Expand Down

0 comments on commit 359b494

Please sign in to comment.