1
0
mirror of https://github.com/godotengine/godot.git synced 2025-12-04 17:04:49 +00:00

Optimize Mobile renderer by using FP16 explicitly.

This commit is contained in:
Dario
2025-05-28 11:58:07 -03:00
parent 8f87e60307
commit 46277836a6
23 changed files with 938 additions and 786 deletions

View File

@@ -380,6 +380,14 @@ uint32_t RenderForwardMobile::get_pipeline_compilations(RS::PipelineSource p_sou
}
void RenderForwardMobile::enable_features(BitField<FeatureBits> p_feature_bits) {
if (p_feature_bits.has_flag(FEATURE_FP32_BIT)) {
scene_shader.enable_fp32_shader_group();
}
if (p_feature_bits.has_flag(FEATURE_FP16_BIT)) {
scene_shader.enable_fp16_shader_group();
}
if (p_feature_bits.has_flag(FEATURE_MULTIVIEW_BIT)) {
scene_shader.enable_multiview_shader_group();
}

View File

@@ -381,7 +381,7 @@ RID SceneShaderForwardMobile::ShaderData::get_shader_variant(ShaderVersion p_sha
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));
return SceneShaderForwardMobile::singleton->shader.version_get_shader(version, p_shader_version + (SceneShaderForwardMobile::singleton->use_fp16 ? SHADER_VERSION_MAX * 2 : 0) + (p_ubershader ? SHADER_VERSION_MAX : 0));
} else {
return RID();
}
@@ -389,6 +389,7 @@ RID SceneShaderForwardMobile::ShaderData::get_shader_variant(ShaderVersion p_sha
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.
// It is intentional for the range of the input masks to be different than the versions available in the shaders as it'll only ever use the regular variants or the FP16 ones.
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) {
@@ -446,7 +447,8 @@ 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) {
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);
RID base_shader = SceneShaderForwardMobile::singleton->shader.version_get_shader(shader_data->version, (SceneShaderForwardMobile::singleton->use_fp16 ? SHADER_VERSION_MAX * 2 : 0));
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, base_shader, RenderForwardMobile::MATERIAL_UNIFORM_SET, true, true);
} else {
return false;
}
@@ -476,6 +478,9 @@ SceneShaderForwardMobile::SceneShaderForwardMobile() {
void SceneShaderForwardMobile::init(const String p_defines) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
// Store whether the shader will prefer using the FP16 variant.
use_fp16 = RD::get_singleton()->has_feature(RD::SUPPORTS_HALF_FLOAT);
// Immutable samplers : create the shadow sampler to be passed when creating the pipeline.
{
RD::SamplerState sampler;
@@ -490,19 +495,26 @@ void SceneShaderForwardMobile::init(const String p_defines) {
{
Vector<ShaderRD::VariantDefine> shader_versions;
for (uint32_t ubershader = 0; ubershader < 2; ubershader++) {
const String base_define = ubershader ? "\n#define UBERSHADER\n" : "";
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_BASE, base_define + "", true)); // SHADER_VERSION_COLOR_PASS
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_BASE, base_define + "\n#define USE_LIGHTMAP\n", true)); // SHADER_VERSION_LIGHTMAP_COLOR_PASS
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_BASE, base_define + "\n#define MODE_RENDER_DEPTH\n#define SHADOW_PASS\n", true)); // 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(ShaderRD::VariantDefine(SHADER_GROUP_BASE, base_define + "\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n#define SHADOW_PASS\n", true)); // SHADER_VERSION_SHADOW_PASS_DP
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_BASE, base_define + "\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n", true)); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
for (uint32_t fp16 = 0; fp16 < 2; fp16++) {
for (uint32_t ubershader = 0; ubershader < 2; ubershader++) {
String base_define = fp16 ? "\n#define EXPLICIT_FP16\n" : "";
int shader_group = fp16 ? SHADER_GROUP_FP16 : SHADER_GROUP_FP32;
int shader_group_multiview = fp16 ? SHADER_GROUP_FP16_MULTIVIEW : SHADER_GROUP_FP32_MULTIVIEW;
base_define += ubershader ? "\n#define UBERSHADER\n" : "";
// Multiview versions of our shaders.
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, base_define + "\n#define USE_MULTIVIEW\n", false)); // SHADER_VERSION_COLOR_PASS_MULTIVIEW
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, base_define + "\n#define USE_MULTIVIEW\n#define USE_LIGHTMAP\n", false)); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, base_define + "\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n#define SHADOW_PASS\n", false)); // SHADER_VERSION_SHADOW_PASS_MULTIVIEW
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, base_define + "\n#define USE_MULTIVIEW\n#define MODE_RENDER_MOTION_VECTORS\n", false)); // SHADER_VERSION_MOTION_VECTORS_MULTIVIEW
bool default_enabled = (uint32_t(use_fp16) == fp16);
shader_versions.push_back(ShaderRD::VariantDefine(shader_group, base_define + "", default_enabled)); // SHADER_VERSION_COLOR_PASS
shader_versions.push_back(ShaderRD::VariantDefine(shader_group, base_define + "\n#define USE_LIGHTMAP\n", default_enabled)); // SHADER_VERSION_LIGHTMAP_COLOR_PASS
shader_versions.push_back(ShaderRD::VariantDefine(shader_group, base_define + "\n#define MODE_RENDER_DEPTH\n#define SHADOW_PASS\n", default_enabled)); // 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(ShaderRD::VariantDefine(shader_group, base_define + "\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n#define SHADOW_PASS\n", default_enabled)); // SHADER_VERSION_SHADOW_PASS_DP
shader_versions.push_back(ShaderRD::VariantDefine(shader_group, base_define + "\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n", default_enabled)); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
// Multiview versions of our shaders.
shader_versions.push_back(ShaderRD::VariantDefine(shader_group_multiview, base_define + "\n#define USE_MULTIVIEW\n", false)); // SHADER_VERSION_COLOR_PASS_MULTIVIEW
shader_versions.push_back(ShaderRD::VariantDefine(shader_group_multiview, base_define + "\n#define USE_MULTIVIEW\n#define USE_LIGHTMAP\n", false)); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW
shader_versions.push_back(ShaderRD::VariantDefine(shader_group_multiview, base_define + "\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n#define SHADOW_PASS\n", false)); // SHADER_VERSION_SHADOW_PASS_MULTIVIEW
shader_versions.push_back(ShaderRD::VariantDefine(shader_group_multiview, base_define + "\n#define USE_MULTIVIEW\n#define MODE_RENDER_MOTION_VECTORS\n", false)); // SHADER_VERSION_MOTION_VECTORS_MULTIVIEW
}
}
Vector<RD::PipelineImmutableSampler> immutable_samplers;
@@ -514,7 +526,7 @@ void SceneShaderForwardMobile::init(const String p_defines) {
shader.initialize(shader_versions, p_defines, immutable_samplers);
if (RendererCompositorRD::get_singleton()->is_xr_enabled()) {
shader.enable_group(SHADER_GROUP_MULTIVIEW);
enable_multiview_shader_group();
}
}
@@ -536,21 +548,21 @@ void SceneShaderForwardMobile::init(const String p_defines) {
actions.renames["MAIN_CAM_INV_VIEW_MATRIX"] = "scene_data.main_cam_inv_view_matrix";
actions.renames["VERTEX"] = "vertex";
actions.renames["NORMAL"] = "normal";
actions.renames["TANGENT"] = "tangent";
actions.renames["BINORMAL"] = "binormal";
actions.renames["NORMAL"] = "normal_highp";
actions.renames["TANGENT"] = "tangent_highp";
actions.renames["BINORMAL"] = "binormal_highp";
actions.renames["POSITION"] = "position";
actions.renames["UV"] = "uv_interp";
actions.renames["UV2"] = "uv2_interp";
actions.renames["COLOR"] = "color_interp";
actions.renames["COLOR"] = "color_highp";
actions.renames["POINT_SIZE"] = "gl_PointSize";
actions.renames["INSTANCE_ID"] = "gl_InstanceIndex";
actions.renames["VERTEX_ID"] = "gl_VertexIndex";
actions.renames["Z_CLIP_SCALE"] = "z_clip_scale";
actions.renames["ALPHA_SCISSOR_THRESHOLD"] = "alpha_scissor_threshold";
actions.renames["ALPHA_HASH_SCALE"] = "alpha_hash_scale";
actions.renames["ALPHA_ANTIALIASING_EDGE"] = "alpha_antialiasing_edge";
actions.renames["ALPHA_SCISSOR_THRESHOLD"] = "alpha_scissor_threshold_highp";
actions.renames["ALPHA_HASH_SCALE"] = "alpha_hash_scale_highp";
actions.renames["ALPHA_ANTIALIASING_EDGE"] = "alpha_antialiasing_edge_highp";
actions.renames["ALPHA_TEXTURE_COORDINATE"] = "alpha_texture_coordinate";
//builtins
@@ -567,36 +579,36 @@ void SceneShaderForwardMobile::init(const String p_defines) {
actions.renames["FRAGCOORD"] = "gl_FragCoord";
actions.renames["FRONT_FACING"] = "gl_FrontFacing";
actions.renames["NORMAL_MAP"] = "normal_map";
actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth";
actions.renames["BENT_NORMAL_MAP"] = "bent_normal_map";
actions.renames["ALBEDO"] = "albedo";
actions.renames["ALPHA"] = "alpha";
actions.renames["PREMUL_ALPHA_FACTOR"] = "premul_alpha";
actions.renames["METALLIC"] = "metallic";
actions.renames["SPECULAR"] = "specular";
actions.renames["ROUGHNESS"] = "roughness";
actions.renames["RIM"] = "rim";
actions.renames["RIM_TINT"] = "rim_tint";
actions.renames["CLEARCOAT"] = "clearcoat";
actions.renames["CLEARCOAT_ROUGHNESS"] = "clearcoat_roughness";
actions.renames["ANISOTROPY"] = "anisotropy";
actions.renames["ANISOTROPY_FLOW"] = "anisotropy_flow";
actions.renames["SSS_STRENGTH"] = "sss_strength";
actions.renames["SSS_TRANSMITTANCE_COLOR"] = "transmittance_color";
actions.renames["SSS_TRANSMITTANCE_DEPTH"] = "transmittance_depth";
actions.renames["SSS_TRANSMITTANCE_BOOST"] = "transmittance_boost";
actions.renames["BACKLIGHT"] = "backlight";
actions.renames["AO"] = "ao";
actions.renames["AO_LIGHT_AFFECT"] = "ao_light_affect";
actions.renames["EMISSION"] = "emission";
actions.renames["NORMAL_MAP"] = "normal_map_highp";
actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth_highp";
actions.renames["BENT_NORMAL_MAP"] = "bent_normal_map_highp";
actions.renames["ALBEDO"] = "albedo_highp";
actions.renames["ALPHA"] = "alpha_highp";
actions.renames["PREMUL_ALPHA_FACTOR"] = "premul_alpha_highp";
actions.renames["METALLIC"] = "metallic_highp";
actions.renames["SPECULAR"] = "specular_highp";
actions.renames["ROUGHNESS"] = "roughness_highp";
actions.renames["RIM"] = "rim_highp";
actions.renames["RIM_TINT"] = "rim_tint_highp";
actions.renames["CLEARCOAT"] = "clearcoat_highp";
actions.renames["CLEARCOAT_ROUGHNESS"] = "clearcoat_roughness_highp";
actions.renames["ANISOTROPY"] = "anisotropy_highp";
actions.renames["ANISOTROPY_FLOW"] = "anisotropy_flow_highp";
actions.renames["SSS_STRENGTH"] = "sss_strength_highp";
actions.renames["SSS_TRANSMITTANCE_COLOR"] = "transmittance_color_highp";
actions.renames["SSS_TRANSMITTANCE_DEPTH"] = "transmittance_depth_highp";
actions.renames["SSS_TRANSMITTANCE_BOOST"] = "transmittance_boost_highp";
actions.renames["BACKLIGHT"] = "backlight_highp";
actions.renames["AO"] = "ao_highp";
actions.renames["AO_LIGHT_AFFECT"] = "ao_light_affect_highp";
actions.renames["EMISSION"] = "emission_highp";
actions.renames["POINT_COORD"] = "gl_PointCoord";
actions.renames["INSTANCE_CUSTOM"] = "instance_custom";
actions.renames["SCREEN_UV"] = "screen_uv";
actions.renames["DEPTH"] = "gl_FragDepth";
actions.renames["FOG"] = "fog";
actions.renames["RADIANCE"] = "custom_radiance";
actions.renames["IRRADIANCE"] = "custom_irradiance";
actions.renames["FOG"] = "fog_highp";
actions.renames["RADIANCE"] = "custom_radiance_highp";
actions.renames["IRRADIANCE"] = "custom_irradiance_highp";
actions.renames["BONE_INDICES"] = "bone_attrib";
actions.renames["BONE_WEIGHTS"] = "weight_attrib";
actions.renames["CUSTOM0"] = "custom0_attrib";
@@ -617,14 +629,14 @@ void SceneShaderForwardMobile::init(const String p_defines) {
actions.renames["EYE_OFFSET"] = "eye_offset";
//for light
actions.renames["VIEW"] = "view";
actions.renames["SPECULAR_AMOUNT"] = "specular_amount";
actions.renames["LIGHT_COLOR"] = "light_color";
actions.renames["VIEW"] = "view_highp";
actions.renames["SPECULAR_AMOUNT"] = "specular_amount_highp";
actions.renames["LIGHT_COLOR"] = "light_color_highp";
actions.renames["LIGHT_IS_DIRECTIONAL"] = "is_directional";
actions.renames["LIGHT"] = "light";
actions.renames["ATTENUATION"] = "attenuation";
actions.renames["DIFFUSE_LIGHT"] = "diffuse_light";
actions.renames["SPECULAR_LIGHT"] = "specular_light";
actions.renames["LIGHT"] = "light_highp";
actions.renames["ATTENUATION"] = "attenuation_highp";
actions.renames["DIFFUSE_LIGHT"] = "diffuse_light_highp";
actions.renames["SPECULAR_LIGHT"] = "specular_light_highp";
actions.usage_defines["NORMAL"] = "#define NORMAL_USED\n";
actions.usage_defines["TANGENT"] = "#define TANGENT_USED\n";
@@ -749,7 +761,7 @@ void fragment() {
material_storage->material_set_shader(default_material, default_shader);
MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D));
default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS);
default_shader_rd = shader.version_get_shader(md->shader_data->version, (use_fp16 ? SHADER_VERSION_MAX * 2 : 0) + SHADER_VERSION_COLOR_PASS);
default_material_shader_ptr = md->shader_data;
default_material_uniform_set = md->uniform_set;
@@ -830,12 +842,34 @@ uint32_t SceneShaderForwardMobile::get_pipeline_compilations(RS::PipelineSource
return pipeline_compilations[p_source];
}
void SceneShaderForwardMobile::enable_fp32_shader_group() {
shader.enable_group(SHADER_GROUP_FP32);
if (is_multiview_shader_group_enabled()) {
enable_multiview_shader_group();
}
}
void SceneShaderForwardMobile::enable_fp16_shader_group() {
shader.enable_group(SHADER_GROUP_FP16);
if (is_multiview_shader_group_enabled()) {
enable_multiview_shader_group();
}
}
void SceneShaderForwardMobile::enable_multiview_shader_group() {
shader.enable_group(SHADER_GROUP_MULTIVIEW);
if (shader.is_group_enabled(SHADER_GROUP_FP32)) {
shader.enable_group(SHADER_GROUP_FP32_MULTIVIEW);
}
if (shader.is_group_enabled(SHADER_GROUP_FP16)) {
shader.enable_group(SHADER_GROUP_FP16_MULTIVIEW);
}
}
bool SceneShaderForwardMobile::is_multiview_shader_group_enabled() const {
return shader.is_group_enabled(SHADER_GROUP_MULTIVIEW);
return shader.is_group_enabled(SHADER_GROUP_FP32_MULTIVIEW) || shader.is_group_enabled(SHADER_GROUP_FP16_MULTIVIEW);
}
SceneShaderForwardMobile::~SceneShaderForwardMobile() {

View File

@@ -74,8 +74,10 @@ public:
}
enum ShaderGroup {
SHADER_GROUP_BASE, // Always compiled at the beginning.
SHADER_GROUP_MULTIVIEW,
SHADER_GROUP_FP32,
SHADER_GROUP_FP32_MULTIVIEW,
SHADER_GROUP_FP16,
SHADER_GROUP_FP16_MULTIVIEW,
};
struct ShaderSpecialization {
@@ -311,6 +313,7 @@ public:
SceneForwardMobileShaderRD shader;
ShaderCompiler compiler;
bool use_fp16 = false;
RID default_shader;
RID default_material;
@@ -344,6 +347,8 @@ public:
void init(const String p_defines);
void set_default_specialization(const ShaderSpecialization &p_specialization);
uint32_t get_pipeline_compilations(RS::PipelineSource p_source);
void enable_fp32_shader_group();
void enable_fp16_shader_group();
void enable_multiview_shader_group();
bool is_multiview_shader_group_enabled() const;
};