Make Sky initialize shaders only once

* Create the shader on demand.
* Makes sure compilation happens only once, then shader is cached.
* Speeds up scene loading times.
* Speeds up editor initialization.
This commit is contained in:
reduz 2021-07-21 08:47:49 -03:00
parent 71f8253579
commit 67e5715dbf
3 changed files with 111 additions and 19 deletions

View File

@ -1085,6 +1085,10 @@ void unregister_scene_types() {
BaseMaterial3D::finish_shaders(); BaseMaterial3D::finish_shaders();
#endif // _3D_DISABLED #endif // _3D_DISABLED
PhysicalSkyMaterial::cleanup_shader();
PanoramaSkyMaterial::cleanup_shader();
ProceduralSkyMaterial::cleanup_shader();
ParticlesMaterial::finish_shaders(); ParticlesMaterial::finish_shaders();
CanvasItemMaterial::finish_shaders(); CanvasItemMaterial::finish_shaders();
ColorPicker::finish_shaders(); ColorPicker::finish_shaders();

View File

@ -30,6 +30,9 @@
#include "sky_material.h" #include "sky_material.h"
Mutex ProceduralSkyMaterial::shader_mutex;
RID ProceduralSkyMaterial::shader;
void ProceduralSkyMaterial::set_sky_top_color(const Color &p_sky_top) { void ProceduralSkyMaterial::set_sky_top_color(const Color &p_sky_top) {
sky_top_color = p_sky_top; sky_top_color = p_sky_top;
RS::get_singleton()->material_set_param(_get_material(), "sky_top_color", sky_top_color.to_linear()); RS::get_singleton()->material_set_param(_get_material(), "sky_top_color", sky_top_color.to_linear());
@ -128,7 +131,17 @@ Shader::Mode ProceduralSkyMaterial::get_shader_mode() const {
return Shader::MODE_SKY; return Shader::MODE_SKY;
} }
RID ProceduralSkyMaterial::get_rid() const {
_update_shader();
if (!shader_set) {
RS::get_singleton()->material_set_shader(_get_material(), shader);
shader_set = true;
}
return _get_material();
}
RID ProceduralSkyMaterial::get_shader_rid() const { RID ProceduralSkyMaterial::get_shader_rid() const {
_update_shader();
return shader; return shader;
} }
@ -180,10 +193,18 @@ void ProceduralSkyMaterial::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_curve", PROPERTY_HINT_EXP_EASING), "set_sun_curve", "get_sun_curve"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_curve", PROPERTY_HINT_EXP_EASING), "set_sun_curve", "get_sun_curve");
} }
ProceduralSkyMaterial::ProceduralSkyMaterial() { void ProceduralSkyMaterial::cleanup_shader() {
shader = RS::get_singleton()->shader_create(); if (shader.is_valid()) {
RS::get_singleton()->free(shader);
}
}
RS::get_singleton()->shader_set_code(shader, R"( void ProceduralSkyMaterial::_update_shader() {
shader_mutex.lock();
if (shader.is_null()) {
shader = RS::get_singleton()->shader_create();
RS::get_singleton()->shader_set_code(shader, R"(
shader_type sky; shader_type sky;
uniform vec4 sky_top_color : hint_color = vec4(0.35, 0.46, 0.71, 1.0); uniform vec4 sky_top_color : hint_color = vec4(0.35, 0.46, 0.71, 1.0);
@ -250,9 +271,11 @@ void sky() {
COLOR = mix(ground, sky, step(0.0, EYEDIR.y)); COLOR = mix(ground, sky, step(0.0, EYEDIR.y));
} }
)"); )");
}
shader_mutex.unlock();
}
RS::get_singleton()->material_set_shader(_get_material(), shader); ProceduralSkyMaterial::ProceduralSkyMaterial() {
set_sky_top_color(Color(0.35, 0.46, 0.71)); set_sky_top_color(Color(0.35, 0.46, 0.71));
set_sky_horizon_color(Color(0.55, 0.69, 0.81)); set_sky_horizon_color(Color(0.55, 0.69, 0.81));
set_sky_curve(0.09); set_sky_curve(0.09);
@ -268,7 +291,6 @@ void sky() {
} }
ProceduralSkyMaterial::~ProceduralSkyMaterial() { ProceduralSkyMaterial::~ProceduralSkyMaterial() {
RS::get_singleton()->free(shader);
RS::get_singleton()->material_set_shader(_get_material(), RID()); RS::get_singleton()->material_set_shader(_get_material(), RID());
} }
@ -293,7 +315,17 @@ Shader::Mode PanoramaSkyMaterial::get_shader_mode() const {
return Shader::MODE_SKY; return Shader::MODE_SKY;
} }
RID PanoramaSkyMaterial::get_rid() const {
_update_shader();
if (!shader_set) {
RS::get_singleton()->material_set_shader(_get_material(), shader);
shader_set = true;
}
return _get_material();
}
RID PanoramaSkyMaterial::get_shader_rid() const { RID PanoramaSkyMaterial::get_shader_rid() const {
_update_shader();
return shader; return shader;
} }
@ -304,10 +336,21 @@ void PanoramaSkyMaterial::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "panorama", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_panorama", "get_panorama"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "panorama", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_panorama", "get_panorama");
} }
PanoramaSkyMaterial::PanoramaSkyMaterial() { Mutex PanoramaSkyMaterial::shader_mutex;
shader = RS::get_singleton()->shader_create(); RID PanoramaSkyMaterial::shader;
RS::get_singleton()->shader_set_code(shader, R"( void PanoramaSkyMaterial::cleanup_shader() {
if (shader.is_valid()) {
RS::get_singleton()->free(shader);
}
}
void PanoramaSkyMaterial::_update_shader() {
shader_mutex.lock();
if (shader.is_null()) {
shader = RS::get_singleton()->shader_create();
RS::get_singleton()->shader_set_code(shader, R"(
shader_type sky; shader_type sky;
uniform sampler2D source_panorama : filter_linear; uniform sampler2D source_panorama : filter_linear;
@ -316,12 +359,15 @@ void sky() {
COLOR = texture(source_panorama, SKY_COORDS).rgb; COLOR = texture(source_panorama, SKY_COORDS).rgb;
} }
)"); )");
}
RS::get_singleton()->material_set_shader(_get_material(), shader); shader_mutex.unlock();
}
PanoramaSkyMaterial::PanoramaSkyMaterial() {
} }
PanoramaSkyMaterial::~PanoramaSkyMaterial() { PanoramaSkyMaterial::~PanoramaSkyMaterial() {
RS::get_singleton()->free(shader);
RS::get_singleton()->material_set_shader(_get_material(), RID()); RS::get_singleton()->material_set_shader(_get_material(), RID());
} }
@ -436,10 +482,23 @@ Shader::Mode PhysicalSkyMaterial::get_shader_mode() const {
return Shader::MODE_SKY; return Shader::MODE_SKY;
} }
RID PhysicalSkyMaterial::get_rid() const {
_update_shader();
if (!shader_set) {
RS::get_singleton()->material_set_shader(_get_material(), shader);
shader_set = true;
}
return _get_material();
}
RID PhysicalSkyMaterial::get_shader_rid() const { RID PhysicalSkyMaterial::get_shader_rid() const {
_update_shader();
return shader; return shader;
} }
Mutex PhysicalSkyMaterial::shader_mutex;
RID PhysicalSkyMaterial::shader;
void PhysicalSkyMaterial::_bind_methods() { void PhysicalSkyMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_rayleigh_coefficient", "rayleigh"), &PhysicalSkyMaterial::set_rayleigh_coefficient); ClassDB::bind_method(D_METHOD("set_rayleigh_coefficient", "rayleigh"), &PhysicalSkyMaterial::set_rayleigh_coefficient);
ClassDB::bind_method(D_METHOD("get_rayleigh_coefficient"), &PhysicalSkyMaterial::get_rayleigh_coefficient); ClassDB::bind_method(D_METHOD("get_rayleigh_coefficient"), &PhysicalSkyMaterial::get_rayleigh_coefficient);
@ -491,10 +550,18 @@ void PhysicalSkyMaterial::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "night_sky", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_night_sky", "get_night_sky"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "night_sky", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_night_sky", "get_night_sky");
} }
PhysicalSkyMaterial::PhysicalSkyMaterial() { void PhysicalSkyMaterial::cleanup_shader() {
shader = RS::get_singleton()->shader_create(); if (shader.is_valid()) {
RS::get_singleton()->free(shader);
}
}
RS::get_singleton()->shader_set_code(shader, R"( void PhysicalSkyMaterial::_update_shader() {
shader_mutex.lock();
if (shader.is_null()) {
shader = RS::get_singleton()->shader_create();
RS::get_singleton()->shader_set_code(shader, R"(
shader_type sky; shader_type sky;
uniform float rayleigh : hint_range(0, 64) = 2.0; uniform float rayleigh : hint_range(0, 64) = 2.0;
@ -588,9 +655,12 @@ void sky() {
} }
} }
)"); )");
}
RS::get_singleton()->material_set_shader(_get_material(), shader); shader_mutex.unlock();
}
PhysicalSkyMaterial::PhysicalSkyMaterial() {
set_rayleigh_coefficient(2.0); set_rayleigh_coefficient(2.0);
set_rayleigh_color(Color(0.056, 0.14, 0.3)); set_rayleigh_color(Color(0.056, 0.14, 0.3));
set_mie_coefficient(0.005); set_mie_coefficient(0.005);
@ -604,5 +674,4 @@ void sky() {
} }
PhysicalSkyMaterial::~PhysicalSkyMaterial() { PhysicalSkyMaterial::~PhysicalSkyMaterial() {
RS::get_singleton()->free(shader);
} }

