summaryrefslogtreecommitdiff
path: root/servers/rendering
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering')
-rw-r--r--servers/rendering/rasterizer_dummy.h16
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp6
-rw-r--r--servers/rendering/renderer_canvas_cull.h6
-rw-r--r--servers/rendering/renderer_canvas_render.cpp4
-rw-r--r--servers/rendering/renderer_canvas_render.h4
-rw-r--r--servers/rendering/renderer_compositor.cpp4
-rw-r--r--servers/rendering/renderer_compositor.h7
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.cpp12
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.h4
-rw-r--r--servers/rendering/renderer_rd/effects_rd.cpp71
-rw-r--r--servers/rendering/renderer_rd/effects_rd.h32
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp86
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h13
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp23
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h8
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp18
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h7
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp23
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h8
-rw-r--r--servers/rendering/renderer_rd/pipeline_cache_rd.cpp4
-rw-r--r--servers/rendering/renderer_rd/pipeline_cache_rd.h4
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp25
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h8
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp14
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.h6
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp4
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_environment_rd.h4
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp30
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_gi_rd.h22
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp247
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h23
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp21
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.h8
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.cpp213
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.h28
-rw-r--r--servers/rendering/renderer_rd/shader_compiler_rd.cpp121
-rw-r--r--servers/rendering/renderer_rd/shader_compiler_rd.h4
-rw-r--r--servers/rendering/renderer_rd/shader_rd.cpp13
-rw-r--r--servers/rendering/renderer_rd/shader_rd.h4
-rw-r--r--servers/rendering/renderer_rd/shaders/fsr_upscale.glsl173
-rw-r--r--servers/rendering/renderer_rd/shaders/gi.glsl18
-rw-r--r--servers/rendering/renderer_rd/shaders/giprobe_write.glsl1
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl40
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl21
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl37
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl27
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl3
-rw-r--r--servers/rendering/renderer_rd/shaders/volumetric_fog.glsl38
-rw-r--r--servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl78
-rw-r--r--servers/rendering/renderer_rd/shaders/voxel_gi.glsl1
-rw-r--r--servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl56
-rw-r--r--servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl5
-rw-r--r--servers/rendering/renderer_scene.cpp4
-rw-r--r--servers/rendering/renderer_scene.h6
-rw-r--r--servers/rendering/renderer_scene_cull.cpp13
-rw-r--r--servers/rendering/renderer_scene_cull.h21
-rw-r--r--servers/rendering/renderer_scene_occlusion_cull.cpp4
-rw-r--r--servers/rendering/renderer_scene_occlusion_cull.h4
-rw-r--r--servers/rendering/renderer_scene_render.cpp4
-rw-r--r--servers/rendering/renderer_scene_render.h6
-rw-r--r--servers/rendering/renderer_storage.cpp4
-rw-r--r--servers/rendering/renderer_storage.h8
-rw-r--r--servers/rendering/renderer_thread_pool.cpp4
-rw-r--r--servers/rendering/renderer_thread_pool.h4
-rw-r--r--servers/rendering/renderer_viewport.cpp121
-rw-r--r--servers/rendering/renderer_viewport.h19
-rw-r--r--servers/rendering/rendering_device.cpp18
-rw-r--r--servers/rendering/rendering_device.h5
-rw-r--r--servers/rendering/rendering_device_binds.cpp20
-rw-r--r--servers/rendering/rendering_device_binds.h10
-rw-r--r--servers/rendering/rendering_server_default.cpp30
-rw-r--r--servers/rendering/rendering_server_default.h24
-rw-r--r--servers/rendering/rendering_server_globals.cpp4
-rw-r--r--servers/rendering/rendering_server_globals.h4
-rw-r--r--servers/rendering/shader_language.cpp1036
-rw-r--r--servers/rendering/shader_language.h121
-rw-r--r--servers/rendering/shader_types.cpp146
-rw-r--r--servers/rendering/shader_types.h8
-rw-r--r--servers/rendering/shader_warnings.cpp20
-rw-r--r--servers/rendering/shader_warnings.h13
80 files changed, 2164 insertions, 1170 deletions
diff --git a/servers/rendering/rasterizer_dummy.h b/servers/rendering/rasterizer_dummy.h
index f4a44c30f9..f6f64a9680 100644
--- a/servers/rendering/rasterizer_dummy.h
+++ b/servers/rendering/rasterizer_dummy.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -195,7 +195,7 @@ public:
void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {}
RID render_buffers_create() override { return RID(); }
- void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override {}
+ void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override {}
void gi_set_use_half_resolution(bool p_enable) override {}
void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {}
@@ -258,7 +258,7 @@ public:
Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); }
Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); }
- void texture_replace(RID p_texture, RID p_by_texture) override {}
+ void texture_replace(RID p_texture, RID p_by_texture) override { free(p_by_texture); }
void texture_set_size_override(RID p_texture, int p_width, int p_height) override {}
void texture_set_path(RID p_texture, const String &p_path) override {}
@@ -293,8 +293,8 @@ public:
String shader_get_code(RID p_shader) const override { return ""; }
void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override {}
- void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) override {}
- RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const override { return RID(); }
+ void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override {}
+ RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override { return RID(); }
Variant shader_get_param_default(RID p_material, const StringName &p_param) const override { return Variant(); }
RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); };
@@ -692,7 +692,9 @@ public:
virtual void update_memory_info() override {}
virtual uint64_t get_rendering_info(RS::RenderingInfo p_info) override { return 0; }
- bool has_os_feature(const String &p_feature) const override { return false; }
+ bool has_os_feature(const String &p_feature) const override {
+ return p_feature == "rgtc" || p_feature == "bptc" || p_feature == "s3tc" || p_feature == "etc" || p_feature == "etc2";
+ }
void update_dirty_resources() override {}
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index 7b70483571..02af3c6eb9 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -786,7 +786,7 @@ void RendererCanvasCull::canvas_item_add_texture_rect(RID p_item, const Rect2 &p
if (p_tile) {
rect->flags |= RendererCanvasRender::CANVAS_RECT_TILE;
rect->flags |= RendererCanvasRender::CANVAS_RECT_REGION;
- rect->source = Rect2(0, 0, fabsf(p_rect.size.width), fabsf(p_rect.size.height));
+ rect->source = Rect2(0, 0, ABS(p_rect.size.width), ABS(p_rect.size.height));
}
if (p_rect.size.x < 0) {
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index a2fdf95c76..fc53ce2327 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -152,7 +152,7 @@ public:
void erase_item(Item *p_item) {
int idx = find_item(p_item);
if (idx >= 0) {
- child_items.remove(idx);
+ child_items.remove_at(idx);
}
}
diff --git a/servers/rendering/renderer_canvas_render.cpp b/servers/rendering/renderer_canvas_render.cpp
index 1945435586..3b68cd74fd 100644
--- a/servers/rendering/renderer_canvas_render.cpp
+++ b/servers/rendering/renderer_canvas_render.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h
index 04ddae4089..1840925f78 100644
--- a/servers/rendering/renderer_canvas_render.h
+++ b/servers/rendering/renderer_canvas_render.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_compositor.cpp b/servers/rendering/renderer_compositor.cpp
index 80c4625261..82e8bd6ef9 100644
--- a/servers/rendering/renderer_compositor.cpp
+++ b/servers/rendering/renderer_compositor.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h
index 1971c3e781..f245af9a4a 100644
--- a/servers/rendering/renderer_compositor.h
+++ b/servers/rendering/renderer_compositor.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -67,6 +67,7 @@ private:
protected:
static RendererCompositor *(*_create_func)();
+ bool back_end = false;
public:
static RendererCompositor *create();
@@ -88,7 +89,7 @@ public:
virtual uint64_t get_frame_number() const = 0;
virtual double get_frame_delta_time() const = 0;
- virtual bool is_low_end() const = 0;
+ _FORCE_INLINE_ virtual bool is_low_end() const { return back_end; };
virtual bool is_xr_enabled() const;
RendererCompositor();
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
index b952ecbff0..6ad3556969 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -460,14 +460,6 @@ void ClusterBuilderRD::bake_cluster() {
RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(ClusterBuilderSharedDataRD::ClusterRender::PushConstant));
uint32_t instances = 1;
-#if 0
- for (uint32_t j = i+1; j < element_count; j++) {
- if (elements[i].type!=elements[j].type) {
- break;
- }
- instances++;
- }
-#endif
RD::get_singleton()->draw_list_draw(draw_list, true, instances);
i += instances;
}
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.h b/servers/rendering/renderer_rd/cluster_builder_rd.h
index feafd4c2db..7f6750fa7e 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.h
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp
index c69408a30b..0650e528e7 100644
--- a/servers/rendering/renderer_rd/effects_rd.cpp
+++ b/servers/rendering/renderer_rd/effects_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -237,6 +237,43 @@ RID EffectsRD::_get_compute_uniform_set_from_image_pair(RID p_texture1, RID p_te
return uniform_set;
}
+void EffectsRD::fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness) {
+ memset(&FSR_upscale.push_constant, 0, sizeof(FSRUpscalePushConstant));
+
+ int dispatch_x = (p_size.x + 15) / 16;
+ int dispatch_y = (p_size.y + 15) / 16;
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, FSR_upscale.pipeline);
+
+ FSR_upscale.push_constant.resolution_width = p_internal_size.width;
+ FSR_upscale.push_constant.resolution_height = p_internal_size.height;
+ FSR_upscale.push_constant.upscaled_width = p_size.width;
+ FSR_upscale.push_constant.upscaled_height = p_size.height;
+ FSR_upscale.push_constant.sharpness = p_fsr_upscale_sharpness;
+
+ //FSR Easc
+ FSR_upscale.push_constant.pass = FSR_UPSCALE_PASS_EASU;
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_secondary_texture), 1);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &FSR_upscale.push_constant, sizeof(FSRUpscalePushConstant));
+
+ RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ //FSR Rcas
+ FSR_upscale.push_constant.pass = FSR_UPSCALE_PASS_RCAS;
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_secondary_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_destination_texture), 1);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &FSR_upscale.push_constant, sizeof(FSRUpscalePushConstant));
+
+ RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
+
+ RD::get_singleton()->compute_list_end(compute_list);
+}
+
void EffectsRD::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) {
memset(&copy_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant));
@@ -443,7 +480,7 @@ void EffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back
RD::get_singleton()->compute_list_end();
}
-void EffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_treshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
+void EffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian glow with the mobile renderer.");
memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
@@ -456,7 +493,7 @@ void EffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const
copy.push_constant.glow_strength = p_strength;
copy.push_constant.glow_bloom = p_bloom;
- copy.push_constant.glow_hdr_threshold = p_hdr_bleed_treshold;
+ copy.push_constant.glow_hdr_threshold = p_hdr_bleed_threshold;
copy.push_constant.glow_hdr_scale = p_hdr_bleed_scale;
copy.push_constant.glow_exposure = p_exposure;
copy.push_constant.glow_white = 0; //actually unused
@@ -479,7 +516,7 @@ void EffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const
RD::get_singleton()->compute_list_end();
}
-void EffectsRD::gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_treshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
+void EffectsRD::gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian glow with the clustered renderer.");
memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
@@ -492,7 +529,7 @@ void EffectsRD::gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_
blur_raster.push_constant.glow_strength = p_strength;
blur_raster.push_constant.glow_bloom = p_bloom;
- blur_raster.push_constant.glow_hdr_threshold = p_hdr_bleed_treshold;
+ blur_raster.push_constant.glow_hdr_threshold = p_hdr_bleed_threshold;
blur_raster.push_constant.glow_hdr_scale = p_hdr_bleed_scale;
blur_raster.push_constant.glow_exposure = p_exposure;
blur_raster.push_constant.glow_white = 0; //actually unused
@@ -1888,6 +1925,27 @@ void EffectsRD::sort_buffer(RID p_uniform_set, int p_size) {
}
EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
+ {
+ Vector<String> FSR_upscale_modes;
+
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ // MoltenVK does not support some of the operations used by the normal mode of FSR. Fallback works just fine though.
+ FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
+#else
+ // Everyone else can use normal mode when available.
+ if (RD::get_singleton()->get_device_capabilities()->supports_fsr_half_float) {
+ FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_NORMAL\n");
+ } else {
+ FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
+ }
+#endif
+
+ FSR_upscale.shader.initialize(FSR_upscale_modes);
+
+ FSR_upscale.shader_version = FSR_upscale.shader.version_create();
+ FSR_upscale.pipeline = RD::get_singleton()->compute_pipeline_create(FSR_upscale.shader.version_get_shader(FSR_upscale.shader_version, 0));
+ }
+
prefer_raster_effects = p_prefer_raster_effects;
if (prefer_raster_effects) {
@@ -2523,6 +2581,7 @@ EffectsRD::~EffectsRD() {
RD::get_singleton()->free(index_buffer); //array gets freed as dependency
RD::get_singleton()->free(filter.coefficient_buffer);
+ FSR_upscale.shader.version_free(FSR_upscale.shader_version);
if (prefer_raster_effects) {
blur_raster.shader.version_free(blur_raster.shader_version);
bokeh.raster_shader.version_free(blur_raster.shader_version);
diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h
index 0db0919dbc..e26ba520e7 100644
--- a/servers/rendering/renderer_rd/effects_rd.h
+++ b/servers/rendering/renderer_rd/effects_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -45,6 +45,7 @@
#include "servers/rendering/renderer_rd/shaders/cubemap_filter_raster.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/cubemap_roughness_raster.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/fsr_upscale.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/luminance_reduce.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/resolve.glsl.gen.h"
@@ -69,6 +70,28 @@ class EffectsRD {
private:
bool prefer_raster_effects;
+ enum FSRUpscalePass {
+ FSR_UPSCALE_PASS_EASU = 0,
+ FSR_UPSCALE_PASS_RCAS = 1
+ };
+
+ struct FSRUpscalePushConstant {
+ float resolution_width;
+ float resolution_height;
+ float upscaled_width;
+ float upscaled_height;
+ float sharpness;
+ int pass;
+ int _unused0, _unused1;
+ };
+
+ struct FSRUpscale {
+ FSRUpscalePushConstant push_constant;
+ FsrUpscaleShaderRD shader;
+ RID shader_version;
+ RID pipeline;
+ } FSR_upscale;
+
enum BlurRasterMode {
BLUR_MIPMAP,
@@ -754,6 +777,7 @@ private:
public:
bool get_prefer_raster_effects();
+ void fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness);
void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID());
void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false, bool p_alpha_to_one = false);
void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array);
@@ -762,8 +786,8 @@ public:
void 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 = false, bool p_panorama = false);
void gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Rect2i &p_region, bool p_8bit_dst = false);
void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false);
- void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
- void gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
+ void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
+ void gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
void 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);
void 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);
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
index 0f5af96417..06669a7bb5 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -334,6 +334,14 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
const GeometryInstanceSurfaceDataCache *surf = p_params->elements[i];
const RenderElementInfo &element_info = p_params->element_info[i];
+ if ((p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_SPECULAR) && !(surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) {
+ continue; // Objects with "Depth-prepass" transparency are included in both render lists, but should only be rendered in the transparent pass
+ }
+
+ if (surf->owner->instance_count == 0) {
+ continue;
+ }
+
push_constant.base_index = i + p_params->element_offset;
RID material_uniform_set;
@@ -954,20 +962,20 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
bool uses_gi = false;
float fade_alpha = 1.0;
- if (p_render_list == RENDER_LIST_OPAQUE) {
- if (inst->fade_near || inst->fade_far) {
- float fade_dist = inst->transform.origin.distance_to(p_render_data->cam_transform.origin);
- if (inst->fade_far && fade_dist > inst->fade_far_begin) {
- fade_alpha = MAX(0.0, 1.0 - (fade_dist - inst->fade_far_begin) / (inst->fade_far_end - inst->fade_far_begin));
- } else if (inst->fade_near && fade_dist < inst->fade_near_end) {
- fade_alpha = MAX(0.0, (fade_dist - inst->fade_near_begin) / (inst->fade_near_end - inst->fade_near_begin));
- }
+ if (inst->fade_near || inst->fade_far) {
+ float fade_dist = inst->transform.origin.distance_to(p_render_data->cam_transform.origin);
+ if (inst->fade_far && fade_dist > inst->fade_far_begin) {
+ fade_alpha = MAX(0.0, 1.0 - (fade_dist - inst->fade_far_begin) / (inst->fade_far_end - inst->fade_far_begin));
+ } else if (inst->fade_near && fade_dist < inst->fade_near_end) {
+ fade_alpha = MAX(0.0, (fade_dist - inst->fade_near_begin) / (inst->fade_near_end - inst->fade_near_begin));
}
+ }
- fade_alpha *= inst->force_alpha * inst->parent_fade_alpha;
+ fade_alpha *= inst->force_alpha * inst->parent_fade_alpha;
- flags = (flags & ~INSTANCE_DATA_FLAGS_FADE_MASK) | (uint32_t(fade_alpha * 255.0) << INSTANCE_DATA_FLAGS_FADE_SHIFT);
+ flags = (flags & ~INSTANCE_DATA_FLAGS_FADE_MASK) | (uint32_t(fade_alpha * 255.0) << INSTANCE_DATA_FLAGS_FADE_SHIFT);
+ if (p_render_list == RENDER_LIST_OPAQUE) {
// Setup GI
if (inst->lightmap_instance.is_valid()) {
int32_t lightmap_cull_index = -1;
@@ -1202,6 +1210,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
scene_state.ubo.viewport_size[0] = vp_he.x;
scene_state.ubo.viewport_size[1] = vp_he.y;
scene_state.ubo.directional_light_count = 0;
+ scene_state.ubo.opaque_prepass_threshold = 0.99f;
Size2i screen_size;
RID opaque_framebuffer;
@@ -1445,6 +1454,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RD::get_singleton()->draw_command_begin_label("Render Opaque Pass");
scene_state.ubo.directional_light_count = p_render_data->directional_light_count;
+ scene_state.ubo.opaque_prepass_threshold = 0.0f;
_setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, p_render_data->render_buffers.is_valid());
@@ -1628,6 +1638,7 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page
render_data.render_info = p_render_info;
scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
+ scene_state.ubo.opaque_prepass_threshold = 0.1f;
_setup_environment(&render_data, true, Vector2(1, 1), !p_flip_y, Color(), false, p_use_pancake, shadow_pass_index);
@@ -1714,6 +1725,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con
_update_render_base_uniform_set();
scene_state.ubo.dual_paraboloid_side = 0;
+ scene_state.ubo.opaque_prepass_threshold = 0.0;
_setup_environment(&render_data, true, Vector2(1, 1), true, Color(), false, false);
@@ -1751,6 +1763,7 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform
scene_state.ubo.dual_paraboloid_side = 0;
scene_state.ubo.material_uv2_mode = false;
+ scene_state.ubo.opaque_prepass_threshold = 0.0f;
_setup_environment(&render_data, true, Vector2(1, 1), false, Color());
@@ -1794,6 +1807,7 @@ void RenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p
scene_state.ubo.dual_paraboloid_side = 0;
scene_state.ubo.material_uv2_mode = true;
+ scene_state.ubo.opaque_prepass_threshold = 0.0;
_setup_environment(&render_data, true, Vector2(1, 1), false, Color());
@@ -1940,7 +1954,9 @@ void RenderForwardClustered::_base_uniforms_changed() {
}
void RenderForwardClustered::_update_render_base_uniform_set() {
- if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != storage->lightmap_array_get_version())) {
+ if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != storage->lightmap_array_get_version()) || base_uniform_set_updated) {
+ base_uniform_set_updated = false;
+
if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) {
RD::get_singleton()->free(render_base_uniform_set);
}
@@ -1955,18 +1971,18 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
u.binding = 1;
u.ids.resize(12);
RID *ids_ptr = u.ids.ptrw();
- ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[0] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[1] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[2] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[3] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[4] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[5] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[6] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[7] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[8] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[9] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[10] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[11] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
uniforms.push_back(u);
}
@@ -1985,19 +2001,19 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RID sampler;
switch (decals_get_filter()) {
case RS::DECAL_FILTER_NEAREST: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_NEAREST_MIPMAPS: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_LINEAR: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_LINEAR_MIPMAPS: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
}
@@ -2012,19 +2028,19 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RID sampler;
switch (light_projectors_get_filter()) {
case RS::LIGHT_PROJECTOR_FILTER_NEAREST: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
}
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
index 2ba9558128..d7035f80e9 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -129,6 +129,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
virtual void _base_uniforms_changed() override;
virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) override;
+ bool base_uniform_set_updated = false;
void _update_render_base_uniform_set();
RID _setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture);
RID _setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas = false, int p_index = 0);
@@ -257,7 +258,8 @@ class RenderForwardClustered : public RendererSceneRenderRD {
float roughness_limiter_amount;
float roughness_limiter_limit;
- uint32_t roughness_limiter_pad[2];
+ float opaque_prepass_threshold;
+ uint32_t roughness_limiter_pad;
float sdf_to_bounds[16];
@@ -602,6 +604,11 @@ protected:
virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override;
public:
+ _FORCE_INLINE_ virtual void update_uniform_sets() override {
+ base_uniform_set_updated = true;
+ _update_render_base_uniform_set();
+ }
+
virtual GeometryInstance *geometry_instance_create(RID p_base) override;
virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override;
virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override;
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
index b74d7f9c31..0cdcbc952d 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -44,7 +44,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
uniforms.clear();
uses_screen_texture = false;
- if (code == String()) {
+ if (code.is_empty()) {
return; //just invalid, but no error
}
@@ -336,11 +336,20 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
valid = true;
}
-void SceneShaderForwardClustered::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
+void SceneShaderForwardClustered::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
- default_texture_params.erase(p_name);
+ if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+ default_texture_params[p_name].erase(p_index);
+
+ if (default_texture_params[p_name].is_empty()) {
+ default_texture_params.erase(p_name);
+ }
+ }
} else {
- default_texture_params[p_name] = p_texture;
+ if (!default_texture_params.has(p_name)) {
+ default_texture_params[p_name] = Map<int, RID>();
+ }
+ default_texture_params[p_name][p_index] = p_texture;
}
}
@@ -576,6 +585,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.renames["CUSTOM1"] = "custom1_attrib";
actions.renames["CUSTOM2"] = "custom2_attrib";
actions.renames["CUSTOM3"] = "custom3_attrib";
+ actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
// not implemented but need these just in case code is in the shaders
actions.renames["VIEW_INDEX"] = "0";
@@ -640,6 +650,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n";
actions.render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n";
actions.render_mode_defines["particle_trails"] = "#define USE_PARTICLE_TRAILS\n";
+ actions.render_mode_defines["depth_draw_opaque"] = "#define USE_OPAQUE_PREPASS\n";
bool force_lambert = GLOBAL_GET("rendering/shading/overrides/force_lambert_over_burley");
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
index b09bd7e065..98448ce846 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -135,7 +135,7 @@ public:
uint32_t ubo_size;
String code;
- Map<StringName, RID> default_texture_params;
+ Map<StringName, Map<int, RID>> default_texture_params;
DepthDraw depth_draw;
DepthTest depth_test;
@@ -166,7 +166,7 @@ public:
uint32_t index = 0;
virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index 95f5b46831..c0950d421d 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -483,6 +483,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
scene_state.ubo.viewport_size[0] = vp_he.x;
scene_state.ubo.viewport_size[1] = vp_he.y;
scene_state.ubo.directional_light_count = 0;
+ scene_state.ubo.opaque_prepass_threshold = 0.0;
// We can only use our full subpass approach if we're:
// - not reading from SCREEN_TEXTURE/DEPTH_TEXTURE
@@ -793,7 +794,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if (using_subpass_transparent) {
RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer);
- RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR_TRANSPARENT, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
render_list_params.framebuffer_format = fb_format;
if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) {
// secondary command buffers need more testing at this time
@@ -897,6 +898,7 @@ void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedAr
render_data.lod_distance_multiplier = p_lod_distance_multiplier;
scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
+ scene_state.ubo.opaque_prepass_threshold = 0.1;
_setup_environment(&render_data, true, Vector2(1, 1), !p_flip_y, Color(), false, p_use_pancake, shadow_pass_index);
@@ -978,6 +980,7 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c
scene_state.ubo.dual_paraboloid_side = 0;
scene_state.ubo.material_uv2_mode = false;
+ scene_state.ubo.opaque_prepass_threshold = 0.0f;
RenderDataRD render_data;
render_data.cam_projection = p_cam_projection;
@@ -1089,6 +1092,7 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const
_update_render_base_uniform_set();
scene_state.ubo.dual_paraboloid_side = 0;
+ scene_state.ubo.opaque_prepass_threshold = 0.0;
RenderDataRD render_data;
render_data.cam_projection = p_cam_projection;
@@ -1447,13 +1451,13 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
}
// ADD Element
- if (p_pass_mode == PASS_MODE_COLOR) {
+ if (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) {
#ifdef DEBUG_ENABLED
bool force_alpha = unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW);
#else
bool force_alpha = false;
#endif
- if (!force_alpha && (surf->flags & (GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH | GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE))) {
+ if (!force_alpha && (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) {
rl->add_element(surf);
}
if (force_alpha || (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA)) {
@@ -1821,6 +1825,10 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
const RenderElementInfo &element_info = p_params->element_info[i];
const GeometryInstanceForwardMobile *inst = surf->owner;
+ if (inst->instance_count == 0) {
+ continue;
+ }
+
uint32_t base_spec_constants = p_params->spec_constant_base_flags;
// GeometryInstanceForwardMobile::PushConstant push_constant = inst->push_constant;
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
index 74bfe16557..0ef1fe6ceb 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -292,7 +292,8 @@ protected:
float roughness_limiter_amount;
float roughness_limiter_limit;
- uint32_t roughness_limiter_pad[2];
+ float opaque_prepass_threshold;
+ uint32_t roughness_limiter_pad;
// Fog
uint32_t fog_enabled;
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
index 16d650a540..9b96cc18bc 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -47,7 +47,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
uniforms.clear();
uses_screen_texture = false;
- if (code == String()) {
+ if (code.is_empty()) {
return; //just invalid, but no error
}
@@ -325,11 +325,20 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
valid = true;
}
-void SceneShaderForwardMobile::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
+void SceneShaderForwardMobile::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
- default_texture_params.erase(p_name);
+ if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+ default_texture_params[p_name].erase(p_index);
+
+ if (default_texture_params[p_name].is_empty()) {
+ default_texture_params.erase(p_name);
+ }
+ }
} else {
- default_texture_params[p_name] = p_texture;
+ if (!default_texture_params.has(p_name)) {
+ default_texture_params[p_name] = Map<int, RID>();
+ }
+ default_texture_params[p_name][p_index] = p_texture;
}
}
@@ -564,6 +573,7 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.renames["CUSTOM1"] = "custom1_attrib";
actions.renames["CUSTOM2"] = "custom2_attrib";
actions.renames["CUSTOM3"] = "custom3_attrib";
+ actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
actions.renames["VIEW_INDEX"] = "ViewIndex";
actions.renames["VIEW_MONO_LEFT"] = "0";
@@ -627,6 +637,7 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n";
actions.render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n";
actions.render_mode_defines["particle_trails"] = "#define USE_PARTICLE_TRAILS\n";
+ actions.render_mode_defines["depth_draw_opaque"] = "#define USE_OPAQUE_PREPASS\n";
bool force_lambert = GLOBAL_GET("rendering/shading/overrides/force_lambert_over_burley");
if (!force_lambert) {
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
index e1c10f0206..770f9bde3b 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -111,7 +111,7 @@ public:
uint32_t ubo_size;
String code;
- Map<StringName, RID> default_texture_params;
+ Map<StringName, Map<int, RID>> default_texture_params;
DepthDraw depth_draw;
DepthTest depth_test;
@@ -141,7 +141,7 @@ public:
uint32_t index = 0;
virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
index 0d60052666..e812a48d3d 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.h b/servers/rendering/renderer_rd/pipeline_cache_rd.h
index e52f47fa47..8d82480b38 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.h
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 13a3e814f6..704a164a3a 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -758,6 +758,10 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
instance_count = storage->multimesh_get_instances_to_draw(multimesh);
+ if (instance_count == 0) {
+ break;
+ }
+
RID uniform_set = storage->multimesh_get_2d_uniform_set(multimesh, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET);
RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, uniform_set, TRANSFORMS_UNIFORM_SET);
push_constant.flags |= 1; //multimesh, trails disabled
@@ -1949,7 +1953,7 @@ void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) {
uses_sdf = false;
uses_time = false;
- if (code == String()) {
+ if (code.is_empty()) {
return; //just invalid, but no error
}
@@ -2120,11 +2124,20 @@ void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) {
valid = true;
}
-void RendererCanvasRenderRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
+void RendererCanvasRenderRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
- default_texture_params.erase(p_name);
+ if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+ default_texture_params[p_name].erase(p_index);
+
+ if (default_texture_params[p_name].is_empty()) {
+ default_texture_params.erase(p_name);
+ }
+ }
} else {
- default_texture_params[p_name] = p_texture;
+ if (!default_texture_params.has(p_name)) {
+ default_texture_params[p_name] = Map<int, RID>();
+ }
+ default_texture_params[p_name][p_index] = p_texture;
}
}
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index ec7d7e2854..c9544a5239 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -173,14 +173,14 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
uint32_t ubo_size;
String code;
- Map<StringName, RID> default_texture_params;
+ Map<StringName, Map<int, RID>> default_texture_params;
bool uses_screen_texture = false;
bool uses_sdf = false;
bool uses_time = false;
virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index 559e6d5ad7..2f8ef696cd 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -240,7 +240,7 @@ RendererCompositorRD *RendererCompositorRD::singleton = nullptr;
RendererCompositorRD::RendererCompositorRD() {
{
String shader_cache_dir = Engine::get_singleton()->get_shader_cache_path();
- if (shader_cache_dir == String()) {
+ if (shader_cache_dir.is_empty()) {
shader_cache_dir = "user://";
}
DirAccessRef da = DirAccess::open(shader_cache_dir);
@@ -261,7 +261,7 @@ RendererCompositorRD::RendererCompositorRD() {
shader_cache_dir = String(); //disable only if not editor
}
- if (shader_cache_dir != String()) {
+ if (!shader_cache_dir.is_empty()) {
bool compress = GLOBAL_GET("rendering/shader_compiler/shader_cache/compress");
bool use_zstd = GLOBAL_GET("rendering/shader_compiler/shader_cache/use_zstd_compression");
bool strip_debug = GLOBAL_GET("rendering/shader_compiler/shader_cache/strip_debug");
@@ -281,12 +281,12 @@ RendererCompositorRD::RendererCompositorRD() {
storage = memnew(RendererStorageRD);
canvas = memnew(RendererCanvasRenderRD(storage));
- uint32_t back_end = GLOBAL_GET("rendering/vulkan/rendering/back_end");
+ back_end = (bool)(int)GLOBAL_GET("rendering/vulkan/rendering/back_end");
uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
- if (back_end == 1 || textures_per_stage < 48) {
+ if (back_end || textures_per_stage < 48) {
scene = memnew(RendererSceneRenderImplementation::RenderForwardMobile(storage));
- } else { // back_end == 0
+ } else { // back_end == false
// default to our high end renderer
scene = memnew(RendererSceneRenderImplementation::RenderForwardClustered(storage));
}
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h
index 0230c46800..9a992d5819 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.h
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -116,8 +116,6 @@ public:
_create_func = _create_current;
}
- virtual bool is_low_end() const { return false; }
-
static RendererCompositorRD *singleton;
RendererCompositorRD();
~RendererCompositorRD();
diff --git a/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp
index 550e59ba98..7ea117ef33 100644
--- a/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_rd/renderer_scene_environment_rd.h b/servers/rendering/renderer_rd/renderer_scene_environment_rd.h
index ec9cb4a798..5731577f78 100644
--- a/servers/rendering/renderer_rd/renderer_scene_environment_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_environment_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
index 807af00c8e..ba7569aeb5 100644
--- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -1305,7 +1305,6 @@ void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_fr
RD::get_singleton()->draw_list_draw(p_draw_list, false, total_probes, total_points);
if (gi->sdfgi_debug_probe_dir != Vector3()) {
- print_line("CLICK DEBUG ME?");
uint32_t cascade = 0;
Vector3 offset = Vector3((Vector3i(1, 1, 1) * -int32_t(cascade_size >> 1) + cascades[cascade].position)) * cascades[cascade].cell_size * Vector3(1.0, 1.0 / y_mult, 1.0);
Vector3 probe_size = cascades[cascade].cell_size * (cascade_size / SDFGI::PROBE_DIVISOR) * Vector3(1.0, 1.0 / y_mult, 1.0);
@@ -1333,11 +1332,6 @@ void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_fr
}
}
- if (gi->sdfgi_debug_probe_enabled) {
- print_line("found: " + gi->sdfgi_debug_probe_index);
- } else {
- print_line("no found");
- }
gi->sdfgi_debug_probe_dir = Vector3();
}
@@ -1864,7 +1858,7 @@ void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region,
Ref<Image> img;
img.instantiate();
for (uint32_t i = 0; i < cascade_size; i++) {
- Vector<uint8_t> subarr = data.subarray(128 * 128 * i, 128 * 128 * (i + 1) - 1);
+ Vector<uint8_t> subarr = data.slice(128 * 128 * i, 128 * 128 * (i + 1));
img->create(cascade_size, cascade_size, false, Image::FORMAT_L8, subarr);
img->save_png("res://cascade_sdf_" + itos(cascade) + "_" + itos(i) + ".png");
}
@@ -1877,7 +1871,7 @@ void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region,
Ref<Image> img;
img.instantiate();
for (uint32_t i = 0; i < cascade_size; i++) {
- Vector<uint8_t> subarr = data.subarray(128 * 128 * i * 2, 128 * 128 * (i + 1) * 2 - 1);
+ Vector<uint8_t> subarr = data.slice(128 * 128 * i * 2, 128 * 128 * (i + 1) * 2);
img->createcascade_size, cascade_size, false, Image::FORMAT_RGB565, subarr);
img->convert(Image::FORMAT_RGBA8);
img->save_png("res://cascade_" + itos(cascade) + "_" + itos(i) + ".png");
@@ -3132,8 +3126,8 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.width = rb->width;
- tf.height = rb->height;
+ tf.width = rb->internal_width;
+ tf.height = rb->internal_height;
if (half_resolution) {
tf.width >>= 1;
tf.height >>= 1;
@@ -3146,13 +3140,13 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
PushConstant push_constant;
- push_constant.screen_size[0] = rb->width;
- push_constant.screen_size[1] = rb->height;
+ push_constant.screen_size[0] = rb->internal_width;
+ push_constant.screen_size[1] = rb->internal_height;
push_constant.z_near = p_projection.get_z_near();
push_constant.z_far = p_projection.get_z_far();
push_constant.orthogonal = p_projection.is_orthogonal();
- push_constant.proj_info[0] = -2.0f / (rb->width * p_projection.matrix[0][0]);
- push_constant.proj_info[1] = -2.0f / (rb->height * p_projection.matrix[1][1]);
+ push_constant.proj_info[0] = -2.0f / (rb->internal_width * p_projection.matrix[0][0]);
+ push_constant.proj_info[1] = -2.0f / (rb->internal_height * p_projection.matrix[1][1]);
push_constant.proj_info[2] = (1.0f - p_projection.matrix[0][2]) / p_projection.matrix[0][0];
push_constant.proj_info[3] = (1.0f + p_projection.matrix[1][2]) / p_projection.matrix[1][1];
push_constant.max_voxel_gi_instances = MIN((uint64_t)MAX_VOXEL_GI_INSTANCES, p_voxel_gi_instances.size());
@@ -3344,9 +3338,9 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant));
if (rb->gi.using_half_size_gi) {
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->width >> 1, rb->height >> 1, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width >> 1, rb->internal_height >> 1, 1);
} else {
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->width, rb->height, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width, rb->internal_height, 1);
}
//do barrier later to allow oeverlap
//RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //no barriers, let other compute, raster and transfer happen at the same time
diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
index 9f6fc8a9b7..a407199d0a 100644
--- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -602,19 +602,15 @@ public:
};
struct VoxelGIData {
- float xform[16];
- float bounds[3];
- float dynamic_range;
+ float xform[16]; // 64 - 64
- float bias;
- float normal_bias;
- uint32_t blend_ambient;
- uint32_t texture_slot;
+ float bounds[3]; // 12 - 76
+ float dynamic_range; // 4 - 80
- uint32_t pad0;
- uint32_t pad1;
- uint32_t pad2;
- uint32_t mipmaps;
+ float bias; // 4 - 84
+ float normal_bias; // 4 - 88
+ uint32_t blend_ambient; // 4 - 92
+ uint32_t mipmaps; // 4 - 96
};
struct PushConstant {
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index 3d8ae4c944..12e5b71df1 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -1503,8 +1503,8 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
RD::TextureFormat tf;
tf.format = _render_buffers_get_color_format(); // RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.width = rb->width;
- tf.height = rb->height;
+ tf.width = rb->internal_width;
+ tf.height = rb->internal_height;
tf.texture_type = rb->view_count > 1 ? RD::TEXTURE_TYPE_2D_ARRAY : RD::TEXTURE_TYPE_2D;
tf.array_layers = rb->view_count;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
@@ -1515,6 +1515,10 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
}
tf.mipmaps = mipmaps_required;
+ rb->sss_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ tf.width = rb->internal_width;
+ tf.height = rb->internal_height;
rb->blur[0].texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
//the second one is smaller (only used for separatable part of blur)
tf.width >>= 1;
@@ -1522,8 +1526,8 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
tf.mipmaps--;
rb->blur[1].texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
- int base_width = rb->width;
- int base_height = rb->height;
+ int base_width = rb->internal_width;
+ int base_height = rb->internal_height;
for (uint32_t i = 0; i < mipmaps_required; i++) {
RenderBuffers::Blur::Mipmap mm;
@@ -1577,8 +1581,8 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
// create 4 weight textures, 2 full size, 2 half size
tf.format = RD::DATA_FORMAT_R16_SFLOAT; // We could probably use DATA_FORMAT_R8_SNORM if we don't pre-multiply by blur_size but that depends on whether we can remove DEPTH_GAP
- tf.width = rb->width;
- tf.height = rb->height;
+ tf.width = rb->internal_width;
+ tf.height = rb->internal_height;
tf.texture_type = rb->view_count > 1 ? RD::TEXTURE_TYPE_2D_ARRAY : RD::TEXTURE_TYPE_2D;
tf.array_layers = rb->view_count;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
@@ -1656,8 +1660,8 @@ void RendererSceneRenderRD::_allocate_depth_backbuffer_textures(RenderBuffers *r
void RendererSceneRenderRD::_allocate_luminance_textures(RenderBuffers *rb) {
ERR_FAIL_COND(!rb->luminance.current.is_null());
- int w = rb->width;
- int h = rb->height;
+ int w = rb->internal_width;
+ int h = rb->internal_height;
while (true) {
w = MAX(w / 8, 1);
@@ -1709,9 +1713,26 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
rb->texture_fb = RID();
}
- if (rb->texture.is_valid()) {
- RD::get_singleton()->free(rb->texture);
+ if (rb->internal_texture == rb->texture && rb->internal_texture.is_valid()) {
+ RD::get_singleton()->free(rb->internal_texture);
rb->texture = RID();
+ rb->internal_texture = RID();
+ rb->upscale_texture = RID();
+ } else {
+ if (rb->texture.is_valid()) {
+ RD::get_singleton()->free(rb->texture);
+ rb->texture = RID();
+ }
+
+ if (rb->internal_texture.is_valid()) {
+ RD::get_singleton()->free(rb->internal_texture);
+ rb->internal_texture = RID();
+ }
+
+ if (rb->upscale_texture.is_valid()) {
+ RD::get_singleton()->free(rb->upscale_texture);
+ rb->upscale_texture = RID();
+ }
}
if (rb->depth_texture.is_valid()) {
@@ -1729,6 +1750,11 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
rb->depth_back_texture = RID();
}
+ if (rb->sss_texture.is_valid()) {
+ RD::get_singleton()->free(rb->sss_texture);
+ rb->sss_texture = RID();
+ }
+
for (int i = 0; i < 2; i++) {
for (int m = 0; m < rb->blur[i].mipmaps.size(); m++) {
// do we free the texture slice here? or is it enough to free the main texture?
@@ -1818,7 +1844,7 @@ void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatri
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
- bool can_use_effects = rb->width >= 8 && rb->height >= 8;
+ bool can_use_effects = rb->internal_width >= 8 && rb->internal_height >= 8;
if (!can_use_effects) {
//just copy
@@ -1829,18 +1855,18 @@ void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatri
_allocate_blur_textures(rb);
}
- storage->get_effects()->sub_surface_scattering(rb->texture, rb->blur[0].mipmaps[0].texture, rb->depth_texture, p_camera, Size2i(rb->width, rb->height), sss_scale, sss_depth_scale, sss_quality);
+ storage->get_effects()->sub_surface_scattering(rb->internal_texture, rb->sss_texture, rb->depth_texture, p_camera, Size2i(rb->internal_width, rb->internal_height), sss_scale, sss_depth_scale, sss_quality);
}
void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive) {
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
- bool can_use_effects = rb->width >= 8 && rb->height >= 8;
+ bool can_use_effects = rb->internal_width >= 8 && rb->internal_height >= 8;
if (!can_use_effects) {
//just copy
- storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->texture, RID());
+ storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, RID());
return;
}
@@ -1852,8 +1878,8 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb
if (rb->ssr.depth_scaled.is_null()) {
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R32_SFLOAT;
- tf.width = rb->width / 2;
- tf.height = rb->height / 2;
+ tf.width = rb->internal_width / 2;
+ tf.height = rb->internal_height / 2;
tf.texture_type = RD::TEXTURE_TYPE_2D;
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
@@ -1867,8 +1893,8 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb
if (ssr_roughness_quality != RS::ENV_SSR_ROUGNESS_QUALITY_DISABLED && !rb->ssr.blur_radius[0].is_valid()) {
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.width = rb->width / 2;
- tf.height = rb->height / 2;
+ tf.width = rb->internal_width / 2;
+ tf.height = rb->internal_height / 2;
tf.texture_type = RD::TEXTURE_TYPE_2D;
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
@@ -1880,8 +1906,8 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb
_allocate_blur_textures(rb);
}
- storage->get_effects()->screen_space_reflection(rb->texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].mipmaps[1].texture, rb->blur[1].mipmaps[0].texture, Size2i(rb->width / 2, rb->height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection);
- storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->texture, rb->blur[0].mipmaps[1].texture);
+ storage->get_effects()->screen_space_reflection(rb->internal_texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].mipmaps[1].texture, rb->blur[1].mipmaps[0].texture, Size2i(rb->internal_width / 2, rb->internal_height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection);
+ storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, rb->blur[0].mipmaps[1].texture);
}
void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection) {
@@ -1918,15 +1944,15 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
int half_width;
int half_height;
if (ssao_half_size) {
- buffer_width = (rb->width + 3) / 4;
- buffer_height = (rb->height + 3) / 4;
- half_width = (rb->width + 7) / 8;
- half_height = (rb->height + 7) / 8;
+ buffer_width = (rb->internal_width + 3) / 4;
+ buffer_height = (rb->internal_height + 3) / 4;
+ half_width = (rb->internal_width + 7) / 8;
+ half_height = (rb->internal_height + 7) / 8;
} else {
- buffer_width = (rb->width + 1) / 2;
- buffer_height = (rb->height + 1) / 2;
- half_width = (rb->width + 3) / 4;
- half_height = (rb->height + 3) / 4;
+ buffer_width = (rb->internal_width + 1) / 2;
+ buffer_height = (rb->internal_height + 1) / 2;
+ half_width = (rb->internal_width + 3) / 4;
+ half_height = (rb->internal_height + 3) / 4;
}
bool uniform_sets_are_invalid = false;
if (rb->ssao.depth.is_null()) {
@@ -1998,8 +2024,8 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
{
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.width = rb->width;
- tf.height = rb->height;
+ tf.width = rb->internal_width;
+ tf.height = rb->internal_height;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
rb->ssao.ao_final = RD::get_singleton()->texture_create(tf, RD::TextureView());
RD::get_singleton()->set_resource_name(rb->ssao.ao_final, "SSAO Final");
@@ -2022,7 +2048,7 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
settings.blur_passes = ssao_blur_passes;
settings.fadeout_from = ssao_fadeout_from;
settings.fadeout_to = ssao_fadeout_to;
- settings.full_screen_size = Size2i(rb->width, rb->height);
+ settings.full_screen_size = Size2i(rb->internal_width, rb->internal_height);
settings.half_screen_size = Size2i(buffer_width, buffer_height);
settings.quarter_screen_size = Size2i(half_width, half_height);
@@ -2086,7 +2112,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
ERR_FAIL_COND(!rb);
RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_render_data->environment);
- //glow (if enabled)
+ // Glow and override exposure (if enabled).
CameraEffects *camfx = camera_effects_owner.get_or_null(p_render_data->camera_effects);
bool can_use_effects = rb->width >= 8 && rb->height >= 8;
@@ -2102,9 +2128,9 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
EffectsRD::BokehBuffers buffers;
- // textures we use
- buffers.base_texture_size = Size2i(rb->width, rb->height);
- buffers.base_texture = rb->texture;
+ // Textures we use
+ buffers.base_texture_size = Size2i(rb->internal_width, rb->internal_height);
+ buffers.base_texture = rb->internal_texture;
buffers.depth_texture = rb->depth_texture;
buffers.secondary_texture = rb->blur[0].mipmaps[0].texture;
buffers.half_texture[0] = rb->blur[1].mipmaps[0].texture;
@@ -2114,7 +2140,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
if (can_use_storage) {
storage->get_effects()->bokeh_dof(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal);
} else {
- // set framebuffers
+ // Set framebuffers.
buffers.base_fb = rb->texture_fb;
buffers.secondary_fb = rb->weight_buffers[1].fb;
buffers.half_fb[0] = rb->weight_buffers[2].fb;
@@ -2124,7 +2150,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
buffers.weight_texture[2] = rb->weight_buffers[2].weight;
buffers.weight_texture[3] = rb->weight_buffers[3].weight;
- // set weight buffers
+ // Set weight buffers.
buffers.base_weight_fb = rb->base_weight_fb;
storage->get_effects()->bokeh_dof_raster(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal);
@@ -2143,17 +2169,17 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
double step = env->auto_exp_speed * time_step;
if (can_use_storage) {
- storage->get_effects()->luminance_reduction(rb->texture, Size2i(rb->width, rb->height), rb->luminance.reduce, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
+ storage->get_effects()->luminance_reduction(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
} else {
- storage->get_effects()->luminance_reduction_raster(rb->texture, Size2i(rb->width, rb->height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
+ storage->get_effects()->luminance_reduction_raster(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
}
- //swap final reduce with prev luminance
+ // Swap final reduce with prev luminance.
SWAP(rb->luminance.current, rb->luminance.reduce.write[rb->luminance.reduce.size() - 1]);
if (!can_use_storage) {
SWAP(rb->luminance.current_fb, rb->luminance.fb.write[rb->luminance.fb.size() - 1]);
}
- RenderingServerDefault::redraw_request(); //redraw all the time if auto exposure rendering is on
+ RenderingServerDefault::redraw_request(); // Redraw all the time if auto exposure rendering is on.
RD::get_singleton()->draw_command_end_label();
}
@@ -2188,9 +2214,9 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
luminance_texture = rb->luminance.current;
}
if (can_use_storage) {
- storage->get_effects()->gaussian_glow(rb->texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
+ storage->get_effects()->gaussian_glow(rb->internal_texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
} else {
- storage->get_effects()->gaussian_glow_raster(rb->texture, rb->blur[1].mipmaps[i].half_fb, rb->blur[1].mipmaps[i].half_texture, rb->blur[1].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
+ storage->get_effects()->gaussian_glow_raster(rb->internal_texture, rb->blur[1].mipmaps[i].half_fb, rb->blur[1].mipmaps[i].half_texture, rb->blur[1].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
}
} else {
if (can_use_storage) {
@@ -2207,7 +2233,6 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
{
RD::get_singleton()->draw_command_begin_label("Tonemap");
- //tonemap
EffectsRD::TonemapSettings tonemap;
if (can_use_effects && env && env->auto_exposure && rb->luminance.current.is_valid()) {
@@ -2238,7 +2263,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
}
tonemap.use_debanding = rb->use_debanding;
- tonemap.texture_size = Vector2i(rb->width, rb->height);
+ tonemap.texture_size = Vector2i(rb->internal_width, rb->internal_height);
if (env) {
tonemap.tonemap_mode = env->tone_mapper;
@@ -2246,6 +2271,10 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
tonemap.exposure = env->exposure;
}
+ if (camfx && camfx->override_exposure_enabled) {
+ tonemap.exposure = camfx->override_exposure;
+ }
+
tonemap.use_color_correction = false;
tonemap.use_1d_color_correction = false;
tonemap.color_correction_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
@@ -2265,7 +2294,15 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier();
tonemap.view_count = p_render_data->view_count;
- storage->get_effects()->tonemapper(rb->texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap);
+ storage->get_effects()->tonemapper(rb->internal_texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap);
+
+ RD::get_singleton()->draw_command_end_label();
+ }
+
+ if (can_use_effects && can_use_storage && (rb->internal_width != rb->width || rb->internal_height != rb->height)) {
+ RD::get_singleton()->draw_command_begin_label("FSR Upscale");
+
+ storage->get_effects()->fsr_upscale(rb->internal_texture, rb->upscale_texture, rb->texture, Size2i(rb->internal_width, rb->internal_height), Size2i(rb->width, rb->height), rb->fsr_sharpness);
RD::get_singleton()->draw_command_end_label();
}
@@ -2280,6 +2317,8 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
ERR_FAIL_COND(!rb);
RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_render_data->environment);
+ // Override exposure (if enabled).
+ CameraEffects *camfx = camera_effects_owner.get_or_null(p_render_data->camera_effects);
bool can_use_effects = rb->width >= 8 && rb->height >= 8;
@@ -2293,6 +2332,10 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
tonemap.white = env->white;
}
+ if (camfx && camfx->override_exposure_enabled) {
+ tonemap.exposure = camfx->override_exposure;
+ }
+
// We don't support glow or auto exposure here, if they are needed, don't use subpasses!
// The problem is that we need to use the result so far and process them before we can
// apply this to our results.
@@ -2619,14 +2662,28 @@ bool RendererSceneRenderRD::_render_buffers_can_be_storage() {
return true;
}
-void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) {
+void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) {
ERR_FAIL_COND_MSG(p_view_count == 0, "Must have at least 1 view");
+ if (!_render_buffers_can_be_storage()) {
+ p_internal_height = p_height;
+ p_internal_width = p_width;
+ }
+
+ if (p_width != p_internal_width) {
+ float fsr_mipmap_bias = -log2f(p_width / p_internal_width) + p_fsr_mipmap_bias;
+ storage->sampler_rd_configure_custom(fsr_mipmap_bias);
+ update_uniform_sets();
+ }
+
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
// Should we add an overrule per viewport?
+ rb->internal_width = p_internal_width;
+ rb->internal_height = p_internal_height;
rb->width = p_width;
rb->height = p_height;
+ rb->fsr_sharpness = p_fsr_sharpness;
rb->render_target = p_render_target;
rb->msaa = p_msaa;
rb->screen_space_aa = p_screen_space_aa;
@@ -2648,8 +2705,8 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
}
tf.format = _render_buffers_get_color_format();
- tf.width = rb->width;
- tf.height = rb->height;
+ tf.width = rb->internal_width; // If set to rb->width, msaa won't crash
+ tf.height = rb->internal_height; // If set to rb->width, msaa won't crash
tf.array_layers = rb->view_count; // create a layer for every view
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | (_render_buffers_can_be_storage() ? RD::TEXTURE_USAGE_STORAGE_BIT : 0) | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) {
@@ -2657,7 +2714,17 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
}
tf.usage_bits |= RD::TEXTURE_USAGE_INPUT_ATTACHMENT_BIT; // only needed when using subpasses in the mobile renderer
- rb->texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ rb->internal_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ if ((p_internal_width != p_width || p_internal_height != p_height)) {
+ tf.width = rb->width;
+ tf.height = rb->height;
+ rb->texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ rb->upscale_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ } else {
+ rb->texture = rb->internal_texture;
+ rb->upscale_texture = rb->internal_texture;
+ }
}
{
@@ -2671,8 +2738,8 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
tf.format = RD::DATA_FORMAT_R32_SFLOAT;
}
- tf.width = rb->width;
- tf.height = rb->height;
+ tf.width = rb->internal_width;
+ tf.height = rb->internal_height;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
tf.array_layers = rb->view_count; // create a layer for every view
@@ -2688,16 +2755,16 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
if (!_render_buffers_can_be_storage()) {
// ONLY USED ON MOBILE RENDERER, ONLY USED FOR POST EFFECTS!
Vector<RID> fb;
- fb.push_back(rb->texture);
+ fb.push_back(rb->internal_texture);
rb->texture_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, rb->view_count);
}
RID target_texture = storage->render_target_get_rd_texture(rb->render_target);
- rb->data->configure(rb->texture, rb->depth_texture, target_texture, rb->width, rb->height, p_msaa, p_view_count);
+ rb->data->configure(rb->internal_texture, rb->depth_texture, target_texture, p_internal_width, p_internal_height, p_msaa, p_view_count);
if (is_clustered_enabled()) {
- rb->cluster_builder->setup(Size2i(rb->width, rb->height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->texture);
+ rb->cluster_builder->setup(Size2i(p_internal_width, p_internal_height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->internal_texture);
}
}
@@ -3514,7 +3581,7 @@ void RendererSceneRenderRD::FogShaderData::set_code(const String &p_code) {
ubo_size = 0;
uniforms.clear();
- if (code == String()) {
+ if (code.is_empty()) {
return; //just invalid, but no error
}
@@ -3549,11 +3616,20 @@ void RendererSceneRenderRD::FogShaderData::set_code(const String &p_code) {
valid = true;
}
-void RendererSceneRenderRD::FogShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
+void RendererSceneRenderRD::FogShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
- default_texture_params.erase(p_name);
+ if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+ default_texture_params[p_name].erase(p_index);
+
+ if (default_texture_params[p_name].is_empty()) {
+ default_texture_params.erase(p_name);
+ }
+ }
} else {
- default_texture_params[p_name] = p_texture;
+ if (!default_texture_params.has(p_name)) {
+ default_texture_params[p_name] = Map<int, RID>();
+ }
+ default_texture_params[p_name][p_index] = p_texture;
}
}
@@ -3778,6 +3854,18 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
rb->volumetric_fog->fog_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
RD::get_singleton()->set_resource_name(rb->volumetric_fog->fog_map, "Fog map");
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ Vector<uint8_t> dm;
+ dm.resize(target_width * target_height * volumetric_fog_depth * 4);
+ dm.fill(0);
+
+ rb->volumetric_fog->density_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
+ RD::get_singleton()->set_resource_name(rb->volumetric_fog->density_map, "Fog density map");
+ rb->volumetric_fog->light_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
+ RD::get_singleton()->set_resource_name(rb->volumetric_fog->light_map, "Fog light map");
+ rb->volumetric_fog->emissive_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
+ RD::get_singleton()->set_resource_name(rb->volumetric_fog->emissive_map, "Fog emissive map");
+#else
tf.format = RD::DATA_FORMAT_R32_UINT;
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
rb->volumetric_fog->density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
@@ -3789,6 +3877,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
rb->volumetric_fog->emissive_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
RD::get_singleton()->set_resource_name(rb->volumetric_fog->emissive_map, "Fog emissive map");
RD::get_singleton()->texture_clear(rb->volumetric_fog->emissive_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
+#endif
Vector<RD::Uniform> uniforms;
{
@@ -3854,7 +3943,11 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
{
RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
u.binding = 1;
u.ids.push_back(rb->volumetric_fog->emissive_map);
uniforms.push_back(u);
@@ -3870,7 +3963,11 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
{
RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
u.binding = 3;
u.ids.push_back(rb->volumetric_fog->density_map);
uniforms.push_back(u);
@@ -3878,7 +3975,11 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
{
RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
u.binding = 4;
u.ids.push_back(rb->volumetric_fog->light_map);
uniforms.push_back(u);
@@ -3954,6 +4055,10 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
kernel_size = Vector3i(int32_t(rb->volumetric_fog->width), int32_t(rb->volumetric_fog->height), int32_t(rb->volumetric_fog->depth));
}
+ if (kernel_size.x == 0 || kernel_size.y == 0 || kernel_size.z == 0) {
+ continue;
+ }
+
volumetric_fog.push_constant.position[0] = position.x;
volumetric_fog.push_constant.position[1] = position.y;
volumetric_fog.push_constant.position[2] = position.z;
@@ -4141,14 +4246,22 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
}
{
RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
u.binding = 16;
u.ids.push_back(rb->volumetric_fog->density_map);
uniforms.push_back(u);
}
{
RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
u.binding = 17;
u.ids.push_back(rb->volumetric_fog->light_map);
uniforms.push_back(u);
@@ -4156,7 +4269,11 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
{
RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
u.binding = 18;
u.ids.push_back(rb->volumetric_fog->emissive_map);
uniforms.push_back(u);
@@ -4167,7 +4284,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 19;
RID radiance_texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
- RID sky_texture = sky.sky_get_radiance_texture_rd(env->sky);
+ RID sky_texture = env->sky.is_valid() ? sky.sky_get_radiance_texture_rd(env->sky) : RID();
u.ids.push_back(sky_texture.is_valid() ? sky_texture : radiance_texture);
uniforms.push_back(u);
}
@@ -4300,9 +4417,9 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
uint32_t cluster_screen_width = (rb->width - 1) / cluster_size + 1;
uint32_t cluster_screen_height = (rb->height - 1) / cluster_size + 1;
- params.cluster_type_size = cluster_screen_width * cluster_screen_height * (32 + 32);
- params.cluster_width = cluster_screen_width;
params.max_cluster_element_count_div_32 = max_cluster_elements / 32;
+ params.cluster_type_size = cluster_screen_width * cluster_screen_height * (params.max_cluster_element_count_div_32 + 32);
+ params.cluster_width = cluster_screen_width;
params.screen_size[0] = rb->width;
params.screen_size[1] = rb->height;
@@ -4682,9 +4799,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
if (p_render_buffers.is_valid()) {
/*
_debug_draw_cluster(p_render_buffers);
-
RENDER_TIMESTAMP("Tonemap");
-
_render_buffers_post_process_and_tonemap(&render_data);
*/
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index baa0144d43..d5af19a258 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -456,7 +456,11 @@ private:
struct RenderBuffers {
RenderBufferData *data = nullptr;
- int width = 0, height = 0;
+ int internal_width = 0;
+ int internal_height = 0;
+ int width = 0;
+ int height = 0;
+ float fsr_sharpness = 0.2f;
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
bool use_debanding = false;
@@ -466,9 +470,12 @@ private:
uint64_t auto_exposure_version = 1;
- RID texture; //main texture for rendering to, must be filled after done rendering
+ RID sss_texture; //texture for sss. This needs to be a different resolution than blur[0]
+ RID internal_texture; //main texture for rendering to, must be filled after done rendering
+ RID texture; //upscaled version of main texture (This uses the same resource as internal_texture if there is no upscaling)
RID depth_texture; //main depth texture
RID texture_fb; // framebuffer for the main texture, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!!
+ RID upscale_texture; //used when upscaling internal_texture (This uses the same resource as internal_texture if there is no upscaling)
RendererSceneGIRD::SDFGI *sdfgi = nullptr;
VolumetricFog *volumetric_fog = nullptr;
@@ -879,12 +886,12 @@ private:
String path;
String code;
- Map<StringName, RID> default_texture_params;
+ Map<StringName, Map<int, RID>> default_texture_params;
bool uses_time;
virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
@@ -1332,7 +1339,7 @@ public:
virtual RD::DataFormat _render_buffers_get_color_format();
virtual bool _render_buffers_can_be_storage();
virtual RID render_buffers_create() override;
- virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override;
+ virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override;
virtual void gi_set_use_half_resolution(bool p_enable) override;
RID render_buffers_get_depth_texture(RID p_render_buffers);
@@ -1363,6 +1370,8 @@ public:
float render_buffers_get_volumetric_fog_end(RID p_render_buffers);
float render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers);
+ virtual void update_uniform_sets(){};
+
virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
index ce41e191e2..9e3108c39d 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -46,7 +46,7 @@ void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) {
ubo_size = 0;
uniforms.clear();
- if (code == String()) {
+ if (code.is_empty()) {
return; //just invalid, but no error
}
@@ -137,11 +137,20 @@ void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) {
valid = true;
}
-void RendererSceneSkyRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
+void RendererSceneSkyRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
- default_texture_params.erase(p_name);
+ if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+ default_texture_params[p_name].erase(p_index);
+
+ if (default_texture_params[p_name].is_empty()) {
+ default_texture_params.erase(p_name);
+ }
+ }
} else {
- default_texture_params[p_name] = p_texture;
+ if (!default_texture_params.has(p_name)) {
+ default_texture_params[p_name] = Map<int, RID>();
+ }
+ default_texture_params[p_name][p_index] = p_texture;
}
}
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
index 7f563c9bc4..1359cdec67 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -118,7 +118,7 @@ private:
String path;
String code;
- Map<StringName, RID> default_texture_params;
+ Map<StringName, Map<int, RID>> default_texture_params;
bool uses_time;
bool uses_position;
@@ -127,7 +127,7 @@ private:
bool uses_light;
virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
index d2c8d0e47c..496dde123d 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -1034,7 +1034,7 @@ Ref<Image> RendererStorageRD::texture_2d_get(RID p_texture) const {
ERR_FAIL_COND_V(!tex, Ref<Image>());
#ifdef TOOLS_ENABLED
- if (tex->image_cache_2d.is_valid()) {
+ if (tex->image_cache_2d.is_valid() && !tex->is_render_target) {
return tex->image_cache_2d;
}
#endif
@@ -1049,7 +1049,7 @@ Ref<Image> RendererStorageRD::texture_2d_get(RID p_texture) const {
}
#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint()) {
+ if (Engine::get_singleton()->is_editor_hint() && !tex->is_render_target) {
tex->image_cache_2d = image;
}
#endif
@@ -1089,7 +1089,7 @@ Vector<Ref<Image>> RendererStorageRD::texture_3d_get(RID p_texture) const {
const Texture::BufferSlice3D &bs = tex->buffer_slices_3d[i];
ERR_FAIL_COND_V(bs.offset >= (uint32_t)all_data.size(), Vector<Ref<Image>>());
ERR_FAIL_COND_V(bs.offset + bs.buffer_size > (uint32_t)all_data.size(), Vector<Ref<Image>>());
- Vector<uint8_t> sub_region = all_data.subarray(bs.offset, bs.offset + bs.buffer_size - 1);
+ Vector<uint8_t> sub_region = all_data.slice(bs.offset, bs.offset + bs.buffer_size);
Ref<Image> img;
img.instantiate();
@@ -1227,6 +1227,100 @@ RendererStorageRD::CanvasTexture::~CanvasTexture() {
clear_sets();
}
+void RendererStorageRD::sampler_rd_configure_custom(float p_mipmap_bias) {
+ for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
+ for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
+ RD::SamplerState sampler_state;
+ switch (i) {
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.max_lod = 0;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.max_lod = 0;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+ sampler_state.lod_bias = p_mipmap_bias;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+ sampler_state.lod_bias = p_mipmap_bias;
+
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+ sampler_state.lod_bias = p_mipmap_bias;
+ sampler_state.use_anisotropy = true;
+ sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+ sampler_state.lod_bias = p_mipmap_bias;
+ sampler_state.use_anisotropy = true;
+ sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
+
+ } break;
+ default: {
+ }
+ }
+ switch (j) {
+ case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: {
+ sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+ sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+ sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: {
+ sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT;
+ sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT;
+ sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_REPEAT;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: {
+ sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ } break;
+ default: {
+ }
+ }
+
+ if (custom_rd_samplers[i][j].is_valid()) {
+ RD::get_singleton()->free(custom_rd_samplers[i][j]);
+ }
+
+ custom_rd_samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state);
+ }
+ }
+}
+
RID RendererStorageRD::canvas_texture_allocate() {
return canvas_texture_owner.allocate_rid();
}
@@ -1440,8 +1534,10 @@ void RendererStorageRD::shader_set_code(RID p_shader, const String &p_code) {
}
if (shader->data) {
- for (const KeyValue<StringName, RID> &E : shader->default_texture_parameter) {
- shader->data->set_default_texture_param(E.key, E.value);
+ for (const KeyValue<StringName, Map<int, RID>> &E : shader->default_texture_parameter) {
+ for (const KeyValue<int, RID> &E2 : E.value) {
+ shader->data->set_default_texture_param(E.key, E2.value, E2.key);
+ }
}
}
}
@@ -1471,17 +1567,26 @@ void RendererStorageRD::shader_get_param_list(RID p_shader, List<PropertyInfo> *
}
}
-void RendererStorageRD::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) {
+void RendererStorageRD::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) {
Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND(!shader);
if (p_texture.is_valid() && texture_owner.owns(p_texture)) {
- shader->default_texture_parameter[p_name] = p_texture;
+ if (!shader->default_texture_parameter.has(p_name)) {
+ shader->default_texture_parameter[p_name] = Map<int, RID>();
+ }
+ shader->default_texture_parameter[p_name][p_index] = p_texture;
} else {
- shader->default_texture_parameter.erase(p_name);
+ if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) {
+ shader->default_texture_parameter[p_name].erase(p_index);
+
+ if (shader->default_texture_parameter[p_name].is_empty()) {
+ shader->default_texture_parameter.erase(p_name);
+ }
+ }
}
if (shader->data) {
- shader->data->set_default_texture_param(p_name, p_texture);
+ shader->data->set_default_texture_param(p_name, p_texture, p_index);
}
for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
Material *material = E->get();
@@ -1489,11 +1594,11 @@ void RendererStorageRD::shader_set_default_texture_param(RID p_shader, const Str
}
}
-RID RendererStorageRD::shader_get_default_texture_param(RID p_shader, const StringName &p_name) const {
+RID RendererStorageRD::shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const {
Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND_V(!shader, RID());
- if (shader->default_texture_parameter.has(p_name)) {
- return shader->default_texture_parameter[p_name];
+ if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) {
+ return shader->default_texture_parameter[p_name][p_index];
}
return RID();
@@ -2547,7 +2652,17 @@ void RendererStorageRD::MaterialData::update_uniform_buffer(const Map<StringName
//regular uniform
uint32_t offset = p_uniform_offsets[E.value.order];
#ifdef DEBUG_ENABLED
- uint32_t size = ShaderLanguage::get_type_size(E.value.type);
+ uint32_t size = 0U;
+ // The following code enforces a 16-byte alignment of uniform arrays.
+ if (E.value.array_size > 0) {
+ size = ShaderLanguage::get_datatype_size(E.value.type) * E.value.array_size;
+ int m = (16 * E.value.array_size);
+ if ((size % m) != 0U) {
+ size += m - (size % m);
+ }
+ } else {
+ size = ShaderLanguage::get_datatype_size(E.value.type);
+ }
ERR_CONTINUE(offset + size > p_buffer_size);
#endif
uint8_t *data = &p_buffer[offset];
@@ -2610,7 +2725,7 @@ RendererStorageRD::MaterialData::~MaterialData() {
}
}
-void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, RID> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) {
+void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) {
RendererStorageRD *singleton = (RendererStorageRD *)RendererStorage::base_singleton;
#ifdef TOOLS_ENABLED
Texture *roughness_detect_texture = nullptr;
@@ -2673,19 +2788,19 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari
if (uniform_array_size > 0) {
if (textures.size() < uniform_array_size) {
- const Map<StringName, RID>::Element *W = p_default_textures.find(uniform_name);
+ const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name);
for (int j = textures.size(); j < uniform_array_size; j++) {
- if (W) {
- textures.push_back(W->get());
+ if (W && W->get().has(j)) {
+ textures.push_back(W->get()[j]);
} else {
textures.push_back(RID());
}
}
}
} else if (textures.is_empty()) {
- const Map<StringName, RID>::Element *W = p_default_textures.find(uniform_name);
- if (W) {
- textures.push_back(W->get());
+ const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name);
+ if (W && W->get().has(0)) {
+ textures.push_back(W->get()[0]);
}
}
}
@@ -2703,11 +2818,14 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari
case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: {
rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK);
} break;
- case ShaderLanguage::ShaderNode::Uniform::HINT_NONE: {
+ case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: {
+ rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_ANISO);
+ } break;
+ case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: {
rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL);
} break;
- case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: {
- rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_ANISO);
+ case ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL: {
+ rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL);
} break;
default: {
rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
@@ -2746,7 +2864,7 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari
}
}
#ifdef TOOLS_ENABLED
- if (roughness_detect_texture && normal_detect_texture && normal_detect_texture->path != String()) {
+ if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) {
roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
}
#endif
@@ -2786,7 +2904,7 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari
rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
}
#ifdef TOOLS_ENABLED
- if (roughness_detect_texture && normal_detect_texture && normal_detect_texture->path != String()) {
+ if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) {
roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
}
#endif
@@ -2833,7 +2951,7 @@ void RendererStorageRD::MaterialData::free_parameters_uniform_set(RID p_uniform_
}
}
-bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, RID> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) {
+bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) {
if ((uint32_t)ubo_data.size() != p_ubo_size) {
p_uniform_dirty = true;
if (uniform_buffer.is_valid()) {
@@ -2857,7 +2975,7 @@ bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<St
//check whether buffer changed
if (p_uniform_dirty && ubo_data.size()) {
- update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), false);
+ update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), true);
RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), p_barrier);
}
@@ -4419,7 +4537,8 @@ void RendererStorageRD::_update_dirty_multimeshes() {
if (multimesh->data_cache_dirty_regions[i]) {
uint32_t offset = i * region_size;
uint32_t size = multimesh->stride_cache * (uint32_t)multimesh->instances * (uint32_t)sizeof(float);
- RD::get_singleton()->buffer_update(multimesh->buffer, offset, MIN(region_size, size - offset), &data[i * region_size]);
+ uint32_t region_start_index = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * i;
+ RD::get_singleton()->buffer_update(multimesh->buffer, offset, MIN(region_size, size - offset), &data[region_start_index]);
}
}
}
@@ -5704,7 +5823,7 @@ void RendererStorageRD::ParticlesShaderData::set_code(const String &p_code) {
uniforms.clear();
uses_collision = false;
- if (code == String()) {
+ if (code.is_empty()) {
return; //just invalid, but no error
}
@@ -5747,11 +5866,20 @@ void RendererStorageRD::ParticlesShaderData::set_code(const String &p_code) {
valid = true;
}
-void RendererStorageRD::ParticlesShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
+void RendererStorageRD::ParticlesShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
- default_texture_params.erase(p_name);
+ if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+ default_texture_params[p_name].erase(p_index);
+
+ if (default_texture_params[p_name].is_empty()) {
+ default_texture_params.erase(p_name);
+ }
+ }
} else {
- default_texture_params[p_name] = p_texture;
+ if (!default_texture_params.has(p_name)) {
+ default_texture_params[p_name] = Map<int, RID>();
+ }
+ default_texture_params[p_name][p_index] = p_texture;
}
}
@@ -9109,7 +9237,7 @@ void RendererStorageRD::_update_global_variables() {
for (uint32_t i = 0; i < total_regions; i++) {
if (global_variables.buffer_dirty_regions[i]) {
- RD::get_singleton()->buffer_update(global_variables.buffer, i * region_byte_size, region_byte_size, global_variables.buffer_values);
+ RD::get_singleton()->buffer_update(global_variables.buffer, i * region_byte_size, region_byte_size, &global_variables.buffer_values[i * GlobalVariables::BUFFER_DIRTY_REGION_SIZE]);
global_variables.buffer_dirty_regions[i] = false;
}
@@ -9140,7 +9268,6 @@ void RendererStorageRD::_update_global_variables() {
ERR_CONTINUE(!material); //wtf
_material_queue_update(material, false, true);
- print_line("update material texture?");
}
global_variables.must_update_texture_materials = false;
@@ -9753,6 +9880,9 @@ RendererStorageRD::RendererStorageRD() {
}
}
+ //custom sampler
+ sampler_rd_configure_custom(0.0f);
+
//default rd buffers
{
Vector<uint8_t> buffer;
@@ -9905,7 +10035,7 @@ RendererStorageRD::RendererStorageRD() {
actions.renames["RESTART"] = "restart";
actions.renames["CUSTOM"] = "PARTICLE.custom";
actions.renames["TRANSFORM"] = "PARTICLE.xform";
- actions.renames["TIME"] = "FRAME.time";
+ actions.renames["TIME"] = "frame_history.data[0].time";
actions.renames["PI"] = _MKSTR(Math_PI);
actions.renames["TAU"] = _MKSTR(Math_TAU);
actions.renames["E"] = _MKSTR(Math_E);
@@ -10083,6 +10213,15 @@ RendererStorageRD::~RendererStorageRD() {
}
}
+ //custom samplers
+ for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
+ for (int j = 0; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
+ if (custom_rd_samplers[i][j].is_valid()) {
+ RD::get_singleton()->free(custom_rd_samplers[i][j]);
+ }
+ }
+ }
+
//def buffers
for (int i = 0; i < DEFAULT_RD_BUFFER_MAX; i++) {
RD::get_singleton()->free(mesh_default_rd_buffers[i]);
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h
index f13bd4a7f4..8f044dbe75 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.h
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -135,7 +135,7 @@ public:
struct ShaderData {
virtual void set_code(const String &p_Code) = 0;
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture) = 0;
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0;
virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0;
virtual void get_instance_param_list(List<InstanceShaderParam> *p_param_list) const = 0;
@@ -152,7 +152,7 @@ public:
struct MaterialData {
void update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color);
- void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, RID> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color);
+ void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color);
virtual void set_render_priority(int p_priority) = 0;
virtual void set_next_pass(RID p_pass) = 0;
@@ -160,7 +160,7 @@ public:
virtual ~MaterialData();
//to be used internally by update_parameters, in the most common configuration of material parameters
- bool update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, RID> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
+ bool update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
void free_parameters_uniform_set(RID p_uniform_set);
private:
@@ -320,6 +320,7 @@ private:
RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX];
RID default_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
+ RID custom_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
RID default_rd_storage_buffer;
/* DECAL ATLAS */
@@ -374,7 +375,7 @@ private:
ShaderData *data;
String code;
ShaderType type;
- Map<StringName, RID> default_texture_parameter;
+ Map<StringName, Map<int, RID>> default_texture_parameter;
Set<Material *> owners;
};
@@ -883,14 +884,14 @@ private:
String path;
String code;
- Map<StringName, RID> default_texture_params;
+ Map<StringName, Map<int, RID>> default_texture_params;
RID pipeline;
bool uses_time;
virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
@@ -1391,6 +1392,13 @@ public:
_FORCE_INLINE_ RID sampler_rd_get_default(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
return default_rd_samplers[p_filter][p_repeat];
}
+ _FORCE_INLINE_ RID sampler_rd_get_custom(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
+ return custom_rd_samplers[p_filter][p_repeat];
+ }
+
+ void sampler_rd_configure_custom(float mipmap_bias);
+
+ void sampler_rd_set_default(float p_mipmap_bias);
/* CANVAS TEXTURE API */
@@ -1414,8 +1422,8 @@ public:
String shader_get_code(RID p_shader) const;
void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const;
- void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture);
- RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const;
+ void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index);
+ RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const;
Variant shader_get_param_default(RID p_shader, const StringName &p_param) const;
void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function);
diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.cpp b/servers/rendering/renderer_rd/shader_compiler_rd.cpp
index 215959bb6a..38ac00176f 100644
--- a/servers/rendering/renderer_rd/shader_compiler_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_compiler_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -54,81 +54,6 @@ static String _typestr(SL::DataType p_type) {
return type;
}
-static int _get_datatype_size(SL::DataType p_type) {
- switch (p_type) {
- case SL::TYPE_VOID:
- return 0;
- case SL::TYPE_BOOL:
- return 4;
- case SL::TYPE_BVEC2:
- return 8;
- case SL::TYPE_BVEC3:
- return 12;
- case SL::TYPE_BVEC4:
- return 16;
- case SL::TYPE_INT:
- return 4;
- case SL::TYPE_IVEC2:
- return 8;
- case SL::TYPE_IVEC3:
- return 12;
- case SL::TYPE_IVEC4:
- return 16;
- case SL::TYPE_UINT:
- return 4;
- case SL::TYPE_UVEC2:
- return 8;
- case SL::TYPE_UVEC3:
- return 12;
- case SL::TYPE_UVEC4:
- return 16;
- case SL::TYPE_FLOAT:
- return 4;
- case SL::TYPE_VEC2:
- return 8;
- case SL::TYPE_VEC3:
- return 12;
- case SL::TYPE_VEC4:
- return 16;
- case SL::TYPE_MAT2:
- return 32; // 4 * 4 + 4 * 4
- case SL::TYPE_MAT3:
- return 48; // 4 * 4 + 4 * 4 + 4 * 4
- case SL::TYPE_MAT4:
- return 64;
- case SL::TYPE_SAMPLER2D:
- return 16;
- case SL::TYPE_ISAMPLER2D:
- return 16;
- case SL::TYPE_USAMPLER2D:
- return 16;
- case SL::TYPE_SAMPLER2DARRAY:
- return 16;
- case SL::TYPE_ISAMPLER2DARRAY:
- return 16;
- case SL::TYPE_USAMPLER2DARRAY:
- return 16;
- case SL::TYPE_SAMPLER3D:
- return 16;
- case SL::TYPE_ISAMPLER3D:
- return 16;
- case SL::TYPE_USAMPLER3D:
- return 16;
- case SL::TYPE_SAMPLERCUBE:
- return 16;
- case SL::TYPE_SAMPLERCUBEARRAY:
- return 16;
- case SL::TYPE_STRUCT:
- return 0;
-
- case SL::TYPE_MAX: {
- ERR_FAIL_V(0);
- };
- }
-
- ERR_FAIL_V(0);
-}
-
static int _get_datatype_alignment(SL::DataType p_type) {
switch (p_type) {
case SL::TYPE_VOID:
@@ -227,6 +152,13 @@ static String _prestr(SL::DataPrecision p_pres, bool p_force_highp = false) {
return "";
}
+static String _constr(bool p_is_const) {
+ if (p_is_const) {
+ return "const ";
+ }
+ return "";
+}
+
static String _qualstr(SL::ArgumentQualifier p_qual) {
switch (p_qual) {
case SL::ARGUMENT_QUALIFIER_IN:
@@ -417,9 +349,7 @@ void ShaderCompilerRD::_dump_function_deps(const SL::ShaderNode *p_node, const S
if (i > 0) {
header += ", ";
}
- if (fnode->arguments[i].is_const) {
- header += "const ";
- }
+ header += _constr(fnode->arguments[i].is_const);
if (fnode->arguments[i].type == SL::TYPE_STRUCT) {
header += _qualstr(fnode->arguments[i].qualifier) + _mkid(fnode->arguments[i].type_str) + " " + _mkid(fnode->arguments[i].name);
} else {
@@ -653,20 +583,22 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
uniform_defines.write[uniform.order] = ucode;
if (is_buffer_global) {
//globals are indices into the global table
- uniform_sizes.write[uniform.order] = _get_datatype_size(ShaderLanguage::TYPE_UINT);
+ uniform_sizes.write[uniform.order] = ShaderLanguage::get_datatype_size(ShaderLanguage::TYPE_UINT);
uniform_alignments.write[uniform.order] = _get_datatype_alignment(ShaderLanguage::TYPE_UINT);
} else {
+ // The following code enforces a 16-byte alignment of uniform arrays.
if (uniform.array_size > 0) {
- int size = _get_datatype_size(uniform.type) * uniform.array_size;
+ int size = ShaderLanguage::get_datatype_size(uniform.type) * uniform.array_size;
int m = (16 * uniform.array_size);
if ((size % m) != 0) {
size += m - (size % m);
}
uniform_sizes.write[uniform.order] = size;
+ uniform_alignments.write[uniform.order] = 16;
} else {
- uniform_sizes.write[uniform.order] = _get_datatype_size(uniform.type);
+ uniform_sizes.write[uniform.order] = ShaderLanguage::get_datatype_size(uniform.type);
+ uniform_alignments.write[uniform.order] = _get_datatype_alignment(uniform.type);
}
- uniform_alignments.write[uniform.order] = _get_datatype_alignment(uniform.type);
}
}
@@ -791,7 +723,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
for (int i = 0; i < pnode->vconstants.size(); i++) {
const SL::ShaderNode::Constant &cnode = pnode->vconstants[i];
String gcode;
- gcode += "const ";
+ gcode += _constr(true);
gcode += _prestr(cnode.precision, ShaderLanguage::is_float_type(cnode.type));
if (cnode.type == SL::TYPE_STRUCT) {
gcode += _mkid(cnode.type_str);
@@ -875,9 +807,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
SL::VariableDeclarationNode *vdnode = (SL::VariableDeclarationNode *)p_node;
String declaration;
- if (vdnode->is_const) {
- declaration += "const ";
- }
+ declaration += _constr(vdnode->is_const);
if (vdnode->datatype == SL::TYPE_STRUCT) {
declaration += _mkid(vdnode->struct_name);
} else {
@@ -997,9 +927,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
case SL::Node::TYPE_ARRAY_DECLARATION: {
SL::ArrayDeclarationNode *adnode = (SL::ArrayDeclarationNode *)p_node;
String declaration;
- if (adnode->is_const) {
- declaration += "const ";
- }
+ declaration += _constr(adnode->is_const);
if (adnode->datatype == SL::TYPE_STRUCT) {
declaration += _mkid(adnode->struct_name);
} else {
@@ -1315,6 +1243,9 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
code += ")";
} break;
+ case SL::OP_EMPTY: {
+ // Semicolon (or empty statement) - ignored.
+ } break;
default: {
if (p_use_scope) {
@@ -1407,7 +1338,13 @@ ShaderLanguage::DataType ShaderCompilerRD::_get_variable_type(const StringName &
}
Error ShaderCompilerRD::compile(RS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code) {
- Error err = parser.compile(p_code, ShaderTypes::get_singleton()->get_functions(p_mode), ShaderTypes::get_singleton()->get_modes(p_mode), ShaderLanguage::VaryingFunctionNames(), ShaderTypes::get_singleton()->get_types(), _get_variable_type);
+ SL::ShaderCompileInfo info;
+ info.functions = ShaderTypes::get_singleton()->get_functions(p_mode);
+ info.render_modes = ShaderTypes::get_singleton()->get_modes(p_mode);
+ info.shader_types = ShaderTypes::get_singleton()->get_types();
+ info.global_variable_type_func = _get_variable_type;
+
+ Error err = parser.compile(p_code, info);
if (err != OK) {
Vector<String> shader = p_code.split("\n");
diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.h b/servers/rendering/renderer_rd/shader_compiler_rd.h
index 2ab689c27c..5670d881f6 100644
--- a/servers/rendering/renderer_rd/shader_compiler_rd.h
+++ b/servers/rendering/renderer_rd/shader_compiler_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp
index b9a8947fa2..73766d14d8 100644
--- a/servers/rendering/renderer_rd/shader_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -79,7 +79,7 @@ void ShaderRD::_add_stage(const char *p_code, StageType p_stage_type) {
}
if (push_chunk) {
- if (text != String()) {
+ if (!text.is_empty()) {
StageTemplate::Chunk text_chunk;
text_chunk.type = StageTemplate::Chunk::TYPE_TEXT;
text_chunk.text = text.utf8();
@@ -90,7 +90,7 @@ void ShaderRD::_add_stage(const char *p_code, StageType p_stage_type) {
}
}
- if (text != String()) {
+ if (!text.is_empty()) {
StageTemplate::Chunk text_chunk;
text_chunk.type = StageTemplate::Chunk::TYPE_TEXT;
text_chunk.text = text.utf8();
@@ -177,6 +177,9 @@ void ShaderRD::_build_variant_code(StringBuilder &builder, uint32_t p_variant, c
for (const KeyValue<StringName, CharString> &E : p_version->code_sections) {
builder.append(String("#define ") + String(E.key) + "_CODE_USED\n");
}
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ builder.append("#define MOLTENVK_USED\n");
+#endif
} break;
case StageTemplate::Chunk::TYPE_MATERIAL_UNIFORMS: {
builder.append(p_version->uniforms.get_data()); //uniforms (same for vertex and fragment)
@@ -635,7 +638,7 @@ void ShaderRD::initialize(const Vector<String> &p_variant_defines, const String
variants_enabled.push_back(true);
}
- if (shader_cache_dir != String()) {
+ if (!shader_cache_dir.is_empty()) {
StringBuilder hash_build;
hash_build.append("[base_hash]");
diff --git a/servers/rendering/renderer_rd/shader_rd.h b/servers/rendering/renderer_rd/shader_rd.h
index 984b168659..06f78ab193 100644
--- a/servers/rendering/renderer_rd/shader_rd.h
+++ b/servers/rendering/renderer_rd/shader_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_rd/shaders/fsr_upscale.glsl b/servers/rendering/renderer_rd/shaders/fsr_upscale.glsl
new file mode 100644
index 0000000000..54a7790f77
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/fsr_upscale.glsl
@@ -0,0 +1,173 @@
+/*************************************************************************/
+/* fsr_upscale.glsl */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#[compute]
+
+#version 450
+
+#VERSION_DEFINES
+
+#define A_GPU
+#define A_GLSL
+
+#ifdef MODE_FSR_UPSCALE_NORMAL
+
+#define A_HALF
+
+#endif
+
+#include "thirdparty/amd-fsr/ffx_a.h"
+
+layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
+
+layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly image2D fsr_image;
+layout(set = 0, binding = 0) uniform sampler2D source_image;
+
+#define FSR_UPSCALE_PASS_TYPE_EASU 0
+#define FSR_UPSCALE_PASS_TYPE_RCAS 1
+
+layout(push_constant, binding = 1, std430) uniform Params {
+ float resolution_width;
+ float resolution_height;
+ float upscaled_width;
+ float upscaled_height;
+ float sharpness;
+ int pass;
+}
+params;
+
+AU4 Const0, Const1, Const2, Const3;
+
+#ifdef MODE_FSR_UPSCALE_FALLBACK
+
+#define FSR_EASU_F
+AF4 FsrEasuRF(AF2 p) {
+ AF4 res = textureGather(source_image, p, 0);
+ return res;
+}
+AF4 FsrEasuGF(AF2 p) {
+ AF4 res = textureGather(source_image, p, 1);
+ return res;
+}
+AF4 FsrEasuBF(AF2 p) {
+ AF4 res = textureGather(source_image, p, 2);
+ return res;
+}
+
+#define FSR_RCAS_F
+AF4 FsrRcasLoadF(ASU2 p) {
+ return AF4(texelFetch(source_image, ASU2(p), 0));
+}
+void FsrRcasInputF(inout AF1 r, inout AF1 g, inout AF1 b) {}
+
+#else
+
+#define FSR_EASU_H
+AH4 FsrEasuRH(AF2 p) {
+ AH4 res = AH4(textureGather(source_image, p, 0));
+ return res;
+}
+AH4 FsrEasuGH(AF2 p) {
+ AH4 res = AH4(textureGather(source_image, p, 1));
+ return res;
+}
+AH4 FsrEasuBH(AF2 p) {
+ AH4 res = AH4(textureGather(source_image, p, 2));
+ return res;
+}
+
+#define FSR_RCAS_H
+AH4 FsrRcasLoadH(ASW2 p) {
+ return AH4(texelFetch(source_image, ASU2(p), 0));
+}
+void FsrRcasInputH(inout AH1 r, inout AH1 g, inout AH1 b) {}
+
+#endif
+
+#include "thirdparty/amd-fsr/ffx_fsr1.h"
+
+void fsr_easu_pass(AU2 pos) {
+#ifdef MODE_FSR_UPSCALE_NORMAL
+
+ AH3 Gamma2Color = AH3(0, 0, 0);
+ FsrEasuH(Gamma2Color, pos, Const0, Const1, Const2, Const3);
+ imageStore(fsr_image, ASU2(pos), AH4(Gamma2Color, 1));
+
+#else
+
+ AF3 Gamma2Color = AF3(0, 0, 0);
+ FsrEasuF(Gamma2Color, pos, Const0, Const1, Const2, Const3);
+ imageStore(fsr_image, ASU2(pos), AF4(Gamma2Color, 1));
+
+#endif
+}
+
+void fsr_rcas_pass(AU2 pos) {
+#ifdef MODE_FSR_UPSCALE_NORMAL
+
+ AH3 Gamma2Color = AH3(0, 0, 0);
+ FsrRcasH(Gamma2Color.r, Gamma2Color.g, Gamma2Color.b, pos, Const0);
+ imageStore(fsr_image, ASU2(pos), AH4(Gamma2Color, 1));
+
+#else
+
+ AF3 Gamma2Color = AF3(0, 0, 0);
+ FsrRcasF(Gamma2Color.r, Gamma2Color.g, Gamma2Color.b, pos, Const0);
+ imageStore(fsr_image, ASU2(pos), AF4(Gamma2Color, 1));
+
+#endif
+}
+
+void fsr_pass(AU2 pos) {
+ if (params.pass == FSR_UPSCALE_PASS_TYPE_EASU) {
+ fsr_easu_pass(pos);
+ } else if (params.pass == FSR_UPSCALE_PASS_TYPE_RCAS) {
+ fsr_rcas_pass(pos);
+ }
+}
+
+void main() {
+ // Clang does not like unused functions. If ffx_a.h is included in the binary, clang will throw a fit and not compile so we must configure FSR in this shader
+ if (params.pass == FSR_UPSCALE_PASS_TYPE_EASU) {
+ FsrEasuCon(Const0, Const1, Const2, Const3, params.resolution_width, params.resolution_height, params.resolution_width, params.resolution_height, params.upscaled_width, params.upscaled_height);
+ } else if (params.pass == FSR_UPSCALE_PASS_TYPE_RCAS) {
+ FsrRcasCon(Const0, params.sharpness);
+ }
+
+ AU2 gxy = ARmp8x8(gl_LocalInvocationID.x) + AU2(gl_WorkGroupID.x << 4u, gl_WorkGroupID.y << 4u);
+
+ fsr_pass(gxy);
+ gxy.x += 8u;
+ fsr_pass(gxy);
+ gxy.y += 8u;
+ fsr_pass(gxy);
+ gxy.x -= 8u;
+ fsr_pass(gxy);
+}
diff --git a/servers/rendering/renderer_rd/shaders/gi.glsl b/servers/rendering/renderer_rd/shaders/gi.glsl
index 5528ea3659..9854f124d7 100644
--- a/servers/rendering/renderer_rd/shaders/gi.glsl
+++ b/servers/rendering/renderer_rd/shaders/gi.glsl
@@ -68,19 +68,15 @@ sdfgi;
#define MAX_VOXEL_GI_INSTANCES 8
struct VoxelGIData {
- mat4 xform;
- vec3 bounds;
- float dynamic_range;
+ mat4 xform; // 64 - 64
- float bias;
- float normal_bias;
- bool blend_ambient;
- uint texture_slot;
+ vec3 bounds; // 12 - 76
+ float dynamic_range; // 4 - 80
- uint pad0;
- uint pad1;
- uint pad2;
- uint mipmaps;
+ float bias; // 4 - 84
+ float normal_bias; // 4 - 88
+ bool blend_ambient; // 4 - 92
+ uint mipmaps; // 4 - 96
};
layout(set = 0, binding = 16, std140) uniform VoxelGIs {
diff --git a/servers/rendering/renderer_rd/shaders/giprobe_write.glsl b/servers/rendering/renderer_rd/shaders/giprobe_write.glsl
index 25d87ca45d..a6d65bffeb 100644
--- a/servers/rendering/renderer_rd/shaders/giprobe_write.glsl
+++ b/servers/rendering/renderer_rd/shaders/giprobe_write.glsl
@@ -7,7 +7,6 @@
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
#define NO_CHILDREN 0xFFFFFFFF
-#define GREY_VEC vec3(0.33333, 0.33333, 0.33333)
struct CellChildren {
uint children[8];
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
index a83f87d23a..e4628b2d5a 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
@@ -6,6 +6,8 @@
#include "scene_forward_clustered_inc.glsl"
+#define SHADER_IS_SRGB false
+
/* INPUT ATTRIBS */
layout(location = 0) in vec3 vertex_attrib;
@@ -108,13 +110,14 @@ void main() {
#endif
uint instance_index = draw_call.instance_index;
- instance_index_interp = instance_index;
bool is_multimesh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH);
if (!is_multimesh) {
instance_index += gl_InstanceIndex;
}
+ instance_index_interp = instance_index;
+
mat4 world_matrix = instances.data[instance_index].transform;
mat3 world_normal_matrix;
@@ -357,6 +360,8 @@ void main() {
#VERSION_DEFINES
+#define SHADER_IS_SRGB false
+
/* Specialization Constants (Toggles) */
layout(constant_id = 0) const bool sc_use_forward_gi = false;
@@ -565,12 +570,8 @@ void main() {
discard;
#endif
-#ifdef USE_SUBGROUPS
- //ensures instance_index is in sgpr
- uint instance_index = subgroupBroadcastFirst(instance_index_interp);
-#else
uint instance_index = instance_index_interp;
-#endif
+
//lay out everything, whathever is unused is optimized away anyway
vec3 vertex = vertex_interp;
vec3 view = -normalize(vertex_interp);
@@ -694,7 +695,7 @@ void main() {
#endif // ALPHA_ANTIALIASING_EDGE_USED
#ifdef USE_OPAQUE_PREPASS
- if (alpha < opaque_prepass_threshold) {
+ if (alpha < scene_data.opaque_prepass_threshold) {
discard;
}
#endif // USE_OPAQUE_PREPASS
@@ -1532,7 +1533,7 @@ void main() {
float size_A = sc_use_light_soft_shadows ? directional_lights.data[i].size : 0.0;
- light_compute(normal, directional_lights.data[i].direction, normalize(view), size_A, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0,
+ light_compute(normal, directional_lights.data[i].direction, normalize(view), size_A, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -1543,7 +1544,7 @@ void main() {
transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
- rim, rim_tint, albedo,
+ rim, rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@@ -1551,9 +1552,6 @@ void main() {
#ifdef LIGHT_ANISOTROPY_USED
binormal, tangent, anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- alpha,
-#endif
diffuse_light,
specular_light);
}
@@ -1606,7 +1604,7 @@ void main() {
shadow = blur_shadow(shadow);
- light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow,
+ light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -1618,7 +1616,6 @@ void main() {
#ifdef LIGHT_RIM_USED
rim,
rim_tint,
- albedo,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@@ -1626,9 +1623,6 @@ void main() {
#ifdef LIGHT_ANISOTROPY_USED
tangent, binormal, anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- alpha,
-#endif
diffuse_light, specular_light);
}
}
@@ -1682,7 +1676,7 @@ void main() {
shadow = blur_shadow(shadow);
- light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow,
+ light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -1694,7 +1688,6 @@ void main() {
#ifdef LIGHT_RIM_USED
rim,
rim_tint,
- albedo,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@@ -1702,9 +1695,6 @@ void main() {
#ifdef LIGHT_ANISOTROPY_USED
tangent, binormal, anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- alpha,
-#endif
diffuse_light, specular_light);
}
}
@@ -1721,7 +1711,7 @@ void main() {
#ifdef USE_OPAQUE_PREPASS
- if (alpha < opaque_prepass_threshold) {
+ if (alpha < scene_data.opaque_prepass_threshold) {
discard;
}
@@ -1767,7 +1757,11 @@ void main() {
}
}
+#ifdef MOLTENVK_USED
+ imageStore(geom_facing_grid, grid_pos, uvec4(imageLoad(geom_facing_grid, grid_pos).r | facing_bits)); //store facing bits
+#else
imageAtomicOr(geom_facing_grid, grid_pos, facing_bits); //store facing bits
+#endif
if (length(emission) > 0.001) {
float lumas[6];
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
index c8489f2137..9fe4b55f67 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
@@ -208,7 +208,8 @@ layout(set = 1, binding = 0, std140) uniform SceneData {
float roughness_limiter_amount;
float roughness_limiter_limit;
- uvec2 roughness_limiter_pad;
+ float opaque_prepass_threshold;
+ uint roughness_limiter_pad;
mat4 sdf_to_bounds;
@@ -304,19 +305,15 @@ layout(set = 1, binding = 15) uniform texture2DArray sdfgi_lightprobe_texture;
layout(set = 1, binding = 16) uniform texture3D sdfgi_occlusion_cascades;
struct VoxelGIData {
- mat4 xform;
- vec3 bounds;
- float dynamic_range;
+ mat4 xform; // 64 - 64
- float bias;
- float normal_bias;
- bool blend_ambient;
- uint texture_slot;
+ vec3 bounds; // 12 - 76
+ float dynamic_range; // 4 - 80
- float anisotropy_strength;
- float ambient_occlusion;
- float ambient_occlusion_size;
- uint mipmaps;
+ float bias; // 4 - 84
+ float normal_bias; // 4 - 88
+ bool blend_ambient; // 4 - 92
+ uint mipmaps; // 4 - 96
};
layout(set = 1, binding = 17, std140) uniform VoxelGIs {
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
index b26489ddf1..d22f936a35 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
@@ -73,7 +73,7 @@ vec3 F0(float metallic, float specular, vec3 albedo) {
return mix(vec3(dielectric), albedo, vec3(metallic));
}
-void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float attenuation, vec3 f0, uint orms, float specular_amount,
+void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float attenuation, vec3 f0, uint orms, float specular_amount, vec3 albedo, inout float alpha,
#ifdef LIGHT_BACKLIGHT_USED
vec3 backlight,
#endif
@@ -84,7 +84,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
float transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
- float rim, float rim_tint, vec3 rim_color,
+ float rim, float rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
float clearcoat, float clearcoat_gloss,
@@ -92,9 +92,6 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
#ifdef LIGHT_ANISOTROPY_USED
vec3 B, vec3 T, float anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- inout float alpha,
-#endif
inout vec3 diffuse_light, inout vec3 specular_light) {
vec4 orms_unpacked = unpackUnorm4x8(orms);
@@ -171,7 +168,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
#if defined(LIGHT_RIM_USED)
float rim_light = pow(max(0.0, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0));
- diffuse_light += rim_light * rim * mix(vec3(1.0), rim_color, rim_tint) * light_color;
+ diffuse_light += rim_light * rim * mix(vec3(1.0), albedo, rim_tint) * light_color;
#endif
#ifdef LIGHT_TRANSMITTANCE_USED
@@ -577,7 +574,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
return 1.0;
}
-void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow,
+void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow, vec3 albedo, inout float alpha,
#ifdef LIGHT_BACKLIGHT_USED
vec3 backlight,
#endif
@@ -587,7 +584,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
float transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED
- float rim, float rim_tint, vec3 rim_color,
+ float rim, float rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
float clearcoat, float clearcoat_gloss,
@@ -595,9 +592,6 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
#ifdef LIGHT_ANISOTROPY_USED
vec3 binormal, vec3 tangent, float anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- inout float alpha,
-#endif
inout vec3 diffuse_light, inout vec3 specular_light) {
vec3 light_rel_vec = omni_lights.data[idx].position - vertex;
float light_length = length(light_rel_vec);
@@ -703,7 +697,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
light_attenuation *= shadow;
- light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, omni_lights.data[idx].specular_amount,
+ light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, omni_lights.data[idx].specular_amount, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -714,7 +708,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
- rim * omni_attenuation, rim_tint, rim_color,
+ rim * omni_attenuation, rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@@ -722,9 +716,6 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
#ifdef LIGHT_ANISOTROPY_USED
binormal, tangent, anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- alpha,
-#endif
diffuse_light,
specular_light);
}
@@ -823,7 +814,7 @@ vec2 normal_to_panorama(vec3 n) {
return panorama_coords;
}
-void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow,
+void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow, vec3 albedo, inout float alpha,
#ifdef LIGHT_BACKLIGHT_USED
vec3 backlight,
#endif
@@ -833,7 +824,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
float transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED
- float rim, float rim_tint, vec3 rim_color,
+ float rim, float rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
float clearcoat, float clearcoat_gloss,
@@ -841,9 +832,6 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
#ifdef LIGHT_ANISOTROPY_USED
vec3 binormal, vec3 tangent, float anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- inout float alpha,
-#endif
inout vec3 diffuse_light,
inout vec3 specular_light) {
vec3 light_rel_vec = spot_lights.data[idx].position - vertex;
@@ -910,7 +898,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
}
light_attenuation *= shadow;
- light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, spot_lights.data[idx].specular_amount,
+ light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, spot_lights.data[idx].specular_amount, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -921,7 +909,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
- rim * spot_attenuation, rim_tint, rim_color,
+ rim * spot_attenuation, rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@@ -929,9 +917,6 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
#ifdef LIGHT_ANISOTROPY_USED
binormal, tangent, anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- alpha,
-#endif
diffuse_light, specular_light);
}
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
index 2f5cc58619..e92fbecfd0 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
@@ -7,6 +7,8 @@
/* Include our forward mobile UBOs definitions etc. */
#include "scene_forward_mobile_inc.glsl"
+#define SHADER_IS_SRGB false
+
/* INPUT ATTRIBS */
layout(location = 0) in vec3 vertex_attrib;
@@ -370,6 +372,8 @@ void main() {
#VERSION_DEFINES
+#define SHADER_IS_SRGB false
+
/* Specialization Constants */
#if !defined(MODE_RENDER_DEPTH)
@@ -701,7 +705,7 @@ void main() {
#endif // ALPHA_ANTIALIASING_EDGE_USED
#ifdef USE_OPAQUE_PREPASS
- if (alpha < opaque_prepass_threshold) {
+ if (alpha < scene_data.opaque_prepass_threshold) {
discard;
}
#endif // USE_OPAQUE_PREPASS
@@ -1345,7 +1349,7 @@ void main() {
#endif
blur_shadow(shadow);
- light_compute(normal, directional_lights.data[i].direction, normalize(view), 0.0, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0,
+ light_compute(normal, directional_lights.data[i].direction, normalize(view), 0.0, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -1358,7 +1362,7 @@ void main() {
#endif
*/
#ifdef LIGHT_RIM_USED
- rim, rim_tint, albedo,
+ rim, rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@@ -1369,9 +1373,6 @@ void main() {
#ifdef USE_SOFT_SHADOW
directional_lights.data[i].size,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- alpha,
-#endif
diffuse_light,
specular_light);
}
@@ -1395,7 +1396,7 @@ void main() {
shadow = blur_shadow(shadow);
- light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow,
+ light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -1409,7 +1410,6 @@ void main() {
#ifdef LIGHT_RIM_USED
rim,
rim_tint,
- albedo,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@@ -1417,9 +1417,6 @@ void main() {
#ifdef LIGHT_ANISOTROPY_USED
tangent, binormal, anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- alpha,
-#endif
diffuse_light, specular_light);
}
} //omni lights
@@ -1443,7 +1440,7 @@ void main() {
shadow = blur_shadow(shadow);
- light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow,
+ light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -1457,7 +1454,6 @@ void main() {
#ifdef LIGHT_RIM_USED
rim,
rim_tint,
- albedo,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@@ -1465,9 +1461,6 @@ void main() {
#ifdef LIGHT_ANISOTROPY_USED
tangent, binormal, anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- alpha,
-#endif
diffuse_light, specular_light);
}
} //spot lights
@@ -1483,7 +1476,7 @@ void main() {
#ifdef USE_OPAQUE_PREPASS
- if (alpha < opaque_prepass_threshold) {
+ if (alpha < scene_data.opaque_prepass_threshold) {
discard;
}
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
index eb8fb49598..a9a4fce82a 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
@@ -168,7 +168,8 @@ layout(set = 1, binding = 0, std140) uniform SceneData {
mediump float roughness_limiter_amount;
mediump float roughness_limiter_limit;
- uvec2 roughness_limiter_pad;
+ mediump float opaque_prepass_threshold;
+ uint roughness_limiter_pad;
bool fog_enabled;
highp float fog_density;
diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
index afc5d68776..181d3b272f 100644
--- a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
+++ b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
@@ -47,7 +47,13 @@ layout(push_constant, binding = 0, std430) uniform Params {
}
params;
+#ifdef MOLTENVK_USED
+layout(set = 1, binding = 1) volatile buffer emissive_only_map_buffer {
+ uint emissive_only_map[];
+};
+#else
layout(r32ui, set = 1, binding = 1) uniform volatile uimage3D emissive_only_map;
+#endif
layout(set = 1, binding = 2, std140) uniform SceneParams {
vec2 fog_frustum_size_begin;
@@ -71,8 +77,17 @@ layout(set = 1, binding = 2, std140) uniform SceneParams {
}
scene_params;
+#ifdef MOLTENVK_USED
+layout(set = 1, binding = 3) volatile buffer density_only_map_buffer {
+ uint density_only_map[];
+};
+layout(set = 1, binding = 4) volatile buffer light_only_map_buffer {
+ uint light_only_map[];
+};
+#else
layout(r32ui, set = 1, binding = 3) uniform volatile uimage3D density_only_map;
layout(r32ui, set = 1, binding = 4) uniform volatile uimage3D light_only_map;
+#endif
#ifdef MATERIAL_UNIFORMS_USED
layout(set = 2, binding = 0, std140) uniform MaterialUniforms{
@@ -115,6 +130,9 @@ void main() {
if (any(greaterThanEqual(pos, scene_params.fog_volume_size))) {
return; //do not compute
}
+#ifdef MOLTENVK_USED
+ uint lpos = pos.z * scene_params.fog_volume_size.x * scene_params.fog_volume_size.y + pos.y * scene_params.fog_volume_size.x + pos.x;
+#endif
vec3 posf = vec3(pos);
@@ -197,7 +215,11 @@ void main() {
density *= cull_mask;
if (abs(density) > 0.001) {
int final_density = int(density * DENSITY_SCALE);
+#ifdef MOLTENVK_USED
+ atomicAdd(density_only_map[lpos], uint(final_density));
+#else
imageAtomicAdd(density_only_map, pos, uint(final_density));
+#endif
#ifdef EMISSION_USED
{
@@ -207,7 +229,11 @@ void main() {
uvec3 emission_u = uvec3(emission.r * 511.0, emission.g * 511.0, emission.b * 255.0);
// R and G have 11 bits each and B has 10. Then pack them into a 32 bit uint
uint final_emission = emission_u.r << 21 | emission_u.g << 10 | emission_u.b;
+#ifdef MOLTENVK_USED
+ uint prev_emission = atomicAdd(emissive_only_map[lpos], final_emission);
+#else
uint prev_emission = imageAtomicAdd(emissive_only_map, pos, final_emission);
+#endif
// Adding can lead to colors overflowing, so validate
uvec3 prev_emission_u = uvec3(prev_emission >> 21, (prev_emission << 11) >> 21, prev_emission % 1024);
@@ -219,7 +245,11 @@ void main() {
if (any(overflowing)) {
uvec3 overflow_factor = mix(uvec3(0), uvec3(2047 << 21, 2047 << 10, 1023), overflowing);
uint force_max = overflow_factor.r | overflow_factor.g | overflow_factor.b;
+#ifdef MOLTENVK_USED
+ atomicOr(emissive_only_map[lpos], force_max);
+#else
imageAtomicOr(emissive_only_map, pos, force_max);
+#endif
}
}
#endif
@@ -230,7 +260,11 @@ void main() {
uvec3 scattering_u = uvec3(scattering.r * 2047.0, scattering.g * 2047.0, scattering.b * 1023.0);
// R and G have 11 bits each and B has 10. Then pack them into a 32 bit uint
uint final_scattering = scattering_u.r << 21 | scattering_u.g << 10 | scattering_u.b;
+#ifdef MOLTENVK_USED
+ uint prev_scattering = atomicAdd(light_only_map[lpos], final_scattering);
+#else
uint prev_scattering = imageAtomicAdd(light_only_map, pos, final_scattering);
+#endif
// Adding can lead to colors overflowing, so validate
uvec3 prev_scattering_u = uvec3(prev_scattering >> 21, (prev_scattering << 11) >> 21, prev_scattering % 1024);
@@ -242,7 +276,11 @@ void main() {
if (any(overflowing)) {
uvec3 overflow_factor = mix(uvec3(0), uvec3(2047 << 21, 2047 << 10, 1023), overflowing);
uint force_max = overflow_factor.r | overflow_factor.g | overflow_factor.b;
+#ifdef MOLTENVK_USED
+ atomicOr(light_only_map[lpos], force_max);
+#else
imageAtomicOr(light_only_map, pos, force_max);
+#endif
}
}
#endif // ALBEDO_USED
diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl b/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl
index 3d6fbb5653..7c8d4f7f99 100644
--- a/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl
+++ b/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl
@@ -76,19 +76,15 @@ layout(set = 0, binding = 10) uniform sampler shadow_sampler;
#define MAX_VOXEL_GI_INSTANCES 8
struct VoxelGIData {
- mat4 xform;
- vec3 bounds;
- float dynamic_range;
+ mat4 xform; // 64 - 64
- float bias;
- float normal_bias;
- bool blend_ambient;
- uint texture_slot;
+ vec3 bounds; // 12 - 76
+ float dynamic_range; // 4 - 80
- float anisotropy_strength;
- float ambient_occlusion;
- float ambient_occlusion_size;
- uint mipmaps;
+ float bias; // 4 - 84
+ float normal_bias; // 4 - 88
+ bool blend_ambient; // 4 - 92
+ uint mipmaps; // 4 - 96
};
layout(set = 0, binding = 11, std140) uniform VoxelGIs {
@@ -190,9 +186,22 @@ params;
#ifndef MODE_COPY
layout(set = 0, binding = 15) uniform texture3D prev_density_texture;
+#ifdef MOLTENVK_USED
+layout(set = 0, binding = 16) buffer density_only_map_buffer {
+ uint density_only_map[];
+};
+layout(set = 0, binding = 17) buffer light_only_map_buffer {
+ uint light_only_map[];
+};
+layout(set = 0, binding = 18) buffer emissive_only_map_buffer {
+ uint emissive_only_map[];
+};
+#else
layout(r32ui, set = 0, binding = 16) uniform uimage3D density_only_map;
layout(r32ui, set = 0, binding = 17) uniform uimage3D light_only_map;
layout(r32ui, set = 0, binding = 18) uniform uimage3D emissive_only_map;
+#endif
+
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
layout(set = 0, binding = 19) uniform textureCubeArray sky_texture;
#else
@@ -272,6 +281,9 @@ void main() {
if (any(greaterThanEqual(pos, params.fog_volume_size))) {
return; //do not compute
}
+#ifdef MOLTENVK_USED
+ uint lpos = pos.z * params.fog_volume_size.x * params.fog_volume_size.y + pos.y * params.fog_volume_size.x + pos.x;
+#endif
vec3 posf = vec3(pos);
@@ -335,15 +347,28 @@ void main() {
vec3 total_light = vec3(0.0);
float total_density = params.base_density;
+#ifdef MOLTENVK_USED
+ uint local_density = density_only_map[lpos];
+#else
uint local_density = imageLoad(density_only_map, pos).x;
+#endif
+
total_density += float(int(local_density)) / DENSITY_SCALE;
total_density = max(0.0, total_density);
+#ifdef MOLTENVK_USED
+ uint scattering_u = light_only_map[lpos];
+#else
uint scattering_u = imageLoad(light_only_map, pos).x;
+#endif
vec3 scattering = vec3(scattering_u >> 21, (scattering_u << 11) >> 21, scattering_u % 1024) / vec3(2047.0, 2047.0, 1023.0);
scattering += params.base_scattering * params.base_density;
+#ifdef MOLTENVK_USED
+ uint emission_u = emissive_only_map[lpos];
+#else
uint emission_u = imageLoad(emissive_only_map, pos).x;
+#endif
vec3 emission = vec3(emission_u >> 21, (emission_u << 11) >> 21, emission_u % 1024) / vec3(511.0, 511.0, 255.0);
emission += params.base_emission * params.base_density;
@@ -552,16 +577,29 @@ void main() {
if (spot_lights.data[light_index].shadow_enabled) {
//has shadow
- vec4 v = vec4(view_pos, 1.0);
+ vec4 uv_rect = spot_lights.data[light_index].atlas_rect;
+ vec2 flip_offset = spot_lights.data[light_index].direction.xy;
- vec4 splane = (spot_lights.data[light_index].shadow_matrix * v);
- splane /= splane.w;
+ vec3 local_vert = (spot_lights.data[light_index].shadow_matrix * vec4(view_pos, 1.0)).xyz;
- float depth = texture(sampler2D(shadow_atlas, linear_sampler), splane.xy).r;
+ float shadow_len = length(local_vert); //need to remember shadow len from here
+ vec3 shadow_sample = normalize(local_vert);
- shadow_attenuation = exp(min(0.0, (depth - splane.z)) / spot_lights.data[light_index].inv_radius * spot_lights.data[light_index].shadow_volumetric_fog_fade);
- }
+ if (shadow_sample.z >= 0.0) {
+ uv_rect.xy += flip_offset;
+ }
+
+ shadow_sample.z = 1.0 + abs(shadow_sample.z);
+ vec3 pos = vec3(shadow_sample.xy / shadow_sample.z, shadow_len - spot_lights.data[light_index].shadow_bias);
+ pos.z *= spot_lights.data[light_index].inv_radius;
+ pos.xy = pos.xy * 0.5 + 0.5;
+ pos.xy = uv_rect.xy + pos.xy * uv_rect.zw;
+
+ float depth = texture(sampler2D(shadow_atlas, linear_sampler), pos.xy).r;
+
+ shadow_attenuation = exp(min(0.0, (depth - pos.z)) / spot_lights.data[light_index].inv_radius * spot_lights.data[light_index].shadow_volumetric_fog_fade);
+ }
total_light += light * attenuation * shadow_attenuation * henyey_greenstein(dot(normalize(light_rel_vec), normalize(view_pos)), params.phase_g);
}
}
@@ -673,10 +711,16 @@ void main() {
final_density = mix(final_density, reprojected_density, reproject_amount);
imageStore(density_map, pos, final_density);
+#ifdef MOLTENVK_USED
+ density_only_map[lpos] = 0;
+ light_only_map[lpos] = 0;
+ emissive_only_map[lpos] = 0;
+#else
imageStore(density_only_map, pos, uvec4(0));
imageStore(light_only_map, pos, uvec4(0));
imageStore(emissive_only_map, pos, uvec4(0));
#endif
+#endif
#ifdef MODE_FOG
diff --git a/servers/rendering/renderer_rd/shaders/voxel_gi.glsl b/servers/rendering/renderer_rd/shaders/voxel_gi.glsl
index 779f04ed35..73a97d9df1 100644
--- a/servers/rendering/renderer_rd/shaders/voxel_gi.glsl
+++ b/servers/rendering/renderer_rd/shaders/voxel_gi.glsl
@@ -13,7 +13,6 @@ layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
#ifndef MODE_DYNAMIC
#define NO_CHILDREN 0xFFFFFFFF
-#define GREY_VEC vec3(0.33333, 0.33333, 0.33333)
struct CellChildren {
uint children[8];
diff --git a/servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl b/servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl
index 281c496df3..3f3437f527 100644
--- a/servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl
+++ b/servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl
@@ -90,66 +90,10 @@ void main() {
#endif
#ifdef MODE_DEBUG_LIGHT
-
-#ifdef USE_ANISOTROPY
-
-#define POS_X 0
-#define POS_Y 1
-#define POS_Z 2
-#define NEG_X 3
-#define NEG_Y 4
-#define NEG_Z 5
-
- const uint triangle_aniso[12] = uint[](
- NEG_X,
- NEG_Z,
- NEG_Y,
- NEG_Z,
- NEG_X,
- NEG_Y,
- POS_Z,
- POS_X,
- POS_X,
- POS_Y,
- POS_Y,
- POS_Z);
-
- color_interp.xyz = texelFetch(sampler3D(color_tex, tex_sampler), ivec3(posu), int(params.level)).xyz * params.dynamic_range;
- vec3 aniso_pos = texelFetch(sampler3D(aniso_pos_tex, tex_sampler), ivec3(posu), int(params.level)).xyz;
- vec3 aniso_neg = texelFetch(sampler3D(aniso_neg_tex, tex_sampler), ivec3(posu), int(params.level)).xyz;
- uint side = triangle_aniso[gl_VertexIndex / 3];
-
- float strength = 0.0;
- switch (side) {
- case POS_X:
- strength = aniso_pos.x;
- break;
- case POS_Y:
- strength = aniso_pos.y;
- break;
- case POS_Z:
- strength = aniso_pos.z;
- break;
- case NEG_X:
- strength = aniso_neg.x;
- break;
- case NEG_Y:
- strength = aniso_neg.y;
- break;
- case NEG_Z:
- strength = aniso_neg.z;
- break;
- }
-
- color_interp.xyz *= strength;
-
-#else
color_interp = texelFetch(sampler3D(color_tex, tex_sampler), ivec3(posu), int(params.level));
color_interp.xyz *params.dynamic_range;
-
#endif
-#endif
float scale = (1 << params.level);
gl_Position = params.projection * vec4((vec3(posu) + vertex) * scale, 1.0);
diff --git a/servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl b/servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl
index e20b3f680d..3bb4421646 100644
--- a/servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl
+++ b/servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl
@@ -6,10 +6,9 @@
layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
-#define MAX_DISTANCE 100000
+#define MAX_DISTANCE 100000.0
#define NO_CHILDREN 0xFFFFFFFF
-#define GREY_VEC vec3(0.33333, 0.33333, 0.33333)
struct CellChildren {
uint children[8];
@@ -44,7 +43,7 @@ params;
void main() {
vec3 pos = vec3(gl_GlobalInvocationID);
- float closest_dist = 100000.0;
+ float closest_dist = MAX_DISTANCE;
for (uint i = params.offset; i < params.end; i++) {
vec3 posu = vec3(uvec3(cell_data.data[i].position & 0x7FF, (cell_data.data[i].position >> 11) & 0x3FF, cell_data.data[i].position >> 21));
diff --git a/servers/rendering/renderer_scene.cpp b/servers/rendering/renderer_scene.cpp
index dd544d4f3f..b3fdd88626 100644
--- a/servers/rendering/renderer_scene.cpp
+++ b/servers/rendering/renderer_scene.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/renderer_scene.h
index b6e99e4be5..605dd135a2 100644
--- a/servers/rendering/renderer_scene.h
+++ b/servers/rendering/renderer_scene.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -191,7 +191,7 @@ public:
virtual RID render_buffers_create() = 0;
- virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) = 0;
+ virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) = 0;
virtual void gi_set_use_half_resolution(bool p_enable) = 0;
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 8421938507..1f72b23f8a 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -644,6 +644,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
scene_render->geometry_instance_set_use_dynamic_gi(geom->geometry_instance, instance->dynamic_gi);
scene_render->geometry_instance_set_cast_double_sided_shadows(geom->geometry_instance, instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED);
scene_render->geometry_instance_set_use_lightmap(geom->geometry_instance, RID(), instance->lightmap_uv_scale, instance->lightmap_slice_index);
+ scene_render->geometry_instance_set_transparency(geom->geometry_instance, instance->transparency);
if (instance->lightmap_sh.size() == 9) {
scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, instance->lightmap_sh.ptr());
}
@@ -839,6 +840,8 @@ void RendererSceneCull::instance_geometry_set_transparency(RID p_instance, float
Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
+ instance->transparency = p_transparency;
+
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
scene_render->geometry_instance_set_transparency(geom->geometry_instance, p_transparency);
@@ -1310,7 +1313,7 @@ void RendererSceneCull::_update_instance_visibility_dependencies(Instance *p_ins
bool needs_visibility_cull = has_visibility_range && is_geometry_instance && p_instance->array_index != -1;
if (!needs_visibility_cull && p_instance->visibility_index != -1) {
- p_instance->scenario->instance_visibility.remove(p_instance->visibility_index);
+ p_instance->scenario->instance_visibility.remove_at(p_instance->visibility_index);
p_instance->visibility_index = -1;
} else if (needs_visibility_cull && p_instance->visibility_index == -1) {
InstanceVisibilityData vd;
@@ -3855,6 +3858,10 @@ void RendererSceneCull::update() {
}
bool RendererSceneCull::free(RID p_rid) {
+ if (p_rid.is_null()) {
+ return true;
+ }
+
if (scene_render->free(p_rid)) {
return true;
}
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index de22bc1328..feeaad0088 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -439,17 +439,18 @@ public:
RID self;
//scenario stuff
DynamicBVH::ID indexer_id;
- int32_t array_index;
+ int32_t array_index = -1;
int32_t visibility_index = -1;
- float visibility_range_begin;
- float visibility_range_end;
- float visibility_range_begin_margin;
- float visibility_range_end_margin;
+ float visibility_range_begin = 0.0f;
+ float visibility_range_end = 0.0f;
+ float visibility_range_begin_margin = 0.0f;
+ float visibility_range_end_margin = 0.0f;
RS::VisibilityRangeFadeMode visibility_range_fade_mode = RS::VISIBILITY_RANGE_FADE_DISABLED;
Instance *visibility_parent = nullptr;
Set<Instance *> visibility_dependencies;
- uint32_t visibility_dependencies_depth;
- Scenario *scenario;
+ uint32_t visibility_dependencies_depth = 0;
+ float transparency = 0.0f;
+ Scenario *scenario = nullptr;
SelfList<Instance> scenario_item;
//aabb stuff
@@ -1154,7 +1155,7 @@ public:
/* Render Buffers */
PASS0R(RID, render_buffers_create)
- PASS8(render_buffers_configure, RID, RID, int, int, RS::ViewportMSAA, RS::ViewportScreenSpaceAA, bool, uint32_t)
+ PASS12(render_buffers_configure, RID, RID, int, int, int, int, float, float, RS::ViewportMSAA, RS::ViewportScreenSpaceAA, bool, uint32_t)
PASS1(gi_set_use_half_resolution, bool)
/* Shadow Atlas */
diff --git a/servers/rendering/renderer_scene_occlusion_cull.cpp b/servers/rendering/renderer_scene_occlusion_cull.cpp
index 1b8aea36d7..bda0950097 100644
--- a/servers/rendering/renderer_scene_occlusion_cull.cpp
+++ b/servers/rendering/renderer_scene_occlusion_cull.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_scene_occlusion_cull.h b/servers/rendering/renderer_scene_occlusion_cull.h
index 4e4b1b94db..48412dab68 100644
--- a/servers/rendering/renderer_scene_occlusion_cull.h
+++ b/servers/rendering/renderer_scene_occlusion_cull.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp
index 38d1218dee..c802f72fdf 100644
--- a/servers/rendering/renderer_scene_render.cpp
+++ b/servers/rendering/renderer_scene_render.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h
index 200ddc55d4..a56a455535 100644
--- a/servers/rendering/renderer_scene_render.h
+++ b/servers/rendering/renderer_scene_render.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -256,7 +256,7 @@ public:
virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0;
virtual RID render_buffers_create() = 0;
- virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) = 0;
+ virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) = 0;
virtual void gi_set_use_half_resolution(bool p_enable) = 0;
virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0;
diff --git a/servers/rendering/renderer_storage.cpp b/servers/rendering/renderer_storage.cpp
index aa005fac0a..56409ae187 100644
--- a/servers/rendering/renderer_storage.cpp
+++ b/servers/rendering/renderer_storage.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h
index 2985e05e8f..056fecd020 100644
--- a/servers/rendering/renderer_storage.h
+++ b/servers/rendering/renderer_storage.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -183,8 +183,8 @@ public:
virtual String shader_get_code(RID p_shader) const = 0;
virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0;
- virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) = 0;
- virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const = 0;
+ virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) = 0;
+ virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const = 0;
virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const = 0;
virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const = 0;
diff --git a/servers/rendering/renderer_thread_pool.cpp b/servers/rendering/renderer_thread_pool.cpp
index 98050dd508..ddf1d1bd00 100644
--- a/servers/rendering/renderer_thread_pool.cpp
+++ b/servers/rendering/renderer_thread_pool.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_thread_pool.h b/servers/rendering/renderer_thread_pool.h
index ae25415a0d..4626490d32 100644
--- a/servers/rendering/renderer_thread_pool.h
+++ b/servers/rendering/renderer_thread_pool.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index 347238cdaa..395e8d9583 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -77,18 +77,69 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
RSG::scene->free(p_viewport->render_buffers);
p_viewport->render_buffers = RID();
} else {
- float scale_3d = p_viewport->scale_3d;
- if (Engine::get_singleton()->is_editor_hint()) {
- // Ignore the 3D viewport render scaling inside of the editor.
- // The Half Resolution 3D editor viewport option should be used instead.
- scale_3d = 1.0;
+ float scaling_3d_scale = p_viewport->scaling_3d_scale;
+
+ RS::ViewportScaling3DMode scaling_3d_mode = p_viewport->scaling_3d_mode;
+ bool scaling_enabled = true;
+
+ if ((scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) && (scaling_3d_scale > 1.0)) {
+ // FSR is not design for downsampling.
+ // Throw a warning and fallback to VIEWPORT_SCALING_3D_MODE_BILINEAR
+ WARN_PRINT_ONCE("FSR 3D resolution scaling does not support supersampling. Falling back to bilinear scaling.");
+ scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_BILINEAR;
+ }
+
+ if ((scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) && !p_viewport->fsr_enabled) {
+ // FSR is not actually available.
+ // Throw a warning and fallback to disable scaling
+ WARN_PRINT_ONCE("FSR 3D resolution scaling is not available. Disabling 3D resolution scaling.");
+ scaling_enabled = false;
+ }
+
+ if (scaling_3d_scale == 1.0) {
+ scaling_enabled = false;
+ }
+
+ int width;
+ int height;
+ int render_width;
+ int render_height;
+
+ if (scaling_enabled) {
+ switch (scaling_3d_mode) {
+ case RS::VIEWPORT_SCALING_3D_MODE_BILINEAR:
+ // Clamp 3D rendering resolution to reasonable values supported on most hardware.
+ // This prevents freezing the engine or outright crashing on lower-end GPUs.
+ width = CLAMP(p_viewport->size.width * scaling_3d_scale, 1, 16384);
+ height = CLAMP(p_viewport->size.height * scaling_3d_scale, 1, 16384);
+ render_width = width;
+ render_height = height;
+ break;
+ case RS::VIEWPORT_SCALING_3D_MODE_FSR:
+ width = p_viewport->size.width;
+ height = p_viewport->size.height;
+ render_width = MAX(width * scaling_3d_scale, 1.0); // width / (width * scaling)
+ render_height = MAX(height * scaling_3d_scale, 1.0);
+ break;
+ default:
+ // This is an unknown mode.
+ WARN_PRINT_ONCE(vformat("Unknown scaling mode: %d. Disabling 3D resolution scaling.", scaling_3d_mode));
+ width = p_viewport->size.width;
+ height = p_viewport->size.height;
+ render_width = width;
+ render_height = height;
+ break;
+ }
+ } else {
+ width = p_viewport->size.width;
+ height = p_viewport->size.height;
+ render_width = width;
+ render_height = height;
}
- // Clamp 3D rendering resolution to reasonable values supported on most hardware.
- // This prevents freezing the engine or outright crashing on lower-end GPUs.
- const int width = CLAMP(p_viewport->size.width * scale_3d, 1, 16384);
- const int height = CLAMP(p_viewport->size.height * scale_3d, 1, 16384);
- RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, width, height, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_debanding, p_viewport->get_view_count());
+ p_viewport->internal_size = Size2(render_width, render_height);
+
+ RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, render_width, render_height, width, height, p_viewport->fsr_sharpness, p_viewport->fsr_mipmap_bias, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_debanding, p_viewport->get_view_count());
}
}
}
@@ -117,7 +168,7 @@ void RendererViewport::_draw_3d(Viewport *p_viewport) {
}
float screen_lod_threshold = p_viewport->lod_threshold / float(p_viewport->size.width);
- RSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->self, p_viewport->size, screen_lod_threshold, p_viewport->shadow_atlas, xr_interface, &p_viewport->render_info);
+ RSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->self, p_viewport->internal_size, screen_lod_threshold, p_viewport->shadow_atlas, xr_interface, &p_viewport->render_info);
RENDER_TIMESTAMP("<End Rendering 3D Scene");
}
@@ -129,6 +180,11 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
timestamp_vp_map[rt_id] = p_viewport->self;
}
+ if (OS::get_singleton()->get_current_rendering_driver_name() == "opengl3") {
+ // This is currently needed for GLES to keep the current window being rendered to up to date
+ DisplayServer::get_singleton()->gl_window_make_current(p_viewport->viewport_to_screen);
+ }
+
/* Camera should always be BEFORE any other 3D */
bool scenario_draw_canvas_bg = false; //draw canvas, or some layer of it, as BG for 3D instead of in front
@@ -566,7 +622,7 @@ void RendererViewport::draw_viewports() {
// override our size, make sure it matches our required size and is created as a stereo target
vp->size = xr_interface->get_render_target_size();
uint32_t view_count = xr_interface->get_view_count();
- RSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y, view_count);
+ RSG::storage->render_target_set_size(vp->render_target, vp->internal_size.x, vp->internal_size.y, view_count);
// check for an external texture destination (disabled for now, not yet supported)
// RSG::storage->render_target_set_external_texture(vp->render_target, xr_interface->get_external_texture_for_eye(leftOrMono));
@@ -657,6 +713,8 @@ void RendererViewport::viewport_initialize(RID p_rid) {
viewport->render_target = RSG::storage->render_target_create();
viewport->shadow_atlas = RSG::scene->shadow_atlas_create();
viewport->viewport_render_direct_to_screen = false;
+
+ viewport->fsr_enabled = !RSG::rasterizer->is_low_end() && !viewport->disable_3d;
}
void RendererViewport::viewport_set_use_xr(RID p_viewport, bool p_use_xr) {
@@ -671,18 +729,42 @@ void RendererViewport::viewport_set_use_xr(RID p_viewport, bool p_use_xr) {
_configure_3d_render_buffers(viewport);
}
-void RendererViewport::viewport_set_scale_3d(RID p_viewport, float p_scale_3d) {
+void RendererViewport::viewport_set_scaling_3d_mode(RID p_viewport, RS::ViewportScaling3DMode p_mode) {
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ viewport->scaling_3d_mode = p_mode;
+ _configure_3d_render_buffers(viewport);
+}
+
+void RendererViewport::viewport_set_fsr_sharpness(RID p_viewport, float p_sharpness) {
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ viewport->fsr_sharpness = p_sharpness;
+ _configure_3d_render_buffers(viewport);
+}
+
+void RendererViewport::viewport_set_fsr_mipmap_bias(RID p_viewport, float p_mipmap_bias) {
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ viewport->fsr_mipmap_bias = p_mipmap_bias;
+ _configure_3d_render_buffers(viewport);
+}
+
+void RendererViewport::viewport_set_scaling_3d_scale(RID p_viewport, float p_scaling_3d_scale) {
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
// Clamp to reasonable values that are actually useful.
// Values above 2.0 don't serve a practical purpose since the viewport
// isn't displayed with mipmaps.
- if (viewport->scale_3d == CLAMP(p_scale_3d, 0.1, 2.0)) {
+ if (viewport->scaling_3d_scale == CLAMP(p_scaling_3d_scale, 0.1, 2.0)) {
return;
}
- viewport->scale_3d = CLAMP(p_scale_3d, 0.1, 2.0);
+ viewport->scaling_3d_scale = CLAMP(p_scaling_3d_scale, 0.1, 2.0);
_configure_3d_render_buffers(viewport);
}
@@ -708,6 +790,7 @@ void RendererViewport::viewport_set_size(RID p_viewport, int p_width, int p_heig
ERR_FAIL_COND(!viewport);
viewport->size = Size2(p_width, p_height);
+
uint32_t view_count = viewport->get_view_count();
RSG::storage->render_target_set_size(viewport->render_target, p_width, p_height, view_count);
_configure_3d_render_buffers(viewport);
@@ -747,7 +830,7 @@ void RendererViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_
ERR_FAIL_COND(!viewport);
if (p_screen != DisplayServer::INVALID_WINDOW_ID) {
- // If using GLES2 we can optimize this operation by rendering directly to system_fbo
+ // If using OpenGL we can optimize this operation by rendering directly to system_fbo
// instead of rendering to fbo and copying to system_fbo after
if (RSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
RSG::storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y, viewport->get_view_count());
@@ -760,7 +843,7 @@ void RendererViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_
// if render_direct_to_screen was used, reset size and position
if (RSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
RSG::storage->render_target_set_position(viewport->render_target, 0, 0);
- RSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->get_view_count());
+ RSG::storage->render_target_set_size(viewport->render_target, viewport->internal_size.x, viewport->internal_size.y, viewport->get_view_count());
}
viewport->viewport_to_screen_rect = Rect2();
diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h
index f6e6cc8e84..0db8b76dd9 100644
--- a/servers/rendering/renderer_viewport.h
+++ b/servers/rendering/renderer_viewport.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -49,12 +49,16 @@ public:
bool use_xr; /* use xr interface to override camera positioning and projection matrices and control output */
- float scale_3d = 1.0;
-
+ Size2i internal_size;
Size2i size;
RID camera;
RID scenario;
+ RS::ViewportScaling3DMode scaling_3d_mode;
+ float scaling_3d_scale = 1.0;
+ float fsr_sharpness = 0.2f;
+ float fsr_mipmap_bias = 0.0f;
+ bool fsr_enabled;
RS::ViewportUpdateMode update_mode;
RID render_target;
RID render_target_texture;
@@ -207,7 +211,6 @@ public:
void viewport_initialize(RID p_rid);
void viewport_set_use_xr(RID p_viewport, bool p_use_xr);
- void viewport_set_scale_3d(RID p_viewport, float p_scale_3d);
void viewport_set_size(RID p_viewport, int p_width, int p_height);
@@ -216,6 +219,12 @@ public:
void viewport_set_active(RID p_viewport, bool p_active);
void viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport);
+
+ void viewport_set_scaling_3d_mode(RID p_viewport, RS::ViewportScaling3DMode p_mode);
+ void viewport_set_scaling_3d_scale(RID p_viewport, float p_scaling_3d_scale);
+ void viewport_set_fsr_sharpness(RID p_viewport, float p_sharpness);
+ void viewport_set_fsr_mipmap_bias(RID p_viewport, float p_mipmap_bias);
+
void viewport_set_update_mode(RID p_viewport, RS::ViewportUpdateMode p_mode);
void viewport_set_vflip(RID p_viewport, bool p_enable);
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index dcbc5f5c8e..2274214f38 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -185,9 +185,13 @@ Ref<RDShaderSPIRV> RenderingDevice::_shader_compile_spirv_from_source(const Ref<
String error;
ShaderStage stage = ShaderStage(i);
- Vector<uint8_t> spirv = shader_compile_spirv_from_source(stage, p_source->get_stage_source(stage), p_source->get_language(), &error, p_allow_cache);
- bytecode->set_stage_bytecode(stage, spirv);
- bytecode->set_stage_compile_error(stage, error);
+ String source = p_source->get_stage_source(stage);
+
+ if (!source.is_empty()) {
+ Vector<uint8_t> spirv = shader_compile_spirv_from_source(stage, source, p_source->get_language(), &error, p_allow_cache);
+ bytecode->set_stage_bytecode(stage, spirv);
+ bytecode->set_stage_compile_error(stage, error);
+ }
}
return bytecode;
}
@@ -201,7 +205,7 @@ Vector<uint8_t> RenderingDevice::_shader_compile_binary_from_spirv(const Ref<RDS
ShaderStageSPIRVData sd;
sd.shader_stage = stage;
String error = p_spirv->get_stage_compile_error(stage);
- ERR_FAIL_COND_V_MSG(error != String(), Vector<uint8_t>(), "Can't create a shader from an errored bytecode. Check errors in source bytecode.");
+ ERR_FAIL_COND_V_MSG(!error.is_empty(), Vector<uint8_t>(), "Can't create a shader from an errored bytecode. Check errors in source bytecode.");
sd.spir_v = p_spirv->get_stage_bytecode(stage);
if (sd.spir_v.is_empty()) {
continue;
@@ -221,7 +225,7 @@ RID RenderingDevice::_shader_create_from_spirv(const Ref<RDShaderSPIRV> &p_spirv
ShaderStageSPIRVData sd;
sd.shader_stage = stage;
String error = p_spirv->get_stage_compile_error(stage);
- ERR_FAIL_COND_V_MSG(error != String(), RID(), "Can't create a shader from an errored bytecode. Check errors in source bytecode.");
+ ERR_FAIL_COND_V_MSG(!error.is_empty(), RID(), "Can't create a shader from an errored bytecode. Check errors in source bytecode.");
sd.spir_v = p_spirv->get_stage_bytecode(stage);
if (sd.spir_v.is_empty()) {
continue;
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index 5eb8f1cead..3851cbe13f 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -120,6 +120,7 @@ public:
// features
bool supports_multiview = false; // If true this device supports multiview options
+ bool supports_fsr_half_float = false; // If true this device supports FSR scaling 3D in half float mode, otherwise use the fallback mode
};
typedef String (*ShaderSPIRVGetCacheKeyFunction)(const Capabilities *p_capabilities);
diff --git a/servers/rendering/rendering_device_binds.cpp b/servers/rendering/rendering_device_binds.cpp
index a21f28989b..19cde610ba 100644
--- a/servers/rendering/rendering_device_binds.cpp
+++ b/servers/rendering/rendering_device_binds.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -80,7 +80,7 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
}
}
- if (base_error != String()) {
+ if (!base_error.is_empty()) {
break;
}
}
@@ -89,7 +89,7 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
}
}
- if (stage == RD::SHADER_STAGE_MAX && line.strip_edges() != "") {
+ if (stage == RD::SHADER_STAGE_MAX && !line.strip_edges().is_empty()) {
line = line.strip_edges();
if (line.begins_with("//") || line.begins_with("/*")) {
continue; //assuming comment (single line)
@@ -98,7 +98,7 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
if (reading_versions) {
String l = line.strip_edges();
- if (l != "") {
+ if (!l.is_empty()) {
if (l.find("=") == -1) {
base_error = "Missing `=` in '" + l + "'. Version syntax is `version = \"<defines with C escaping>\";`.";
break;
@@ -124,7 +124,7 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
version_texts[version] = define + "\n" + p_defines;
}
} else {
- if (stage == RD::SHADER_STAGE_MAX && line.strip_edges() != "") {
+ if (stage == RD::SHADER_STAGE_MAX && !line.strip_edges().is_empty()) {
base_error = "Text was found that does not belong to a valid section: " + line;
break;
}
@@ -140,7 +140,7 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
}
include = include.substr(1, include.length() - 2).strip_edges();
String include_text = p_include_func(include, p_include_func_userdata);
- if (include_text != String()) {
+ if (!include_text.is_empty()) {
stage_code[stage] += "\n" + include_text + "\n";
} else {
base_error = "#include failed for file '" + include + "'";
@@ -158,7 +158,7 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
Ref<RDShaderFile> shader_file;
shader_file.instantiate();
- if (base_error == "") {
+ if (base_error.is_empty()) {
if (stage_found[RD::SHADER_STAGE_COMPUTE] && stages_found > 1) {
ERR_FAIL_V_MSG(ERR_PARSE_ERROR, "When writing compute shaders, [compute] mustbe the only stage present.");
}
@@ -177,14 +177,14 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) {
String code = stage_code[i];
- if (code == String()) {
+ if (code.is_empty()) {
continue;
}
code = code.replace("VERSION_DEFINES", E.value);
String error;
Vector<uint8_t> spirv = RenderingDevice::get_singleton()->shader_compile_spirv_from_source(RD::ShaderStage(i), code, RD::SHADER_LANGUAGE_GLSL, &error, false);
bytecode->set_stage_bytecode(RD::ShaderStage(i), spirv);
- if (error != "") {
+ if (!error.is_empty()) {
error += String() + "\n\nStage '" + stage_str[i] + "' source code: \n\n";
Vector<String> sclines = code.split("\n");
for (int j = 0; j < sclines.size(); j++) {
diff --git a/servers/rendering/rendering_device_binds.h b/servers/rendering/rendering_device_binds.h
index da614877c4..b07857364b 100644
--- a/servers/rendering/rendering_device_binds.h
+++ b/servers/rendering/rendering_device_binds.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -368,13 +368,13 @@ public:
}
void print_errors(const String &p_file) {
- if (base_error != "") {
+ if (!base_error.is_empty()) {
ERR_PRINT("Error parsing shader '" + p_file + "':\n\n" + base_error);
} else {
for (KeyValue<StringName, Ref<RDShaderSPIRV>> &E : versions) {
for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) {
String error = E.value->get_stage_compile_error(RD::ShaderStage(i));
- if (error != String()) {
+ if (!error.is_empty()) {
static const char *stage_str[RD::SHADER_STAGE_MAX] = {
"vertex",
"fragment",
@@ -427,7 +427,7 @@ protected:
ClassDB::bind_method(D_METHOD("_set_versions", "versions"), &RDShaderFile::_set_versions);
ClassDB::bind_method(D_METHOD("_get_versions"), &RDShaderFile::_get_versions);
- ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_versions", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_versions", "_get_versions");
+ ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_versions", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_versions", "_get_versions");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_error"), "set_base_error", "get_base_error");
}
};
diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp
index 107c9f8040..e60e507f87 100644
--- a/servers/rendering/rendering_server_default.cpp
+++ b/servers/rendering/rendering_server_default.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -64,14 +64,8 @@ void RenderingServerDefault::_free(RID p_rid) {
/* EVENT QUEUING */
-void RenderingServerDefault::request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata) {
- ERR_FAIL_NULL(p_where);
- FrameDrawnCallbacks fdc;
- fdc.object = p_where->get_instance_id();
- fdc.method = p_method;
- fdc.param = p_userdata;
-
- frame_drawn_callbacks.push_back(fdc);
+void RenderingServerDefault::request_frame_drawn_callback(const Callable &p_callable) {
+ frame_drawn_callbacks.push_back(p_callable);
}
void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
@@ -103,15 +97,13 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
RSG::scene->update_visibility_notifiers();
while (frame_drawn_callbacks.front()) {
- Object *obj = ObjectDB::get_instance(frame_drawn_callbacks.front()->get().object);
- if (obj) {
- Callable::CallError ce;
- const Variant *v = &frame_drawn_callbacks.front()->get().param;
- obj->call(frame_drawn_callbacks.front()->get().method, &v, 1, ce);
- if (ce.error != Callable::CallError::CALL_OK) {
- String err = Variant::get_call_error_text(obj, frame_drawn_callbacks.front()->get().method, &v, 1, ce);
- ERR_PRINT("Error calling frame drawn function: " + err);
- }
+ Callable c = frame_drawn_callbacks.front()->get();
+ Variant result;
+ Callable::CallError ce;
+ c.call(nullptr, 0, result, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ String err = Variant::get_callable_error_text(c, nullptr, 0, ce);
+ ERR_PRINT("Error calling frame drawn function: " + err);
}
frame_drawn_callbacks.pop_front();
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index a25bd3dae5..f1722de72b 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -58,13 +58,7 @@ class RenderingServerDefault : public RenderingServer {
static int changes;
RID test_cube;
- struct FrameDrawnCallbacks {
- ObjectID object;
- StringName method;
- Variant param;
- };
-
- List<FrameDrawnCallbacks> frame_drawn_callbacks;
+ List<Callable> frame_drawn_callbacks;
static void _changes_changed() {}
@@ -229,8 +223,8 @@ public:
FUNC2SC(shader_get_param_list, RID, List<PropertyInfo> *)
- FUNC3(shader_set_default_texture_param, RID, const StringName &, RID)
- FUNC2RC(RID, shader_get_default_texture_param, RID, const StringName &)
+ FUNC4(shader_set_default_texture_param, RID, const StringName &, RID, int)
+ FUNC3RC(RID, shader_get_default_texture_param, RID, const StringName &, int)
FUNC2RC(Variant, shader_get_param_default, RID, const StringName &)
FUNC1RC(ShaderNativeSourceCode, shader_get_native_source_code, RID)
@@ -534,7 +528,6 @@ public:
FUNCRIDSPLIT(viewport)
FUNC2(viewport_set_use_xr, RID, bool)
- FUNC2(viewport_set_scale_3d, RID, float)
FUNC3(viewport_set_size, RID, int, int)
FUNC2(viewport_set_active, RID, bool)
@@ -545,6 +538,11 @@ public:
FUNC3(viewport_attach_to_screen, RID, const Rect2 &, int)
FUNC2(viewport_set_render_direct_to_screen, RID, bool)
+ FUNC2(viewport_set_scaling_3d_mode, RID, ViewportScaling3DMode)
+ FUNC2(viewport_set_scaling_3d_scale, RID, float)
+ FUNC2(viewport_set_fsr_sharpness, RID, float)
+ FUNC2(viewport_set_fsr_mipmap_bias, RID, float)
+
FUNC2(viewport_set_update_mode, RID, ViewportUpdateMode)
FUNC1RC(RID, viewport_get_texture, RID)
@@ -880,7 +878,7 @@ public:
/* EVENT QUEUING */
- virtual void request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata) override;
+ virtual void request_frame_drawn_callback(const Callable &p_callable) override;
virtual void draw(bool p_swap_buffers, double frame_step) override;
virtual void sync() override;
diff --git a/servers/rendering/rendering_server_globals.cpp b/servers/rendering/rendering_server_globals.cpp
index 2dda506bac..b8b06b5eea 100644
--- a/servers/rendering/rendering_server_globals.cpp
+++ b/servers/rendering/rendering_server_globals.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/rendering_server_globals.h b/servers/rendering/rendering_server_globals.h
index 63755e6125..4351830a5f 100644
--- a/servers/rendering/rendering_server_globals.h
+++ b/servers/rendering/rendering_server_globals.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index ac978b994a..944a6096b2 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -88,7 +88,8 @@ String ShaderLanguage::get_operator_text(Operator p_op) {
"--",
"()",
"construct",
- "index" };
+ "index",
+ "empty" };
return op_names[p_op];
}
@@ -203,7 +204,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"HINT_WHITE_TEXTURE",
"HINT_BLACK_TEXTURE",
"HINT_NORMAL_TEXTURE",
- "HINT_ANISO_TEXTURE",
+ "HINT_ANISOTROPY_TEXTURE",
"HINT_ALBEDO_TEXTURE",
"HINT_BLACK_ALBEDO_TEXTURE",
"HINT_COLOR",
@@ -213,8 +214,8 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"FILTER_LINEAR",
"FILTER_NEAREST_MIPMAP",
"FILTER_LINEAR_MIPMAP",
- "FILTER_NEAREST_MIPMAP_ANISO",
- "FILTER_LINEAR_MIPMAP_ANISO",
+ "FILTER_NEAREST_MIPMAP_ANISOTROPIC",
+ "FILTER_LINEAR_MIPMAP_ANISOTROPIC",
"REPEAT_ENABLE",
"REPEAT_DISABLE",
"SHADER_TYPE",
@@ -225,7 +226,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
String ShaderLanguage::get_token_text(Token p_token) {
String name = token_names[p_token.type];
- if (p_token.type == TK_INT_CONSTANT || p_token.type == TK_FLOAT_CONSTANT) {
+ if (p_token.is_integer_constant() || p_token.type == TK_FLOAT_CONSTANT) {
name += "(" + rtos(p_token.constant) + ")";
} else if (p_token.type == TK_IDENTIFIER) {
name += "(" + String(p_token.text) + ")";
@@ -317,7 +318,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_HINT_ROUGHNESS_B, "hint_roughness_b" },
{ TK_HINT_ROUGHNESS_A, "hint_roughness_a" },
{ TK_HINT_ROUGHNESS_GRAY, "hint_roughness_gray" },
- { TK_HINT_ANISO_TEXTURE, "hint_aniso" },
+ { TK_HINT_ANISOTROPY_TEXTURE, "hint_anisotropy" },
{ TK_HINT_ALBEDO_TEXTURE, "hint_albedo" },
{ TK_HINT_BLACK_ALBEDO_TEXTURE, "hint_black_albedo" },
{ TK_HINT_COLOR, "hint_color" },
@@ -327,8 +328,8 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_FILTER_LINEAR, "filter_linear" },
{ TK_FILTER_NEAREST_MIPMAP, "filter_nearest_mipmap" },
{ TK_FILTER_LINEAR_MIPMAP, "filter_linear_mipmap" },
- { TK_FILTER_NEAREST_MIPMAP_ANISO, "filter_nearest_mipmap_aniso" },
- { TK_FILTER_LINEAR_MIPMAP_ANISO, "filter_linear_mipmap_aniso" },
+ { TK_FILTER_NEAREST_MIPMAP_ANISOTROPIC, "filter_nearest_mipmap_anisotropic" },
+ { TK_FILTER_LINEAR_MIPMAP_ANISOTROPIC, "filter_linear_mipmap_anisotropic" },
{ TK_REPEAT_ENABLE, "repeat_enable" },
{ TK_REPEAT_DISABLE, "repeat_disable" },
{ TK_SHADER_TYPE, "shader_type" },
@@ -474,6 +475,10 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
case ':':
return _make_token(TK_COLON);
case '^':
+ if (GETCHAR(0) == '=') {
+ char_idx++;
+ return _make_token(TK_OP_ASSIGN_BIT_XOR);
+ }
return _make_token(TK_OP_BIT_XOR);
case '~':
return _make_token(TK_OP_BIT_INVERT);
@@ -540,63 +545,113 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
if (_is_number(GETCHAR(0)) || (GETCHAR(0) == '.' && _is_number(GETCHAR(1)))) {
// parse number
+ bool hexa_found = false;
bool period_found = false;
bool exponent_found = false;
- bool hexa_found = false;
- bool sign_found = false;
bool float_suffix_found = false;
+ bool uint_suffix_found = false;
+ bool end_suffix_found = false;
+
+ enum {
+ CASE_ALL,
+ CASE_HEXA_PERIOD,
+ CASE_EXPONENT,
+ CASE_SIGN_AFTER_EXPONENT,
+ CASE_NONE,
+ CASE_MAX,
+ } lut_case = CASE_ALL;
+
+ static bool suffix_lut[CASE_MAX][127];
+
+ if (!is_const_suffix_lut_initialized) {
+ is_const_suffix_lut_initialized = true;
+
+ for (int i = 0; i < 127; i++) {
+ char t = char(i);
+
+ suffix_lut[CASE_ALL][i] = t == '.' || t == 'x' || t == 'e' || t == 'f' || t == 'u' || t == '-' || t == '+';
+ suffix_lut[CASE_HEXA_PERIOD][i] = t == 'e' || t == 'f';
+ suffix_lut[CASE_EXPONENT][i] = t == 'f' || t == '-' || t == '+';
+ suffix_lut[CASE_SIGN_AFTER_EXPONENT][i] = t == 'f';
+ suffix_lut[CASE_NONE][i] = false;
+ }
+ }
String str;
int i = 0;
while (true) {
- if (GETCHAR(i) == '.') {
- if (period_found || exponent_found || hexa_found || float_suffix_found) {
- return _make_token(TK_ERROR, "Invalid numeric constant");
- }
- period_found = true;
- } else if (GETCHAR(i) == 'x') {
- if (hexa_found || str.length() != 1 || str[0] != '0') {
- return _make_token(TK_ERROR, "Invalid numeric constant");
+ const char32_t symbol = String::char_lowercase(GETCHAR(i));
+ bool error = false;
+
+ if (_is_number(symbol)) {
+ if (end_suffix_found) {
+ error = true;
}
- hexa_found = true;
- } else if (GETCHAR(i) == 'e' && !hexa_found) {
- if (exponent_found || float_suffix_found) {
- return _make_token(TK_ERROR, "Invalid numeric constant");
+ } else {
+ if (symbol < 0x7F && suffix_lut[lut_case][symbol]) {
+ if (symbol == 'x') {
+ hexa_found = true;
+ lut_case = CASE_HEXA_PERIOD;
+ } else if (symbol == '.') {
+ period_found = true;
+ lut_case = CASE_HEXA_PERIOD;
+ } else if (symbol == 'e' && !hexa_found) {
+ exponent_found = true;
+ lut_case = CASE_EXPONENT;
+ } else if (symbol == 'f' && !hexa_found) {
+ if (!period_found && !exponent_found) {
+ error = true;
+ }
+ float_suffix_found = true;
+ end_suffix_found = true;
+ lut_case = CASE_NONE;
+ } else if (symbol == 'u') {
+ uint_suffix_found = true;
+ end_suffix_found = true;
+ lut_case = CASE_NONE;
+ } else if (symbol == '-' || symbol == '+') {
+ if (exponent_found) {
+ lut_case = CASE_SIGN_AFTER_EXPONENT;
+ } else {
+ break;
+ }
+ }
+ } else if (!hexa_found || !_is_hex(symbol)) {
+ if (_is_text_char(symbol)) {
+ error = true;
+ } else {
+ break;
+ }
}
- exponent_found = true;
- } else if (GETCHAR(i) == 'f' && !hexa_found) {
- if (exponent_found) {
- return _make_token(TK_ERROR, "Invalid numeric constant");
+ }
+
+ if (error) {
+ if (hexa_found) {
+ return _make_token(TK_ERROR, "Invalid (hexadecimal) numeric constant");
}
- float_suffix_found = true;
- } else if (_is_number(GETCHAR(i))) {
- if (float_suffix_found) {
- return _make_token(TK_ERROR, "Invalid numeric constant");
+ if (period_found || exponent_found || float_suffix_found) {
+ return _make_token(TK_ERROR, "Invalid (float) numeric constant");
}
- } else if (hexa_found && _is_hex(GETCHAR(i))) {
- } else if ((GETCHAR(i) == '-' || GETCHAR(i) == '+') && exponent_found) {
- if (sign_found) {
- return _make_token(TK_ERROR, "Invalid numeric constant");
+ if (uint_suffix_found) {
+ return _make_token(TK_ERROR, "Invalid (unsigned integer) numeric constant");
}
- sign_found = true;
- } else {
- break;
+ return _make_token(TK_ERROR, "Invalid (integer) numeric constant");
}
-
- str += char32_t(GETCHAR(i));
+ str += symbol;
i++;
}
char32_t last_char = str[str.length() - 1];
- if (hexa_found) {
- //integer(hex)
+ if (hexa_found) { // Integer(hex)
if (str.size() > 11 || !str.is_valid_hex_number(true)) { // > 0xFFFFFFFF
return _make_token(TK_ERROR, "Invalid (hexadecimal) numeric constant");
}
- } else if (period_found || exponent_found || float_suffix_found) {
- //floats
+ } else if (period_found || exponent_found || float_suffix_found) { // Float
+ if (exponent_found && (!_is_number(last_char) && last_char != 'f')) { // checks for eg: "2E", "2E-", "2E+"
+ return _make_token(TK_ERROR, "Invalid (float) numeric constant");
+ }
if (period_found) {
if (float_suffix_found) {
//checks for eg "1.f" or "1.99f" notations
@@ -617,22 +672,28 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
}
if (float_suffix_found) {
- //strip the suffix
+ // Strip the suffix.
str = str.left(str.length() - 1);
- //compensate reading cursor position
+ // Compensate reading cursor position.
char_idx += 1;
}
if (!str.is_valid_float()) {
return _make_token(TK_ERROR, "Invalid (float) numeric constant");
}
- } else {
- //integers
- if (!_is_number(last_char)) {
- return _make_token(TK_ERROR, "Invalid (integer) numeric constant");
+ } else { // Integer
+ if (uint_suffix_found) {
+ // Strip the suffix.
+ str = str.left(str.length() - 1);
+ // Compensate reading cursor position.
+ char_idx += 1;
}
if (!str.is_valid_int()) {
- return _make_token(TK_ERROR, "Invalid numeric constant");
+ if (uint_suffix_found) {
+ return _make_token(TK_ERROR, "Invalid (unsigned integer) numeric constant");
+ } else {
+ return _make_token(TK_ERROR, "Invalid (integer) numeric constant");
+ }
}
}
@@ -640,6 +701,8 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
Token tk;
if (period_found || exponent_found || float_suffix_found) {
tk.type = TK_FLOAT_CONSTANT;
+ } else if (uint_suffix_found) {
+ tk.type = TK_UINT_CONSTANT;
} else {
tk.type = TK_INT_CONSTANT;
}
@@ -909,10 +972,10 @@ void ShaderLanguage::clear() {
completion_type = COMPLETION_NONE;
completion_block = nullptr;
completion_function = StringName();
- completion_class = SubClassTag::TAG_GLOBAL;
+ completion_class = TAG_GLOBAL;
completion_struct = StringName();
-
- unknown_varying_usages.clear();
+ completion_base = TYPE_VOID;
+ completion_base_array = false;
#ifdef DEBUG_ENABLED
used_constants.clear();
@@ -2654,6 +2717,8 @@ const ShaderLanguage::BuiltinFuncConstArgs ShaderLanguage::builtin_func_const_ar
{ nullptr, 0, 0, 0 }
};
+bool ShaderLanguage::is_const_suffix_lut_initialized = false;
+
bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionInfo &p_function_info, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str) {
ERR_FAIL_COND_V(p_func->op != OP_CALL && p_func->op != OP_CONSTRUCT, false);
@@ -2994,7 +3059,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
}
FunctionNode *pfunc = shader->functions[i].function;
- if (arg_list == "") {
+ if (arg_list.is_empty()) {
for (int j = 0; j < pfunc->arguments.size(); j++) {
if (j > 0) {
arg_list += ", ";
@@ -3230,6 +3295,10 @@ bool ShaderLanguage::is_token_operator_assign(TokenType p_type) {
p_type == TK_OP_ASSIGN_BIT_XOR);
}
+bool ShaderLanguage::is_token_hint(TokenType p_type) {
+ return int(p_type) > int(TK_RENDER_MODE) && int(p_type) < int(TK_SHADER_TYPE);
+}
+
bool ShaderLanguage::convert_constant(ConstantNode *p_constant, DataType p_to_type, ConstantNode::Value *p_value) {
if (p_constant->datatype == p_to_type) {
if (p_value) {
@@ -3797,55 +3866,77 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
return pi;
}
-uint32_t ShaderLanguage::get_type_size(DataType p_type) {
+uint32_t ShaderLanguage::get_datatype_size(ShaderLanguage::DataType p_type) {
switch (p_type) {
case TYPE_VOID:
return 0;
case TYPE_BOOL:
- case TYPE_INT:
- case TYPE_UINT:
- case TYPE_FLOAT:
return 4;
case TYPE_BVEC2:
- case TYPE_IVEC2:
- case TYPE_UVEC2:
- case TYPE_VEC2:
return 8;
case TYPE_BVEC3:
- case TYPE_IVEC3:
- case TYPE_UVEC3:
- case TYPE_VEC3:
return 12;
case TYPE_BVEC4:
+ return 16;
+ case TYPE_INT:
+ return 4;
+ case TYPE_IVEC2:
+ return 8;
+ case TYPE_IVEC3:
+ return 12;
case TYPE_IVEC4:
+ return 16;
+ case TYPE_UINT:
+ return 4;
+ case TYPE_UVEC2:
+ return 8;
+ case TYPE_UVEC3:
+ return 12;
case TYPE_UVEC4:
+ return 16;
+ case TYPE_FLOAT:
+ return 4;
+ case TYPE_VEC2:
+ return 8;
+ case TYPE_VEC3:
+ return 12;
case TYPE_VEC4:
return 16;
case TYPE_MAT2:
- return 8;
+ return 32; // 4 * 4 + 4 * 4
case TYPE_MAT3:
- return 12;
+ return 48; // 4 * 4 + 4 * 4 + 4 * 4
case TYPE_MAT4:
- return 16;
+ return 64;
case TYPE_SAMPLER2D:
+ return 16;
case TYPE_ISAMPLER2D:
+ return 16;
case TYPE_USAMPLER2D:
+ return 16;
case TYPE_SAMPLER2DARRAY:
+ return 16;
case TYPE_ISAMPLER2DARRAY:
+ return 16;
case TYPE_USAMPLER2DARRAY:
+ return 16;
case TYPE_SAMPLER3D:
+ return 16;
case TYPE_ISAMPLER3D:
+ return 16;
case TYPE_USAMPLER3D:
+ return 16;
case TYPE_SAMPLERCUBE:
+ return 16;
case TYPE_SAMPLERCUBEARRAY:
- return 4; //not really, but useful for indices
+ return 16;
case TYPE_STRUCT:
- // FIXME: Implement.
- return 0;
- case ShaderLanguage::TYPE_MAX:
return 0;
+ case TYPE_MAX: {
+ ERR_FAIL_V(0);
+ };
}
- return 0;
+ ERR_FAIL_V(0);
}
void ShaderLanguage::get_keyword_list(List<String> *r_keywords) {
@@ -4051,43 +4142,6 @@ bool ShaderLanguage::_validate_varying_assign(ShaderNode::Varying &p_varying, St
return true;
}
-bool ShaderLanguage::_validate_varying_using(ShaderNode::Varying &p_varying, String *r_message) {
- switch (p_varying.stage) {
- case ShaderNode::Varying::STAGE_UNKNOWN:
- VaryingUsage usage;
- usage.var = &p_varying;
- usage.line = tk_line;
- unknown_varying_usages.push_back(usage);
- break;
- case ShaderNode::Varying::STAGE_VERTEX:
- if (current_function == varying_function_names.fragment || current_function == varying_function_names.light) {
- p_varying.stage = ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT;
- }
- break;
- case ShaderNode::Varying::STAGE_FRAGMENT:
- if (current_function == varying_function_names.light) {
- p_varying.stage = ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT;
- }
- break;
- default:
- break;
- }
- return true;
-}
-
-bool ShaderLanguage::_check_varying_usages(int *r_error_line, String *r_error_message) const {
- for (const List<ShaderLanguage::VaryingUsage>::Element *E = unknown_varying_usages.front(); E; E = E->next()) {
- ShaderNode::Varying::Stage stage = E->get().var->stage;
- if (stage != ShaderNode::Varying::STAGE_UNKNOWN && stage != ShaderNode::Varying::STAGE_VERTEX && stage != ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT) {
- *r_error_line = E->get().line;
- *r_error_message = RTR("Fragment-stage varying could not been accessed in custom function!");
- return false;
- }
- }
-
- return true;
-}
-
bool ShaderLanguage::_check_node_constness(const Node *p_node) const {
switch (p_node->type) {
case Node::TYPE_OPERATOR: {
@@ -4293,7 +4347,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_size(BlockNode *p_block, cons
return n;
}
-Error ShaderLanguage::_parse_global_array_size(int &r_array_size) {
+Error ShaderLanguage::_parse_global_array_size(int &r_array_size, const FunctionInfo &p_function_info) {
if (r_array_size > 0) {
_set_error("Array size is already defined!");
return ERR_PARSE_ERROR;
@@ -4303,9 +4357,9 @@ Error ShaderLanguage::_parse_global_array_size(int &r_array_size) {
int array_size = 0;
- if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) {
+ if (!tk.is_integer_constant() || ((int)tk.constant) <= 0) {
_set_tkpos(pos);
- Node *n = _parse_array_size(nullptr, FunctionInfo(), array_size);
+ Node *n = _parse_array_size(nullptr, p_function_info, array_size);
if (!n) {
return ERR_PARSE_ERROR;
}
@@ -4328,27 +4382,28 @@ Error ShaderLanguage::_parse_global_array_size(int &r_array_size) {
return OK;
}
-Error ShaderLanguage::_parse_local_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, ArrayDeclarationNode *p_node, ArrayDeclarationNode::Declaration *p_decl, int &r_array_size, bool &r_is_unknown_size) {
+Error ShaderLanguage::_parse_local_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, Node *&r_size_expression, int &r_array_size, bool &r_is_unknown_size) {
TkPos pos = _get_tkpos();
Token tk = _get_token();
if (tk.type == TK_BRACKET_CLOSE) {
r_is_unknown_size = true;
} else {
- if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) {
+ int size = 0;
+ if (!tk.is_integer_constant() || ((int)tk.constant) <= 0) {
_set_tkpos(pos);
int array_size = 0;
Node *n = _parse_array_size(p_block, p_function_info, array_size);
if (!n) {
return ERR_PARSE_ERROR;
}
- p_decl->size = array_size;
- p_node->size_expression = n;
+ size = array_size;
+ r_size_expression = n;
} else if (((int)tk.constant) > 0) {
- p_decl->size = (uint32_t)tk.constant;
+ size = (uint32_t)tk.constant;
}
- if (p_decl->size <= 0) {
+ if (size <= 0) {
_set_error("Expected single integer constant > 0");
return ERR_PARSE_ERROR;
}
@@ -4359,7 +4414,7 @@ Error ShaderLanguage::_parse_local_array_size(BlockNode *p_block, const Function
return ERR_PARSE_ERROR;
}
- r_array_size = p_decl->size;
+ r_array_size = size;
}
return OK;
@@ -4669,6 +4724,14 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
constant->datatype = TYPE_INT;
expr = constant;
+ } else if (tk.type == TK_UINT_CONSTANT) {
+ ConstantNode *constant = alloc_node<ConstantNode>();
+ ConstantNode::Value v;
+ v.uint = tk.constant;
+ constant->values.push_back(v);
+ constant->datatype = TYPE_UINT;
+ expr = constant;
+
} else if (tk.type == TK_TRUE) {
//handle true constant
ConstantNode *constant = alloc_node<ConstantNode>();
@@ -4770,11 +4833,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (shader->structs.has(identifier)) {
pstruct = shader->structs[identifier].shader_struct;
-#ifdef DEBUG_ENABLED
- if (check_warnings && HAS_WARNING(ShaderWarning::UNUSED_STRUCT_FLAG) && used_structs.has(identifier)) {
- used_structs[identifier].used = true;
- }
-#endif // DEBUG_ENABLED
struct_init = true;
}
@@ -4916,53 +4974,104 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
for (int i = 0; i < call_function->arguments.size(); i++) {
int argidx = i + 1;
if (argidx < func->arguments.size()) {
- if (call_function->arguments[i].is_const || call_function->arguments[i].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_OUT || call_function->arguments[i].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_INOUT) {
- bool error = false;
- Node *n = func->arguments[argidx];
- if (n->type == Node::TYPE_CONSTANT || n->type == Node::TYPE_OPERATOR) {
- error = true;
+ bool error = false;
+ Node *n = func->arguments[argidx];
+ ArgumentQualifier arg_qual = call_function->arguments[i].qualifier;
+ bool is_out_arg = arg_qual != ArgumentQualifier::ARGUMENT_QUALIFIER_IN;
+
+ if (n->type == Node::TYPE_VARIABLE || n->type == Node::TYPE_ARRAY) {
+ StringName varname;
+
+ if (n->type == Node::TYPE_VARIABLE) {
+ VariableNode *vn = static_cast<VariableNode *>(n);
+ varname = vn->name;
+ } else { // TYPE_ARRAY
+ ArrayNode *an = static_cast<ArrayNode *>(n);
+ varname = an->name;
+ }
+
+ if (shader->varyings.has(varname)) {
+ switch (shader->varyings[varname].stage) {
+ case ShaderNode::Varying::STAGE_UNKNOWN: {
+ _set_error(vformat("Varying '%s' must be assigned in the vertex or fragment function first!", varname));
+ return nullptr;
+ }
+ case ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT:
+ [[fallthrough]];
+ case ShaderNode::Varying::STAGE_VERTEX:
+ if (is_out_arg && current_function != varying_function_names.vertex) { // inout/out
+ error = true;
+ }
+ break;
+ case ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT:
+ [[fallthrough]];
+ case ShaderNode::Varying::STAGE_FRAGMENT:
+ if (!is_out_arg) {
+ if (current_function != varying_function_names.fragment && current_function != varying_function_names.light) {
+ error = true;
+ }
+ } else if (current_function != varying_function_names.fragment) { // inout/out
+ error = true;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (error) {
+ _set_error(vformat("Varying '%s' cannot be passed for the '%s' parameter in that context!", varname, _get_qualifier_str(arg_qual)));
+ return nullptr;
+ }
+ }
+ }
+
+ bool is_const_arg = call_function->arguments[i].is_const;
+
+ if (is_const_arg || is_out_arg) {
+ StringName varname;
+
+ if (n->type == Node::TYPE_CONSTANT || n->type == Node::TYPE_OPERATOR || n->type == Node::TYPE_ARRAY_CONSTRUCT) {
+ if (!is_const_arg) {
+ error = true;
+ }
} else if (n->type == Node::TYPE_ARRAY) {
ArrayNode *an = static_cast<ArrayNode *>(n);
- if (an->call_expression != nullptr || an->is_const) {
+ if (!is_const_arg && (an->call_expression != nullptr || an->is_const)) {
error = true;
}
+ varname = an->name;
} else if (n->type == Node::TYPE_VARIABLE) {
VariableNode *vn = static_cast<VariableNode *>(n);
- if (vn->is_const) {
+ if (vn->is_const && !is_const_arg) {
error = true;
- } else {
- StringName varname = vn->name;
- if (shader->constants.has(varname)) {
- error = true;
- } else if (shader->uniforms.has(varname)) {
- error = true;
- } else {
- if (shader->varyings.has(varname)) {
- _set_error(vformat("Varyings cannot be passed for '%s' parameter!", _get_qualifier_str(call_function->arguments[i].qualifier)));
- return nullptr;
- }
- if (p_function_info.built_ins.has(varname)) {
- BuiltInInfo info = p_function_info.built_ins[varname];
- if (info.constant) {
- error = true;
- }
- }
- }
}
+ varname = vn->name;
} else if (n->type == Node::TYPE_MEMBER) {
MemberNode *mn = static_cast<MemberNode *>(n);
- if (mn->basetype_const) {
+ if (mn->basetype_const && is_out_arg) {
error = true;
}
}
+ if (!error && varname != StringName()) {
+ if (shader->constants.has(varname)) {
+ error = true;
+ } else if (shader->uniforms.has(varname)) {
+ error = true;
+ } else if (p_function_info.built_ins.has(varname)) {
+ BuiltInInfo info = p_function_info.built_ins[varname];
+ if (info.constant) {
+ error = true;
+ }
+ }
+ }
+
if (error) {
- _set_error(vformat("Constant value cannot be passed for '%s' parameter!", _get_qualifier_str(call_function->arguments[i].qualifier)));
+ _set_error(vformat("Constant value cannot be passed for '%s' parameter!", _get_qualifier_str(arg_qual)));
return nullptr;
}
}
if (is_sampler_type(call_function->arguments[i].type)) {
//let's see where our argument comes from
- Node *n = func->arguments[argidx];
ERR_CONTINUE(n->type != Node::TYPE_VARIABLE); //bug? this should always be a variable
VariableNode *vn = static_cast<VariableNode *>(n);
StringName varname = vn->name;
@@ -5066,9 +5175,21 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
return nullptr;
}
} else {
- if (!_validate_varying_using(shader->varyings[identifier], &error)) {
- _set_error(error);
- return nullptr;
+ ShaderNode::Varying &var = shader->varyings[identifier];
+
+ switch (var.stage) {
+ case ShaderNode::Varying::STAGE_VERTEX:
+ if (current_function == varying_function_names.fragment || current_function == varying_function_names.light) {
+ var.stage = ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT;
+ }
+ break;
+ case ShaderNode::Varying::STAGE_FRAGMENT:
+ if (current_function == varying_function_names.light) {
+ var.stage = ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT;
+ }
+ break;
+ default:
+ break;
}
}
}
@@ -5206,9 +5327,21 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expression.push_back(e);
continue;
} else {
- _set_error("Expected expression, found: " + get_token_text(tk));
- return nullptr;
- //nothing
+ if (tk.type != TK_SEMICOLON) {
+ _set_error("Expected expression, found: " + get_token_text(tk));
+ return nullptr;
+ } else {
+#ifdef DEBUG_ENABLED
+ if (check_warnings && HAS_WARNING(ShaderWarning::FORMATTING_ERROR_FLAG)) {
+ _add_line_warning(ShaderWarning::FORMATTING_ERROR, "Empty statement. Remove ';' to fix this warning.");
+ }
+#endif // DEBUG_ENABLED
+ _set_tkpos(prepos);
+
+ OperatorNode *func = alloc_node<OperatorNode>();
+ func->op = OP_EMPTY;
+ expr = func;
+ }
}
ERR_FAIL_COND_V(!expr, nullptr);
@@ -5221,7 +5354,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (tk.type == TK_CURSOR) {
//do nothing
- } else if (tk.type == TK_IDENTIFIER) {
} else if (tk.type == TK_PERIOD) {
DataType dt = expr->get_datatype();
String st = expr->get_datatype_name();
@@ -6010,7 +6142,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
ERR_FAIL_V(nullptr); //unexpected operator
}
-#if DEBUG_ENABLED
+#ifdef DEBUG_ENABLED
if (check_warnings && HAS_WARNING(ShaderWarning::FLOAT_COMPARISON_FLAG) && (op == OP_EQUAL || op == OP_NOT_EQUAL) &&
(!expression[i - 1].is_op && !expression[i + 1].is_op) &&
(expression[i - 1].node->get_datatype() == TYPE_FLOAT && expression[i + 1].node->get_datatype() == TYPE_FLOAT)) {
@@ -6071,7 +6203,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
_set_error("Invalid arguments to unary operator '" + get_operator_text(op->op) + "' :" + at);
return nullptr;
}
- expression.remove(i + 1);
+ expression.remove_at(i + 1);
}
} else if (is_ternary) {
@@ -6111,7 +6243,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
for (int i = 0; i < 4; i++) {
- expression.remove(next_op);
+ expression.remove_at(next_op);
}
} else {
@@ -6172,8 +6304,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
return nullptr;
}
- expression.remove(next_op);
- expression.remove(next_op);
+ expression.remove_at(next_op);
+ expression.remove_at(next_op);
}
}
@@ -6327,6 +6459,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
String struct_name = "";
if (is_struct) {
struct_name = tk.text;
+#ifdef DEBUG_ENABLED
+ if (check_warnings && HAS_WARNING(ShaderWarning::UNUSED_STRUCT_FLAG) && used_structs.has(struct_name)) {
+ used_structs[struct_name].used = true;
+ }
+#endif // DEBUG_ENABLED
}
bool is_const = false;
@@ -6372,49 +6509,44 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_PARSE_ERROR;
}
- tk = _get_token();
-
Node *vardecl = nullptr;
+ int array_size = 0;
+ bool fixed_array_size = false;
+ bool first = true;
- while (true) {
+ do {
bool unknown_size = false;
- int array_size = 0;
+ Node *size_expr = nullptr;
ArrayDeclarationNode *anode = nullptr;
ArrayDeclarationNode::Declaration adecl;
- if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) {
- _set_error("Expected identifier or '[' after type.");
- return ERR_PARSE_ERROR;
- }
+ tk = _get_token();
- if (tk.type == TK_BRACKET_OPEN) {
- anode = alloc_node<ArrayDeclarationNode>();
+ if (first) {
+ first = false;
- if (is_struct) {
- anode->struct_name = struct_name;
- anode->datatype = TYPE_STRUCT;
- } else {
- anode->datatype = type;
+ if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) {
+ _set_error("Expected identifier or '[' after datatype.");
+ return ERR_PARSE_ERROR;
}
- anode->precision = precision;
- anode->is_const = is_const;
- vardecl = (Node *)anode;
-
- adecl.size = 0U;
- adecl.single_expression = false;
+ if (tk.type == TK_BRACKET_OPEN) {
+ Error error = _parse_local_array_size(p_block, p_function_info, size_expr, array_size, unknown_size);
+ if (error != OK) {
+ return error;
+ }
+ adecl.single_expression = false;
+ adecl.size = array_size;
- Error error = _parse_local_array_size(p_block, p_function_info, anode, &adecl, array_size, unknown_size);
- if (error != OK) {
- return error;
+ fixed_array_size = true;
+ tk = _get_token();
}
- tk = _get_token();
+ }
- if (tk.type != TK_IDENTIFIER) {
- _set_error("Expected identifier!");
- return ERR_PARSE_ERROR;
- }
+ if (tk.type != TK_IDENTIFIER) {
+ _set_error("Expected identifier!");
+ return ERR_PARSE_ERROR;
}
StringName name = tk.text;
@@ -6452,8 +6584,10 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
tk = _get_token();
+ bool is_array_decl = var.array_size > 0 || unknown_size;
+
if (tk.type == TK_BRACKET_OPEN) {
- if (var.array_size > 0 || unknown_size) {
+ if (is_array_decl) {
_set_error("Array size is already defined!");
return ERR_PARSE_ERROR;
}
@@ -6463,28 +6597,37 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_PARSE_ERROR;
}
- anode = alloc_node<ArrayDeclarationNode>();
- if (is_struct) {
- anode->struct_name = struct_name;
- anode->datatype = TYPE_STRUCT;
- } else {
- anode->datatype = type;
+ Error error = _parse_local_array_size(p_block, p_function_info, size_expr, var.array_size, unknown_size);
+ if (error != OK) {
+ return error;
}
- anode->precision = precision;
- anode->is_const = is_const;
- vardecl = (Node *)anode;
- adecl.size = 0U;
adecl.single_expression = false;
+ adecl.size = var.array_size;
+ array_size = var.array_size;
- Error error = _parse_local_array_size(p_block, p_function_info, anode, &adecl, var.array_size, unknown_size);
- if (error != OK) {
- return error;
- }
+ is_array_decl = true;
tk = _get_token();
}
- if (var.array_size > 0 || unknown_size) {
+ if (is_array_decl) {
+ {
+ anode = alloc_node<ArrayDeclarationNode>();
+
+ if (is_struct) {
+ anode->struct_name = struct_name;
+ anode->datatype = TYPE_STRUCT;
+ } else {
+ anode->datatype = type;
+ }
+
+ anode->precision = precision;
+ anode->is_const = is_const;
+ anode->size_expression = size_expr;
+
+ vardecl = (Node *)anode;
+ }
+
bool full_def = false;
if (tk.type == TK_OP_ASSIGN) {
@@ -6702,6 +6845,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
}
+ array_size = var.array_size;
anode->declarations.push_back(adecl);
} else if (tk.type == TK_OP_ASSIGN) {
VariableDeclarationNode *node = alloc_node<VariableDeclarationNode>();
@@ -6770,22 +6914,24 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
p_block->statements.push_back(vardecl);
-
p_block->variables[name] = var;
+
+ if (!fixed_array_size) {
+ array_size = 0;
+ }
+
if (tk.type == TK_COMMA) {
if (p_block->block_type == BlockNode::BLOCK_TYPE_FOR) {
_set_error("Multiple declarations in 'for' loop are not implemented yet.");
return ERR_PARSE_ERROR;
}
- tk = _get_token();
- //another variable
} else if (tk.type == TK_SEMICOLON) {
break;
} else {
_set_error("Expected ',' or ';' after variable");
return ERR_PARSE_ERROR;
}
- }
+ } while (tk.type == TK_COMMA); //another variable
} else if (tk.type == TK_CURLY_BRACKET_OPEN) {
//a sub block, just because..
BlockNode *block = alloc_node<BlockNode>();
@@ -6838,7 +6984,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
block->parent_block = p_block;
cf->blocks.push_back(block);
err = _parse_block(block, p_function_info, true, p_can_break, p_can_continue);
-
+ if (err) {
+ return err;
+ }
} else {
_set_tkpos(pos); //rollback
}
@@ -6968,7 +7116,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
Node *n = nullptr;
- if (tk.type != TK_INT_CONSTANT) {
+ if (!tk.is_integer_constant()) {
bool correct_constant_expression = false;
DataType data_type;
@@ -6991,11 +7139,15 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
n = vn;
} else {
ConstantNode::Value v;
- v.sint = (int)tk.constant * sign;
+ if (tk.type == TK_UINT_CONSTANT) {
+ v.uint = (uint32_t)tk.constant;
+ } else {
+ v.sint = (int)tk.constant * sign;
+ }
ConstantNode *cn = alloc_node<ConstantNode>();
cn->values.push_back(v);
- cn->datatype = TYPE_INT;
+ cn->datatype = (tk.type == TK_UINT_CONSTANT ? TYPE_UINT : TYPE_INT);
n = cn;
}
@@ -7188,11 +7340,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
//check return type
BlockNode *b = p_block;
- if (b && b->parent_function && p_function_info.main_function) {
- _set_error(vformat("Using 'return' in '%s' processor function results in undefined behavior!", b->parent_function->name));
- return ERR_PARSE_ERROR;
- }
-
while (b && !b->parent_function) {
b = b->parent_block;
}
@@ -7202,6 +7349,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_BUG;
}
+ if (b && b->parent_function && p_function_info.main_function) {
+ _set_error(vformat("Using 'return' in '%s' processor function results in undefined behavior!", b->parent_function->name));
+ return ERR_PARSE_ERROR;
+ }
+
String return_struct_name = String(b->parent_function->return_struct_name);
String array_size_string;
@@ -7217,7 +7369,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (tk.type == TK_SEMICOLON) {
//all is good
if (b->parent_function->return_type != TYPE_VOID) {
- _set_error("Expected return with an expression of type '" + (return_struct_name != "" ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string + "'");
+ _set_error("Expected return with an expression of type '" + (!return_struct_name.is_empty() ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string + "'");
return ERR_PARSE_ERROR;
}
} else {
@@ -7229,7 +7381,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
if (b->parent_function->return_type != expr->get_datatype() || b->parent_function->return_array_size != expr->get_array_size() || return_struct_name != expr->get_datatype_name()) {
- _set_error("Expected return with an expression of type '" + (return_struct_name != "" ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string + "'");
+ _set_error("Expected return with an expression of type '" + (!return_struct_name.is_empty() ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string + "'");
return ERR_PARSE_ERROR;
}
@@ -7351,7 +7503,7 @@ String ShaderLanguage::_get_shader_type_list(const Set<String> &p_shader_types)
// Return a list of shader types as an human-readable string
String valid_types;
for (const Set<String>::Element *E = p_shader_types.front(); E; E = E->next()) {
- if (valid_types != String()) {
+ if (!valid_types.is_empty()) {
valid_types += ", ";
}
@@ -7402,7 +7554,7 @@ Error ShaderLanguage::_validate_datatype(DataType p_type) {
return OK;
}
-Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types) {
+Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const Set<String> &p_shader_types) {
Token tk = _get_token();
TkPos prev_pos;
@@ -7441,9 +7593,16 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
int texture_binding = 0;
int uniforms = 0;
int instance_index = 0;
+#ifdef DEBUG_ENABLED
+ int uniform_buffer_size = 0;
+ int max_uniform_buffer_size = RenderingDevice::get_singleton()->limit_get(RenderingDevice::LIMIT_MAX_UNIFORM_BUFFER_SIZE);
+#endif // DEBUG_ENABLED
ShaderNode::Uniform::Scope uniform_scope = ShaderNode::Uniform::SCOPE_LOCAL;
stages = &p_functions;
+ const FunctionInfo &constants = p_functions.has("constants") ? p_functions["constants"] : FunctionInfo();
+
+ Map<String, String> defined_modes;
while (tk.type != TK_EOF) {
switch (tk.type) {
@@ -7457,13 +7616,40 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- if (p_render_modes.find(mode) == -1) {
- _set_error("Invalid render mode: '" + String(mode) + "'");
+ const String smode = String(mode);
+
+ if (shader->render_modes.find(mode) != -1) {
+ _set_error(vformat("Duplicated render mode: '%s'.", smode));
return ERR_PARSE_ERROR;
}
- if (shader->render_modes.find(mode) != -1) {
- _set_error("Duplicate render mode: '" + String(mode) + "'");
+ bool found = false;
+
+ for (int i = 0; i < p_render_modes.size(); i++) {
+ const ModeInfo &info = p_render_modes[i];
+ const String name = String(info.name);
+
+ if (smode.begins_with(name)) {
+ if (!info.options.is_empty()) {
+ if (info.options.find(smode.substr(name.length() + 1)) != -1) {
+ found = true;
+
+ if (defined_modes.has(name)) {
+ _set_error(vformat("Redefinition of render mode: '%s'. The %s mode has already been set to '%s'.", smode, name, defined_modes[name]));
+ return ERR_PARSE_ERROR;
+ }
+ defined_modes.insert(name, smode);
+ break;
+ }
+ } else {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ _set_error(vformat("Invalid render mode: '%s'.", smode));
return ERR_PARSE_ERROR;
}
@@ -7487,7 +7673,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_IDENTIFIER) {
st.name = tk.text;
- if (shader->structs.has(st.name)) {
+ if (shader->constants.has(st.name) || shader->structs.has(st.name)) {
_set_error("Redefinition of '" + String(st.name) + "'");
return ERR_PARSE_ERROR;
}
@@ -7529,6 +7715,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (shader->structs.has(tk.text)) {
struct_name = tk.text;
+#ifdef DEBUG_ENABLED
+ if (check_warnings && HAS_WARNING(ShaderWarning::UNUSED_STRUCT_FLAG) && used_structs.has(struct_name)) {
+ used_structs[struct_name].used = true;
+ }
+#endif // DEBUG_ENABLED
struct_dt = true;
if (use_precision) {
_set_error("Precision modifier cannot be used on structs.");
@@ -7549,57 +7740,71 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
_set_error("void datatype not allowed here");
return ERR_PARSE_ERROR;
}
- tk = _get_token();
-
- if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) {
- _set_error("Expected identifier or '['.");
- return ERR_PARSE_ERROR;
- }
+ bool first = true;
+ bool fixed_array_size = false;
int array_size = 0;
- if (tk.type == TK_BRACKET_OPEN) {
- Error error = _parse_global_array_size(array_size);
- if (error != OK) {
- return error;
- }
+ do {
tk = _get_token();
- }
- if (tk.type != TK_IDENTIFIER) {
- _set_error("Expected identifier!");
- return ERR_PARSE_ERROR;
- }
+ if (first) {
+ first = false;
- MemberNode *member = alloc_node<MemberNode>();
- member->precision = precision;
- member->datatype = type;
- member->struct_name = struct_name;
- member->name = tk.text;
- member->array_size = array_size;
+ if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) {
+ _set_error("Expected identifier or '['.");
+ return ERR_PARSE_ERROR;
+ }
- if (member_names.has(member->name)) {
- _set_error("Redefinition of '" + String(member->name) + "'");
- return ERR_PARSE_ERROR;
- }
- member_names.insert(member->name);
- tk = _get_token();
+ if (tk.type == TK_BRACKET_OPEN) {
+ Error error = _parse_global_array_size(array_size, constants);
+ if (error != OK) {
+ return error;
+ }
+ fixed_array_size = true;
+ tk = _get_token();
+ }
+ }
- if (tk.type == TK_BRACKET_OPEN) {
- Error error = _parse_global_array_size(member->array_size);
- if (error != OK) {
- return error;
+ if (tk.type != TK_IDENTIFIER) {
+ _set_error("Expected identifier!");
+ return ERR_PARSE_ERROR;
+ }
+
+ MemberNode *member = alloc_node<MemberNode>();
+ member->precision = precision;
+ member->datatype = type;
+ member->struct_name = struct_name;
+ member->name = tk.text;
+ member->array_size = array_size;
+
+ if (member_names.has(member->name)) {
+ _set_error("Redefinition of '" + String(member->name) + "'");
+ return ERR_PARSE_ERROR;
}
+ member_names.insert(member->name);
tk = _get_token();
- }
- if (tk.type != TK_SEMICOLON) {
- _set_error("Expected ';'");
- return ERR_PARSE_ERROR;
- }
+ if (tk.type == TK_BRACKET_OPEN) {
+ Error error = _parse_global_array_size(member->array_size, constants);
+ if (error != OK) {
+ return error;
+ }
+ tk = _get_token();
+ }
+
+ if (!fixed_array_size) {
+ array_size = 0;
+ }
+
+ if (tk.type != TK_SEMICOLON && tk.type != TK_COMMA) {
+ _set_error("Expected ',' or ';' after struct member.");
+ return ERR_PARSE_ERROR;
+ }
- st_node->members.push_back(member);
- member_count++;
+ st_node->members.push_back(member);
+ member_count++;
+ } while (tk.type == TK_COMMA); // another member
}
}
if (member_count == 0) {
@@ -7713,7 +7918,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
if (tk.type == TK_BRACKET_OPEN) {
- Error error = _parse_global_array_size(array_size);
+ Error error = _parse_global_array_size(array_size, constants);
if (error != OK) {
return error;
}
@@ -7728,7 +7933,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
prev_pos = _get_tkpos();
name = tk.text;
- if (_find_identifier(nullptr, false, FunctionInfo(), name)) {
+ if (_find_identifier(nullptr, false, constants, name)) {
_set_error("Redefinition of '" + String(name) + "'");
return ERR_PARSE_ERROR;
}
@@ -7761,7 +7966,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- Error error = _parse_global_array_size(uniform2.array_size);
+ Error error = _parse_global_array_size(uniform2.array_size, constants);
if (error != OK) {
return error;
}
@@ -7792,6 +7997,18 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
uniform2.texture_order = -1;
if (uniform_scope != ShaderNode::Uniform::SCOPE_INSTANCE) {
uniform2.order = uniforms++;
+#ifdef DEBUG_ENABLED
+ if (uniform2.array_size > 0) {
+ int size = get_datatype_size(uniform2.type) * uniform2.array_size;
+ int m = (16 * uniform2.array_size);
+ if ((size % m) != 0U) {
+ size += m - (size % m);
+ }
+ uniform_buffer_size += size;
+ } else {
+ uniform_buffer_size += get_datatype_size(uniform2.type);
+ }
+#endif // DEBUG_ENABLED
}
}
@@ -7809,9 +8026,19 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
int custom_instance_index = -1;
if (tk.type == TK_COLON) {
+ completion_type = COMPLETION_HINT;
+ completion_base = type;
+ completion_base_array = uniform2.array_size > 0;
+
//hint
do {
tk = _get_token();
+ completion_line = tk.line;
+
+ if (!is_token_hint(tk.type)) {
+ _set_error("Expected valid type hint after ':'.");
+ return ERR_PARSE_ERROR;
+ }
if (uniform2.array_size > 0) {
if (tk.type != TK_HINT_COLOR) {
@@ -7838,8 +8065,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_A;
} else if (tk.type == TK_HINT_ROUGHNESS_GRAY) {
uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_GRAY;
- } else if (tk.type == TK_HINT_ANISO_TEXTURE) {
- uniform2.hint = ShaderNode::Uniform::HINT_ANISO;
+ } else if (tk.type == TK_HINT_ANISOTROPY_TEXTURE) {
+ uniform2.hint = ShaderNode::Uniform::HINT_ANISOTROPY;
} else if (tk.type == TK_HINT_ALBEDO_TEXTURE) {
uniform2.hint = ShaderNode::Uniform::HINT_ALBEDO;
} else if (tk.type == TK_HINT_BLACK_ALBEDO_TEXTURE) {
@@ -7872,7 +8099,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
}
- if (tk.type != TK_FLOAT_CONSTANT && tk.type != TK_INT_CONSTANT) {
+ if (tk.type != TK_FLOAT_CONSTANT && !tk.is_integer_constant()) {
_set_error("Expected integer constant");
return ERR_PARSE_ERROR;
}
@@ -7896,7 +8123,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
}
- if (tk.type != TK_FLOAT_CONSTANT && tk.type != TK_INT_CONSTANT) {
+ if (tk.type != TK_FLOAT_CONSTANT && !tk.is_integer_constant()) {
_set_error("Expected integer constant after ','");
return ERR_PARSE_ERROR;
}
@@ -7909,7 +8136,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (tk.type == TK_COMMA) {
tk = _get_token();
- if (tk.type != TK_FLOAT_CONSTANT && tk.type != TK_INT_CONSTANT) {
+ if (tk.type != TK_FLOAT_CONSTANT && !tk.is_integer_constant()) {
_set_error("Expected integer constant after ','");
return ERR_PARSE_ERROR;
}
@@ -7947,7 +8174,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- if (tk.type != TK_INT_CONSTANT) {
+ if (!tk.is_integer_constant()) {
_set_error("Expected integer constant");
return ERR_PARSE_ERROR;
}
@@ -7973,16 +8200,14 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
uniform2.filter = FILTER_NEAREST_MIPMAP;
} else if (tk.type == TK_FILTER_LINEAR_MIPMAP) {
uniform2.filter = FILTER_LINEAR_MIPMAP;
- } else if (tk.type == TK_FILTER_NEAREST_MIPMAP_ANISO) {
- uniform2.filter = FILTER_NEAREST_MIPMAP_ANISO;
- } else if (tk.type == TK_FILTER_LINEAR_MIPMAP_ANISO) {
- uniform2.filter = FILTER_LINEAR_MIPMAP_ANISO;
+ } else if (tk.type == TK_FILTER_NEAREST_MIPMAP_ANISOTROPIC) {
+ uniform2.filter = FILTER_NEAREST_MIPMAP_ANISOTROPIC;
+ } else if (tk.type == TK_FILTER_LINEAR_MIPMAP_ANISOTROPIC) {
+ uniform2.filter = FILTER_LINEAR_MIPMAP_ANISOTROPIC;
} else if (tk.type == TK_REPEAT_DISABLE) {
uniform2.repeat = REPEAT_DISABLE;
} else if (tk.type == TK_REPEAT_ENABLE) {
uniform2.repeat = REPEAT_ENABLE;
- } else {
- _set_error("Expected valid type hint after ':'.");
}
if (uniform2.hint != ShaderNode::Uniform::HINT_RANGE && uniform2.hint != ShaderNode::Uniform::HINT_NONE && uniform2.hint != ShaderNode::Uniform::HINT_COLOR && type <= TYPE_MAT4) {
@@ -8015,7 +8240,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- Node *expr = _parse_and_reduce_expression(nullptr, FunctionInfo());
+ Node *expr = _parse_and_reduce_expression(nullptr, constants);
if (!expr) {
return ERR_PARSE_ERROR;
}
@@ -8049,6 +8274,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
_set_error("Expected ';'");
return ERR_PARSE_ERROR;
}
+
+ completion_type = COMPLETION_NONE;
} else { // varying
ShaderNode::Varying varying;
varying.type = type;
@@ -8073,7 +8300,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
tk = _get_token();
- if (tk.type == TK_INT_CONSTANT && tk.constant > 0) {
+ if (tk.is_integer_constant() && tk.constant > 0) {
varying.array_size = (int)tk.constant;
tk = _get_token();
@@ -8111,7 +8338,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
DataPrecision precision = PRECISION_DEFAULT;
DataType type;
StringName name;
- int return_array_size = 0;
+ int array_size = 0;
if (tk.type == TK_CONST) {
is_constant = true;
@@ -8150,13 +8377,19 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
prev_pos = _get_tkpos();
tk = _get_token();
+ bool unknown_size = false;
+
if (tk.type == TK_BRACKET_OPEN) {
+ if (is_constant && RenderingServer::get_singleton()->is_low_end()) {
+ _set_error("Global const arrays are only supported on high-end platform!");
+ return ERR_PARSE_ERROR;
+ }
bool error = false;
tk = _get_token();
- if (tk.type == TK_INT_CONSTANT) {
- return_array_size = (int)tk.constant;
- if (return_array_size > 0) {
+ if (tk.is_integer_constant()) {
+ array_size = (int)tk.constant;
+ if (array_size > 0) {
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
_set_error("Expected ']'");
@@ -8165,11 +8398,13 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
} else {
error = true;
}
+ } else if (tk.type == TK_BRACKET_CLOSE) {
+ unknown_size = true;
} else {
error = true;
}
if (error) {
- _set_error("Expected integer constant > 0");
+ _set_error("Expected integer constant > 0 or ']'");
return ERR_PARSE_ERROR;
}
@@ -8181,16 +8416,15 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
_get_completable_identifier(nullptr, COMPLETION_MAIN_FUNCTION, name);
if (name == StringName()) {
- _set_error("Expected function name after datatype");
- return ERR_PARSE_ERROR;
- }
-
- if (_find_identifier(nullptr, false, FunctionInfo(), name)) {
- _set_error("Redefinition of '" + String(name) + "'");
+ if (is_constant) {
+ _set_error("Expected identifier or '[' after datatype.");
+ } else {
+ _set_error("Expected function name after datatype.");
+ }
return ERR_PARSE_ERROR;
}
- if (has_builtin(p_functions, name)) {
+ if (shader->structs.has(name) || _find_identifier(nullptr, false, constants, name) || has_builtin(p_functions, name)) {
_set_error("Redefinition of '" + String(name) + "'");
return ERR_PARSE_ERROR;
}
@@ -8203,7 +8437,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
//variable
-
+ bool first = true;
while (true) {
ShaderNode::Constant constant;
constant.name = name;
@@ -8211,21 +8445,23 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
constant.type_str = struct_name;
constant.precision = precision;
constant.initializer = nullptr;
- constant.array_size = 0;
-
- bool unknown_size = false;
+ constant.array_size = (first ? array_size : 0);
+ first = false;
if (tk.type == TK_BRACKET_OPEN) {
if (RenderingServer::get_singleton()->is_low_end()) {
- _set_error("Global const arrays are supported only on high-end platform!");
+ _set_error("Global const arrays are only supported on high-end platform!");
+ return ERR_PARSE_ERROR;
+ }
+ if (constant.array_size > 0 || unknown_size) {
+ _set_error("Array size is already defined!");
return ERR_PARSE_ERROR;
}
-
tk = _get_token();
if (tk.type == TK_BRACKET_CLOSE) {
unknown_size = true;
tk = _get_token();
- } else if (tk.type == TK_INT_CONSTANT && ((int)tk.constant) > 0) {
+ } else if (tk.is_integer_constant() && ((int)tk.constant) > 0) {
constant.array_size = (int)tk.constant;
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
@@ -8298,7 +8534,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
} else {
_set_tkpos(prev_pos);
- Node *n = _parse_and_reduce_expression(nullptr, FunctionInfo());
+ Node *n = _parse_and_reduce_expression(nullptr, constants);
if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
_set_error("Expected single integer constant > 0");
return ERR_PARSE_ERROR;
@@ -8379,7 +8615,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (tk.type == TK_PARENTHESIS_OPEN || curly) { // initialization
while (true) {
- Node *n = _parse_and_reduce_expression(nullptr, FunctionInfo());
+ Node *n = _parse_and_reduce_expression(nullptr, constants);
if (!n) {
return ERR_PARSE_ERROR;
}
@@ -8434,7 +8670,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
constant.initializer = static_cast<ConstantNode *>(expr);
} else {
//variable created with assignment! must parse an expression
- Node *expr = _parse_and_reduce_expression(nullptr, FunctionInfo());
+ Node *expr = _parse_and_reduce_expression(nullptr, constants);
if (!expr) {
return ERR_PARSE_ERROR;
}
@@ -8450,7 +8686,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
constant.initializer = static_cast<ConstantNode *>(expr);
- if (!_compare_datatypes(type, struct_name, 0, expr->get_datatype(), expr->get_datatype_name(), 0)) {
+ if (!_compare_datatypes(type, struct_name, 0, expr->get_datatype(), expr->get_datatype_name(), expr->get_array_size())) {
return ERR_PARSE_ERROR;
}
}
@@ -8481,7 +8717,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
name = tk.text;
- if (_find_identifier(nullptr, false, FunctionInfo(), name)) {
+ if (_find_identifier(nullptr, false, constants, name)) {
_set_error("Redefinition of '" + String(name) + "'");
return ERR_PARSE_ERROR;
}
@@ -8515,6 +8751,12 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
}
+ if (p_functions.has("constants")) { // Adds global constants: 'PI', 'TAU', 'E'
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_functions["constants"].built_ins) {
+ builtins.built_ins.insert(E.key, E.value);
+ }
+ }
+
ShaderNode::Function function;
function.callable = !p_functions.has(name);
@@ -8530,7 +8772,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
func_node->return_type = type;
func_node->return_struct_name = struct_name;
func_node->return_precision = precision;
- func_node->return_array_size = return_array_size;
+ func_node->return_array_size = array_size;
if (p_functions.has(name)) {
func_node->can_discard = p_functions[name].can_discard;
@@ -8584,7 +8826,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
StringName param_struct_name;
DataPrecision pprecision = PRECISION_DEFAULT;
bool use_precision = false;
- int array_size = 0;
+ int arg_array_size = 0;
if (is_token_precision(tk.type)) {
pprecision = get_token_precision(tk.type);
@@ -8597,6 +8839,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (shader->structs.has(tk.text)) {
is_struct = true;
param_struct_name = tk.text;
+#ifdef DEBUG_ENABLED
+ if (check_warnings && HAS_WARNING(ShaderWarning::UNUSED_STRUCT_FLAG) && used_structs.has(param_struct_name)) {
+ used_structs[param_struct_name].used = true;
+ }
+#endif // DEBUG_ENABLED
if (use_precision) {
_set_error("Precision modifier cannot be used on structs.");
return ERR_PARSE_ERROR;
@@ -8634,10 +8881,10 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
bool error = false;
tk = _get_token();
- if (tk.type == TK_INT_CONSTANT) {
- array_size = (int)tk.constant;
+ if (tk.is_integer_constant()) {
+ arg_array_size = (int)tk.constant;
- if (array_size > 0) {
+ if (arg_array_size > 0) {
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
_set_error("Expected ']'");
@@ -8689,17 +8936,17 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- if (array_size > 0) {
+ if (arg_array_size > 0) {
_set_error("Array size is already defined!");
return ERR_PARSE_ERROR;
}
bool error = false;
tk = _get_token();
- if (tk.type == TK_INT_CONSTANT) {
- array_size = (int)tk.constant;
+ if (tk.is_integer_constant()) {
+ arg_array_size = (int)tk.constant;
- if (array_size > 0) {
+ if (arg_array_size > 0) {
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
_set_error("Expected ']'");
@@ -8719,7 +8966,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
}
- arg.array_size = array_size;
+ arg.array_size = arg_array_size;
func_node->arguments.push_back(arg);
if (tk.type == TK_COMMA) {
@@ -8771,14 +9018,14 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
}
- int error_line;
- String error_message;
- if (!_check_varying_usages(&error_line, &error_message)) {
- _set_tkpos({ 0, error_line });
- _set_error(error_message);
- return ERR_PARSE_ERROR;
+#ifdef DEBUG_ENABLED
+ if (HAS_WARNING(ShaderWarning::DEVICE_LIMIT_EXCEEDED) && (uniform_buffer_size > max_uniform_buffer_size)) {
+ Vector<Variant> args;
+ args.push_back(uniform_buffer_size);
+ args.push_back(max_uniform_buffer_size);
+ _add_global_warning(ShaderWarning::DEVICE_LIMIT_EXCEEDED, "uniform buffer", args);
}
-
+#endif // DEBUG_ENABLED
return OK;
}
@@ -8898,7 +9145,7 @@ String ShaderLanguage::get_shader_type(const String &p_code) {
break;
} else if (p_code[i] <= 32) {
- if (cur_identifier != String()) {
+ if (!cur_identifier.is_empty()) {
if (!reading_type) {
if (cur_identifier != "shader_type") {
return String();
@@ -8958,17 +9205,17 @@ uint32_t ShaderLanguage::get_warning_flags() const {
}
#endif // DEBUG_ENABLED
-Error ShaderLanguage::compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const VaryingFunctionNames &p_varying_function_names, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func) {
+Error ShaderLanguage::compile(const String &p_code, const ShaderCompileInfo &p_info) {
clear();
code = p_code;
- global_var_get_type_func = p_global_variable_type_func;
- varying_function_names = p_varying_function_names;
+ global_var_get_type_func = p_info.global_variable_type_func;
+ varying_function_names = p_info.varying_function_names;
nodes = nullptr;
shader = alloc_node<ShaderNode>();
- Error err = _parse_shader(p_functions, p_render_modes, p_shader_types);
+ Error err = _parse_shader(p_info.functions, p_info.render_modes, p_info.shader_types);
#ifdef DEBUG_ENABLED
if (check_warnings) {
@@ -8982,17 +9229,17 @@ Error ShaderLanguage::compile(const String &p_code, const Map<StringName, Functi
return OK;
}
-Error ShaderLanguage::complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const VaryingFunctionNames &p_varying_function_names, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint) {
+Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_info, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint) {
clear();
code = p_code;
- varying_function_names = p_varying_function_names;
+ varying_function_names = p_info.varying_function_names;
nodes = nullptr;
- global_var_get_type_func = p_global_variable_type_func;
+ global_var_get_type_func = p_info.global_variable_type_func;
shader = alloc_node<ShaderNode>();
- _parse_shader(p_functions, p_render_modes, p_shader_types);
+ _parse_shader(p_info.functions, p_info.render_modes, p_info.shader_types);
switch (completion_type) {
case COMPLETION_NONE: {
@@ -9000,9 +9247,32 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
return OK;
} break;
case COMPLETION_RENDER_MODE: {
- for (int i = 0; i < p_render_modes.size(); i++) {
- ScriptCodeCompletionOption option(p_render_modes[i], ScriptCodeCompletionOption::KIND_ENUM);
- r_options->push_back(option);
+ for (int i = 0; i < p_info.render_modes.size(); i++) {
+ const ModeInfo &info = p_info.render_modes[i];
+
+ if (!info.options.is_empty()) {
+ bool found = false;
+
+ for (int j = 0; j < info.options.size(); j++) {
+ if (shader->render_modes.has(String(info.name) + "_" + String(info.options[j]))) {
+ found = true;
+ }
+ }
+
+ if (!found) {
+ for (int j = 0; j < info.options.size(); j++) {
+ ScriptCodeCompletionOption option(String(info.name) + "_" + String(info.options[j]), ScriptCodeCompletionOption::KIND_ENUM);
+ r_options->push_back(option);
+ }
+ }
+ } else {
+ const String name = String(info.name);
+
+ if (!shader->render_modes.has(name)) {
+ ScriptCodeCompletionOption option(name, ScriptCodeCompletionOption::KIND_ENUM);
+ r_options->push_back(option);
+ }
+ }
}
return OK;
@@ -9019,7 +9289,7 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
return OK;
} break;
case COMPLETION_MAIN_FUNCTION: {
- for (const KeyValue<StringName, FunctionInfo> &E : p_functions) {
+ for (const KeyValue<StringName, FunctionInfo> &E : p_info.functions) {
ScriptCodeCompletionOption option(E.key, ScriptCodeCompletionOption::KIND_FUNCTION);
r_options->push_back(option);
}
@@ -9055,8 +9325,8 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
}
if (comp_ident) {
- if (p_functions.has("global")) {
- for (const KeyValue<StringName, BuiltInInfo> &E : p_functions["global"].built_ins) {
+ if (p_info.functions.has("global")) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["global"].built_ins) {
ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER;
if (E.value.constant) {
kind = ScriptCodeCompletionOption::KIND_CONSTANT;
@@ -9065,8 +9335,18 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
}
}
- if (skip_function != StringName() && p_functions.has(skip_function)) {
- for (const KeyValue<StringName, BuiltInInfo> &E : p_functions[skip_function].built_ins) {
+ if (p_info.functions.has("constants")) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["constants"].built_ins) {
+ ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER;
+ if (E.value.constant) {
+ kind = ScriptCodeCompletionOption::KIND_CONSTANT;
+ }
+ matches.insert(E.key, kind);
+ }
+ }
+
+ if (skip_function != StringName() && p_info.functions.has(skip_function)) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions[skip_function].built_ins) {
ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER;
if (E.value.constant) {
kind = ScriptCodeCompletionOption::KIND_CONSTANT;
@@ -9370,15 +9650,6 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
limit = 4;
} break;
- case TYPE_MAT2:
- limit = 2;
- break;
- case TYPE_MAT3:
- limit = 3;
- break;
- case TYPE_MAT4:
- limit = 4;
- break;
default: {
}
}
@@ -9390,6 +9661,57 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
}
} break;
+ case COMPLETION_HINT: {
+ if (completion_base == DataType::TYPE_VEC4) {
+ ScriptCodeCompletionOption option("hint_color", ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+ r_options->push_back(option);
+ } else if ((completion_base == DataType::TYPE_INT || completion_base == DataType::TYPE_FLOAT) && !completion_base_array) {
+ ScriptCodeCompletionOption option("hint_range", ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+
+ if (completion_base == DataType::TYPE_INT) {
+ option.insert_text = "hint_range(0, 100, 1)";
+ } else {
+ option.insert_text = "hint_range(0.0, 1.0, 0.1)";
+ }
+
+ r_options->push_back(option);
+ } else if ((int(completion_base) > int(TYPE_MAT4) && int(completion_base) < int(TYPE_STRUCT)) && !completion_base_array) {
+ static Vector<String> options;
+
+ if (options.is_empty()) {
+ options.push_back("filter_linear");
+ options.push_back("filter_linear_mipmap");
+ options.push_back("filter_linear_mipmap_anisotropic");
+ options.push_back("filter_nearest");
+ options.push_back("filter_nearest_mipmap");
+ options.push_back("filter_nearest_mipmap_anisotropic");
+ options.push_back("hint_albedo");
+ options.push_back("hint_anisotropy");
+ options.push_back("hint_black");
+ options.push_back("hint_black_albedo");
+ options.push_back("hint_normal");
+ options.push_back("hint_roughness_a");
+ options.push_back("hint_roughness_b");
+ options.push_back("hint_roughness_g");
+ options.push_back("hint_roughness_gray");
+ options.push_back("hint_roughness_normal");
+ options.push_back("hint_roughness_r");
+ options.push_back("hint_white");
+ options.push_back("repeat_enable");
+ options.push_back("repeat_disable");
+ }
+
+ for (int i = 0; i < options.size(); i++) {
+ ScriptCodeCompletionOption option(options[i], ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+ r_options->push_back(option);
+ }
+ }
+ if (!completion_base_array) {
+ ScriptCodeCompletionOption option("instance_index", ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+ option.insert_text = "instance_index(0)";
+ r_options->push_back(option);
+ }
+ } break;
}
return ERR_PARSE_ERROR;
@@ -9411,7 +9733,7 @@ ShaderLanguage::ShaderLanguage() {
nodes = nullptr;
completion_class = TAG_GLOBAL;
-#if DEBUG_ENABLED
+#ifdef DEBUG_ENABLED
warnings_check_map.insert(ShaderWarning::UNUSED_CONSTANT, &used_constants);
warnings_check_map.insert(ShaderWarning::UNUSED_FUNCTION, &used_functions);
warnings_check_map.insert(ShaderWarning::UNUSED_STRUCT, &used_structs);
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index c82f71d10d..b9c2d4b33c 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -57,6 +57,7 @@ public:
TK_FALSE,
TK_FLOAT_CONSTANT,
TK_INT_CONSTANT,
+ TK_UINT_CONSTANT,
TK_TYPE_VOID,
TK_TYPE_BOOL,
TK_TYPE_BVEC2,
@@ -168,7 +169,7 @@ public:
TK_HINT_ROUGHNESS_B,
TK_HINT_ROUGHNESS_A,
TK_HINT_ROUGHNESS_GRAY,
- TK_HINT_ANISO_TEXTURE,
+ TK_HINT_ANISOTROPY_TEXTURE,
TK_HINT_ALBEDO_TEXTURE,
TK_HINT_BLACK_ALBEDO_TEXTURE,
TK_HINT_COLOR,
@@ -178,8 +179,8 @@ public:
TK_FILTER_LINEAR,
TK_FILTER_NEAREST_MIPMAP,
TK_FILTER_LINEAR_MIPMAP,
- TK_FILTER_NEAREST_MIPMAP_ANISO,
- TK_FILTER_LINEAR_MIPMAP_ANISO,
+ TK_FILTER_NEAREST_MIPMAP_ANISOTROPIC,
+ TK_FILTER_LINEAR_MIPMAP_ANISOTROPIC,
TK_REPEAT_ENABLE,
TK_REPEAT_DISABLE,
TK_SHADER_TYPE,
@@ -287,6 +288,7 @@ public:
OP_CONSTRUCT,
OP_STRUCT,
OP_INDEX,
+ OP_EMPTY,
OP_MAX
};
@@ -320,8 +322,8 @@ public:
FILTER_LINEAR,
FILTER_NEAREST_MIPMAP,
FILTER_LINEAR_MIPMAP,
- FILTER_NEAREST_MIPMAP_ANISO,
- FILTER_LINEAR_MIPMAP_ANISO,
+ FILTER_NEAREST_MIPMAP_ANISOTROPIC,
+ FILTER_LINEAR_MIPMAP_ANISOTROPIC,
FILTER_DEFAULT,
};
@@ -574,7 +576,7 @@ public:
virtual DataType get_datatype() const override { return datatype; }
virtual String get_datatype_name() const override { return String(struct_name); }
- virtual int get_array_size() const override { return array_size; }
+ virtual int get_array_size() const override { return (index_expression || call_expression) ? 0 : array_size; }
virtual bool is_indexed() const override { return index_expression != nullptr || call_expression != nullptr; }
MemberNode() :
@@ -680,7 +682,7 @@ public:
HINT_ROUGHNESS_GRAY,
HINT_BLACK,
HINT_WHITE,
- HINT_ANISO,
+ HINT_ANISOTROPY,
HINT_MAX
};
@@ -747,6 +749,7 @@ public:
COMPLETION_CALL_ARGUMENTS,
COMPLETION_INDEX,
COMPLETION_STRUCT,
+ COMPLETION_HINT,
};
struct Token {
@@ -754,6 +757,9 @@ public:
StringName text;
double constant;
uint16_t line;
+ bool is_integer_constant() const {
+ return type == TK_INT_CONSTANT || type == TK_UINT_CONSTANT;
+ }
};
static String get_operator_text(Operator p_op);
@@ -771,6 +777,7 @@ public:
static bool is_token_nonvoid_datatype(TokenType p_type);
static bool is_token_operator(TokenType p_type);
static bool is_token_operator_assign(TokenType p_type);
+ static bool is_token_hint(TokenType p_type);
static bool convert_constant(ConstantNode *p_constant, DataType p_to_type, ConstantNode::Value *p_value = nullptr);
static DataType get_scalar_type(DataType p_type);
@@ -780,7 +787,7 @@ public:
static bool is_sampler_type(DataType p_type);
static Variant constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type, int p_array_size, ShaderLanguage::ShaderNode::Uniform::Hint p_hint = ShaderLanguage::ShaderNode::Uniform::HINT_NONE);
static PropertyInfo uniform_to_property_info(const ShaderNode::Uniform &p_uniform);
- static uint32_t get_type_size(DataType p_type);
+ static uint32_t get_datatype_size(DataType p_type);
static void get_keyword_list(List<String> *r_keywords);
static bool is_control_flow_keyword(String p_keyword);
@@ -812,6 +819,57 @@ public:
DataType return_type = TYPE_VOID;
};
+ struct ModeInfo {
+ StringName name;
+ Vector<StringName> options;
+
+ ModeInfo() {}
+
+ ModeInfo(const StringName &p_name) :
+ name(p_name) {
+ }
+
+ ModeInfo(const StringName &p_name, const StringName &p_arg1, const StringName &p_arg2) :
+ name(p_name) {
+ options.push_back(p_arg1);
+ options.push_back(p_arg2);
+ }
+
+ ModeInfo(const StringName &p_name, const StringName &p_arg1, const StringName &p_arg2, const StringName &p_arg3) :
+ name(p_name) {
+ options.push_back(p_arg1);
+ options.push_back(p_arg2);
+ options.push_back(p_arg3);
+ }
+
+ ModeInfo(const StringName &p_name, const StringName &p_arg1, const StringName &p_arg2, const StringName &p_arg3, const StringName &p_arg4) :
+ name(p_name) {
+ options.push_back(p_arg1);
+ options.push_back(p_arg2);
+ options.push_back(p_arg3);
+ options.push_back(p_arg4);
+ }
+
+ ModeInfo(const StringName &p_name, const StringName &p_arg1, const StringName &p_arg2, const StringName &p_arg3, const StringName &p_arg4, const StringName &p_arg5) :
+ name(p_name) {
+ options.push_back(p_arg1);
+ options.push_back(p_arg2);
+ options.push_back(p_arg3);
+ options.push_back(p_arg4);
+ options.push_back(p_arg5);
+ }
+
+ ModeInfo(const StringName &p_name, const StringName &p_arg1, const StringName &p_arg2, const StringName &p_arg3, const StringName &p_arg4, const StringName &p_arg5, const StringName &p_arg6) :
+ name(p_name) {
+ options.push_back(p_arg1);
+ options.push_back(p_arg2);
+ options.push_back(p_arg3);
+ options.push_back(p_arg4);
+ options.push_back(p_arg5);
+ options.push_back(p_arg6);
+ }
+ };
+
struct FunctionInfo {
Map<StringName, BuiltInInfo> built_ins;
Map<StringName, StageFunctionInfo> stage_functions;
@@ -861,11 +919,14 @@ private:
bool check_warnings = false;
uint32_t warning_flags;
- void _add_line_warning(ShaderWarning::Code p_code, const StringName &p_subject = "") {
- warnings.push_back(ShaderWarning(p_code, tk_line, p_subject));
+ void _add_line_warning(ShaderWarning::Code p_code, const StringName &p_subject = "", const Vector<Variant> &p_extra_args = Vector<Variant>()) {
+ warnings.push_back(ShaderWarning(p_code, tk_line, p_subject, p_extra_args));
+ }
+ void _add_global_warning(ShaderWarning::Code p_code, const StringName &p_subject = "", const Vector<Variant> &p_extra_args = Vector<Variant>()) {
+ warnings.push_back(ShaderWarning(p_code, -1, p_subject, p_extra_args));
}
- void _add_warning(ShaderWarning::Code p_code, int p_line, const StringName &p_subject = "") {
- warnings.push_back(ShaderWarning(p_code, p_line, p_subject));
+ void _add_warning(ShaderWarning::Code p_code, int p_line, const StringName &p_subject = "", const Vector<Variant> &p_extra_args = Vector<Variant>()) {
+ warnings.push_back(ShaderWarning(p_code, p_line, p_subject, p_extra_args));
}
void _check_warning_accums();
#endif // DEBUG_ENABLED
@@ -880,14 +941,6 @@ private:
VaryingFunctionNames varying_function_names;
- struct VaryingUsage {
- ShaderNode::Varying *var;
- int line;
- };
- List<VaryingUsage> unknown_varying_usages;
-
- bool _check_varying_usages(int *r_error_line, String *r_error_message) const;
-
TkPos _get_tkpos() {
TkPos tkp;
tkp.char_idx = char_idx;
@@ -965,10 +1018,12 @@ private:
int completion_line;
BlockNode *completion_block;
DataType completion_base;
+ bool completion_base_array;
SubClassTag completion_class;
StringName completion_function;
StringName completion_struct;
int completion_argument;
+
const Map<StringName, FunctionInfo> *stages = nullptr;
bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier);
@@ -976,6 +1031,8 @@ private:
static const BuiltinFuncOutArgs builtin_func_out_args[];
static const BuiltinFuncConstArgs builtin_func_const_args[];
+ static bool is_const_suffix_lut_initialized;
+
Error _validate_datatype(DataType p_type);
bool _compare_datatypes(DataType p_datatype_a, String p_datatype_name_a, int p_array_size_a, DataType p_datatype_b, String p_datatype_name_b, int p_array_size_b);
bool _compare_datatypes_in_nodes(Node *a, Node *b);
@@ -985,12 +1042,11 @@ private:
bool _propagate_function_call_sampler_uniform_settings(StringName p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat);
bool _propagate_function_call_sampler_builtin_reference(StringName p_name, int p_argument, const StringName &p_builtin);
bool _validate_varying_assign(ShaderNode::Varying &p_varying, String *r_message);
- bool _validate_varying_using(ShaderNode::Varying &p_varying, String *r_message);
bool _check_node_constness(const Node *p_node) const;
Node *_parse_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, int &r_array_size);
- Error _parse_global_array_size(int &r_array_size);
- Error _parse_local_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, ArrayDeclarationNode *p_node, ArrayDeclarationNode::Declaration *p_decl, int &r_array_size, bool &r_is_unknown_size);
+ Error _parse_global_array_size(int &r_array_size, const FunctionInfo &p_function_info);
+ Error _parse_local_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, Node *&r_size_expression, int &r_array_size, bool &r_is_unknown_size);
Node *_parse_expression(BlockNode *p_block, const FunctionInfo &p_function_info);
Node *_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info);
@@ -1002,7 +1058,7 @@ private:
String _get_shader_type_list(const Set<String> &p_shader_types) const;
String _get_qualifier_str(ArgumentQualifier p_qualifier) const;
- Error _parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types);
+ Error _parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const Set<String> &p_shader_types);
Error _find_last_flow_op_in_block(BlockNode *p_block, FlowOperation p_op);
Error _find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOperation p_op);
@@ -1023,8 +1079,17 @@ public:
void clear();
static String get_shader_type(const String &p_code);
- Error compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const VaryingFunctionNames &p_varying_function_names, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func);
- Error complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const VaryingFunctionNames &p_varying_function_names, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint);
+
+ struct ShaderCompileInfo {
+ Map<StringName, FunctionInfo> functions;
+ Vector<ModeInfo> render_modes;
+ VaryingFunctionNames varying_function_names = VaryingFunctionNames();
+ Set<String> shader_types;
+ GlobalVariableGetTypeFunc global_variable_type_func = nullptr;
+ };
+
+ Error compile(const String &p_code, const ShaderCompileInfo &p_info);
+ Error complete(const String &p_code, const ShaderCompileInfo &p_info, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint);
String get_error_text();
int get_error_line();
diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp
index eb5c9e66e8..667f8b515f 100644
--- a/servers/rendering/shader_types.cpp
+++ b/servers/rendering/shader_types.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -35,7 +35,7 @@ const Map<StringName, ShaderLanguage::FunctionInfo> &ShaderTypes::get_functions(
return shader_modes[p_mode].functions;
}
-const Vector<StringName> &ShaderTypes::get_modes(RS::ShaderMode p_mode) const {
+const Vector<ShaderLanguage::ModeInfo> &ShaderTypes::get_modes(RS::ShaderMode p_mode) const {
return shader_modes[p_mode].modes;
}
@@ -59,9 +59,9 @@ ShaderTypes::ShaderTypes() {
/*************** SPATIAL ***********************/
shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC3;
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3;
@@ -190,60 +190,36 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["light"].can_discard = true;
shader_modes[RS::SHADER_SPATIAL].functions["light"].main_function = true;
- //order used puts first enum mode (default) first
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("blend_mix");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("blend_add");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("blend_sub");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("blend_mul");
-
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_draw_opaque");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_draw_always");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_draw_never");
-
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_prepass_alpha");
-
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_test_disabled");
-
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("sss_mode_skin");
-
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("cull_back");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("cull_front");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("cull_disabled");
-
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("unshaded");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("wireframe");
-
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_lambert");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_lambert_wrap");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_burley");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_toon");
-
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("specular_schlick_ggx");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("specular_blinn");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("specular_phong");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("specular_toon");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("specular_disabled");
-
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("skip_vertex_transform");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("world_vertex_coords");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("ensure_correct_normals");
-
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("shadows_disabled");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("ambient_light_disabled");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("shadow_to_opacity");
-
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("vertex_lighting");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("particle_trails");
-
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("alpha_to_coverage");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("alpha_to_coverage_and_one");
+ // spatial render modes
+ {
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "blend", "mix", "add", "sub", "mul" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "depth_draw", "opaque", "always", "never" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "depth_prepass_alpha" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "depth_test_disabled" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "sss_mode_skin" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "cull", "back", "front", "disabled" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "unshaded" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "wireframe" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "diffuse", "lambert", "lambert_wrap", "burley", "toon" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "specular", "schlick_ggx", "blinn", "phong", "toon", "disabled" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "skip_vertex_transform" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "world_vertex_coords" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "ensure_correct_normals" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "shadows_disabled" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "ambient_light_disabled" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "shadow_to_opacity" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "vertex_lighting" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "particle_trails" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "alpha_to_coverage" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "alpha_to_coverage_and_one" });
+ }
/************ CANVAS ITEM **************************/
shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC2;
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["UV"] = ShaderLanguage::TYPE_VEC2;
@@ -319,24 +295,20 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].can_discard = true;
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].main_function = true;
- shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("skip_vertex_transform");
-
- shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_mix");
- shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_add");
- shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_sub");
- shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_mul");
- shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_premul_alpha");
- shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_disabled");
-
- shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("unshaded");
- shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("light_only");
+ // canvasitem render modes
+ {
+ shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back({ "skip_vertex_transform" });
+ shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back({ "blend", "mix", "add", "sub", "mul", "premul_alpha", "disabled" });
+ shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back({ "unshaded" });
+ shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back({ "light_only" });
+ }
/************ PARTICLES **************************/
shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_PARTICLES].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_PARTICLES].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_PARTICLES].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4;
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["VELOCITY"] = ShaderLanguage::TYPE_VEC3;
@@ -367,7 +339,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["LIFETIME"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["DELTA"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["NUMBER"] = constt(ShaderLanguage::TYPE_UINT);
- shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["INDEX"] = constt(ShaderLanguage::TYPE_INT);
+ shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["INDEX"] = constt(ShaderLanguage::TYPE_UINT);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["EMISSION_TRANSFORM"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["RANDOM_SEED"] = constt(ShaderLanguage::TYPE_UINT);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["FLAG_EMIT_POSITION"] = constt(ShaderLanguage::TYPE_UINT);
@@ -392,17 +364,20 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_PARTICLES].functions["process"].stage_functions["emit_subparticle"] = emit_vertex_func;
}
- shader_modes[RS::SHADER_PARTICLES].modes.push_back("collision_use_scale");
- shader_modes[RS::SHADER_PARTICLES].modes.push_back("disable_force");
- shader_modes[RS::SHADER_PARTICLES].modes.push_back("disable_velocity");
- shader_modes[RS::SHADER_PARTICLES].modes.push_back("keep_data");
+ // particles render modes
+ {
+ shader_modes[RS::SHADER_PARTICLES].modes.push_back({ "collision_use_scale" });
+ shader_modes[RS::SHADER_PARTICLES].modes.push_back({ "disable_force" });
+ shader_modes[RS::SHADER_PARTICLES].modes.push_back({ "disable_velocity" });
+ shader_modes[RS::SHADER_PARTICLES].modes.push_back({ "keep_data" });
+ }
/************ SKY **************************/
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_SKY].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_SKY].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_SKY].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_SKY].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_SKY].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_SKY].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["POSITION"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["RADIANCE"] = constt(ShaderLanguage::TYPE_SAMPLERCUBE);
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["AT_HALF_RES_PASS"] = constt(ShaderLanguage::TYPE_BOOL);
@@ -439,16 +414,19 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SKY].functions["sky"].built_ins["FOG"] = ShaderLanguage::TYPE_VEC4;
shader_modes[RS::SHADER_SKY].functions["sky"].main_function = true;
- shader_modes[RS::SHADER_SKY].modes.push_back("use_half_res_pass");
- shader_modes[RS::SHADER_SKY].modes.push_back("use_quarter_res_pass");
- shader_modes[RS::SHADER_SKY].modes.push_back("disable_fog");
+ // sky render modes
+ {
+ shader_modes[RS::SHADER_SKY].modes.push_back({ "use_half_res_pass" });
+ shader_modes[RS::SHADER_SKY].modes.push_back({ "use_quarter_res_pass" });
+ shader_modes[RS::SHADER_SKY].modes.push_back({ "disable_fog" });
+ }
/************ FOG **************************/
shader_modes[RS::SHADER_FOG].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_FOG].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_FOG].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_FOG].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_FOG].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_FOG].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_FOG].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["WORLD_POSITION"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["OBJECT_POSITION"] = constt(ShaderLanguage::TYPE_VEC3);
diff --git a/servers/rendering/shader_types.h b/servers/rendering/shader_types.h
index 75a310a1b1..385083b670 100644
--- a/servers/rendering/shader_types.h
+++ b/servers/rendering/shader_types.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -38,7 +38,7 @@
class ShaderTypes {
struct Type {
Map<StringName, ShaderLanguage::FunctionInfo> functions;
- Vector<StringName> modes;
+ Vector<ShaderLanguage::ModeInfo> modes;
};
Map<RS::ShaderMode, Type> shader_modes;
@@ -52,7 +52,7 @@ public:
static ShaderTypes *get_singleton() { return singleton; }
const Map<StringName, ShaderLanguage::FunctionInfo> &get_functions(RS::ShaderMode p_mode) const;
- const Vector<StringName> &get_modes(RS::ShaderMode p_mode) const;
+ const Vector<ShaderLanguage::ModeInfo> &get_modes(RS::ShaderMode p_mode) const;
const Set<String> &get_types() const;
const List<String> &get_types_list() const;
diff --git a/servers/rendering/shader_warnings.cpp b/servers/rendering/shader_warnings.cpp
index 0b8476478c..f2e74c4d78 100644
--- a/servers/rendering/shader_warnings.cpp
+++ b/servers/rendering/shader_warnings.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -61,6 +61,10 @@ String ShaderWarning::get_message() const {
return vformat("The varying '%s' is declared but never used.", subject);
case UNUSED_LOCAL_VARIABLE:
return vformat("The local variable '%s' is declared but never used.", subject);
+ case FORMATTING_ERROR:
+ return subject;
+ case DEVICE_LIMIT_EXCEEDED:
+ return vformat("The total size of the %s for this shader on this device has been exceeded (%s/%s). The shader may not work correctly.", subject, (int)extra_args[0], (int)extra_args[1]);
default:
break;
}
@@ -71,6 +75,10 @@ String ShaderWarning::get_name() const {
return get_name_from_code(code);
}
+Vector<Variant> ShaderWarning::get_extra_args() const {
+ return extra_args;
+}
+
String ShaderWarning::get_name_from_code(Code p_code) {
ERR_FAIL_INDEX_V(p_code, WARNING_MAX, String());
@@ -82,6 +90,8 @@ String ShaderWarning::get_name_from_code(Code p_code) {
"UNUSED_UNIFORM",
"UNUSED_VARYING",
"UNUSED_LOCAL_VARIABLE",
+ "FORMATTING_ERROR",
+ "DEVICE_LIMIT_EXCEEDED",
};
static_assert((sizeof(names) / sizeof(*names)) == WARNING_MAX, "Amount of warning types don't match the amount of warning names.");
@@ -110,6 +120,8 @@ static void init_code_to_flags_map() {
code_to_flags_map->insert(ShaderWarning::UNUSED_UNIFORM, ShaderWarning::UNUSED_UNIFORM_FLAG);
code_to_flags_map->insert(ShaderWarning::UNUSED_VARYING, ShaderWarning::UNUSED_VARYING_FLAG);
code_to_flags_map->insert(ShaderWarning::UNUSED_LOCAL_VARIABLE, ShaderWarning::UNUSED_LOCAL_VARIABLE_FLAG);
+ code_to_flags_map->insert(ShaderWarning::FORMATTING_ERROR, ShaderWarning::FORMATTING_ERROR_FLAG);
+ code_to_flags_map->insert(ShaderWarning::DEVICE_LIMIT_EXCEEDED, ShaderWarning::DEVICE_LIMIT_EXCEEDED_FLAG);
}
ShaderWarning::CodeFlags ShaderWarning::get_flags_from_codemap(const Map<Code, bool> &p_map) {
@@ -128,8 +140,8 @@ ShaderWarning::CodeFlags ShaderWarning::get_flags_from_codemap(const Map<Code, b
return (CodeFlags)result;
}
-ShaderWarning::ShaderWarning(Code p_code, int p_line, const StringName &p_subject) :
- code(p_code), line(p_line), subject(p_subject) {
+ShaderWarning::ShaderWarning(Code p_code, int p_line, const StringName &p_subject, const Vector<Variant> &p_extra_args) :
+ code(p_code), line(p_line), subject(p_subject), extra_args(p_extra_args) {
}
#endif // DEBUG_ENABLED
diff --git a/servers/rendering/shader_warnings.h b/servers/rendering/shader_warnings.h
index db872d8fb1..e309907181 100644
--- a/servers/rendering/shader_warnings.h
+++ b/servers/rendering/shader_warnings.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,6 +36,7 @@
#include "core/string/string_name.h"
#include "core/templates/list.h"
#include "core/templates/map.h"
+#include "core/variant/variant.h"
class ShaderWarning {
public:
@@ -47,6 +48,8 @@ public:
UNUSED_UNIFORM,
UNUSED_VARYING,
UNUSED_LOCAL_VARIABLE,
+ FORMATTING_ERROR,
+ DEVICE_LIMIT_EXCEEDED,
WARNING_MAX,
};
@@ -59,12 +62,15 @@ public:
UNUSED_UNIFORM_FLAG = 16U,
UNUSED_VARYING_FLAG = 32U,
UNUSED_LOCAL_VARIABLE_FLAG = 64U,
+ FORMATTING_ERROR_FLAG = 128U,
+ DEVICE_LIMIT_EXCEEDED_FLAG = 256U,
};
private:
Code code;
int line;
StringName subject;
+ Vector<Variant> extra_args;
public:
Code get_code() const;
@@ -72,12 +78,13 @@ public:
const StringName &get_subject() const;
String get_message() const;
String get_name() const;
+ Vector<Variant> get_extra_args() const;
static String get_name_from_code(Code p_code);
static Code get_code_from_name(const String &p_name);
static CodeFlags get_flags_from_codemap(const Map<Code, bool> &p_map);
- ShaderWarning(Code p_code = WARNING_MAX, int p_line = -1, const StringName &p_subject = "");
+ ShaderWarning(Code p_code = WARNING_MAX, int p_line = -1, const StringName &p_subject = "", const Vector<Variant> &p_extra_args = Vector<Variant>());
};
#endif // DEBUG_ENABLED