1/**************************************************************************/
2/* render_scene_buffers_rd.h */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#ifndef RENDER_SCENE_BUFFERS_RD_H
32#define RENDER_SCENE_BUFFERS_RD_H
33
34#include "../effects/vrs.h"
35#include "../framebuffer_cache_rd.h"
36#include "core/templates/hash_map.h"
37#include "render_buffer_custom_data_rd.h"
38#include "servers/rendering/rendering_device.h"
39#include "servers/rendering/rendering_device_binds.h"
40#include "servers/rendering/rendering_method.h"
41#include "servers/rendering/storage/render_scene_buffers.h"
42
43#define RB_SCOPE_BUFFERS SNAME("render_buffers")
44#define RB_SCOPE_VRS SNAME("VRS")
45
46#define RB_TEXTURE SNAME("texture")
47#define RB_TEX_COLOR SNAME("color")
48#define RB_TEX_COLOR_MSAA SNAME("color_msaa")
49#define RB_TEX_DEPTH SNAME("depth")
50#define RB_TEX_DEPTH_MSAA SNAME("depth_msaa")
51#define RB_TEX_VELOCITY SNAME("velocity")
52#define RB_TEX_VELOCITY_MSAA SNAME("velocity_msaa")
53
54#define RB_TEX_BLUR_0 SNAME("blur_0")
55#define RB_TEX_BLUR_1 SNAME("blur_1")
56#define RB_TEX_HALF_BLUR SNAME("half_blur") // only for raster!
57
58#define RB_TEX_BACK_DEPTH SNAME("back_depth")
59
60class RenderSceneBuffersRD : public RenderSceneBuffers {
61 GDCLASS(RenderSceneBuffersRD, RenderSceneBuffers);
62
63private:
64 bool can_be_storage = true;
65 uint32_t max_cluster_elements = 512;
66 RD::DataFormat base_data_format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
67 RendererRD::VRS *vrs = nullptr;
68 uint64_t auto_exposure_version = 1;
69
70 // Our render target represents our final destination that we display on screen.
71 RID render_target;
72 Size2i target_size = Size2i(0, 0);
73 uint32_t view_count = 1;
74
75 // The internal size of the textures we render 3D to in case we render at a lower resolution and upscale
76 Size2i internal_size = Size2i(0, 0);
77 RS::ViewportScaling3DMode scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF;
78 float fsr_sharpness = 0.2f;
79 float texture_mipmap_bias = 0.0f;
80
81 // Aliassing settings
82 RS::ViewportMSAA msaa_3d = RS::VIEWPORT_MSAA_DISABLED;
83 RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
84 bool use_taa = false;
85 bool use_debanding = false;
86 RD::TextureSamples texture_samples = RD::TEXTURE_SAMPLES_1;
87
88 // Named Textures
89
90 struct NTKey {
91 StringName context;
92 StringName buffer_name;
93
94 bool operator==(const NTKey &p_val) const {
95 return (context == p_val.context) && (buffer_name == p_val.buffer_name);
96 }
97
98 static uint32_t hash(const NTKey &p_val) {
99 uint32_t h = p_val.context.hash();
100 h = hash_murmur3_one_32(p_val.buffer_name.hash(), h);
101 return hash_fmix32(h);
102 }
103
104 NTKey() {}
105 NTKey(const StringName p_context, const StringName p_texture_name) {
106 context = p_context;
107 buffer_name = p_texture_name;
108 }
109 };
110
111 struct NTSliceKey {
112 uint32_t layer;
113 uint32_t layers;
114 uint32_t mipmap;
115 uint32_t mipmaps;
116
117 bool operator==(const NTSliceKey &p_val) const {
118 return (layer == p_val.layer) && (layers == p_val.layers) && (mipmap == p_val.mipmap) && (mipmaps == p_val.mipmaps);
119 }
120
121 static uint32_t hash(const NTSliceKey &p_val) {
122 uint32_t h = hash_murmur3_one_32(p_val.layer);
123 h = hash_murmur3_one_32(p_val.layers, h);
124 h = hash_murmur3_one_32(p_val.mipmap, h);
125 h = hash_murmur3_one_32(p_val.mipmaps, h);
126 return hash_fmix32(h);
127 }
128
129 NTSliceKey() {}
130 NTSliceKey(uint32_t p_layer, uint32_t p_layers, uint32_t p_mipmap, uint32_t p_mipmaps) {
131 layer = p_layer;
132 layers = p_layers;
133 mipmap = p_mipmap;
134 mipmaps = p_mipmaps;
135 }
136 };
137
138 struct NamedTexture {
139 // Cache the data used to create our texture
140 RD::TextureFormat format;
141 bool is_unique; // If marked as unique, we return it into our pool
142
143 // Our texture objects, slices are lazy (i.e. only created when requested).
144 RID texture;
145 mutable HashMap<NTSliceKey, RID, NTSliceKey> slices;
146 Vector<Size2i> sizes;
147 };
148
149 mutable HashMap<NTKey, NamedTexture, NTKey> named_textures;
150 void update_sizes(NamedTexture &p_named_texture);
151 void free_named_texture(NamedTexture &p_named_texture);
152
153 // Data buffers
154 mutable HashMap<StringName, Ref<RenderBufferCustomDataRD>> data_buffers;
155
156protected:
157 static void _bind_methods();
158
159public:
160 RenderSceneBuffersRD();
161 virtual ~RenderSceneBuffersRD();
162
163 // info from our renderer
164 void set_can_be_storage(const bool p_can_be_storage) { can_be_storage = p_can_be_storage; }
165 void set_max_cluster_elements(const uint32_t p_max_elements) { max_cluster_elements = p_max_elements; }
166 uint32_t get_max_cluster_elements() { return max_cluster_elements; }
167 void set_base_data_format(const RD::DataFormat p_base_data_format) { base_data_format = p_base_data_format; }
168 RD::DataFormat get_base_data_format() const { return base_data_format; }
169 void set_vrs(RendererRD::VRS *p_vrs) { vrs = p_vrs; }
170
171 void cleanup();
172 virtual void configure(const RenderSceneBuffersConfiguration *p_config) override;
173 void configure_for_reflections(const Size2i p_reflection_size);
174 virtual void set_fsr_sharpness(float p_fsr_sharpness) override;
175 virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) override;
176 virtual void set_use_debanding(bool p_use_debanding) override;
177
178 // Named Textures
179
180 bool has_texture(const StringName &p_context, const StringName &p_texture_name) const;
181 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);
182 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);
183 RID create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName p_view_name, RD::TextureView p_view = RD::TextureView());
184 RID get_texture(const StringName &p_context, const StringName &p_texture_name) const;
185 const RD::TextureFormat get_texture_format(const StringName &p_context, const StringName &p_texture_name) const;
186 RID get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap, const uint32_t p_layers = 1, const uint32_t p_mipmaps = 1);
187 Size2i get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_mipmap);
188
189 void clear_context(const StringName &p_context);
190
191 // Allocate shared buffers
192 void allocate_blur_textures();
193
194 // Custom data
195 bool has_custom_data(const StringName &p_name);
196 void set_custom_data(const StringName &p_name, Ref<RenderBufferCustomDataRD> p_data);
197 Ref<RenderBufferCustomDataRD> get_custom_data(const StringName &p_name) const;
198
199 // Getters
200
201 _FORCE_INLINE_ RID get_render_target() const { return render_target; }
202 _FORCE_INLINE_ uint32_t get_view_count() const { return view_count; }
203 _FORCE_INLINE_ Size2i get_internal_size() const { return internal_size; }
204 _FORCE_INLINE_ Size2i get_target_size() const { return target_size; }
205 _FORCE_INLINE_ RS::ViewportScaling3DMode get_scaling_3d_mode() const { return scaling_3d_mode; }
206 _FORCE_INLINE_ float get_fsr_sharpness() const { return fsr_sharpness; }
207 _FORCE_INLINE_ RS::ViewportMSAA get_msaa_3d() const { return msaa_3d; }
208 _FORCE_INLINE_ RD::TextureSamples get_texture_samples() const { return texture_samples; }
209 _FORCE_INLINE_ RS::ViewportScreenSpaceAA get_screen_space_aa() const { return screen_space_aa; }
210 _FORCE_INLINE_ bool get_use_taa() const { return use_taa; }
211 _FORCE_INLINE_ bool get_use_debanding() const { return use_debanding; }
212
213 uint64_t get_auto_exposure_version() const { return auto_exposure_version; }
214 void set_auto_exposure_version(const uint64_t p_auto_exposure_version) { auto_exposure_version = p_auto_exposure_version; }
215
216 // For our internal textures we provide some easy access methods.
217
218 _FORCE_INLINE_ bool has_internal_texture() const {
219 return has_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR);
220 }
221 _FORCE_INLINE_ RID get_internal_texture() const {
222 return get_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR);
223 }
224 _FORCE_INLINE_ RID get_internal_texture(const uint32_t p_layer) {
225 return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_COLOR, p_layer, 0);
226 }
227 _FORCE_INLINE_ RID get_color_msaa() const {
228 return get_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR_MSAA);
229 }
230 _FORCE_INLINE_ RID get_color_msaa(uint32_t p_layer) {
231 return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_COLOR_MSAA, p_layer, 0);
232 }
233
234 bool has_depth_texture();
235 RID get_depth_texture();
236 RID get_depth_texture(const uint32_t p_layer);
237
238 RID get_depth_msaa() const {
239 return get_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_MSAA);
240 }
241 RID get_depth_msaa(uint32_t p_layer) {
242 return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_MSAA, p_layer, 0);
243 }
244
245 // back buffer (color)
246 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.
247
248 // Velocity, currently only used by TAA (Clustered) but we'll be using this in other places soon too.
249
250 void ensure_velocity();
251 bool has_velocity_buffer(bool p_has_msaa);
252 RID get_velocity_buffer(bool p_get_msaa);
253 RID get_velocity_buffer(bool p_get_msaa, uint32_t p_layer);
254
255 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
256 // Our classDB doesn't support calling our normal exposed functions
257
258private:
259 RID _create_texture_from_format(const StringName &p_context, const StringName &p_texture_name, const Ref<RDTextureFormat> &p_texture_format, const Ref<RDTextureView> &p_view = Ref<RDTextureView>(), bool p_unique = true);
260 RID _create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName p_view_name, const Ref<RDTextureView> p_view = Ref<RDTextureView>());
261 Ref<RDTextureFormat> _get_texture_format(const StringName &p_context, const StringName &p_texture_name) const;
262
263 // For color and depth as exposed to extensions, we return the buffer that we're rendering into.
264 // Resolving happens after effects etc. are run.
265 RID _get_color_texture() {
266 if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED && has_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR_MSAA)) {
267 return get_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR_MSAA);
268 } else if (has_internal_texture()) {
269 return get_internal_texture();
270 } else {
271 return RID();
272 }
273 }
274
275 RID _get_color_layer(const uint32_t p_layer) {
276 if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED && has_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR_MSAA)) {
277 return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_COLOR_MSAA, p_layer, 0);
278 } else if (has_internal_texture()) {
279 return get_internal_texture(p_layer);
280 } else {
281 return RID();
282 }
283 }
284
285 RID _get_depth_texture() {
286 if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED && has_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_MSAA)) {
287 return get_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_MSAA);
288 } else if (has_depth_texture()) {
289 return get_depth_texture();
290 } else {
291 return RID();
292 }
293 }
294
295 RID _get_depth_layer(const uint32_t p_layer) {
296 if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED && has_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_MSAA)) {
297 return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_MSAA, p_layer, 0);
298 } else if (has_depth_texture()) {
299 return get_depth_texture(p_layer);
300 } else {
301 return RID();
302 }
303 }
304
305 RID _get_velocity_texture() {
306 if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED && has_velocity_buffer(true)) {
307 return get_velocity_buffer(true);
308 } else if (has_velocity_buffer(false)) {
309 return get_velocity_buffer(false);
310 } else {
311 return RID();
312 }
313 }
314
315 RID _get_velocity_layer(const uint32_t p_layer) {
316 if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED && has_velocity_buffer(true)) {
317 return get_velocity_buffer(true, p_layer);
318 } else if (has_velocity_buffer(false)) {
319 return get_velocity_buffer(false, p_layer);
320 } else {
321 return RID();
322 }
323 }
324
325 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
326 // Everything after this needs to be re-evaluated, this is all old implementation
327public:
328 struct WeightBuffers {
329 RID weight;
330 RID fb; // FB with both texture and weight writing into one level lower
331 };
332
333 // 2 full size, 2 half size
334 WeightBuffers weight_buffers[4]; // Only used in raster
335};
336
337#endif // RENDER_SCENE_BUFFERS_RD_H
338