feat: updated engine version to 4.4-rc1

This commit is contained in:
Sara 2025-02-23 14:38:14 +01:00
parent ee00efde1f
commit 21ba8e33af
5459 changed files with 1128836 additions and 198305 deletions

View file

@ -1,4 +1,5 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
Import("env")

View file

@ -33,9 +33,7 @@
#include "core/templates/paged_allocator.h"
#include "servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h"
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/utilities.h"
#define RB_SCOPE_MOBILE SNAME("mobile")
@ -59,32 +57,6 @@ private:
MATERIAL_UNIFORM_SET = 3,
};
enum {
SPEC_CONSTANT_USING_PROJECTOR = 0,
SPEC_CONSTANT_USING_SOFT_SHADOWS = 1,
SPEC_CONSTANT_USING_DIRECTIONAL_SOFT_SHADOWS = 2,
SPEC_CONSTANT_SOFT_SHADOW_SAMPLES = 3,
SPEC_CONSTANT_PENUMBRA_SHADOW_SAMPLES = 4,
SPEC_CONSTANT_DIRECTIONAL_SOFT_SHADOW_SAMPLES = 5,
SPEC_CONSTANT_DIRECTIONAL_PENUMBRA_SHADOW_SAMPLES = 6,
SPEC_CONSTANT_DECAL_USE_MIPMAPS = 7,
SPEC_CONSTANT_PROJECTOR_USE_MIPMAPS = 8,
SPEC_CONSTANT_DISABLE_OMNI_LIGHTS = 9,
SPEC_CONSTANT_DISABLE_SPOT_LIGHTS = 10,
SPEC_CONSTANT_DISABLE_REFLECTION_PROBES = 11,
SPEC_CONSTANT_DISABLE_DIRECTIONAL_LIGHTS = 12,
SPEC_CONSTANT_DISABLE_DECALS = 13,
SPEC_CONSTANT_DISABLE_FOG = 14,
SPEC_CONSTANT_USE_DEPTH_FOG = 16,
SPEC_CONSTANT_IS_MULTIMESH = 17,
};
enum {
MAX_LIGHTMAPS = 8,
MAX_RDL_CULL = 8, // maximum number of reflection probes, decals or lights we can cull per geometry instance
@ -152,14 +124,14 @@ private:
RID render_pass_uniform_set;
bool force_wireframe = false;
Vector2 uv_offset;
uint32_t spec_constant_base_flags = 0;
SceneShaderForwardMobile::ShaderSpecialization base_specialization;
float lod_distance_multiplier = 0.0;
float screen_mesh_lod_threshold = 0.0;
RD::FramebufferFormatID framebuffer_format = 0;
uint32_t element_offset = 0;
uint32_t subpass = 0;
RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_render_pass_uniform_set, uint32_t p_spec_constant_base_flags = 0, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0) {
RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_render_pass_uniform_set, SceneShaderForwardMobile::ShaderSpecialization p_base_specialization, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0) {
elements = p_elements;
element_info = p_element_info;
element_count = p_element_count;
@ -173,7 +145,7 @@ private:
lod_distance_multiplier = p_lod_distance_multiplier;
screen_mesh_lod_threshold = p_screen_mesh_lod_threshold;
element_offset = p_element_offset;
spec_constant_base_flags = p_spec_constant_base_flags;
base_specialization = p_base_specialization;
}
};
@ -208,8 +180,9 @@ private:
struct LightmapData {
float normal_xform[12];
float pad[3];
float texture_size[2];
float exposure_normalization;
uint32_t flags;
};
struct LightmapCaptureData {
@ -221,10 +194,16 @@ private:
struct SceneState {
LocalVector<RID> uniform_buffers;
struct PushConstantUbershader {
SceneShaderForwardMobile::ShaderSpecialization specialization;
SceneShaderForwardMobile::UbershaderConstants constants;
};
struct PushConstant {
float uv_offset[2];
uint32_t base_index;
uint32_t pad;
PushConstantUbershader ubershader;
};
struct InstanceData {
@ -263,6 +242,7 @@ private:
bool used_normal_texture = false;
bool used_depth_texture = false;
bool used_sss = false;
bool used_lightmap = false;
struct ShadowPass {
uint32_t element_from;
@ -275,8 +255,8 @@ private:
float screen_mesh_lod_threshold;
RID framebuffer;
RD::InitialAction initial_depth_action;
Rect2i rect;
bool clear_depth;
};
LocalVector<ShadowPass> shadow_passes;
@ -350,7 +330,7 @@ private:
template <PassMode p_pass_mode>
_FORCE_INLINE_ void _render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element);
void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element);
void _render_list_with_draw_list(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 0.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2());
void _render_list_with_draw_list(RenderListParameters *p_params, RID p_framebuffer, BitField<RD::DrawFlags> p_clear_colors = RD::DRAW_DEFAULT_ALL, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth_value = 0.0, uint32_t p_clear_stencil_value = 0, const Rect2 &p_region = Rect2());
RenderList render_list[RENDER_LIST_MAX];
@ -365,12 +345,12 @@ protected:
virtual RID _render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override;
virtual RID _render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override;
virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override{};
virtual void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override{};
virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override{};
virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {}
virtual void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {}
virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override {}
virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override{};
virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override{};
virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override {}
virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override {}
/* Geometry instance */
@ -378,6 +358,7 @@ protected:
// When changing any of these enums, remember to change the corresponding enums in the shader files as well.
enum {
INSTANCE_DATA_FLAG_MULTIMESH_INDIRECT = 1 << 2,
INSTANCE_DATA_FLAGS_DYNAMIC = 1 << 3,
INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 4,
INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 5,
@ -416,6 +397,10 @@ protected:
};
union {
struct {
uint64_t sort_key1;
uint64_t sort_key2;
};
struct {
// !BAS! CHECK BITS!!!
@ -432,10 +417,6 @@ protected:
// uint64_t lod_index : 8; // no need to sort on LOD
// uint64_t uses_forward_gi : 1; // no GI here, remove
};
struct {
uint64_t sort_key1;
uint64_t sort_key2;
};
} sort;
RS::PrimitiveType primitive = RS::PRIMITIVE_MAX;
@ -454,6 +435,12 @@ protected:
GeometryInstanceSurfaceDataCache *next = nullptr;
GeometryInstanceForwardMobile *owner = nullptr;
SelfList<GeometryInstanceSurfaceDataCache> compilation_dirty_element;
SelfList<GeometryInstanceSurfaceDataCache> compilation_all_element;
GeometryInstanceSurfaceDataCache() :
compilation_dirty_element(this), compilation_all_element(this) {}
};
class GeometryInstanceForwardMobile : public RenderGeometryInstanceBase {
@ -541,6 +528,14 @@ protected:
return forward_id_storage_mobile;
}
struct ForwardIDByMapSort {
uint8_t map;
RendererRD::ForwardID forward_id;
bool operator<(const ForwardIDByMapSort &p_sort) const {
return map > p_sort.map;
}
};
public:
static RenderForwardMobile *get_singleton() { return singleton; }
@ -559,24 +554,79 @@ public:
static void _geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker);
SelfList<GeometryInstanceForwardMobile>::List geometry_instance_dirty_list;
SelfList<GeometryInstanceSurfaceDataCache>::List geometry_surface_compilation_dirty_list;
SelfList<GeometryInstanceSurfaceDataCache>::List geometry_surface_compilation_all_list;
PagedAllocator<GeometryInstanceForwardMobile> geometry_instance_alloc;
PagedAllocator<GeometryInstanceSurfaceDataCache> geometry_instance_surface_alloc;
PagedAllocator<GeometryInstanceLightmapSH> geometry_instance_lightmap_sh;
struct SurfacePipelineData {
void *mesh_surface = nullptr;
void *mesh_surface_shadow = nullptr;
SceneShaderForwardMobile::ShaderData *shader = nullptr;
SceneShaderForwardMobile::ShaderData *shader_shadow = nullptr;
bool instanced = false;
bool uses_opaque = false;
bool uses_transparent = false;
bool uses_depth = false;
bool can_use_lightmap = false;
};
struct GlobalPipelineData {
union {
uint32_t key;
struct {
uint32_t texture_samples : 3;
uint32_t target_samples : 3;
uint32_t use_reflection_probes : 1;
uint32_t use_lightmaps : 1;
uint32_t use_multiview : 1;
uint32_t use_16_bit_shadows : 1;
uint32_t use_32_bit_shadows : 1;
uint32_t use_shadow_cubemaps : 1;
uint32_t use_shadow_dual_paraboloid : 1;
uint32_t use_vrs : 1;
uint32_t use_subpass_post_pass : 1;
uint32_t use_separate_post_pass : 1;
uint32_t use_hdr_render_target : 1;
uint32_t use_ldr_render_target : 1;
};
};
};
GlobalPipelineData global_pipeline_data_compiled = {};
GlobalPipelineData global_pipeline_data_required = {};
typedef Pair<SceneShaderForwardMobile::ShaderData *, SceneShaderForwardMobile::ShaderData::PipelineKey> ShaderPipelinePair;
void _update_global_pipeline_data_requirements_from_project();
void _update_global_pipeline_data_requirements_from_light_storage();
void _geometry_instance_add_surface_with_material(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh);
void _geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, RID p_mat_src, RID p_mesh);
void _geometry_instance_add_surface(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, RID p_material, RID p_mesh);
void _geometry_instance_update(RenderGeometryInstance *p_geometry_instance);
void _mesh_compile_pipeline_for_surface(SceneShaderForwardMobile::ShaderData *p_shader, void *p_mesh_surface, bool p_instanced_surface, RS::PipelineSource p_source, SceneShaderForwardMobile::ShaderData::PipelineKey &r_pipeline_key, Vector<ShaderPipelinePair> *r_pipeline_pairs = nullptr);
void _mesh_compile_pipelines_for_surface(const SurfacePipelineData &p_surface, const GlobalPipelineData &p_global, RS::PipelineSource p_source, Vector<ShaderPipelinePair> *r_pipeline_pairs = nullptr);
void _mesh_generate_all_pipelines_for_surface_cache(GeometryInstanceSurfaceDataCache *p_surface_cache, const GlobalPipelineData &p_global);
void _update_dirty_geometry_instances();
void _update_dirty_geometry_pipelines();
virtual RenderGeometryInstance *geometry_instance_create(RID p_base) override;
virtual void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) override;
virtual uint32_t geometry_instance_get_pair_mask() override;
/* PIPELINES */
virtual void mesh_generate_pipelines(RID p_mesh, bool p_background_compilation) override;
virtual uint32_t get_pipeline_compilations(RS::PipelineSource p_source) override;
virtual bool free(RID p_rid) override;
virtual void update() override;
virtual void base_uniforms_changed() override;
virtual bool is_dynamic_gi_supported() const override;

