Skip to content

Commit

Permalink
Merge pull request #40272 from clayjohn/VULKAN-time-slicing
Browse files Browse the repository at this point in the history
Add incremental update mode to sky
  • Loading branch information
akien-mga authored Jul 11, 2020
2 parents d0cea29 + a54f93c commit 9678a41
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 32 deletions.
4 changes: 2 additions & 2 deletions doc/classes/RenderingServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3431,10 +3431,10 @@
</constant>
<constant name="VIEWPORT_DEBUG_DRAW_GI_BUFFER" value="17" enum="ViewportDebugDraw">
</constant>
<constant name="SKY_MODE_QUALITY" value="0" enum="SkyMode">
<constant name="SKY_MODE_QUALITY" value="1" enum="SkyMode">
Uses high quality importance sampling to process the radiance map. In general, this results in much higher quality than [constant Sky.PROCESS_MODE_REALTIME] but takes much longer to generate. This should not be used if you plan on changing the sky at runtime. If you are finding that the reflection is not blurry enough and is showing sparkles or fireflies, try increasing [member ProjectSettings.rendering/quality/reflections/ggx_samples].
</constant>
<constant name="SKY_MODE_REALTIME" value="1" enum="SkyMode">
<constant name="SKY_MODE_REALTIME" value="3" enum="SkyMode">
Uses the fast filtering algorithm to process the radiance map. In general this results in lower quality, but substantially faster run times.
[b]Note:[/b] The fast filtering algorithm is limited to 256x256 cubemaps, so [member Sky.radiance_size] must be set to [constant Sky.RADIANCE_SIZE_256].
</constant>
Expand Down
12 changes: 9 additions & 3 deletions doc/classes/Sky.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,17 @@
<constant name="RADIANCE_SIZE_MAX" value="7" enum="RadianceSize">
Represents the size of the [enum RadianceSize] enum.
</constant>
<constant name="PROCESS_MODE_QUALITY" value="0" enum="ProcessMode">
<constant name="PROCESS_MODE_AUTOMATIC" value="0" enum="ProcessMode">
Automatically selects the appropriate process mode based on your sky shader. If your shader uses [code]TIME[/code] or [code]POSITION[/code], this will use [constant PROCESS_MODE_REALTIME]. If your shader uses any of the [code]LIGHT_*[/code] variables or any custom uniforms, this uses [constant PROCESS_MODE_INCREMENTAL]. Otherwise, this defaults to [constant PROCESS_MODE_QUALITY].
</constant>
<constant name="PROCESS_MODE_QUALITY" value="1" enum="ProcessMode">
Uses high quality importance sampling to process the radiance map. In general, this results in much higher quality than [constant PROCESS_MODE_REALTIME] but takes much longer to generate. This should not be used if you plan on changing the sky at runtime. If you are finding that the reflection is not blurry enough and is showing sparkles or fireflies, try increasing [member ProjectSettings.rendering/quality/reflections/ggx_samples].
</constant>
<constant name="PROCESS_MODE_REALTIME" value="1" enum="ProcessMode">
Uses the fast filtering algorithm to process the radiance map. In general this results in lower quality, but substantially faster run times.
<constant name="PROCESS_MODE_INCREMENTAL" value="2" enum="ProcessMode">
Uses the same high quality importance sampling to process the radiance map as [constant PROCESS_MODE_QUALITY], but updates over several frames. The number of frames is determined by [member ProjectSettings.rendering/quality/reflections/roughness_layers]. Use this when you need highest quality radiance maps, but have a sky that updates slowly.
</constant>
<constant name="PROCESS_MODE_REALTIME" value="3" enum="ProcessMode">
Uses the fast filtering algorithm to process the radiance map. In general this results in lower quality, but substantially faster run times. If you need better quality, but still need to update the sky every frame, consider turning on [member ProjectSettings.rendering/quality/reflections/fast_filter_high_quality].
[b]Note:[/b] The fast filtering algorithm is limited to 256x256 cubemaps, so [member radiance_size] must be set to [constant RADIANCE_SIZE_256].
</constant>
</constants>
Expand Down
6 changes: 4 additions & 2 deletions scene/resources/sky.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ void Sky::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_material"), &Sky::get_material);

ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "sky_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,PanoramaSkyMaterial,ProceduralSkyMaterial,PhysicalSkyMaterial"), "set_material", "get_material");
ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Automatic,HighQuality,HighQualityIncremental,RealTime"), "set_process_mode", "get_process_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "radiance_size", PROPERTY_HINT_ENUM, "32,64,128,256,512,1024,2048"), "set_radiance_size", "get_radiance_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "HighQuality,RealTime"), "set_process_mode", "get_process_mode");

