Extracting render buffers and changing it to a more generic solution

This commit is contained in:
Bastiaan Olij 2022-08-04 18:40:39 +10:00
parent 0c221f0284
commit 2cd84be64d
49 changed files with 3095 additions and 2656 deletions

View File

@ -568,7 +568,7 @@ void RasterizerSceneGLES3::_update_dirty_skys() {
dirty_sky_list = nullptr;
}
void RasterizerSceneGLES3::_setup_sky(const RenderDataGLES3 *p_render_data, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size) {
void RasterizerSceneGLES3::_setup_sky(const RenderDataGLES3 *p_render_data, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size) {
GLES3::LightStorage *light_storage = GLES3::LightStorage::get_singleton();
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
ERR_FAIL_COND(p_render_data->environment.is_null());
@ -1718,23 +1718,23 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) {
void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) {
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
GLES3::Config *config = GLES3::Config::get_singleton();
RENDER_TIMESTAMP("Setup 3D Scene");
RenderBuffers *rb = nullptr;
Ref<RenderSceneBuffersGLES3> rb;
if (p_render_buffers.is_valid()) {
rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
rb = p_render_buffers;
ERR_FAIL_COND(rb.is_null());
}
// Assign render data
// Use the format from rendererRD
RenderDataGLES3 render_data;
{
render_data.render_buffers = p_render_buffers;
render_data.transparent_bg = rb->is_transparent;
render_data.render_buffers = rb;
render_data.transparent_bg = rb.is_valid() ? rb->is_transparent : false;
// Our first camera is used by default
render_data.cam_transform = p_camera_data->main_transform;
render_data.inv_cam_transform = render_data.cam_transform.affine_inverse();
@ -1886,7 +1886,7 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *
sky_energy_multiplier *= bg_energy_multiplier;
_setup_sky(&render_data, p_render_buffers, *render_data.lights, projection, render_data.cam_transform, screen_size);
_setup_sky(&render_data, *render_data.lights, projection, render_data.cam_transform, screen_size);
if (environment_get_sky(render_data.environment).is_valid()) {
if (environment_get_reflection_source(render_data.environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(render_data.environment) == RS::ENV_AMBIENT_SOURCE_SKY || (environment_get_reflection_source(render_data.environment) == RS::ENV_REFLECTION_SOURCE_BG && environment_get_background(render_data.environment) == RS::ENV_BG_SKY)) {
@ -2005,8 +2005,8 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *
_render_list_template<PASS_MODE_COLOR_TRANSPARENT>(&render_list_params_alpha, &render_data, 0, render_list[RENDER_LIST_ALPHA].elements.size(), true);
if (p_render_buffers.is_valid()) {
_render_buffers_debug_draw(p_render_buffers, p_shadow_atlas, p_occluder_debug_tex);
if (rb.is_valid()) {
_render_buffers_debug_draw(rb, p_shadow_atlas, p_occluder_debug_tex);
}
glDisable(GL_BLEND);
texture_storage->render_target_disable_clear_request(rb->render_target);
@ -2328,74 +2328,10 @@ void RasterizerSceneGLES3::set_debug_draw_mode(RS::ViewportDebugDraw p_debug_dra
debug_draw = p_debug_draw;
}
RID RasterizerSceneGLES3::render_buffers_create() {
RenderBuffers rb;
return render_buffers_owner.make_rid(rb);
}
void RasterizerSceneGLES3::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
//rb->internal_width = p_internal_width; // ignore for now
//rb->internal_height = p_internal_height;
rb->width = p_width;
rb->height = p_height;
//rb->fsr_sharpness = p_fsr_sharpness;
rb->render_target = p_render_target;
//rb->msaa = p_msaa;
//rb->screen_space_aa = p_screen_space_aa;
//rb->use_debanding = p_use_debanding;
//rb->view_count = p_view_count;
_free_render_buffer_data(rb);
GLES3::RenderTarget *rt = texture_storage->get_render_target(p_render_target);
rb->is_transparent = rt->is_transparent;
// framebuffer
glGenFramebuffers(1, &rb->framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, rb->framebuffer);
glBindTexture(GL_TEXTURE_2D, rt->color);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
glGenTextures(1, &rb->depth_texture);
glBindTexture(GL_TEXTURE_2D, rb->depth_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rb->depth_texture, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, texture_storage->system_fbo);
if (status != GL_FRAMEBUFFER_COMPLETE) {
_free_render_buffer_data(rb);
WARN_PRINT("Could not create 3D renderbuffer, status: " + texture_storage->get_framebuffer_error(status));
return;
}
}
void RasterizerSceneGLES3::_free_render_buffer_data(RenderBuffers *rb) {
if (rb->depth_texture) {
glDeleteTextures(1, &rb->depth_texture);
rb->depth_texture = 0;
}
if (rb->framebuffer) {
glDeleteFramebuffers(1, &rb->framebuffer);
rb->framebuffer = 0;
}
Ref<RenderSceneBuffers> RasterizerSceneGLES3::render_buffers_create() {
Ref<RenderSceneBuffersGLES3> rb;
rb.instantiate();
return rb;
}
//clear render buffers
@ -2423,7 +2359,7 @@ void RasterizerSceneGLES3::_free_render_buffer_data(RenderBuffers *rb) {
}
*/
void RasterizerSceneGLES3::_render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) {
void RasterizerSceneGLES3::_render_buffers_debug_draw(Ref<RenderSceneBuffersGLES3> p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) {
}
void RasterizerSceneGLES3::gi_set_use_half_resolution(bool p_enable) {
@ -2454,12 +2390,6 @@ bool RasterizerSceneGLES3::free(RID p_rid) {
ERR_FAIL_COND_V(!sky, false);
_free_sky_data(sky);
sky_owner.free(p_rid);
} else if (render_buffers_owner.owns(p_rid)) {
RenderBuffers *rb = render_buffers_owner.get_or_null(p_rid);
ERR_FAIL_COND_V(!rb, false);
_free_render_buffer_data(rb);
render_buffers_owner.free(p_rid);
} else if (light_instance_owner.owns(p_rid)) {
LightInstance *light_instance = light_instance_owner.get_or_null(p_rid);
ERR_FAIL_COND_V(!light_instance, false);

View File

@ -45,6 +45,7 @@
#include "shaders/cubemap_filter.glsl.gen.h"
#include "shaders/sky.glsl.gen.h"
#include "storage/material_storage.h"
#include "storage/render_scene_buffers_gles3.h"
#include "storage/utilities.h"
enum RenderListType {
@ -91,7 +92,7 @@ enum {
};
struct RenderDataGLES3 {
RID render_buffers = RID();
Ref<RenderSceneBuffersGLES3> render_buffers;
bool transparent_bg = false;
Transform3D cam_transform = Transform3D();
@ -490,52 +491,11 @@ protected:
double time;
double time_step = 0;
struct RenderBuffers {
int internal_width = 0;
int internal_height = 0;
int width = 0;
int height = 0;
//float fsr_sharpness = 0.2f;
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
//RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
//bool use_debanding = false;
//uint32_t view_count = 1;
bool is_transparent = false;
RID render_target;
GLuint internal_texture = 0; // Used for rendering when post effects are enabled
GLuint depth_texture = 0; // Main depth texture
GLuint framebuffer = 0; // Main framebuffer, contains internal_texture and depth_texture or render_target->color and depth_texture
//built-in textures used for ping pong image processing and blurring
struct Blur {
RID texture;
struct Mipmap {
RID texture;
int width;
int height;
GLuint fbo;
};
Vector<Mipmap> mipmaps;
};
Blur blur[2]; //the second one starts from the first mipmap
};
bool screen_space_roughness_limiter = false;
float screen_space_roughness_limiter_amount = 0.25;
float screen_space_roughness_limiter_limit = 0.18;
mutable RID_Owner<RenderBuffers, true> render_buffers_owner;
void _free_render_buffer_data(RenderBuffers *rb);
void _allocate_blur_textures(RenderBuffers *rb);
void _allocate_depth_backbuffer_textures(RenderBuffers *rb);
void _render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer);
void _render_buffers_debug_draw(Ref<RenderSceneBuffersGLES3> p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer);
/* Camera Attributes */
@ -626,7 +586,7 @@ protected:
Sky *dirty_sky_list = nullptr;
mutable RID_Owner<Sky, true> sky_owner;
void _setup_sky(const RenderDataGLES3 *p_render_data, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size);
void _setup_sky(const RenderDataGLES3 *p_render_data, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size);
void _invalidate_sky(Sky *p_sky);
void _update_dirty_skys();
void _update_sky_radiance(RID p_env, const Projection &p_projection, const Transform3D &p_transform, float p_luminance_multiplier);
@ -657,14 +617,14 @@ public:
/* SDFGI UPDATE */
void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {}
int sdfgi_get_pending_region_count(RID p_render_buffers) const override {
void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {}
int sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const override {
return 0;
}
AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override {
AABB sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override {
return AABB();
}
uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override {
uint32_t sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override {
return 0;
}
@ -751,7 +711,7 @@ public:
void voxel_gi_set_quality(RS::VoxelGIQuality) override;
void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
void render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) override;
@ -769,8 +729,7 @@ public:
return debug_draw;
}
RID render_buffers_create() override;
void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
Ref<RenderSceneBuffers> render_buffers_create() override;
void gi_set_use_half_resolution(bool p_enable) override;
void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override;

View File

@ -0,0 +1,103 @@
/*************************************************************************/
/* render_scene_buffers_gles3.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifdef GLES3_ENABLED
#include "render_scene_buffers_gles3.h"
#include "texture_storage.h"
RenderSceneBuffersGLES3::~RenderSceneBuffersGLES3() {
free_render_buffer_data();
}
void RenderSceneBuffersGLES3::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
//internal_size.x = p_internal_size.x; // ignore for now
//internal_size.y = p_internal_size.y;
width = p_target_size.x;
height = p_target_size.y;
//fsr_sharpness = p_fsr_sharpness;
//texture_mipmap_bias = p_texture_mipmap_bias;
render_target = p_render_target;
//msaa = p_msaa;
//screen_space_aa = p_screen_space_aa;
//use_debanding = p_use_debanding;
//view_count = p_view_count;
free_render_buffer_data();
GLES3::RenderTarget *rt = texture_storage->get_render_target(p_render_target);
is_transparent = rt->is_transparent;
// framebuffer
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glBindTexture(GL_TEXTURE_2D, rt->color);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
glGenTextures(1, &depth_texture);
glBindTexture(GL_TEXTURE_2D, depth_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_texture, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, texture_storage->system_fbo);
if (status != GL_FRAMEBUFFER_COMPLETE) {
free_render_buffer_data();
WARN_PRINT("Could not create 3D renderbuffer, status: " + texture_storage->get_framebuffer_error(status));
return;
}
}
void RenderSceneBuffersGLES3::free_render_buffer_data() {
if (depth_texture) {
glDeleteTextures(1, &depth_texture);
depth_texture = 0;
}
if (framebuffer) {
glDeleteFramebuffers(1, &framebuffer);
framebuffer = 0;
}
}
#endif // GLES3_ENABLED

View File

@ -0,0 +1,98 @@
/*************************************************************************/
/* render_scene_buffers_gles3.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef RENDER_SCENE_BUFFERS_GLES3_H
#define RENDER_SCENE_BUFFERS_GLES3_H
#ifdef GLES3_ENABLED
#include "servers/rendering/storage/render_scene_buffers.h"
#include "platform_config.h"
#ifndef OPENGL_INCLUDE_H
#include <GLES3/gl3.h>
#else
#include OPENGL_INCLUDE_H
#endif
class RenderSceneBuffersGLES3 : public RenderSceneBuffers {
GDCLASS(RenderSceneBuffersGLES3, RenderSceneBuffers);
public:
// Original implementation, need to investigate which ones we'll keep like this and what we'll change...
int internal_width = 0;
int internal_height = 0;
int width = 0;
int height = 0;
//float fsr_sharpness = 0.2f;
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
//RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
//bool use_debanding = false;
//uint32_t view_count = 1;
bool is_transparent = false;
RID render_target;
GLuint internal_texture = 0; // Used for rendering when post effects are enabled
GLuint depth_texture = 0; // Main depth texture
GLuint framebuffer = 0; // Main framebuffer, contains internal_texture and depth_texture or render_target->color and depth_texture
//built-in textures used for ping pong image processing and blurring
struct Blur {
RID texture;
struct Mipmap {
RID texture;
int width;
int height;
GLuint fbo;
};
Vector<Mipmap> mipmaps;
};
Blur blur[2]; //the second one starts from the first mipmap
private:
public:
virtual ~RenderSceneBuffersGLES3();
virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
virtual void set_fsr_sharpness(float p_fsr_sharpness) override{};
virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) override{};
virtual void set_use_debanding(bool p_use_debanding) override{};
void free_render_buffer_data();
};
#endif // GLES3_ENABLED
#endif // RENDER_SCENE_BUFFERS_GLES3_H

View File

@ -106,10 +106,10 @@ public:
/* SDFGI UPDATE */
void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {}
int sdfgi_get_pending_region_count(RID p_render_buffers) const override { return 0; }
AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override { return AABB(); }
uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override { return 0; }
void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {}
int sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const override { return 0; }
AABB sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override { return AABB(); }
uint32_t sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override { return 0; }
/* SKY API */
@ -180,7 +180,7 @@ public:
void voxel_gi_set_quality(RS::VoxelGIQuality) override {}
void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {}
void render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {}
void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {}
void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) override {}
@ -188,8 +188,7 @@ public:
void set_time(double p_time, double p_step) override {}
void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {}
RID render_buffers_create() override { return RID(); }
void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override {}
Ref<RenderSceneBuffers> render_buffers_create() override { return Ref<RenderSceneBuffers>(); }
void gi_set_use_half_resolution(bool p_enable) override {}
void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {}

View File

@ -705,7 +705,7 @@ void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, con
RD::get_singleton()->compute_list_end();
}
void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_scale) {
void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, RID p_half_texture, RID p_dest_texture, float p_luminance_multiplier, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_scale) {
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian glow with the clustered renderer.");
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
@ -713,6 +713,9 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminanc
MaterialStorage *material_storage = MaterialStorage::get_singleton();
ERR_FAIL_NULL(material_storage);
RID half_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_half_texture);
RID dest_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_dest_texture);
memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
BlurRasterMode blur_mode = p_first_pass && p_auto_exposure.is_valid() ? BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : BLUR_MODE_GAUSSIAN_GLOW;
@ -737,14 +740,14 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminanc
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
RD::Uniform u_rd_texture_half(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_rd_texture_half }));
RD::Uniform u_half_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_half_texture }));
RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, blur_mode);
ERR_FAIL_COND(shader.is_null());
//HORIZONTAL
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half)));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(half_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(half_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
if (p_auto_exposure.is_valid() && p_first_pass) {
RD::Uniform u_auto_exposure(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_auto_exposure }));
@ -764,9 +767,9 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminanc
ERR_FAIL_COND(shader.is_null());
//VERTICAL
draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_rd_texture_half), 0);
draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_half_texture), 0);
RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
blur_raster.push_constant.flags = base_flags;
@ -810,9 +813,11 @@ void CopyEffects::make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const
RD::get_singleton()->compute_list_end();
}
void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size) {
void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size) {
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of mipmap with the clustered renderer.");
RID dest_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_dest_texture);
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
MaterialStorage *material_storage = MaterialStorage::get_singleton();
@ -833,8 +838,8 @@ void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebu
RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, mode);
ERR_FAIL_COND(shader.is_null());
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));

View File

@ -322,10 +322,10 @@ public:
void gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst = false);
void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0);
void gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0);
void gaussian_glow_raster(RID p_source_rd_texture, RID p_half_texture, RID p_dest_texture, float p_luminance_multiplier, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0);
void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size);
void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false);

View File

@ -0,0 +1,127 @@
/*************************************************************************/
/* fsr.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "fsr.h"
#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
using namespace RendererRD;
FSR::FSR() {
Vector<String> FSR_upscale_modes;
#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
// MoltenVK does not support some of the operations used by the normal mode of FSR. Fallback works just fine though.
FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
#else
// Everyone else can use normal mode when available.
if (RD::get_singleton()->has_feature(RD::SUPPORTS_FSR_HALF_FLOAT)) {
FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_NORMAL\n");
} else {
FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
}
#endif
fsr_shader.initialize(FSR_upscale_modes);
shader_version = fsr_shader.version_create();
pipeline = RD::get_singleton()->compute_pipeline_create(fsr_shader.version_get_shader(shader_version, 0));
}
FSR::~FSR() {
fsr_shader.version_free(shader_version);
}
void FSR::fsr_upscale(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_source_rd_texture, RID p_destination_texture) {
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
MaterialStorage *material_storage = MaterialStorage::get_singleton();
ERR_FAIL_NULL(material_storage);
Size2i internal_size = p_render_buffers->get_internal_size();
Size2i target_size = p_render_buffers->get_target_size();
float fsr_upscale_sharpness = p_render_buffers->get_fsr_sharpness();
if (!p_render_buffers->has_texture(SNAME("FSR"), SNAME("upscale_texture"))) {
RD::DataFormat format = p_render_buffers->get_base_data_format();
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
uint32_t layers = 1; // we only need one layer, in multiview we're processing one layer at a time.
p_render_buffers->create_texture(SNAME("FSR"), SNAME("upscale_texture"), format, usage_bits, RD::TEXTURE_SAMPLES_1, target_size, layers);
}
RID upscale_texture = p_render_buffers->get_texture(SNAME("FSR"), SNAME("upscale_texture"));
FSRUpscalePushConstant push_constant;
memset(&push_constant, 0, sizeof(FSRUpscalePushConstant));
int dispatch_x = (target_size.x + 15) / 16;
int dispatch_y = (target_size.y + 15) / 16;
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipeline);
push_constant.resolution_width = internal_size.width;
push_constant.resolution_height = internal_size.height;
push_constant.upscaled_width = target_size.width;
push_constant.upscaled_height = target_size.height;
push_constant.sharpness = fsr_upscale_sharpness;
RID shader = fsr_shader.version_get_shader(shader_version, 0);
ERR_FAIL_COND(shader.is_null());
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
//FSR Easc
RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, { default_sampler, p_source_rd_texture });
RD::Uniform u_upscale_texture(RD::UNIFORM_TYPE_IMAGE, 0, { upscale_texture });
push_constant.pass = FSR_UPSCALE_PASS_EASU;
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_upscale_texture), 1);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(FSRUpscalePushConstant));
RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
//FSR Rcas
RD::Uniform u_upscale_texture_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, { default_sampler, upscale_texture });
RD::Uniform u_destination_texture(RD::UNIFORM_TYPE_IMAGE, 0, { p_destination_texture });
push_constant.pass = FSR_UPSCALE_PASS_RCAS;
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_upscale_texture_with_sampler), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_destination_texture), 1);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(FSRUpscalePushConstant));
RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
RD::get_singleton()->compute_list_end(compute_list);
}

View File

@ -0,0 +1,73 @@
/*************************************************************************/
/* fsr.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef FSR_RD_H
#define FSR_RD_H
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
#include "servers/rendering/renderer_rd/shaders/effects/fsr_upscale.glsl.gen.h"
#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering_server.h"
namespace RendererRD {
class FSR {
public:
FSR();
~FSR();
void fsr_upscale(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_source_rd_texture, RID p_destination_texture);
private:
enum FSRUpscalePass {
FSR_UPSCALE_PASS_EASU = 0,
FSR_UPSCALE_PASS_RCAS = 1
};
struct FSRUpscalePushConstant {
float resolution_width;
float resolution_height;
float upscaled_width;
float upscaled_height;
float sharpness;
int pass;
int _unused0, _unused1;
};
FsrUpscaleShaderRD fsr_shader;
RID shader_version;
RID pipeline;
};
} // namespace RendererRD
#endif // FSR_RD_H

View File

@ -32,6 +32,7 @@
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
using namespace RendererRD;
@ -333,6 +334,22 @@ SSEffects::SSEffects() {
}
}
}
// Subsurface scattering
{
Vector<String> sss_modes;
sss_modes.push_back("\n#define USE_11_SAMPLES\n");
sss_modes.push_back("\n#define USE_17_SAMPLES\n");
sss_modes.push_back("\n#define USE_25_SAMPLES\n");
sss.shader.initialize(sss_modes);
sss.shader_version = sss.shader.version_create();
for (int i = 0; i < sss_modes.size(); i++) {
sss.pipelines[i] = RD::get_singleton()->compute_pipeline_create(sss.shader.version_get_shader(sss.shader_version, i));
}
}
}
SSEffects::~SSEffects() {
@ -376,6 +393,11 @@ SSEffects::~SSEffects() {
RD::get_singleton()->free(ssao.importance_map_load_counter);
}
{
// Cleanup Subsurface scattering
sss.shader.version_free(sss.shader_version);
}
singleton = nullptr;
}
@ -1713,3 +1735,73 @@ void SSEffects::ssr_free(SSRRenderBuffers &p_ssr_buffers) {
p_ssr_buffers.normal_scaled = RID();
}
}
/* Subsurface scattering */
void SSEffects::sub_surface_scattering(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_diffuse, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RenderingServer::SubSurfaceScatteringQuality p_quality) {
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
MaterialStorage *material_storage = MaterialStorage::get_singleton();
ERR_FAIL_NULL(material_storage);
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
// Our intermediate buffer is only created if we haven't created it already.
RD::DataFormat format = p_render_buffers->get_base_data_format();
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
uint32_t layers = 1; // We only need one layer, we're handling one view at a time
uint32_t mipmaps = 1; // Image::get_image_required_mipmaps(p_screen_size.x, p_screen_size.y, Image::FORMAT_RGBAH);
RID intermediate = p_render_buffers->create_texture(SNAME("SSR"), SNAME("intermediate"), format, usage_bits, RD::TEXTURE_SAMPLES_1, p_screen_size, layers, mipmaps);
Plane p = p_camera.xform4(Plane(1, 0, -1, 1));
p.normal /= p.d;
float unit_size = p.normal.x;
{ //scale color and depth to half
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
sss.push_constant.camera_z_far = p_camera.get_z_far();
sss.push_constant.camera_z_near = p_camera.get_z_near();
sss.push_constant.orthogonal = p_camera.is_orthogonal();
sss.push_constant.unit_size = unit_size;
sss.push_constant.screen_size[0] = p_screen_size.x;
sss.push_constant.screen_size[1] = p_screen_size.y;
sss.push_constant.vertical = false;
sss.push_constant.scale = p_scale;
sss.push_constant.depth_scale = p_depth_scale;
RID shader = sss.shader.version_get_shader(sss.shader_version, p_quality - 1);
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sss.pipelines[p_quality - 1]);
RD::Uniform u_diffuse_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_diffuse }));
RD::Uniform u_diffuse(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_diffuse }));
RD::Uniform u_intermediate_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, intermediate }));
RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ intermediate }));
RD::Uniform u_depth_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_depth }));
// horizontal
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_diffuse_with_sampler), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_intermediate), 1);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_depth_with_sampler), 2);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
// vertical
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate_with_sampler), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_diffuse), 1);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_depth_with_sampler), 2);
sss.push_constant.vertical = true;
RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
RD::get_singleton()->compute_list_end();
}
}

