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 | |
60 | class RenderSceneBuffersRD : public RenderSceneBuffers { |
61 | GDCLASS(RenderSceneBuffersRD, RenderSceneBuffers); |
62 | |
63 | private: |
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 | |
156 | protected: |
157 | static void _bind_methods(); |
158 | |
159 | public: |
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 | |
258 | private: |
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 |
327 | public: |
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 | |