BIND_ENUM_CONSTANT(RADIANCE_SIZE_32);
BIND_ENUM_CONSTANT(RADIANCE_SIZE_64);
Expand All @@ -95,12 +95,14 @@ void Sky::_bind_methods() {
BIND_ENUM_CONSTANT(RADIANCE_SIZE_2048);
BIND_ENUM_CONSTANT(RADIANCE_SIZE_MAX);

BIND_ENUM_CONSTANT(PROCESS_MODE_AUTOMATIC);
BIND_ENUM_CONSTANT(PROCESS_MODE_QUALITY);
BIND_ENUM_CONSTANT(PROCESS_MODE_INCREMENTAL);
BIND_ENUM_CONSTANT(PROCESS_MODE_REALTIME);
}

Sky::Sky() {
mode = PROCESS_MODE_QUALITY;
mode = PROCESS_MODE_AUTOMATIC;
radiance_size = RADIANCE_SIZE_256;
sky = RS::get_singleton()->sky_create();
}
Expand Down
2 changes: 2 additions & 0 deletions scene/resources/sky.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ class Sky : public Resource {
};

enum ProcessMode {
PROCESS_MODE_AUTOMATIC,
PROCESS_MODE_QUALITY,
PROCESS_MODE_INCREMENTAL,
PROCESS_MODE_REALTIME
};

Expand Down
83 changes: 60 additions & 23 deletions servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,16 +181,14 @@ void RasterizerSceneRD::_create_reflection_importance_sample(ReflectionData &rd,
}
}

