summaryrefslogtreecommitdiff
path: root/servers/rendering/renderer_rd/storage_rd/texture_storage.h
blob: f710de110001a66e2ac97d15928d394ff8e7f933 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
/**************************************************************************/
/*  texture_storage.h                                                     */
/**************************************************************************/
/*                         This file is part of:                          */
/*                             GODOT ENGINE                               */
/*                        https://godotengine.org                         */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */
/*                                                                        */
/* 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 TEXTURE_STORAGE_RD_H
#define TEXTURE_STORAGE_RD_H

#include "core/templates/local_vector.h"
#include "core/templates/paged_array.h"
#include "core/templates/rid_owner.h"
#include "servers/rendering/renderer_rd/shaders/canvas_sdf.glsl.gen.h"
#include "servers/rendering/renderer_rd/storage_rd/forward_id_storage.h"
#include "servers/rendering/rendering_server_default.h"
#include "servers/rendering/storage/texture_storage.h"
#include "servers/rendering/storage/utilities.h"

namespace RendererRD {

class LightStorage;
class MaterialStorage;

class TextureStorage : public RendererTextureStorage {
public:
	enum DefaultRDTexture {
		DEFAULT_RD_TEXTURE_WHITE,
		DEFAULT_RD_TEXTURE_BLACK,
		DEFAULT_RD_TEXTURE_TRANSPARENT,
		DEFAULT_RD_TEXTURE_NORMAL,
		DEFAULT_RD_TEXTURE_ANISO,
		DEFAULT_RD_TEXTURE_DEPTH,
		DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER,
		DEFAULT_RD_TEXTURE_CUBEMAP_BLACK,
		DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK,
		DEFAULT_RD_TEXTURE_CUBEMAP_WHITE,
		DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_WHITE,
		DEFAULT_RD_TEXTURE_3D_WHITE,
		DEFAULT_RD_TEXTURE_3D_BLACK,
		DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE,
		DEFAULT_RD_TEXTURE_2D_ARRAY_BLACK,
		DEFAULT_RD_TEXTURE_2D_ARRAY_NORMAL,
		DEFAULT_RD_TEXTURE_2D_ARRAY_DEPTH,
		DEFAULT_RD_TEXTURE_2D_UINT,
		DEFAULT_RD_TEXTURE_VRS,
		DEFAULT_RD_TEXTURE_MAX
	};

	enum TextureType {
		TYPE_2D,
		TYPE_LAYERED,
		TYPE_3D
	};

private:
	friend class LightStorage;
	friend class MaterialStorage;

	static TextureStorage *singleton;

	RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX];

	/* Canvas Texture API */

	class CanvasTexture {
	public:
		RID diffuse;
		RID normal_map;
		RID specular;
		Color specular_color = Color(1, 1, 1, 1);
		float shininess = 1.0;

		RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
		RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
		RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];

		Size2i size_cache = Size2i(1, 1);
		bool use_normal_cache = false;
		bool use_specular_cache = false;
		bool cleared_cache = true;

		void clear_sets();
		~CanvasTexture();
	};

	RID_Owner<CanvasTexture, true> canvas_texture_owner;

	/* Texture API */

	struct RenderTarget;

	class Texture {
	public:
		TextureType type;
		RS::TextureLayeredType layered_type = RS::TEXTURE_LAYERED_2D_ARRAY;

		RenderingDevice::TextureType rd_type;
		RID rd_texture;
		RID rd_texture_srgb;
		RenderingDevice::DataFormat rd_format;
		RenderingDevice::DataFormat rd_format_srgb;

		RD::TextureView rd_view;

		Image::Format format;
		Image::Format validated_format;

		int width;
		int height;
		int depth;
		int layers;
		int mipmaps;

		int height_2d;
		int width_2d;

		struct BufferSlice3D {
			Size2i size;
			uint32_t offset = 0;
			uint32_t buffer_size = 0;
		};
		Vector<BufferSlice3D> buffer_slices_3d;
		uint32_t buffer_size_3d = 0;

		RenderTarget *render_target = nullptr;
		bool is_render_target;
		bool is_proxy;

		Ref<Image> image_cache_2d;
		String path;

		RID proxy_to;
		Vector<RID> proxies;

		HashSet<RID> lightmap_users;

		RS::TextureDetectCallback detect_3d_callback = nullptr;
		void *detect_3d_callback_ud = nullptr;

		RS::TextureDetectCallback detect_normal_callback = nullptr;
		void *detect_normal_callback_ud = nullptr;

		RS::TextureDetectRoughnessCallback detect_roughness_callback = nullptr;
		void *detect_roughness_callback_ud = nullptr;

		CanvasTexture *canvas_texture = nullptr;

		void cleanup();
	};

	//textures can be created from threads, so this RID_Owner is thread safe
	mutable RID_Owner<Texture, true> texture_owner;
	Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); };

	struct TextureToRDFormat {
		RD::DataFormat format;
		RD::DataFormat format_srgb;
		RD::TextureSwizzle swizzle_r;
		RD::TextureSwizzle swizzle_g;
		RD::TextureSwizzle swizzle_b;
		RD::TextureSwizzle swizzle_a;
		TextureToRDFormat() {
			format = RD::DATA_FORMAT_MAX;
			format_srgb = RD::DATA_FORMAT_MAX;
			swizzle_r = RD::TEXTURE_SWIZZLE_R;
			swizzle_g = RD::TEXTURE_SWIZZLE_G;
			swizzle_b = RD::TEXTURE_SWIZZLE_B;
			swizzle_a = RD::TEXTURE_SWIZZLE_A;
		}
	};

	Ref<Image> _validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format);
	void _texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0, bool p_immediate = false);

	/* DECAL API */

	struct DecalAtlas {
		struct Texture {
			int panorama_to_dp_users;
			int users;
			Rect2 uv_rect;
		};

		struct SortItem {
			RID texture;
			Size2i pixel_size;
			Size2i size;
			Point2i pos;

			bool operator<(const SortItem &p_item) const {
				//sort larger to smaller
				if (size.height == p_item.size.height) {
					return size.width > p_item.size.width;
				} else {
					return size.height > p_item.size.height;
				}
			}
		};

		HashMap<RID, Texture> textures;
		bool dirty = true;
		int mipmaps = 5;

		RID texture;
		RID texture_srgb;
		struct MipMap {
			RID fb;
			RID texture;
			Size2i size;
		};
		Vector<MipMap> texture_mipmaps;

		Size2i size;
	} decal_atlas;

	struct Decal {
		Vector3 size = Vector3(2, 2, 2);
		RID textures[RS::DECAL_TEXTURE_MAX];
		float emission_energy = 1.0;
		float albedo_mix = 1.0;
		Color modulate = Color(1, 1, 1, 1);
		uint32_t cull_mask = (1 << 20) - 1;
		float upper_fade = 0.3;
		float lower_fade = 0.3;
		bool distance_fade = false;
		float distance_fade_begin = 40.0;
		float distance_fade_length = 10.0;
		float normal_fade = 0.0;

		Dependency dependency;
	};

	mutable RID_Owner<Decal, true> decal_owner;

	/* DECAL INSTANCE */

	struct DecalInstance {
		RID decal;
		Transform3D transform;
		float sorting_offset = 0.0;
		uint32_t cull_mask = 0;
		RendererRD::ForwardID forward_id = -1;
	};

	mutable RID_Owner<DecalInstance> decal_instance_owner;

	/* DECAL DATA (UBO) */

	struct DecalData {
		float xform[16];
		float inv_extents[3];
		float albedo_mix;
		float albedo_rect[4];
		float normal_rect[4];
		float orm_rect[4];
		float emission_rect[4];
		float modulate[4];
		float emission_energy;
		uint32_t mask;
		float upper_fade;
		float lower_fade;
		float normal_xform[12];
		float normal[3];
		float normal_fade;
	};

	struct DecalInstanceSort {
		float depth;
		DecalInstance *decal_instance;
		Decal *decal;
		bool operator<(const DecalInstanceSort &p_sort) const {
			return depth < p_sort.depth;
		}
	};

	uint32_t max_decals = 0;
	uint32_t decal_count = 0;
	DecalData *decals = nullptr;
	DecalInstanceSort *decal_sort = nullptr;
	RID decal_buffer;

	/* RENDER TARGET API */

	struct RenderTarget {
		Size2i size;
		uint32_t view_count;
		RID color;
		Vector<RID> color_slices;
		RID color_multisample; // Needed when MSAA is enabled.

		RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;

		//used for retrieving from CPU
		RD::DataFormat color_format = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
		RD::DataFormat color_format_srgb = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
		Image::Format image_format = Image::FORMAT_L8;

		bool is_transparent = false;

		bool sdf_enabled = false;

		RID backbuffer; //used for effects
		RID backbuffer_fb;
		RID backbuffer_mipmap0;

		Vector<RID> backbuffer_mipmaps;

		RID framebuffer_uniform_set;
		RID backbuffer_uniform_set;

		RID sdf_buffer_write;
		RID sdf_buffer_write_fb;
		RID sdf_buffer_process[2];
		RID sdf_buffer_read;
		RID sdf_buffer_process_uniform_sets[2];
		RS::ViewportSDFOversize sdf_oversize = RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT;
		RS::ViewportSDFScale sdf_scale = RS::VIEWPORT_SDF_SCALE_50_PERCENT;
		Size2i process_size;

		// VRS
		RS::ViewportVRSMode vrs_mode = RS::VIEWPORT_VRS_DISABLED;
		RID vrs_texture;

		// overridden textures
		struct RTOverridden {
			RID color;
			RID depth;
			RID velocity;

			// In a multiview scenario, which is the most likely where we
			// override our destination textures, we need to obtain slices
			// for each layer of these textures.
			// These are likely changing every frame as we loop through
			// texture chains hence we add a cache to manage these slices.
			// For this we define a key using the RID of the texture and
			// the layer for which we create a slice.
			struct SliceKey {
				RID rid;
				uint32_t layer = 0;

				bool operator==(const SliceKey &p_val) const {
					return (rid == p_val.rid) && (layer == p_val.layer);
				}

				static uint32_t hash(const SliceKey &p_val) {
					uint32_t h = hash_one_uint64(p_val.rid.get_id());
					h = hash_murmur3_one_32(p_val.layer, h);
					return hash_fmix32(h);
				}

				SliceKey() {}
				SliceKey(RID p_rid, uint32_t p_layer) {
					rid = p_rid;
					layer = p_layer;
				}
			};

			mutable HashMap<SliceKey, RID, SliceKey> cached_slices;
		} overridden;

		//texture generated for this owner (nor RD).
		RID texture;
		bool was_used;

		//clear request
		bool clear_requested;
		Color clear_color;

		RID get_framebuffer();
	};

	mutable RID_Owner<RenderTarget> render_target_owner;
	RenderTarget *get_render_target(RID p_rid) const { return render_target_owner.get_or_null(p_rid); };

	void _clear_render_target(RenderTarget *rt);
	void _update_render_target(RenderTarget *rt);
	void _create_render_target_backbuffer(RenderTarget *rt);
	void _render_target_allocate_sdf(RenderTarget *rt);
	void _render_target_clear_sdf(RenderTarget *rt);
	Rect2i _render_target_get_sdf_rect(const RenderTarget *rt) const;

	struct RenderTargetSDF {
		enum {
			SHADER_LOAD,
			SHADER_LOAD_SHRINK,
			SHADER_PROCESS,
			SHADER_PROCESS_OPTIMIZED,
			SHADER_STORE,
			SHADER_STORE_SHRINK,
			SHADER_MAX
		};

		struct PushConstant {
			int32_t size[2];
			int32_t stride;
			int32_t shift;
			int32_t base_size[2];
			int32_t pad[2];
		};

		CanvasSdfShaderRD shader;
		RID shader_version;
		RID pipelines[SHADER_MAX];
	} rt_sdf;