View File

@ -44,9 +44,12 @@
#include "servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/effects/subsurface_scattering.glsl.gen.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering_server.h"
class RenderSceneBuffersRD;
namespace RendererRD {
class SSEffects {
@ -168,6 +171,9 @@ public:
void screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const RID *p_diffuse_slices, const RID *p_normal_roughness_slices, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, const RID *p_metallic_slices, const Color &p_metallic_mask, const RID *p_depth_slices, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets);
void ssr_free(SSRRenderBuffers &p_ssr_buffers);
/* subsurface scattering */
void sub_surface_scattering(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_diffuse, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality);
private:
/* SS Downsampler */
@ -501,6 +507,29 @@ private:
RID shader_version;
RID pipelines[SSR_VARIATIONS][SCREEN_SPACE_REFLECTION_FILTER_MAX];
} ssr_filter;
/* Subsurface scattering */
struct SubSurfaceScatteringPushConstant {
int32_t screen_size[2];
float camera_z_far;
float camera_z_near;
uint32_t vertical;
uint32_t orthogonal;
float unit_size;
float scale;
float depth_scale;
uint32_t pad[3];
};
struct SubSurfaceScattering {
SubSurfaceScatteringPushConstant push_constant;
SubsurfaceScatteringShaderRD shader;
RID shader_version;
RID pipelines[3]; //3 quality levels
} sss;
};
} // namespace RendererRD

View File

@ -0,0 +1,138 @@
/*************************************************************************/
/* taa.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "taa.h"
#include "servers/rendering/renderer_rd/effects/copy_effects.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
using namespace RendererRD;
TAA::TAA() {
Vector<String> taa_modes;
taa_modes.push_back("\n#define MODE_TAA_RESOLVE");
taa_shader.initialize(taa_modes);
shader_version = taa_shader.version_create();
pipeline = RD::get_singleton()->compute_pipeline_create(taa_shader.version_get_shader(shader_version, 0));
}
TAA::~TAA() {
taa_shader.version_free(shader_version);
}
void TAA::msaa_resolve(Ref<RenderSceneBuffersRD> p_render_buffers) {
if (!p_render_buffers->has_velocity_buffer(true)) {
// nothing to resolve
return;
}
for (uint32_t v = 0; v < p_render_buffers->get_view_count(); v++) {
RID velocity_buffer_msaa = p_render_buffers->get_velocity_buffer(true, v);
RID velocity_buffer = p_render_buffers->get_velocity_buffer(false, v);
RD::get_singleton()->texture_resolve_multisample(velocity_buffer_msaa, velocity_buffer);
}
}
void TAA::resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far) {
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
MaterialStorage *material_storage = MaterialStorage::get_singleton();
ERR_FAIL_NULL(material_storage);
RID shader = taa_shader.version_get_shader(shader_version, 0);
ERR_FAIL_COND(shader.is_null());
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
TAAResolvePushConstant push_constant;
memset(&push_constant, 0, sizeof(TAAResolvePushConstant));
push_constant.resolution_width = p_resolution.width;
push_constant.resolution_height = p_resolution.height;
push_constant.disocclusion_threshold = 0.025f;
push_constant.disocclusion_scale = 10.0f;
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipeline);
RD::Uniform u_frame_source(RD::UNIFORM_TYPE_IMAGE, 0, { p_frame });
RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, { default_sampler, p_depth });
RD::Uniform u_velocity(RD::UNIFORM_TYPE_IMAGE, 2, { p_velocity });
RD::Uniform u_prev_velocity(RD::UNIFORM_TYPE_IMAGE, 3, { p_prev_velocity });
RD::Uniform u_history(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 4, { default_sampler, p_history });
RD::Uniform u_frame_dest(RD::UNIFORM_TYPE_IMAGE, 5, { p_temp });
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_frame_source, u_depth, u_velocity, u_prev_velocity, u_history, u_frame_dest), 0);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(TAAResolvePushConstant));
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_resolution.width, p_resolution.height, 1);
RD::get_singleton()->compute_list_end();
}
void TAA::process(Ref<RenderSceneBuffersRD> p_render_buffers, RD::DataFormat p_format, float p_z_near, float p_z_far) {
CopyEffects *copy_effects = CopyEffects::get_singleton();
uint32_t view_count = p_render_buffers->get_view_count();
Size2i internal_size = p_render_buffers->get_internal_size();
Size2i target_size = p_render_buffers->get_target_size();
bool just_allocated = false;
if (!p_render_buffers->has_texture(SNAME("taa"), SNAME("history"))) {
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
p_render_buffers->create_texture(SNAME("taa"), SNAME("history"), p_format, usage_bits);
p_render_buffers->create_texture(SNAME("taa"), SNAME("temp"), p_format, usage_bits);
p_render_buffers->create_texture(SNAME("taa"), SNAME("prev_velocity"), RD::DATA_FORMAT_R16G16_SFLOAT, usage_bits);
just_allocated = true;
}
RD::get_singleton()->draw_command_begin_label("TAA");
for (uint32_t v = 0; v < view_count; v++) {
// Get our (cached) slices
RID internal_texture = p_render_buffers->get_internal_texture(v);
RID velocity_buffer = p_render_buffers->get_velocity_buffer(false, v);
RID taa_history = p_render_buffers->get_texture_slice(SNAME("taa"), SNAME("history"), v, 0);
RID taa_prev_velocity = p_render_buffers->get_texture_slice(SNAME("taa"), SNAME("prev_velocity"), v, 0);
if (!just_allocated) {
RID depth_texture = p_render_buffers->get_depth_texture(v);
RID taa_temp = p_render_buffers->get_texture_slice(SNAME("taa"), SNAME("temp"), v, 0);
resolve(internal_texture, taa_temp, depth_texture, velocity_buffer, taa_prev_velocity, taa_history, Size2(internal_size.x, internal_size.y), p_z_near, p_z_far);
copy_effects->copy_to_rect(taa_temp, internal_texture, Rect2(0, 0, internal_size.x, internal_size.y));
}
copy_effects->copy_to_rect(internal_texture, taa_history, Rect2(0, 0, internal_size.x, internal_size.y));
copy_effects->copy_to_rect(velocity_buffer, taa_prev_velocity, Rect2(0, 0, target_size.x, target_size.y));
}
RD::get_singleton()->draw_command_end_label();
}

View File

@ -0,0 +1,68 @@
/*************************************************************************/
/* taa.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef TAA_RD_H
#define TAA_RD_H
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
#include "servers/rendering/renderer_rd/shaders/effects/taa_resolve.glsl.gen.h"
#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering_server.h"
namespace RendererRD {
class TAA {
public:
TAA();
~TAA();
void msaa_resolve(Ref<RenderSceneBuffersRD> p_render_buffers);
void process(Ref<RenderSceneBuffersRD> p_render_buffers, RD::DataFormat p_format, float p_z_near, float p_z_far);
private:
struct TAAResolvePushConstant {
float resolution_width;
float resolution_height;
float disocclusion_threshold;
float disocclusion_scale;
};
TaaResolveShaderRD taa_shader;
RID shader_version;
RID pipeline;
void resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far);
};
} // namespace RendererRD
#endif // TAA_RD_H

View File

@ -91,47 +91,22 @@ void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multi
RD::get_singleton()->draw_list_end();
}
void VRS::create_vrs_texture(const int p_base_width, const int p_base_height, const uint32_t p_view_count, RID &p_vrs_texture, RID &p_vrs_fb) {
// TODO find a way to skip this if VRS is not supported, but we don't have access to VulkanContext here, even though we're in vulkan.. hmmm
Size2i VRS::get_vrs_texture_size(const Size2i p_base_size) const {
// TODO we should find some way to store this properly, we're assuming 16x16 as this seems to be the standard but in our vrs_capacities we
// obtain a minimum and maximum size, and we should choose something within this range and then make sure that is consistently set when creating
// our frame buffer. Also it is important that we make the resulting size we calculate down below available to the end user so they know the size
// of the VRS buffer to supply.
Size2i texel_size = Size2i(16, 16);
RD::TextureFormat tf;
if (p_view_count > 1) {
tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
} else {
tf.texture_type = RD::TEXTURE_TYPE_2D;
int width = p_base_size.x / texel_size.x;
if (p_base_size.x % texel_size.x != 0) {
width++;
}
tf.format = RD::DATA_FORMAT_R8_UINT;
tf.width = p_base_width / texel_size.x;
if (p_base_width % texel_size.x != 0) {
tf.width++;
int height = p_base_size.y / texel_size.y;
if (p_base_size.y % texel_size.y != 0) {
height++;
}
tf.height = p_base_height / texel_size.y;
if (p_base_height % texel_size.y != 0) {
tf.height++;
}
tf.array_layers = p_view_count; // create a layer for every view
tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
tf.samples = RD::TEXTURE_SAMPLES_1;
p_vrs_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
// by default VRS is assumed to be our VRS attachment, but if we need to write into it, we need a bit more control
Vector<RID> fb;
fb.push_back(p_vrs_texture);
RD::FramebufferPass pass;
pass.color_attachments.push_back(0);
Vector<RD::FramebufferPass> passes;
passes.push_back(pass);
p_vrs_fb = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, p_view_count);
return Size2i(width, height);
}
void VRS::update_vrs_texture(RID p_vrs_fb, RID p_render_target) {

View File

@ -66,7 +66,7 @@ public:
void copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multiview = false);
void create_vrs_texture(const int p_base_width, const int p_base_height, const uint32_t p_view_count, RID &p_vrs_texture, RID &p_vrs_fb);
Size2i get_vrs_texture_size(const Size2i p_base_size) const;
void update_vrs_texture(RID p_vrs_fb, RID p_render_target);
};

View File

@ -108,115 +108,6 @@ RID EffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bool p_use_m
return uniform_set;
}
void EffectsRD::fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness) {
memset(&FSR_upscale.push_constant, 0, sizeof(FSRUpscalePushConstant));
int dispatch_x = (p_size.x + 15) / 16;
int dispatch_y = (p_size.y + 15) / 16;
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, FSR_upscale.pipeline);
FSR_upscale.push_constant.resolution_width = p_internal_size.width;
FSR_upscale.push_constant.resolution_height = p_internal_size.height;
FSR_upscale.push_constant.upscaled_width = p_size.width;
FSR_upscale.push_constant.upscaled_height = p_size.height;
FSR_upscale.push_constant.sharpness = p_fsr_upscale_sharpness;
//FSR Easc
FSR_upscale.push_constant.pass = FSR_UPSCALE_PASS_EASU;
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_secondary_texture), 1);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &FSR_upscale.push_constant, sizeof(FSRUpscalePushConstant));
RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
//FSR Rcas
FSR_upscale.push_constant.pass = FSR_UPSCALE_PASS_RCAS;
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_secondary_texture), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_destination_texture), 1);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &FSR_upscale.push_constant, sizeof(FSRUpscalePushConstant));
RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
RD::get_singleton()->compute_list_end(compute_list);
}
void EffectsRD::taa_resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far) {
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
RID shader = TAA_resolve.shader.version_get_shader(TAA_resolve.shader_version, 0);
ERR_FAIL_COND(shader.is_null());
memset(&TAA_resolve.push_constant, 0, sizeof(TAAResolvePushConstant));
TAA_resolve.push_constant.resolution_width = p_resolution.width;
TAA_resolve.push_constant.resolution_height = p_resolution.height;
TAA_resolve.push_constant.disocclusion_threshold = 0.025f;
TAA_resolve.push_constant.disocclusion_scale = 10.0f;
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, TAA_resolve.pipeline);
RD::Uniform u_frame_source(RD::UNIFORM_TYPE_IMAGE, 0, { p_frame });
RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, { default_sampler, p_depth });
RD::Uniform u_velocity(RD::UNIFORM_TYPE_IMAGE, 2, { p_velocity });
RD::Uniform u_prev_velocity(RD::UNIFORM_TYPE_IMAGE, 3, { p_prev_velocity });
RD::Uniform u_history(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 4, { default_sampler, p_history });
RD::Uniform u_frame_dest(RD::UNIFORM_TYPE_IMAGE, 5, { p_temp });
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_frame_source, u_depth, u_velocity, u_prev_velocity, u_history, u_frame_dest), 0);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &TAA_resolve.push_constant, sizeof(TAAResolvePushConstant));
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_resolution.width, p_resolution.height, 1);
RD::get_singleton()->compute_list_end();
}
void EffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RenderingServer::SubSurfaceScatteringQuality p_quality) {
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
Plane p = p_camera.xform4(Plane(1, 0, -1, 1));
p.normal /= p.d;
float unit_size = p.normal.x;
{ //scale color and depth to half
sss.push_constant.camera_z_far = p_camera.get_z_far();
sss.push_constant.camera_z_near = p_camera.get_z_near();
sss.push_constant.orthogonal = p_camera.is_orthogonal();
sss.push_constant.unit_size = unit_size;
sss.push_constant.screen_size[0] = p_screen_size.x;
sss.push_constant.screen_size[1] = p_screen_size.y;
sss.push_constant.vertical = false;
sss.push_constant.scale = p_scale;
sss.push_constant.depth_scale = p_depth_scale;
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sss.pipelines[p_quality - 1]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_diffuse), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_diffuse2), 1);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth), 2);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_diffuse2), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_diffuse), 1);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth), 2);
sss.push_constant.vertical = true;
RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
RD::get_singleton()->compute_list_end();
}
}
void EffectsRD::luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set) {
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of luminance reduction with the mobile renderer.");
@ -377,27 +268,6 @@ void EffectsRD::sort_buffer(RID p_uniform_set, int p_size) {
}
EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
{
Vector<String> FSR_upscale_modes;
#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
// MoltenVK does not support some of the operations used by the normal mode of FSR. Fallback works just fine though.
FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
#else
// Everyone else can use normal mode when available.
if (RD::get_singleton()->has_feature(RD::SUPPORTS_FSR_HALF_FLOAT)) {
FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_NORMAL\n");
} else {
FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
}
#endif
FSR_upscale.shader.initialize(FSR_upscale_modes);
FSR_upscale.shader_version = FSR_upscale.shader.version_create();
FSR_upscale.pipeline = RD::get_singleton()->compute_pipeline_create(FSR_upscale.shader.version_get_shader(FSR_upscale.shader_version, 0));
}
prefer_raster_effects = p_prefer_raster_effects;
if (prefer_raster_effects) {
@ -445,23 +315,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
roughness_limiter.pipeline = RD::get_singleton()->compute_pipeline_create(roughness_limiter.shader.version_get_shader(roughness_limiter.shader_version, 0));
}
if (!prefer_raster_effects) {
{
Vector<String> sss_modes;
sss_modes.push_back("\n#define USE_11_SAMPLES\n");
sss_modes.push_back("\n#define USE_17_SAMPLES\n");
sss_modes.push_back("\n#define USE_25_SAMPLES\n");
sss.shader.initialize(sss_modes);
sss.shader_version = sss.shader.version_create();
for (int i = 0; i < sss_modes.size(); i++) {
sss.pipelines[i] = RD::get_singleton()->compute_pipeline_create(sss.shader.version_get_shader(sss.shader_version, i));
}
}
}
{
Vector<String> sort_modes;
sort_modes.push_back("\n#define MODE_SORT_BLOCK\n");
@ -477,14 +330,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
}
}
{
Vector<String> taa_modes;
taa_modes.push_back("\n#define MODE_TAA_RESOLVE");
TAA_resolve.shader.initialize(taa_modes);
TAA_resolve.shader_version = TAA_resolve.shader.version_create();
TAA_resolve.pipeline = RD::get_singleton()->compute_pipeline_create(TAA_resolve.shader.version_get_shader(TAA_resolve.shader_version, 0));
}
RD::SamplerState sampler;
sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
@ -523,8 +368,6 @@ EffectsRD::~EffectsRD() {
RD::get_singleton()->free(default_mipmap_sampler);
RD::get_singleton()->free(index_buffer); //array gets freed as dependency
FSR_upscale.shader.version_free(FSR_upscale.shader_version);
TAA_resolve.shader.version_free(TAA_resolve.shader_version);
if (prefer_raster_effects) {
luminance_reduce_raster.shader.version_free(luminance_reduce_raster.shader_version);
} else {
@ -532,7 +375,6 @@ EffectsRD::~EffectsRD() {
}
if (!prefer_raster_effects) {
roughness_limiter.shader.version_free(roughness_limiter.shader_version);
sss.shader.version_free(sss.shader_version);
}
sort.shader.version_free(sort.shader_version);
}

View File

@ -33,13 +33,10 @@
#include "core/math/projection.h"
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
#include "servers/rendering/renderer_rd/shaders/fsr_upscale.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/luminance_reduce.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/roughness_limiter.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/sort.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/taa_resolve.glsl.gen.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering_server.h"
@ -48,42 +45,6 @@ class EffectsRD {
private:
bool prefer_raster_effects;
enum FSRUpscalePass {
FSR_UPSCALE_PASS_EASU = 0,
FSR_UPSCALE_PASS_RCAS = 1
};
struct FSRUpscalePushConstant {
float resolution_width;
float resolution_height;
float upscaled_width;
float upscaled_height;
float sharpness;
int pass;
int _unused0, _unused1;
};
struct FSRUpscale {
FSRUpscalePushConstant push_constant;
FsrUpscaleShaderRD shader;
RID shader_version;
RID pipeline;
} FSR_upscale;
struct TAAResolvePushConstant {
float resolution_width;
float resolution_height;
float disocclusion_threshold;
float disocclusion_scale;
};
struct TAAResolve {
TAAResolvePushConstant push_constant;
TaaResolveShaderRD shader;
RID shader_version;
RID pipeline;
} TAA_resolve;
enum LuminanceReduceMode {
LUMINANCE_REDUCE_READ,
LUMINANCE_REDUCE,
@ -143,27 +104,6 @@ private:
} roughness_limiter;
struct SubSurfaceScatteringPushConstant {
int32_t screen_size[2];
float camera_z_far;
float camera_z_near;
uint32_t vertical;
uint32_t orthogonal;
float unit_size;
float scale;
float depth_scale;
uint32_t pad[3];
};
struct SubSurfaceScattering {
SubSurfaceScatteringPushConstant push_constant;
SubsurfaceScatteringShaderRD shader;
RID shader_version;
RID pipelines[3]; //3 quality levels
} sss;
enum SortMode {
SORT_MODE_BLOCK,
SORT_MODE_STEP,
@ -230,16 +170,11 @@ private:
public:
bool get_prefer_raster_effects();
void fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness);
void taa_resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far);
void luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
void luminance_reduction_raster(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, Vector<RID> p_fb, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
void roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve);
void sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality);
void sort_buffer(RID p_uniform_set, int p_size);
EffectsRD(bool p_prefer_raster_effects);

View File

@ -473,7 +473,7 @@ Fog::FogShaderData::~FogShaderData() {
////////////////////////////////////////////////////////////////////////////////
// Volumetric Fog
Fog::VolumetricFog::VolumetricFog(const Vector3i &fog_size, RID p_sky_shader) {
void Fog::VolumetricFog::init(const Vector3i &fog_size, RID p_sky_shader) {
width = fog_size.x;
height = fog_size.y;
depth = fog_size.z;
@ -591,6 +591,8 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
RENDER_TIMESTAMP("> Volumetric Fog");
RD::get_singleton()->draw_command_begin_label("Volumetric Fog");
Ref<VolumetricFog> fog = p_settings.vfog;
if (p_fog_volumes.size() > 0) {
RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog Volumes");
@ -623,9 +625,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
params.z_far = z_far;
params.time = p_settings.time;
params.fog_volume_size[0] = p_settings.vfog->width;
params.fog_volume_size[1] = p_settings.vfog->height;
params.fog_volume_size[2] = p_settings.vfog->depth;
params.fog_volume_size[0] = fog->width;
params.fog_volume_size[1] = fog->height;
params.fog_volume_size[2] = fog->depth;
params.use_temporal_reprojection = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env);
params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES;
@ -638,7 +640,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
RD::get_singleton()->buffer_update(volumetric_fog.volume_ubo, 0, sizeof(VolumetricFogShader::VolumeUBO), &params, RD::BARRIER_MASK_COMPUTE);
if (p_settings.vfog->fog_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->fog_uniform_set)) {
if (fog->fog_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(fog->fog_uniform_set)) {
Vector<RD::Uniform> uniforms;
{
@ -649,7 +651,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
#endif
u.binding = 1;
u.append_id(p_settings.vfog->emissive_map);
u.append_id(fog->emissive_map);
uniforms.push_back(u);
}
@ -669,7 +671,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
#endif
u.binding = 3;
u.append_id(p_settings.vfog->density_map);
u.append_id(fog->density_map);
uniforms.push_back(u);
}
@ -681,11 +683,11 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
#endif
u.binding = 4;
u.append_id(p_settings.vfog->light_map);
u.append_id(fog->light_map);
uniforms.push_back(u);
}
p_settings.vfog->fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
fog->fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
}
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
@ -731,7 +733,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
if (volume_type != RS::FOG_VOLUME_SHAPE_WORLD) {
// Local fog volume.
Vector3i points[8];
Vector3 fog_size = Vector3(p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
Vector3 fog_size = Vector3(fog->width, fog->height, fog->depth);
float volumetric_fog_detail_spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env);
points[0] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
points[1] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
@ -742,7 +744,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
points[6] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
points[7] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
min = Vector3i(int32_t(p_settings.vfog->width) - 1, int32_t(p_settings.vfog->height) - 1, int32_t(p_settings.vfog->depth) - 1);
min = Vector3i(int32_t(fog->width) - 1, int32_t(fog->height) - 1, int32_t(fog->depth) - 1);
max = Vector3i(1, 1, 1);
for (int j = 0; j < 8; j++) {
@ -753,9 +755,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
kernel_size = max - min;
} else {
// Volume type global runs on all cells
extents = Vector3(p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
extents = Vector3(fog->width, fog->height, fog->depth);
min = Vector3i(0, 0, 0);
kernel_size = Vector3i(int32_t(p_settings.vfog->width), int32_t(p_settings.vfog->height), int32_t(p_settings.vfog->depth));
kernel_size = Vector3i(int32_t(fog->width), int32_t(fog->height), int32_t(fog->depth));
}
if (kernel_size.x == 0 || kernel_size.y == 0 || kernel_size.z == 0) {
@ -777,7 +779,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shader_data->pipeline);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->fog_uniform_set, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->fog_uniform_set, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VolumetricFogShader::FogPushConstant));
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, volumetric_fog.base_uniform_set, VolumetricFogShader::FogSet::FOG_SET_BASE);
if (material->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material->uniform_set)) { // Material may not have a uniform set.
@ -795,7 +797,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
RD::get_singleton()->compute_list_end();
}
if (p_settings.vfog->process_uniform_set_density.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->process_uniform_set_density)) {
if (fog->process_uniform_set_density.is_null() || !RD::get_singleton()->uniform_set_is_valid(fog->process_uniform_set_density)) {
//re create uniform set if needed
Vector<RD::Uniform> uniforms;
Vector<RD::Uniform> copy_uniforms;
@ -875,7 +877,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 8;
u.append_id(p_settings.vfog->light_density_map);
u.append_id(fog->light_density_map);
uniforms.push_back(u);
copy_uniforms.push_back(u);
}
@ -884,7 +886,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 9;
u.append_id(p_settings.vfog->fog_map);
u.append_id(fog->fog_map);
uniforms.push_back(u);
}
@ -892,7 +894,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 9;
u.append_id(p_settings.vfog->prev_light_density_map);
u.append_id(fog->prev_light_density_map);
copy_uniforms.push_back(u);
}
@ -909,7 +911,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 11;
u.append_id(p_settings.voxel_gl_buffer);
u.append_id(p_settings.voxel_gi_buffer);
uniforms.push_back(u);
copy_uniforms.push_back(u);
}
@ -944,7 +946,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 15;
u.append_id(p_settings.vfog->prev_light_density_map);
u.append_id(fog->prev_light_density_map);
uniforms.push_back(u);
}
{
@ -955,7 +957,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
#endif
u.binding = 16;
u.append_id(p_settings.vfog->density_map);
u.append_id(fog->density_map);
uniforms.push_back(u);
}
{
@ -966,7 +968,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
#endif
u.binding = 17;
u.append_id(p_settings.vfog->light_map);
u.append_id(fog->light_map);
uniforms.push_back(u);
}
@ -978,7 +980,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
#endif
u.binding = 18;
u.append_id(p_settings.vfog->emissive_map);
u.append_id(fog->emissive_map);
uniforms.push_back(u);
}
@ -992,9 +994,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
uniforms.push_back(u);
}
p_settings.vfog->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->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);
p_settings.vfog->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->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);
@ -1002,17 +1004,17 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
uniforms.write[7].set_id(0, aux8);
uniforms.write[8].set_id(0, aux7);
p_settings.vfog->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->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);
p_settings.vfog->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->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);
}
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 != nullptr);
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());
if (using_sdfgi) {
if (p_settings.vfog->sdfgi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->sdfgi_uniform_set)) {
if (fog->sdfgi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(fog->sdfgi_uniform_set)) {
Vector<RD::Uniform> uniforms;
{
@ -1039,12 +1041,12 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
uniforms.push_back(u);
}
p_settings.vfog->sdfgi_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_DENSITY_WITH_SDFGI), 1);
fog->sdfgi_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_DENSITY_WITH_SDFGI), 1);
}
}
p_settings.vfog->length = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_length(p_settings.env);
p_settings.vfog->spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env);
fog->length = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_length(p_settings.env);
fog->spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env);
VolumetricFogShader::ParamsUBO params;
@ -1079,9 +1081,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
params.ambient_color[2] = ambient_color.b;
params.sky_contribution = RendererSceneRenderRD::get_singleton()->environment_get_ambient_sky_contribution(p_settings.env);
params.fog_volume_size[0] = p_settings.vfog->width;
params.fog_volume_size[1] = p_settings.vfog->height;
params.fog_volume_size[2] = p_settings.vfog->depth;
params.fog_volume_size[0] = fog->width;
params.fog_volume_size[1] = fog->height;
params.fog_volume_size[2] = fog->depth;
params.directional_light_count = p_directional_light_count;
@ -1149,19 +1151,19 @@ 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, p_settings.vfog->process_uniform_set_density, 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set_density, 0);
if (using_sdfgi) {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->sdfgi_uniform_set, 1);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->sdfgi_uniform_set, 1);
}
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth);
RD::get_singleton()->compute_list_add_barrier(compute_list);
// 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, p_settings.vfog->copy_uniform_set, 0);
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->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);
}
RD::get_singleton()->draw_command_end_label();
@ -1172,8 +1174,8 @@ 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, p_settings.vfog->process_uniform_set, 0);
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->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();
//need restart for buffer update
@ -1183,8 +1185,8 @@ 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, p_settings.vfog->process_uniform_set2, 0);
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->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);
RD::get_singleton()->draw_command_end_label();
@ -1194,8 +1196,8 @@ 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, p_settings.vfog->process_uniform_set, 0);
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, 1);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->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);

View File

@ -38,8 +38,11 @@
#include "servers/rendering/renderer_rd/environment/gi.h"
#include "servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl.gen.h"
#include "servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h"
#include "servers/rendering/storage/utilities.h"
#define RB_SCOPE_FOG SNAME("Fog")
namespace RendererRD {
class Fog : public RendererFog {
@ -261,7 +264,10 @@ public:
void fog_instance_free(RID p_rid);
/* Volumetric FOG */
struct VolumetricFog {
class VolumetricFog : public RenderBufferCustomDataRD {
GDCLASS(VolumetricFog, RenderBufferCustomDataRD)
public:
enum {
MAX_TEMPORAL_FRAMES = 16
};
@ -290,7 +296,10 @@ public:
int last_shadow_filter = -1;
VolumetricFog(const Vector3i &fog_size, RID p_sky_shader);
virtual void configure(RenderSceneBuffersRD *p_render_buffers) override{};
virtual void free_data() override{};
void init(const Vector3i &fog_size, RID p_sky_shader);
~VolumetricFog();
};
@ -304,7 +313,7 @@ public:
uint32_t max_cluster_elements;
bool volumetric_fog_filter_active;
RID shadow_sampler;
RID voxel_gl_buffer;
RID voxel_gi_buffer;
RID shadow_atlas_depth;
RID omni_light_buffer;
RID spot_light_buffer;
@ -312,11 +321,11 @@ public:
RID directional_light_buffer;
// Objects related to our render buffer
VolumetricFog *vfog;
Ref<VolumetricFog> vfog;
ClusterBuilderRD *cluster_builder;
GI *gi;
GI::SDFGI *sdfgi;
GI::RenderBuffersGI *rbgi;
Ref<GI::SDFGI> sdfgi;
Ref<GI::RenderBuffersGI> rbgi;
RID env;
SkyRD *sky;
};