void RasterizerSceneRD::_update_reflection_mipmaps(ReflectionData &rd) {
if (sky_use_cubemap_array) {
for (int i = 0; i < rd.layers.size(); i++) {
for (int j = 0; j < rd.layers[i].mipmaps.size() - 1; j++) {
for (int k = 0; k < 6; k++) {
RID view = rd.layers[i].mipmaps[j].views[k];
RID texture = rd.layers[i].mipmaps[j + 1].views[k];
Size2i size = rd.layers[i].mipmaps[j + 1].size;
storage->get_effects()->make_mipmap(view, texture, size);
}
void RasterizerSceneRD::_update_reflection_mipmaps(ReflectionData &rd, int p_start, int p_end) {
for (int i = p_start; i < p_end; i++) {
for (int j = 0; j < rd.layers[i].mipmaps.size() - 1; j++) {
for (int k = 0; k < 6; k++) {
RID view = rd.layers[i].mipmaps[j].views[k];
RID texture = rd.layers[i].mipmaps[j + 1].views[k];
Size2i size = rd.layers[i].mipmaps[j + 1].size;
storage->get_effects()->make_mipmap(view, texture, size);
}
}
}
Expand Down Expand Up @@ -1924,6 +1922,7 @@ void RasterizerSceneRD::_update_dirty_skys() {
}

sky->reflection.dirty = true;
sky->processing_layer = 0;

Sky *next = sky->dirty_list;
sky->dirty_list = nullptr;
Expand Down Expand Up @@ -2276,8 +2275,32 @@ void RasterizerSceneRD::_update_sky(RID p_environment, const CameraMatrix &p_pro

float multiplier = environment_get_bg_energy(p_environment);

bool update_single_frame = sky->mode == RS::SKY_MODE_REALTIME || sky->mode == RS::SKY_MODE_QUALITY;
RS::SkyMode sky_mode = sky->mode;

if (sky_mode == RS::SKY_MODE_AUTOMATIC) {
if (shader_data->uses_time || shader_data->uses_position) {
update_single_frame = true;
sky_mode = RS::SKY_MODE_REALTIME;
} else if (shader_data->uses_light || shader_data->ubo_size > 0) {
update_single_frame = false;
sky_mode = RS::SKY_MODE_INCREMENTAL;
} else {
update_single_frame = true;
sky_mode = RS::SKY_MODE_QUALITY;
}
}

if (sky->processing_layer == 0 && sky_mode == RS::SKY_MODE_INCREMENTAL) {
// On the first frame after creating sky, rebuild in single frame
update_single_frame = true;
sky_mode = RS::SKY_MODE_QUALITY;
}

int max_processing_layer = sky_use_cubemap_array ? sky->reflection.layers.size() : sky->reflection.layers[0].mipmaps.size();

// Update radiance cubemap
if (sky->reflection.dirty) {
if (sky->reflection.dirty && (sky->processing_layer >= max_processing_layer || update_single_frame)) {
static const Vector3 view_normals[6] = {
Vector3(+1, 0, 0),
Vector3(-1, 0, 0),
Expand Down Expand Up @@ -2349,27 +2372,41 @@ void RasterizerSceneRD::_update_sky(RID p_environment, const CameraMatrix &p_pro
storage->get_effects()->render_sky(cubemap_draw_list, time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], sky_scene_state.sampler_uniform_set, sky_scene_state.light_uniform_set, pipeline, material->uniform_set, texture_uniform_set, cm, local_view.basis, multiplier, p_transform.origin);
RD::get_singleton()->draw_list_end();
}
if (sky_use_cubemap_array) {
if (sky->mode == RS::SKY_MODE_QUALITY) {
for (int i = 1; i < sky->reflection.layers.size(); i++) {
_create_reflection_importance_sample(sky->reflection, sky_use_cubemap_array, 10, i);
}
} else {
_create_reflection_fast_filter(sky->reflection, sky_use_cubemap_array);
}

_update_reflection_mipmaps(sky->reflection);
if (sky_mode == RS::SKY_MODE_REALTIME) {
_create_reflection_fast_filter(sky->reflection, sky_use_cubemap_array);
if (sky_use_cubemap_array) {
_update_reflection_mipmaps(sky->reflection, 0, sky->reflection.layers.size());
}
} else {
if (sky->mode == RS::SKY_MODE_QUALITY) {
for (int i = 1; i < sky->reflection.layers[0].mipmaps.size(); i++) {
if (update_single_frame) {
for (int i = 1; i < max_processing_layer; i++) {
_create_reflection_importance_sample(sky->reflection, sky_use_cubemap_array, 10, i);
}
if (sky_use_cubemap_array) {
_update_reflection_mipmaps(sky->reflection, 0, sky->reflection.layers.size());
}
} else {
_create_reflection_fast_filter(sky->reflection, sky_use_cubemap_array);
if (sky_use_cubemap_array) {
// Multi-Frame so just update the first array level
_update_reflection_mipmaps(sky->reflection, 0, 1);
}
}
sky->processing_layer = 1;
}

sky->reflection.dirty = false;

} else {
if (sky_mode == RS::SKY_MODE_INCREMENTAL && sky->processing_layer < max_processing_layer) {
_create_reflection_importance_sample(sky->reflection, sky_use_cubemap_array, 10, sky->processing_layer);

if (sky_use_cubemap_array) {
_update_reflection_mipmaps(sky->reflection, sky->processing_layer, sky->processing_layer + 1);
}

sky->processing_layer++;
}
}
}

Expand Down
5 changes: 3 additions & 2 deletions servers/rendering/rasterizer_rd/rasterizer_scene_rd.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ class RasterizerSceneRD : public RasterizerScene {
void _update_reflection_data(ReflectionData &rd, int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality);
void _create_reflection_fast_filter(ReflectionData &rd, bool p_use_arrays);
void _create_reflection_importance_sample(ReflectionData &rd, bool p_use_arrays, int p_cube_side, int p_base_layer);
void _update_reflection_mipmaps(ReflectionData &rd);
void _update_reflection_mipmaps(ReflectionData &rd, int p_start, int p_end);

/* Sky shader */

Expand Down Expand Up @@ -261,10 +261,11 @@ class RasterizerSceneRD : public RasterizerScene {

int radiance_size = 256;

RS::SkyMode mode = RS::SKY_MODE_QUALITY;
RS::SkyMode mode = RS::SKY_MODE_AUTOMATIC;

ReflectionData reflection;
bool dirty = false;
int processing_layer = 0;
Sky *dirty_list = nullptr;

//State to track when radiance cubemap needs updating
Expand Down
2 changes: 2 additions & 0 deletions servers/rendering_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,9 @@ class RenderingServer : public Object {
/* SKY API */

enum SkyMode {
SKY_MODE_AUTOMATIC,
SKY_MODE_QUALITY,
SKY_MODE_INCREMENTAL,
SKY_MODE_REALTIME
};

Expand Down

0 comments on commit 9678a41

Please sign in to comment.