Path: blob/master/servers/rendering/renderer_rd/storage_rd/utilities.cpp
10279 views
/**************************************************************************/1/* utilities.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#include "utilities.h"31#include "../environment/fog.h"32#include "../environment/gi.h"33#include "light_storage.h"34#include "mesh_storage.h"35#include "particles_storage.h"36#include "texture_storage.h"3738using namespace RendererRD;3940Utilities *Utilities::singleton = nullptr;4142Utilities::Utilities() {43singleton = this;44}4546Utilities::~Utilities() {47singleton = nullptr;48}4950/* INSTANCES */5152RS::InstanceType Utilities::get_base_type(RID p_rid) const {53if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_rid)) {54return RS::INSTANCE_MESH;55}56if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_rid)) {57return RS::INSTANCE_MULTIMESH;58}59if (RendererRD::LightStorage::get_singleton()->owns_reflection_probe(p_rid)) {60return RS::INSTANCE_REFLECTION_PROBE;61}62if (RendererRD::TextureStorage::get_singleton()->owns_decal(p_rid)) {63return RS::INSTANCE_DECAL;64}65if (RendererRD::GI::get_singleton()->owns_voxel_gi(p_rid)) {66return RS::INSTANCE_VOXEL_GI;67}68if (RendererRD::LightStorage::get_singleton()->owns_light(p_rid)) {69return RS::INSTANCE_LIGHT;70}71if (RendererRD::LightStorage::get_singleton()->owns_lightmap(p_rid)) {72return RS::INSTANCE_LIGHTMAP;73}74if (RendererRD::ParticlesStorage::get_singleton()->owns_particles(p_rid)) {75return RS::INSTANCE_PARTICLES;76}77if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision(p_rid)) {78return RS::INSTANCE_PARTICLES_COLLISION;79}80if (RendererRD::Fog::get_singleton()->owns_fog_volume(p_rid)) {81return RS::INSTANCE_FOG_VOLUME;82}83if (owns_visibility_notifier(p_rid)) {84return RS::INSTANCE_VISIBLITY_NOTIFIER;85}8687return RS::INSTANCE_NONE;88}8990bool Utilities::free(RID p_rid) {91if (RendererRD::LightStorage::get_singleton()->free(p_rid)) {92return true;93} else if (RendererRD::MaterialStorage::get_singleton()->free(p_rid)) {94return true;95} else if (RendererRD::MeshStorage::get_singleton()->free(p_rid)) {96return true;97} else if (RendererRD::ParticlesStorage::get_singleton()->free(p_rid)) {98return true;99} else if (RendererRD::TextureStorage::get_singleton()->free(p_rid)) {100return true;101} else if (RendererRD::GI::get_singleton()->owns_voxel_gi(p_rid)) {102RendererRD::GI::get_singleton()->voxel_gi_free(p_rid);103return true;104} else if (RendererRD::Fog::get_singleton()->owns_fog_volume(p_rid)) {105RendererRD::Fog::get_singleton()->fog_volume_free(p_rid);106return true;107} else if (owns_visibility_notifier(p_rid)) {108visibility_notifier_free(p_rid);109return true;110} else {111return false;112}113}114115/* DEPENDENCIES */116117void Utilities::base_update_dependency(RID p_base, DependencyTracker *p_instance) {118if (MeshStorage::get_singleton()->owns_mesh(p_base)) {119Dependency *dependency = MeshStorage::get_singleton()->mesh_get_dependency(p_base);120p_instance->update_dependency(dependency);121} else if (MeshStorage::get_singleton()->owns_multimesh(p_base)) {122Dependency *dependency = MeshStorage::get_singleton()->multimesh_get_dependency(p_base);123p_instance->update_dependency(dependency);124125RID mesh = MeshStorage::get_singleton()->multimesh_get_mesh(p_base);126if (mesh.is_valid()) {127base_update_dependency(mesh, p_instance);128}129} else if (LightStorage::get_singleton()->owns_reflection_probe(p_base)) {130Dependency *dependency = LightStorage::get_singleton()->reflection_probe_get_dependency(p_base);131p_instance->update_dependency(dependency);132} else if (TextureStorage::get_singleton()->owns_decal(p_base)) {133Dependency *dependency = TextureStorage::get_singleton()->decal_get_dependency(p_base);134p_instance->update_dependency(dependency);135} else if (GI::get_singleton()->owns_voxel_gi(p_base)) {136Dependency *dependency = GI::get_singleton()->voxel_gi_get_dependency(p_base);137p_instance->update_dependency(dependency);138} else if (LightStorage::get_singleton()->owns_lightmap(p_base)) {139Dependency *dependency = LightStorage::get_singleton()->lightmap_get_dependency(p_base);140p_instance->update_dependency(dependency);141} else if (LightStorage::get_singleton()->owns_light(p_base)) {142Dependency *dependency = LightStorage::get_singleton()->light_get_dependency(p_base);143p_instance->update_dependency(dependency);144} else if (ParticlesStorage::get_singleton()->owns_particles(p_base)) {145Dependency *dependency = ParticlesStorage::get_singleton()->particles_get_dependency(p_base);146p_instance->update_dependency(dependency);147} else if (ParticlesStorage::get_singleton()->owns_particles_collision(p_base)) {148Dependency *dependency = ParticlesStorage::get_singleton()->particles_collision_get_dependency(p_base);149p_instance->update_dependency(dependency);150} else if (Fog::get_singleton()->owns_fog_volume(p_base)) {151Dependency *dependency = Fog::get_singleton()->fog_volume_get_dependency(p_base);152p_instance->update_dependency(dependency);153} else if (owns_visibility_notifier(p_base)) {154VisibilityNotifier *vn = get_visibility_notifier(p_base);155p_instance->update_dependency(&vn->dependency);156}157}158159/* VISIBILITY NOTIFIER */160161RID Utilities::visibility_notifier_allocate() {162return visibility_notifier_owner.allocate_rid();163}164165void Utilities::visibility_notifier_initialize(RID p_notifier) {166visibility_notifier_owner.initialize_rid(p_notifier, VisibilityNotifier());167}168169void Utilities::visibility_notifier_free(RID p_notifier) {170VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);171vn->dependency.deleted_notify(p_notifier);172visibility_notifier_owner.free(p_notifier);173}174175void Utilities::visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) {176VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);177ERR_FAIL_NULL(vn);178vn->aabb = p_aabb;179vn->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);180}181182void Utilities::visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) {183VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);184ERR_FAIL_NULL(vn);185vn->enter_callback = p_enter_callbable;186vn->exit_callback = p_exit_callable;187}188189AABB Utilities::visibility_notifier_get_aabb(RID p_notifier) const {190const VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);191ERR_FAIL_NULL_V(vn, AABB());192return vn->aabb;193}194195void Utilities::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) {196VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);197ERR_FAIL_NULL(vn);198199if (p_enter) {200if (vn->enter_callback.is_valid()) {201if (p_deferred) {202vn->enter_callback.call_deferred();203} else {204vn->enter_callback.call();205}206}207} else {208if (vn->exit_callback.is_valid()) {209if (p_deferred) {210vn->exit_callback.call_deferred();211} else {212vn->exit_callback.call();213}214}215}216}217218/* TIMING */219220void Utilities::capture_timestamps_begin() {221RD::get_singleton()->capture_timestamp("Frame Begin");222}223224void Utilities::capture_timestamp(const String &p_name) {225RD::get_singleton()->capture_timestamp(p_name);226}227228uint32_t Utilities::get_captured_timestamps_count() const {229return RD::get_singleton()->get_captured_timestamps_count();230}231232uint64_t Utilities::get_captured_timestamps_frame() const {233return RD::get_singleton()->get_captured_timestamps_frame();234}235236uint64_t Utilities::get_captured_timestamp_gpu_time(uint32_t p_index) const {237return RD::get_singleton()->get_captured_timestamp_gpu_time(p_index);238}239240uint64_t Utilities::get_captured_timestamp_cpu_time(uint32_t p_index) const {241return RD::get_singleton()->get_captured_timestamp_cpu_time(p_index);242}243244String Utilities::get_captured_timestamp_name(uint32_t p_index) const {245return RD::get_singleton()->get_captured_timestamp_name(p_index);246}247248/* MISC */249250void Utilities::update_dirty_resources() {251MaterialStorage::get_singleton()->_update_global_shader_uniforms(); //must do before materials, so it can queue them for update252MaterialStorage::get_singleton()->_update_queued_materials();253MeshStorage::get_singleton()->_update_dirty_multimeshes();254MeshStorage::get_singleton()->_update_dirty_skeletons();255TextureStorage::get_singleton()->update_decal_atlas();256}257258bool Utilities::has_os_feature(const String &p_feature) const {259if (!RD::get_singleton()) {260return false;261}262263if (p_feature == "rgtc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC5_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {264return true;265}266267#if !defined(ANDROID_ENABLED) && !defined(APPLE_EMBEDDED_ENABLED)268// Some Android devices report support for S3TC but we don't expect that and don't export the textures.269// This could be fixed but so few devices support it that it doesn't seem useful (and makes bigger APKs).270// For good measure we do the same hack for iOS, just in case.271if (p_feature == "s3tc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {272return true;273}274#endif275276if (p_feature == "bptc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC7_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {277return true;278}279280if (p_feature == "etc2" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {281return true;282}283284if (p_feature == "astc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ASTC_4x4_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {285return true;286}287288if (p_feature == "astc_hdr" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ASTC_4x4_SFLOAT_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {289return true;290}291292return false;293}294295void Utilities::update_memory_info() {296texture_mem_cache = RenderingDevice::get_singleton()->get_memory_usage(RenderingDevice::MEMORY_TEXTURES);297buffer_mem_cache = RenderingDevice::get_singleton()->get_memory_usage(RenderingDevice::MEMORY_BUFFERS);298total_mem_cache = RenderingDevice::get_singleton()->get_memory_usage(RenderingDevice::MEMORY_TOTAL);299}300301uint64_t Utilities::get_rendering_info(RS::RenderingInfo p_info) {302if (p_info == RS::RENDERING_INFO_TEXTURE_MEM_USED) {303return texture_mem_cache;304} else if (p_info == RS::RENDERING_INFO_BUFFER_MEM_USED) {305return buffer_mem_cache;306} else if (p_info == RS::RENDERING_INFO_VIDEO_MEM_USED) {307return total_mem_cache;308}309return 0;310}311312String Utilities::get_video_adapter_name() const {313return RenderingDevice::get_singleton()->get_device_name();314}315316String Utilities::get_video_adapter_vendor() const {317return RenderingDevice::get_singleton()->get_device_vendor_name();318}319320RenderingDevice::DeviceType Utilities::get_video_adapter_type() const {321return RenderingDevice::get_singleton()->get_device_type();322}323324String Utilities::get_video_adapter_api_version() const {325return RenderingDevice::get_singleton()->get_device_api_version();326}327328Size2i Utilities::get_maximum_viewport_size() const {329RenderingDevice *device = RenderingDevice::get_singleton();330331int max_x = device->limit_get(RenderingDevice::LIMIT_MAX_VIEWPORT_DIMENSIONS_X);332int max_y = device->limit_get(RenderingDevice::LIMIT_MAX_VIEWPORT_DIMENSIONS_Y);333return Size2i(max_x, max_y);334}335336uint32_t Utilities::get_maximum_shader_varyings() const {337return RenderingDevice::get_singleton()->limit_get(RenderingDevice::LIMIT_MAX_SHADER_VARYINGS);338}339340uint64_t Utilities::get_maximum_uniform_buffer_size() const {341return RenderingDevice::get_singleton()->limit_get(RenderingDevice::LIMIT_MAX_UNIFORM_BUFFER_SIZE);342}343344345