View File

@ -34,6 +34,7 @@
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_default.h"
@ -384,6 +385,13 @@ RID GI::voxel_gi_get_sdf_texture(RID p_voxel_gi) {
return voxel_gi->sdf_texture;
}
Dependency *GI::voxel_gi_get_dependency(RID p_voxel_gi) const {
VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND_V(!voxel_gi, nullptr);
return &voxel_gi->dependency;
}
////////////////////////////////////////////////////////////////////////////////
// SDFGI
@ -1121,7 +1129,11 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re
reads_sky = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_read_sky_light(p_env);
}
void GI::SDFGI::erase() {
void GI::SDFGI::free_data() {
// we don't free things here, we handle SDFGI differently at the moment destructing the object when it needs to change.
}
GI::SDFGI::~SDFGI() {
for (uint32_t i = 0; i < cascades.size(); i++) {
const SDFGI::Cascade &c = cascades[i];
RD::get_singleton()->free(c.light_data);
@ -1982,10 +1994,9 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r
}
}
void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render, float p_exposure_normalization) {
void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render, float p_exposure_normalization) {
//print_line("rendering region " + itos(p_region));
RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but...
ERR_FAIL_COND(p_render_buffers.is_null()); // we wouldn't be here if this failed but...
AABB bounds;
Vector3i from;
Vector3i size;
@ -2342,9 +2353,8 @@ void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArr
}
}
void GI::SDFGI::render_static_lights(RenderDataRD *p_render_data, RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render) {
RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but...
void GI::SDFGI::render_static_lights(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render) {
ERR_FAIL_COND(p_render_buffers.is_null()); // we wouldn't be here if this failed but...
RD::get_singleton()->draw_command_begin_label("SDFGI Render Static Lights");
@ -3572,25 +3582,27 @@ void GI::free() {
}
}
GI::SDFGI *GI::create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size) {
SDFGI *sdfgi = memnew(SDFGI);
Ref<GI::SDFGI> GI::create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size) {
Ref<SDFGI> sdfgi;
sdfgi.instantiate();
sdfgi->create(p_env, p_world_position, p_requested_history_size, this);
return sdfgi;
}
void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render) {
void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render) {
ERR_FAIL_COND(p_render_buffers.is_null());
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
ERR_FAIL_NULL(texture_storage);
r_voxel_gi_instances_used = 0;
// feels a little dirty to use our container this way but....
RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(rb == nullptr);
RID voxel_gi_buffer = p_scene_render->render_buffers_get_voxel_gi_buffer(p_render_buffers);
Ref<RenderBuffersGI> rbgi = p_render_buffers->get_custom_data(RB_SCOPE_GI);
ERR_FAIL_COND(rbgi.is_null());
RID voxel_gi_buffer = rbgi->get_voxel_gi_buffer();
VoxelGIData voxel_gi_data[MAX_VOXEL_GI_INSTANCES];
bool voxel_gi_instances_changed = false;
@ -3601,7 +3613,7 @@ void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, RID p_render_buff
for (int i = 0; i < MAX_VOXEL_GI_INSTANCES; i++) {
RID texture;
if (i < (int)p_voxel_gi_instances.size()) {
VoxelGIInstance *gipi = get_probe_instance(p_voxel_gi_instances[i]);
VoxelGIInstance *gipi = voxel_gi_instance_owner.get_or_null(p_voxel_gi_instances[i]);
if (gipi) {
texture = gipi->texture;
@ -3653,28 +3665,30 @@ void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, RID p_render_buff
texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
}
if (texture != rb->rbgi.voxel_gi_textures[i]) {
if (texture != rbgi->voxel_gi_textures[i]) {
voxel_gi_instances_changed = true;
rb->rbgi.voxel_gi_textures[i] = texture;
rbgi->voxel_gi_textures[i] = texture;
}
}
if (voxel_gi_instances_changed) {
for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {
if (RD::get_singleton()->uniform_set_is_valid(rb->rbgi.uniform_set[v])) {
RD::get_singleton()->free(rb->rbgi.uniform_set[v]);
if (RD::get_singleton()->uniform_set_is_valid(rbgi->uniform_set[v])) {
RD::get_singleton()->free(rbgi->uniform_set[v]);
}
rb->rbgi.uniform_set[v] = RID();
rbgi->uniform_set[v] = RID();
}
if (rb->volumetric_fog) {
if (RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->fog_uniform_set)) {
RD::get_singleton()->free(rb->volumetric_fog->fog_uniform_set);
RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set);
RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set2);
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);
}
rb->volumetric_fog->fog_uniform_set = RID();
rb->volumetric_fog->process_uniform_set = RID();
rb->volumetric_fog->process_uniform_set2 = RID();
fog->fog_uniform_set = RID();
fog->process_uniform_set = RID();
fog->process_uniform_set2 = RID();
}
}
@ -3687,7 +3701,14 @@ void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, RID p_render_buff
}
}
void GI::RenderBuffersGI::free() {
RID GI::RenderBuffersGI::get_voxel_gi_buffer() {
if (voxel_gi_buffer.is_null()) {
voxel_gi_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(GI::VoxelGIData) * GI::MAX_VOXEL_GI_INSTANCES);
}
return voxel_gi_buffer;
}
void GI::RenderBuffersGI::free_data() {
for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {
if (RD::get_singleton()->uniform_set_is_valid(uniform_set[v])) {
RD::get_singleton()->free(uniform_set[v]);
@ -3700,28 +3721,13 @@ void GI::RenderBuffersGI::free() {
scene_data_ubo = RID();
}
if (ambient_buffer.is_valid()) {
RD::get_singleton()->free(ambient_buffer);
RD::get_singleton()->free(reflection_buffer);
ambient_buffer = RID();
reflection_buffer = RID();
// these are automatically freed when we free the textures, so just reset..
for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {
ambient_slice[v] = RID();
reflection_slice[v] = RID();
}
view_count = 0;
}
if (voxel_gi_buffer.is_valid()) {
RD::get_singleton()->free(voxel_gi_buffer);
voxel_gi_buffer = RID();
}
}
void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) {
void GI::process_gi(Ref<RenderSceneBuffersRD> p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
@ -3729,65 +3735,38 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
RD::get_singleton()->draw_command_begin_label("GI Render");
RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(rb == nullptr);
ERR_FAIL_COND(p_render_buffers.is_null());
if (rb->rbgi.ambient_buffer.is_null() || rb->rbgi.using_half_size_gi != half_resolution || rb->rbgi.view_count != p_view_count) {
// Free our old buffer if applicable
if (rb->rbgi.ambient_buffer.is_valid()) {
RD::get_singleton()->free(rb->rbgi.ambient_buffer);
RD::get_singleton()->free(rb->rbgi.reflection_buffer);
Ref<RenderBuffersGI> rbgi = p_render_buffers->get_custom_data(RB_SCOPE_GI);
ERR_FAIL_COND(rbgi.is_null());
for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {
rb->rbgi.ambient_slice[v] = RID();
rb->rbgi.reflection_slice[v] = RID();
}
}
Size2i internal_size = p_render_buffers->get_internal_size();
// Remember the view count we're using
rb->rbgi.view_count = p_view_count;
if (rbgi->using_half_size_gi != half_resolution) {
p_render_buffers->clear_context(RB_SCOPE_GI);
}
if (!p_render_buffers->has_texture(RB_SCOPE_GI, RB_TEX_AMBIENT)) {
Size2i size = internal_size;
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
// Create textures for our ambient and reflection data
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
tf.width = rb->internal_width;
tf.height = rb->internal_height;
if (half_resolution) {
tf.width >>= 1;
tf.height >>= 1;
size.x >>= 1;
size.y >>= 1;
}
if (p_view_count > 1) {
tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
tf.array_layers = p_view_count;
} else {
tf.texture_type = RD::TEXTURE_TYPE_2D;
tf.array_layers = 1;
}
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
rb->rbgi.ambient_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
RD::get_singleton()->set_resource_name(rb->rbgi.ambient_buffer, "GI Ambient Buffer");
rb->rbgi.reflection_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
RD::get_singleton()->set_resource_name(rb->rbgi.reflection_buffer, "GI Reflection Buffer");
rb->rbgi.using_half_size_gi = half_resolution;
if (p_view_count == 1) {
// Just copy, we don't need to create slices
rb->rbgi.ambient_slice[0] = rb->rbgi.ambient_buffer;
rb->rbgi.reflection_slice[0] = rb->rbgi.reflection_buffer;
} else {
for (uint32_t v = 0; v < p_view_count; v++) {
rb->rbgi.ambient_slice[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.ambient_buffer, v, 0);
rb->rbgi.reflection_slice[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.reflection_buffer, v, 0);
}
}
p_render_buffers->create_texture(RB_SCOPE_GI, RB_TEX_AMBIENT, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, usage_bits, RD::TEXTURE_SAMPLES_1, size);
p_render_buffers->create_texture(RB_SCOPE_GI, RB_TEX_REFLECTION, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, usage_bits, RD::TEXTURE_SAMPLES_1, size);
rbgi->using_half_size_gi = half_resolution;
}
// Setup our scene data
{
SceneData scene_data;
if (rb->rbgi.scene_data_ubo.is_null()) {
rb->rbgi.scene_data_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SceneData));
if (rbgi->scene_data_ubo.is_null()) {
rbgi->scene_data_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SceneData));
}
for (uint32_t v = 0; v < p_view_count; v++) {
@ -3801,10 +3780,10 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
// Note that we will be ignoring the origin of this transform.
RendererRD::MaterialStorage::store_transform(p_cam_transform, scene_data.cam_transform);
scene_data.screen_size[0] = rb->internal_width;
scene_data.screen_size[1] = rb->internal_height;
scene_data.screen_size[0] = internal_size.x;
scene_data.screen_size[1] = internal_size.y;
RD::get_singleton()->buffer_update(rb->rbgi.scene_data_ubo, 0, sizeof(SceneData), &scene_data, RD::BARRIER_MASK_COMPUTE);
RD::get_singleton()->buffer_update(rbgi->scene_data_ubo, 0, sizeof(SceneData), &scene_data, RD::BARRIER_MASK_COMPUTE);
}
// Now compute the contents of our buffers.
@ -3826,22 +3805,28 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
push_constant.z_far = p_projections[0].get_z_far();
// these are only used if we have 1 view, else we use the projections in our scene data
push_constant.proj_info[0] = -2.0f / (rb->internal_width * p_projections[0].matrix[0][0]);
push_constant.proj_info[1] = -2.0f / (rb->internal_height * p_projections[0].matrix[1][1]);
push_constant.proj_info[0] = -2.0f / (internal_size.x * p_projections[0].matrix[0][0]);
push_constant.proj_info[1] = -2.0f / (internal_size.y * p_projections[0].matrix[1][1]);
push_constant.proj_info[2] = (1.0f - p_projections[0].matrix[0][2]) / p_projections[0].matrix[0][0];
push_constant.proj_info[3] = (1.0f + p_projections[0].matrix[1][2]) / p_projections[0].matrix[1][1];
bool use_sdfgi = rb->sdfgi != nullptr;
bool use_sdfgi = p_render_buffers->has_custom_data(RB_SCOPE_SDFGI);
bool use_voxel_gi_instances = push_constant.max_voxel_gi_instances > 0;
Ref<SDFGI> sdfgi;
if (use_sdfgi) {
sdfgi = p_render_buffers->get_custom_data(RB_SCOPE_SDFGI);
}
uint32_t pipeline_specialization = 0;
if (rb->rbgi.using_half_size_gi) {
if (rbgi->using_half_size_gi) {
pipeline_specialization |= SHADER_SPECIALIZATION_HALF_RES;
}
if (p_view_count > 1) {
pipeline_specialization |= SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX;
}
if (p_vrs_slices[0].is_valid()) {
bool has_vrs_texture = p_render_buffers->has_texture(RB_SCOPE_VRS, RB_TEXTURE);
if (has_vrs_texture) {
pipeline_specialization |= SHADER_SPECIALIZATION_USE_VRS;
}
@ -3851,15 +3836,15 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
push_constant.view_index = v;
// setup our uniform set
if (rb->rbgi.uniform_set[v].is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->rbgi.uniform_set[v])) {
if (rbgi->uniform_set[v].is_null() || !RD::get_singleton()->uniform_set_is_valid(rbgi->uniform_set[v])) {
Vector<RD::Uniform> uniforms;
{
RD::Uniform u;
u.binding = 1;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
u.append_id(rb->sdfgi->cascades[j].sdf_tex);
if (use_sdfgi && j < sdfgi->cascades.size()) {
u.append_id(sdfgi->cascades[j].sdf_tex);
} else {
u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
}
@ -3871,8 +3856,8 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
u.binding = 2;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
u.append_id(rb->sdfgi->cascades[j].light_tex);
if (use_sdfgi && j < sdfgi->cascades.size()) {
u.append_id(sdfgi->cascades[j].light_tex);
} else {
u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
}
@ -3884,8 +3869,8 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
u.binding = 3;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
u.append_id(rb->sdfgi->cascades[j].light_aniso_0_tex);
if (use_sdfgi && j < sdfgi->cascades.size()) {
u.append_id(sdfgi->cascades[j].light_aniso_0_tex);
} else {
u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
}
@ -3897,8 +3882,8 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
u.binding = 4;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
u.append_id(rb->sdfgi->cascades[j].light_aniso_1_tex);
if (use_sdfgi && j < sdfgi->cascades.size()) {
u.append_id(sdfgi->cascades[j].light_aniso_1_tex);
} else {
u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
}
@ -3909,8 +3894,8 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 5;
if (rb->sdfgi) {
u.append_id(rb->sdfgi->occlusion_texture);
if (use_sdfgi) {
u.append_id(sdfgi->occlusion_texture);
} else {
u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
}
@ -3935,7 +3920,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 9;
u.append_id(rb->rbgi.ambient_slice[v]);
u.append_id(p_render_buffers->get_texture_slice(RB_SCOPE_GI, RB_TEX_AMBIENT, v, 0));
uniforms.push_back(u);
}
@ -3943,7 +3928,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 10;
u.append_id(rb->rbgi.reflection_slice[v]);
u.append_id(p_render_buffers->get_texture_slice(RB_SCOPE_GI, RB_TEX_REFLECTION, v, 0));
uniforms.push_back(u);
}
@ -3951,8 +3936,8 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 11;
if (rb->sdfgi) {
u.append_id(rb->sdfgi->lightprobe_texture);
if (use_sdfgi) {
u.append_id(sdfgi->lightprobe_texture);
} else {
u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE));
}
@ -3962,7 +3947,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 12;
u.append_id(rb->views[v].view_depth);
u.append_id(p_render_buffers->get_depth_texture(v));
uniforms.push_back(u);
}
{
@ -3991,7 +3976,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 16;
u.append_id(rb->rbgi.voxel_gi_buffer);
u.append_id(rbgi->get_voxel_gi_buffer());
uniforms.push_back(u);
}
{
@ -3999,7 +3984,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 17;
for (int i = 0; i < MAX_VOXEL_GI_INSTANCES; i++) {
u.append_id(rb->rbgi.voxel_gi_textures[i]);
u.append_id(rbgi->voxel_gi_textures[i]);
}
uniforms.push_back(u);
}
@ -4007,29 +3992,29 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 18;
u.append_id(rb->rbgi.scene_data_ubo);
u.append_id(rbgi->scene_data_ubo);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 19;
RID buffer = p_vrs_slices[v].is_valid() ? p_vrs_slices[v] : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_VRS);
RID buffer = has_vrs_texture ? p_render_buffers->get_texture_slice(RB_SCOPE_VRS, RB_TEXTURE, v, 0) : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_VRS);
u.append_id(buffer);
uniforms.push_back(u);
}
rb->rbgi.uniform_set[v] = RD::get_singleton()->uniform_set_create(uniforms, shader.version_get_shader(shader_version, 0), 0);
rbgi->uniform_set[v] = RD::get_singleton()->uniform_set_create(uniforms, shader.version_get_shader(shader_version, 0), 0);
}
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipelines[pipeline_specialization][mode]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->rbgi.uniform_set[v], 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rbgi->uniform_set[v], 0);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant));
if (rb->rbgi.using_half_size_gi) {
RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width >> 1, rb->internal_height >> 1, 1);
if (rbgi->using_half_size_gi) {
RD::get_singleton()->compute_list_dispatch_threads(compute_list, internal_size.x >> 1, internal_size.y >> 1, 1);
} else {
RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width, rb->internal_height, 1);
RD::get_singleton()->compute_list_dispatch_threads(compute_list, internal_size.x, internal_size.y, 1);
}
}
@ -4053,21 +4038,21 @@ void GI::voxel_gi_instance_free(RID p_rid) {
}
void GI::voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) {
VoxelGIInstance *voxel_gi = get_probe_instance(p_probe);
VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);
ERR_FAIL_COND(!voxel_gi);
voxel_gi->transform = p_xform;
}
bool GI::voxel_gi_needs_update(RID p_probe) const {
VoxelGIInstance *voxel_gi = get_probe_instance(p_probe);
VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);
ERR_FAIL_COND_V(!voxel_gi, false);
return voxel_gi->last_probe_version != voxel_gi_get_version(voxel_gi->probe);
}
void GI::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) {
VoxelGIInstance *voxel_gi = get_probe_instance(p_probe);
VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);
ERR_FAIL_COND(!voxel_gi);
voxel_gi->update(p_update_light_instances, p_light_instances, p_dynamic_objects, p_scene_render);