View file

@ -43,9 +43,9 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
//compile
code = p_code;
valid = false;
ubo_size = 0;
uniforms.clear();
_clear_vertex_input_mask_cache();
if (code.is_empty()) {
return; //just invalid, but no error
@ -53,10 +53,10 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
ShaderCompiler::GeneratedCode gen_code;
int blend_mode = BLEND_MODE_MIX;
int depth_testi = DEPTH_TEST_ENABLED;
int alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
int cull = CULL_BACK;
blend_mode = BLEND_MODE_MIX;
depth_testi = DEPTH_TEST_ENABLED;
alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
cull_mode = RS::CULL_MODE_BACK;
uses_point_size = false;
uses_alpha = false;
@ -68,8 +68,8 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
uses_roughness = false;
uses_normal = false;
uses_tangent = false;
bool uses_normal_map = false;
bool wireframe = false;
uses_normal_map = false;
wireframe = false;
unshaded = false;
uses_vertex = false;
@ -91,7 +91,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MIX);
actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_mode, BLEND_MODE_SUB);
actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MUL);
actions.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&blend_mode, BLEND_MODE_PREMULT_ALPHA);
actions.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&blend_mode, BLEND_MODE_PREMULTIPLIED_ALPHA);
actions.render_mode_values["alpha_to_coverage"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE);
actions.render_mode_values["alpha_to_coverage_and_one"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE);
@ -102,9 +102,9 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
actions.render_mode_values["depth_test_disabled"] = Pair<int *, int>(&depth_testi, DEPTH_TEST_DISABLED);
actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull, CULL_DISABLED);
actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull, CULL_FRONT);
actions.render_mode_values["cull_back"] = Pair<int *, int>(&cull, CULL_BACK);
actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull_mode, RS::CULL_MODE_DISABLED);
actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull_mode, RS::CULL_MODE_FRONT);
actions.render_mode_values["cull_back"] = Pair<int *, int>(&cull_mode, RS::CULL_MODE_BACK);
actions.render_mode_flags["unshaded"] = &unshaded;
actions.render_mode_flags["wireframe"] = &wireframe;
@ -141,13 +141,19 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
actions.uniforms = &uniforms;
SceneShaderForwardMobile *shader_singleton = (SceneShaderForwardMobile *)SceneShaderForwardMobile::singleton;
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
Error err = SceneShaderForwardMobile::singleton->compiler.compile(RS::SHADER_SPATIAL, code, &actions, path, gen_code);
Error err = shader_singleton->compiler.compile(RS::SHADER_SPATIAL, code, &actions, path, gen_code);
ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
if (err != OK) {
if (version.is_valid()) {
SceneShaderForwardMobile::singleton->shader.version_free(version);
version = RID();
}
ERR_FAIL_MSG("Shader compilation failed.");
}
if (version.is_null()) {
version = shader_singleton->shader.version_create();
version = SceneShaderForwardMobile::singleton->shader.version_create();
}
depth_draw = DepthDraw(depth_drawi);
@ -163,11 +169,11 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
#ifdef DEBUG_ENABLED
if (uses_sss) {
WARN_PRINT_ONCE_ED("Sub-surface scattering is only available when using the Forward+ rendering backend.");
WARN_PRINT_ONCE_ED("Subsurface scattering is only available when using the Forward+ renderer.");
}
if (uses_transmittance) {
WARN_PRINT_ONCE_ED("Transmittance is only available when using the Forward+ rendering backend.");
WARN_PRINT_ONCE_ED("Transmittance is only available when using the Forward+ renderer.");
}
#endif
@ -189,86 +195,62 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]);
#endif
shader_singleton->shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines);
ERR_FAIL_COND(!shader_singleton->shader.version_is_valid(version));
SceneShaderForwardMobile::singleton->shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines);
ubo_size = gen_code.uniform_total_size;
ubo_offsets = gen_code.uniform_offsets;
texture_uniforms = gen_code.texture_uniforms;
//blend modes
pipeline_hash_map.clear_pipelines();
// if any form of Alpha Antialiasing is enabled, set the blend mode to alpha to coverage
// If any form of Alpha Antialiasing is enabled, set the blend mode to alpha to coverage.
if (alpha_antialiasing_mode != ALPHA_ANTIALIASING_OFF) {
blend_mode = BLEND_MODE_ALPHA_TO_COVERAGE;
}
RD::PipelineColorBlendState::Attachment blend_attachment;
uses_blend_alpha = blend_mode_uses_blend_alpha(BlendMode(blend_mode));
}
switch (blend_mode) {
case BLEND_MODE_MIX: {
blend_attachment.enable_blend = true;
blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
bool SceneShaderForwardMobile::ShaderData::is_animated() const {
return (uses_fragment_time && uses_discard) || (uses_vertex_time && uses_vertex);
}
} break;
case BLEND_MODE_ADD: {
blend_attachment.enable_blend = true;
blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE;
blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
uses_blend_alpha = true; //force alpha used because of blend
bool SceneShaderForwardMobile::ShaderData::casts_shadows() const {
bool has_read_screen_alpha = uses_screen_texture || uses_depth_texture || uses_normal_texture;
bool has_base_alpha = (uses_alpha && (!uses_alpha_clip || uses_alpha_antialiasing)) || has_read_screen_alpha;
bool has_alpha = has_base_alpha || uses_blend_alpha;
} break;
case BLEND_MODE_SUB: {
blend_attachment.enable_blend = true;
blend_attachment.alpha_blend_op = RD::BLEND_OP_REVERSE_SUBTRACT;
blend_attachment.color_blend_op = RD::BLEND_OP_REVERSE_SUBTRACT;
blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE;
blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
uses_blend_alpha = true; //force alpha used because of blend
return !has_alpha || (uses_depth_prepass_alpha && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test == DEPTH_TEST_DISABLED));
}
} break;
case BLEND_MODE_MUL: {
blend_attachment.enable_blend = true;
blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_DST_COLOR;
blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ZERO;
blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_DST_ALPHA;
blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO;
uses_blend_alpha = true; //force alpha used because of blend
} break;
case BLEND_MODE_ALPHA_TO_COVERAGE: {
blend_attachment.enable_blend = true;
blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO;
} break;
case BLEND_MODE_PREMULT_ALPHA: {
blend_attachment.enable_blend = true;
blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_ONE;
blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
uses_blend_alpha = true; // Force alpha used because of blend.
} break;
RS::ShaderNativeSourceCode SceneShaderForwardMobile::ShaderData::get_native_source_code() const {
if (version.is_valid()) {
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
return SceneShaderForwardMobile::singleton->shader.version_get_native_source_code(version);
} else {
return RS::ShaderNativeSourceCode();
}
}
void SceneShaderForwardMobile::ShaderData::_create_pipeline(PipelineKey p_pipeline_key) {
#if PRINT_PIPELINE_COMPILATION_KEYS
print_line(
"HASH:", p_pipeline_key.hash(),
"VERSION:", version,
"VERTEX:", p_pipeline_key.vertex_format_id,
"FRAMEBUFFER:", p_pipeline_key.framebuffer_format_id,
"CULL:", p_pipeline_key.cull_mode,
"PRIMITIVE:", p_pipeline_key.primitive_type,
"VERSION:", p_pipeline_key.version,
"SPEC PACKED #0:", p_pipeline_key.shader_specialization.packed_0,
"SPEC PACKED #1:", p_pipeline_key.shader_specialization.packed_1,
"SPEC PACKED #2:", p_pipeline_key.shader_specialization.packed_2,
"SPEC PACKED #3:", p_pipeline_key.shader_specialization.packed_3,
"RENDER PASS:", p_pipeline_key.render_pass,
"WIREFRAME:", p_pipeline_key.wireframe);
#endif
RD::PipelineColorBlendState::Attachment blend_attachment = blend_mode_to_blend_attachment(BlendMode(blend_mode));
RD::PipelineColorBlendState blend_state_blend;
blend_state_blend.attachments.push_back(blend_attachment);
RD::PipelineColorBlendState blend_state_opaque = RD::PipelineColorBlendState::create_disabled(1);
@ -286,113 +268,161 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
depth_stencil_state.enable_depth_write = depth_draw != DEPTH_DRAW_DISABLED ? true : false;
}
for (int i = 0; i < CULL_VARIANT_MAX; i++) {
RD::PolygonCullMode cull_mode_rd_table[CULL_VARIANT_MAX][3] = {
{ RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_FRONT, RD::POLYGON_CULL_BACK },
{ RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_BACK, RD::POLYGON_CULL_FRONT },
{ RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED }
};
RD::RenderPrimitive primitive_rd_table[RS::PRIMITIVE_MAX] = {
RD::RENDER_PRIMITIVE_POINTS,
RD::RENDER_PRIMITIVE_LINES,
RD::RENDER_PRIMITIVE_LINESTRIPS,
RD::RENDER_PRIMITIVE_TRIANGLES,
RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS,
};
RD::PolygonCullMode cull_mode_rd = cull_mode_rd_table[i][cull];
RD::RenderPrimitive primitive_rd = uses_point_size ? RD::RENDER_PRIMITIVE_POINTS : primitive_rd_table[p_pipeline_key.primitive_type];
for (int j = 0; j < RS::PRIMITIVE_MAX; j++) {
RD::RenderPrimitive primitive_rd_table[RS::PRIMITIVE_MAX] = {
RD::RENDER_PRIMITIVE_POINTS,
RD::RENDER_PRIMITIVE_LINES,
RD::RENDER_PRIMITIVE_LINESTRIPS,
RD::RENDER_PRIMITIVE_TRIANGLES,
RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS,
};
RD::PipelineRasterizationState raster_state;
raster_state.cull_mode = p_pipeline_key.cull_mode;
raster_state.wireframe = wireframe || p_pipeline_key.wireframe;
RD::RenderPrimitive primitive_rd = uses_point_size ? RD::RENDER_PRIMITIVE_POINTS : primitive_rd_table[j];
RD::PipelineMultisampleState multisample_state;
multisample_state.sample_count = RD::get_singleton()->framebuffer_format_get_texture_samples(p_pipeline_key.framebuffer_format_id, 0);
for (int k = 0; k < SHADER_VERSION_MAX; k++) {
if (!static_cast<SceneShaderForwardMobile *>(singleton)->shader.is_variant_enabled(k)) {
continue;
}
RD::PipelineRasterizationState raster_state;
raster_state.cull_mode = cull_mode_rd;
raster_state.wireframe = wireframe;
RD::PipelineColorBlendState blend_state;
if (uses_alpha || uses_blend_alpha) {
// These flags should only go through if we have some form of MSAA.
if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) {
multisample_state.enable_alpha_to_coverage = true;
} else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) {
multisample_state.enable_alpha_to_coverage = true;
multisample_state.enable_alpha_to_one = true;
}
RD::PipelineColorBlendState blend_state;
RD::PipelineDepthStencilState depth_stencil = depth_stencil_state;
RD::PipelineMultisampleState multisample_state;
if (uses_alpha || uses_blend_alpha) {
// only allow these flags to go through if we have some form of msaa
if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) {
multisample_state.enable_alpha_to_coverage = true;
} else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) {
multisample_state.enable_alpha_to_coverage = true;
multisample_state.enable_alpha_to_one = true;
}
if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_MULTIVIEW || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW) {
blend_state = blend_state_blend;
if (depth_draw == DEPTH_DRAW_OPAQUE && !uses_alpha_clip) {
depth_stencil.enable_depth_write = false; //alpha does not draw depth
}
} else if (k == SHADER_VERSION_SHADOW_PASS || k == SHADER_VERSION_SHADOW_PASS_MULTIVIEW || k == SHADER_VERSION_SHADOW_PASS_DP) {
//none, blend state contains nothing
} else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) {
blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
} else {
pipelines[i][j][k].clear();
continue; // do not use this version (will error if using it is attempted)
}
} else {
if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_MULTIVIEW || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW) {
blend_state = blend_state_opaque;
} else if (k == SHADER_VERSION_SHADOW_PASS || k == SHADER_VERSION_SHADOW_PASS_MULTIVIEW || k == SHADER_VERSION_SHADOW_PASS_DP) {
//none, leave empty
} else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) {
blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
} else {
// ???
}
}
RID shader_variant = shader_singleton->shader.version_get_shader(version, k);
pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants);
if (p_pipeline_key.version == SHADER_VERSION_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_COLOR_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW) {
blend_state = blend_state_blend;
if (depth_draw == DEPTH_DRAW_OPAQUE && !uses_alpha_clip) {
// Alpha does not write to depth.
depth_stencil_state.enable_depth_write = false;
}
} else if (p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS || p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS_DP) {
// Contains nothing.
} else if (p_pipeline_key.version == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) {
// Writes to normal and roughness in opaque way.
blend_state = RD::PipelineColorBlendState::create_disabled(5);
} else {
// Do not use this version (error case).
}
} else {
if (p_pipeline_key.version == SHADER_VERSION_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_COLOR_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW) {
blend_state = blend_state_opaque;
} else if (p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS || p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS_DP) {
// Contains nothing.
} else if (p_pipeline_key.version == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) {
// Writes to normal and roughness in opaque way.
blend_state = RD::PipelineColorBlendState::create_disabled(5);
} else {
// Unknown pipeline version.
}
}
valid = true;
// Convert the specialization from the key to pipeline specialization constants.
Vector<RD::PipelineSpecializationConstant> specialization_constants;
RD::PipelineSpecializationConstant sc;
sc.constant_id = 0;
sc.int_value = p_pipeline_key.shader_specialization.packed_0;
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
specialization_constants.push_back(sc);
sc.constant_id = 1;
sc.int_value = p_pipeline_key.shader_specialization.packed_1;
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
specialization_constants.push_back(sc);
sc.constant_id = 2;
sc.int_value = p_pipeline_key.shader_specialization.packed_2;
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
specialization_constants.push_back(sc);
sc.constant_id = 3;
sc.float_value = p_pipeline_key.shader_specialization.packed_3;
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT;
specialization_constants.push_back(sc);
RID shader_rid = get_shader_variant(p_pipeline_key.version, p_pipeline_key.ubershader);
ERR_FAIL_COND(shader_rid.is_null());
RID pipeline = RD::get_singleton()->render_pipeline_create(shader_rid, p_pipeline_key.framebuffer_format_id, p_pipeline_key.vertex_format_id, primitive_rd, raster_state, multisample_state, depth_stencil_state, blend_state, 0, p_pipeline_key.render_pass, specialization_constants);
ERR_FAIL_COND(pipeline.is_null());
pipeline_hash_map.add_compiled_pipeline(p_pipeline_key.hash(), pipeline);
}
bool SceneShaderForwardMobile::ShaderData::is_animated() const {
return (uses_fragment_time && uses_discard) || (uses_vertex_time && uses_vertex);
RD::PolygonCullMode SceneShaderForwardMobile::ShaderData::get_cull_mode_from_cull_variant(CullVariant p_cull_variant) {
const RD::PolygonCullMode cull_mode_rd_table[CULL_VARIANT_MAX][3] = {
{ RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_FRONT, RD::POLYGON_CULL_BACK },
{ RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_BACK, RD::POLYGON_CULL_FRONT },
{ RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED }
};
return cull_mode_rd_table[p_cull_variant][cull_mode];
}
bool SceneShaderForwardMobile::ShaderData::casts_shadows() const {
bool has_read_screen_alpha = uses_screen_texture || uses_depth_texture || uses_normal_texture;
bool has_base_alpha = (uses_alpha && (!uses_alpha_clip || uses_alpha_antialiasing)) || has_read_screen_alpha;
bool has_alpha = has_base_alpha || uses_blend_alpha;
return !has_alpha || (uses_depth_prepass_alpha && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test == DEPTH_TEST_DISABLED));
void SceneShaderForwardMobile::ShaderData::_clear_vertex_input_mask_cache() {
for (uint32_t i = 0; i < VERTEX_INPUT_MASKS_SIZE; i++) {
vertex_input_masks[i].store(0);
}
}
RS::ShaderNativeSourceCode SceneShaderForwardMobile::ShaderData::get_native_source_code() const {
SceneShaderForwardMobile *shader_singleton = (SceneShaderForwardMobile *)SceneShaderForwardMobile::singleton;
RID SceneShaderForwardMobile::ShaderData::get_shader_variant(ShaderVersion p_shader_version, bool p_ubershader) const {
if (version.is_valid()) {
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
ERR_FAIL_NULL_V(SceneShaderForwardMobile::singleton, RID());
return SceneShaderForwardMobile::singleton->shader.version_get_shader(version, p_shader_version + (p_ubershader ? SHADER_VERSION_MAX : 0));
} else {
return RID();
}
}
return shader_singleton->shader.version_get_native_source_code(version);
uint64_t SceneShaderForwardMobile::ShaderData::get_vertex_input_mask(ShaderVersion p_shader_version, bool p_ubershader) {
// Vertex input masks require knowledge of the shader. Since querying the shader can be expensive due to high contention and the necessary mutex, we cache the result instead.
uint32_t input_mask_index = p_shader_version + (p_ubershader ? SHADER_VERSION_MAX : 0);
uint64_t input_mask = vertex_input_masks[input_mask_index].load(std::memory_order_relaxed);
if (input_mask == 0) {
RID shader_rid = get_shader_variant(p_shader_version, p_ubershader);
ERR_FAIL_COND_V(shader_rid.is_null(), 0);
input_mask = RD::get_singleton()->shader_get_vertex_input_attribute_mask(shader_rid);
vertex_input_masks[input_mask_index].store(input_mask, std::memory_order_relaxed);
}
return input_mask;
}
bool SceneShaderForwardMobile::ShaderData::is_valid() const {
if (version.is_valid()) {
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
ERR_FAIL_NULL_V(SceneShaderForwardMobile::singleton, false);
return SceneShaderForwardMobile::singleton->shader.version_is_valid(version);
} else {
return false;
}
}
SceneShaderForwardMobile::ShaderData::ShaderData() :
shader_list_element(this) {
pipeline_hash_map.set_creation_object_and_function(this, &ShaderData::_create_pipeline);
pipeline_hash_map.set_compilations(SceneShaderForwardMobile::singleton->pipeline_compilations, &SceneShaderForwardMobile::singleton_mutex);
}
SceneShaderForwardMobile::ShaderData::~ShaderData() {
SceneShaderForwardMobile *shader_singleton = (SceneShaderForwardMobile *)SceneShaderForwardMobile::singleton;
ERR_FAIL_NULL(shader_singleton);
//pipeline variants will clear themselves if shader is gone
pipeline_hash_map.clear_pipelines();
if (version.is_valid()) {
shader_singleton->shader.version_free(version);
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
ERR_FAIL_NULL(SceneShaderForwardMobile::singleton);
SceneShaderForwardMobile::singleton->shader.version_free(version);
}
}
RendererRD::MaterialStorage::ShaderData *SceneShaderForwardMobile::_create_shader_func() {
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
ShaderData *shader_data = memnew(ShaderData);
singleton->shader_list.add(&shader_data->shader_list_element);
return shader_data;
@ -407,9 +437,12 @@ void SceneShaderForwardMobile::MaterialData::set_next_pass(RID p_pass) {
}
bool SceneShaderForwardMobile::MaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
SceneShaderForwardMobile *shader_singleton = (SceneShaderForwardMobile *)SceneShaderForwardMobile::singleton;
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardMobile::MATERIAL_UNIFORM_SET, true, true);
if (shader_data->version.is_valid()) {
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, SceneShaderForwardMobile::singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardMobile::MATERIAL_UNIFORM_SET, true, true);
} else {
return false;
}
}
SceneShaderForwardMobile::MaterialData::~MaterialData() {
@ -426,6 +459,7 @@ RendererRD::MaterialStorage::MaterialData *SceneShaderForwardMobile::_create_mat
/* Scene Shader */
SceneShaderForwardMobile *SceneShaderForwardMobile::singleton = nullptr;
Mutex SceneShaderForwardMobile::singleton_mutex;
SceneShaderForwardMobile::SceneShaderForwardMobile() {
// there should be only one of these, contained within our RenderForwardMobile singleton.
@ -435,27 +469,48 @@ SceneShaderForwardMobile::SceneShaderForwardMobile() {
void SceneShaderForwardMobile::init(const String p_defines) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
// Immutable samplers : create the shadow sampler to be passed when creating the pipeline.
{
RD::SamplerState sampler;
sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
sampler.enable_compare = true;
sampler.compare_op = RD::COMPARE_OP_GREATER;
shadow_sampler = RD::get_singleton()->sampler_create(sampler);
}
/* SCENE SHADER */
{
Vector<String> shader_versions;
shader_versions.push_back(""); // SHADER_VERSION_COLOR_PASS
shader_versions.push_back("\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_SHADOW_PASS, should probably change this to MODE_RENDER_SHADOW because we don't have a depth pass here...
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n"); // SHADER_VERSION_SHADOW_PASS_DP
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
for (uint32_t ubershader = 0; ubershader < 2; ubershader++) {
const String base_define = ubershader ? "\n#define UBERSHADER\n" : "";
shader_versions.push_back(base_define + ""); // SHADER_VERSION_COLOR_PASS
shader_versions.push_back(base_define + "\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS
shader_versions.push_back(base_define + "\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_SHADOW_PASS, should probably change this to MODE_RENDER_SHADOW because we don't have a depth pass here...
shader_versions.push_back(base_define + "\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n"); // SHADER_VERSION_SHADOW_PASS_DP
shader_versions.push_back(base_define + "\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
// multiview versions of our shaders
shader_versions.push_back("\n#define USE_MULTIVIEW\n"); // SHADER_VERSION_COLOR_PASS_MULTIVIEW
shader_versions.push_back("\n#define USE_MULTIVIEW\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW
shader_versions.push_back("\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_SHADOW_PASS_MULTIVIEW
shader.initialize(shader_versions, p_defines);
// Multiview versions of our shaders.
shader_versions.push_back(base_define + "\n#define USE_MULTIVIEW\n"); // SHADER_VERSION_COLOR_PASS_MULTIVIEW
shader_versions.push_back(base_define + "\n#define USE_MULTIVIEW\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW
shader_versions.push_back(base_define + "\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_SHADOW_PASS_MULTIVIEW
}
Vector<RD::PipelineImmutableSampler> immutable_samplers;
RD::PipelineImmutableSampler immutable_shadow_sampler;
immutable_shadow_sampler.binding = 2;
immutable_shadow_sampler.append_id(shadow_sampler);
immutable_shadow_sampler.uniform_type = RenderingDeviceCommons::UNIFORM_TYPE_SAMPLER;
immutable_samplers.push_back(immutable_shadow_sampler);
shader.initialize(shader_versions, p_defines, immutable_samplers);
if (!RendererCompositorRD::get_singleton()->is_xr_enabled()) {
shader.set_variant_enabled(SHADER_VERSION_COLOR_PASS_MULTIVIEW, false);
shader.set_variant_enabled(SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW, false);
shader.set_variant_enabled(SHADER_VERSION_SHADOW_PASS_MULTIVIEW, false);
for (uint32_t ubershader = 0; ubershader < 2; ubershader++) {
uint32_t base_variant = ubershader ? SHADER_VERSION_MAX : 0;
shader.set_variant_enabled(base_variant + SHADER_VERSION_COLOR_PASS_MULTIVIEW, false);
shader.set_variant_enabled(base_variant + SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW, false);
shader.set_variant_enabled(base_variant + SHADER_VERSION_SHADOW_PASS_MULTIVIEW, false);
}
}
}
@ -500,6 +555,8 @@ void SceneShaderForwardMobile::init(const String p_defines) {
actions.renames["PI"] = _MKSTR(Math_PI);
actions.renames["TAU"] = _MKSTR(Math_TAU);
actions.renames["E"] = _MKSTR(Math_E);
actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
actions.renames["CLIP_SPACE_FAR"] = "SHADER_SPACE_FAR";
actions.renames["VIEWPORT_SIZE"] = "read_viewport_size";
actions.renames["FRAGCOORD"] = "gl_FragCoord";
@ -539,7 +596,6 @@ void SceneShaderForwardMobile::init(const String p_defines) {
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["LIGHT_VERTEX"] = "light_vertex";
actions.renames["NODE_POSITION_WORLD"] = "read_model_matrix[3].xyz";
@ -632,6 +688,13 @@ void SceneShaderForwardMobile::init(const String p_defines) {
actions.render_mode_defines["ambient_light_disabled"] = "#define AMBIENT_LIGHT_DISABLED\n";
actions.render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n";
actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n";
bool force_vertex_shading = GLOBAL_GET("rendering/shading/overrides/force_vertex_shading");
if (!force_vertex_shading) {
// If forcing vertex shading, this will be defined already.
actions.render_mode_defines["vertex_lighting"] = "#define USE_VERTEX_LIGHTING\n";
}
actions.render_mode_defines["debug_shadow_splits"] = "#define DEBUG_DRAW_PSSM_SPLITS\n";
actions.render_mode_defines["fog_disabled"] = "#define FOG_DISABLED\n";
@ -741,27 +804,23 @@ void fragment() {
default_vec4_xform_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RenderForwardMobile::TRANSFORMS_UNIFORM_SET);
}
{
RD::SamplerState sampler;
sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
sampler.enable_compare = true;
sampler.compare_op = RD::COMPARE_OP_GREATER;
shadow_sampler = RD::get_singleton()->sampler_create(sampler);
}
void SceneShaderForwardMobile::set_default_specialization(const ShaderSpecialization &p_specialization) {
default_specialization = p_specialization;
for (SelfList<ShaderData> *E = shader_list.first(); E; E = E->next()) {
E->self()->pipeline_hash_map.clear_pipelines();
}
}
void SceneShaderForwardMobile::set_default_specialization_constants(const Vector<RD::PipelineSpecializationConstant> &p_constants) {
default_specialization_constants = p_constants;
for (SelfList<ShaderData> *E = shader_list.first(); E; E = E->next()) {
for (int i = 0; i < ShaderData::CULL_VARIANT_MAX; i++) {
for (int j = 0; j < RS::PRIMITIVE_MAX; j++) {
for (int k = 0; k < SHADER_VERSION_MAX; k++) {
E->self()->pipelines[i][j][k].update_specialization_constants(default_specialization_constants);
}
}
}
}
uint32_t SceneShaderForwardMobile::get_pipeline_compilations(RS::PipelineSource p_source) {
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
return pipeline_compilations[p_source];
}
bool SceneShaderForwardMobile::is_multiview_enabled() const {
return shader.is_variant_enabled(SHADER_VERSION_COLOR_PASS_MULTIVIEW);
}
SceneShaderForwardMobile::~SceneShaderForwardMobile() {

View file

@ -31,7 +31,8 @@
#ifndef SCENE_SHADER_FORWARD_MOBILE_H
#define SCENE_SHADER_FORWARD_MOBILE_H
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
#include "../storage_rd/material_storage.h"
#include "servers/rendering/renderer_rd/pipeline_hash_map_rd.h"
#include "servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl.gen.h"
namespace RendererSceneRenderImplementation {
@ -39,6 +40,7 @@ namespace RendererSceneRenderImplementation {
class SceneShaderForwardMobile {
private:
static SceneShaderForwardMobile *singleton;
static Mutex singleton_mutex;
public:
enum ShaderVersion {
@ -55,16 +57,79 @@ public:
SHADER_VERSION_MAX
};
struct ShaderData : public RendererRD::MaterialStorage::ShaderData {
enum BlendMode { //used internally
BLEND_MODE_MIX,
BLEND_MODE_ADD,
BLEND_MODE_SUB,
BLEND_MODE_MUL,
BLEND_MODE_PREMULT_ALPHA,
BLEND_MODE_ALPHA_TO_COVERAGE
struct ShaderSpecialization {
union {
uint32_t packed_0;
struct {
uint32_t use_light_projector : 1;
uint32_t use_light_soft_shadows : 1;
uint32_t use_directional_soft_shadows : 1;
uint32_t decal_use_mipmaps : 1;
uint32_t projector_use_mipmaps : 1;
uint32_t disable_fog : 1;
uint32_t use_depth_fog : 1;
uint32_t use_fog_aerial_perspective : 1;
uint32_t use_fog_sun_scatter : 1;
uint32_t use_fog_height_density : 1;
uint32_t use_lightmap_bicubic_filter : 1;
uint32_t multimesh : 1;
uint32_t multimesh_format_2d : 1;
uint32_t multimesh_has_color : 1;
uint32_t multimesh_has_custom_data : 1;
uint32_t scene_use_ambient_cubemap : 1;
uint32_t scene_use_reflection_cubemap : 1;
uint32_t scene_roughness_limiter_enabled : 1;
uint32_t padding_0 : 2;
uint32_t soft_shadow_samples : 6;
uint32_t penumbra_shadow_samples : 6;
};
};
union {
uint32_t packed_1;
struct {
uint32_t directional_soft_shadow_samples : 6;
uint32_t directional_penumbra_shadow_samples : 6;
uint32_t omni_lights : 4;
uint32_t spot_lights : 4;
uint32_t reflection_probes : 4;
uint32_t directional_lights : 4;
uint32_t decals : 4;
};
};
union {
uint32_t packed_2;
struct {
uint32_t directional_light_blend_splits : 8;
uint32_t padding_1 : 24;
};
};
union {
float packed_3;
float luminance_multiplier;
};
};
struct UbershaderConstants {
union {
uint32_t packed_0;
struct {
uint32_t cull_mode : 2;
};
};
uint32_t padding_1;
uint32_t padding_2;
uint32_t padding_3;
};
struct ShaderData : public RendererRD::MaterialStorage::ShaderData {
enum DepthDraw {
DEPTH_DRAW_DISABLED,
DEPTH_DRAW_OPAQUE,
@ -76,12 +141,6 @@ public:
DEPTH_TEST_ENABLED
};
enum Cull {
CULL_DISABLED,
CULL_FRONT,
CULL_BACK
};
enum CullVariant {
CULL_VARIANT_NORMAL,
CULL_VARIANT_REVERSED,
@ -96,10 +155,41 @@ public:
ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE
};
bool valid = false;
struct PipelineKey {
RD::VertexFormatID vertex_format_id;
RD::FramebufferFormatID framebuffer_format_id;
RD::PolygonCullMode cull_mode = RD::POLYGON_CULL_MAX;
RS::PrimitiveType primitive_type = RS::PRIMITIVE_MAX;
ShaderSpecialization shader_specialization = {};
ShaderVersion version = SHADER_VERSION_MAX;
uint32_t render_pass = 0;
uint32_t wireframe = false;
uint32_t ubershader = false;
uint32_t hash() const {
uint32_t h = hash_murmur3_one_32(vertex_format_id);
h = hash_murmur3_one_32(framebuffer_format_id, h);
h = hash_murmur3_one_32(cull_mode, h);
h = hash_murmur3_one_32(primitive_type, h);
h = hash_murmur3_one_32(shader_specialization.packed_0, h);
h = hash_murmur3_one_32(shader_specialization.packed_1, h);
h = hash_murmur3_one_32(shader_specialization.packed_2, h);
h = hash_murmur3_one_float(shader_specialization.packed_3, h);
h = hash_murmur3_one_32(version, h);
h = hash_murmur3_one_32(render_pass, h);
h = hash_murmur3_one_32(wireframe, h);
h = hash_murmur3_one_32(ubershader, h);
return hash_fmix32(h);
}
};
void _create_pipeline(PipelineKey p_pipeline_key);
PipelineHashMapRD<PipelineKey, ShaderData, void (ShaderData::*)(PipelineKey)> pipeline_hash_map;
RID version;
uint64_t vertex_input_mask = 0;
PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][SHADER_VERSION_MAX];
static const uint32_t VERTEX_INPUT_MASKS_SIZE = SHADER_VERSION_MAX * 2;
std::atomic<uint64_t> vertex_input_masks[VERTEX_INPUT_MASKS_SIZE] = {};
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
@ -111,6 +201,11 @@ public:
DepthDraw depth_draw;
DepthTest depth_test;
int blend_mode = BLEND_MODE_MIX;
int depth_testi = DEPTH_TEST_ENABLED;
int alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
int cull_mode = RS::CULL_MODE_BACK;
bool uses_point_size = false;
bool uses_alpha = false;
bool uses_blend_alpha = false;
@ -122,6 +217,8 @@ public:
bool uses_normal = false;
bool uses_tangent = false;
bool uses_particle_trails = false;
bool uses_normal_map = false;
bool wireframe = false;
bool unshaded = false;
bool uses_vertex = false;
@ -140,10 +237,35 @@ public:
uint64_t last_pass = 0;
uint32_t index = 0;
_FORCE_INLINE_ bool uses_alpha_pass() const {
bool has_read_screen_alpha = uses_screen_texture || uses_depth_texture || uses_normal_texture;
bool has_base_alpha = (uses_alpha && (!uses_alpha_clip || uses_alpha_antialiasing));
bool has_blend_alpha = uses_blend_alpha;
bool has_alpha = has_base_alpha || has_blend_alpha;
bool no_depth_draw = depth_draw == DEPTH_DRAW_DISABLED;
bool no_depth_test = depth_test == DEPTH_TEST_DISABLED;
return has_alpha || has_read_screen_alpha || no_depth_draw || no_depth_test;
}
_FORCE_INLINE_ bool uses_depth_in_alpha_pass() const {
bool no_depth_draw = depth_draw == DEPTH_DRAW_DISABLED;
bool no_depth_test = depth_test == DEPTH_TEST_DISABLED;
return (uses_depth_prepass_alpha || uses_alpha_antialiasing) && !(no_depth_draw || no_depth_test);
}
_FORCE_INLINE_ bool uses_shared_shadow_material() const {
return !uses_particle_trails && !writes_modelview_or_projection && !uses_vertex && !uses_discard && !uses_depth_prepass_alpha && !uses_alpha_clip && !uses_alpha_antialiasing && !uses_world_coordinates && !wireframe;
}
virtual void set_code(const String &p_Code);
virtual bool is_animated() const;
virtual bool casts_shadows() const;
virtual RS::ShaderNativeSourceCode get_native_source_code() const;
RD::PolygonCullMode get_cull_mode_from_cull_variant(CullVariant p_cull_variant);
void _clear_vertex_input_mask_cache();
RID get_shader_variant(ShaderVersion p_shader_version, bool p_ubershader) const;
uint64_t get_vertex_input_mask(ShaderVersion p_shader_version, bool p_ubershader);
bool is_valid() const;
SelfList<ShaderData> shader_list_element;
@ -204,10 +326,14 @@ public:
SceneShaderForwardMobile();
~SceneShaderForwardMobile();
Vector<RD::PipelineSpecializationConstant> default_specialization_constants;
ShaderSpecialization default_specialization = {};
uint32_t pipeline_compilations[RS::PIPELINE_SOURCE_MAX] = {};
void init(const String p_defines);
void set_default_specialization_constants(const Vector<RD::PipelineSpecializationConstant> &p_constants);
void set_default_specialization(const ShaderSpecialization &p_specialization);
uint32_t get_pipeline_compilations(RS::PipelineSource p_source);
bool is_multiview_enabled() const;
};
} // namespace RendererSceneRenderImplementation