View File

@ -51,7 +51,10 @@ private:
float sun_angle_max; float sun_angle_max;
float sun_curve; float sun_curve;
RID shader; static Mutex shader_mutex;
static RID shader;
static void _update_shader();
mutable bool shader_set = false;
protected: protected:
static void _bind_methods(); static void _bind_methods();
@ -90,6 +93,9 @@ public:
virtual Shader::Mode get_shader_mode() const override; virtual Shader::Mode get_shader_mode() const override;
virtual RID get_shader_rid() const override; virtual RID get_shader_rid() const override;
virtual RID get_rid() const override;
static void cleanup_shader();
ProceduralSkyMaterial(); ProceduralSkyMaterial();
~ProceduralSkyMaterial(); ~ProceduralSkyMaterial();
@ -103,7 +109,11 @@ class PanoramaSkyMaterial : public Material {
private: private:
Ref<Texture2D> panorama; Ref<Texture2D> panorama;
RID shader;
static Mutex shader_mutex;
static RID shader;
static void _update_shader();
mutable bool shader_set = false;
protected: protected:
static void _bind_methods(); static void _bind_methods();
@ -115,6 +125,9 @@ public:
virtual Shader::Mode get_shader_mode() const override; virtual Shader::Mode get_shader_mode() const override;
virtual RID get_shader_rid() const override; virtual RID get_shader_rid() const override;
virtual RID get_rid() const override;
static void cleanup_shader();
PanoramaSkyMaterial(); PanoramaSkyMaterial();
~PanoramaSkyMaterial(); ~PanoramaSkyMaterial();
@ -127,7 +140,8 @@ class PhysicalSkyMaterial : public Material {
GDCLASS(PhysicalSkyMaterial, Material); GDCLASS(PhysicalSkyMaterial, Material);
private: private:
RID shader; static Mutex shader_mutex;
static RID shader;
float rayleigh; float rayleigh;
Color rayleigh_color; Color rayleigh_color;
@ -140,6 +154,8 @@ private:
float exposure; float exposure;
float dither_strength; float dither_strength;
Ref<Texture2D> night_sky; Ref<Texture2D> night_sky;
static void _update_shader();
mutable bool shader_set = false;
protected: protected:
static void _bind_methods(); static void _bind_methods();
@ -182,6 +198,9 @@ public:
virtual Shader::Mode get_shader_mode() const override; virtual Shader::Mode get_shader_mode() const override;
virtual RID get_shader_rid() const override; virtual RID get_shader_rid() const override;
static void cleanup_shader();
virtual RID get_rid() const override;
PhysicalSkyMaterial(); PhysicalSkyMaterial();
~PhysicalSkyMaterial(); ~PhysicalSkyMaterial();
}; };