View File

@ -44,10 +44,17 @@
#include "servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/environment/voxel_gi.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/environment/voxel_gi_debug.glsl.gen.h"
#include "servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_device.h"
#include "servers/rendering/storage/utilities.h"
#define RB_SCOPE_GI SNAME("rbgi")
#define RB_SCOPE_SDFGI SNAME("sdfgi")
#define RB_TEX_AMBIENT SNAME("ambient")
#define RB_TEX_REFLECTION SNAME("reflection")
// Forward declare RenderDataRD and RendererSceneRenderRD so we can pass it into some of our methods, these classes are pretty tightly bound
struct RenderDataRD;
class RendererSceneRenderRD;
@ -89,6 +96,60 @@ public:
Dependency dependency;
};
/* VOXEL_GI INSTANCE */
//@TODO VoxelGIInstance is still directly used in the render code, we'll address this when we refactor the render code itself.
struct VoxelGIInstance {
// access to our containers
GI *gi = nullptr;
RID probe;
RID texture;
RID write_buffer;
struct Mipmap {
RID texture;
RID uniform_set;
RID second_bounce_uniform_set;
RID write_uniform_set;
uint32_t level;
uint32_t cell_offset;
uint32_t cell_count;
};
Vector<Mipmap> mipmaps;
struct DynamicMap {
RID texture; //color normally, or emission on first pass
RID fb_depth; //actual depth buffer for the first pass, float depth for later passes
RID depth; //actual depth buffer for the first pass, float depth for later passes
RID normal; //normal buffer for the first pass
RID albedo; //emission buffer for the first pass
RID orm; //orm buffer for the first pass
RID fb; //used for rendering, only valid on first map
RID uniform_set;
uint32_t size;
int mipmap; // mipmap to write to, -1 if no mipmap assigned
};
Vector<DynamicMap> dynamic_maps;
int slot = -1;
uint32_t last_probe_version = 0;
uint32_t last_probe_data_version = 0;
//uint64_t last_pass = 0;
uint32_t render_index = 0;
bool has_dynamic_object_data = false;
Transform3D transform;
void update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render);
void debug(RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
void free_resources();
};
private:
static GI *singleton;
@ -98,6 +159,8 @@ private:
/* VOXEL_GI INSTANCE */
mutable RID_Owner<VoxelGIInstance> voxel_gi_instance_owner;
struct VoxelGILight {
uint32_t type;
float energy;
@ -370,9 +433,40 @@ private:
public:
static GI *get_singleton() { return singleton; }
/* GI */
enum {
MAX_VOXEL_GI_INSTANCES = 8
};
// Struct for use in render buffer
class RenderBuffersGI : public RenderBufferCustomDataRD {
GDCLASS(RenderBuffersGI, RenderBufferCustomDataRD)
private:
RID voxel_gi_buffer;
public:
RID voxel_gi_textures[MAX_VOXEL_GI_INSTANCES];
RID full_buffer;
RID full_dispatch;
RID full_mask;
/* GI buffers */
bool using_half_size_gi = false;
RID uniform_set[RendererSceneRender::MAX_RENDER_VIEWS];
RID scene_data_ubo;
RID get_voxel_gi_buffer();
virtual void configure(RenderSceneBuffersRD *p_render_buffers) override{};
virtual void free_data() override;
};
/* VOXEL GI API */
VoxelGI *get_voxel_gi(RID p_rid) { return voxel_gi_owner.get_or_null(p_rid); };
bool owns_voxel_gi(RID p_rid) { return voxel_gi_owner.owns(p_rid); };
virtual RID voxel_gi_allocate() override;
@ -422,72 +516,23 @@ public:
RID voxel_gi_get_sdf_texture(RID p_voxel_gi);
Dependency *voxel_gi_get_dependency(RID p_voxel_gi) const;
/* VOXEL_GI INSTANCE */
//@TODO VoxelGIInstance is still directly used in the render code, we'll address this when we refactor the render code itself.
struct VoxelGIInstance {
// access to our containers
GI *gi = nullptr;
RID probe;
RID texture;
RID write_buffer;
struct Mipmap {
RID texture;
RID uniform_set;
RID second_bounce_uniform_set;
RID write_uniform_set;
uint32_t level;
uint32_t cell_offset;
uint32_t cell_count;
};
Vector<Mipmap> mipmaps;
struct DynamicMap {
RID texture; //color normally, or emission on first pass
RID fb_depth; //actual depth buffer for the first pass, float depth for later passes
RID depth; //actual depth buffer for the first pass, float depth for later passes
RID normal; //normal buffer for the first pass
RID albedo; //emission buffer for the first pass
RID orm; //orm buffer for the first pass
RID fb; //used for rendering, only valid on first map
RID uniform_set;
uint32_t size;
int mipmap; // mipmap to write to, -1 if no mipmap assigned
};
Vector<DynamicMap> dynamic_maps;
int slot = -1;
uint32_t last_probe_version = 0;
uint32_t last_probe_data_version = 0;
//uint64_t last_pass = 0;
uint32_t render_index = 0;
bool has_dynamic_object_data = false;
Transform3D transform;
void update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render);
void debug(RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
void free_resources();
};
mutable RID_Owner<VoxelGIInstance> voxel_gi_instance_owner;
_FORCE_INLINE_ VoxelGIInstance *get_probe_instance(RID p_probe) const {
return voxel_gi_instance_owner.get_or_null(p_probe);
};
_FORCE_INLINE_ RID voxel_gi_instance_get_texture(RID p_probe) {
VoxelGIInstance *voxel_gi = get_probe_instance(p_probe);
VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);
ERR_FAIL_COND_V(!voxel_gi, RID());
return voxel_gi->texture;
};
_FORCE_INLINE_ void voxel_gi_instance_set_render_index(RID p_probe, uint32_t p_index) {
VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);
ERR_FAIL_NULL(voxel_gi);
voxel_gi->render_index = p_index;
};
bool voxel_gi_instance_owns(RID p_rid) const {
return voxel_gi_instance_owner.owns(p_rid);
}
@ -498,7 +543,10 @@ public:
/* SDFGI */
struct SDFGI {
class SDFGI : public RenderBufferCustomDataRD {
GDCLASS(SDFGI, RenderBufferCustomDataRD)
public:
enum {
MAX_CASCADES = 8,
CASCADE_SIZE = 128,
@ -624,8 +672,11 @@ public:
int32_t cascade_dynamic_light_count[SDFGI::MAX_CASCADES]; //used dynamically
RID integrate_sky_uniform_set;
virtual void configure(RenderSceneBuffersRD *p_render_buffers) override{};
virtual void free_data() override;
~SDFGI();
void create(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, GI *p_gi);
void erase();
void update(RID p_env, const Vector3 &p_world_position);
void update_light();
void update_probes(RID p_env, RendererRD::SkyRD::Sky *p_sky);
@ -637,8 +688,8 @@ public:
void debug_probes(RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth);
void pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data, RendererSceneRenderRD *p_scene_render);
void render_region(RID p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render, float p_exposure_normalization);
void render_static_lights(RenderDataRD *p_render_data, RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render);
void render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render, float p_exposure_normalization);
void render_static_lights(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render);
};
RS::EnvironmentSDFGIRayCount sdfgi_ray_count = RS::ENV_SDFGI_RAY_COUNT_16;
@ -655,34 +706,6 @@ public:
int sdfgi_get_lightprobe_octahedron_size() const { return SDFGI::LIGHTPROBE_OCT_SIZE; }
/* GI */
enum {
MAX_VOXEL_GI_INSTANCES = 8
};
// Struct for use in render buffer
struct RenderBuffersGI {
RID voxel_gi_textures[MAX_VOXEL_GI_INSTANCES];
RID voxel_gi_buffer;
RID full_buffer;
RID full_dispatch;
RID full_mask;
/* GI buffers */
RID ambient_buffer;
RID ambient_slice[RendererSceneRender::MAX_RENDER_VIEWS];
RID reflection_buffer;
RID reflection_slice[RendererSceneRender::MAX_RENDER_VIEWS];
bool using_half_size_gi = false;
uint32_t view_count = 1;
RID uniform_set[RendererSceneRender::MAX_RENDER_VIEWS];
RID scene_data_ubo;
void free();
};
struct SDFGIData {
float grid_size[3];
uint32_t max_cascades;
@ -787,10 +810,10 @@ public:
void init(RendererRD::SkyRD *p_sky);
void free();
SDFGI *create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size);
Ref<SDFGI> create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size);
void setup_voxel_gi_instances(RenderDataRD *p_render_data, RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render);
void process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render);
void setup_voxel_gi_instances(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render);
void process_gi(Ref<RenderSceneBuffersRD> p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances);
RID voxel_gi_instance_create(RID p_base);
void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform);

View File

@ -35,6 +35,7 @@
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_default.h"
#include "servers/rendering/rendering_server_globals.h"
@ -1109,7 +1110,7 @@ SkyRD::~SkyRD() {
RD::get_singleton()->free(index_buffer); //array gets freed as dependency
}
void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) {
void SkyRD::setup(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) {
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(p_env.is_null());
@ -1294,24 +1295,25 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh
//setup fog variables
sky_scene_state.ubo.volumetric_fog_enabled = false;
if (p_render_buffers.is_valid()) {
if (p_scene_render->render_buffers_has_volumetric_fog(p_render_buffers)) {
if (p_render_buffers->has_custom_data(RB_SCOPE_FOG)) {
Ref<RendererRD::Fog::VolumetricFog> fog = p_render_buffers->get_custom_data(RB_SCOPE_FOG);
sky_scene_state.ubo.volumetric_fog_enabled = true;
float fog_end = p_scene_render->render_buffers_get_volumetric_fog_end(p_render_buffers);
float fog_end = fog->length;
if (fog_end > 0.0) {
sky_scene_state.ubo.volumetric_fog_inv_length = 1.0 / fog_end;
} else {
sky_scene_state.ubo.volumetric_fog_inv_length = 1.0;
}
float fog_detail_spread = p_scene_render->render_buffers_get_volumetric_fog_detail_spread(p_render_buffers); //reverse lookup
float fog_detail_spread = fog->spread; //reverse lookup
if (fog_detail_spread > 0.0) {
sky_scene_state.ubo.volumetric_fog_detail_spread = 1.0 / fog_detail_spread;
} else {
sky_scene_state.ubo.volumetric_fog_detail_spread = 1.0;
}
sky_scene_state.fog_uniform_set = p_scene_render->render_buffers_get_volumetric_fog_sky_uniform_set(p_render_buffers);
sky_scene_state.fog_uniform_set = fog->sky_uniform_set;
}
}

View File

@ -42,6 +42,7 @@
// Forward declare RendererSceneRenderRD so we can pass it into some of our methods, these classes are pretty tightly bound
class RendererSceneRenderRD;
class RenderSceneBuffersRD;
namespace RendererRD {
@ -296,7 +297,7 @@ public:
void set_texture_format(RD::DataFormat p_texture_format);
~SkyRD();
void setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render);
void setup(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render);
void update(RID p_env, const Projection &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
void draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); // only called by clustered renderer
void update_res_buffers(RID p_env, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);

View File

@ -33,12 +33,22 @@
#include "core/templates/paged_allocator.h"
#include "servers/rendering/renderer_rd/effects/resolve.h"
#include "servers/rendering/renderer_rd/effects/taa.h"
#include "servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h"
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
#include "servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl.gen.h"
#include "servers/rendering/renderer_rd/storage_rd/utilities.h"
#define RB_SCOPE_FORWARD_CLUSTERED SNAME("forward_clustered")
#define RB_TEX_SPECULAR SNAME("specular")
#define RB_TEX_SPECULAR_MSAA SNAME("specular_msaa")
#define RB_TEX_ROUGHNESS SNAME("normal_roughnesss")
#define RB_TEX_ROUGHNESS_MSAA SNAME("normal_roughnesss_msaa")
#define RB_TEX_VOXEL_GI SNAME("voxel_gi")
#define RB_TEX_VOXEL_GI_MSAA SNAME("voxel_gi_msaa")
namespace RendererSceneRenderImplementation {
class RenderForwardClustered : public RendererSceneRenderRD {
@ -81,73 +91,67 @@ class RenderForwardClustered : public RendererSceneRenderRD {
/* Framebuffer */
struct RenderBufferDataForwardClustered : public RenderBufferData {
class RenderBufferDataForwardClustered : public RenderBufferCustomDataRD {
GDCLASS(RenderBufferDataForwardClustered, RenderBufferCustomDataRD)
private:
RenderSceneBuffersRD *render_buffers = nullptr;
RD::TextureSamples texture_samples = RD::TEXTURE_SAMPLES_1;
public:
//for rendering, may be MSAAd
RID color;
RID depth;
RID specular;
RID normal_roughness_buffer;
RID voxelgi_buffer;
RID velocity_buffer;
RS::ViewportMSAA msaa;
RD::TextureSamples texture_samples;
bool use_taa;
RID color_msaa;
RID depth_msaa;
RID specular_msaa;
RID normal_roughness_buffer_msaa;
RID voxelgi_buffer_msaa;
RID velocity_buffer_msaa;
RID depth_fb;
RID depth_normal_roughness_fb;
RID depth_normal_roughness_voxelgi_fb;
RID color_only_fb;
RID specular_only_fb;
RID vrs;
int width, height;
HashMap<uint32_t, RID> color_framebuffers;
// for multiview
uint32_t view_count = 1;
RID color_views[RendererSceneRender::MAX_RENDER_VIEWS]; // we should rewrite this so we get access to the existing views in our renderer, something we can address when we reorg this
RID depth_views[RendererSceneRender::MAX_RENDER_VIEWS]; // we should rewrite this so we get access to the existing views in our renderer, something we can address when we reorg this
RID specular_views[RendererSceneRender::MAX_RENDER_VIEWS];
RID specular_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
RID color_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
RID depth_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
RID normal_roughness_views[RendererSceneRender::MAX_RENDER_VIEWS];
RID normal_roughness_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
RID voxelgi_views[RendererSceneRender::MAX_RENDER_VIEWS];
RID voxelgi_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
RID vrs_views[RendererSceneRender::MAX_RENDER_VIEWS];
enum DepthFrameBufferType {
DEPTH_FB,
DEPTH_FB_ROUGHNESS,
DEPTH_FB_ROUGHNESS_VOXELGI
};
RID render_sdfgi_uniform_set;
void ensure_specular();
void ensure_voxelgi();
void ensure_velocity();
void clear();
virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture);
RID get_color_pass_fb(uint32_t p_color_pass_flags);
~RenderBufferDataForwardClustered();
RID get_color_msaa() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_COLOR_MSAA); }
RID get_color_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_COLOR_MSAA, p_layer, 0); }
RID get_depth_msaa() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_DEPTH_MSAA); }
RID get_depth_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_DEPTH_MSAA, p_layer, 0); }
void ensure_specular();
bool has_specular() const { return render_buffers->has_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR); }
RID get_specular() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR); }
RID get_specular(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR, p_layer, 0); }
RID get_specular_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR_MSAA, p_layer, 0); }
void ensure_normal_roughness_texture();
bool has_normal_roughness() const { return render_buffers->has_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS); }
RID get_normal_roughness() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS); }
RID get_normal_roughness(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS, p_layer, 0); }
RID get_normal_roughness_msaa() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS_MSAA); }
RID get_normal_roughness_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS_MSAA, p_layer, 0); }
void ensure_voxelgi();
bool has_voxelgi() const { return render_buffers->has_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI); }
RID get_voxelgi() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI); }
RID get_voxelgi(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI, p_layer, 0); }
RID get_voxelgi_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI_MSAA, p_layer, 0); }
RID get_color_only_fb();
RID get_color_pass_fb(uint32_t p_color_pass_flags);
RID get_depth_fb(DepthFrameBufferType p_type = DEPTH_FB);
RID get_specular_only_fb();
virtual void configure(RenderSceneBuffersRD *p_render_buffers) override;
virtual void free_data() override;
};
virtual RenderBufferData *_create_render_buffer_data() override;
void _allocate_normal_roughness_texture(RenderBufferDataForwardClustered *rb);
virtual void setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) override;
RID render_base_uniform_set;
uint64_t lightmap_texture_array_version = 0xFFFFFFFF;
virtual void _base_uniforms_changed() override;
virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) override;
virtual RID _render_buffers_get_velocity_texture(RID p_render_buffers) override;
virtual RID _render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override;
virtual RID _render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override;
bool base_uniform_set_updated = false;
void _update_render_base_uniform_set();
@ -612,6 +616,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
virtual void _update_shader_quality_settings() override;
RendererRD::Resolve *resolve_effects = nullptr;
RendererRD::TAA *taa = nullptr;
protected:
virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override;
@ -623,7 +628,7 @@ protected:
virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) override;
virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override;
virtual void _render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override;
virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) override;
public:

View File

@ -69,102 +69,28 @@ void RenderForwardMobile::_map_forward_id(ForwardIDType p_type, ForwardID p_id,
/* Render buffer */
void RenderForwardMobile::RenderBufferDataForwardMobile::clear() {
if (color_msaa.is_valid()) {
RD::get_singleton()->free(color_msaa);
color_msaa = RID();
}
if (depth_msaa.is_valid()) {
RD::get_singleton()->free(depth_msaa);
depth_msaa = RID();
}
color = RID();
depth = RID();
for (int i = 0; i < FB_CONFIG_MAX; i++) {
color_fbs[i] = RID();
void RenderForwardMobile::RenderBufferDataForwardMobile::free_data() {
// this should already be done but JIC..
if (render_buffers) {
render_buffers->clear_context(RB_SCOPE_MOBILE);
}
}
void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture) {
clear();
void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RenderSceneBuffersRD *p_render_buffers) {
if (render_buffers) {
// JIC
free_data();
}
msaa = p_msaa;
vrs = p_vrs_texture;
render_buffers = p_render_buffers;
ERR_FAIL_NULL(render_buffers); // Huh? really?
Size2i target_size = RD::get_singleton()->texture_size(p_target_buffer);
RS::ViewportMSAA msaa_3d = render_buffers->get_msaa_3d();
if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED) {
// Create our MSAA textures...
width = p_width;
height = p_height;
bool is_scaled = (target_size.width != p_width) || (target_size.height != p_height);
view_count = p_view_count;
color = p_color_buffer;
depth = p_depth_buffer;
// We are creating 4 configurations here for our framebuffers.
if (p_msaa == RS::VIEWPORT_MSAA_DISABLED) {
Vector<RID> fb;
fb.push_back(p_color_buffer); // 0 - color buffer
fb.push_back(depth); // 1 - depth buffer
if (vrs.is_valid()) {
fb.push_back(vrs); // 2 - vrs texture
}
// Now define our subpasses
Vector<RD::FramebufferPass> passes;
RD::FramebufferPass pass;
// re-using the same attachments
pass.color_attachments.push_back(0);
pass.depth_attachment = 1;
if (vrs.is_valid()) {
pass.vrs_attachment = 2;
}
// - opaque pass
passes.push_back(pass);
color_fbs[FB_CONFIG_ONE_PASS] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
// - add sky pass
passes.push_back(pass);
color_fbs[FB_CONFIG_TWO_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
// - add alpha pass
passes.push_back(pass);
color_fbs[FB_CONFIG_THREE_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
if (!is_scaled) {
// - add blit to 2D pass
int target_buffer_id = fb.size();
fb.push_back(p_target_buffer); // 2/3 - target buffer
RD::FramebufferPass blit_pass;
blit_pass.color_attachments.push_back(target_buffer_id);
blit_pass.input_attachments.push_back(0);
passes.push_back(blit_pass); // this doesn't need VRS
color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
} else {
// can't do our blit pass if resolutions don't match
color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RID();
}
} else {
RD::DataFormat color_format = RenderForwardMobile::singleton->_render_buffers_get_color_format();
RD::TextureFormat tf;
if (view_count > 1) {
tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
} else {
tf.texture_type = RD::TEXTURE_TYPE_2D;
}
tf.format = color_format;
tf.width = p_width;
tf.height = p_height;
tf.array_layers = view_count; // create a layer for every view
tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
RD::DataFormat format = render_buffers->get_base_data_format();
uint32_t usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
const RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = {
RD::TEXTURE_SAMPLES_1,
@ -173,79 +99,145 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
RD::TEXTURE_SAMPLES_8,
};
texture_samples = ts[p_msaa];
tf.samples = texture_samples;
texture_samples = ts[msaa_3d];
color_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView());
render_buffers->create_texture(RB_SCOPE_MOBILE, RB_TEX_COLOR_MSAA, format, usage_bits, texture_samples);
tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
depth_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView());
render_buffers->create_texture(RB_SCOPE_MOBILE, RB_TEX_DEPTH_MSAA, format, usage_bits, texture_samples);
}
}
{
Vector<RID> fb;
fb.push_back(color_msaa); // 0 - msaa color buffer
fb.push_back(depth_msaa); // 1 - msaa depth buffer
if (vrs.is_valid()) {
fb.push_back(vrs); // 2 - vrs texture
RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(FramebufferConfigType p_config_type) {
ERR_FAIL_NULL_V(render_buffers, RID());
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
ERR_FAIL_NULL_V(texture_storage, RID());
// We use our framebuffer cache here instead of building these in RenderBufferDataForwardMobile::configure
// This approach ensures we only build the framebuffers we actually need for this viewport.
// In the (near) future this means that if we cycle through a texture chain for our render target, we'll also support
// this.
RS::ViewportMSAA msaa_3d = render_buffers->get_msaa_3d();
bool use_msaa = msaa_3d != RS::VIEWPORT_MSAA_DISABLED;
uint32_t view_count = render_buffers->get_view_count();
RID vrs_texture;
if (render_buffers->has_texture(RB_SCOPE_VRS, RB_TEXTURE)) {
vrs_texture = render_buffers->get_texture(RB_SCOPE_VRS, RB_TEXTURE);
}
Vector<RID> textures;
int color_buffer_id = 0;
textures.push_back(use_msaa ? get_color_msaa() : render_buffers->get_internal_texture()); // 0 - color buffer
textures.push_back(use_msaa ? get_depth_msaa() : render_buffers->get_depth_texture()); // 1 - depth buffer
if (vrs_texture.is_valid()) {
textures.push_back(vrs_texture); // 2 - vrs texture
}
if (use_msaa) {
color_buffer_id = textures.size();
textures.push_back(render_buffers->get_internal_texture()); // color buffer for resolve
// TODO add support for resolving depth buffer!!!
}
// Now define our subpasses
Vector<RD::FramebufferPass> passes;
// Define our base pass, we'll be re-using this
RD::FramebufferPass pass;
pass.color_attachments.push_back(0);
pass.depth_attachment = 1;
if (vrs_texture.is_valid()) {
pass.vrs_attachment = 2;
}
switch (p_config_type) {
case FB_CONFIG_ONE_PASS: {
// just one pass
if (use_msaa) {
// Add resolve
pass.resolve_attachments.push_back(color_buffer_id);
}
passes.push_back(pass);
// Now define our subpasses
Vector<RD::FramebufferPass> passes;
RD::FramebufferPass pass;
return FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, view_count);
} break;
case FB_CONFIG_TWO_SUBPASSES: {
// - opaque pass
passes.push_back(pass);
// re-using the same attachments
pass.color_attachments.push_back(0);
pass.depth_attachment = 1;
if (vrs.is_valid()) {
pass.vrs_attachment = 2;
// - add sky pass
if (use_msaa) {
// add resolve
pass.resolve_attachments.push_back(color_buffer_id);
}
passes.push_back(pass);
return FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, view_count);
} break;
case FB_CONFIG_THREE_SUBPASSES: {
// - opaque pass
passes.push_back(pass);
// - add sky pass
passes.push_back(pass);
// - add alpha pass
if (use_msaa) {
// add resolve
pass.resolve_attachments.push_back(color_buffer_id);
}
passes.push_back(pass);
return FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, view_count);
} break;
case FB_CONFIG_FOUR_SUBPASSES: {
Size2i target_size = render_buffers->get_target_size();
Size2i internal_size = render_buffers->get_internal_size();
// can't do our blit pass if resolutions don't match
ERR_FAIL_COND_V(target_size != internal_size, RID());
// - opaque pass
passes.push_back(pass);
// - add sky pass
int color_buffer_id = fb.size();
fb.push_back(color); // color buffer
passes.push_back(pass); // without resolve for our 3 + 4 subpass config
{
// but with resolve for our 2 subpass config
Vector<RD::FramebufferPass> two_passes;
two_passes.push_back(pass); // opaque subpass without resolve
pass.resolve_attachments.push_back(color_buffer_id);
two_passes.push_back(pass); // sky subpass with resolve
color_fbs[FB_CONFIG_TWO_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, two_passes, RenderingDevice::INVALID_ID, view_count);
}
// - add alpha pass (with resolve, we just added that above)
passes.push_back(pass);
color_fbs[FB_CONFIG_THREE_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
{
// we also need our one pass with resolve
Vector<RD::FramebufferPass> one_pass_with_resolve;
one_pass_with_resolve.push_back(pass); // note our pass configuration already has resolve..
color_fbs[FB_CONFIG_ONE_PASS] = RD::get_singleton()->framebuffer_create_multipass(fb, one_pass_with_resolve, RenderingDevice::INVALID_ID, view_count);
// - add alpha pass
if (use_msaa) {
// add resolve
pass.resolve_attachments.push_back(color_buffer_id);
}
passes.push_back(pass);
if (!is_scaled) {
// - add blit to 2D pass
int target_buffer_id = fb.size();
fb.push_back(p_target_buffer); // target buffer
RD::FramebufferPass blit_pass;
blit_pass.color_attachments.push_back(target_buffer_id);
blit_pass.input_attachments.push_back(color_buffer_id);
passes.push_back(blit_pass);
// - add blit to 2D pass
RID render_target = render_buffers->get_render_target();
ERR_FAIL_COND_V(render_target.is_null(), RID());
RID target_buffer = texture_storage->render_target_get_rd_texture(render_target);
ERR_FAIL_COND_V(target_buffer.is_null(), RID());
color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
} else {
// can't do our blit pass if resolutions don't match
color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RID();
}
}
}
int target_buffer_id = textures.size();
textures.push_back(target_buffer); // target buffer
RD::FramebufferPass blit_pass;
blit_pass.input_attachments.push_back(color_buffer_id); // Read from our (resolved) color buffer
blit_pass.color_attachments.push_back(target_buffer_id); // Write into our target buffer
// this doesn't need VRS
passes.push_back(blit_pass);
return FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, view_count);
} break;
default:
break;
};
return RID();
}
RID RenderForwardMobile::reflection_probe_create_framebuffer(RID p_color, RID p_depth) {
@ -274,12 +266,11 @@ RID RenderForwardMobile::reflection_probe_create_framebuffer(RID p_color, RID p_
return RD::get_singleton()->framebuffer_create_multipass(fb, passes);
}
RenderForwardMobile::RenderBufferDataForwardMobile::~RenderBufferDataForwardMobile() {
clear();
}
void RenderForwardMobile::setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) {
Ref<RenderBufferDataForwardMobile> data;
data.instantiate();
RendererSceneRenderRD::RenderBufferData *RenderForwardMobile::_create_render_buffer_data() {
return memnew(RenderBufferDataForwardMobile);
p_render_buffers->set_custom_data(RB_SCOPE_MOBILE, data);
}
bool RenderForwardMobile::free(RID p_rid) {
@ -314,9 +305,11 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
//there should always be enough uniform buffers for render passes, otherwise bugs
ERR_FAIL_INDEX_V(p_index, (int)scene_state.uniform_buffers.size(), RID());
RenderBufferDataForwardMobile *rb = nullptr;
Ref<RenderBufferDataForwardMobile> rb_data;
Ref<RenderSceneBuffersRD> rb;
if (p_render_data && p_render_data->render_buffers.is_valid()) {
rb = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers));
rb = p_render_data->render_buffers;
rb_data = rb->get_custom_data(RB_SCOPE_MOBILE);
}
// default render buffer and scene state uniform set
@ -442,8 +435,12 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
RD::Uniform u;
u.binding = 9;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID();
RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH);
RID texture;
if (rb.is_valid() && rb->has_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_DEPTH)) {
texture = rb->get_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_DEPTH);
} else {
texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH);
}
u.append_id(texture);
uniforms.push_back(u);
}
@ -451,7 +448,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
RD::Uniform u;
u.binding = 10;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID();
RID bbt = rb_data.is_valid() ? rb->get_back_buffer_texture() : RID();
RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
u.append_id(texture);
uniforms.push_back(u);
@ -500,9 +497,9 @@ void RenderForwardMobile::_setup_lightmaps(const RenderDataRD *p_render_data, co
}
void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) {
RenderBufferDataForwardMobile *render_buffer = nullptr;
Ref<RenderBufferDataForwardMobile> rb_data;
if (p_render_data->render_buffers.is_valid()) {
render_buffer = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers));
rb_data = p_render_data->render_buffers->get_custom_data(RB_SCOPE_MOBILE);
}
RENDER_TIMESTAMP("Setup 3D Scene");
@ -538,12 +535,11 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] = p_render_data->instances->size();
}
if (render_buffer) {
if (rb_data.is_valid()) {
// setup rendering to render buffer
screen_size.x = render_buffer->width;
screen_size.y = render_buffer->height;
screen_size = p_render_data->render_buffers->get_internal_size();
if (render_buffer->color_fbs[FB_CONFIG_FOUR_SUBPASSES].is_null()) {
if (rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES).is_null()) {
// can't do blit subpass
using_subpass_post_process = false;
} else if (p_render_data->environment.is_valid() && (environment_get_glow_enabled(p_render_data->environment) || RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes) || RSG::camera_attributes->camera_attributes_uses_dof(p_render_data->camera_attributes))) {
@ -559,13 +555,13 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if (using_subpass_post_process) {
// all as subpasses
framebuffer = render_buffer->color_fbs[FB_CONFIG_FOUR_SUBPASSES];
framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES);
} else if (using_subpass_transparent) {
// our tonemap pass is separate
framebuffer = render_buffer->color_fbs[FB_CONFIG_THREE_SUBPASSES];
framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_THREE_SUBPASSES);
} else {
// only opaque and sky as subpasses
framebuffer = render_buffer->color_fbs[FB_CONFIG_TWO_SUBPASSES];
framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_TWO_SUBPASSES);
}
} else if (p_render_data->reflection_probe.is_valid()) {
uint32_t resolution = reflection_probe_instance_get_resolution(p_render_data->reflection_probe);
@ -626,7 +622,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
clear_color.g *= bg_energy_multiplier;
clear_color.b *= bg_energy_multiplier;
/*
if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_get_fog_enabled(p_render_data->environment)) {
if (p_render_data->render_buffers->has_custom_data(RB_SCOPE_FOG) || environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
@ -638,7 +634,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
clear_color.g *= bg_energy_multiplier;
clear_color.b *= bg_energy_multiplier;
/*
if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_get_fog_enabled(p_render_data->environment)) {
if (p_render_data->render_buffers->has_custom_data(RB_SCOPE_FOG) || environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
@ -708,7 +704,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
}
RID nullrids[RendererSceneRender::MAX_RENDER_VIEWS];
_pre_opaque_render(p_render_data, false, false, false, nullrids, RID(), nullrids);
_pre_opaque_render(p_render_data, false, false, false, nullrids, RID());
uint32_t spec_constant_base_flags = 0;
@ -728,7 +724,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
}
}
{
if (render_buffer) {
if (rb_data.is_valid()) {
RD::get_singleton()->draw_command_begin_label("Render 3D Pass");
} else {
RD::get_singleton()->draw_command_begin_label("Render Reflection Probe Pass");
@ -759,8 +755,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
// regular forward for now
Vector<Color> c;
c.push_back(clear_color.srgb_to_linear()); // our render buffer
if (render_buffer) {
if (render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
if (rb_data.is_valid()) {
if (p_render_data->render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
c.push_back(clear_color.srgb_to_linear()); // our resolve buffer
}
if (using_subpass_post_process) {
@ -859,8 +855,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
// note if we are using MSAA we should get an automatic resolve through our subpass configuration.
// blit to tonemap
if (render_buffer && using_subpass_post_process) {
_post_process_subpass(render_buffer->color, framebuffer, p_render_data);
if (rb_data.is_valid() && using_subpass_post_process) {
_post_process_subpass(p_render_data->render_buffers->get_internal_texture(), framebuffer, p_render_data);
}
RD::get_singleton()->draw_command_end_label(); // Render 3D Pass / Render Reflection Probe Pass
@ -869,7 +865,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
} else {
RENDER_TIMESTAMP("Render Transparent");
framebuffer = render_buffer->color_fbs[FB_CONFIG_ONE_PASS];
framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_ONE_PASS);
// this may be needed if we re-introduced steps that change info, not sure which do so in the previous implementation
// _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
@ -897,7 +893,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
}
}
if (render_buffer && !using_subpass_post_process) {
if (rb_data.is_valid() && !using_subpass_post_process) {
RD::get_singleton()->draw_command_begin_label("Post process pass");
// If we need extra effects we do this in its own pass
@ -908,7 +904,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RD::get_singleton()->draw_command_end_label(); // Post process pass
}
if (render_buffer) {
if (rb_data.is_valid()) {
_disable_clear_request(p_render_data);
}
}
@ -1132,7 +1128,7 @@ void RenderForwardMobile::_render_uv2(const PagedArray<RenderGeometryInstance *>
RD::get_singleton()->draw_command_end_label();
}
void RenderForwardMobile::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) {
void RenderForwardMobile::_render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) {
// we don't do GI in low end..
}
@ -1364,15 +1360,11 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
}
}
RID RenderForwardMobile::_render_buffers_get_normal_texture(RID p_render_buffers) {
// RenderBufferDataForwardMobile *rb = (RenderBufferDataForwardMobile *)render_buffers_get_data(p_render_buffers);
// We don't have this. This is for debugging
// return rb->normal_roughness_buffer;
RID RenderForwardMobile::_render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) {
return RID();
}
RID RenderForwardMobile::_render_buffers_get_velocity_texture(RID p_render_buffers) {
RID RenderForwardMobile::_render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) {
return RID();
}
@ -1625,37 +1617,6 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
//time global variables
scene_state.ubo.time = time;
/*
scene_state.ubo.gi_upscale_for_msaa = false;
scene_state.ubo.volumetric_fog_enabled = false;
scene_state.ubo.fog_enabled = false;
if (p_render_data->render_buffers.is_valid()) {
RenderBufferDataForwardMobile *render_buffers = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers));
if (render_buffers->msaa != RS::VIEWPORT_MSAA_DISABLED) {
scene_state.ubo.gi_upscale_for_msaa = true;
}
if (render_buffers_has_volumetric_fog(p_render_data->render_buffers)) {
scene_state.ubo.volumetric_fog_enabled = true;
float fog_end = render_buffers_get_volumetric_fog_end(p_render_data->render_buffers);
if (fog_end > 0.0) {
scene_state.ubo.volumetric_fog_inv_length = 1.0 / fog_end;
} else {
scene_state.ubo.volumetric_fog_inv_length = 1.0;
}
float fog_detail_spread = render_buffers_get_volumetric_fog_detail_spread(p_render_data->render_buffers); //reverse lookup
if (fog_detail_spread > 0.0) {
scene_state.ubo.volumetric_fog_detail_spread = 1.0 / fog_detail_spread;
} else {
scene_state.ubo.volumetric_fog_detail_spread = 1.0;
}
}
}
*/
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
scene_state.ubo.use_ambient_light = true;
scene_state.ubo.ambient_light_color_energy[0] = 1;

View File

@ -37,6 +37,8 @@
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/utilities.h"
#define RB_SCOPE_MOBILE SNAME("mobile")
namespace RendererSceneRenderImplementation {
class RenderForwardMobile : public RendererSceneRenderRD {
@ -107,43 +109,38 @@ protected:
/* Render Buffer */
// We can have:
// - 4 subpasses combining the full render cycle
// - 3 subpasses + 1 normal pass for tonemapping/glow/dof/etc (using fb for 2D buffer)
// - 2 subpasses + 1 normal pass for transparent + 1 normal pass for tonemapping/glow/dof/etc (using fb for 2D buffer)
enum RenderBufferMobileFramebufferConfigType {
FB_CONFIG_ONE_PASS, // Single pass frame buffer for alpha pass
FB_CONFIG_TWO_SUBPASSES, // Opaque + Sky sub pass
FB_CONFIG_THREE_SUBPASSES, // Opaque + Sky + Alpha sub pass
FB_CONFIG_FOUR_SUBPASSES, // Opaque + Sky + Alpha sub pass + Tonemap pass
FB_CONFIG_MAX
class RenderBufferDataForwardMobile : public RenderBufferCustomDataRD {
GDCLASS(RenderBufferDataForwardMobile, RenderBufferCustomDataRD);
public:
// We can have:
// - 4 subpasses combining the full render cycle
// - 3 subpasses + 1 normal pass for tonemapping/glow/dof/etc (using fb for 2D buffer)
// - 2 subpasses + 1 normal pass for transparent + 1 normal pass for tonemapping/glow/dof/etc (using fb for 2D buffer)
enum FramebufferConfigType {
FB_CONFIG_ONE_PASS, // Single pass frame buffer for alpha pass
FB_CONFIG_TWO_SUBPASSES, // Opaque + Sky sub pass
FB_CONFIG_THREE_SUBPASSES, // Opaque + Sky + Alpha sub pass
FB_CONFIG_FOUR_SUBPASSES, // Opaque + Sky + Alpha sub pass + Tonemap pass
FB_CONFIG_MAX
};
RID get_color_msaa() const { return render_buffers->get_texture(RB_SCOPE_MOBILE, RB_TEX_COLOR_MSAA); }
RID get_color_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_MOBILE, RB_TEX_COLOR_MSAA, p_layer, 0); }
RID get_depth_msaa() const { return render_buffers->get_texture(RB_SCOPE_MOBILE, RB_TEX_DEPTH_MSAA); }
RID get_depth_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_MOBILE, RB_TEX_DEPTH_MSAA, p_layer, 0); }
RID get_color_fbs(FramebufferConfigType p_config_type);
virtual void free_data() override;
virtual void configure(RenderSceneBuffersRD *p_render_buffers) override;
private:
RenderSceneBuffersRD *render_buffers = nullptr;
RD::TextureSamples texture_samples = RD::TEXTURE_SAMPLES_1;
};
struct RenderBufferDataForwardMobile : public RenderBufferData {
RID color;
RID depth;
// RID normal_roughness_buffer;
RS::ViewportMSAA msaa;
RD::TextureSamples texture_samples;
RID color_msaa;
RID depth_msaa;
// RID normal_roughness_buffer_msaa;
RID vrs;
RID color_fbs[FB_CONFIG_MAX];
int width, height;
uint32_t view_count;
void clear();
virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture);
~RenderBufferDataForwardMobile();
};
virtual RenderBufferData *_create_render_buffer_data() override;
virtual void setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) override;
/* Rendering */
@ -218,15 +215,15 @@ protected:
virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) override;
virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override;
virtual void _render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override;
virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) override;
uint64_t lightmap_texture_array_version = 0xFFFFFFFF;
virtual void _base_uniforms_changed() override;
void _update_render_base_uniform_set();
virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) override;
virtual RID _render_buffers_get_velocity_texture(RID p_render_buffers) override;
virtual RID _render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override;
virtual RID _render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override;
void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_append = false);
void _fill_element_info(RenderListType p_render_list, uint32_t p_offset = 0, int32_t p_max_elements = -1);