public:
	static TextureStorage *get_singleton();

	_FORCE_INLINE_ RID texture_rd_get_default(DefaultRDTexture p_texture) {
		return default_rd_textures[p_texture];
	}

	TextureStorage();
	virtual ~TextureStorage();

	bool free(RID p_rid);

	/* Canvas Texture API */

	bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); };

	virtual RID canvas_texture_allocate() override;
	virtual void canvas_texture_initialize(RID p_rid) override;
	virtual void canvas_texture_free(RID p_rid) override;

	virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override;
	virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override;

	virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override;
	virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override;

	bool canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular);

	/* Texture API */

	bool owns_texture(RID p_rid) const { return texture_owner.owns(p_rid); };

	virtual bool can_create_resources_async() const override;

	virtual RID texture_allocate() override;
	virtual void texture_free(RID p_rid) override;

	virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override;
	virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override;
	virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override;
	virtual void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent

	virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override;
	virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override;
	virtual void texture_proxy_update(RID p_proxy, RID p_base) override;

	//these two APIs can be used together or in combination with the others.
	virtual void texture_2d_placeholder_initialize(RID p_texture) override;
	virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override;
	virtual void texture_3d_placeholder_initialize(RID p_texture) override;

	virtual Ref<Image> texture_2d_get(RID p_texture) const override;
	virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override;
	virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const override;

	virtual void texture_replace(RID p_texture, RID p_by_texture) override;
	virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) override;

	virtual void texture_set_path(RID p_texture, const String &p_path) override;
	virtual String texture_get_path(RID p_texture) const override;

	virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override;
	virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override;
	virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override;

	virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) override;

	virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override;

	virtual Size2 texture_size_with_proxy(RID p_proxy) override;

	virtual RID texture_get_rd_texture_rid(RID p_texture, bool p_srgb = false) const override;

	//internal usage
	_FORCE_INLINE_ TextureType texture_get_type(RID p_texture) {
		RendererRD::TextureStorage::Texture *tex = texture_owner.get_or_null(p_texture);
		if (tex == nullptr) {
			return TYPE_2D;
		}

		return tex->type;
	}

	_FORCE_INLINE_ int texture_get_layers(RID p_texture) {
		RendererRD::TextureStorage::Texture *tex = texture_owner.get_or_null(p_texture);
		if (tex == nullptr) {
			return 1;
		}

		return tex->layers;
	}

	_FORCE_INLINE_ RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) {
		if (p_texture.is_null()) {
			return RID();
		}
		RendererRD::TextureStorage::Texture *tex = texture_owner.get_or_null(p_texture);

		if (!tex) {
			return RID();
		}
		return (p_srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture;
	}

	_FORCE_INLINE_ Size2i texture_2d_get_size(RID p_texture) {
		if (p_texture.is_null()) {
			return Size2i();
		}
		RendererRD::TextureStorage::Texture *tex = texture_owner.get_or_null(p_texture);

		if (!tex) {
			return Size2i();
		}
		return Size2i(tex->width_2d, tex->height_2d);
	}

	/* DECAL API */

	void update_decal_atlas();

	bool owns_decal(RID p_rid) const { return decal_owner.owns(p_rid); };

	RID decal_atlas_get_texture() const;
	RID decal_atlas_get_texture_srgb() const;
	_FORCE_INLINE_ Rect2 decal_atlas_get_texture_rect(RID p_texture) {
		DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture);
		if (!t) {
			return Rect2();
		}

		return t->uv_rect;
	}

	virtual RID decal_allocate() override;
	virtual void decal_initialize(RID p_decal) override;
	virtual void decal_free(RID p_rid) override;

	virtual void decal_set_size(RID p_decal, const Vector3 &p_size) override;
	virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override;
	virtual void decal_set_emission_energy(RID p_decal, float p_energy) override;
	virtual void decal_set_albedo_mix(RID p_decal, float p_mix) override;
	virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) override;
	virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) override;
	virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) override;
	virtual void decal_set_fade(RID p_decal, float p_above, float p_below) override;
	virtual void decal_set_normal_fade(RID p_decal, float p_fade) override;

	void decal_atlas_mark_dirty_on_texture(RID p_texture);
	void decal_atlas_remove_texture(RID p_texture);

	virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override;
	virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override;

	_FORCE_INLINE_ Vector3 decal_get_size(RID p_decal) {
		const Decal *decal = decal_owner.get_or_null(p_decal);
		return decal->size;
	}

	_FORCE_INLINE_ RID decal_get_texture(RID p_decal, RS::DecalTexture p_texture) {
		const Decal *decal = decal_owner.get_or_null(p_decal);
		return decal->textures[p_texture];
	}

	_FORCE_INLINE_ Color decal_get_modulate(RID p_decal) {
		const Decal *decal = decal_owner.get_or_null(p_decal);
		return decal->modulate;
	}

	_FORCE_INLINE_ float decal_get_emission_energy(RID p_decal) {
		const Decal *decal = decal_owner.get_or_null(p_decal);
		return decal->emission_energy;
	}

	_FORCE_INLINE_ float decal_get_albedo_mix(RID p_decal) {
		const Decal *decal = decal_owner.get_or_null(p_decal);
		return decal->albedo_mix;
	}

	_FORCE_INLINE_ uint32_t decal_get_cull_mask(RID p_decal) {
		const Decal *decal = decal_owner.get_or_null(p_decal);
		return decal->cull_mask;
	}

	_FORCE_INLINE_ float decal_get_upper_fade(RID p_decal) {
		const Decal *decal = decal_owner.get_or_null(p_decal);
		return decal->upper_fade;
	}

	_FORCE_INLINE_ float decal_get_lower_fade(RID p_decal) {
		const Decal *decal = decal_owner.get_or_null(p_decal);
		return decal->lower_fade;
	}

	_FORCE_INLINE_ float decal_get_normal_fade(RID p_decal) {
		const Decal *decal = decal_owner.get_or_null(p_decal);
		return decal->normal_fade;
	}

	_FORCE_INLINE_ bool decal_is_distance_fade_enabled(RID p_decal) {
		const Decal *decal = decal_owner.get_or_null(p_decal);
		return decal->distance_fade;
	}

	_FORCE_INLINE_ float decal_get_distance_fade_begin(RID p_decal) {
		const Decal *decal = decal_owner.get_or_null(p_decal);
		return decal->distance_fade_begin;
	}

	_FORCE_INLINE_ float decal_get_distance_fade_length(RID p_decal) {
		const Decal *decal = decal_owner.get_or_null(p_decal);
		return decal->distance_fade_length;
	}

	virtual AABB decal_get_aabb(RID p_decal) const override;
	virtual uint32_t decal_get_cull_mask(RID p_decal) const override;
	Dependency *decal_get_dependency(RID p_decal);

	/* DECAL INSTANCE API */

	bool owns_decal_instance(RID p_rid) const { return decal_instance_owner.owns(p_rid); }

	virtual RID decal_instance_create(RID p_decal) override;
	virtual void decal_instance_free(RID p_decal_instance) override;
	virtual void decal_instance_set_transform(RID p_decal_instance, const Transform3D &p_transform) override;
	virtual void decal_instance_set_sorting_offset(RID p_decal_instance, float p_sorting_offset) override;

	_FORCE_INLINE_ RID decal_instance_get_base(RID p_decal_instance) const {
		DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance);
		return di->decal;
	}

	_FORCE_INLINE_ RendererRD::ForwardID decal_instance_get_forward_id(RID p_decal_instance) const {
		DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance);
		return di->forward_id;
	}

	_FORCE_INLINE_ Transform3D decal_instance_get_transform(RID p_decal_instance) const {
		DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance);
		return di->transform;
	}

	_FORCE_INLINE_ ForwardID decal_instance_get_forward_id(RID p_decal_instance) {
		DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance);
		return di->forward_id;
	}

	_FORCE_INLINE_ void decal_instance_set_cullmask(RID p_decal_instance, uint32_t p_cull_mask) const {
		DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance);
		di->cull_mask = p_cull_mask;
	}

	/* DECAL DATA API */

	void free_decal_data();
	void set_max_decals(const uint32_t p_max_decals);
	RID get_decal_buffer() { return decal_buffer; }
	void update_decal_buffer(const PagedArray<RID> &p_decals, const Transform3D &p_camera_xform);

	/* RENDER TARGET API */

	bool owns_render_target(RID p_rid) const { return render_target_owner.owns(p_rid); };

	virtual RID render_target_create() override;
	virtual void render_target_free(RID p_rid) override;

	virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) override;
	virtual Point2i render_target_get_position(RID p_render_target) const override;
	virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override;
	virtual Size2i render_target_get_size(RID p_render_target) const override;
	virtual void render_target_set_transparent(RID p_render_target, bool p_is_transparent) override;
	virtual bool render_target_get_transparent(RID p_render_target) const override;
	virtual void render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) override;
	virtual bool render_target_get_direct_to_screen(RID p_render_target) const override;
	virtual bool render_target_was_used(RID p_render_target) const override;
	virtual void render_target_set_as_unused(RID p_render_target) override;
	virtual void render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) override;
	virtual RS::ViewportMSAA render_target_get_msaa(RID p_render_target) const override;

	void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps);
	void render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color);
	void render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region);
	RID render_target_get_back_buffer_uniform_set(RID p_render_target, RID p_base_shader);

	virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color) override;
	virtual bool render_target_is_clear_requested(RID p_render_target) override;
	virtual Color render_target_get_clear_request_color(RID p_render_target) override;
	virtual void render_target_disable_clear_request(RID p_render_target) override;
	virtual void render_target_do_clear_request(RID p_render_target) override;

	virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override;
	RID render_target_get_sdf_texture(RID p_render_target);
	RID render_target_get_sdf_framebuffer(RID p_render_target);
	void render_target_sdf_process(RID p_render_target);
	virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const override;
	virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override;
	bool render_target_is_sdf_enabled(RID p_render_target) const;

	virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override;
	virtual RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const override;
	virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override;
	virtual RID render_target_get_vrs_texture(RID p_render_target) const override;

	virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) override;
	virtual RID render_target_get_override_color(RID p_render_target) const override;
	virtual RID render_target_get_override_depth(RID p_render_target) const override;
	RID render_target_get_override_depth_slice(RID p_render_target, const uint32_t p_layer) const;
	virtual RID render_target_get_override_velocity(RID p_render_target) const override;
	RID render_target_get_override_velocity_slice(RID p_render_target, const uint32_t p_layer) const;

	virtual RID render_target_get_texture(RID p_render_target) override;

	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_texture_msaa(RID p_render_target);
	RID render_target_get_rd_backbuffer(RID p_render_target);
	RID render_target_get_rd_backbuffer_framebuffer(RID p_render_target);

	RID render_target_get_framebuffer_uniform_set(RID p_render_target);
	RID render_target_get_backbuffer_uniform_set(RID p_render_target);

	void render_target_set_framebuffer_uniform_set(RID p_render_target, RID p_uniform_set);
	void render_target_set_backbuffer_uniform_set(RID p_render_target, RID p_uniform_set);
};

} // namespace RendererRD

#endif // TEXTURE_STORAGE_RD_H