1/**************************************************************************/
2/* copy_effects.cpp */
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#include "copy_effects.h"
32#include "core/config/project_settings.h"
33#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
34#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
35#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
36#include "thirdparty/misc/cubemap_coeffs.h"
37
38using namespace RendererRD;
39
40CopyEffects *CopyEffects::singleton = nullptr;
41
42CopyEffects *CopyEffects::get_singleton() {
43 return singleton;
44}
45
46CopyEffects::CopyEffects(bool p_prefer_raster_effects) {
47 singleton = this;
48 prefer_raster_effects = p_prefer_raster_effects;
49
50 if (prefer_raster_effects) {
51 // init blur shader (on compute use copy shader)
52
53 Vector<String> blur_modes;
54 blur_modes.push_back("\n#define MODE_MIPMAP\n"); // BLUR_MIPMAP
55 blur_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n"); // BLUR_MODE_GAUSSIAN_BLUR
56 blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n"); // BLUR_MODE_GAUSSIAN_GLOW
57 blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n"); // BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE
58 blur_modes.push_back("\n#define MODE_COPY\n"); // BLUR_MODE_COPY
59 blur_modes.push_back("\n#define MODE_SET_COLOR\n"); // BLUR_MODE_SET_COLOR
60
61 blur_raster.shader.initialize(blur_modes);
62 memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
63 blur_raster.shader_version = blur_raster.shader.version_create();
64
65 for (int i = 0; i < BLUR_MODE_MAX; i++) {
66 blur_raster.pipelines[i].setup(blur_raster.shader.version_get_shader(blur_raster.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
67 }
68
69 } else {
70 // not used in clustered
71 for (int i = 0; i < BLUR_MODE_MAX; i++) {
72 blur_raster.pipelines[i].clear();
73 }
74
75 Vector<String> copy_modes;
76 copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n");
77 copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define DST_IMAGE_8BIT\n");
78 copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define MODE_GLOW\n");
79 copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define MODE_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n");
80 copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n");
81 copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n#define DST_IMAGE_8BIT\n");
82 copy_modes.push_back("\n#define MODE_SIMPLE_COPY_DEPTH\n");
83 copy_modes.push_back("\n#define MODE_SET_COLOR\n");
84 copy_modes.push_back("\n#define MODE_SET_COLOR\n#define DST_IMAGE_8BIT\n");
85 copy_modes.push_back("\n#define MODE_MIPMAP\n");
86 copy_modes.push_back("\n#define MODE_LINEARIZE_DEPTH_COPY\n");
87 copy_modes.push_back("\n#define MODE_CUBEMAP_TO_PANORAMA\n");
88 copy_modes.push_back("\n#define MODE_CUBEMAP_ARRAY_TO_PANORAMA\n");
89
90 copy.shader.initialize(copy_modes);
91 memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
92
93 copy.shader_version = copy.shader.version_create();
94
95 for (int i = 0; i < COPY_MODE_MAX; i++) {
96 if (copy.shader.is_variant_enabled(i)) {
97 copy.pipelines[i] = RD::get_singleton()->compute_pipeline_create(copy.shader.version_get_shader(copy.shader_version, i));
98 }
99 }
100 }
101
102 {
103 Vector<String> copy_modes;
104 copy_modes.push_back("\n"); // COPY_TO_FB_COPY
105 copy_modes.push_back("\n#define MODE_PANORAMA_TO_DP\n"); // COPY_TO_FB_COPY_PANORAMA_TO_DP
106 copy_modes.push_back("\n#define MODE_TWO_SOURCES\n"); // COPY_TO_FB_COPY2
107 copy_modes.push_back("\n#define MULTIVIEW\n"); // COPY_TO_FB_MULTIVIEW
108 copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n"); // COPY_TO_FB_MULTIVIEW_WITH_DEPTH
109 copy_modes.push_back("\n#define MODE_SET_COLOR\n"); // COPY_TO_FB_SET_COLOR
110
111 copy_to_fb.shader.initialize(copy_modes);
112
113 if (!RendererCompositorRD::get_singleton()->is_xr_enabled()) {
114 copy_to_fb.shader.set_variant_enabled(COPY_TO_FB_MULTIVIEW, false);
115 copy_to_fb.shader.set_variant_enabled(COPY_TO_FB_MULTIVIEW_WITH_DEPTH, false);
116 }
117
118 copy_to_fb.shader_version = copy_to_fb.shader.version_create();
119
120 //use additive
121
122 for (int i = 0; i < COPY_TO_FB_MAX; i++) {
123 if (copy_to_fb.shader.is_variant_enabled(i)) {
124 copy_to_fb.pipelines[i].setup(copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
125 } else {
126 copy_to_fb.pipelines[i].clear();
127 }
128 }
129 }
130
131 {
132 // Initialize copier
133 Vector<String> copy_modes;
134 copy_modes.push_back("\n");
135
136 cube_to_dp.shader.initialize(copy_modes);
137
138 cube_to_dp.shader_version = cube_to_dp.shader.version_create();
139 RID shader = cube_to_dp.shader.version_get_shader(cube_to_dp.shader_version, 0);
140 RD::PipelineDepthStencilState dss;
141 dss.enable_depth_test = true;
142 dss.depth_compare_operator = RD::COMPARE_OP_ALWAYS;
143 dss.enable_depth_write = true;
144 cube_to_dp.pipeline.setup(shader, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), dss, RD::PipelineColorBlendState(), 0);
145 }
146
147 {
148 //Initialize cubemap downsampler
149 Vector<String> cubemap_downsampler_modes;
150 cubemap_downsampler_modes.push_back("");
151
152 if (prefer_raster_effects) {
153 cubemap_downsampler.raster_shader.initialize(cubemap_downsampler_modes);
154
155 cubemap_downsampler.shader_version = cubemap_downsampler.raster_shader.version_create();
156
157 cubemap_downsampler.raster_pipeline.setup(cubemap_downsampler.raster_shader.version_get_shader(cubemap_downsampler.shader_version, 0), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
158 } else {
159 cubemap_downsampler.compute_shader.initialize(cubemap_downsampler_modes);
160
161 cubemap_downsampler.shader_version = cubemap_downsampler.compute_shader.version_create();
162
163 cubemap_downsampler.compute_pipeline = RD::get_singleton()->compute_pipeline_create(cubemap_downsampler.compute_shader.version_get_shader(cubemap_downsampler.shader_version, 0));
164 cubemap_downsampler.raster_pipeline.clear();
165 }
166 }
167
168 {
169 // Initialize cubemap filter
170 filter.use_high_quality = GLOBAL_GET("rendering/reflections/sky_reflections/fast_filter_high_quality");
171
172 Vector<String> cubemap_filter_modes;
173 cubemap_filter_modes.push_back("\n#define USE_HIGH_QUALITY\n");
174 cubemap_filter_modes.push_back("\n#define USE_LOW_QUALITY\n");
175 cubemap_filter_modes.push_back("\n#define USE_HIGH_QUALITY\n#define USE_TEXTURE_ARRAY\n");
176 cubemap_filter_modes.push_back("\n#define USE_LOW_QUALITY\n#define USE_TEXTURE_ARRAY\n");
177
178 if (filter.use_high_quality) {
179 filter.coefficient_buffer = RD::get_singleton()->storage_buffer_create(sizeof(high_quality_coeffs));
180 RD::get_singleton()->buffer_update(filter.coefficient_buffer, 0, sizeof(high_quality_coeffs), &high_quality_coeffs[0]);
181 } else {
182 filter.coefficient_buffer = RD::get_singleton()->storage_buffer_create(sizeof(low_quality_coeffs));
183 RD::get_singleton()->buffer_update(filter.coefficient_buffer, 0, sizeof(low_quality_coeffs), &low_quality_coeffs[0]);
184 }
185
186 if (prefer_raster_effects) {
187 filter.raster_shader.initialize(cubemap_filter_modes);
188
189 // array variants are not supported in raster
190 filter.raster_shader.set_variant_enabled(FILTER_MODE_HIGH_QUALITY_ARRAY, false);
191 filter.raster_shader.set_variant_enabled(FILTER_MODE_LOW_QUALITY_ARRAY, false);
192
193 filter.shader_version = filter.raster_shader.version_create();
194
195 for (int i = 0; i < FILTER_MODE_MAX; i++) {
196 if (filter.raster_shader.is_variant_enabled(i)) {
197 filter.raster_pipelines[i].setup(filter.raster_shader.version_get_shader(filter.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
198 } else {
199 filter.raster_pipelines[i].clear();
200 }
201 }
202
203 Vector<RD::Uniform> uniforms;
204 {
205 RD::Uniform u;
206 u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
207 u.binding = 0;
208 u.append_id(filter.coefficient_buffer);
209 uniforms.push_back(u);
210 }
211 filter.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.raster_shader.version_get_shader(filter.shader_version, filter.use_high_quality ? 0 : 1), 1);
212 } else {
213 filter.compute_shader.initialize(cubemap_filter_modes);
214 filter.shader_version = filter.compute_shader.version_create();
215
216 for (int i = 0; i < FILTER_MODE_MAX; i++) {
217 filter.compute_pipelines[i] = RD::get_singleton()->compute_pipeline_create(filter.compute_shader.version_get_shader(filter.shader_version, i));
218 filter.raster_pipelines[i].clear();
219 }
220
221 Vector<RD::Uniform> uniforms;
222 {
223 RD::Uniform u;
224 u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
225 u.binding = 0;
226 u.append_id(filter.coefficient_buffer);
227 uniforms.push_back(u);
228 }
229 filter.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.compute_shader.version_get_shader(filter.shader_version, filter.use_high_quality ? 0 : 1), 1);
230 }
231 }
232
233 {
234 // Initialize roughness
235 Vector<String> cubemap_roughness_modes;
236 cubemap_roughness_modes.push_back("");
237
238 if (prefer_raster_effects) {
239 roughness.raster_shader.initialize(cubemap_roughness_modes);
240
241 roughness.shader_version = roughness.raster_shader.version_create();
242
243 roughness.raster_pipeline.setup(roughness.raster_shader.version_get_shader(roughness.shader_version, 0), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
244
245 } else {
246 roughness.compute_shader.initialize(cubemap_roughness_modes);
247
248 roughness.shader_version = roughness.compute_shader.version_create();
249
250 roughness.compute_pipeline = RD::get_singleton()->compute_pipeline_create(roughness.compute_shader.version_get_shader(roughness.shader_version, 0));
251 roughness.raster_pipeline.clear();
252 }
253 }
254
255 {
256 Vector<String> specular_modes;
257 specular_modes.push_back("\n#define MODE_MERGE\n"); // SPECULAR_MERGE_ADD
258 specular_modes.push_back("\n#define MODE_MERGE\n#define MODE_SSR\n"); // SPECULAR_MERGE_SSR
259 specular_modes.push_back("\n"); // SPECULAR_MERGE_ADDITIVE_ADD
260 specular_modes.push_back("\n#define MODE_SSR\n"); // SPECULAR_MERGE_ADDITIVE_SSR
261
262 specular_modes.push_back("\n#define USE_MULTIVIEW\n#define MODE_MERGE\n"); // SPECULAR_MERGE_ADD_MULTIVIEW
263 specular_modes.push_back("\n#define USE_MULTIVIEW\n#define MODE_MERGE\n#define MODE_SSR\n"); // SPECULAR_MERGE_SSR_MULTIVIEW
264 specular_modes.push_back("\n#define USE_MULTIVIEW\n"); // SPECULAR_MERGE_ADDITIVE_ADD_MULTIVIEW
265 specular_modes.push_back("\n#define USE_MULTIVIEW\n#define MODE_SSR\n"); // SPECULAR_MERGE_ADDITIVE_SSR_MULTIVIEW
266
267 specular_merge.shader.initialize(specular_modes);
268
269 if (!RendererCompositorRD::get_singleton()->is_xr_enabled()) {
270 specular_merge.shader.set_variant_enabled(SPECULAR_MERGE_ADD_MULTIVIEW, false);
271 specular_merge.shader.set_variant_enabled(SPECULAR_MERGE_SSR_MULTIVIEW, false);
272 specular_merge.shader.set_variant_enabled(SPECULAR_MERGE_ADDITIVE_ADD_MULTIVIEW, false);
273 specular_merge.shader.set_variant_enabled(SPECULAR_MERGE_ADDITIVE_SSR_MULTIVIEW, false);
274 }
275
276 specular_merge.shader_version = specular_merge.shader.version_create();
277
278 //use additive
279
280 RD::PipelineColorBlendState::Attachment ba;
281 ba.enable_blend = true;
282 ba.src_color_blend_factor = RD::BLEND_FACTOR_ONE;
283 ba.dst_color_blend_factor = RD::BLEND_FACTOR_ONE;
284 ba.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
285 ba.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
286 ba.color_blend_op = RD::BLEND_OP_ADD;
287 ba.alpha_blend_op = RD::BLEND_OP_ADD;
288
289 RD::PipelineColorBlendState blend_additive;
290 blend_additive.attachments.push_back(ba);
291
292 for (int i = 0; i < SPECULAR_MERGE_MAX; i++) {
293 if (specular_merge.shader.is_variant_enabled(i)) {
294 RD::PipelineColorBlendState blend_state;
295 if (i == SPECULAR_MERGE_ADDITIVE_ADD || i == SPECULAR_MERGE_ADDITIVE_SSR || i == SPECULAR_MERGE_ADDITIVE_ADD_MULTIVIEW || i == SPECULAR_MERGE_ADDITIVE_SSR_MULTIVIEW) {
296 blend_state = blend_additive;
297 } else {
298 blend_state = RD::PipelineColorBlendState::create_disabled();
299 }
300 specular_merge.pipelines[i].setup(specular_merge.shader.version_get_shader(specular_merge.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
301 }
302 }
303 }
304}
305
306CopyEffects::~CopyEffects() {
307 if (prefer_raster_effects) {
308 blur_raster.shader.version_free(blur_raster.shader_version);
309 cubemap_downsampler.raster_shader.version_free(cubemap_downsampler.shader_version);
310 filter.raster_shader.version_free(filter.shader_version);
311 roughness.raster_shader.version_free(roughness.shader_version);
312 } else {
313 copy.shader.version_free(copy.shader_version);
314 cubemap_downsampler.compute_shader.version_free(cubemap_downsampler.shader_version);
315 filter.compute_shader.version_free(filter.shader_version);
316 roughness.compute_shader.version_free(roughness.shader_version);
317 }
318
319 specular_merge.shader.version_free(specular_merge.shader_version);
320
321 RD::get_singleton()->free(filter.coefficient_buffer);
322
323 if (RD::get_singleton()->uniform_set_is_valid(filter.image_uniform_set)) {
324 RD::get_singleton()->free(filter.image_uniform_set);
325 }
326
327 if (RD::get_singleton()->uniform_set_is_valid(filter.uniform_set)) {
328 RD::get_singleton()->free(filter.uniform_set);
329 }
330
331 copy_to_fb.shader.version_free(copy_to_fb.shader_version);
332 cube_to_dp.shader.version_free(cube_to_dp.shader_version);
333
334 singleton = nullptr;
335}
336
337void CopyEffects::copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_all_source, bool p_8_bit_dst, bool p_alpha_to_one) {
338 ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the copy_to_rect shader with the mobile renderer.");
339
340 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
341 ERR_FAIL_NULL(uniform_set_cache);
342 MaterialStorage *material_storage = MaterialStorage::get_singleton();
343 ERR_FAIL_NULL(material_storage);
344
345 memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
346 if (p_flip_y) {
347 copy.push_constant.flags |= COPY_FLAG_FLIP_Y;
348 }
349
350 if (p_force_luminance) {
351 copy.push_constant.flags |= COPY_FLAG_FORCE_LUMINANCE;
352 }
353
354 if (p_all_source) {
355 copy.push_constant.flags |= COPY_FLAG_ALL_SOURCE;
356 }
357
358 if (p_alpha_to_one) {
359 copy.push_constant.flags |= COPY_FLAG_ALPHA_TO_ONE;
360 }
361
362 copy.push_constant.section[0] = p_rect.position.x;
363 copy.push_constant.section[1] = p_rect.position.y;
364 copy.push_constant.section[2] = p_rect.size.width;
365 copy.push_constant.section[3] = p_rect.size.height;
366 copy.push_constant.target[0] = p_rect.position.x;
367 copy.push_constant.target[1] = p_rect.position.y;
368
369 // setup our uniforms
370 RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
371
372 RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
373 RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_texture);
374
375 CopyMode mode = p_8_bit_dst ? COPY_MODE_SIMPLY_COPY_8BIT : COPY_MODE_SIMPLY_COPY;
376 RID shader = copy.shader.version_get_shader(copy.shader_version, mode);
377 ERR_FAIL_COND(shader.is_null());
378
379 RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
380 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
381 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
382 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3);
383 RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
384 RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1);
385 RD::get_singleton()->compute_list_end();
386}
387
388void CopyEffects::copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array) {
389 ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the copy_cubemap_to_panorama shader with the mobile renderer.");
390
391 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
392 ERR_FAIL_NULL(uniform_set_cache);
393 MaterialStorage *material_storage = MaterialStorage::get_singleton();
394 ERR_FAIL_NULL(material_storage);
395
396 memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
397
398 copy.push_constant.section[0] = 0;
399 copy.push_constant.section[1] = 0;
400 copy.push_constant.section[2] = p_panorama_size.width;
401 copy.push_constant.section[3] = p_panorama_size.height;
402 copy.push_constant.target[0] = 0;
403 copy.push_constant.target[1] = 0;
404 copy.push_constant.camera_z_far = p_lod;
405
406 // setup our uniforms
407 RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
408
409 RD::Uniform u_source_cube(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_cube }));
410 RD::Uniform u_dest_panorama(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_panorama);
411
412 CopyMode mode = p_is_array ? COPY_MODE_CUBE_ARRAY_TO_PANORAMA : COPY_MODE_CUBE_TO_PANORAMA;
413 RID shader = copy.shader.version_get_shader(copy.shader_version, mode);
414 ERR_FAIL_COND(shader.is_null());
415
416 RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
417 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
418 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_cube), 0);
419 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_panorama), 3);
420 RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
421 RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_panorama_size.width, p_panorama_size.height, 1);
422 RD::get_singleton()->compute_list_end();
423}
424
425void CopyEffects::copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y) {
426 ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the copy_depth_to_rect shader with the mobile renderer.");
427
428 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
429 ERR_FAIL_NULL(uniform_set_cache);
430 MaterialStorage *material_storage = MaterialStorage::get_singleton();
431 ERR_FAIL_NULL(material_storage);
432
433 memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
434 if (p_flip_y) {
435 copy.push_constant.flags |= COPY_FLAG_FLIP_Y;
436 }
437
438 copy.push_constant.section[0] = 0;
439 copy.push_constant.section[1] = 0;
440 copy.push_constant.section[2] = p_rect.size.width;
441 copy.push_constant.section[3] = p_rect.size.height;
442 copy.push_constant.target[0] = p_rect.position.x;
443 copy.push_constant.target[1] = p_rect.position.y;
444
445 // setup our uniforms
446 RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
447
448 RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
449 RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_texture);
450
451 CopyMode mode = COPY_MODE_SIMPLY_COPY_DEPTH;
452 RID shader = copy.shader.version_get_shader(copy.shader_version, mode);
453 ERR_FAIL_COND(shader.is_null());
454
455 RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
456 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
457 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
458 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3);
459 RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
460 RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1);
461 RD::get_singleton()->compute_list_end();
462}
463
464void CopyEffects::copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far) {
465 ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the copy_depth_to_rect_and_linearize shader with the mobile renderer.");
466
467 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
468 ERR_FAIL_NULL(uniform_set_cache);
469 MaterialStorage *material_storage = MaterialStorage::get_singleton();
470 ERR_FAIL_NULL(material_storage);
471
472 memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
473 if (p_flip_y) {
474 copy.push_constant.flags |= COPY_FLAG_FLIP_Y;
475 }
476
477 copy.push_constant.section[0] = 0;
478 copy.push_constant.section[1] = 0;
479 copy.push_constant.section[2] = p_rect.size.width;
480 copy.push_constant.section[3] = p_rect.size.height;
481 copy.push_constant.target[0] = p_rect.position.x;
482 copy.push_constant.target[1] = p_rect.position.y;
483 copy.push_constant.camera_z_far = p_z_far;
484 copy.push_constant.camera_z_near = p_z_near;
485
486 // setup our uniforms
487 RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
488
489 RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
490 RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_texture);
491
492 CopyMode mode = COPY_MODE_LINEARIZE_DEPTH;
493 RID shader = copy.shader.version_get_shader(copy.shader_version, mode);
494 ERR_FAIL_COND(shader.is_null());
495
496 RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
497 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
498 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
499 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3);
500 RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
501 RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1);
502 RD::get_singleton()->compute_list_end();
503}
504
505void CopyEffects::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y, bool p_panorama) {
506 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
507 ERR_FAIL_NULL(uniform_set_cache);
508 MaterialStorage *material_storage = MaterialStorage::get_singleton();
509 ERR_FAIL_NULL(material_storage);
510
511 memset(&copy_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant));
512
513 copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_USE_SECTION;
514 copy_to_fb.push_constant.section[0] = p_uv_rect.position.x;
515 copy_to_fb.push_constant.section[1] = p_uv_rect.position.y;
516 copy_to_fb.push_constant.section[2] = p_uv_rect.size.x;
517 copy_to_fb.push_constant.section[3] = p_uv_rect.size.y;
518
519 if (p_flip_y) {
520 copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_FLIP_Y;
521 }
522
523 copy_to_fb.push_constant.luminance_multiplier = 1.0;
524
525 // setup our uniforms
526 RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
527
528 RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
529
530 CopyToFBMode mode = p_panorama ? COPY_TO_FB_COPY_PANORAMA_TO_DP : COPY_TO_FB_COPY;
531 RID shader = copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, mode);
532 ERR_FAIL_COND(shader.is_null());
533
534 RD::DrawListID draw_list = p_draw_list;
535 RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
536 RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
537 RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
538 RD::get_singleton()->draw_list_set_push_constant(draw_list, &copy_to_fb.push_constant, sizeof(CopyToFbPushConstant));
539 RD::get_singleton()->draw_list_draw(draw_list, true);
540}
541
542void CopyEffects::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary, bool p_multiview, bool p_alpha_to_one, bool p_linear) {
543 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
544 ERR_FAIL_NULL(uniform_set_cache);
545 MaterialStorage *material_storage = MaterialStorage::get_singleton();
546 ERR_FAIL_NULL(material_storage);
547
548 memset(&copy_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant));
549 copy_to_fb.push_constant.luminance_multiplier = 1.0;
550
551 if (p_flip_y) {
552 copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_FLIP_Y;
553 }
554 if (p_force_luminance) {
555 copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_FORCE_LUMINANCE;
556 }
557 if (p_alpha_to_zero) {
558 copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_ALPHA_TO_ZERO;
559 }
560 if (p_srgb) {
561 copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_SRGB;
562 }
563 if (p_alpha_to_one) {
564 copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_ALPHA_TO_ONE;
565 }
566 if (p_linear) {
567 // Used for copying to a linear buffer. In the mobile renderer we divide the contents of the linear buffer
568 // to allow for a wider effective range.
569 copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_LINEAR;
570 copy_to_fb.push_constant.luminance_multiplier = prefer_raster_effects ? 2.0 : 1.0;
571 }
572
573 // setup our uniforms
574 RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
575
576 RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
577
578 CopyToFBMode mode;
579 if (p_multiview) {
580 mode = p_secondary.is_valid() ? COPY_TO_FB_MULTIVIEW_WITH_DEPTH : COPY_TO_FB_MULTIVIEW;
581 } else {
582 mode = p_secondary.is_valid() ? COPY_TO_FB_COPY2 : COPY_TO_FB_COPY;
583 }
584
585 RID shader = copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, mode);
586 ERR_FAIL_COND(shader.is_null());
587
588 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, Vector<Color>(), 1.0, 0, p_rect);
589 RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
590 RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
591 if (p_secondary.is_valid()) {
592 // TODO may need to do this differently when reading from depth buffer for multiview
593 RD::Uniform u_secondary(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_secondary }));
594 RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_secondary), 1);
595 }
596 RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
597 RD::get_singleton()->draw_list_set_push_constant(draw_list, &copy_to_fb.push_constant, sizeof(CopyToFbPushConstant));
598 RD::get_singleton()->draw_list_draw(draw_list, true);
599 RD::get_singleton()->draw_list_end();
600}
601
602void CopyEffects::copy_raster(RID p_source_texture, RID p_dest_framebuffer) {
603 ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the copy with the clustered renderer.");
604
605 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
606 ERR_FAIL_NULL(uniform_set_cache);
607 MaterialStorage *material_storage = MaterialStorage::get_singleton();
608 ERR_FAIL_NULL(material_storage);
609
610 memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
611
612 // setup our uniforms
613 RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
614
615 RD::Uniform u_source_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_texture }));
616
617 RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, BLUR_MODE_COPY);
618 ERR_FAIL_COND(shader.is_null());
619
620 // Just copy it back (we use our blur raster shader here)..
621 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);
622 RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[BLUR_MODE_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
623 RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_texture), 0);
624 RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
625 RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
626
627 RD::get_singleton()->draw_list_draw(draw_list, true);
628 RD::get_singleton()->draw_list_end();
629}
630
631void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, const Size2i &p_size, bool p_8bit_dst) {
632 ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian blur with the mobile renderer.");
633
634 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
635 ERR_FAIL_NULL(uniform_set_cache);
636 MaterialStorage *material_storage = MaterialStorage::get_singleton();
637 ERR_FAIL_NULL(material_storage);
638
639 memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
640
641 copy.push_constant.section[0] = p_region.position.x;
642 copy.push_constant.section[1] = p_region.position.y;
643 copy.push_constant.target[0] = p_region.position.x;
644 copy.push_constant.target[1] = p_region.position.y;
645 copy.push_constant.section[2] = p_size.width;
646 copy.push_constant.section[3] = p_size.height;
647
648 // setup our uniforms
649 RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
650
651 RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
652 RD::Uniform u_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_texture);
653
654 CopyMode mode = p_8bit_dst ? COPY_MODE_GAUSSIAN_COPY_8BIT : COPY_MODE_GAUSSIAN_COPY;
655 RID shader = copy.shader.version_get_shader(copy.shader_version, mode);
656 ERR_FAIL_COND(shader.is_null());
657
658 RD::DrawListID compute_list = RD::get_singleton()->compute_list_begin();
659 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
660 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
661 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_texture), 3);
662
663 RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
664
665 RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_region.size.width, p_region.size.height, 1);
666
667 RD::get_singleton()->compute_list_end();
668}
669
670void CopyEffects::gaussian_blur_raster(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_region, const Size2i &p_size) {
671 ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian blur with the clustered renderer.");
672
673 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
674 ERR_FAIL_NULL(uniform_set_cache);
675 MaterialStorage *material_storage = MaterialStorage::get_singleton();
676 ERR_FAIL_NULL(material_storage);
677
678 RID dest_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_dest_texture);
679
680 memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
681
682 BlurRasterMode blur_mode = BLUR_MODE_GAUSSIAN_BLUR;
683
684 blur_raster.push_constant.pixel_size[0] = 1.0 / float(p_size.x);
685 blur_raster.push_constant.pixel_size[1] = 1.0 / float(p_size.y);
686
687 // setup our uniforms
688 RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
689
690 RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
691
692 RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, blur_mode);
693 ERR_FAIL_COND(shader.is_null());
694
695 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);
696 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)));
697 RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
698
699 RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
700
701 RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
702 RD::get_singleton()->draw_list_end();
703}
704
705void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, 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) {
706 ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian glow with the mobile renderer.");
707
708 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
709 ERR_FAIL_NULL(uniform_set_cache);
710 MaterialStorage *material_storage = MaterialStorage::get_singleton();
711 ERR_FAIL_NULL(material_storage);
712
713 memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
714
715 CopyMode copy_mode = p_first_pass && p_auto_exposure.is_valid() ? COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : COPY_MODE_GAUSSIAN_GLOW;
716 uint32_t base_flags = 0;
717
718 copy.push_constant.section[2] = p_size.x;
719 copy.push_constant.section[3] = p_size.y;
720
721 copy.push_constant.glow_strength = p_strength;
722 copy.push_constant.glow_bloom = p_bloom;
723 copy.push_constant.glow_hdr_threshold = p_hdr_bleed_threshold;
724 copy.push_constant.glow_hdr_scale = p_hdr_bleed_scale;
725 copy.push_constant.glow_exposure = p_exposure;
726 copy.push_constant.glow_white = 0; //actually unused
727 copy.push_constant.glow_luminance_cap = p_luminance_cap;
728
729 copy.push_constant.glow_auto_exposure_scale = p_auto_exposure_scale; //unused also
730
731 // setup our uniforms
732 RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
733
734 RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
735 RD::Uniform u_back_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_back_texture);
736
737 RID shader = copy.shader.version_get_shader(copy.shader_version, copy_mode);
738 ERR_FAIL_COND(shader.is_null());
739
740 RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
741 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[copy_mode]);
742 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
743 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_back_texture), 3);
744 if (p_auto_exposure.is_valid() && p_first_pass) {
745 RD::Uniform u_auto_exposure(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_auto_exposure }));
746 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_auto_exposure), 1);
747 }
748
749 copy.push_constant.flags = base_flags | (p_first_pass ? COPY_FLAG_GLOW_FIRST_PASS : 0);
750 RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
751
752 RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_size.width, p_size.height, 1);
753 RD::get_singleton()->compute_list_end();
754}
755
756void 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_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) {
757 ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian glow with the clustered renderer.");
758
759 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
760 ERR_FAIL_NULL(uniform_set_cache);
761 MaterialStorage *material_storage = MaterialStorage::get_singleton();
762 ERR_FAIL_NULL(material_storage);
763
764 RID half_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_half_texture);
765 RID dest_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_dest_texture);
766
767 memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
768
769 BlurRasterMode blur_mode = p_first_pass && p_auto_exposure.is_valid() ? BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : BLUR_MODE_GAUSSIAN_GLOW;
770 uint32_t base_flags = 0;
771
772 blur_raster.push_constant.pixel_size[0] = 1.0 / float(p_size.x);
773 blur_raster.push_constant.pixel_size[1] = 1.0 / float(p_size.y);
774
775 blur_raster.push_constant.glow_strength = p_strength;
776 blur_raster.push_constant.glow_bloom = p_bloom;
777 blur_raster.push_constant.glow_hdr_threshold = p_hdr_bleed_threshold;
778 blur_raster.push_constant.glow_hdr_scale = p_hdr_bleed_scale;
779 blur_raster.push_constant.glow_exposure = p_exposure;
780 blur_raster.push_constant.glow_white = 0; //actually unused
781 blur_raster.push_constant.glow_luminance_cap = p_luminance_cap;
782
783 blur_raster.push_constant.glow_auto_exposure_scale = p_auto_exposure_scale; //unused also
784
785 blur_raster.push_constant.luminance_multiplier = p_luminance_multiplier;
786
787 // setup our uniforms
788 RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
789
790 RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
791 RD::Uniform u_half_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_half_texture }));
792
793 RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, blur_mode);
794 ERR_FAIL_COND(shader.is_null());
795
796 //HORIZONTAL
797 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);
798 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)));
799 RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
800 if (p_auto_exposure.is_valid() && p_first_pass) {
801 RD::Uniform u_auto_exposure(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_auto_exposure }));
802 RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_auto_exposure), 1);
803 }
804
805 blur_raster.push_constant.flags = base_flags | BLUR_FLAG_HORIZONTAL | (p_first_pass ? BLUR_FLAG_GLOW_FIRST_PASS : 0);
806 RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
807
808 RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
809 RD::get_singleton()->draw_list_end();
810
811 blur_mode = BLUR_MODE_GAUSSIAN_GLOW;
812
813 shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, blur_mode);
814 ERR_FAIL_COND(shader.is_null());
815
816 //VERTICAL
817 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);
818 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)));
819 RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_half_texture), 0);
820
821 blur_raster.push_constant.flags = base_flags;
822 RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
823
824 RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
825 RD::get_singleton()->draw_list_end();
826}
827
828void CopyEffects::make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size) {
829 ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the make_mipmap shader with the mobile renderer.");
830
831 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
832 ERR_FAIL_NULL(uniform_set_cache);
833 MaterialStorage *material_storage = MaterialStorage::get_singleton();
834 ERR_FAIL_NULL(material_storage);
835
836 memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
837
838 copy.push_constant.section[0] = 0;
839 copy.push_constant.section[1] = 0;
840 copy.push_constant.section[2] = p_size.width;
841 copy.push_constant.section[3] = p_size.height;
842
843 // setup our uniforms
844 RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
845
846 RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
847 RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_texture);
848
849 CopyMode mode = COPY_MODE_MIPMAP;
850 RID shader = copy.shader.version_get_shader(copy.shader_version, mode);
851 ERR_FAIL_COND(shader.is_null());
852
853 RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
854 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
855 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
856 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3);
857 RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
858 RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_size.width, p_size.height, 1);
859 RD::get_singleton()->compute_list_end();
860}
861
862void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size) {
863 ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of mipmap with the clustered renderer.");
864
865 RID dest_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_dest_texture);
866
867 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
868 ERR_FAIL_NULL(uniform_set_cache);
869 MaterialStorage *material_storage = MaterialStorage::get_singleton();
870 ERR_FAIL_NULL(material_storage);
871
872 memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
873
874 BlurRasterMode mode = BLUR_MIPMAP;
875
876 blur_raster.push_constant.pixel_size[0] = 1.0 / float(p_size.x);
877 blur_raster.push_constant.pixel_size[1] = 1.0 / float(p_size.y);
878
879 // setup our uniforms
880 RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
881
882 RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
883
884 RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, mode);
885 ERR_FAIL_COND(shader.is_null());
886
887 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);
888 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)));
889 RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
890 RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
891 RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
892
893 RD::get_singleton()->draw_list_draw(draw_list, true);
894 RD::get_singleton()->draw_list_end();
895}
896
897void CopyEffects::set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst) {
898 ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the set_color shader with the mobile renderer.");
899
900 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
901 ERR_FAIL_NULL(uniform_set_cache);
902
903 memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
904
905 copy.push_constant.section[0] = 0;
906 copy.push_constant.section[1] = 0;
907 copy.push_constant.section[2] = p_region.size.width;
908 copy.push_constant.section[3] = p_region.size.height;
909 copy.push_constant.target[0] = p_region.position.x;
910 copy.push_constant.target[1] = p_region.position.y;
911 copy.push_constant.set_color[0] = p_color.r;
912 copy.push_constant.set_color[1] = p_color.g;
913 copy.push_constant.set_color[2] = p_color.b;
914 copy.push_constant.set_color[3] = p_color.a;
915
916 // setup our uniforms
917 RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_texture);
918
919 CopyMode mode = p_8bit_dst ? COPY_MODE_SET_COLOR_8BIT : COPY_MODE_SET_COLOR;
920 RID shader = copy.shader.version_get_shader(copy.shader_version, mode);
921 ERR_FAIL_COND(shader.is_null());
922
923 RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
924 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
925 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3);
926 RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
927 RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_region.size.width, p_region.size.height, 1);
928 RD::get_singleton()->compute_list_end();
929}
930
931void CopyEffects::set_color_raster(RID p_dest_texture, const Color &p_color, const Rect2i &p_region) {
932 ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the set_color shader with the clustered renderer.");
933
934 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
935 ERR_FAIL_NULL(uniform_set_cache);
936 MaterialStorage *material_storage = MaterialStorage::get_singleton();
937 ERR_FAIL_NULL(material_storage);
938
939 memset(&copy_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant));
940
941 copy_to_fb.push_constant.set_color[0] = p_color.r;
942 copy_to_fb.push_constant.set_color[1] = p_color.g;
943 copy_to_fb.push_constant.set_color[2] = p_color.b;
944 copy_to_fb.push_constant.set_color[3] = p_color.a;
945
946 RID dest_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_dest_texture);
947
948 CopyToFBMode mode = COPY_TO_FB_SET_COLOR;
949
950 RID shader = copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, mode);
951 ERR_FAIL_COND(shader.is_null());
952
953 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, Vector<Color>(), 1.0, 0, p_region);
954 RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer)));
955 RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
956 RD::get_singleton()->draw_list_set_push_constant(draw_list, &copy_to_fb.push_constant, sizeof(CopyToFbPushConstant));
957 RD::get_singleton()->draw_list_draw(draw_list, true);
958 RD::get_singleton()->draw_list_end();
959}
960
961void CopyEffects::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip, BitField<RD::BarrierMask> p_post_barrier) {
962 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
963 ERR_FAIL_NULL(uniform_set_cache);
964 MaterialStorage *material_storage = MaterialStorage::get_singleton();
965 ERR_FAIL_NULL(material_storage);
966
967 CopyToDPPushConstant push_constant;
968 push_constant.screen_rect[0] = p_rect.position.x;
969 push_constant.screen_rect[1] = p_rect.position.y;
970 push_constant.screen_rect[2] = p_rect.size.width;
971 push_constant.screen_rect[3] = p_rect.size.height;
972 push_constant.z_far = p_z_far;
973 push_constant.z_near = p_z_near;
974 push_constant.texel_size[0] = 1.0f / p_dst_size.x;
975 push_constant.texel_size[1] = 1.0f / p_dst_size.y;
976 push_constant.texel_size[0] *= p_dp_flip ? -1.0f : 1.0f; // Encode dp flip as x size sign
977
978 // setup our uniforms
979 RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
980
981 RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
982
983 RID shader = cube_to_dp.shader.version_get_shader(cube_to_dp.shader_version, 0);
984 ERR_FAIL_COND(shader.is_null());
985
986 RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
987 RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, cube_to_dp.pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer)));
988 RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
989 RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
990
991 RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(CopyToDPPushConstant));
992 RD::get_singleton()->draw_list_draw(draw_list, true);
993 RD::get_singleton()->draw_list_end(p_post_barrier);
994}
995
996void CopyEffects::cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size) {
997 ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute based cubemap downsample with the mobile renderer.");
998
999 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
1000 ERR_FAIL_NULL(uniform_set_cache);
1001 MaterialStorage *material_storage = MaterialStorage::get_singleton();
1002 ERR_FAIL_NULL(material_storage);
1003
1004 cubemap_downsampler.push_constant.face_size = p_size.x;
1005 cubemap_downsampler.push_constant.face_id = 0; // we render all 6 sides to each layer in one call
1006
1007 // setup our uniforms
1008 RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
1009
1010 RD::Uniform u_source_cubemap(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_cubemap }));
1011 RD::Uniform u_dest_cubemap(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_dest_cubemap }));
1012
1013 RID shader = cubemap_downsampler.compute_shader.version_get_shader(cubemap_downsampler.shader_version, 0);
1014 ERR_FAIL_COND(shader.is_null());
1015
1016 RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
1017 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, cubemap_downsampler.compute_pipeline);
1018 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_cubemap), 0);
1019 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_dest_cubemap), 1);
1020
1021 int x_groups = (p_size.x - 1) / 8 + 1;
1022 int y_groups = (p_size.y - 1) / 8 + 1;
1023
1024 RD::get_singleton()->compute_list_set_push_constant(compute_list, &cubemap_downsampler.push_constant, sizeof(CubemapDownsamplerPushConstant));
1025
1026 RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 6); // one z_group for each face
1027
1028 RD::get_singleton()->compute_list_end();
1029}
1030
1031void CopyEffects::cubemap_downsample_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, const Size2i &p_size) {
1032 ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use raster based cubemap downsample with the clustered renderer.");
1033 ERR_FAIL_COND_MSG(p_face_id >= 6, "Raster implementation of cubemap downsample must process one side at a time.");
1034
1035 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
1036 ERR_FAIL_NULL(uniform_set_cache);
1037 MaterialStorage *material_storage = MaterialStorage::get_singleton();
1038 ERR_FAIL_NULL(material_storage);
1039
1040 cubemap_downsampler.push_constant.face_size = p_size.x;
1041 cubemap_downsampler.push_constant.face_id = p_face_id;
1042
1043 // setup our uniforms
1044 RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
1045
1046 RD::Uniform u_source_cubemap(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_cubemap }));
1047
1048 RID shader = cubemap_downsampler.raster_shader.version_get_shader(cubemap_downsampler.shader_version, 0);
1049 ERR_FAIL_COND(shader.is_null());
1050
1051 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);
1052 RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, cubemap_downsampler.raster_pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
1053 RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_cubemap), 0);
1054
1055 RD::get_singleton()->draw_list_set_push_constant(draw_list, &cubemap_downsampler.push_constant, sizeof(CubemapDownsamplerPushConstant));
1056
1057 RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
1058 RD::get_singleton()->draw_list_end();
1059}
1060
1061void CopyEffects::cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array) {
1062 ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute based cubemap filter with the mobile renderer.");
1063
1064 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
1065 ERR_FAIL_NULL(uniform_set_cache);
1066 MaterialStorage *material_storage = MaterialStorage::get_singleton();
1067 ERR_FAIL_NULL(material_storage);
1068
1069 Vector<RD::Uniform> uniforms;
1070 for (int i = 0; i < p_dest_cubemap.size(); i++) {
1071 RD::Uniform u;
1072 u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
1073 u.binding = i;
1074 u.append_id(p_dest_cubemap[i]);
1075 uniforms.push_back(u);
1076 }
1077 if (RD::get_singleton()->uniform_set_is_valid(filter.image_uniform_set)) {
1078 RD::get_singleton()->free(filter.image_uniform_set);
1079 }
1080 filter.image_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.compute_shader.version_get_shader(filter.shader_version, 0), 2);
1081
1082 // setup our uniforms
1083 RID default_mipmap_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
1084
1085 RD::Uniform u_source_cubemap(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_mipmap_sampler, p_source_cubemap }));
1086
1087 int mode = p_use_array ? FILTER_MODE_HIGH_QUALITY_ARRAY : FILTER_MODE_HIGH_QUALITY;
1088 mode = filter.use_high_quality ? mode : mode + 1;
1089
1090 RID shader = filter.compute_shader.version_get_shader(filter.shader_version, mode);
1091 ERR_FAIL_COND(shader.is_null());
1092
1093 RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
1094 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, filter.compute_pipelines[mode]);
1095 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_cubemap), 0);
1096 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, filter.uniform_set, 1);
1097 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, filter.image_uniform_set, 2);
1098
1099 int x_groups = p_use_array ? 1792 : 342; // (128 * 128 * 7) / 64 : (128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2) / 64
1100
1101 RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, 6, 1); // one y_group for each face
1102
1103 RD::get_singleton()->compute_list_end();
1104}
1105
1106void CopyEffects::cubemap_filter_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_mip_level) {
1107 ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use raster based cubemap filter with the clustered renderer.");
1108 ERR_FAIL_COND_MSG(p_face_id >= 6, "Raster implementation of cubemap filter must process one side at a time.");
1109
1110 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
1111 ERR_FAIL_NULL(uniform_set_cache);
1112 MaterialStorage *material_storage = MaterialStorage::get_singleton();
1113 ERR_FAIL_NULL(material_storage);
1114
1115 // TODO implement!
1116 CubemapFilterRasterPushConstant push_constant;
1117 push_constant.mip_level = p_mip_level;
1118 push_constant.face_id = p_face_id;
1119
1120 // setup our uniforms
1121 RID default_mipmap_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
1122
1123 RD::Uniform u_source_cubemap(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_mipmap_sampler, p_source_cubemap }));
1124
1125 CubemapFilterMode mode = filter.use_high_quality ? FILTER_MODE_HIGH_QUALITY : FILTER_MODE_LOW_QUALITY;
1126
1127 RID shader = filter.raster_shader.version_get_shader(filter.shader_version, mode);
1128 ERR_FAIL_COND(shader.is_null());
1129
1130 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);
1131 RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, filter.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
1132 RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_cubemap), 0);
1133 RD::get_singleton()->draw_list_bind_uniform_set(draw_list, filter.uniform_set, 1);
1134
1135 RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(CubemapFilterRasterPushConstant));
1136
1137 RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
1138 RD::get_singleton()->draw_list_end();
1139}
1140
1141void CopyEffects::cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size) {
1142 ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute based cubemap roughness with the mobile renderer.");
1143
1144 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
1145 ERR_FAIL_NULL(uniform_set_cache);
1146 MaterialStorage *material_storage = MaterialStorage::get_singleton();
1147 ERR_FAIL_NULL(material_storage);
1148
1149 memset(&roughness.push_constant, 0, sizeof(CubemapRoughnessPushConstant));
1150
1151 roughness.push_constant.face_id = p_face_id > 9 ? 0 : p_face_id;
1152 // Remap to perceptual-roughness^2 to create more detail in lower mips and match the mapping of cubemap_filter.
1153 roughness.push_constant.roughness = p_roughness * p_roughness;
1154 roughness.push_constant.sample_count = p_sample_count;
1155 roughness.push_constant.use_direct_write = p_roughness == 0.0;
1156 roughness.push_constant.face_size = p_size;
1157
1158 // setup our uniforms
1159 RID default_mipmap_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
1160
1161 RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_mipmap_sampler, p_source_rd_texture }));
1162 RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_dest_texture }));
1163
1164 RID shader = roughness.compute_shader.version_get_shader(roughness.shader_version, 0);
1165 ERR_FAIL_COND(shader.is_null());
1166
1167 RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
1168 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, roughness.compute_pipeline);
1169
1170 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
1171 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_dest_texture), 1);
1172
1173 RD::get_singleton()->compute_list_set_push_constant(compute_list, &roughness.push_constant, sizeof(CubemapRoughnessPushConstant));
1174
1175 int x_groups = (p_size - 1) / 8 + 1;
1176 int y_groups = (p_size - 1) / 8 + 1;
1177
1178 RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, p_face_id > 9 ? 6 : 1);
1179
1180 RD::get_singleton()->compute_list_end();
1181}
1182
1183void CopyEffects::cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size) {
1184 ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use raster based cubemap roughness with the clustered renderer.");
1185 ERR_FAIL_COND_MSG(p_face_id >= 6, "Raster implementation of cubemap roughness must process one side at a time.");
1186
1187 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
1188 ERR_FAIL_NULL(uniform_set_cache);
1189 MaterialStorage *material_storage = MaterialStorage::get_singleton();
1190 ERR_FAIL_NULL(material_storage);
1191
1192 memset(&roughness.push_constant, 0, sizeof(CubemapRoughnessPushConstant));
1193
1194 roughness.push_constant.face_id = p_face_id;
1195 roughness.push_constant.roughness = p_roughness * p_roughness; // Shader expects roughness, not perceptual roughness, so multiply before passing in.
1196 roughness.push_constant.sample_count = p_sample_count;
1197 roughness.push_constant.use_direct_write = p_roughness == 0.0;
1198 roughness.push_constant.face_size = p_size;
1199
1200 // Setup our uniforms.
1201 RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
1202
1203 RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
1204
1205 RID shader = roughness.raster_shader.version_get_shader(roughness.shader_version, 0);
1206 ERR_FAIL_COND(shader.is_null());
1207
1208 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);
1209 RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, roughness.raster_pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
1210 RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
1211
1212 RD::get_singleton()->draw_list_set_push_constant(draw_list, &roughness.push_constant, sizeof(CubemapRoughnessPushConstant));
1213
1214 RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
1215 RD::get_singleton()->draw_list_end();
1216}
1217
1218void CopyEffects::merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection, uint32_t p_view_count) {
1219 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
1220 ERR_FAIL_NULL(uniform_set_cache);
1221 MaterialStorage *material_storage = MaterialStorage::get_singleton();
1222 ERR_FAIL_NULL(material_storage);
1223
1224 RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
1225
1226 RD::get_singleton()->draw_command_begin_label("Merge specular");
1227
1228 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_READ, Vector<Color>());
1229
1230 int mode;
1231 if (p_reflection.is_valid()) {
1232 if (p_base.is_valid()) {
1233 mode = SPECULAR_MERGE_SSR;
1234 } else {
1235 mode = SPECULAR_MERGE_ADDITIVE_SSR;
1236 }
1237 } else {
1238 if (p_base.is_valid()) {
1239 mode = SPECULAR_MERGE_ADD;
1240 } else {
1241 mode = SPECULAR_MERGE_ADDITIVE_ADD;
1242 }
1243 }
1244
1245 if (p_view_count > 1) {
1246 mode += SPECULAR_MERGE_ADD_MULTIVIEW;
1247 }
1248
1249 RID shader = specular_merge.shader.version_get_shader(specular_merge.shader_version, mode);
1250 RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
1251
1252 if (p_base.is_valid()) {
1253 RD::Uniform u_base(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_base }));
1254 RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 2, u_base), 2);
1255 }
1256
1257 RD::Uniform u_specular(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_specular }));
1258 RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_specular), 0);
1259
1260 if (p_reflection.is_valid()) {
1261 RD::Uniform u_reflection(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_reflection }));
1262 RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_reflection), 1);
1263 }
1264
1265 RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
1266 RD::get_singleton()->draw_list_end();
1267
1268 RD::get_singleton()->draw_command_end_label();
1269}
1270