View File

@ -200,7 +200,7 @@ public:
RID get_cache(Args... args) {
uint32_t h = hash_murmur3_one_32(1); //1 view
h = hash_murmur3_one_32(sizeof...(Args), h);
h = _hash_args(h, args...);
h = _hash_rids(h, args...);
h = hash_murmur3_one_32(0, h); // 0 passes
h = hash_fmix32(h);
@ -228,7 +228,7 @@ public:
RID get_cache_multiview(uint32_t p_views, Args... args) {
uint32_t h = hash_murmur3_one_32(p_views);
h = hash_murmur3_one_32(sizeof...(Args), h);
h = _hash_args(h, args...);
h = _hash_rids(h, args...);
h = hash_murmur3_one_32(0, h); // 0 passes
h = hash_fmix32(h);

File diff suppressed because it is too large Load Diff

View File

@ -37,18 +37,21 @@
#include "servers/rendering/renderer_rd/cluster_builder_rd.h"
#include "servers/rendering/renderer_rd/effects/bokeh_dof.h"
#include "servers/rendering/renderer_rd/effects/copy_effects.h"
#include "servers/rendering/renderer_rd/effects/fsr.h"
#include "servers/rendering/renderer_rd/effects/ss_effects.h"
#include "servers/rendering/renderer_rd/effects/tone_mapper.h"
#include "servers/rendering/renderer_rd/effects/vrs.h"
#include "servers/rendering/renderer_rd/environment/fog.h"
#include "servers/rendering/renderer_rd/environment/gi.h"
#include "servers/rendering/renderer_rd/environment/sky.h"
#include "servers/rendering/renderer_rd/framebuffer_cache_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
#include "servers/rendering/renderer_scene.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_device.h"
struct RenderDataRD {
RID render_buffers;
Ref<RenderSceneBuffersRD> render_buffers;
Transform3D cam_transform;
Projection cam_projection;
@ -104,15 +107,12 @@ protected:
RendererRD::BokehDOF *bokeh_dof = nullptr;
RendererRD::CopyEffects *copy_effects = nullptr;
RendererRD::ToneMapper *tone_mapper = nullptr;
RendererRD::FSR *fsr = nullptr;
RendererRD::VRS *vrs = nullptr;
double time = 0.0;
double time_step = 0.0;
struct RenderBufferData {
virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture) = 0;
virtual ~RenderBufferData() {}
};
virtual RenderBufferData *_create_render_buffer_data() = 0;
virtual void setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) = 0;
void _setup_lights(RenderDataRD *p_render_data, 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);
void _setup_decals(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform);
@ -127,31 +127,28 @@ protected:
virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) = 0;
virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) = 0;
virtual void _render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) = 0;
virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) = 0;
void _debug_sdfgi_probes(RID p_render_buffers, RID p_framebuffer, uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth);
void _debug_draw_cluster(RID p_render_buffers);
RenderBufferData *render_buffers_get_data(RID p_render_buffers);
void _debug_sdfgi_probes(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_framebuffer, uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth);
void _debug_draw_cluster(Ref<RenderSceneBuffersRD> p_render_buffers);
virtual void _base_uniforms_changed() = 0;
virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) = 0;
virtual RID _render_buffers_get_velocity_texture(RID p_render_buffers) = 0;
virtual RID _render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) = 0;
virtual RID _render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) = 0;
void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection);
void _process_ssr(RID p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_buffer_slices, RID p_specular_buffer, const RID *p_metallic_slices, const Color &p_metallic_mask, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive);
void _process_sss(RID p_render_buffers, const Projection &p_camera);
void _process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform);
void _process_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection);
void _process_ssr(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_buffer_slices, RID p_specular_buffer, const RID *p_metallic_slices, const Color &p_metallic_mask, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive);
void _process_sss(Ref<RenderSceneBuffersRD> p_render_buffers, const Projection &p_camera);
void _process_ssil(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform);
void _copy_framebuffer_to_ssil(RID p_render_buffers);
void _process_taa(RID p_render_buffers, RID p_velocity_buffer, float p_z_near, float p_z_far);
void _copy_framebuffer_to_ssil(Ref<RenderSceneBuffersRD> p_render_buffers);
bool _needs_post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi);
void _post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi);
void _pre_resolve_render(RenderDataRD *p_render_data, bool p_use_gi);
void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices);
void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer);
void _render_buffers_copy_screen_texture(const RenderDataRD *p_render_data);
void _render_buffers_copy_depth_texture(const RenderDataRD *p_render_data);
@ -424,131 +421,22 @@ private:
bool use_physical_light_units = false;
/* RENDER BUFFERS */
/* Cluster builder */
ClusterBuilderSharedDataRD cluster_builder_shared;
ClusterBuilderRD *current_cluster_builder = nullptr;
struct RenderBuffers {
RenderBufferData *data = nullptr;
int internal_width = 0;
int internal_height = 0;
int width = 0;
int height = 0;
float fsr_sharpness = 0.2f;
RS::ViewportMSAA msaa_3d = RS::VIEWPORT_MSAA_DISABLED;
RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
bool use_taa = false;
bool use_debanding = false;
uint32_t view_count = 1;
/* RENDER BUFFERS */
RID render_target;
void _allocate_luminance_textures(Ref<RenderSceneBuffersRD> rb);
uint64_t auto_exposure_version = 1;
RID sss_texture; //texture for sss. This needs to be a different resolution than blur[0]
RID internal_texture; //main texture for rendering to, must be filled after done rendering
RID texture; //upscaled version of main texture (This uses the same resource as internal_texture if there is no upscaling)
RID depth_texture; //main depth texture
RID texture_fb; // framebuffer for the main texture, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!!
RID upscale_texture; //used when upscaling internal_texture (This uses the same resource as internal_texture if there is no upscaling)
RID vrs_texture; // texture for vrs.
RID vrs_fb; // framebuffer to write to our vrs texture
// Access to the layers for each of our views (specifically needed for applying post effects on stereoscopic images)
struct View {
RID view_texture; // texture slice for this view/layer
RID view_depth; // depth slice for this view/layer
RID view_fb; // framebuffer for this view/layer, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!!
};
Vector<View> views;
RendererRD::GI::SDFGI *sdfgi = nullptr;
RendererRD::GI::RenderBuffersGI rbgi;
RendererRD::Fog::VolumetricFog *volumetric_fog = nullptr;
ClusterBuilderRD *cluster_builder = nullptr;
//built-in textures used for ping pong image processing and blurring
struct Blur {
RID texture;
struct Mipmap {
RID texture;
int width;
int height;
// only used on mobile renderer
RID fb;
RID half_texture;
RID half_fb;
};
struct Layer {
Vector<Mipmap> mipmaps;
};
Vector<Layer> layers;
};
Blur blur[2]; //the second one starts from the first mipmap
struct WeightBuffers {
RID weight;
RID fb; // FB with both texture and weight writing into one level lower
};
// 2 full size, 2 half size
WeightBuffers weight_buffers[4]; // Only used in raster
RID depth_back_texture;
RID depth_back_fb; // only used on mobile
struct Luminance {
Vector<RID> reduce;
RID current;
// used only on mobile renderer
Vector<RID> fb;
RID current_fb;
} luminance;
struct SSEffects {
RID linear_depth;
Vector<RID> linear_depth_slices;
RID downsample_uniform_set;
Projection last_frame_projection;
Transform3D last_frame_transform;
RendererRD::SSEffects::SSAORenderBuffers ssao;
RendererRD::SSEffects::SSILRenderBuffers ssil;
} ss_effects;
RendererRD::SSEffects::SSRRenderBuffers ssr;
struct TAA {
RID history;
RID temp;
RID prev_velocity; // Last frame velocity buffer
} taa;
};
void _render_buffers_debug_draw(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer);
/* GI */
bool screen_space_roughness_limiter = false;
float screen_space_roughness_limiter_amount = 0.25;
float screen_space_roughness_limiter_limit = 0.18;
mutable RID_Owner<RenderBuffers> render_buffers_owner;
void _free_render_buffer_data(RenderBuffers *rb);
void _allocate_blur_textures(RenderBuffers *rb);
void _allocate_depth_backbuffer_textures(RenderBuffers *rb);
void _allocate_luminance_textures(RenderBuffers *rb);
void _render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer);
/* Cluster */
struct Cluster {
@ -727,11 +615,14 @@ private:
uint32_t volumetric_fog_depth = 128;
bool volumetric_fog_filter_active = true;
void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes);
void _update_volumetric_fog(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes);
public:
static RendererSceneRenderRD *get_singleton() { return singleton; }
/* Cluster builder */
ClusterBuilderSharedDataRD *get_cluster_builder_shared() { return &cluster_builder_shared; }
/* GI */
RendererRD::GI *get_gi() { return &gi; }
@ -774,10 +665,10 @@ public:
/* SDFGI UPDATE */
virtual void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override;
virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const override;
virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override;
virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override;
virtual void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) override;
virtual int sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const override;
virtual AABB sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override;
virtual uint32_t sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override;
RID sdfgi_get_ubo() const { return gi.sdfgi_ubo; }
/* SKY API */
@ -1071,42 +962,14 @@ public:
virtual float _render_buffers_get_luminance_multiplier();
virtual RD::DataFormat _render_buffers_get_color_format();
virtual bool _render_buffers_can_be_storage();
virtual RID render_buffers_create() override;
virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
virtual Ref<RenderSceneBuffers> render_buffers_create() override;
virtual void gi_set_use_half_resolution(bool p_enable) override;
RID render_buffers_get_depth_texture(RID p_render_buffers);
RID render_buffers_get_ao_texture(RID p_render_buffers);
RID render_buffers_get_ssil_texture(RID p_render_buffers);
RID render_buffers_get_back_buffer_texture(RID p_render_buffers);
RID render_buffers_get_back_depth_texture(RID p_render_buffers);
RID render_buffers_get_voxel_gi_buffer(RID p_render_buffers);
RID render_buffers_get_default_voxel_gi_buffer();
RID render_buffers_get_gi_ambient_texture(RID p_render_buffers);
RID render_buffers_get_gi_reflection_texture(RID p_render_buffers);
uint32_t render_buffers_get_sdfgi_cascade_count(RID p_render_buffers) const;
bool render_buffers_is_sdfgi_enabled(RID p_render_buffers) const;
RID render_buffers_get_sdfgi_irradiance_probes(RID p_render_buffers) const;
Vector3 render_buffers_get_sdfgi_cascade_offset(RID p_render_buffers, uint32_t p_cascade) const;
Vector3i render_buffers_get_sdfgi_cascade_probe_offset(RID p_render_buffers, uint32_t p_cascade) const;
float render_buffers_get_sdfgi_cascade_probe_size(RID p_render_buffers, uint32_t p_cascade) const;
float render_buffers_get_sdfgi_normal_bias(RID p_render_buffers) const;
uint32_t render_buffers_get_sdfgi_cascade_probe_count(RID p_render_buffers) const;
uint32_t render_buffers_get_sdfgi_cascade_size(RID p_render_buffers) const;
bool render_buffers_is_sdfgi_using_occlusion(RID p_render_buffers) const;
float render_buffers_get_sdfgi_energy(RID p_render_buffers) const;
RID render_buffers_get_sdfgi_occlusion_texture(RID p_render_buffers) const;
bool render_buffers_has_volumetric_fog(RID p_render_buffers) const;
RID render_buffers_get_volumetric_fog_texture(RID p_render_buffers);
RID render_buffers_get_volumetric_fog_sky_uniform_set(RID p_render_buffers);
float render_buffers_get_volumetric_fog_end(RID p_render_buffers);
float render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers);
virtual void update_uniform_sets(){};
virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
virtual void render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
virtual void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;

View File

