diff options
Diffstat (limited to 'servers/rendering/renderer_rd/renderer_scene_render_rd.cpp')
| -rw-r--r-- | servers/rendering/renderer_rd/renderer_scene_render_rd.cpp | 478 |
1 files changed, 320 insertions, 158 deletions
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 46057bddab..fd797b1cab 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -567,6 +567,8 @@ int RendererSceneRenderRD::reflection_atlas_get_size(RID p_ref_atlas) const { RID RendererSceneRenderRD::reflection_probe_instance_create(RID p_probe) { ReflectionProbeInstance rpi; rpi.probe = p_probe; + rpi.forward_id = _allocate_forward_id(FORWARD_ID_TYPE_REFLECTION_PROBE); + return reflection_probe_instance_owner.make_rid(rpi); } @@ -627,6 +629,8 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); ERR_FAIL_COND_V(!rpi, false); + RD::get_singleton()->draw_command_begin_label("Reflection probe render"); + if (storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->size != 256) { WARN_PRINT("ReflectionProbes set to UPDATE_ALWAYS must have an atlas size of 256. Please update the atlas size in the ProjectSettings."); reflection_atlas_set_size(p_reflection_atlas, 256, atlas->count); @@ -654,12 +658,12 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc //reflection atlas was unused, create: RD::TextureFormat tf; tf.array_layers = 6 * atlas->count; - tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.format = _render_buffers_get_color_format(); tf.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY; tf.mipmaps = mipmaps; tf.width = atlas->size; tf.height = atlas->size; - tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | (_render_buffers_can_be_storage() ? RD::TEXTURE_USAGE_STORAGE_BIT : 0); atlas->reflection = RD::get_singleton()->texture_create(tf, RD::TextureView()); } @@ -673,12 +677,9 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc } atlas->reflections.resize(atlas->count); for (int i = 0; i < atlas->count; i++) { - atlas->reflections.write[i].data.update_reflection_data(atlas->size, mipmaps, false, atlas->reflection, i * 6, storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS, sky.roughness_layers); + atlas->reflections.write[i].data.update_reflection_data(storage, atlas->size, mipmaps, false, atlas->reflection, i * 6, storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS, sky.roughness_layers, _render_buffers_get_color_format()); for (int j = 0; j < 6; j++) { - Vector<RID> fb; - fb.push_back(atlas->reflections.write[i].data.layers[0].mipmaps[0].views[j]); - fb.push_back(atlas->depth_buffer); - atlas->reflections.write[i].fbs[j] = RD::get_singleton()->framebuffer_create(fb); + atlas->reflections.write[i].fbs[j] = reflection_probe_create_framebuffer(atlas->reflections.write[i].data.layers[0].mipmaps[0].views[j], atlas->depth_buffer); } } @@ -709,15 +710,28 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc } } + if (rpi->atlas_index != -1) { // should we fail if this is still -1 ? + atlas->reflections.write[rpi->atlas_index].owner = p_instance; + } + rpi->atlas = p_reflection_atlas; rpi->rendering = true; rpi->dirty = false; rpi->processing_layer = 1; rpi->processing_side = 0; + RD::get_singleton()->draw_command_end_label(); + return true; } +RID RendererSceneRenderRD::reflection_probe_create_framebuffer(RID p_color, RID p_depth) { + Vector<RID> fb; + fb.push_back(p_color); + fb.push_back(p_depth); + return RD::get_singleton()->framebuffer_create(fb); +} + bool RendererSceneRenderRD::reflection_probe_instance_postprocess_step(RID p_instance) { ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); ERR_FAIL_COND_V(!rpi, false); @@ -1229,6 +1243,9 @@ RID RendererSceneRenderRD::light_instance_create(RID p_light) { light_instance->self = li; light_instance->light = p_light; light_instance->light_type = storage->light_get_type(p_light); + if (light_instance->light_type != RS::LIGHT_DIRECTIONAL) { + light_instance->forward_id = _allocate_forward_id(light_instance->light_type == RS::LIGHT_OMNI ? FORWARD_ID_TYPE_OMNI_LIGHT : FORWARD_ID_TYPE_SPOT_LIGHT); + } return li; } @@ -1302,6 +1319,7 @@ RendererSceneRenderRD::ShadowCubemap *RendererSceneRenderRD::_get_shadow_cubemap RID RendererSceneRenderRD::decal_instance_create(RID p_decal) { DecalInstance di; di.decal = p_decal; + di.forward_id = _allocate_forward_id(FORWARD_ID_TYPE_DECAL); return decal_instance_owner.make_rid(di); } @@ -1373,12 +1391,20 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) { uint32_t mipmaps_required = Image::get_image_required_mipmaps(rb->width, rb->height, Image::FORMAT_RGBAH); + // TODO make sure texture_create_shared_from_slice works for multiview + RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.format = _render_buffers_get_color_format(); // RD::DATA_FORMAT_R16G16B16A16_SFLOAT; tf.width = rb->width; tf.height = rb->height; - tf.texture_type = RD::TEXTURE_TYPE_2D; - tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + tf.texture_type = rb->view_count > 1 ? RD::TEXTURE_TYPE_2D_ARRAY : RD::TEXTURE_TYPE_2D; + tf.array_layers = rb->view_count; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + if (_render_buffers_can_be_storage()) { + tf.usage_bits += RD::TEXTURE_USAGE_STORAGE_BIT; + } else { + tf.usage_bits += RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + } tf.mipmaps = mipmaps_required; rb->blur[0].texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); @@ -1398,11 +1424,40 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) { mm.width = base_width; mm.height = base_height; + if (!_render_buffers_can_be_storage()) { + Vector<RID> fb; + fb.push_back(mm.texture); + + mm.fb = RD::get_singleton()->framebuffer_create(fb); + } + + if (!_render_buffers_can_be_storage()) { + // and half texture, this is an intermediate result so just allocate a texture, is this good enough? + tf.width = MAX(1, base_width >> 1); + tf.height = base_height; + tf.mipmaps = 1; // 1 or 0? + + mm.half_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + Vector<RID> half_fb; + half_fb.push_back(mm.half_texture); + mm.half_fb = RD::get_singleton()->framebuffer_create(half_fb); + } + rb->blur[0].mipmaps.push_back(mm); if (i > 0) { mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[1].texture, 0, i - 1); + if (!_render_buffers_can_be_storage()) { + Vector<RID> fb; + fb.push_back(mm.texture); + + mm.fb = RD::get_singleton()->framebuffer_create(fb); + + // We can re-use the half texture here as it is an intermediate result + } + rb->blur[1].mipmaps.push_back(mm); } @@ -1425,26 +1480,48 @@ void RendererSceneRenderRD::_allocate_luminance_textures(RenderBuffers *rb) { tf.format = RD::DATA_FORMAT_R32_SFLOAT; tf.width = w; tf.height = h; - tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT; bool final = w == 1 && h == 1; - if (final) { - tf.usage_bits |= RD::TEXTURE_USAGE_SAMPLING_BIT; + if (_render_buffers_can_be_storage()) { + tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT; + if (final) { + tf.usage_bits |= RD::TEXTURE_USAGE_SAMPLING_BIT; + } + } else { + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; } RID texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); rb->luminance.reduce.push_back(texture); + if (!_render_buffers_can_be_storage()) { + Vector<RID> fb; + fb.push_back(texture); + + rb->luminance.fb.push_back(RD::get_singleton()->framebuffer_create(fb)); + } if (final) { rb->luminance.current = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + if (!_render_buffers_can_be_storage()) { + Vector<RID> fb; + fb.push_back(rb->luminance.current); + + rb->luminance.current_fb = RD::get_singleton()->framebuffer_create(fb); + } break; } } } void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) { + if (rb->texture_fb.is_valid()) { + RD::get_singleton()->free(rb->texture_fb); + rb->texture_fb = RID(); + } + if (rb->texture.is_valid()) { RD::get_singleton()->free(rb->texture); rb->texture = RID(); @@ -1456,19 +1533,43 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) { } for (int i = 0; i < 2; i++) { + for (int m = 0; m < rb->blur[i].mipmaps.size(); m++) { + // do we free the texture slice here? or is it enough to free the main texture? + + // do free the mobile extra stuff + if (rb->blur[i].mipmaps[m].fb.is_valid()) { + RD::get_singleton()->free(rb->blur[i].mipmaps[m].fb); + } + if (rb->blur[i].mipmaps[m].half_fb.is_valid()) { + RD::get_singleton()->free(rb->blur[i].mipmaps[m].half_fb); + } + if (rb->blur[i].mipmaps[m].half_texture.is_valid()) { + RD::get_singleton()->free(rb->blur[i].mipmaps[m].half_texture); + } + } + rb->blur[i].mipmaps.clear(); + if (rb->blur[i].texture.is_valid()) { RD::get_singleton()->free(rb->blur[i].texture); rb->blur[i].texture = RID(); - rb->blur[i].mipmaps.clear(); } } + for (int i = 0; i < rb->luminance.fb.size(); i++) { + RD::get_singleton()->free(rb->luminance.fb[i]); + } + rb->luminance.fb.clear(); + for (int i = 0; i < rb->luminance.reduce.size(); i++) { RD::get_singleton()->free(rb->luminance.reduce[i]); } - rb->luminance.reduce.clear(); + if (rb->luminance.current_fb.is_valid()) { + RD::get_singleton()->free(rb->luminance.current_fb); + rb->luminance.current_fb = RID(); + } + if (rb->luminance.current.is_valid()) { RD::get_singleton()->free(rb->luminance.current); rb->luminance.current = RID(); @@ -1740,17 +1841,27 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende CameraEffects *camfx = camera_effects_owner.getornull(p_render_data->camera_effects); bool can_use_effects = rb->width >= 8 && rb->height >= 8; + bool can_use_storage = _render_buffers_can_be_storage(); + + // @TODO IMPLEMENT MULTIVIEW, all effects need to support stereo buffers or effects are only applied to the left eye if (can_use_effects && camfx && (camfx->dof_blur_near_enabled || camfx->dof_blur_far_enabled) && camfx->dof_blur_amount > 0.0) { + RD::get_singleton()->draw_command_begin_label("DOF"); if (rb->blur[0].texture.is_null()) { _allocate_blur_textures(rb); } - float bokeh_size = camfx->dof_blur_amount * 64.0; - storage->get_effects()->bokeh_dof(rb->texture, rb->depth_texture, Size2i(rb->width, rb->height), rb->blur[0].mipmaps[0].texture, rb->blur[1].mipmaps[0].texture, rb->blur[0].mipmaps[1].texture, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal); + if (can_use_storage) { + float bokeh_size = camfx->dof_blur_amount * 64.0; + storage->get_effects()->bokeh_dof(rb->texture, rb->depth_texture, Size2i(rb->width, rb->height), rb->blur[0].mipmaps[0].texture, rb->blur[1].mipmaps[0].texture, rb->blur[0].mipmaps[1].texture, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal); + } else { + storage->get_effects()->blur_dof_raster(rb->texture, rb->depth_texture, Size2i(rb->width, rb->height), rb->texture_fb, rb->blur[0].mipmaps[0].texture, rb->blur[0].mipmaps[0].fb, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, camfx->dof_blur_amount, dof_blur_quality, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal); + } + RD::get_singleton()->draw_command_end_label(); } if (can_use_effects && env && env->auto_exposure) { + RD::get_singleton()->draw_command_begin_label("Auto exposure"); if (rb->luminance.current.is_null()) { _allocate_luminance_textures(rb); } @@ -1759,16 +1870,26 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende rb->auto_exposure_version = env->auto_exposure_version; double step = env->auto_exp_speed * time_step; - storage->get_effects()->luminance_reduction(rb->texture, Size2i(rb->width, rb->height), rb->luminance.reduce, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate); - + if (can_use_storage) { + storage->get_effects()->luminance_reduction(rb->texture, Size2i(rb->width, rb->height), rb->luminance.reduce, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate); + } else { + storage->get_effects()->luminance_reduction_raster(rb->texture, Size2i(rb->width, rb->height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate); + } //swap final reduce with prev luminance SWAP(rb->luminance.current, rb->luminance.reduce.write[rb->luminance.reduce.size() - 1]); + if (!can_use_storage) { + SWAP(rb->luminance.current_fb, rb->luminance.fb.write[rb->luminance.fb.size() - 1]); + } + RenderingServerDefault::redraw_request(); //redraw all the time if auto exposure rendering is on + RD::get_singleton()->draw_command_end_label(); } int max_glow_level = -1; if (can_use_effects && env && env->glow_enabled) { + RD::get_singleton()->draw_command_begin_label("Gaussian Glow"); + /* see that blur textures are allocated */ if (rb->blur[1].texture.is_null()) { @@ -1794,14 +1915,26 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende if (env->auto_exposure && rb->luminance.current.is_valid()) { luminance_texture = rb->luminance.current; } - storage->get_effects()->gaussian_glow(rb->texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale); + if (can_use_storage) { + storage->get_effects()->gaussian_glow(rb->texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale); + } else { + storage->get_effects()->gaussian_glow_raster(rb->texture, rb->blur[1].mipmaps[i].half_fb, rb->blur[1].mipmaps[i].half_texture, rb->blur[1].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale); + } } else { - storage->get_effects()->gaussian_glow(rb->blur[1].mipmaps[i - 1].texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality); + if (can_use_storage) { + storage->get_effects()->gaussian_glow(rb->blur[1].mipmaps[i - 1].texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality); + } else { + storage->get_effects()->gaussian_glow_raster(rb->blur[1].mipmaps[i - 1].texture, rb->blur[1].mipmaps[i].half_fb, rb->blur[1].mipmaps[i].half_texture, rb->blur[1].mipmaps[i].fb, Vector2(1.0 / vp_w, 1.0 / vp_h), env->glow_strength, glow_high_quality); + } } } + + RD::get_singleton()->draw_command_end_label(); } { + RD::get_singleton()->draw_command_begin_label("Tonemap"); + //tonemap EffectsRD::TonemapSettings tonemap; @@ -1860,11 +1993,81 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende tonemap.view_count = p_render_data->view_count; storage->get_effects()->tonemapper(rb->texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap); + + RD::get_singleton()->draw_command_end_label(); } storage->render_target_disable_clear_request(rb->render_target); } +void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_framebuffer, const RenderDataRD *p_render_data) { + RD::get_singleton()->draw_command_begin_label("Post Process Subpass"); + + RenderBuffers *rb = render_buffers_owner.getornull(p_render_data->render_buffers); + ERR_FAIL_COND(!rb); + + RendererSceneEnvironmentRD *env = environment_owner.getornull(p_render_data->environment); + + bool can_use_effects = rb->width >= 8 && rb->height >= 8; + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_switch_to_next_pass(); + + EffectsRD::TonemapSettings tonemap; + + if (env) { + tonemap.tonemap_mode = env->tone_mapper; + tonemap.exposure = env->exposure; + tonemap.white = env->white; + } + + // We don't support glow or auto exposure here, if they are needed, don't use subpasses! + // The problem is that we need to use the result so far and process them before we can + // apply this to our results. + if (can_use_effects && env && env->glow_enabled) { + ERR_FAIL_MSG("Glow is not supported when using subpasses."); + } + if (can_use_effects && env && env->auto_exposure) { + ERR_FAIL_MSG("Glow is not supported when using subpasses."); + } + + tonemap.use_glow = false; + tonemap.glow_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + tonemap.use_auto_exposure = false; + tonemap.exposure_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + + tonemap.use_color_correction = false; + tonemap.use_1d_color_correction = false; + tonemap.color_correction_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + + if (can_use_effects && env) { + tonemap.use_bcs = env->adjustments_enabled; + tonemap.brightness = env->adjustments_brightness; + tonemap.contrast = env->adjustments_contrast; + tonemap.saturation = env->adjustments_saturation; + if (env->adjustments_enabled && env->color_correction.is_valid()) { + tonemap.use_color_correction = true; + tonemap.use_1d_color_correction = env->use_1d_color_correction; + tonemap.color_correction_texture = storage->texture_get_rd_texture(env->color_correction); + } + } + + tonemap.use_debanding = rb->use_debanding; + tonemap.texture_size = Vector2i(rb->width, rb->height); + + tonemap.view_count = p_render_data->view_count; + + storage->get_effects()->tonemapper(draw_list, p_source_texture, RD::get_singleton()->framebuffer_get_format(p_framebuffer), tonemap); + + RD::get_singleton()->draw_command_end_label(); +} + +void RendererSceneRenderRD::_disable_clear_request(const RenderDataRD *p_render_data) { + RenderBuffers *rb = render_buffers_owner.getornull(p_render_data->render_buffers); + ERR_FAIL_COND(!rb); + + storage->render_target_disable_clear_request(rb->render_target); +} + void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) { EffectsRD *effects = storage->get_effects(); @@ -2114,8 +2317,16 @@ float RendererSceneRenderRD::render_buffers_get_volumetric_fog_detail_spread(RID return rb->volumetric_fog->spread; } +RD::DataFormat RendererSceneRenderRD::_render_buffers_get_color_format() { + return RD::DATA_FORMAT_R16G16B16A16_SFLOAT; +} + +bool RendererSceneRenderRD::_render_buffers_can_be_storage() { + return true; +} + void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) { - ERR_FAIL_COND_MSG(p_view_count == 0, "Must have atleast 1 view"); + ERR_FAIL_COND_MSG(p_view_count == 0, "Must have at least 1 view"); RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); rb->width = p_width; @@ -2140,16 +2351,15 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p if (rb->view_count > 1) { tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; } - tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.format = _render_buffers_get_color_format(); tf.width = rb->width; tf.height = rb->height; tf.array_layers = rb->view_count; // create a layer for every view - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | (_render_buffers_can_be_storage() ? RD::TEXTURE_USAGE_STORAGE_BIT : 0) | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) { - tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - } else { - tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; } + tf.usage_bits |= RD::TEXTURE_USAGE_INPUT_ATTACHMENT_BIT; // only needed when using subpasses in the mobile renderer rb->texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); } @@ -2179,7 +2389,16 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p rb->depth_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); } - rb->data->configure(rb->texture, rb->depth_texture, p_width, p_height, p_msaa, p_view_count); + if (!_render_buffers_can_be_storage()) { + // ONLY USED ON MOBILE RENDERER, ONLY USED FOR POST EFFECTS! + Vector<RID> fb; + fb.push_back(rb->texture); + + rb->texture_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, rb->view_count); + } + + RID target_texture = storage->render_target_get_rd_texture(rb->render_target); + rb->data->configure(rb->texture, rb->depth_texture, target_texture, p_width, p_height, p_msaa, p_view_count); if (is_clustered_enabled()) { rb->cluster_builder->setup(Size2i(p_width, p_height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->texture); @@ -2241,6 +2460,8 @@ void RendererSceneRenderRD::shadows_quality_set(RS::ShadowQuality p_quality) { get_vogel_disk(penumbra_shadow_kernel, penumbra_shadow_samples); get_vogel_disk(soft_shadow_kernel, soft_shadow_samples); } + + _update_shader_quality_settings(); } void RendererSceneRenderRD::directional_shadow_quality_set(RS::ShadowQuality p_quality) { @@ -2281,6 +2502,23 @@ void RendererSceneRenderRD::directional_shadow_quality_set(RS::ShadowQuality p_q get_vogel_disk(directional_penumbra_shadow_kernel, directional_penumbra_shadow_samples); get_vogel_disk(directional_soft_shadow_kernel, directional_soft_shadow_samples); } + + _update_shader_quality_settings(); +} + +void RendererSceneRenderRD::decals_set_filter(RenderingServer::DecalFilter p_filter) { + if (decals_filter == p_filter) { + return; + } + decals_filter = p_filter; + _update_shader_quality_settings(); +} +void RendererSceneRenderRD::light_projectors_set_filter(RenderingServer::LightProjectorFilter p_filter) { + if (light_projectors_filter == p_filter) { + return; + } + light_projectors_filter = p_filter; + _update_shader_quality_settings(); } int RendererSceneRenderRD::get_roughness_layers() const { @@ -2320,10 +2558,13 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti sort_array.sort(cluster.reflection_sort, cluster.reflection_count); } + bool using_forward_ids = _uses_forward_ids(); for (uint32_t i = 0; i < cluster.reflection_count; i++) { ReflectionProbeInstance *rpi = cluster.reflection_sort[i].instance; - rpi->render_index = i; + if (using_forward_ids) { + _map_forward_id(FORWARD_ID_TYPE_REFLECTION_PROBE, rpi->forward_id, i); + } RID base_probe = rpi->probe; @@ -2373,7 +2614,7 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti } } -void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count) { +void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count, bool &r_directional_light_soft_shadows) { Transform3D inverse_transform = p_camera_transform.affine_inverse(); r_directional_light_count = 0; @@ -2385,6 +2626,8 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const cluster.omni_light_count = 0; cluster.spot_light_count = 0; + r_directional_light_soft_shadows = false; + for (int i = 0; i < (int)p_lights.size(); i++) { LightInstance *li = light_instance_owner.getornull(p_lights[i]); if (!li) { @@ -2423,6 +2666,9 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const // technically this will keep expanding until reaching the sun, but all we care // is expand until we reach the radius of the near plane (there can't be more occluders than that) angular_diameter = Math::tan(Math::deg2rad(angular_diameter)); + if (storage->light_has_shadow(base)) { + r_directional_light_soft_shadows = true; + } } else { angular_diameter = 0.0; } @@ -2615,6 +2861,8 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); } + bool using_forward_ids = _uses_forward_ids(); + for (uint32_t i = 0; i < (cluster.omni_light_count + cluster.spot_light_count); i++) { uint32_t index = (i < cluster.omni_light_count) ? i : i - (cluster.omni_light_count); Cluster::LightData &light_data = (i < cluster.omni_light_count) ? cluster.omni_lights[index] : cluster.spot_lights[index]; @@ -2622,6 +2870,10 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const LightInstance *li = (i < cluster.omni_light_count) ? cluster.omni_light_sort[index].instance : cluster.spot_light_sort[index].instance; RID base = li->light; + if (using_forward_ids) { + _map_forward_id(type == RS::LIGHT_OMNI ? FORWARD_ID_TYPE_OMNI_LIGHT : FORWARD_ID_TYPE_SPOT_LIGHT, li->forward_id, index); + } + Transform3D light_transform = li->transform; float sign = storage->light_is_negative(base) ? -1 : 1; @@ -2754,7 +3006,6 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const light_data.shadow_enabled = false; } - li->light_index = index; li->cull_mask = storage->light_get_cull_mask(base); if (current_cluster_builder != nullptr) { @@ -2823,11 +3074,15 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const sort_array.sort(cluster.decal_sort, cluster.decal_count); } + bool using_forward_ids = _uses_forward_ids(); for (uint32_t i = 0; i < cluster.decal_count; i++) { DecalInstance *di = cluster.decal_sort[i].instance; RID decal = di->decal; - di->render_index = i; + if (using_forward_ids) { + _map_forward_id(FORWARD_ID_TYPE_DECAL, di->forward_id, i); + } + di->cull_mask = storage->decal_get_cull_mask(decal); Transform3D xform = di->transform; @@ -2944,116 +3199,6 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const } } -void RendererSceneRenderRD::_fill_instance_indices(const RID *p_omni_light_instances, uint32_t p_omni_light_instance_count, uint32_t *p_omni_light_indices, const RID *p_spot_light_instances, uint32_t p_spot_light_instance_count, uint32_t *p_spot_light_indices, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count, uint32_t *p_reflection_probe_indices, const RID *p_decal_instances, uint32_t p_decal_instance_count, uint32_t *p_decal_instance_indices, uint32_t p_layer_mask, uint32_t p_max_dst_words) { - // first zero out our indices - for (uint32_t i = 0; i < p_max_dst_words; i++) { - p_omni_light_indices[i] = 0; - p_spot_light_indices[i] = 0; - p_reflection_probe_indices[i] = 0; - p_decal_instance_indices[i] = 0; - } - - { - // process omni lights - uint32_t dword = 0; - uint32_t shift = 0; - - for (uint32_t i = 0; i < p_omni_light_instance_count && dword < p_max_dst_words; i++) { - LightInstance *li = light_instance_owner.getornull(p_omni_light_instances[i]); - - if ((li->cull_mask & p_layer_mask) && (li->light_index < 255)) { - p_omni_light_indices[dword] += li->light_index << shift; - if (shift == 24) { - dword++; - shift = 0; - } else { - shift += 8; - } - } - } - - if (dword < 2) { - // put in ending mark - p_omni_light_indices[dword] += 0xFF << shift; - } - } - - { - // process spot lights - uint32_t dword = 0; - uint32_t shift = 0; - - for (uint32_t i = 0; i < p_spot_light_instance_count && dword < p_max_dst_words; i++) { - LightInstance *li = light_instance_owner.getornull(p_spot_light_instances[i]); - - if ((li->cull_mask & p_layer_mask) && (li->light_index < 255)) { - p_spot_light_indices[dword] += li->light_index << shift; - if (shift == 24) { - dword++; - shift = 0; - } else { - shift += 8; - } - } - } - - if (dword < 2) { - // put in ending mark - p_spot_light_indices[dword] += 0xFF << shift; - } - } - - { - // process reflection probes - uint32_t dword = 0; - uint32_t shift = 0; - - for (uint32_t i = 0; i < p_reflection_probe_instance_count && dword < p_max_dst_words; i++) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_reflection_probe_instances[i]); - - if ((rpi->cull_mask & p_layer_mask) && (rpi->render_index < 255)) { - p_reflection_probe_indices[dword] += rpi->render_index << shift; - if (shift == 24) { - dword++; - shift = 0; - } else { - shift += 8; - } - } - } - - if (dword < 2) { - // put in ending mark - p_reflection_probe_indices[dword] += 0xFF << shift; - } - } - - { - // process decals - uint32_t dword = 0; - uint32_t shift = 0; - - for (uint32_t i = 0; i < p_decal_instance_count && dword < p_max_dst_words; i++) { - DecalInstance *decal = decal_instance_owner.getornull(p_decal_instances[i]); - - if ((decal->cull_mask & p_layer_mask) && (decal->render_index < 255)) { - p_decal_instance_indices[dword] += decal->render_index << shift; - if (shift == 24) { - dword++; - shift = 0; - } else { - shift += 8; - } - } - } - - if (dword < 2) { - // put in ending mark - p_decal_instance_indices[dword] += 0xFF << shift; - } - } -} - void RendererSceneRenderRD::_volumetric_fog_erase(RenderBuffers *rb) { ERR_FAIL_COND(!rb->volumetric_fog); @@ -3617,7 +3762,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool uint32_t directional_light_count = 0; uint32_t positional_light_count = 0; - _setup_lights(*p_render_data->lights, p_render_data->cam_transform, p_render_data->shadow_atlas, using_shadows, directional_light_count, positional_light_count); + _setup_lights(*p_render_data->lights, p_render_data->cam_transform, p_render_data->shadow_atlas, using_shadows, directional_light_count, positional_light_count, p_render_data->directional_light_soft_shadows); _setup_decals(*p_render_data->decals, p_render_data->cam_transform.affine_inverse()); p_render_data->directional_light_count = directional_light_count; @@ -3773,9 +3918,28 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData _render_scene(&render_data, clear_color); if (p_render_buffers.is_valid()) { - if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_OMNI_LIGHTS || debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_SPOT_LIGHTS || debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_DECALS || debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_REFLECTION_PROBES) { + /* + _debug_draw_cluster(p_render_buffers); + + RENDER_TIMESTAMP("Tonemap"); + + _render_buffers_post_process_and_tonemap(&render_data); + */ + + _render_buffers_debug_draw(p_render_buffers, p_shadow_atlas, p_occluder_debug_tex); + if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SDFGI && rb != nullptr && rb->sdfgi != nullptr) { + rb->sdfgi->debug_draw(render_data.cam_projection, render_data.cam_transform, rb->width, rb->height, rb->render_target, rb->texture); + } + } +} + +void RendererSceneRenderRD::_debug_draw_cluster(RID p_render_buffers) { + if (p_render_buffers.is_valid() && current_cluster_builder != nullptr) { + RS::ViewportDebugDraw dd = get_debug_draw_mode(); + + if (dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_OMNI_LIGHTS || dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_SPOT_LIGHTS || dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_DECALS || dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_REFLECTION_PROBES) { ClusterBuilderRD::ElementType elem_type = ClusterBuilderRD::ELEMENT_TYPE_MAX; - switch (debug_draw) { + switch (dd) { case RS::VIEWPORT_DEBUG_DRAW_CLUSTER_OMNI_LIGHTS: elem_type = ClusterBuilderRD::ELEMENT_TYPE_OMNI_LIGHT; break; @@ -3791,17 +3955,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData default: { } } - if (current_cluster_builder != nullptr) { - current_cluster_builder->debug(elem_type); - } - } - - RENDER_TIMESTAMP("Tonemap"); - - _render_buffers_post_process_and_tonemap(&render_data); - _render_buffers_debug_draw(p_render_buffers, p_shadow_atlas, p_occluder_debug_tex); - if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SDFGI && rb != nullptr && rb->sdfgi != nullptr) { - rb->sdfgi->debug_draw(render_data.cam_projection, render_data.cam_transform, rb->width, rb->height, rb->render_target, rb->texture); + current_cluster_builder->debug(elem_type); } } } @@ -4029,11 +4183,13 @@ bool RendererSceneRenderRD::free(RID p_rid) { } reflection_atlas_owner.free(p_rid); } else if (reflection_probe_instance_owner.owns(p_rid)) { - //not much to delete, just free it - //ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_rid); + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_rid); + _free_forward_id(FORWARD_ID_TYPE_REFLECTION_PROBE, rpi->forward_id); reflection_probe_release_atlas_index(p_rid); reflection_probe_instance_owner.free(p_rid); } else if (decal_instance_owner.owns(p_rid)) { + DecalInstance *di = decal_instance_owner.getornull(p_rid); + _free_forward_id(FORWARD_ID_TYPE_DECAL, di->forward_id); decal_instance_owner.free(p_rid); } else if (lightmap_instance_owner.owns(p_rid)) { lightmap_instance_owner.free(p_rid); @@ -4068,6 +4224,9 @@ bool RendererSceneRenderRD::free(RID p_rid) { shadow_atlas->shadow_owners.erase(p_rid); } + if (light_instance->light_type != RS::LIGHT_DIRECTIONAL) { + _free_forward_id(light_instance->light_type == RS::LIGHT_OMNI ? FORWARD_ID_TYPE_OMNI_LIGHT : FORWARD_ID_TYPE_SPOT_LIGHT, light_instance->forward_id); + } light_instance_owner.free(p_rid); } else if (shadow_atlas_owner.owns(p_rid)) { @@ -4357,6 +4516,9 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) { environment_set_volumetric_fog_volume_size(GLOBAL_GET("rendering/environment/volumetric_fog/volume_size"), GLOBAL_GET("rendering/environment/volumetric_fog/volume_depth")); environment_set_volumetric_fog_filter_active(GLOBAL_GET("rendering/environment/volumetric_fog/use_filter")); + decals_set_filter(RS::DecalFilter(int(GLOBAL_GET("rendering/textures/decals/filter")))); + light_projectors_set_filter(RS::LightProjectorFilter(int(GLOBAL_GET("rendering/textures/light_projectors/filter")))); + cull_argument.set_page_pool(&cull_argument_pool); } |