@ -0,0 +1,48 @@
/*************************************************************************/
/* render_buffer_custom_data_rd.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef RENDER_BUFFER_CUSTOM_DATA_RD_H
#define RENDER_BUFFER_CUSTOM_DATA_RD_H
#include "core/object/ref_counted.h"
class RenderSceneBuffersRD;
class RenderBufferCustomDataRD : public RefCounted {
GDCLASS(RenderBufferCustomDataRD, RefCounted);
public:
virtual void configure(RenderSceneBuffersRD *p_render_buffers) = 0;
virtual void free_data() = 0; // called on cleanup
private:
};
#endif // RENDER_BUFFER_CUSTOM_DATA_RD_H

View File

@ -0,0 +1,559 @@
/*************************************************************************/
/* render_scene_buffers_rd.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "render_scene_buffers_rd.h"
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
RenderSceneBuffersRD::RenderSceneBuffersRD() {
}
RenderSceneBuffersRD::~RenderSceneBuffersRD() {
cleanup();
data_buffers.clear();
// need to investigate if we can remove these things.
if (cluster_builder) {
memdelete(cluster_builder);
}
}
void RenderSceneBuffersRD::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_texture", "context", "name"), &RenderSceneBuffersRD::has_texture);
// FIXME we can't pass RD::DataFormat, RD::TextureSamples and RD::TextureView in ClassDB, need to solve views differently...
// ClassDB::bind_method(D_METHOD("create_texture", "context", "name", "data_format", "usage_bits", "texture_samples", "size", "layers", "mipmaps", "unique"), &RenderSceneBuffersRD::create_texture);
// ClassDB::bind_method(D_METHOD("create_texture_from_format", "context", "name", "format", "view", "unique"), &RenderSceneBuffersRD::create_texture_from_format);
// ClassDB::bind_method(D_METHOD("create_texture_view", "context", "name", "view_name", "view"), &RenderSceneBuffersRD::has_texture);
ClassDB::bind_method(D_METHOD("get_texture", "context", "name"), &RenderSceneBuffersRD::get_texture);
// ClassDB::bind_method(D_METHOD("get_texture_format", "context", "name"), &RenderSceneBuffersRD::get_texture_format);
ClassDB::bind_method(D_METHOD("get_texture_slice", "context", "name", "layer", "mipmap"), &RenderSceneBuffersRD::get_texture_slice);
ClassDB::bind_method(D_METHOD("get_texture_slice_size", "context", "name", "layer", "mipmap"), &RenderSceneBuffersRD::get_texture_slice_size);
ClassDB::bind_method(D_METHOD("clear_context", "context"), &RenderSceneBuffersRD::clear_context);
}
void RenderSceneBuffersRD::update_sizes(NamedTexture &p_named_texture) {
ERR_FAIL_COND(p_named_texture.texture.is_null());
uint32_t size = p_named_texture.format.array_layers * p_named_texture.format.mipmaps;
p_named_texture.sizes.resize(size);
Size2i mipmap_size = Size2i(p_named_texture.format.width, p_named_texture.format.height);
for (uint32_t mipmap = 0; mipmap < p_named_texture.format.mipmaps; mipmap++) {
for (uint32_t layer = 0; layer < p_named_texture.format.array_layers; layer++) {
uint32_t index = layer * p_named_texture.format.mipmaps + mipmap;
p_named_texture.sizes.ptrw()[index] = mipmap_size;
}
mipmap_size.width = MAX(1, mipmap_size.width >> 1);
mipmap_size.height = MAX(1, mipmap_size.height >> 1);
}
}
void RenderSceneBuffersRD::free_named_texture(NamedTexture &p_named_texture) {
if (p_named_texture.texture.is_valid()) {
RD::get_singleton()->free(p_named_texture.texture);
}
p_named_texture.texture = RID();
p_named_texture.slices.clear(); // slices should be freed automatically as dependents...
}
void RenderSceneBuffersRD::cleanup() {
// Free our data buffers (but don't destroy them)
for (KeyValue<StringName, Ref<RenderBufferCustomDataRD>> &E : data_buffers) {
E.value->free_data();
}
// Clear our named textures
for (KeyValue<NTKey, NamedTexture> &E : named_textures) {
free_named_texture(E.value);
}
named_textures.clear();
// old stuff, to be re-evaluated...
for (int i = 0; i < luminance.fb.size(); i++) {
RD::get_singleton()->free(luminance.fb[i]);
}
luminance.fb.clear();
for (int i = 0; i < luminance.reduce.size(); i++) {
RD::get_singleton()->free(luminance.reduce[i]);
}
luminance.reduce.clear();
if (luminance.current_fb.is_valid()) {
RD::get_singleton()->free(luminance.current_fb);
luminance.current_fb = RID();
}
if (luminance.current.is_valid()) {
RD::get_singleton()->free(luminance.current);
luminance.current = RID();
}
if (ss_effects.linear_depth.is_valid()) {
RD::get_singleton()->free(ss_effects.linear_depth);
ss_effects.linear_depth = RID();
ss_effects.linear_depth_slices.clear();
}
sse->ssao_free(ss_effects.ssao);
sse->ssil_free(ss_effects.ssil);
sse->ssr_free(ssr);
}
void RenderSceneBuffersRD::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND_MSG(p_view_count == 0, "Must have at least 1 view");
target_size = p_target_size;
internal_size = p_internal_size;
// FIXME, right now we do this because only our clustered renderer supports FSR upscale
// this does mean that with linear upscale if we use subpasses, we could get into trouble.
if (!can_be_storage) {
internal_size = target_size;
}
if (p_use_taa) {
// Use negative mipmap LOD bias when TAA is enabled to compensate for loss of sharpness.
// This restores sharpness in still images to be roughly at the same level as without TAA,
// but moving scenes will still be blurrier.
p_texture_mipmap_bias -= 0.5;
}
if (p_screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) {
// Use negative mipmap LOD bias when FXAA is enabled to compensate for loss of sharpness.
// If both TAA and FXAA are enabled, combine their negative LOD biases together.
p_texture_mipmap_bias -= 0.25;
}
material_storage->sampler_rd_configure_custom(p_texture_mipmap_bias);
// need to check if we really need to do this here..
RendererSceneRenderRD::get_singleton()->update_uniform_sets();
render_target = p_render_target;
fsr_sharpness = p_fsr_sharpness;
msaa_3d = p_msaa_3d;
screen_space_aa = p_screen_space_aa;
use_taa = p_use_taa;
use_debanding = p_use_debanding;
view_count = p_view_count;
/* may move this into our clustered renderer data object */
if (can_be_storage) {
if (cluster_builder == nullptr) {
cluster_builder = memnew(ClusterBuilderRD);
}
cluster_builder->set_shared(RendererSceneRenderRD::get_singleton()->get_cluster_builder_shared());
}
// cleanout any old buffers we had.
cleanup();
// create our 3D render buffers
{
// Create our color buffer(s)
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | (can_be_storage ? RD::TEXTURE_USAGE_STORAGE_BIT : 0) | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
usage_bits |= RD::TEXTURE_USAGE_INPUT_ATTACHMENT_BIT; // only needed when using subpasses in the mobile renderer
// our internal texture should have MSAA support if applicable
if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED) {
usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
}
create_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR, base_data_format, usage_bits);
}
// Create our depth buffer
{
// TODO If we have depth buffer supplied externally, pick this up
RD::DataFormat format;
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
if (msaa_3d == RS::VIEWPORT_MSAA_DISABLED) {
format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, (RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT)) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
usage_bits |= RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
} else {
format = RD::DATA_FORMAT_R32_SFLOAT;
usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
}
create_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH, format, usage_bits);
}
// VRS (note, our vrs object will only be set if VRS is supported)
RID vrs_texture;
RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(p_render_target);
if (vrs && vrs_mode != RS::VIEWPORT_VRS_DISABLED) {
uint32_t usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
vrs_texture = create_texture(RB_SCOPE_VRS, RB_TEXTURE, RD::DATA_FORMAT_R8_UINT, usage_bits, RD::TEXTURE_SAMPLES_1, vrs->get_vrs_texture_size(internal_size));
}
for (KeyValue<StringName, Ref<RenderBufferCustomDataRD>> &E : data_buffers) {
E.value->configure(this);
}
if (cluster_builder) {
RID sampler = RendererRD::MaterialStorage::get_singleton()->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
cluster_builder->setup(internal_size, max_cluster_elements, get_depth_texture(), sampler, get_internal_texture());
}
}
void RenderSceneBuffersRD::set_fsr_sharpness(float p_fsr_sharpness) {
fsr_sharpness = p_fsr_sharpness;
}
void RenderSceneBuffersRD::set_texture_mipmap_bias(float p_texture_mipmap_bias) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
material_storage->sampler_rd_configure_custom(p_texture_mipmap_bias);
}
void RenderSceneBuffersRD::set_use_debanding(bool p_use_debanding) {
use_debanding = p_use_debanding;
}
// Named textures
bool RenderSceneBuffersRD::has_texture(const StringName &p_context, const StringName &p_texture_name) const {
NTKey key(p_context, p_texture_name);
return named_textures.has(key);
}
RID RenderSceneBuffersRD::create_texture(const StringName &p_context, const StringName &p_texture_name, const RD::DataFormat p_data_format, const uint32_t p_usage_bits, const RD::TextureSamples p_texture_samples, const Size2i p_size, const uint32_t p_layers, const uint32_t p_mipmaps, bool p_unique) {
// Keep some useful data, we use default values when these are 0.
Size2i size = p_size == Size2i(0, 0) ? internal_size : p_size;
uint32_t layers = p_layers == 0 ? view_count : p_layers;
uint32_t mipmaps = p_mipmaps == 0 ? 1 : p_mipmaps;
// Create our texture
RD::TextureFormat tf;
tf.format = p_data_format;
if (layers > 1) {
tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
}
tf.width = size.x;
tf.height = size.y;
tf.depth = 1;
tf.array_layers = layers;
tf.mipmaps = mipmaps;
tf.usage_bits = p_usage_bits;
tf.samples = p_texture_samples;
return create_texture_from_format(p_context, p_texture_name, tf, RD::TextureView(), p_unique);
}
RID RenderSceneBuffersRD::create_texture_from_format(const StringName &p_context, const StringName &p_texture_name, const RD::TextureFormat &p_texture_format, RD::TextureView p_view, bool p_unique) {
// TODO p_unique, if p_unique is true, this is a texture that can be shared. This will be implemented later as an optimisation.
NTKey key(p_context, p_texture_name);
// check if this is a known texture
if (named_textures.has(key)) {
return named_textures[key].texture;
}
// Add a new entry..
NamedTexture &named_texture = named_textures[key];
named_texture.format = p_texture_format;
named_texture.is_unique = p_unique;
named_texture.texture = RD::get_singleton()->texture_create(p_texture_format, p_view);
Array arr;
arr.push_back(p_context);
arr.push_back(p_texture_name);
RD::get_singleton()->set_resource_name(named_texture.texture, String("RenderBuffer {0}/{1}").format(arr));
update_sizes(named_texture);
// The rest is lazy created..
return named_texture.texture;
}
RID RenderSceneBuffersRD::create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName p_view_name, RD::TextureView p_view) {
NTKey view_key(p_context, p_view_name);
// check if this is a known texture
if (named_textures.has(view_key)) {
return named_textures[view_key].texture;
}
NTKey key(p_context, p_texture_name);
ERR_FAIL_COND_V(!named_textures.has(key), RID());
NamedTexture &named_texture = named_textures[key];
NamedTexture &view_texture = named_textures[view_key];
view_texture.format = named_texture.format;
view_texture.is_unique = named_texture.is_unique;
view_texture.texture = RD::get_singleton()->texture_create_shared(p_view, named_texture.texture);
Array arr;
arr.push_back(p_context);
arr.push_back(p_view_name);
RD::get_singleton()->set_resource_name(view_texture.texture, String("RenderBuffer View {0}/{1}").format(arr));
update_sizes(named_texture);
return view_texture.texture;
}
RID RenderSceneBuffersRD::get_texture(const StringName &p_context, const StringName &p_texture_name) const {
NTKey key(p_context, p_texture_name);
ERR_FAIL_COND_V(!named_textures.has(key), RID());
return named_textures[key].texture;
}
const RD::TextureFormat RenderSceneBuffersRD::get_texture_format(const StringName &p_context, const StringName &p_texture_name) const {
NTKey key(p_context, p_texture_name);
ERR_FAIL_COND_V(!named_textures.has(key), RD::TextureFormat());
return named_textures[key].format;
}
RID RenderSceneBuffersRD::get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap) {
NTKey key(p_context, p_texture_name);
// check if this is a known texture
ERR_FAIL_COND_V(!named_textures.has(key), RID());
NamedTexture &named_texture = named_textures[key];
ERR_FAIL_COND_V(named_texture.texture.is_null(), RID());
// check if we're in bounds
ERR_FAIL_UNSIGNED_INDEX_V(p_layer, named_texture.format.array_layers, RID());
ERR_FAIL_UNSIGNED_INDEX_V(p_mipmap, named_texture.format.mipmaps, RID());
// if we don't have multiple layers or mipmaps, we can just return our texture as is
if (named_texture.format.array_layers == 1 && named_texture.format.mipmaps == 1) {
return named_texture.texture;
}
// get our index and make sure we have enough entries in our slices vector
uint32_t index = p_layer * named_texture.format.mipmaps + p_mipmap;
while (named_texture.slices.size() <= int(index)) {
named_texture.slices.push_back(RID());
}
// create our slice if we don't have it already
if (named_texture.slices[index].is_null()) {
named_texture.slices.ptrw()[index] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), named_texture.texture, p_layer, p_mipmap);
Array arr;
arr.push_back(p_context);
arr.push_back(p_texture_name);
arr.push_back(itos(p_layer));
arr.push_back(itos(p_mipmap));
RD::get_singleton()->set_resource_name(named_texture.slices[index], String("RenderBuffer {0}/{1} slice {2}/{3}").format(arr));
}
// and return our slice
return named_texture.slices[index];
}
Size2i RenderSceneBuffersRD::get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap) {
NTKey key(p_context, p_texture_name);
// check if this is a known texture
ERR_FAIL_COND_V(!named_textures.has(key), Size2i());
NamedTexture &named_texture = named_textures[key];
ERR_FAIL_COND_V(named_texture.texture.is_null(), Size2i());
// check if we're in bounds
ERR_FAIL_UNSIGNED_INDEX_V(p_layer, named_texture.format.array_layers, Size2i());
ERR_FAIL_UNSIGNED_INDEX_V(p_mipmap, named_texture.format.mipmaps, Size2i());
// get our index
uint32_t index = p_layer * named_texture.format.mipmaps + p_mipmap;
// and return our size
return named_texture.sizes[index];
}
void RenderSceneBuffersRD::clear_context(const StringName &p_context) {
Vector<NTKey> to_free; // free these
// Find all entries for our context, we don't want to free them yet or our loop fails.
for (KeyValue<NTKey, NamedTexture> &E : named_textures) {
if (E.key.context == p_context) {
to_free.push_back(E.key);
}
}
// Now free these and remove them from our textures
for (NTKey &key : to_free) {
free_named_texture(named_textures[key]);
named_textures.erase(key);
}
}
// Allocate shared buffers
void RenderSceneBuffersRD::allocate_blur_textures() {
if (has_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0)) {
// already allocated...
return;
}
uint32_t mipmaps_required = Image::get_image_required_mipmaps(internal_size.x, internal_size.y, Image::FORMAT_RGBAH);
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
if (can_be_storage) {
usage_bits += RD::TEXTURE_USAGE_STORAGE_BIT;
} else {
usage_bits += RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
}
create_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, base_data_format, usage_bits, RD::TEXTURE_SAMPLES_1, internal_size, view_count, mipmaps_required);
create_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, base_data_format, usage_bits, RD::TEXTURE_SAMPLES_1, Size2i(internal_size.x >> 1, internal_size.y >> 1), view_count, mipmaps_required - 1);
// if !can_be_storage we need a half width version
if (!can_be_storage) {
create_texture(RB_SCOPE_BUFFERS, RB_TEX_HALF_BLUR, base_data_format, usage_bits, RD::TEXTURE_SAMPLES_1, Size2i(internal_size.x >> 1, internal_size.y), 1, mipmaps_required);
}
// TODO redo this:
if (!can_be_storage) {
// create 4 weight textures, 2 full size, 2 half size
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R16_SFLOAT; // We could probably use DATA_FORMAT_R8_SNORM if we don't pre-multiply by blur_size but that depends on whether we can remove DEPTH_GAP
tf.width = internal_size.x;
tf.height = internal_size.y;
tf.texture_type = RD::TEXTURE_TYPE_2D;
tf.array_layers = 1; // Our DOF effect handles one eye per turn
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
tf.mipmaps = 1;
for (uint32_t i = 0; i < 4; i++) {
// associated blur texture
RID texture;
if (i == 1) {
texture = get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, 0, 0);
} else if (i == 2) {
texture = get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, 0, 0);
} else if (i == 3) {
texture = get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, 0, 1);
}
// create weight texture
weight_buffers[i].weight = RD::get_singleton()->texture_create(tf, RD::TextureView());
// create frame buffer
Vector<RID> fb;
if (i != 0) {
fb.push_back(texture);
}
fb.push_back(weight_buffers[i].weight);
weight_buffers[i].fb = RD::get_singleton()->framebuffer_create(fb);
if (i == 1) {
// next 2 are half size
tf.width = MAX(1u, tf.width >> 1);
tf.height = MAX(1u, tf.height >> 1);
}
}
}
}
// Data buffers
bool RenderSceneBuffersRD::has_custom_data(const StringName &p_name) {
return data_buffers.has(p_name);
}
void RenderSceneBuffersRD::set_custom_data(const StringName &p_name, Ref<RenderBufferCustomDataRD> p_data) {
if (p_data.is_valid()) {
data_buffers[p_name] = p_data;
} else if (has_custom_data(p_name)) {
data_buffers.erase(p_name);
}
}
Ref<RenderBufferCustomDataRD> RenderSceneBuffersRD::get_custom_data(const StringName &p_name) const {
ERR_FAIL_COND_V(!data_buffers.has(p_name), Ref<RenderBufferCustomDataRD>());
Ref<RenderBufferCustomDataRD> ret = data_buffers[p_name];
return ret;
}
// Velocity texture.
void RenderSceneBuffersRD::ensure_velocity() {
if (!has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY)) {
uint32_t usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED) {
uint32_t msaa_usage_bits = usage_bits | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
const RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = {
RD::TEXTURE_SAMPLES_1,
RD::TEXTURE_SAMPLES_2,
RD::TEXTURE_SAMPLES_4,
RD::TEXTURE_SAMPLES_8,
};
create_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA, RD::DATA_FORMAT_R16G16_SFLOAT, msaa_usage_bits, ts[msaa_3d]);
}
create_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY, RD::DATA_FORMAT_R16G16_SFLOAT, usage_bits);
}
}
RID RenderSceneBuffersRD::get_velocity_buffer(bool p_get_msaa) {
if (p_get_msaa) {
if (!has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA)) {
return RID();
} else {
return get_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA);
}
} else {
if (!has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY)) {
return RID();
} else {
return get_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY);
}
}
}

View File

@ -0,0 +1,256 @@
/*************************************************************************/
/* render_scene_buffers_rd.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef RENDER_SCENE_BUFFERS_RD_H
#define RENDER_SCENE_BUFFERS_RD_H
#include "core/templates/hash_map.h"
#include "servers/rendering/renderer_rd/effects/vrs.h"
#include "servers/rendering/renderer_rd/framebuffer_cache_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h"
#include "servers/rendering/renderer_scene.h"
#include "servers/rendering/rendering_device.h"
#include "servers/rendering/storage/render_scene_buffers.h"
// These can be retired in due time
#include "servers/rendering/renderer_rd/cluster_builder_rd.h"
#include "servers/rendering/renderer_rd/effects/ss_effects.h"
#include "servers/rendering/renderer_rd/environment/fog.h"
#define RB_SCOPE_BUFFERS SNAME("render_buffers")
#define RB_SCOPE_VRS SNAME("VRS")
#define RB_TEXTURE SNAME("texture")
#define RB_TEX_COLOR SNAME("color")
#define RB_TEX_COLOR_MSAA SNAME("color_msaa")
#define RB_TEX_DEPTH SNAME("depth")
#define RB_TEX_DEPTH_MSAA SNAME("depth_msaa")
#define RB_TEX_VELOCITY SNAME("velocity")
#define RB_TEX_VELOCITY_MSAA SNAME("velocity_msaa")
#define RB_TEX_BLUR_0 SNAME("blur_0")
#define RB_TEX_BLUR_1 SNAME("blur_1")
#define RB_TEX_HALF_BLUR SNAME("half_blur") // only for raster!
#define RB_TEX_BACK_DEPTH SNAME("back_depth")
class RenderSceneBuffersRD : public RenderSceneBuffers {
GDCLASS(RenderSceneBuffersRD, RenderSceneBuffers);
private:
bool can_be_storage = true;
uint32_t max_cluster_elements = 512;
RD::DataFormat base_data_format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
RendererRD::SSEffects *sse = nullptr;
RendererRD::VRS *vrs = nullptr;
uint64_t auto_exposure_version = 1;
// Our render target represents our final destination that we display on screen.
RID render_target;
Size2i target_size = Size2i(0, 0);
uint32_t view_count = 1;
// The internal size of the textures we render 3D to in case we render at a lower resolution and upscale
Size2i internal_size = Size2i(0, 0);
float fsr_sharpness = 0.2f;
// Aliassing settings
RS::ViewportMSAA msaa_3d = RS::VIEWPORT_MSAA_DISABLED;
RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
bool use_taa = false;
bool use_debanding = false;
// Named Textures
struct NTKey {
StringName context;
StringName buffer_name;
bool operator==(const NTKey &p_val) const {
return (context == p_val.context) && (buffer_name == p_val.buffer_name);
}
static uint32_t hash(const NTKey &p_val) {
// FIXME, properly hash two stringnames together
uint32_t h = p_val.context.hash();
h = hash_murmur3_one_32(p_val.buffer_name.hash(), h);
return hash_fmix32(h);
}
NTKey() {}
NTKey(const StringName p_context, const StringName p_texture_name) {
context = p_context;
buffer_name = p_texture_name;
}
};
struct NamedTexture {
// Cache the data used to create our texture
RD::TextureFormat format;
bool is_unique; // If marked as unique, we return it into our pool
// Our texture objects, slices are lazy (i.e. only created when requested).
RID texture;
Vector<RID> slices;
Vector<Size2i> sizes;
};
mutable HashMap<NTKey, NamedTexture, NTKey> named_textures;
void update_sizes(NamedTexture &p_named_texture);
void free_named_texture(NamedTexture &p_named_texture);
// Data buffers
mutable HashMap<StringName, Ref<RenderBufferCustomDataRD>> data_buffers;
protected:
static void _bind_methods();
public:
RenderSceneBuffersRD();
virtual ~RenderSceneBuffersRD();
// info from our renderer
void set_can_be_storage(const bool p_can_be_storage) { can_be_storage = p_can_be_storage; }
void set_max_cluster_elements(const uint32_t p_max_elements) { max_cluster_elements = p_max_elements; }
void set_base_data_format(const RD::DataFormat p_base_data_format) { base_data_format = p_base_data_format; }
RD::DataFormat get_base_data_format() const { return base_data_format; }
void set_sseffects(RendererRD::SSEffects *p_ss_effects) { sse = p_ss_effects; }
void set_vrs(RendererRD::VRS *p_vrs) { vrs = p_vrs; }
void cleanup();
virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
virtual void set_fsr_sharpness(float p_fsr_sharpness) override;
virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) override;
virtual void set_use_debanding(bool p_use_debanding) override;
// Named Textures
bool has_texture(const StringName &p_context, const StringName &p_texture_name) const;
RID create_texture(const StringName &p_context, const StringName &p_texture_name, const RD::DataFormat p_data_format, const uint32_t p_usage_bits, const RD::TextureSamples p_texture_samples = RD::TEXTURE_SAMPLES_1, const Size2i p_size = Size2i(0, 0), const uint32_t p_layers = 0, const uint32_t p_mipmaps = 1, bool p_unique = true);
RID create_texture_from_format(const StringName &p_context, const StringName &p_texture_name, const RD::TextureFormat &p_texture_format, RD::TextureView p_view = RD::TextureView(), bool p_unique = true);
RID create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName p_view_name, RD::TextureView p_view = RD::TextureView());
RID get_texture(const StringName &p_context, const StringName &p_texture_name) const;
const RD::TextureFormat get_texture_format(const StringName &p_context, const StringName &p_texture_name) const;
RID get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap);
Size2i get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap);
void clear_context(const StringName &p_context);
// Allocate shared buffers
void allocate_blur_textures();
// Custom data
bool has_custom_data(const StringName &p_name);
void set_custom_data(const StringName &p_name, Ref<RenderBufferCustomDataRD> p_data);
Ref<RenderBufferCustomDataRD> get_custom_data(const StringName &p_name) const;
// Getters
_FORCE_INLINE_ RID get_render_target() const { return render_target; }
_FORCE_INLINE_ uint32_t get_view_count() const { return view_count; }
_FORCE_INLINE_ Size2i get_internal_size() const { return internal_size; }
_FORCE_INLINE_ Size2i get_target_size() const { return target_size; }
_FORCE_INLINE_ float get_fsr_sharpness() const { return fsr_sharpness; }
_FORCE_INLINE_ RS::ViewportMSAA get_msaa_3d() const { return msaa_3d; }
_FORCE_INLINE_ RS::ViewportScreenSpaceAA get_screen_space_aa() const { return screen_space_aa; }
_FORCE_INLINE_ bool get_use_taa() const { return use_taa; }
_FORCE_INLINE_ bool get_use_debanding() const { return use_debanding; }
uint64_t get_auto_exposure_version() const { return auto_exposure_version; }
void set_auto_exposure_version(const uint64_t p_auto_exposure_version) { auto_exposure_version = p_auto_exposure_version; }
// For our internal textures we provide some easy access methods.
_FORCE_INLINE_ RID get_internal_texture() const {
return get_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR);
}
_FORCE_INLINE_ RID get_internal_texture(const uint32_t p_layer) {
return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_COLOR, p_layer, 0);
}
_FORCE_INLINE_ RID get_depth_texture() const {
return get_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH);
}
_FORCE_INLINE_ RID get_depth_texture(const uint32_t p_layer) {
return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_DEPTH, p_layer, 0);
}
// back buffer (color)
RID get_back_buffer_texture() const { return has_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0) ? get_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0) : RID(); } // We (re)use our blur texture here.
// Velocity, currently only used by TAA (Clustered) but we'll be using this in other places soon too.
void ensure_velocity();
bool has_velocity_buffer(bool p_has_msaa) { return has_texture(RB_SCOPE_BUFFERS, p_has_msaa ? RB_TEX_VELOCITY_MSAA : RB_TEX_VELOCITY); }
RID get_velocity_buffer(bool p_get_msaa);
RID get_velocity_buffer(bool p_get_msaa, uint32_t p_layer) { return get_texture_slice(RB_SCOPE_BUFFERS, p_get_msaa ? RB_TEX_VELOCITY_MSAA : RB_TEX_VELOCITY, p_layer, 0); }
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Everything after this needs to be re-evaluated, this is all old implementation
ClusterBuilderRD *cluster_builder = nullptr;
struct WeightBuffers {
RID weight;
RID fb; // FB with both texture and weight writing into one level lower
};
// 2 full size, 2 half size
WeightBuffers weight_buffers[4]; // Only used in raster
struct Luminance {
Vector<RID> reduce;
RID current;
// used only on mobile renderer
Vector<RID> fb;
RID current_fb;
} luminance;
struct SSEffects {
RID linear_depth;
Vector<RID> linear_depth_slices;
RID downsample_uniform_set;
Projection last_frame_projection;
Transform3D last_frame_transform;
RendererRD::SSEffects::SSAORenderBuffers ssao;
RendererRD::SSEffects::SSILRenderBuffers ssil;
} ss_effects;
RendererRD::SSEffects::SSRRenderBuffers ssr;
RID get_ao_texture() const { return ss_effects.ssao.ao_final; }
RID get_ssil_texture() const { return ss_effects.ssil.ssil_final; }
};
#endif // RENDER_SCENE_BUFFERS_RD_H

View File

@ -2120,6 +2120,7 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) {
if (rt->color.is_valid()) {
RD::get_singleton()->free(rt->color);
}
rt->color_slices.clear(); // these are automatically freed.
if (rt->color_multisample.is_valid()) {
RD::get_singleton()->free(rt->color_multisample);
@ -2174,6 +2175,7 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
}
rd_color_attachment_format.samples = RD::TEXTURE_SAMPLES_1;
rd_color_attachment_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
rd_color_attachment_format.usage_bits |= RD::TEXTURE_USAGE_STORAGE_BIT; // FIXME we need this only when FSR is enabled
rd_color_attachment_format.shareable_formats.push_back(rt->color_format);
rd_color_attachment_format.shareable_formats.push_back(rt->color_format_srgb);
if (rt->msaa != RS::VIEWPORT_MSAA_DISABLED) {
@ -2392,6 +2394,24 @@ RID TextureStorage::render_target_get_rd_texture(RID p_render_target) {
return rt->color;
}
RID TextureStorage::render_target_get_rd_texture_slice(RID p_render_target, uint32_t p_layer) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
if (rt->view_count == 1) {
return rt->color;
} else {
ERR_FAIL_UNSIGNED_INDEX_V(p_layer, rt->view_count, RID());
if (rt->color_slices.size() == 0) {
for (uint32_t v = 0; v < rt->view_count; v++) {
RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->color, v, 0);
rt->color_slices.push_back(slice);
}
}
return rt->color_slices[p_layer];
}
}
RID TextureStorage::render_target_get_rd_backbuffer(RID p_render_target) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());

View File

@ -254,6 +254,7 @@ private:
uint32_t view_count;
RID framebuffer;
RID color;
Vector<RID> color_slices;
RID color_multisample; // Needed when MSAA is enabled.
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
@ -589,6 +590,7 @@ public:
Size2 render_target_get_size(RID p_render_target);
RID render_target_get_rd_framebuffer(RID p_render_target);
RID render_target_get_rd_texture(RID p_render_target);
RID render_target_get_rd_texture_slice(RID p_render_target, uint32_t p_layer);
RID render_target_get_rd_backbuffer(RID p_render_target);
RID render_target_get_rd_backbuffer_framebuffer(RID p_render_target);

View File

@ -155,8 +155,8 @@ void Utilities::base_update_dependency(RID p_base, DependencyTracker *p_instance
Dependency *dependency = TextureStorage::get_singleton()->decal_get_dependency(p_base);
p_instance->update_dependency(dependency);
} else if (GI::get_singleton()->owns_voxel_gi(p_base)) {
GI::VoxelGI *gip = GI::get_singleton()->get_voxel_gi(p_base);
p_instance->update_dependency(&gip->dependency);
Dependency *dependency = GI::get_singleton()->voxel_gi_get_dependency(p_base);
p_instance->update_dependency(dependency);
} else if (LightStorage::get_singleton()->owns_lightmap(p_base)) {
Dependency *dependency = LightStorage::get_singleton()->lightmap_get_dependency(p_base);
p_instance->update_dependency(dependency);

View File

@ -31,6 +31,7 @@
#ifndef RENDERER_SCENE_H
#define RENDERER_SCENE_H
#include "servers/rendering/storage/render_scene_buffers.h"
#include "servers/rendering_server.h"
#include "servers/xr/xr_interface.h"
@ -287,9 +288,7 @@ public:
/* Render Buffers */
virtual RID render_buffers_create() = 0;
virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) = 0;
virtual Ref<RenderSceneBuffers> render_buffers_create() = 0;
virtual void gi_set_use_half_resolution(bool p_enable) = 0;
@ -300,13 +299,13 @@ public:
virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) = 0;
virtual void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) = 0;
virtual void render_empty_scene(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_scenario, RID p_shadow_atlas) = 0;
struct RenderInfo {
int info[RS::VIEWPORT_RENDER_INFO_TYPE_MAX][RS::VIEWPORT_RENDER_INFO_MAX] = {};
};
virtual void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info = nullptr) = 0;
virtual void render_camera(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info = nullptr) = 0;
virtual void update() = 0;
virtual void render_probes() = 0;

View File

@ -2450,7 +2450,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
return animated_material_found;
}
void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info) {
void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info) {
#ifndef _3D_DISABLED
Camera *camera = camera_owner.get_or_null(p_camera);
@ -2910,7 +2910,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
}
}
void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_camera_data, RID p_render_buffers, RID p_environment, RID p_force_camera_attributes, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows, RendererScene::RenderInfo *r_render_info) {
void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_camera_data, const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, RID p_force_camera_attributes, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows, RendererScene::RenderInfo *r_render_info) {
Instance *render_reflection_probe = instance_owner.get_or_null(p_reflection_probe); //if null, not rendering to it
Scenario *scenario = scenario_owner.get_or_null(p_scenario);
@ -3270,8 +3270,6 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
for (uint32_t i = 0; i < cull.sdfgi.region_count; i++) {
render_sdfgi_data[i].instances.clear();
}
// virtual void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold,const RenderShadowData *p_render_shadows,int p_render_shadow_count,const RenderSDFGIData *p_render_sdfgi_regions,int p_render_sdfgi_region_count,const RenderSDFGIStaticLightData *p_render_sdfgi_static_lights=nullptr) = 0;
}
RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) {
@ -3295,7 +3293,7 @@ RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) {
return RID();
}
void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
void RendererSceneCull::render_empty_scene(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
#ifndef _3D_DISABLED
Scenario *scenario = scenario_owner.get_or_null(p_scenario);
@ -3383,7 +3381,8 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
RendererSceneRender::CameraData camera_data;
camera_data.set_camera(xform, cm, false, false);
_render_scene(&camera_data, RID(), environment, RID(), RSG::light_storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, mesh_lod_threshold, use_shadows);
Ref<RenderSceneBuffers> render_buffers;
_render_scene(&camera_data, render_buffers, environment, RID(), RSG::light_storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, mesh_lod_threshold, use_shadows);
} else {
//do roughness postprocess step until it believes it's done

View File

@ -1055,10 +1055,10 @@ public:
_FORCE_INLINE_ bool _visibility_parent_check(const CullData &p_cull_data, const InstanceData &p_instance_data);
bool _render_reflection_probe_step(Instance *p_instance, int p_step);
void _render_scene(const RendererSceneRender::CameraData *p_camera_data, RID p_render_buffers, RID p_environment, RID p_force_camera_attributes, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows = true, RenderInfo *r_render_info = nullptr);
void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas);
void _render_scene(const RendererSceneRender::CameraData *p_camera_data, const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, RID p_force_camera_attributes, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows = true, RenderInfo *r_render_info = nullptr);
void render_empty_scene(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_scenario, RID p_shadow_atlas);
void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RendererScene::RenderInfo *r_render_info = nullptr);
void render_camera(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RendererScene::RenderInfo *r_render_info = nullptr);
void update_dirty_instances();
void render_particle_colliders();
@ -1253,8 +1253,7 @@ public:
/* Render Buffers */
PASS0R(RID, render_buffers_create)
PASS13(render_buffers_configure, RID, RID, int, int, int, int, float, float, RS::ViewportMSAA, RS::ViewportScreenSpaceAA, bool, bool, uint32_t)
PASS0R(Ref<RenderSceneBuffers>, render_buffers_create)
PASS1(gi_set_use_half_resolution, bool)
/* Shadow Atlas */

View File

@ -36,6 +36,7 @@
#include "servers/rendering/renderer_geometry_instance.h"
#include "servers/rendering/renderer_scene.h"
#include "servers/rendering/storage/environment_storage.h"
#include "storage/render_scene_buffers.h"
#include "storage/utilities.h"
class RendererSceneRender {
@ -68,10 +69,10 @@ public:
/* SDFGI UPDATE */
virtual void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) = 0;
virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const = 0;
virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const = 0;
virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const = 0;
virtual void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) = 0;
virtual int sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const = 0;
virtual AABB sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const = 0;
virtual uint32_t sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const = 0;
/* SKY API */
@ -317,7 +318,7 @@ public:
void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_vaspect);
};
virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) = 0;
virtual void render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) = 0;
virtual void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) = 0;
@ -326,8 +327,7 @@ public:
virtual void set_time(double p_time, double p_step) = 0;
virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0;
virtual RID render_buffers_create() = 0;
virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) = 0;
virtual Ref<RenderSceneBuffers> render_buffers_create() = 0;
virtual void gi_set_use_half_resolution(bool p_enable) = 0;
virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0;

View File

@ -110,8 +110,7 @@ Vector<RendererViewport::Viewport *> RendererViewport::_sort_active_viewports()
void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
if (p_viewport->render_buffers.is_valid()) {
if (p_viewport->size.width == 0 || p_viewport->size.height == 0) {
RSG::scene->free(p_viewport->render_buffers);
p_viewport->render_buffers = RID();
p_viewport->render_buffers.unref();
} else {
const float scaling_3d_scale = p_viewport->scaling_3d_scale;
RS::ViewportScaling3DMode scaling_3d_mode = p_viewport->scaling_3d_mode;
@ -177,7 +176,7 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
// to compensate for the loss of sharpness.
const float texture_mipmap_bias = log2f(MIN(scaling_3d_scale, 1.0)) + p_viewport->texture_mipmap_bias;
RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, render_width, render_height, width, height, p_viewport->fsr_sharpness, texture_mipmap_bias, p_viewport->msaa_3d, p_viewport->screen_space_aa, p_viewport->use_taa, p_viewport->use_debanding, p_viewport->get_view_count());
p_viewport->render_buffers->configure(p_viewport->render_target, Size2i(render_width, render_height), Size2(width, height), p_viewport->fsr_sharpness, texture_mipmap_bias, p_viewport->msaa_3d, p_viewport->screen_space_aa, p_viewport->use_taa, p_viewport->use_debanding, p_viewport->get_view_count());
}
}
}
@ -784,7 +783,9 @@ void RendererViewport::viewport_set_fsr_sharpness(RID p_viewport, float p_sharpn
ERR_FAIL_COND(!viewport);
viewport->fsr_sharpness = p_sharpness;
_configure_3d_render_buffers(viewport);
if (viewport->render_buffers.is_valid()) {
viewport->render_buffers->set_fsr_sharpness(p_sharpness);
}
}
void RendererViewport::viewport_set_texture_mipmap_bias(RID p_viewport, float p_mipmap_bias) {
@ -792,7 +793,9 @@ void RendererViewport::viewport_set_texture_mipmap_bias(RID p_viewport, float p_
ERR_FAIL_COND(!viewport);
viewport->texture_mipmap_bias = p_mipmap_bias;
_configure_3d_render_buffers(viewport);
if (viewport->render_buffers.is_valid()) {
viewport->render_buffers->set_texture_mipmap_bias(p_mipmap_bias);
}
}
void RendererViewport::viewport_set_scaling_3d_scale(RID p_viewport, float p_scaling_3d_scale) {
@ -1128,7 +1131,9 @@ void RendererViewport::viewport_set_use_debanding(RID p_viewport, bool p_use_deb
return;
}
viewport->use_debanding = p_use_debanding;
_configure_3d_render_buffers(viewport);
if (viewport->render_buffers.is_valid()) {
viewport->render_buffers->set_use_debanding(p_use_debanding);
}
}
void RendererViewport::viewport_set_use_occlusion_culling(RID p_viewport, bool p_use_occlusion_culling) {
@ -1284,7 +1289,7 @@ bool RendererViewport::free(RID p_rid) {
RSG::texture_storage->render_target_free(viewport->render_target);
RSG::scene->free(viewport->shadow_atlas);
if (viewport->render_buffers.is_valid()) {
RSG::scene->free(viewport->render_buffers);
viewport->render_buffers.unref();
}
while (viewport->canvas_map.begin()) {

View File

@ -38,6 +38,7 @@
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering_server.h"
#include "servers/xr/xr_interface.h"
#include "storage/render_scene_buffers.h"
class RendererViewport {
public:
@ -64,7 +65,7 @@ public:
RS::ViewportUpdateMode update_mode = RenderingServer::VIEWPORT_UPDATE_WHEN_VISIBLE;
RID render_target;
RID render_target_texture;
RID render_buffers;
Ref<RenderSceneBuffers> render_buffers;
RS::ViewportMSAA msaa_2d = RenderingServer::VIEWPORT_MSAA_DISABLED;
RS::ViewportMSAA msaa_3d = RenderingServer::VIEWPORT_MSAA_DISABLED;

View File

@ -464,6 +464,32 @@ public:
Vector<DataFormat> shareable_formats;
bool is_resolve_buffer = false;
bool operator==(const TextureFormat &b) const {
if (format != b.format) {
return false;
} else if (width != b.width) {
return false;
} else if (height != b.height) {
return false;
} else if (depth != b.depth) {
return false;
} else if (array_layers != b.array_layers) {
return false;
} else if (mipmaps != b.mipmaps) {
return false;
} else if (texture_type != b.texture_type) {
return false;
} else if (samples != b.samples) {
return false;
} else if (usage_bits != b.usage_bits) {
return false;
} else if (shareable_formats != b.shareable_formats) {
return false;
} else {
return true;
}
}
TextureFormat() {
format = DATA_FORMAT_R8_UNORM;
width = 1;

View File

@ -0,0 +1,51 @@
/*************************************************************************/
/* render_scene_buffers.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "render_scene_buffers.h"
void RenderSceneBuffers::_bind_methods() {
ClassDB::bind_method(D_METHOD("configure", "render_target", "internal_size", "target_size", "fsr_sharpness", "texture_mipmap_bias", "msaa", "screen_space_aa", "use_taa", "use_debanding", "view_count"), &RenderSceneBuffers::configure);
}
void RenderSceneBuffers::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
GDVIRTUAL_CALL(_configure, p_render_target, p_internal_size, p_target_size, p_fsr_sharpness, p_texture_mipmap_bias, p_msaa, p_screen_space_aa, p_use_taa, p_use_debanding, p_view_count);
};
void RenderSceneBuffers::set_fsr_sharpness(float p_fsr_sharpness) {
GDVIRTUAL_CALL(_set_fsr_sharpness, p_fsr_sharpness);
}
void RenderSceneBuffers::set_texture_mipmap_bias(float p_texture_mipmap_bias) {
GDVIRTUAL_CALL(_set_texture_mipmap_bias, p_texture_mipmap_bias);
}
void RenderSceneBuffers::set_use_debanding(bool p_use_debanding) {
GDVIRTUAL_CALL(_set_use_debanding, p_use_debanding);
}

View File

@ -0,0 +1,60 @@
/*************************************************************************/
/* render_scene_buffers.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef RENDER_SCENE_BUFFERS_H
#define RENDER_SCENE_BUFFERS_H
#include "core/object/ref_counted.h"
#include "servers/rendering_server.h"
class RenderSceneBuffers : public RefCounted {
GDCLASS(RenderSceneBuffers, RefCounted);
protected:
static void _bind_methods();
GDVIRTUAL10(_configure, RID, Size2i, Size2i, float, float, RS::ViewportMSAA, RenderingServer::ViewportScreenSpaceAA, bool, bool, uint32_t)
GDVIRTUAL1(_set_fsr_sharpness, float)
GDVIRTUAL1(_set_texture_mipmap_bias, float)
GDVIRTUAL1(_set_use_debanding, bool)
public:
RenderSceneBuffers(){};
virtual ~RenderSceneBuffers(){};
virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count);
// for those settings that are unlikely to require buffers to be recreated, we'll add setters
virtual void set_fsr_sharpness(float p_fsr_sharpness);
virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias);
virtual void set_use_debanding(bool p_use_debanding);
};
#endif // RENDER_SCENE_BUFFERS_H

View File

@ -358,9 +358,5 @@ RID XRInterfaceExtension::get_render_target_texture(RID p_render_target) {
RID XRInterfaceExtension::get_render_target_depth(RID p_render_target) {
// TODO implement this, the problem is that our depth texture isn't part of our render target as it is used for 3D rendering only
// but we don't have access to our render buffers from here....
RendererSceneRenderRD * rd_scene = ?????;
ERR_FAIL_NULL_V_MSG(rd_scene, RID(), "Renderer scene render not setup");
return rd_scene->render_buffers_get_depth_texture(????????????);
}
*/