initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled

This commit is contained in:
2025-09-16 20:46:46 -04:00
commit 9d30169a8d
13378 changed files with 7050105 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
Import("env")
env.add_source_files(env.servers_sources, "*.cpp")

View File

@@ -0,0 +1,43 @@
/**************************************************************************/
/* forward_id_storage.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#include "forward_id_storage.h"
using namespace RendererRD;
ForwardIDStorage *ForwardIDStorage::singleton = nullptr;
ForwardIDStorage::ForwardIDStorage() {
singleton = this;
}
ForwardIDStorage::~ForwardIDStorage() {
singleton = nullptr;
}

View File

@@ -0,0 +1,65 @@
/**************************************************************************/
/* forward_id_storage.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include <cstdint>
class RendererSceneRenderRD;
namespace RendererRD {
typedef int32_t ForwardID;
enum ForwardIDType {
FORWARD_ID_TYPE_OMNI_LIGHT,
FORWARD_ID_TYPE_SPOT_LIGHT,
FORWARD_ID_TYPE_REFLECTION_PROBE,
FORWARD_ID_TYPE_DECAL,
FORWARD_ID_MAX,
};
class ForwardIDStorage {
private:
static ForwardIDStorage *singleton;
public:
static ForwardIDStorage *get_singleton() { return singleton; }
ForwardIDStorage();
virtual ~ForwardIDStorage();
virtual RendererRD::ForwardID allocate_forward_id(RendererRD::ForwardIDType p_type) { return -1; }
virtual void free_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id) {}
virtual void map_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id, uint32_t p_index, uint64_t p_last_pass) {}
virtual bool uses_forward_ids() const { return false; }
};
} // namespace RendererRD

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,478 @@
/**************************************************************************/
/* material_storage.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "texture_storage.h"
#include "core/math/projection.h"
#include "core/templates/local_vector.h"
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
#include "servers/rendering/shader_compiler.h"
#include "servers/rendering/shader_language.h"
#include "servers/rendering/storage/material_storage.h"
#include "servers/rendering/storage/utilities.h"
namespace RendererRD {
class MaterialStorage : public RendererMaterialStorage {
public:
enum ShaderType {
SHADER_TYPE_2D,
SHADER_TYPE_3D,
SHADER_TYPE_PARTICLES,
SHADER_TYPE_SKY,
SHADER_TYPE_FOG,
SHADER_TYPE_MAX
};
struct ShaderData {
enum BlendMode {
BLEND_MODE_MIX,
BLEND_MODE_ADD,
BLEND_MODE_SUB,
BLEND_MODE_MUL,
BLEND_MODE_ALPHA_TO_COVERAGE,
BLEND_MODE_PREMULTIPLIED_ALPHA,
BLEND_MODE_DISABLED
};
String path;
HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
HashMap<StringName, HashMap<int, RID>> default_texture_params;
virtual void set_path_hint(const String &p_hint);
virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index);
virtual Variant get_default_parameter(const StringName &p_parameter) const;
virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_parameter_texture(const StringName &p_param) const;
virtual void set_code(const String &p_Code) = 0;
virtual bool is_animated() const = 0;
virtual bool casts_shadows() const = 0;
virtual RS::ShaderNativeSourceCode get_native_source_code() const = 0;
virtual Pair<ShaderRD *, RID> get_native_shader_and_version() const = 0;
virtual ~ShaderData() {}
static RD::PipelineColorBlendState::Attachment blend_mode_to_blend_attachment(BlendMode p_mode);
static bool blend_mode_uses_blend_alpha(BlendMode p_mode);
};
struct MaterialData {
Vector<RendererRD::TextureStorage::RenderTarget *> render_target_cache;
void update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color);
void update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color, bool p_3d_material);
void set_as_used();
virtual void set_render_priority(int p_priority) = 0;
virtual void set_next_pass(RID p_pass) = 0;
virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0;
virtual ~MaterialData();
//to be used internally by update_parameters, in the most common configuration of material parameters
bool update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &r_uniform_set, RID p_shader, uint32_t p_shader_uniform_set, bool p_use_linear_color, bool p_3d_material);
void free_parameters_uniform_set(RID p_uniform_set);
private:
friend class MaterialStorage;
RID self;
List<RID>::Element *global_buffer_E = nullptr;
List<RID>::Element *global_texture_E = nullptr;
uint64_t global_textures_pass = 0;
HashMap<StringName, uint64_t> used_global_textures;
//internally by update_parameters_uniform_set
Vector<uint8_t> ubo_data[2]; // 0: linear buffer; 1: sRGB buffer.
RID uniform_buffer[2]; // 0: linear buffer; 1: sRGB buffer.
Vector<RID> texture_cache;
};
struct Samplers {
RID rids[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
float mipmap_bias = 0.0f;
bool use_nearest_mipmap_filter = false;
int anisotropic_filtering_level = 2;
_FORCE_INLINE_ RID get_sampler(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) const {
return rids[p_filter][p_repeat];
}
template <typename Collection>
void append_uniforms(Collection &p_uniforms, int p_first_index) const;
bool is_valid() const;
bool is_null() const;
};
private:
static MaterialStorage *singleton;
/* Samplers */
Samplers default_samplers;
/* Buffers */
RID quad_index_buffer;
RID quad_index_array;
/* GLOBAL SHADER UNIFORM API */
struct GlobalShaderUniforms {
enum {
BUFFER_DIRTY_REGION_SIZE = 1024
};
struct Variable {
HashSet<RID> texture_materials; // materials using this
RS::GlobalShaderParameterType type;
Variant value;
Variant override;
int32_t buffer_index; //for vectors
int32_t buffer_elements; //for vectors
};
HashMap<StringName, Variable> variables;
struct Value {
float x;
float y;
float z;
float w;
};
struct ValueInt {
int32_t x;
int32_t y;
int32_t z;
int32_t w;
};
struct ValueUInt {
uint32_t x;
uint32_t y;
uint32_t z;
uint32_t w;
};
struct ValueUsage {
uint32_t elements = 0;
};
List<RID> materials_using_buffer;
List<RID> materials_using_texture;
RID buffer;
Value *buffer_values = nullptr;
ValueUsage *buffer_usage = nullptr;
bool *buffer_dirty_regions = nullptr;
uint32_t buffer_dirty_region_count = 0;
uint32_t buffer_size;
bool must_update_texture_materials = false;
bool must_update_buffer_materials = false;
HashMap<RID, int32_t> instance_buffer_pos;
} global_shader_uniforms;
int32_t _global_shader_uniform_allocate(uint32_t p_elements);
void _global_shader_uniform_store_in_buffer(int32_t p_index, RS::GlobalShaderParameterType p_type, const Variant &p_value);
void _global_shader_uniform_mark_buffer_dirty(int32_t p_index, int32_t p_elements);
/* SHADER API */
struct Material;
struct Shader {
ShaderData *data = nullptr;
String code;
String path_hint;
ShaderType type;
HashMap<StringName, HashMap<int, RID>> default_texture_parameter;
HashSet<Material *> owners;
bool embedded = false;
};
typedef ShaderData *(*ShaderDataRequestFunction)();
ShaderDataRequestFunction shader_data_request_func[SHADER_TYPE_MAX];
mutable RID_Owner<Shader, true> shader_owner;
HashSet<RID> embedded_set;
Mutex embedded_set_mutex;
Shader *get_shader(RID p_rid) { return shader_owner.get_or_null(p_rid); }
/* MATERIAL API */
typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *);
struct Material {
RID self;
MaterialData *data = nullptr;
Shader *shader = nullptr;
//shortcut to shader data and type
ShaderType shader_type = SHADER_TYPE_MAX;
uint32_t shader_id = 0;
bool uniform_dirty = false;
bool texture_dirty = false;
HashMap<StringName, Variant> params;
int32_t priority = 0;
RID next_pass;
SelfList<Material> update_element;
Dependency dependency;
Material() :
update_element(this) {}
};
MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX];
mutable RID_Owner<Material, true> material_owner;
Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); }
SelfList<Material>::List material_update_list;
Mutex material_update_list_mutex;
static void _material_uniform_set_erased(void *p_material);
public:
static MaterialStorage *get_singleton();
MaterialStorage();
virtual ~MaterialStorage();
bool free(RID p_rid);
/* Helpers */
static _FORCE_INLINE_ void store_transform(const Transform3D &p_mtx, float *p_array) {
p_array[0] = p_mtx.basis.rows[0][0];
p_array[1] = p_mtx.basis.rows[1][0];
p_array[2] = p_mtx.basis.rows[2][0];
p_array[3] = 0;
p_array[4] = p_mtx.basis.rows[0][1];
p_array[5] = p_mtx.basis.rows[1][1];
p_array[6] = p_mtx.basis.rows[2][1];
p_array[7] = 0;
p_array[8] = p_mtx.basis.rows[0][2];
p_array[9] = p_mtx.basis.rows[1][2];
p_array[10] = p_mtx.basis.rows[2][2];
p_array[11] = 0;
p_array[12] = p_mtx.origin.x;
p_array[13] = p_mtx.origin.y;
p_array[14] = p_mtx.origin.z;
p_array[15] = 1;
}
static _FORCE_INLINE_ void store_basis_3x4(const Basis &p_mtx, float *p_array) {
p_array[0] = p_mtx.rows[0][0];
p_array[1] = p_mtx.rows[1][0];
p_array[2] = p_mtx.rows[2][0];
p_array[3] = 0;
p_array[4] = p_mtx.rows[0][1];
p_array[5] = p_mtx.rows[1][1];
p_array[6] = p_mtx.rows[2][1];
p_array[7] = 0;
p_array[8] = p_mtx.rows[0][2];
p_array[9] = p_mtx.rows[1][2];
p_array[10] = p_mtx.rows[2][2];
p_array[11] = 0;
}
static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_mtx, float *p_array) {
p_array[0] = p_mtx.rows[0][0];
p_array[1] = p_mtx.rows[1][0];
p_array[2] = p_mtx.rows[2][0];
p_array[3] = 0;
p_array[4] = p_mtx.rows[0][1];
p_array[5] = p_mtx.rows[1][1];
p_array[6] = p_mtx.rows[2][1];
p_array[7] = 0;
p_array[8] = p_mtx.rows[0][2];
p_array[9] = p_mtx.rows[1][2];
p_array[10] = p_mtx.rows[2][2];
p_array[11] = 0;
}
static _FORCE_INLINE_ void store_transform_transposed_3x4(const Transform3D &p_mtx, float *p_array) {
p_array[0] = p_mtx.basis.rows[0][0];
p_array[1] = p_mtx.basis.rows[0][1];
p_array[2] = p_mtx.basis.rows[0][2];
p_array[3] = p_mtx.origin.x;
p_array[4] = p_mtx.basis.rows[1][0];
p_array[5] = p_mtx.basis.rows[1][1];
p_array[6] = p_mtx.basis.rows[1][2];
p_array[7] = p_mtx.origin.y;
p_array[8] = p_mtx.basis.rows[2][0];
p_array[9] = p_mtx.basis.rows[2][1];
p_array[10] = p_mtx.basis.rows[2][2];
p_array[11] = p_mtx.origin.z;
}
static _FORCE_INLINE_ void store_camera(const Projection &p_mtx, float *p_array) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
p_array[i * 4 + j] = p_mtx.columns[i][j];
}
}
}
static _FORCE_INLINE_ void store_soft_shadow_kernel(const float *p_kernel, float *p_array) {
for (int i = 0; i < 128; i++) {
p_array[i] = p_kernel[i];
}
}
// http://andrewthall.org/papers/df64_qf128.pdf
#ifdef REAL_T_IS_DOUBLE
static _FORCE_INLINE_ void split_double(double a, float *a_hi, float *a_lo) {
const double SPLITTER = (1 << 29) + 1;
double t = a * SPLITTER;
double t_hi = t - (t - a);
double t_lo = a - t_hi;
*a_hi = (float)t_hi;
*a_lo = (float)t_lo;
}
#endif
/* Samplers */
Samplers samplers_rd_allocate(float p_mipmap_bias = 0.0f, RS::ViewportAnisotropicFiltering anisotropic_filtering_level = RS::ViewportAnisotropicFiltering::VIEWPORT_ANISOTROPY_4X) const;
void samplers_rd_free(Samplers &p_samplers) const;
_FORCE_INLINE_ RID sampler_rd_get_default(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
return default_samplers.get_sampler(p_filter, p_repeat);
}
_FORCE_INLINE_ const Samplers &samplers_rd_get_default() const {
return default_samplers;
}
/* Buffers */
RID get_quad_index_array() { return quad_index_array; }
/* GLOBAL SHADER UNIFORM API */
void _update_global_shader_uniforms();
virtual void global_shader_parameter_add(const StringName &p_name, RS::GlobalShaderParameterType p_type, const Variant &p_value) override;
virtual void global_shader_parameter_remove(const StringName &p_name) override;
virtual Vector<StringName> global_shader_parameter_get_list() const override;
virtual void global_shader_parameter_set(const StringName &p_name, const Variant &p_value) override;
virtual void global_shader_parameter_set_override(const StringName &p_name, const Variant &p_value) override;
virtual Variant global_shader_parameter_get(const StringName &p_name) const override;
virtual RS::GlobalShaderParameterType global_shader_parameter_get_type(const StringName &p_name) const override;
RS::GlobalShaderParameterType global_shader_parameter_get_type_internal(const StringName &p_name) const;
virtual void global_shader_parameters_load_settings(bool p_load_textures = true) override;
virtual void global_shader_parameters_clear() override;
virtual int32_t global_shader_parameters_instance_allocate(RID p_instance) override;
virtual void global_shader_parameters_instance_free(RID p_instance) override;
virtual void global_shader_parameters_instance_update(RID p_instance, int p_index, const Variant &p_value, int p_flags_count = 0) override;
RID global_shader_uniforms_get_storage_buffer() const;
/* SHADER API */
bool owns_shader(RID p_rid) { return shader_owner.owns(p_rid); }
virtual RID shader_allocate() override;
virtual void shader_initialize(RID p_shader, bool p_embedded = true) override;
virtual void shader_free(RID p_rid) override;
virtual void shader_set_code(RID p_shader, const String &p_code) override;
virtual void shader_set_path_hint(RID p_shader, const String &p_path) override;
virtual String shader_get_code(RID p_shader) const override;
virtual void get_shader_parameter_list(RID p_shader, List<PropertyInfo> *p_param_list) const override;
virtual void shader_set_default_texture_parameter(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override;
virtual RID shader_get_default_texture_parameter(RID p_shader, const StringName &p_name, int p_index) const override;
virtual Variant shader_get_parameter_default(RID p_shader, const StringName &p_param) const override;
void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function);
ShaderData *shader_get_data(RID p_shader) const;
virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override;
virtual void shader_embedded_set_lock() override;
virtual const HashSet<RID> &shader_embedded_set_get() const override;
virtual void shader_embedded_set_unlock() override;
/* MATERIAL API */
bool owns_material(RID p_rid) { return material_owner.owns(p_rid); }
void _material_queue_update(Material *material, bool p_uniform, bool p_texture);
void _update_queued_materials();
virtual RID material_allocate() override;
virtual void material_initialize(RID p_material) override;
virtual void material_free(RID p_rid) override;
virtual void material_set_shader(RID p_material, RID p_shader) override;
ShaderData *material_get_shader_data(RID p_material);
virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override;
virtual Variant material_get_param(RID p_material, const StringName &p_param) const override;
virtual void material_set_next_pass(RID p_material, RID p_next_material) override;
virtual void material_set_render_priority(RID p_material, int priority) override;
virtual bool material_is_animated(RID p_material) override;
virtual bool material_casts_shadows(RID p_material) override;
virtual RS::CullMode material_get_cull_mode(RID p_material) const override;
virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override;
virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) override;
void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function);
MaterialDataRequestFunction material_get_data_request_function(ShaderType p_shader_type);
_FORCE_INLINE_ uint32_t material_get_shader_id(RID p_material) {
Material *material = material_owner.get_or_null(p_material);
return material->shader_id;
}
_FORCE_INLINE_ MaterialData *material_get_data(RID p_material, ShaderType p_shader_type) {
Material *material = material_owner.get_or_null(p_material);
if (!material || material->shader_type != p_shader_type) {
return nullptr;
} else {
return material->data;
}
}
};
} // namespace RendererRD

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,814 @@
/**************************************************************************/
/* mesh_storage.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "../../rendering_server_globals.h"
#include "core/templates/local_vector.h"
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
#include "servers/rendering/renderer_rd/shaders/skeleton.glsl.gen.h"
#include "servers/rendering/storage/mesh_storage.h"
#include "servers/rendering/storage/utilities.h"
namespace RendererRD {
class MeshStorage : public RendererMeshStorage {
public:
enum DefaultRDBuffer {
DEFAULT_RD_BUFFER_VERTEX,
DEFAULT_RD_BUFFER_NORMAL,
DEFAULT_RD_BUFFER_TANGENT,
DEFAULT_RD_BUFFER_COLOR,
DEFAULT_RD_BUFFER_TEX_UV,
DEFAULT_RD_BUFFER_TEX_UV2,
DEFAULT_RD_BUFFER_CUSTOM0,
DEFAULT_RD_BUFFER_CUSTOM1,
DEFAULT_RD_BUFFER_CUSTOM2,
DEFAULT_RD_BUFFER_CUSTOM3,
DEFAULT_RD_BUFFER_BONES,
DEFAULT_RD_BUFFER_WEIGHTS,
DEFAULT_RD_BUFFER_MAX,
};
enum IndirectMultiMesh : uint32_t {
INDIRECT_MULTIMESH_COMMAND_STRIDE = 5
};
private:
static MeshStorage *singleton;
RID default_rd_storage_buffer;
/* Mesh */
RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX];
struct MeshInstance;
struct Mesh {
struct Surface {
RS::PrimitiveType primitive = RS::PRIMITIVE_POINTS;
uint64_t format = 0;
uint32_t vertex_count = 0;
RID vertex_buffer;
uint32_t vertex_buffer_size = 0;
RID attribute_buffer;
uint32_t attribute_buffer_size = 0;
RID skin_buffer;
uint32_t skin_buffer_size = 0;
// A different pipeline needs to be allocated
// depending on the inputs available in the
// material.
// There are never that many geometry/material
// combinations, so a simple array is the most
// cache-efficient structure.
struct Version {
uint64_t input_mask = 0;
uint32_t current_buffer = 0;
uint32_t previous_buffer = 0;
bool input_motion_vectors = false;
RD::VertexFormatID vertex_format = 0;
RID vertex_array;
};
SpinLock version_lock; //needed to access versions
Version *versions = nullptr; //allocated on demand
uint32_t version_count = 0;
RID index_buffer;
uint32_t index_buffer_size = 0;
RID index_array;
uint32_t index_count = 0;
struct LOD {
float edge_length = 0.0;
uint32_t index_count = 0;
RID index_buffer;
uint32_t index_buffer_size = 0;
RID index_array;
};
LOD *lods = nullptr;
uint32_t lod_count = 0;
AABB aabb;
Vector<AABB> bone_aabbs;
// Transform used in runtime bone AABBs compute.
// As bone AABBs are saved in Mesh space, but bones animation is in Skeleton space.
Transform3D mesh_to_skeleton_xform;
Vector4 uv_scale;
RID blend_shape_buffer;
uint32_t blend_shape_buffer_size = 0;
RID material;
uint32_t render_index = 0;
uint64_t render_pass = 0;
uint32_t multimesh_render_index = 0;
uint64_t multimesh_render_pass = 0;
uint32_t particles_render_index = 0;
uint64_t particles_render_pass = 0;
RID uniform_set;
};
uint32_t blend_shape_count = 0;
RS::BlendShapeMode blend_shape_mode = RS::BLEND_SHAPE_MODE_NORMALIZED;
Surface **surfaces = nullptr;
uint32_t surface_count = 0;
bool has_bone_weights = false;
AABB aabb;
AABB custom_aabb;
uint64_t skeleton_aabb_version = 0;
RID skeleton_aabb_rid;
Vector<RID> material_cache;
List<MeshInstance *> instances;
RID shadow_mesh;
HashSet<Mesh *> shadow_owners;
String path;
Dependency dependency;
};
mutable RID_Owner<Mesh, true> mesh_owner;
/* Mesh Instance API */
struct MeshInstance {
Mesh *mesh = nullptr;
RID skeleton;
struct Surface {
RID vertex_buffer[2];
RID uniform_set[2];
uint32_t current_buffer = 0;
uint32_t previous_buffer = 0;
uint64_t last_change = 0;
Mesh::Surface::Version *versions = nullptr; //allocated on demand
uint32_t version_count = 0;
};
LocalVector<Surface> surfaces;
LocalVector<float> blend_weights;
RID blend_weights_buffer;
List<MeshInstance *>::Element *I = nullptr; //used to erase itself
uint64_t skeleton_version = 0;
bool dirty = false;
bool weights_dirty = false;
SelfList<MeshInstance> weight_update_list;
SelfList<MeshInstance> array_update_list;
Transform2D canvas_item_transform_2d;
MeshInstance() :
weight_update_list(this), array_update_list(this) {}
};
RD::VertexFormatID _mesh_surface_generate_vertex_format(uint64_t p_surface_format, uint64_t p_input_mask, bool p_instanced_surface, bool p_input_motion_vectors, uint32_t &r_position_stride);
void _mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint64_t p_input_mask, bool p_input_motion_vectors, MeshInstance::Surface *mis = nullptr, uint32_t p_current_buffer = 0, uint32_t p_previous_buffer = 0);
void _mesh_surface_clear(Mesh *p_mesh, int p_surface);
void _mesh_instance_clear(MeshInstance *mi);
void _mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface);
void _mesh_instance_add_surface_buffer(MeshInstance *mi, Mesh *mesh, MeshInstance::Surface *s, uint32_t p_surface, uint32_t p_buffer_index);
void _mesh_instance_remove_surface(MeshInstance *mi, int p_surface);
mutable RID_Owner<MeshInstance> mesh_instance_owner;
SelfList<MeshInstance>::List dirty_mesh_instance_weights;
SelfList<MeshInstance>::List dirty_mesh_instance_arrays;
/* MultiMesh */
struct MultiMesh {
RID mesh;
int instances = 0;
RS::MultimeshTransformFormat xform_format = RS::MULTIMESH_TRANSFORM_3D;
bool uses_colors = false;
bool uses_custom_data = false;
int visible_instances = -1;
AABB aabb;
AABB custom_aabb;
bool aabb_dirty = false;
bool buffer_set = false;
bool indirect = false;
bool motion_vectors_enabled = false;
uint32_t motion_vectors_current_offset = 0;
uint32_t motion_vectors_previous_offset = 0;
uint64_t motion_vectors_last_change = -1;
uint32_t stride_cache = 0;
uint32_t color_offset_cache = 0;
uint32_t custom_data_offset_cache = 0;
Vector<float> data_cache; //used if individual setting is used
bool *data_cache_dirty_regions = nullptr;
uint32_t data_cache_dirty_region_count = 0;
bool *previous_data_cache_dirty_regions = nullptr;
uint32_t previous_data_cache_dirty_region_count = 0;
RID buffer; //storage buffer
RID uniform_set_3d;
RID uniform_set_2d;
RID command_buffer; //used if indirect setting is used
bool dirty = false;
MultiMesh *dirty_list = nullptr;
RendererMeshStorage::MultiMeshInterpolator interpolator;
Dependency dependency;
};
mutable RID_Owner<MultiMesh, true> multimesh_owner;
MultiMesh *multimesh_dirty_list = nullptr;
_FORCE_INLINE_ void _multimesh_make_local(MultiMesh *multimesh) const;
_FORCE_INLINE_ void _multimesh_enable_motion_vectors(MultiMesh *multimesh);
_FORCE_INLINE_ void _multimesh_update_motion_vectors_data_cache(MultiMesh *multimesh);
_FORCE_INLINE_ bool _multimesh_uses_motion_vectors(MultiMesh *multimesh);
_FORCE_INLINE_ void _multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb);
_FORCE_INLINE_ void _multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb);
_FORCE_INLINE_ void _multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances);
/* Skeleton */
struct SkeletonShader {
struct PushConstant {
uint32_t has_normal;
uint32_t has_tangent;
uint32_t has_skeleton;
uint32_t has_blend_shape;
uint32_t vertex_count;
uint32_t vertex_stride;
uint32_t skin_stride;
uint32_t skin_weight_offset;
uint32_t blend_shape_count;
uint32_t normalized_blend_shapes;
uint32_t normal_tangent_stride;
uint32_t pad1;
float skeleton_transform_x[2];
float skeleton_transform_y[2];
float skeleton_transform_offset[2];
float inverse_transform_x[2];
float inverse_transform_y[2];
float inverse_transform_offset[2];
};
enum {
UNIFORM_SET_INSTANCE = 0,
UNIFORM_SET_SURFACE = 1,
UNIFORM_SET_SKELETON = 2,
};
enum {
SHADER_MODE_2D,
SHADER_MODE_3D,
SHADER_MODE_MAX
};
SkeletonShaderRD shader;
RID version;
RID version_shader[SHADER_MODE_MAX];
RID pipeline[SHADER_MODE_MAX];
RID default_skeleton_uniform_set;
} skeleton_shader;
struct Skeleton {
bool use_2d = false;
int size = 0;
LocalVector<float> data;
RID buffer;
bool dirty = false;
Skeleton *dirty_list = nullptr;
Transform2D base_transform_2d;
RID uniform_set_3d;
RID uniform_set_mi;
uint64_t version = 1;
Dependency dependency;
};
mutable RID_Owner<Skeleton, true> skeleton_owner;
_FORCE_INLINE_ void _skeleton_make_dirty(Skeleton *skeleton);
Skeleton *skeleton_dirty_list = nullptr;
enum AttributeLocation {
ATTRIBUTE_LOCATION_PREV_VERTEX = 12,
ATTRIBUTE_LOCATION_PREV_NORMAL = 13,
ATTRIBUTE_LOCATION_PREV_TANGENT = 14
};
public:
static MeshStorage *get_singleton();
MeshStorage();
virtual ~MeshStorage();
bool free(RID p_rid);
RID get_default_rd_storage_buffer() const { return default_rd_storage_buffer; }
/* MESH API */
bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); }
virtual RID mesh_allocate() override;
virtual void mesh_initialize(RID p_mesh) override;
virtual void mesh_free(RID p_rid) override;
virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) override;
/// Return stride
virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override;
virtual int mesh_get_blend_shape_count(RID p_mesh) const override;
virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) override;
virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const override;
virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override;
virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override;
virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override;
virtual void mesh_surface_update_index_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override;
virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override;
virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const override;
virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override;
virtual int mesh_get_surface_count(RID p_mesh) const override;
virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override;
virtual AABB mesh_get_custom_aabb(RID p_mesh) const override;
virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override;
virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override;
virtual void mesh_set_path(RID p_mesh, const String &p_path) override;
virtual String mesh_get_path(RID p_mesh) const override;
virtual void mesh_clear(RID p_mesh) override;
virtual void mesh_surface_remove(RID p_mesh, int p_surface) override;
virtual void mesh_debug_usage(List<RS::MeshInfo> *r_info) override;
virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) override;
_FORCE_INLINE_ const RID *mesh_get_surface_count_and_materials(RID p_mesh, uint32_t &r_surface_count) {
Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_NULL_V(mesh, nullptr);
r_surface_count = mesh->surface_count;
if (r_surface_count == 0) {
return nullptr;
}
if (mesh->material_cache.is_empty()) {
mesh->material_cache.resize(mesh->surface_count);
for (uint32_t i = 0; i < r_surface_count; i++) {
mesh->material_cache.write[i] = mesh->surfaces[i]->material;
}
}
return mesh->material_cache.ptr();
}
_FORCE_INLINE_ void *mesh_get_surface(RID p_mesh, uint32_t p_surface_index) {
Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_NULL_V(mesh, nullptr);
ERR_FAIL_UNSIGNED_INDEX_V(p_surface_index, mesh->surface_count, nullptr);
return mesh->surfaces[p_surface_index];
}
_FORCE_INLINE_ RID mesh_get_shadow_mesh(RID p_mesh) {
Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_NULL_V(mesh, RID());
return mesh->shadow_mesh;
}
_FORCE_INLINE_ RS::PrimitiveType mesh_surface_get_primitive(void *p_surface) {
Mesh::Surface *surface = reinterpret_cast<Mesh::Surface *>(p_surface);
return surface->primitive;
}
_FORCE_INLINE_ bool mesh_surface_has_lod(void *p_surface) const {
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
return s->lod_count > 0;
}
_FORCE_INLINE_ uint32_t mesh_surface_get_vertices_drawn_count(void *p_surface) const {
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
return s->index_count ? s->index_count : s->vertex_count;
}
_FORCE_INLINE_ AABB mesh_surface_get_aabb(void *p_surface) {
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
return s->aabb;
}
_FORCE_INLINE_ uint64_t mesh_surface_get_format(void *p_surface) {
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
return s->format;
}
_FORCE_INLINE_ Vector4 mesh_surface_get_uv_scale(void *p_surface) {
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
return s->uv_scale;
}
_FORCE_INLINE_ uint32_t mesh_surface_get_lod(void *p_surface, float p_model_scale, float p_distance_threshold, float p_mesh_lod_threshold, uint32_t &r_index_count) const {
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
int32_t current_lod = -1;
r_index_count = s->index_count;
for (uint32_t i = 0; i < s->lod_count; i++) {
float screen_size = s->lods[i].edge_length * p_model_scale / p_distance_threshold;
if (screen_size > p_mesh_lod_threshold) {
break;
}
current_lod = i;
}
if (current_lod == -1) {
return 0;
} else {
r_index_count = s->lods[current_lod].index_count;
return current_lod + 1;
}
}
_FORCE_INLINE_ RID mesh_surface_get_index_array(void *p_surface, uint32_t p_lod) const {
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
if (p_lod == 0) {
return s->index_array;
} else {
return s->lods[p_lod - 1].index_array;
}
}
_FORCE_INLINE_ void mesh_surface_get_vertex_arrays_and_format(void *p_surface, uint64_t p_input_mask, bool p_input_motion_vectors, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) {
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
s->version_lock.lock();
//there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way
for (uint32_t i = 0; i < s->version_count; i++) {
if (s->versions[i].input_mask != p_input_mask || s->versions[i].input_motion_vectors != p_input_motion_vectors) {
// Find the version that matches the inputs required.
continue;
}
//we have this version, hooray
r_vertex_format = s->versions[i].vertex_format;
r_vertex_array_rd = s->versions[i].vertex_array;
s->version_lock.unlock();
return;
}
uint32_t version = s->version_count;
s->version_count++;
s->versions = (Mesh::Surface::Version *)memrealloc(s->versions, sizeof(Mesh::Surface::Version) * s->version_count);
_mesh_surface_generate_version_for_input_mask(s->versions[version], s, p_input_mask, p_input_motion_vectors);
r_vertex_format = s->versions[version].vertex_format;
r_vertex_array_rd = s->versions[version].vertex_array;
s->version_lock.unlock();
}
_FORCE_INLINE_ void mesh_instance_surface_get_vertex_arrays_and_format(RID p_mesh_instance, uint64_t p_surface_index, uint64_t p_input_mask, bool p_input_motion_vectors, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) {
MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
ERR_FAIL_NULL(mi);
Mesh *mesh = mi->mesh;
ERR_FAIL_UNSIGNED_INDEX(p_surface_index, mesh->surface_count);
MeshInstance::Surface *mis = &mi->surfaces[p_surface_index];
Mesh::Surface *s = mesh->surfaces[p_surface_index];
uint32_t current_buffer = mis->current_buffer;
// Using the previous buffer is only allowed if the surface was updated this frame and motion vectors are required.
uint32_t previous_buffer = p_input_motion_vectors && (RSG::rasterizer->get_frame_number() == mis->last_change) ? mis->previous_buffer : current_buffer;
s->version_lock.lock();
//there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way
for (uint32_t i = 0; i < mis->version_count; i++) {
if (mis->versions[i].input_mask != p_input_mask || mis->versions[i].input_motion_vectors != p_input_motion_vectors) {
// Find the version that matches the inputs required.
continue;
}
if (mis->versions[i].current_buffer != current_buffer || mis->versions[i].previous_buffer != previous_buffer) {
// Find the version that corresponds to the correct buffers that should be used.
continue;
}
//we have this version, hooray
r_vertex_format = mis->versions[i].vertex_format;
r_vertex_array_rd = mis->versions[i].vertex_array;
s->version_lock.unlock();
return;
}
uint32_t version = mis->version_count;
mis->version_count++;
mis->versions = (Mesh::Surface::Version *)memrealloc(mis->versions, sizeof(Mesh::Surface::Version) * mis->version_count);
_mesh_surface_generate_version_for_input_mask(mis->versions[version], s, p_input_mask, p_input_motion_vectors, mis, current_buffer, previous_buffer);
r_vertex_format = mis->versions[version].vertex_format;
r_vertex_array_rd = mis->versions[version].vertex_array;
s->version_lock.unlock();
}
_FORCE_INLINE_ RID mesh_get_default_rd_buffer(DefaultRDBuffer p_buffer) {
ERR_FAIL_INDEX_V(p_buffer, DEFAULT_RD_BUFFER_MAX, RID());
return mesh_default_rd_buffers[p_buffer];
}
_FORCE_INLINE_ uint32_t mesh_surface_get_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
Mesh *mesh = mesh_owner.get_or_null(p_mesh);
Mesh::Surface *s = mesh->surfaces[p_surface_index];
if (s->render_pass != p_render_pass) {
(*r_index)++;
s->render_pass = p_render_pass;
s->render_index = *r_index;
}
return s->render_index;
}
_FORCE_INLINE_ uint32_t mesh_surface_get_multimesh_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
Mesh *mesh = mesh_owner.get_or_null(p_mesh);
Mesh::Surface *s = mesh->surfaces[p_surface_index];
if (s->multimesh_render_pass != p_render_pass) {
(*r_index)++;
s->multimesh_render_pass = p_render_pass;
s->multimesh_render_index = *r_index;
}
return s->multimesh_render_index;
}
_FORCE_INLINE_ uint32_t mesh_surface_get_particles_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
Mesh *mesh = mesh_owner.get_or_null(p_mesh);
Mesh::Surface *s = mesh->surfaces[p_surface_index];
if (s->particles_render_pass != p_render_pass) {
(*r_index)++;
s->particles_render_pass = p_render_pass;
s->particles_render_index = *r_index;
}
return s->particles_render_index;
}
_FORCE_INLINE_ RD::VertexFormatID mesh_surface_get_vertex_format(void *p_surface, uint64_t p_input_mask, bool p_instanced_surface, bool p_input_motion_vectors) {
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
uint32_t position_stride = 0;
return _mesh_surface_generate_vertex_format(s->format, p_input_mask, p_instanced_surface, p_input_motion_vectors, position_stride);
}
Dependency *mesh_get_dependency(RID p_mesh) const;
/* MESH INSTANCE API */
bool owns_mesh_instance(RID p_rid) const { return mesh_instance_owner.owns(p_rid); }
virtual RID mesh_instance_create(RID p_base) override;
virtual void mesh_instance_free(RID p_rid) override;
virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override;
virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override;
virtual void mesh_instance_check_for_update(RID p_mesh_instance) override;
virtual void mesh_instance_set_canvas_item_transform(RID p_mesh_instance, const Transform2D &p_transform) override;
virtual void update_mesh_instances() override;
/* MULTIMESH API */
bool owns_multimesh(RID p_rid) { return multimesh_owner.owns(p_rid); }
virtual RID _multimesh_allocate() override;
virtual void _multimesh_initialize(RID p_multimesh) override;
virtual void _multimesh_free(RID p_rid) override;
virtual void _multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false, bool p_use_indirect = false) override;
virtual int _multimesh_get_instance_count(RID p_multimesh) const override;
virtual void _multimesh_set_mesh(RID p_multimesh, RID p_mesh) override;
virtual void _multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) override;
virtual void _multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) override;
virtual void _multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) override;
virtual void _multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) override;
virtual RID _multimesh_get_mesh(RID p_multimesh) const override;
virtual Transform3D _multimesh_instance_get_transform(RID p_multimesh, int p_index) const override;
virtual Transform2D _multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const override;
virtual Color _multimesh_instance_get_color(RID p_multimesh, int p_index) const override;
virtual Color _multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override;
virtual void _multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override;
virtual RID _multimesh_get_command_buffer_rd_rid(RID p_multimesh) const override;
virtual RID _multimesh_get_buffer_rd_rid(RID p_multimesh) const override;
virtual Vector<float> _multimesh_get_buffer(RID p_multimesh) const override;
virtual void _multimesh_set_visible_instances(RID p_multimesh, int p_visible) override;
virtual int _multimesh_get_visible_instances(RID p_multimesh) const override;
virtual void _multimesh_set_custom_aabb(RID p_multimesh, const AABB &p_aabb) override;
virtual AABB _multimesh_get_custom_aabb(RID p_multimesh) const override;
virtual AABB _multimesh_get_aabb(RID p_multimesh) override;
virtual MultiMeshInterpolator *_multimesh_get_interpolator(RID p_multimesh) const override;
void _update_dirty_multimeshes();
void _multimesh_get_motion_vectors_offsets(RID p_multimesh, uint32_t &r_current_offset, uint32_t &r_prev_offset);
bool _multimesh_uses_motion_vectors_offsets(RID p_multimesh);
bool _multimesh_uses_motion_vectors(RID p_multimesh);
_FORCE_INLINE_ bool multimesh_uses_indirect(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL_V(multimesh, false);
return multimesh->indirect;
}
_FORCE_INLINE_ RS::MultimeshTransformFormat multimesh_get_transform_format(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL_V(multimesh, RS::MULTIMESH_TRANSFORM_3D);
return multimesh->xform_format;
}
_FORCE_INLINE_ bool multimesh_uses_colors(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL_V(multimesh, false);
return multimesh->uses_colors;
}
_FORCE_INLINE_ bool multimesh_uses_custom_data(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL_V(multimesh, false);
return multimesh->uses_custom_data;
}
_FORCE_INLINE_ uint32_t multimesh_get_instances_to_draw(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL_V(multimesh, 0);
if (multimesh->visible_instances >= 0) {
return multimesh->visible_instances;
}
return multimesh->instances;
}
_FORCE_INLINE_ RID multimesh_get_3d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
if (multimesh == nullptr) {
return RID();
}
if (!multimesh->uniform_set_3d.is_valid()) {
if (!multimesh->buffer.is_valid()) {
return RID();
}
Vector<RD::Uniform> uniforms;
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 0;
u.append_id(multimesh->buffer);
uniforms.push_back(u);
multimesh->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
}
return multimesh->uniform_set_3d;
}
_FORCE_INLINE_ RID multimesh_get_2d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
if (multimesh == nullptr) {
return RID();
}
if (!multimesh->uniform_set_2d.is_valid()) {
if (!multimesh->buffer.is_valid()) {
return RID();
}
Vector<RD::Uniform> uniforms;
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 0;
u.append_id(multimesh->buffer);
uniforms.push_back(u);
multimesh->uniform_set_2d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
}
return multimesh->uniform_set_2d;
}
Dependency *multimesh_get_dependency(RID p_multimesh) const;
/* SKELETON API */
bool owns_skeleton(RID p_rid) const { return skeleton_owner.owns(p_rid); }
virtual RID skeleton_allocate() override;
virtual void skeleton_initialize(RID p_skeleton) override;
virtual void skeleton_free(RID p_rid) override;
virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) override;
virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) override;
virtual int skeleton_get_bone_count(RID p_skeleton) const override;
virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) override;
virtual Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const override;
virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override;
virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override;
virtual void skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance) override;
void _update_dirty_skeletons();
_FORCE_INLINE_ bool skeleton_is_valid(RID p_skeleton) {
return skeleton_owner.get_or_null(p_skeleton) != nullptr;
}
_FORCE_INLINE_ RID skeleton_get_3d_uniform_set(RID p_skeleton, RID p_shader, uint32_t p_set) const {
Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
ERR_FAIL_NULL_V(skeleton, RID());
if (skeleton->size == 0) {
return RID();
}
if (skeleton->use_2d) {
return RID();
}
if (!skeleton->uniform_set_3d.is_valid()) {
Vector<RD::Uniform> uniforms;
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 0;
u.append_id(skeleton->buffer);
uniforms.push_back(u);
skeleton->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
}
return skeleton->uniform_set_3d;
}
};
} // namespace RendererRD

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,600 @@
/**************************************************************************/
/* particles_storage.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "core/templates/local_vector.h"
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
#include "servers/rendering/renderer_rd/effects/sort_effects.h"
#include "servers/rendering/renderer_rd/shaders/particles.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/particles_copy.glsl.gen.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/shader_compiler.h"
#include "servers/rendering/storage/particles_storage.h"
#include "servers/rendering/storage/utilities.h"
namespace RendererRD {
class ParticlesStorage : public RendererParticlesStorage {
private:
static ParticlesStorage *singleton;
/* EFFECTS */
SortEffects *sort_effects = nullptr;
/* PARTICLES */
enum {
BASE_UNIFORM_SET,
MATERIAL_UNIFORM_SET,
COLLISION_TEXTURTES_UNIFORM_SET,
};
const int SAMPLERS_BINDING_FIRST_INDEX = 3;
struct ParticleData {
float xform[16];
float velocity[3];
uint32_t active;
float color[4];
float custom[4];
};
struct ParticlesFrameParams {
enum {
MAX_ATTRACTORS = 32,
MAX_COLLIDERS = 32,
MAX_3D_TEXTURES = 7
};
enum AttractorType {
ATTRACTOR_TYPE_SPHERE,
ATTRACTOR_TYPE_BOX,
ATTRACTOR_TYPE_VECTOR_FIELD,
};
struct Attractor {
float transform[16];
float extents[3]; //exents or radius
uint32_t type;
uint32_t texture_index; //texture index for vector field
float strength;
float attenuation;
float directionality;
};
enum CollisionType {
COLLISION_TYPE_SPHERE,
COLLISION_TYPE_BOX,
COLLISION_TYPE_SDF,
COLLISION_TYPE_HEIGHT_FIELD,
COLLISION_TYPE_2D_SDF,
};
struct Collider {
float transform[16];
float extents[3]; //exents or radius
uint32_t type;
uint32_t texture_index; //texture index for vector field
float scale;
uint32_t pad[2];
};
uint32_t emitting;
float system_phase;
float prev_system_phase;
uint32_t cycle;
float explosiveness;
float randomness;
float time;
float delta;
uint32_t frame;
float amount_ratio;
uint32_t pad1;
uint32_t pad2;
uint32_t random_seed;
uint32_t attractor_count;
uint32_t collider_count;
float particle_size;
float emission_transform[16];
float emitter_velocity[3];
float interp_to_end;
Attractor attractors[MAX_ATTRACTORS];
Collider colliders[MAX_COLLIDERS];
};
struct ParticleEmissionBuffer {
struct Data {
float xform[16];
float velocity[3];
uint32_t flags;
float color[4];
float custom[4];
};
int32_t particle_count;
int32_t particle_max;
uint32_t pad1;
uint32_t pad2;
Data data[1]; //its 2020 and empty arrays are still non standard in C++
};
struct Particles {
RS::ParticlesMode mode = RS::PARTICLES_MODE_3D;
bool inactive = true;
double inactive_time = 0.0;
bool emitting = false;
bool one_shot = false;
int amount = 0;
double lifetime = 1.0;
double pre_process_time = 0.0;
real_t request_process_time = 0.0;
real_t explosiveness = 0.0;
real_t randomness = 0.0;
bool restart_request = false;
AABB custom_aabb = AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8));
bool use_local_coords = false;
bool has_collision_cache = false;
bool has_sdf_collision = false;
Transform2D sdf_collision_transform;
Rect2 sdf_collision_to_screen;
RID sdf_collision_texture;
RID process_material;
uint32_t frame_counter = 0;
RS::ParticlesTransformAlign transform_align = RS::PARTICLES_TRANSFORM_ALIGN_DISABLED;
RS::ParticlesDrawOrder draw_order = RS::PARTICLES_DRAW_ORDER_INDEX;
Vector<RID> draw_passes;
Vector<Transform3D> trail_bind_poses;
bool trail_bind_poses_dirty = false;
RID trail_bind_pose_buffer;
RID trail_bind_pose_uniform_set;
RID particle_buffer;
RID particle_instance_buffer;
RID frame_params_buffer;
uint32_t userdata_count = 0;
RID particles_material_uniform_set;
RID particles_copy_uniform_set;
RID particles_transforms_buffer_uniform_set;
RID collision_textures_uniform_set;
RID collision_3d_textures[ParticlesFrameParams::MAX_3D_TEXTURES];
uint32_t collision_3d_textures_used = 0;
RID collision_heightmap_texture;
RID particles_sort_buffer;
RID particles_sort_uniform_set;
bool dirty = false;
SelfList<Particles> update_list;
RID sub_emitter;
double phase = 0.0;
double prev_phase = 0.0;
uint64_t prev_ticks = 0;
uint32_t random_seed = 0;
uint32_t cycle_number = 0;
double speed_scale = 1.0;
int fixed_fps = 30;
bool interpolate = true;
bool fractional_delta = false;
double frame_remainder = 0;
real_t collision_base_size = 0.01;
uint32_t instance_motion_vectors_current_offset = 0;
uint32_t instance_motion_vectors_previous_offset = 0;
uint64_t instance_motion_vectors_last_change = -1;
bool instance_motion_vectors_enabled = false;
bool clear = true;
bool force_sub_emit = false;
Transform3D emission_transform;
Vector3 emitter_velocity;
float interp_to_end = 0.0;
float amount_ratio = 1.0;
Vector<uint8_t> emission_buffer_data;
ParticleEmissionBuffer *emission_buffer = nullptr;
RID emission_storage_buffer;
RID unused_emission_storage_buffer;
RID unused_trail_storage_buffer;
HashSet<RID> collisions;
Dependency dependency;
double trail_lifetime = 0.3;
bool trails_enabled = false;
LocalVector<ParticlesFrameParams> frame_history;
LocalVector<ParticlesFrameParams> trail_params;
Particles() :
update_list(this) {
random_seed = Math::rand();
}
};
void _particles_process(Particles *p_particles, double p_delta);
void _particles_allocate_emission_buffer(Particles *particles);
void _particles_ensure_unused_emission_buffer(Particles *particles);
void _particles_ensure_unused_trail_buffer(Particles *particles);
void _particles_free_data(Particles *particles);
void _particles_update_buffers(Particles *particles);
struct ParticlesShader {
struct PushConstant {
float lifetime;
uint32_t clear;
uint32_t total_particles;
uint32_t trail_size;
uint32_t use_fractional_delta;
uint32_t sub_emitter_mode;
uint32_t can_emit;
uint32_t trail_pass;
};
ParticlesShaderRD shader;
ShaderCompiler compiler;
RID default_shader;
RID default_material;
RID default_shader_rd;
RID base_uniform_set;
struct CopyPushConstant {
float sort_direction[3];
uint32_t total_particles;
uint32_t trail_size;
uint32_t trail_total;
float frame_delta;
float frame_remainder;
float align_up[3];
uint32_t align_mode;
uint32_t lifetime_split;
uint32_t lifetime_reverse;
uint32_t motion_vectors_current_offset;
struct {
uint32_t order_by_lifetime : 1;
uint32_t copy_mode_2d : 1;
};
float inv_emission_transform[16];
};
enum {
MAX_USERDATAS = 6
};
enum {
COPY_MODE_FILL_INSTANCES,
COPY_MODE_FILL_SORT_BUFFER,
COPY_MODE_FILL_INSTANCES_WITH_SORT_BUFFER,
COPY_MODE_MAX,
};
ParticlesCopyShaderRD copy_shader;
RID copy_shader_version;
RID copy_pipelines[COPY_MODE_MAX * (MAX_USERDATAS + 1)];
LocalVector<float> pose_update_buffer;
} particles_shader;
SelfList<Particles>::List particle_update_list;
mutable RID_Owner<Particles, true> particles_owner;
/* Particle Shader */
struct ParticlesShaderData : public MaterialStorage::ShaderData {
bool valid = false;
RID version;
bool uses_collision = false;
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
uint32_t ubo_size = 0;
String code;
RID pipeline;
bool uses_time = false;
bool userdatas_used[ParticlesShader::MAX_USERDATAS] = {};
uint32_t userdata_count = 0;
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;
virtual Pair<ShaderRD *, RID> get_native_shader_and_version() const;
ParticlesShaderData() {}
virtual ~ParticlesShaderData();
};
MaterialStorage::ShaderData *_create_particles_shader_func();
static MaterialStorage::ShaderData *_create_particles_shader_funcs() {
return ParticlesStorage::get_singleton()->_create_particles_shader_func();
}
struct ParticleProcessMaterialData : public MaterialStorage::MaterialData {
ParticlesShaderData *shader_data = nullptr;
RID uniform_set;
virtual void set_render_priority(int p_priority) {}
virtual void set_next_pass(RID p_pass) {}
virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
virtual ~ParticleProcessMaterialData();
};
MaterialStorage::MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader);
static MaterialStorage::MaterialData *_create_particles_material_funcs(MaterialStorage::ShaderData *p_shader) {
return ParticlesStorage::get_singleton()->_create_particles_material_func(static_cast<ParticlesShaderData *>(p_shader));
}
/* Particles Collision */
struct ParticlesCollision {
RS::ParticlesCollisionType type = RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT;
uint32_t cull_mask = 0xFFFFFFFF;
float radius = 1.0;
Vector3 extents = Vector3(1, 1, 1);
float attractor_strength = 1.0;
float attractor_attenuation = 1.0;
float attractor_directionality = 0.0;
RID field_texture;
RID heightfield_texture;
RID heightfield_fb;
Size2i heightfield_fb_size;
uint32_t heightfield_mask = (1 << 20) - 1;
RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024;
Dependency dependency;
};
struct ParticlesCollisionInstance {
RID collision;
Transform3D transform;
bool active = false;
};
mutable RID_Owner<ParticlesCollision, true> particles_collision_owner;
mutable RID_Owner<ParticlesCollisionInstance> particles_collision_instance_owner;
public:
static ParticlesStorage *get_singleton();
ParticlesStorage();
virtual ~ParticlesStorage();
bool free(RID p_rid);
/* PARTICLES */
bool owns_particles(RID p_rid) { return particles_owner.owns(p_rid); }
virtual RID particles_allocate() override;
virtual void particles_initialize(RID p_rid) override;
virtual void particles_free(RID p_rid) override;
virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override;
virtual void particles_set_emitting(RID p_particles, bool p_emitting) override;
virtual void particles_set_amount(RID p_particles, int p_amount) override;
virtual void particles_set_amount_ratio(RID p_particles, float p_amount_ratio) override;
virtual void particles_set_lifetime(RID p_particles, double p_lifetime) override;
virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) override;
virtual void particles_set_pre_process_time(RID p_particles, double p_time) override;
virtual void particles_request_process_time(RID p_particles, real_t p_request_process_time) override;
virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override;
virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override;
virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override;
virtual void particles_set_speed_scale(RID p_particles, double p_scale) override;
virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override;
virtual void particles_set_process_material(RID p_particles, RID p_material) override;
virtual RID particles_get_process_material(RID p_particles) const override;
virtual void particles_set_fixed_fps(RID p_particles, int p_fps) override;
virtual void particles_set_interpolate(RID p_particles, bool p_enable) override;
virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) override;
virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) override;
virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override;
virtual void particles_set_seed(RID p_particles, uint32_t p_seed) override;
virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) override;
virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override;
virtual void particles_restart(RID p_particles) override;
virtual void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override;
virtual void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) override;
virtual void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) override;
virtual void particles_set_draw_passes(RID p_particles, int p_count) override;
virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) override;
virtual void particles_request_process(RID p_particles) override;
virtual AABB particles_get_current_aabb(RID p_particles) override;
virtual AABB particles_get_aabb(RID p_particles) const override;
virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override;
virtual void particles_set_emitter_velocity(RID p_particles, const Vector3 &p_velocity) override;
virtual void particles_set_interp_to_end(RID p_particles, float p_interp_to_end) override;
virtual bool particles_get_emitting(RID p_particles) override;
virtual int particles_get_draw_passes(RID p_particles) const override;
virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const override;
virtual void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) override;
virtual bool particles_is_inactive(RID p_particles) const override;
_FORCE_INLINE_ RS::ParticlesMode particles_get_mode(RID p_particles) {
Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_NULL_V(particles, RS::PARTICLES_MODE_2D);
return particles->mode;
}
_FORCE_INLINE_ uint32_t particles_get_frame_counter(RID p_particles) {
Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_NULL_V(particles, false);
return particles->frame_counter;
}
_FORCE_INLINE_ uint32_t particles_get_amount(RID p_particles, uint32_t &r_trail_divisor) {
Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_NULL_V(particles, 0);
if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
r_trail_divisor = particles->trail_bind_poses.size();
} else {
r_trail_divisor = 1;
}
return particles->amount * r_trail_divisor;
}
_FORCE_INLINE_ bool particles_has_collision(RID p_particles) {
Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_NULL_V(particles, false);
return particles->has_collision_cache;
}
_FORCE_INLINE_ uint32_t particles_is_using_local_coords(RID p_particles) {
Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_NULL_V(particles, false);
return particles->use_local_coords;
}
_FORCE_INLINE_ RID particles_get_instance_buffer_uniform_set(RID p_particles, RID p_shader, uint32_t p_set) {
Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_NULL_V(particles, RID());
if (particles->particles_transforms_buffer_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(particles->particles_transforms_buffer_uniform_set)) {
_particles_update_buffers(particles);
Vector<RD::Uniform> uniforms;
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 0;
u.append_id(particles->particle_instance_buffer);
uniforms.push_back(u);
}
particles->particles_transforms_buffer_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
}
return particles->particles_transforms_buffer_uniform_set;
}
void particles_get_instance_buffer_motion_vectors_offsets(RID p_particles, uint32_t &r_current_offset, uint32_t &r_prev_offset);
virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance) override;
virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance) override;
void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture);
virtual void update_particles() override;
void particles_update_dependency(RID p_particles, DependencyTracker *p_instance);
Dependency *particles_get_dependency(RID p_particles) const;
/* Particles Collision */
bool owns_particles_collision(RID p_rid) { return particles_collision_owner.owns(p_rid); }
virtual RID particles_collision_allocate() override;
virtual void particles_collision_initialize(RID p_particles_collision) override;
virtual void particles_collision_free(RID p_rid) override;
virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) override;
virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) override;
virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) override; //for spheres
virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) override; //for non-spheres
virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) override;
virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) override;
virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) override;
virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) override; //for SDF and vector field, heightfield is dynamic
virtual void particles_collision_height_field_update(RID p_particles_collision) override; //for SDF and vector field
virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override; //for SDF and vector field
virtual AABB particles_collision_get_aabb(RID p_particles_collision) const override;
Vector3 particles_collision_get_extents(RID p_particles_collision) const;
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override;
RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const;
virtual uint32_t particles_collision_get_height_field_mask(RID p_particles_collision) const override;
virtual void particles_collision_set_height_field_mask(RID p_particles_collision, uint32_t p_heightfield_mask) override;
virtual uint32_t particles_collision_get_cull_mask(RID p_particles_collision) const override;
Dependency *particles_collision_get_dependency(RID p_particles) const;
//used from 2D and 3D
bool owns_particles_collision_instance(RID p_rid) { return particles_collision_instance_owner.owns(p_rid); }
virtual RID particles_collision_instance_create(RID p_collision) override;
virtual void particles_collision_instance_free(RID p_rid) override;
virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override;
virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override;
};
} // namespace RendererRD

View File

@@ -0,0 +1,45 @@
/**************************************************************************/
/* render_buffer_custom_data_rd.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "core/object/ref_counted.h"
class RenderSceneBuffersRD;
class RenderBufferCustomDataRD : public RefCounted {
GDCLASS(RenderBufferCustomDataRD, RefCounted);
public:
virtual void configure(RenderSceneBuffersRD *p_render_buffers) = 0;
virtual void free_data() = 0; // called on cleanup
private:
};

View File

@@ -0,0 +1,47 @@
/**************************************************************************/
/* render_data_rd.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#include "render_data_rd.h"
Ref<RenderSceneBuffers> RenderDataRD::get_render_scene_buffers() const {
return render_buffers;
}
RenderSceneData *RenderDataRD::get_render_scene_data() const {
return scene_data;
}
RID RenderDataRD::get_environment() const {
return environment;
}
RID RenderDataRD::get_camera_attributes() const {
return camera_attributes;
}

View File

@@ -0,0 +1,97 @@
/**************************************************************************/
/* render_data_rd.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h"
#include "servers/rendering/storage/render_data.h"
class RenderDataRD : public RenderData {
GDCLASS(RenderDataRD, RenderData);
public:
// Access methods to expose data externally
virtual Ref<RenderSceneBuffers> get_render_scene_buffers() const override;
virtual RenderSceneData *get_render_scene_data() const override;
virtual RID get_environment() const override;
virtual RID get_camera_attributes() const override;
// Members are publicly accessible within the render engine.
Ref<RenderSceneBuffersRD> render_buffers;
RenderSceneDataRD *scene_data = nullptr;
const PagedArray<RenderGeometryInstance *> *instances = nullptr;
const PagedArray<RID> *lights = nullptr;
const PagedArray<RID> *reflection_probes = nullptr;
const PagedArray<RID> *voxel_gi_instances = nullptr;
const PagedArray<RID> *decals = nullptr;
const PagedArray<RID> *lightmaps = nullptr;
const PagedArray<RID> *fog_volumes = nullptr;
RID environment;
RID camera_attributes;
RID compositor;
RID shadow_atlas;
RID occluder_debug_tex;
RID reflection_atlas;
RID reflection_probe;
int reflection_probe_pass = 0;
RID cluster_buffer;
uint32_t cluster_size = 0;
uint32_t cluster_max_elements = 0;
uint32_t directional_light_count = 0;
bool directional_light_soft_shadows = false;
bool lightmap_bicubic_filter = false;
RenderingMethod::RenderInfo *render_info = nullptr;
/* Viewport data */
bool transparent_bg = false;
Rect2i render_region;
/* Shadow data */
const RendererSceneRender::RenderShadowData *render_shadows = nullptr;
int render_shadow_count = 0;
LocalVector<int> cube_shadows;
LocalVector<int> shadows;
LocalVector<int> directional_shadows;
/* GI info */
const RendererSceneRender::RenderSDFGIData *render_sdfgi_regions = nullptr;
int render_sdfgi_region_count = 0;
const RendererSceneRender::RenderSDFGIUpdateData *sdfgi_update_data = nullptr;
uint32_t voxel_gi_count = 0;
};

View File

@@ -0,0 +1,72 @@
/**************************************************************************/
/* render_scene_buffers_rd.compat.inc */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#ifndef DISABLE_DEPRECATED
RID RenderSceneBuffersRD::_get_color_texture_compat_80214() {
return _get_color_texture(msaa_3d != RS::VIEWPORT_MSAA_DISABLED);
}
RID RenderSceneBuffersRD::_get_color_layer_compat_80214(const uint32_t p_layer) {
return _get_color_layer(p_layer, msaa_3d != RS::VIEWPORT_MSAA_DISABLED);
}
RID RenderSceneBuffersRD::_get_depth_texture_compat_80214() {
return _get_depth_texture(msaa_3d != RS::VIEWPORT_MSAA_DISABLED);
}
RID RenderSceneBuffersRD::_get_depth_layer_compat_80214(const uint32_t p_layer) {
return _get_depth_layer(p_layer, msaa_3d != RS::VIEWPORT_MSAA_DISABLED);
}
RID RenderSceneBuffersRD::_get_velocity_texture_compat_80214() {
return _get_velocity_texture(msaa_3d != RS::VIEWPORT_MSAA_DISABLED);
}
RID RenderSceneBuffersRD::_get_velocity_layer_compat_80214(const uint32_t p_layer) {
return _get_velocity_layer(p_layer, msaa_3d != RS::VIEWPORT_MSAA_DISABLED);
}
RID RenderSceneBuffersRD::_create_texture_bind_compat_98670(const StringName &p_context, const StringName &p_texture_name, const RD::DataFormat p_data_format, const uint32_t p_usage_bits, const RD::TextureSamples p_texture_samples, const Size2i p_size, const uint32_t p_layers, const uint32_t p_mipmaps, bool p_unique) {
return create_texture(p_context, p_texture_name, p_data_format, p_usage_bits, p_texture_samples, p_size, p_layers, p_mipmaps, p_unique, false);
}
void RenderSceneBuffersRD::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("get_color_texture"), &RenderSceneBuffersRD::_get_color_texture_compat_80214);
ClassDB::bind_compatibility_method(D_METHOD("get_color_layer", "layer"), &RenderSceneBuffersRD::_get_color_layer_compat_80214);
ClassDB::bind_compatibility_method(D_METHOD("get_depth_texture"), &RenderSceneBuffersRD::_get_depth_texture_compat_80214);
ClassDB::bind_compatibility_method(D_METHOD("get_depth_layer", "layer"), &RenderSceneBuffersRD::_get_depth_layer_compat_80214);
ClassDB::bind_compatibility_method(D_METHOD("get_velocity_texture"), &RenderSceneBuffersRD::_get_velocity_texture_compat_80214);
ClassDB::bind_compatibility_method(D_METHOD("get_velocity_layer", "layer"), &RenderSceneBuffersRD::_get_velocity_layer_compat_80214);
ClassDB::bind_compatibility_method(D_METHOD("create_texture", "context", "name", "data_format", "usage_bits", "texture_samples", "size", "layers", "mipmaps", "unique"), &RenderSceneBuffersRD::_create_texture_bind_compat_98670);
}
#endif // DISABLE_DEPRECATED

View File

@@ -0,0 +1,777 @@
/**************************************************************************/
/* render_scene_buffers_rd.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#include "render_scene_buffers_rd.h"
#include "render_scene_buffers_rd.compat.inc"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
RenderSceneBuffersRD::RenderSceneBuffersRD() {
}
RenderSceneBuffersRD::~RenderSceneBuffersRD() {
cleanup();
data_buffers.clear();
RendererRD::MaterialStorage::get_singleton()->samplers_rd_free(samplers);
}
void RenderSceneBuffersRD::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_texture", "context", "name"), &RenderSceneBuffersRD::has_texture);
ClassDB::bind_method(D_METHOD("create_texture", "context", "name", "data_format", "usage_bits", "texture_samples", "size", "layers", "mipmaps", "unique", "discardable"), &RenderSceneBuffersRD::create_texture);
ClassDB::bind_method(D_METHOD("create_texture_from_format", "context", "name", "format", "view", "unique"), &RenderSceneBuffersRD::_create_texture_from_format);
ClassDB::bind_method(D_METHOD("create_texture_view", "context", "name", "view_name", "view"), &RenderSceneBuffersRD::_create_texture_view);
ClassDB::bind_method(D_METHOD("get_texture", "context", "name"), &RenderSceneBuffersRD::get_texture);
ClassDB::bind_method(D_METHOD("get_texture_format", "context", "name"), &RenderSceneBuffersRD::_get_texture_format);
ClassDB::bind_method(D_METHOD("get_texture_slice", "context", "name", "layer", "mipmap", "layers", "mipmaps"), &RenderSceneBuffersRD::get_texture_slice);
ClassDB::bind_method(D_METHOD("get_texture_slice_view", "context", "name", "layer", "mipmap", "layers", "mipmaps", "view"), &RenderSceneBuffersRD::_get_texture_slice_view);
ClassDB::bind_method(D_METHOD("get_texture_slice_size", "context", "name", "mipmap"), &RenderSceneBuffersRD::get_texture_slice_size);
ClassDB::bind_method(D_METHOD("clear_context", "context"), &RenderSceneBuffersRD::clear_context);
// Access to some core buffers so users don't need to know their names.
ClassDB::bind_method(D_METHOD("get_color_texture", "msaa"), &RenderSceneBuffersRD::_get_color_texture, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_color_layer", "layer", "msaa"), &RenderSceneBuffersRD::_get_color_layer, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_depth_texture", "msaa"), &RenderSceneBuffersRD::_get_depth_texture, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_depth_layer", "layer", "msaa"), &RenderSceneBuffersRD::_get_depth_layer, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_velocity_texture", "msaa"), &RenderSceneBuffersRD::_get_velocity_texture, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_velocity_layer", "layer", "msaa"), &RenderSceneBuffersRD::_get_velocity_layer, DEFVAL(false));
// Expose a few properties we're likely to use externally
ClassDB::bind_method(D_METHOD("get_render_target"), &RenderSceneBuffersRD::get_render_target);
ClassDB::bind_method(D_METHOD("get_view_count"), &RenderSceneBuffersRD::get_view_count);
ClassDB::bind_method(D_METHOD("get_internal_size"), &RenderSceneBuffersRD::get_internal_size);
ClassDB::bind_method(D_METHOD("get_target_size"), &RenderSceneBuffersRD::get_target_size);
ClassDB::bind_method(D_METHOD("get_scaling_3d_mode"), &RenderSceneBuffersRD::get_scaling_3d_mode);
ClassDB::bind_method(D_METHOD("get_fsr_sharpness"), &RenderSceneBuffersRD::get_fsr_sharpness);
ClassDB::bind_method(D_METHOD("get_msaa_3d"), &RenderSceneBuffersRD::get_msaa_3d);
ClassDB::bind_method(D_METHOD("get_texture_samples"), &RenderSceneBuffersRD::get_texture_samples);
ClassDB::bind_method(D_METHOD("get_screen_space_aa"), &RenderSceneBuffersRD::get_screen_space_aa);
ClassDB::bind_method(D_METHOD("get_use_taa"), &RenderSceneBuffersRD::get_use_taa);
ClassDB::bind_method(D_METHOD("get_use_debanding"), &RenderSceneBuffersRD::get_use_debanding);
}
void RenderSceneBuffersRD::update_sizes(NamedTexture &p_named_texture) {
ERR_FAIL_COND(p_named_texture.texture.is_null());
p_named_texture.sizes.resize(p_named_texture.format.mipmaps);
Size2i mipmap_size = Size2i(p_named_texture.format.width, p_named_texture.format.height);
for (uint32_t mipmap = 0; mipmap < p_named_texture.format.mipmaps; mipmap++) {
p_named_texture.sizes.ptrw()[mipmap] = mipmap_size;
mipmap_size = Size2i(mipmap_size.width >> 1, mipmap_size.height >> 1).maxi(1);
}
}
void RenderSceneBuffersRD::free_named_texture(NamedTexture &p_named_texture) {
if (p_named_texture.texture.is_valid()) {
RD::get_singleton()->free(p_named_texture.texture);
}
p_named_texture.texture = RID();
p_named_texture.slices.clear(); // slices should be freed automatically as dependents...
}
void RenderSceneBuffersRD::update_samplers() {
float computed_mipmap_bias = texture_mipmap_bias;
if (use_taa || (RS::scaling_3d_mode_type(scaling_3d_mode) == RS::VIEWPORT_SCALING_3D_TYPE_TEMPORAL)) {
// Use negative mipmap LOD bias when TAA or FSR2 is enabled to compensate for loss of sharpness.
// This restores sharpness in still images to be roughly at the same level as without TAA,
// but moving scenes will still be blurrier.
computed_mipmap_bias -= 0.5;
}
if (screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) {
// Use negative mipmap LOD bias when FXAA is enabled to compensate for loss of sharpness.
// If both TAA and FXAA are enabled, combine their negative LOD biases together.
computed_mipmap_bias -= 0.25;
}
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
material_storage->samplers_rd_free(samplers);
samplers = material_storage->samplers_rd_allocate(computed_mipmap_bias, anisotropic_filtering_level);
}
void RenderSceneBuffersRD::cleanup() {
// Free our data buffers (but don't destroy them)
for (KeyValue<StringName, Ref<RenderBufferCustomDataRD>> &E : data_buffers) {
E.value->free_data();
}
// Clear our named textures
for (KeyValue<NTKey, NamedTexture> &E : named_textures) {
free_named_texture(E.value);
}
named_textures.clear();
// Clear weight_buffer / blur textures.
for (WeightBuffers &weight_buffer : weight_buffers) {
if (weight_buffer.weight.is_valid()) {
RD::get_singleton()->free(weight_buffer.weight);
weight_buffer.weight = RID();
}
}
#ifdef METAL_ENABLED
if (mfx_spatial_context) {
memdelete(mfx_spatial_context);
mfx_spatial_context = nullptr;
}
#endif
}
void RenderSceneBuffersRD::configure(const RenderSceneBuffersConfiguration *p_config) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
render_target = p_config->get_render_target();
target_size = p_config->get_target_size();
internal_size = p_config->get_internal_size();
view_count = p_config->get_view_count();
scaling_3d_mode = p_config->get_scaling_3d_mode();
msaa_3d = p_config->get_msaa_3d();
screen_space_aa = p_config->get_screen_space_aa();
fsr_sharpness = p_config->get_fsr_sharpness();
texture_mipmap_bias = p_config->get_texture_mipmap_bias();
anisotropic_filtering_level = p_config->get_anisotropic_filtering_level();
use_taa = p_config->get_use_taa();
use_debanding = p_config->get_use_debanding();
ERR_FAIL_COND_MSG(view_count == 0, "Must have at least 1 view");
vrs_mode = texture_storage->render_target_get_vrs_mode(render_target);
update_samplers();
// cleanout any old buffers we had.
cleanup();
// Create our color buffer.
const bool resolve_target = msaa_3d != RS::VIEWPORT_MSAA_DISABLED;
create_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR, base_data_format, get_color_usage_bits(resolve_target, false, can_be_storage));
// TODO: Detect when it is safe to use RD::TEXTURE_USAGE_TRANSIENT_BIT for RB_TEX_DEPTH, RB_TEX_COLOR_MSAA and/or RB_TEX_DEPTH_MSAA.
// (it means we cannot sample from it, we cannot copy from/to it) to save VRAM (and maybe performance too).
// Create our depth buffer.
create_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH, get_depth_format(resolve_target, false, can_be_storage), get_depth_usage_bits(resolve_target, false, can_be_storage));
// Create our MSAA buffers.
if (msaa_3d == RS::VIEWPORT_MSAA_DISABLED) {
texture_samples = RD::TEXTURE_SAMPLES_1;
} else {
texture_samples = msaa_to_samples(msaa_3d);
create_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR_MSAA, base_data_format, get_color_usage_bits(false, true, can_be_storage), texture_samples, Size2i(), 0, 1, true, true);
create_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_MSAA, get_depth_format(false, true, can_be_storage), get_depth_usage_bits(false, true, can_be_storage), texture_samples, Size2i(), 0, 1, true, true);
}
// VRS (note, our vrs object will only be set if VRS is supported)
RID vrs_texture;
if (vrs && vrs_mode != RS::VIEWPORT_VRS_DISABLED) {
vrs_texture = create_texture(RB_SCOPE_VRS, RB_TEXTURE, get_vrs_format(), get_vrs_usage_bits(), RD::TEXTURE_SAMPLES_1, vrs->get_vrs_texture_size(internal_size));
}
// (re-)configure any named buffers
for (KeyValue<StringName, Ref<RenderBufferCustomDataRD>> &E : data_buffers) {
E.value->configure(this);
}
}
void RenderSceneBuffersRD::configure_for_reflections(const Size2i p_reflection_size) {
// For now our render buffers for reflections are only used for effects/environment (Sky/Fog/Etc)
// Possibly at some point move our entire reflection atlas buffer management into this class
target_size = p_reflection_size;
internal_size = p_reflection_size;
render_target = RID();
scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF;
fsr_sharpness = 0.0;
msaa_3d = RS::VIEWPORT_MSAA_DISABLED;
screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
use_taa = false;
use_debanding = false;
view_count = 1;
// cleanout any old buffers we had.
cleanup();
// (re-)configure any named buffers
for (KeyValue<StringName, Ref<RenderBufferCustomDataRD>> &E : data_buffers) {
E.value->configure(this);
}
}
void RenderSceneBuffersRD::set_fsr_sharpness(float p_fsr_sharpness) {
fsr_sharpness = p_fsr_sharpness;
}
void RenderSceneBuffersRD::set_texture_mipmap_bias(float p_texture_mipmap_bias) {
texture_mipmap_bias = p_texture_mipmap_bias;
update_samplers();
}
void RenderSceneBuffersRD::set_anisotropic_filtering_level(RS::ViewportAnisotropicFiltering p_anisotropic_filtering_level) {
anisotropic_filtering_level = p_anisotropic_filtering_level;
update_samplers();
}
void RenderSceneBuffersRD::set_use_debanding(bool p_use_debanding) {
use_debanding = p_use_debanding;
}
#ifdef METAL_ENABLED
void RenderSceneBuffersRD::ensure_mfx(RendererRD::MFXSpatialEffect *p_effect) {
if (mfx_spatial_context) {
return;
}
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RenderingDevice *rd = RD::get_singleton();
// Determine the output format of the render target.
RID dest = texture_storage->render_target_get_rd_texture(render_target);
RD::TextureFormat tf = rd->texture_get_format(dest);
RD::DataFormat output_format = tf.format;
RendererRD::MFXSpatialEffect::CreateParams params = {
.input_size = internal_size,
.output_size = target_size,
.input_format = base_data_format,
.output_format = output_format,
};
mfx_spatial_context = p_effect->create_context(params);
}
#endif
// Named textures
bool RenderSceneBuffersRD::has_texture(const StringName &p_context, const StringName &p_texture_name) const {
NTKey key(p_context, p_texture_name);
return named_textures.has(key);
}
RID RenderSceneBuffersRD::create_texture(const StringName &p_context, const StringName &p_texture_name, const RD::DataFormat p_data_format, const uint32_t p_usage_bits, const RD::TextureSamples p_texture_samples, const Size2i p_size, const uint32_t p_layers, const uint32_t p_mipmaps, bool p_unique, bool p_discardable) {
// Keep some useful data, we use default values when these are 0.
Size2i size = p_size == Size2i(0, 0) ? internal_size : p_size;
uint32_t layers = p_layers == 0 ? view_count : p_layers;
uint32_t mipmaps = p_mipmaps == 0 ? 1 : p_mipmaps;
// Create our texture
RD::TextureFormat tf;
tf.format = p_data_format;
if (layers > 1) {
tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
}
tf.width = size.x;
tf.height = size.y;
tf.depth = 1;
tf.array_layers = layers;
tf.mipmaps = mipmaps;
tf.usage_bits = p_usage_bits;
tf.samples = p_texture_samples;
tf.is_discardable = p_discardable;
return create_texture_from_format(p_context, p_texture_name, tf, RD::TextureView(), p_unique);
}
RID RenderSceneBuffersRD::_create_texture_from_format(const StringName &p_context, const StringName &p_texture_name, const Ref<RDTextureFormat> &p_texture_format, const Ref<RDTextureView> &p_view, bool p_unique) {
ERR_FAIL_COND_V(p_texture_format.is_null(), RID());
RD::TextureView texture_view;
if (p_view.is_valid()) { // only use when supplied, else default.
texture_view = p_view->base;
}
return create_texture_from_format(p_context, p_texture_name, p_texture_format->base, texture_view, p_unique);
}
RID RenderSceneBuffersRD::create_texture_from_format(const StringName &p_context, const StringName &p_texture_name, const RD::TextureFormat &p_texture_format, RD::TextureView p_view, bool p_unique) {
// TODO p_unique, if p_unique is true, this is a texture that can be shared. This will be implemented later as an optimization.
NTKey key(p_context, p_texture_name);
// check if this is a known texture
if (named_textures.has(key)) {
return named_textures[key].texture;
}
// Add a new entry..
NamedTexture &named_texture = named_textures[key];
named_texture.format = p_texture_format;
named_texture.is_unique = p_unique;
named_texture.texture = RD::get_singleton()->texture_create(p_texture_format, p_view);
Array arr = { p_context, p_texture_name };
RD::get_singleton()->set_resource_name(named_texture.texture, String("RenderBuffer {0}/{1}").format(arr));
update_sizes(named_texture);
// The rest is lazy created..
return named_texture.texture;
}
RID RenderSceneBuffersRD::_create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName &p_view_name, const Ref<RDTextureView> p_view) {
RD::TextureView texture_view;
if (p_view.is_valid()) { // only use when supplied, else default.
texture_view = p_view->base;
}
return create_texture_view(p_context, p_texture_name, p_view_name, texture_view);
}
RID RenderSceneBuffersRD::create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName &p_view_name, RD::TextureView p_view) {
NTKey view_key(p_context, p_view_name);
// check if this is a known texture
if (named_textures.has(view_key)) {
return named_textures[view_key].texture;
}
NTKey key(p_context, p_texture_name);
ERR_FAIL_COND_V(!named_textures.has(key), RID());
NamedTexture &named_texture = named_textures[key];
NamedTexture &view_texture = named_textures[view_key];
view_texture.format = named_texture.format;
view_texture.is_unique = named_texture.is_unique;
view_texture.texture = RD::get_singleton()->texture_create_shared(p_view, named_texture.texture);
Array arr = { p_context, p_view_name };
RD::get_singleton()->set_resource_name(view_texture.texture, String("RenderBuffer View {0}/{1}").format(arr));
update_sizes(named_texture);
return view_texture.texture;
}
RID RenderSceneBuffersRD::get_texture(const StringName &p_context, const StringName &p_texture_name) const {
NTKey key(p_context, p_texture_name);
ERR_FAIL_COND_V(!named_textures.has(key), RID());
return named_textures[key].texture;
}
Ref<RDTextureFormat> RenderSceneBuffersRD::_get_texture_format(const StringName &p_context, const StringName &p_texture_name) const {
Ref<RDTextureFormat> tf;
tf.instantiate();
tf->base = get_texture_format(p_context, p_texture_name);
return tf;
}
RID RenderSceneBuffersRD::_get_texture_slice_view(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap, const uint32_t p_layers, const uint32_t p_mipmaps, const Ref<RDTextureView> p_view) {
RD::TextureView texture_view;
if (p_view.is_valid()) {
texture_view = p_view->base;
}
return get_texture_slice_view(p_context, p_texture_name, p_layer, p_mipmap, p_layers, p_mipmaps, texture_view);
}
const RD::TextureFormat RenderSceneBuffersRD::get_texture_format(const StringName &p_context, const StringName &p_texture_name) const {
NTKey key(p_context, p_texture_name);
ERR_FAIL_COND_V(!named_textures.has(key), RD::TextureFormat());
return named_textures[key].format;
}
RID RenderSceneBuffersRD::get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap, const uint32_t p_layers, const uint32_t p_mipmaps) {
return get_texture_slice_view(p_context, p_texture_name, p_layer, p_mipmap, p_layers, p_mipmaps, RD::TextureView());
}
RID RenderSceneBuffersRD::get_texture_slice_view(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap, const uint32_t p_layers, const uint32_t p_mipmaps, RD::TextureView p_view) {
NTKey key(p_context, p_texture_name);
// check if this is a known texture
ERR_FAIL_COND_V(!named_textures.has(key), RID());
NamedTexture &named_texture = named_textures[key];
ERR_FAIL_COND_V(named_texture.texture.is_null(), RID());
// check if we're in bounds
ERR_FAIL_UNSIGNED_INDEX_V(p_layer, named_texture.format.array_layers, RID());
ERR_FAIL_COND_V(p_layers == 0, RID());
ERR_FAIL_COND_V(p_layer + p_layers > named_texture.format.array_layers, RID());
ERR_FAIL_UNSIGNED_INDEX_V(p_mipmap, named_texture.format.mipmaps, RID());
ERR_FAIL_COND_V(p_mipmaps == 0, RID());
ERR_FAIL_COND_V(p_mipmap + p_mipmaps > named_texture.format.mipmaps, RID());
// asking the whole thing? just return the original
RD::TextureView default_view = RD::TextureView();
if (p_layer == 0 && p_mipmap == 0 && named_texture.format.array_layers == p_layers && named_texture.format.mipmaps == p_mipmaps && p_view == default_view) {
return named_texture.texture;
}
// see if we have this
NTSliceKey slice_key(p_layer, p_layers, p_mipmap, p_mipmaps, p_view);
if (named_texture.slices.has(slice_key)) {
return named_texture.slices[slice_key];
}
// create our slice
RID &slice = named_texture.slices[slice_key];
slice = RD::get_singleton()->texture_create_shared_from_slice(p_view, named_texture.texture, p_layer, p_mipmap, p_mipmaps, p_layers > 1 ? RD::TEXTURE_SLICE_2D_ARRAY : RD::TEXTURE_SLICE_2D, p_layers);
Array arr = {
p_context,
p_texture_name,
itos(p_layer),
itos(p_layers),
itos(p_mipmap),
itos(p_mipmaps),
itos(p_view.format_override),
itos(p_view.swizzle_r),
itos(p_view.swizzle_g),
itos(p_view.swizzle_b),
itos(p_view.swizzle_a)
};
RD::get_singleton()->set_resource_name(slice, String("RenderBuffer {0}/{1}, layer {2}/{3}, mipmap {4}/{5}, view {6}/{7}/{8}/{9}/{10}").format(arr));
// and return our slice
return slice;
}
Size2i RenderSceneBuffersRD::get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_mipmap) {
NTKey key(p_context, p_texture_name);
// check if this is a known texture
ERR_FAIL_COND_V(!named_textures.has(key), Size2i());
NamedTexture &named_texture = named_textures[key];
ERR_FAIL_COND_V(named_texture.texture.is_null(), Size2i());
// check if we're in bounds
ERR_FAIL_UNSIGNED_INDEX_V(p_mipmap, named_texture.format.mipmaps, Size2i());
// return our size
return named_texture.sizes[p_mipmap];
}
void RenderSceneBuffersRD::clear_context(const StringName &p_context) {
Vector<NTKey> to_free; // free these
// Find all entries for our context, we don't want to free them yet or our loop fails.
for (KeyValue<NTKey, NamedTexture> &E : named_textures) {
if (E.key.context == p_context) {
to_free.push_back(E.key);
}
}
// Now free these and remove them from our textures
for (NTKey &key : to_free) {
free_named_texture(named_textures[key]);
named_textures.erase(key);
}
}
// Allocate shared buffers
void RenderSceneBuffersRD::allocate_blur_textures() {
if (has_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0)) {
// already allocated...
return;
}
Size2i blur_size = internal_size;
if (RS::scaling_3d_mode_type(scaling_3d_mode) == RS::VIEWPORT_SCALING_3D_TYPE_TEMPORAL) {
// The blur texture should be as big as the target size when using an upscaler.
blur_size = target_size;
}
uint32_t mipmaps_required = Image::get_image_required_mipmaps(blur_size.x, blur_size.y, Image::FORMAT_RGBAH);
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
if (can_be_storage) {
usage_bits += RD::TEXTURE_USAGE_STORAGE_BIT;
} else {
usage_bits += RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
}
create_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, base_data_format, usage_bits, RD::TEXTURE_SAMPLES_1, blur_size, view_count, mipmaps_required);
create_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, base_data_format, usage_bits, RD::TEXTURE_SAMPLES_1, Size2i(blur_size.x >> 1, blur_size.y >> 1), view_count, mipmaps_required - 1);
// if !can_be_storage we need a half width version
if (!can_be_storage) {
create_texture(RB_SCOPE_BUFFERS, RB_TEX_HALF_BLUR, base_data_format, usage_bits, RD::TEXTURE_SAMPLES_1, Size2i(blur_size.x >> 1, blur_size.y), 1, mipmaps_required);
}
// TODO redo this:
if (!can_be_storage) {
// create 4 weight textures, 2 full size, 2 half size
RD::TextureFormat tf;
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 = blur_size.x;
tf.height = blur_size.y;
tf.texture_type = RD::TEXTURE_TYPE_2D;
tf.array_layers = 1; // Our DOF effect handles one eye per turn
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
tf.mipmaps = 1;
for (uint32_t i = 0; i < 4; i++) {
// associated blur texture
RID texture;
if (i == 1) {
texture = get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, 0, 0);
} else if (i == 2) {
texture = get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, 0, 0);
} else if (i == 3) {
texture = get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, 0, 1);
}
// create weight texture
weight_buffers[i].weight = RD::get_singleton()->texture_create(tf, RD::TextureView());
// create frame buffer
Vector<RID> fb;
if (i != 0) {
fb.push_back(texture);
}
fb.push_back(weight_buffers[i].weight);
weight_buffers[i].fb = RD::get_singleton()->framebuffer_create(fb);
if (i == 1) {
// next 2 are half size
tf.width = MAX(1u, tf.width >> 1);
tf.height = MAX(1u, tf.height >> 1);
}
}
}
}
// Data buffers
bool RenderSceneBuffersRD::has_custom_data(const StringName &p_name) {
return data_buffers.has(p_name);
}
void RenderSceneBuffersRD::set_custom_data(const StringName &p_name, Ref<RenderBufferCustomDataRD> p_data) {
if (p_data.is_valid()) {
data_buffers[p_name] = p_data;
} else if (has_custom_data(p_name)) {
data_buffers.erase(p_name);
}
}
Ref<RenderBufferCustomDataRD> RenderSceneBuffersRD::get_custom_data(const StringName &p_name) const {
ERR_FAIL_COND_V(!data_buffers.has(p_name), Ref<RenderBufferCustomDataRD>());
Ref<RenderBufferCustomDataRD> ret = data_buffers[p_name];
return ret;
}
// Depth texture
bool RenderSceneBuffersRD::has_depth_texture() {
if (render_target.is_null()) {
// not applicable when there is no render target (likely this is for a reflection probe)
return false;
}
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RID depth = texture_storage->render_target_get_override_depth(render_target);
if (depth.is_valid()) {
return true;
} else {
return has_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH);
}
}
RID RenderSceneBuffersRD::get_depth_texture() {
if (render_target.is_null()) {
// not applicable when there is no render target (likely this is for a reflection probe)
return RID();
}
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RID depth = texture_storage->render_target_get_override_depth(render_target);
if (depth.is_valid()) {
return depth;
} else {
return get_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH);
}
}
RID RenderSceneBuffersRD::get_depth_texture(const uint32_t p_layer) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RID depth_slice = texture_storage->render_target_get_override_depth_slice(render_target, p_layer);
if (depth_slice.is_valid()) {
return depth_slice;
} else {
return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_DEPTH, p_layer, 0);
}
}
// Upscaled texture.
void RenderSceneBuffersRD::ensure_upscaled() {
if (!has_upscaled_texture()) {
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | (can_be_storage ? RD::TEXTURE_USAGE_STORAGE_BIT : 0) | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
usage_bits |= RD::TEXTURE_USAGE_INPUT_ATTACHMENT_BIT;
create_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR_UPSCALED, base_data_format, usage_bits, RD::TEXTURE_SAMPLES_1, target_size);
}
}
// Velocity texture.
void RenderSceneBuffersRD::ensure_velocity() {
if (!has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY)) {
const bool msaa = msaa_3d != RS::VIEWPORT_MSAA_DISABLED;
create_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY, get_velocity_format(), get_velocity_usage_bits(msaa, false, can_be_storage));
if (msaa) {
create_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA, get_velocity_format(), get_velocity_usage_bits(false, msaa, can_be_storage), texture_samples);
}
}
}
bool RenderSceneBuffersRD::has_velocity_buffer(bool p_has_msaa) {
if (p_has_msaa) {
return has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA);
} else {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RID velocity = texture_storage->render_target_get_override_velocity(render_target);
if (velocity.is_valid()) {
return true;
} else {
return has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY);
}
}
}
RID RenderSceneBuffersRD::get_velocity_buffer(bool p_get_msaa) {
if (p_get_msaa) {
if (!has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA)) {
return RID();
} else {
return get_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA);
}
} else {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RID velocity = texture_storage->render_target_get_override_velocity(render_target);
if (velocity.is_valid()) {
return velocity;
} else if (!has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY)) {
return RID();
} else {
return get_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY);
}
}
}
RID RenderSceneBuffersRD::get_velocity_buffer(bool p_get_msaa, uint32_t p_layer) {
if (p_get_msaa) {
return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA, p_layer, 0);
} else {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RID velocity_slice = texture_storage->render_target_get_override_velocity_slice(render_target, p_layer);
if (velocity_slice.is_valid()) {
return velocity_slice;
} else {
return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY, p_layer, 0);
}
}
}
RID RenderSceneBuffersRD::get_velocity_depth_buffer() {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RID velocity_depth = texture_storage->render_target_get_override_velocity_depth(render_target);
return velocity_depth;
}
uint32_t RenderSceneBuffersRD::get_color_usage_bits(bool p_resolve, bool p_msaa, bool p_storage) {
DEV_ASSERT((!p_resolve && !p_msaa) || (p_resolve != p_msaa));
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_INPUT_ATTACHMENT_BIT;
if (p_msaa) {
usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
} else if (p_resolve) {
usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | (p_storage ? RD::TEXTURE_USAGE_STORAGE_BIT : 0);
} else {
usage_bits |= (p_storage ? RD::TEXTURE_USAGE_STORAGE_BIT : 0);
}
return usage_bits;
}
RD::DataFormat RenderSceneBuffersRD::get_depth_format(bool p_resolve, bool p_msaa, bool p_storage) {
if (p_resolve) {
return RD::DATA_FORMAT_R32_SFLOAT;
} else {
const RenderingDeviceCommons::DataFormat preferred_formats[2] = {
p_storage ? RD::DATA_FORMAT_D32_SFLOAT_S8_UINT : RD::DATA_FORMAT_D24_UNORM_S8_UINT,
p_storage ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT
};
return RD::get_singleton()->texture_is_format_supported_for_usage(preferred_formats[0], get_depth_usage_bits(p_resolve, p_msaa, p_storage)) ? preferred_formats[0] : preferred_formats[1];
}
}
uint32_t RenderSceneBuffersRD::get_depth_usage_bits(bool p_resolve, bool p_msaa, bool p_storage) {
DEV_ASSERT((!p_resolve && !p_msaa) || (p_resolve != p_msaa));
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
if (p_msaa) {
usage_bits |= RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
} else if (p_resolve) {
usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | (p_storage ? RD::TEXTURE_USAGE_STORAGE_BIT : 0);
} else {
usage_bits |= RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
}
return usage_bits;
}
RD::DataFormat RenderSceneBuffersRD::get_velocity_format() {
return RD::DATA_FORMAT_R16G16_SFLOAT;
}
uint32_t RenderSceneBuffersRD::get_velocity_usage_bits(bool p_resolve, bool p_msaa, bool p_storage) {
return get_color_usage_bits(p_resolve, p_msaa, p_storage);
}
RD::DataFormat RenderSceneBuffersRD::get_vrs_format() {
return RD::get_singleton()->vrs_get_format();
}
uint32_t RenderSceneBuffersRD::get_vrs_usage_bits() {
return RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT;
}

View File

@@ -0,0 +1,456 @@
/**************************************************************************/
/* render_scene_buffers_rd.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#ifdef METAL_ENABLED
#include "../effects/metal_fx.h"
#endif
#include "../effects/vrs.h"
#include "core/templates/hash_map.h"
#include "material_storage.h"
#include "render_buffer_custom_data_rd.h"
#include "servers/rendering/rendering_device.h"
#include "servers/rendering/rendering_device_binds.h"
#include "servers/rendering/storage/render_scene_buffers.h"
#define RB_SCOPE_BUFFERS SNAME("render_buffers")
#define RB_SCOPE_VRS SNAME("VRS")
#define RB_TEXTURE SNAME("texture")
#define RB_TEX_COLOR SNAME("color")
#define RB_TEX_COLOR_MSAA SNAME("color_msaa")
#define RB_TEX_COLOR_UPSCALED SNAME("color_upscaled")
#define RB_TEX_DEPTH SNAME("depth")
#define RB_TEX_DEPTH_MSAA SNAME("depth_msaa")
#define RB_TEX_VELOCITY SNAME("velocity")
#define RB_TEX_VELOCITY_MSAA SNAME("velocity_msaa")
#define RB_TEX_BLUR_0 SNAME("blur_0")
#define RB_TEX_BLUR_1 SNAME("blur_1")
#define RB_TEX_HALF_BLUR SNAME("half_blur") // only for raster!
#define RB_TEX_BACK_COLOR SNAME("back_color")
#define RB_TEX_BACK_DEPTH SNAME("back_depth")
class RenderSceneBuffersRD : public RenderSceneBuffers {
GDCLASS(RenderSceneBuffersRD, RenderSceneBuffers);
private:
bool can_be_storage = true;
uint32_t max_cluster_elements = 512;
RD::DataFormat base_data_format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
RendererRD::VRS *vrs = nullptr;
uint64_t auto_exposure_version = 1;
RS::ViewportVRSMode vrs_mode = RS::VIEWPORT_VRS_DISABLED;
// Our render target represents our final destination that we display on screen.
RID render_target;
Size2i target_size = Size2i(0, 0);
uint32_t view_count = 1;
// The internal size of the textures we render 3D to in case we render at a lower resolution and upscale
Size2i internal_size = Size2i(0, 0);
RS::ViewportScaling3DMode scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF;
float fsr_sharpness = 0.2f;
float texture_mipmap_bias = 0.0f;
RS::ViewportAnisotropicFiltering anisotropic_filtering_level = RS::VIEWPORT_ANISOTROPY_4X;
#ifdef METAL_ENABLED
RendererRD::MFXSpatialContext *mfx_spatial_context = nullptr;
#endif
// Aliasing settings
RS::ViewportMSAA msaa_3d = RS::VIEWPORT_MSAA_DISABLED;
RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
bool use_taa = false;
bool use_debanding = false;
RD::TextureSamples texture_samples = RD::TEXTURE_SAMPLES_1;
// Named Textures
struct NTKey {
StringName context;
StringName buffer_name;
bool operator==(const NTKey &p_val) const {
return (context == p_val.context) && (buffer_name == p_val.buffer_name);
}
static uint32_t hash(const NTKey &p_val) {
uint32_t h = p_val.context.hash();
h = hash_murmur3_one_32(p_val.buffer_name.hash(), h);
return hash_fmix32(h);
}
NTKey() {}
NTKey(const StringName &p_context, const StringName &p_texture_name) {
context = p_context;
buffer_name = p_texture_name;
}
};
struct NTSliceKey {
uint32_t layer;
uint32_t layers;
uint32_t mipmap;
uint32_t mipmaps;
RD::TextureView texture_view;
bool operator==(const NTSliceKey &p_val) const {
return (layer == p_val.layer) && (layers == p_val.layers) && (mipmap == p_val.mipmap) && (mipmaps == p_val.mipmaps) && (texture_view == p_val.texture_view);
}
static uint32_t hash(const NTSliceKey &p_val) {
uint32_t h = hash_murmur3_one_32(p_val.layer);
h = hash_murmur3_one_32(p_val.layers, h);
h = hash_murmur3_one_32(p_val.mipmap, h);
h = hash_murmur3_one_32(p_val.mipmaps, h);
h = hash_murmur3_one_32(p_val.texture_view.format_override, h);
h = hash_murmur3_one_32(p_val.texture_view.swizzle_r, h);
h = hash_murmur3_one_32(p_val.texture_view.swizzle_g, h);
h = hash_murmur3_one_32(p_val.texture_view.swizzle_b, h);
h = hash_murmur3_one_32(p_val.texture_view.swizzle_a, h);
return hash_fmix32(h);
}
NTSliceKey() {}
NTSliceKey(uint32_t p_layer, uint32_t p_layers, uint32_t p_mipmap, uint32_t p_mipmaps, RD::TextureView p_texture_view) {
layer = p_layer;
layers = p_layers;
mipmap = p_mipmap;
mipmaps = p_mipmaps;
texture_view = p_texture_view;
}
};
struct NamedTexture {
// Cache the data used to create our texture
RD::TextureFormat format;
bool is_unique; // If marked as unique, we return it into our pool
// Our texture objects, slices are lazy (i.e. only created when requested).
RID texture;
mutable HashMap<NTSliceKey, RID, NTSliceKey> slices;
Vector<Size2i> sizes;
};
mutable HashMap<NTKey, NamedTexture, NTKey> named_textures;
void update_sizes(NamedTexture &p_named_texture);
void free_named_texture(NamedTexture &p_named_texture);
// Data buffers
mutable HashMap<StringName, Ref<RenderBufferCustomDataRD>> data_buffers;
// Samplers.
RendererRD::MaterialStorage::Samplers samplers;
void update_samplers();
protected:
static void _bind_methods();
public:
RenderSceneBuffersRD();
virtual ~RenderSceneBuffersRD();
// info from our renderer
void set_can_be_storage(const bool p_can_be_storage) { can_be_storage = p_can_be_storage; }
bool get_can_be_storage() const { return can_be_storage; }
void set_max_cluster_elements(const uint32_t p_max_elements) { max_cluster_elements = p_max_elements; }
uint32_t get_max_cluster_elements() { return max_cluster_elements; }
void set_base_data_format(const RD::DataFormat p_base_data_format) { base_data_format = p_base_data_format; }
RD::DataFormat get_base_data_format() const { return base_data_format; }
void set_vrs(RendererRD::VRS *p_vrs) { vrs = p_vrs; }
RS::ViewportVRSMode get_vrs_mode() { return vrs_mode; }
void cleanup();
virtual void configure(const RenderSceneBuffersConfiguration *p_config) override;
void configure_for_reflections(const Size2i p_reflection_size);
virtual void set_fsr_sharpness(float p_fsr_sharpness) override;
virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) override;
virtual void set_anisotropic_filtering_level(RS::ViewportAnisotropicFiltering p_anisotropic_filtering_level) override;
virtual void set_use_debanding(bool p_use_debanding) override;
#ifdef METAL_ENABLED
void ensure_mfx(RendererRD::MFXSpatialEffect *p_effect);
_FORCE_INLINE_ RendererRD::MFXSpatialContext *get_mfx_spatial_context() const { return mfx_spatial_context; }
#endif
// Named Textures
bool has_texture(const StringName &p_context, const StringName &p_texture_name) const;
RID create_texture(const StringName &p_context, const StringName &p_texture_name, const RD::DataFormat p_data_format, const uint32_t p_usage_bits, const RD::TextureSamples p_texture_samples = RD::TEXTURE_SAMPLES_1, const Size2i p_size = Size2i(0, 0), const uint32_t p_layers = 0, const uint32_t p_mipmaps = 1, bool p_unique = true, bool p_discardable = false);
RID create_texture_from_format(const StringName &p_context, const StringName &p_texture_name, const RD::TextureFormat &p_texture_format, RD::TextureView p_view = RD::TextureView(), bool p_unique = true);
RID create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName &p_view_name, RD::TextureView p_view = RD::TextureView());
RID get_texture(const StringName &p_context, const StringName &p_texture_name) const;
const RD::TextureFormat get_texture_format(const StringName &p_context, const StringName &p_texture_name) const;
RID get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap, const uint32_t p_layers = 1, const uint32_t p_mipmaps = 1);
RID get_texture_slice_view(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap, const uint32_t p_layers = 1, const uint32_t p_mipmaps = 1, RD::TextureView p_view = RD::TextureView());
Size2i get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_mipmap);
void clear_context(const StringName &p_context);
// Allocate shared buffers
void allocate_blur_textures();
// Custom data
bool has_custom_data(const StringName &p_name);
void set_custom_data(const StringName &p_name, Ref<RenderBufferCustomDataRD> p_data);
Ref<RenderBufferCustomDataRD> get_custom_data(const StringName &p_name) const;
// Getters
_FORCE_INLINE_ RID get_render_target() const { return render_target; }
_FORCE_INLINE_ uint32_t get_view_count() const { return view_count; }
_FORCE_INLINE_ Size2i get_internal_size() const { return internal_size; }
_FORCE_INLINE_ Size2i get_target_size() const { return target_size; }
_FORCE_INLINE_ RS::ViewportScaling3DMode get_scaling_3d_mode() const { return scaling_3d_mode; }
_FORCE_INLINE_ float get_fsr_sharpness() const { return fsr_sharpness; }
_FORCE_INLINE_ RS::ViewportMSAA get_msaa_3d() const { return msaa_3d; }
_FORCE_INLINE_ RD::TextureSamples get_texture_samples() const { return texture_samples; }
_FORCE_INLINE_ RS::ViewportScreenSpaceAA get_screen_space_aa() const { return screen_space_aa; }
_FORCE_INLINE_ bool get_use_taa() const { return use_taa; }
_FORCE_INLINE_ bool get_use_debanding() const { return use_debanding; }
uint64_t get_auto_exposure_version() const { return auto_exposure_version; }
void set_auto_exposure_version(const uint64_t p_auto_exposure_version) { auto_exposure_version = p_auto_exposure_version; }
// For our internal textures we provide some easy access methods.
_FORCE_INLINE_ bool has_internal_texture() const {
return has_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR);
}
_FORCE_INLINE_ RID get_internal_texture() const {
return get_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR);
}
_FORCE_INLINE_ RID get_internal_texture(const uint32_t p_layer) {
return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_COLOR, p_layer, 0);
}
_FORCE_INLINE_ RID get_internal_texture_reactive(const uint32_t p_layer) {
RD::TextureView alpha_only_view;
alpha_only_view.swizzle_r = RD::TEXTURE_SWIZZLE_A;
alpha_only_view.swizzle_g = RD::TEXTURE_SWIZZLE_A;
alpha_only_view.swizzle_b = RD::TEXTURE_SWIZZLE_A;
alpha_only_view.swizzle_a = RD::TEXTURE_SWIZZLE_A;
return get_texture_slice_view(RB_SCOPE_BUFFERS, RB_TEX_COLOR, p_layer, 0, 1, 1, alpha_only_view);
}
_FORCE_INLINE_ RID get_color_msaa() const {
return get_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR_MSAA);
}
_FORCE_INLINE_ RID get_color_msaa(uint32_t p_layer) {
return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_COLOR_MSAA, p_layer, 0);
}
bool has_depth_texture();
RID get_depth_texture();
RID get_depth_texture(const uint32_t p_layer);
RID get_depth_msaa() const {
return get_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_MSAA);
}
RID get_depth_msaa(uint32_t p_layer) {
return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_MSAA, p_layer, 0);
}
// back buffer (color)
RID get_back_buffer_texture() const {
// Prefer returning the dedicated backbuffer color texture if it was created. Return the reused blur texture otherwise.
if (has_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_COLOR)) {
return get_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_COLOR);
} else if (has_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0)) {
return get_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0);
} else {
return RID();
}
}
// Upscaled.
void ensure_upscaled();
_FORCE_INLINE_ bool has_upscaled_texture() const {
return has_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR_UPSCALED);
}
_FORCE_INLINE_ RID get_upscaled_texture() const {
return get_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR_UPSCALED);
}
_FORCE_INLINE_ RID get_upscaled_texture(const uint32_t p_layer) {
return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_COLOR_UPSCALED, p_layer, 0);
}
// Velocity, currently only used by TAA (Clustered) but we'll be using this in other places soon too.
void ensure_velocity();
bool has_velocity_buffer(bool p_has_msaa);
RID get_velocity_buffer(bool p_get_msaa);
RID get_velocity_buffer(bool p_get_msaa, uint32_t p_layer);
RID get_velocity_depth_buffer();
// Samplers adjusted with the mipmap bias that is best fit for the configuration of these render buffers.
_FORCE_INLINE_ RendererRD::MaterialStorage::Samplers get_samplers() const {
return samplers;
}
_FORCE_INLINE_ static RD::TextureSamples msaa_to_samples(RS::ViewportMSAA p_msaa) {
switch (p_msaa) {
case RS::VIEWPORT_MSAA_DISABLED:
return RD::TEXTURE_SAMPLES_1;
case RS::VIEWPORT_MSAA_2X:
return RD::TEXTURE_SAMPLES_2;
case RS::VIEWPORT_MSAA_4X:
return RD::TEXTURE_SAMPLES_4;
case RS::VIEWPORT_MSAA_8X:
return RD::TEXTURE_SAMPLES_8;
default:
DEV_ASSERT(false && "Unknown MSAA option.");
return RD::TEXTURE_SAMPLES_1;
}
}
static uint32_t get_color_usage_bits(bool p_resolve, bool p_msaa, bool p_storage);
static RD::DataFormat get_depth_format(bool p_resolve, bool p_msaa, bool p_storage);
static uint32_t get_depth_usage_bits(bool p_resolve, bool p_msaa, bool p_storage);
static RD::DataFormat get_velocity_format();
static uint32_t get_velocity_usage_bits(bool p_resolve, bool p_msaa, bool p_storage);
static RD::DataFormat get_vrs_format();
static uint32_t get_vrs_usage_bits();
private:
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Our classDB doesn't support calling our normal exposed functions
RID _create_texture_from_format(const StringName &p_context, const StringName &p_texture_name, const Ref<RDTextureFormat> &p_texture_format, const Ref<RDTextureView> &p_view = Ref<RDTextureView>(), bool p_unique = true);
RID _create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName &p_view_name, const Ref<RDTextureView> p_view = Ref<RDTextureView>());
Ref<RDTextureFormat> _get_texture_format(const StringName &p_context, const StringName &p_texture_name) const;
RID _get_texture_slice_view(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap, const uint32_t p_layers = 1, const uint32_t p_mipmaps = 1, const Ref<RDTextureView> p_view = Ref<RDTextureView>());
// For color and depth as exposed to extensions:
// - we need separately named functions to access the layer,
// - we don't output an error for missing buffers but just return an empty RID.
RID _get_color_texture(bool p_msaa = false) {
if (p_msaa) {
if (has_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR_MSAA)) {
return get_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR_MSAA);
} else {
return RID();
}
} else if (has_internal_texture()) {
return get_internal_texture();
} else {
return RID();
}
}
RID _get_color_layer(const uint32_t p_layer, bool p_msaa = false) {
if (p_msaa) {
if (has_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR_MSAA)) {
return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_COLOR_MSAA, p_layer, 0);
} else {
return RID();
}
} else if (has_internal_texture()) {
return get_internal_texture(p_layer);
} else {
return RID();
}
}
RID _get_depth_texture(bool p_msaa = false) {
if (p_msaa) {
if (has_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_MSAA)) {
return get_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_MSAA);
} else {
return RID();
}
} else if (has_depth_texture()) {
return get_depth_texture();
} else {
return RID();
}
}
RID _get_depth_layer(const uint32_t p_layer, bool p_msaa = false) {
if (p_msaa) {
if (has_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_MSAA)) {
return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_MSAA, p_layer, 0);
} else {
return RID();
}
} else if (has_depth_texture()) {
return get_depth_texture(p_layer);
} else {
return RID();
}
}
RID _get_velocity_texture(bool p_msaa = false) {
if (has_velocity_buffer(p_msaa)) {
return get_velocity_buffer(p_msaa);
} else {
return RID();
}
}
RID _get_velocity_layer(const uint32_t p_layer, bool p_msaa = false) {
if (has_velocity_buffer(p_msaa)) {
return get_velocity_buffer(p_msaa, p_layer);
} else {
return RID();
}
}
#ifndef DISABLE_DEPRECATED
RID _get_color_texture_compat_80214();
RID _get_color_layer_compat_80214(const uint32_t p_layer);
RID _get_depth_texture_compat_80214();
RID _get_depth_layer_compat_80214(const uint32_t p_layer);
RID _get_velocity_texture_compat_80214();
RID _get_velocity_layer_compat_80214(const uint32_t p_layer);
RID _create_texture_bind_compat_98670(const StringName &p_context, const StringName &p_texture_name, const RD::DataFormat p_data_format, const uint32_t p_usage_bits, const RD::TextureSamples p_texture_samples, const Size2i p_size, const uint32_t p_layers, const uint32_t p_mipmaps, bool p_unique);
static void _bind_compatibility_methods();
#endif // DISABLE_DEPRECATED
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Everything after this needs to be re-evaluated, this is all old implementation
public:
struct WeightBuffers {
RID weight;
RID fb; // FB with both texture and weight writing into one level lower
};
// 2 full size, 2 half size
WeightBuffers weight_buffers[4]; // Only used in raster
};

View File

@@ -0,0 +1,294 @@
/**************************************************************************/
/* render_scene_data_rd.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#include "render_scene_data_rd.h"
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/light_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
Transform3D RenderSceneDataRD::get_cam_transform() const {
return cam_transform;
}
Projection RenderSceneDataRD::get_cam_projection() const {
Projection correction;
correction.set_depth_correction(flip_y);
correction.add_jitter_offset(taa_jitter);
return correction * cam_projection;
}
uint32_t RenderSceneDataRD::get_view_count() const {
return view_count;
}
Vector3 RenderSceneDataRD::get_view_eye_offset(uint32_t p_view) const {
ERR_FAIL_UNSIGNED_INDEX_V(p_view, view_count, Vector3());
return view_eye_offset[p_view];
}
Projection RenderSceneDataRD::get_view_projection(uint32_t p_view) const {
ERR_FAIL_UNSIGNED_INDEX_V(p_view, view_count, Projection());
Projection correction;
correction.set_depth_correction(flip_y);
correction.add_jitter_offset(taa_jitter);
return correction * view_projection[p_view];
}
RID RenderSceneDataRD::create_uniform_buffer() {
return RD::get_singleton()->uniform_buffer_create(sizeof(UBODATA));
}
void RenderSceneDataRD::update_ubo(RID p_uniform_buffer, RS::ViewportDebugDraw p_debug_mode, RID p_env, RID p_reflection_probe_instance, RID p_camera_attributes, bool p_pancake_shadows, const Size2i &p_screen_size, const Color &p_default_bg_color, float p_luminance_multiplier, bool p_opaque_render_buffers, bool p_apply_alpha_multiplier) {
RendererSceneRenderRD *render_scene_render = RendererSceneRenderRD::get_singleton();
UBODATA ubo_data;
memset(&ubo_data, 0, sizeof(UBODATA));
// just for easy access..
UBO &ubo = ubo_data.ubo;
UBO &prev_ubo = ubo_data.prev_ubo;
Projection correction;
correction.set_depth_correction(flip_y);
correction.add_jitter_offset(taa_jitter);
Projection projection = correction * cam_projection;
//store camera into ubo
RendererRD::MaterialStorage::store_camera(projection, ubo.projection_matrix);
RendererRD::MaterialStorage::store_camera(projection.inverse(), ubo.inv_projection_matrix);
RendererRD::MaterialStorage::store_transform(cam_transform, ubo.inv_view_matrix);
RendererRD::MaterialStorage::store_transform(cam_transform.affine_inverse(), ubo.view_matrix);
#ifdef REAL_T_IS_DOUBLE
RendererRD::MaterialStorage::split_double(-cam_transform.origin.x, &ubo.inv_view_matrix[12], &ubo.inv_view_matrix[3]);
RendererRD::MaterialStorage::split_double(-cam_transform.origin.y, &ubo.inv_view_matrix[13], &ubo.inv_view_matrix[7]);
RendererRD::MaterialStorage::split_double(-cam_transform.origin.z, &ubo.inv_view_matrix[14], &ubo.inv_view_matrix[11]);
#endif
for (uint32_t v = 0; v < view_count; v++) {
projection = correction * view_projection[v];
RendererRD::MaterialStorage::store_camera(projection, ubo.projection_matrix_view[v]);
RendererRD::MaterialStorage::store_camera(projection.inverse(), ubo.inv_projection_matrix_view[v]);
ubo.eye_offset[v][0] = view_eye_offset[v].x;
ubo.eye_offset[v][1] = view_eye_offset[v].y;
ubo.eye_offset[v][2] = view_eye_offset[v].z;
ubo.eye_offset[v][3] = 0.0;
}
RendererRD::MaterialStorage::store_transform(main_cam_transform, ubo.main_cam_inv_view_matrix);
ubo.taa_jitter[0] = taa_jitter.x;
ubo.taa_jitter[1] = taa_jitter.y;
ubo.taa_frame_count = taa_frame_count;
ubo.z_far = z_far;
ubo.z_near = z_near;
ubo.flags = 0;
ubo.flags |= p_pancake_shadows ? SCENE_DATA_FLAGS_USE_PANCAKE_SHADOWS : 0;
RendererRD::MaterialStorage::store_soft_shadow_kernel(render_scene_render->directional_penumbra_shadow_kernel_get(), ubo.directional_penumbra_shadow_kernel);
RendererRD::MaterialStorage::store_soft_shadow_kernel(render_scene_render->directional_soft_shadow_kernel_get(), ubo.directional_soft_shadow_kernel);
RendererRD::MaterialStorage::store_soft_shadow_kernel(render_scene_render->penumbra_shadow_kernel_get(), ubo.penumbra_shadow_kernel);
RendererRD::MaterialStorage::store_soft_shadow_kernel(render_scene_render->soft_shadow_kernel_get(), ubo.soft_shadow_kernel);
ubo.camera_visible_layers = camera_visible_layers;
ubo.pass_alpha_multiplier = p_opaque_render_buffers && p_apply_alpha_multiplier ? 0.0f : 1.0f;
ubo.viewport_size[0] = p_screen_size.x;
ubo.viewport_size[1] = p_screen_size.y;
Size2 screen_pixel_size = Vector2(1.0, 1.0) / Size2(p_screen_size);
ubo.screen_pixel_size[0] = screen_pixel_size.x;
ubo.screen_pixel_size[1] = screen_pixel_size.y;
ubo.shadow_atlas_pixel_size[0] = shadow_atlas_pixel_size.x;
ubo.shadow_atlas_pixel_size[1] = shadow_atlas_pixel_size.y;
ubo.directional_shadow_pixel_size[0] = directional_shadow_pixel_size.x;
ubo.directional_shadow_pixel_size[1] = directional_shadow_pixel_size.y;
ubo.time = time;
ubo.directional_light_count = directional_light_count;
ubo.dual_paraboloid_side = dual_paraboloid_side;
ubo.opaque_prepass_threshold = opaque_prepass_threshold;
ubo.flags |= material_uv2_mode ? SCENE_DATA_FLAGS_USE_UV2_MATERIAL : 0;
ubo.flags |= shadow_pass ? SCENE_DATA_FLAGS_IN_SHADOW_PASS : 0;
if (p_debug_mode == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
ubo.flags |= SCENE_DATA_FLAGS_USE_AMBIENT_LIGHT;
ubo.ambient_light_color_energy[0] = 1;
ubo.ambient_light_color_energy[1] = 1;
ubo.ambient_light_color_energy[2] = 1;
ubo.ambient_light_color_energy[3] = 1.0;
} else if (p_env.is_valid()) {
RS::EnvironmentBG env_bg = render_scene_render->environment_get_background(p_env);
RS::EnvironmentAmbientSource ambient_src = render_scene_render->environment_get_ambient_source(p_env);
float bg_energy_multiplier = render_scene_render->environment_get_bg_energy_multiplier(p_env);
ubo.ambient_light_color_energy[3] = bg_energy_multiplier;
ubo.ambient_color_sky_mix = render_scene_render->environment_get_ambient_sky_contribution(p_env);
//ambient
if (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && (env_bg == RS::ENV_BG_CLEAR_COLOR || env_bg == RS::ENV_BG_COLOR)) {
Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : render_scene_render->environment_get_bg_color(p_env);
color = color.srgb_to_linear();
ubo.ambient_light_color_energy[0] = color.r * bg_energy_multiplier;
ubo.ambient_light_color_energy[1] = color.g * bg_energy_multiplier;
ubo.ambient_light_color_energy[2] = color.b * bg_energy_multiplier;
ubo.flags |= SCENE_DATA_FLAGS_USE_AMBIENT_LIGHT;
} else {
float energy = render_scene_render->environment_get_ambient_light_energy(p_env);
Color color = render_scene_render->environment_get_ambient_light(p_env);
color = color.srgb_to_linear();
ubo.ambient_light_color_energy[0] = color.r * energy;
ubo.ambient_light_color_energy[1] = color.g * energy;
ubo.ambient_light_color_energy[2] = color.b * energy;
bool use_ambient_cubemap = (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ambient_src == RS::ENV_AMBIENT_SOURCE_SKY;
bool use_ambient_light = use_ambient_cubemap || ambient_src == RS::ENV_AMBIENT_SOURCE_COLOR;
ubo.flags |= use_ambient_cubemap ? SCENE_DATA_FLAGS_USE_AMBIENT_CUBEMAP : 0;
ubo.flags |= use_ambient_light ? SCENE_DATA_FLAGS_USE_AMBIENT_LIGHT : 0;
}
//specular
RS::EnvironmentReflectionSource ref_src = render_scene_render->environment_get_reflection_source(p_env);
if ((ref_src == RS::ENV_REFLECTION_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ref_src == RS::ENV_REFLECTION_SOURCE_SKY) {
ubo.flags |= SCENE_DATA_FLAGS_USE_REFLECTION_CUBEMAP;
}
if ((ubo.flags & SCENE_DATA_FLAGS_USE_AMBIENT_CUBEMAP) || (ubo.flags & SCENE_DATA_FLAGS_USE_REFLECTION_CUBEMAP)) {
Basis sky_transform = render_scene_render->environment_get_sky_orientation(p_env);
sky_transform = sky_transform.inverse() * cam_transform.basis;
RendererRD::MaterialStorage::store_transform_3x3(sky_transform, ubo.radiance_inverse_xform);
}
ubo.flags |= render_scene_render->environment_get_fog_enabled(p_env) ? SCENE_DATA_FLAGS_USE_FOG : 0;
ubo.fog_density = render_scene_render->environment_get_fog_density(p_env);
ubo.fog_height = render_scene_render->environment_get_fog_height(p_env);
ubo.fog_height_density = render_scene_render->environment_get_fog_height_density(p_env);
ubo.fog_aerial_perspective = render_scene_render->environment_get_fog_aerial_perspective(p_env);
ubo.fog_depth_curve = render_scene_render->environment_get_fog_depth_curve(p_env);
ubo.fog_depth_end = render_scene_render->environment_get_fog_depth_end(p_env) > 0.0 ? render_scene_render->environment_get_fog_depth_end(p_env) : ubo.z_far;
ubo.fog_depth_begin = MIN(render_scene_render->environment_get_fog_depth_begin(p_env), ubo.fog_depth_end - 0.001);
Color fog_color = render_scene_render->environment_get_fog_light_color(p_env).srgb_to_linear();
float fog_energy = render_scene_render->environment_get_fog_light_energy(p_env);
ubo.fog_light_color[0] = fog_color.r * fog_energy;
ubo.fog_light_color[1] = fog_color.g * fog_energy;
ubo.fog_light_color[2] = fog_color.b * fog_energy;
ubo.fog_sun_scatter = render_scene_render->environment_get_fog_sun_scatter(p_env);
} else {
if (!(p_reflection_probe_instance.is_valid() && RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(p_reflection_probe_instance))) {
ubo.flags |= SCENE_DATA_FLAGS_USE_AMBIENT_LIGHT;
Color clear_color = p_default_bg_color;
clear_color = clear_color.srgb_to_linear();
ubo.ambient_light_color_energy[0] = clear_color.r;
ubo.ambient_light_color_energy[1] = clear_color.g;
ubo.ambient_light_color_energy[2] = clear_color.b;
ubo.ambient_light_color_energy[3] = 1.0;
}
}
if (p_camera_attributes.is_valid()) {
ubo.emissive_exposure_normalization = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_camera_attributes);
ubo.IBL_exposure_normalization = 1.0;
if (p_env.is_valid()) {
RID sky_rid = render_scene_render->environment_get_sky(p_env);
if (sky_rid.is_valid()) {
float current_exposure = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_camera_attributes) * render_scene_render->environment_get_bg_intensity(p_env) / p_luminance_multiplier;
ubo.IBL_exposure_normalization = current_exposure / MAX(0.001, render_scene_render->get_sky()->sky_get_baked_exposure(sky_rid));
}
}
} else if (emissive_exposure_normalization > 0.0) {
// This branch is triggered when using render_material().
// Emissive is set outside the function.
ubo.emissive_exposure_normalization = emissive_exposure_normalization;
// IBL isn't used don't set it.
} else {
ubo.emissive_exposure_normalization = 1.0;
ubo.IBL_exposure_normalization = 1.0;
}
bool roughness_limiter_enabled = p_opaque_render_buffers && render_scene_render->screen_space_roughness_limiter_is_active();
ubo.flags |= roughness_limiter_enabled ? SCENE_DATA_FLAGS_USE_ROUGHNESS_LIMITER : 0;
ubo.roughness_limiter_amount = render_scene_render->screen_space_roughness_limiter_get_amount();
ubo.roughness_limiter_limit = render_scene_render->screen_space_roughness_limiter_get_limit();
if (calculate_motion_vectors) {
// Q : Should we make a complete copy or should we define a separate UBO with just the components we need?
memcpy(&prev_ubo, &ubo, sizeof(UBO));
Projection prev_correction;
prev_correction.set_depth_correction(true);
prev_correction.add_jitter_offset(prev_taa_jitter);
Projection prev_projection = prev_correction * prev_cam_projection;
//store camera into ubo
RendererRD::MaterialStorage::store_camera(prev_projection, prev_ubo.projection_matrix);
RendererRD::MaterialStorage::store_camera(prev_projection.inverse(), prev_ubo.inv_projection_matrix);
RendererRD::MaterialStorage::store_transform(prev_cam_transform, prev_ubo.inv_view_matrix);
RendererRD::MaterialStorage::store_transform(prev_cam_transform.affine_inverse(), prev_ubo.view_matrix);
#ifdef REAL_T_IS_DOUBLE
RendererRD::MaterialStorage::split_double(-prev_cam_transform.origin.x, &prev_ubo.inv_view_matrix[12], &prev_ubo.inv_view_matrix[3]);
RendererRD::MaterialStorage::split_double(-prev_cam_transform.origin.y, &prev_ubo.inv_view_matrix[13], &prev_ubo.inv_view_matrix[7]);
RendererRD::MaterialStorage::split_double(-prev_cam_transform.origin.z, &prev_ubo.inv_view_matrix[14], &prev_ubo.inv_view_matrix[11]);
#endif
for (uint32_t v = 0; v < view_count; v++) {
prev_projection = prev_correction * view_projection[v];
RendererRD::MaterialStorage::store_camera(prev_projection, prev_ubo.projection_matrix_view[v]);
RendererRD::MaterialStorage::store_camera(prev_projection.inverse(), prev_ubo.inv_projection_matrix_view[v]);
}
prev_ubo.taa_jitter[0] = prev_taa_jitter.x;
prev_ubo.taa_jitter[1] = prev_taa_jitter.y;
prev_ubo.time -= time_step;
}
uniform_buffer = p_uniform_buffer;
RD::get_singleton()->buffer_update(uniform_buffer, 0, sizeof(UBODATA), &ubo);
}
RID RenderSceneDataRD::get_uniform_buffer() const {
return uniform_buffer;
}

View File

@@ -0,0 +1,177 @@
/**************************************************************************/
/* render_scene_data_rd.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/storage/render_scene_data.h"
// This is a container for data related to rendering a single frame of a viewport where we load this data into a UBO
// that can be used by the main scene shader but also by various effects.
class RenderSceneDataRD : public RenderSceneData {
GDCLASS(RenderSceneDataRD, RenderSceneData);
public:
bool calculate_motion_vectors = false;
Transform3D cam_transform;
Projection cam_projection;
Vector2 taa_jitter;
float taa_frame_count = 0.0f;
uint32_t camera_visible_layers;
bool cam_orthogonal = false;
bool cam_frustum = false;
bool flip_y = false;
// For billboards to cast correct shadows.
Transform3D main_cam_transform;
// For stereo rendering
uint32_t view_count = 1;
Vector3 view_eye_offset[RendererSceneRender::MAX_RENDER_VIEWS];
Projection view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
Transform3D prev_cam_transform;
Projection prev_cam_projection;
Vector2 prev_taa_jitter;
Projection prev_view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
float z_near = 0.0;
float z_far = 0.0;
float lod_distance_multiplier = 0.0;
float screen_mesh_lod_threshold = 0.0;
uint32_t directional_light_count = 0;
float dual_paraboloid_side = 0.0;
float opaque_prepass_threshold = 0.0;
bool material_uv2_mode = false;
float emissive_exposure_normalization = 0.0;
bool shadow_pass = false;
Size2 shadow_atlas_pixel_size;
Size2 directional_shadow_pixel_size;
float time;
float time_step;
virtual Transform3D get_cam_transform() const override;
virtual Projection get_cam_projection() const override;
virtual uint32_t get_view_count() const override;
virtual Vector3 get_view_eye_offset(uint32_t p_view) const override;
virtual Projection get_view_projection(uint32_t p_view) const override;
RID create_uniform_buffer();
void update_ubo(RID p_uniform_buffer, RS::ViewportDebugDraw p_debug_mode, RID p_env, RID p_reflection_probe_instance, RID p_camera_attributes, bool p_pancake_shadows, const Size2i &p_screen_size, const Color &p_default_bg_color, float p_luminance_multiplier, bool p_opaque_render_buffers, bool p_apply_alpha_multiplier);
virtual RID get_uniform_buffer() const override;
private:
RID uniform_buffer; // loaded into this uniform buffer (supplied externally)
enum SceneDataFlags {
SCENE_DATA_FLAGS_USE_AMBIENT_LIGHT = 1 << 0,
SCENE_DATA_FLAGS_USE_AMBIENT_CUBEMAP = 1 << 1,
SCENE_DATA_FLAGS_USE_REFLECTION_CUBEMAP = 1 << 2,
SCENE_DATA_FLAGS_USE_ROUGHNESS_LIMITER = 1 << 3,
SCENE_DATA_FLAGS_USE_FOG = 1 << 4,
SCENE_DATA_FLAGS_USE_UV2_MATERIAL = 1 << 5,
SCENE_DATA_FLAGS_USE_PANCAKE_SHADOWS = 1 << 6,
SCENE_DATA_FLAGS_IN_SHADOW_PASS = 1 << 7, // Only used by Forward+ renderer.
SCENE_DATA_FLAGS_MAX
};
// This struct is loaded into Set 1 - Binding 0, populated at start of rendering a frame, must match with shader code
struct UBO {
float projection_matrix[16];
float inv_projection_matrix[16];
float inv_view_matrix[16];
float view_matrix[16];
float projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16];
float inv_projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16];
float eye_offset[RendererSceneRender::MAX_RENDER_VIEWS][4];
float main_cam_inv_view_matrix[16];
float viewport_size[2];
float screen_pixel_size[2];
float directional_penumbra_shadow_kernel[128]; //32 vec4s
float directional_soft_shadow_kernel[128];
float penumbra_shadow_kernel[128];
float soft_shadow_kernel[128];
float shadow_atlas_pixel_size[2];
float directional_shadow_pixel_size[2];
uint32_t directional_light_count;
float dual_paraboloid_side;
float z_far;
float z_near;
float roughness_limiter_amount;
float roughness_limiter_limit;
float opaque_prepass_threshold;
uint32_t flags;
float radiance_inverse_xform[12];
float ambient_light_color_energy[4];
float ambient_color_sky_mix;
float fog_density;
float fog_height;
float fog_height_density;
float fog_depth_curve;
float fog_depth_begin;
float fog_depth_end;
float fog_sun_scatter;
float fog_light_color[3];
float fog_aerial_perspective;
float time;
float taa_frame_count; // Used to add break up samples over multiple frames. Value is an integer from 0 to taa_phase_count -1.
float taa_jitter[2];
float emissive_exposure_normalization; // Needed to normalize emissive when using physical units.
float IBL_exposure_normalization; // Adjusts for baked exposure.
uint32_t camera_visible_layers;
float pass_alpha_multiplier;
};
struct UBODATA {
UBO ubo;
UBO prev_ubo;
};
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,825 @@
/**************************************************************************/
/* texture_storage.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "core/templates/paged_array.h"
#include "core/templates/rid_owner.h"
#include "servers/rendering/renderer_rd/shaders/canvas_sdf.glsl.gen.h"
#include "servers/rendering/renderer_rd/storage_rd/forward_id_storage.h"
#include "servers/rendering/rendering_server_default.h"
#include "servers/rendering/storage/texture_storage.h"
#include "servers/rendering/storage/utilities.h"
namespace RendererRD {
class LightStorage;
class MaterialStorage;
class TextureStorage : public RendererTextureStorage {
public:
enum DefaultRDTexture {
DEFAULT_RD_TEXTURE_WHITE,
DEFAULT_RD_TEXTURE_BLACK,
DEFAULT_RD_TEXTURE_TRANSPARENT,
DEFAULT_RD_TEXTURE_NORMAL,
DEFAULT_RD_TEXTURE_ANISO,
DEFAULT_RD_TEXTURE_DEPTH,
DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER,
DEFAULT_RD_TEXTURE_CUBEMAP_BLACK,
DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK,
DEFAULT_RD_TEXTURE_CUBEMAP_WHITE,
DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_WHITE,
DEFAULT_RD_TEXTURE_3D_WHITE,
DEFAULT_RD_TEXTURE_3D_BLACK,
DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE,
DEFAULT_RD_TEXTURE_2D_ARRAY_BLACK,
DEFAULT_RD_TEXTURE_2D_ARRAY_NORMAL,
DEFAULT_RD_TEXTURE_2D_ARRAY_DEPTH,
DEFAULT_RD_TEXTURE_2D_UINT,
DEFAULT_RD_TEXTURE_VRS,
DEFAULT_RD_TEXTURE_MAX
};
enum TextureType {
TYPE_2D,
TYPE_LAYERED,
TYPE_3D
};
struct CanvasTextureInfo {
RID diffuse;
RID normal;
RID specular;
RID sampler;
Size2i size;
Color specular_color;
bool use_normal = false;
bool use_specular = false;
_FORCE_INLINE_ bool is_valid() const { return diffuse.is_valid(); }
_FORCE_INLINE_ bool is_null() const { return diffuse.is_null(); }
};
typedef void (*InvalidationCallback)(bool p_deleted, void *p_userdata);
private:
friend class LightStorage;
friend class MaterialStorage;
static TextureStorage *singleton;
RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX];
/* Canvas Texture API */
struct CanvasTextureCache {
RID diffuse;
RID normal;
RID specular;
};
class CanvasTexture {
public:
RID diffuse;
RID normal_map;
RID specular;
Color specular_color = Color(1, 1, 1, 1);
float shininess = 1.0;
RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
CanvasTextureCache info_cache[2];
InvalidationCallback invalidated_callback = nullptr;
void *invalidated_callback_userdata = nullptr;
Size2i size_cache = Size2i(1, 1);
bool use_normal_cache = false;
bool use_specular_cache = false;
void clear_cache();
~CanvasTexture();
};
RID_Owner<CanvasTexture, true> canvas_texture_owner;
/* Texture API */
struct RenderTarget;
class Texture {
public:
TextureType type;
RS::TextureLayeredType layered_type = RS::TEXTURE_LAYERED_2D_ARRAY;
RenderingDevice::TextureType rd_type;
RID rd_texture;
RID rd_texture_srgb;
RenderingDevice::DataFormat rd_format;
RenderingDevice::DataFormat rd_format_srgb;
RD::TextureView rd_view;
Image::Format format;
Image::Format validated_format;
int width;
int height;
int depth;
int layers;
int mipmaps;
int height_2d;
int width_2d;
struct BufferSlice3D {
Size2i size;
uint32_t offset = 0;
uint32_t buffer_size = 0;
};
Vector<BufferSlice3D> buffer_slices_3d;
uint32_t buffer_size_3d = 0;
RenderTarget *render_target = nullptr;
bool is_render_target;
bool is_proxy;
Ref<Image> image_cache_2d;
String path;
RID proxy_to;
Vector<RID> proxies;
HashSet<RID> lightmap_users;
RS::TextureDetectCallback detect_3d_callback = nullptr;
void *detect_3d_callback_ud = nullptr;
RS::TextureDetectCallback detect_normal_callback = nullptr;
void *detect_normal_callback_ud = nullptr;
RS::TextureDetectRoughnessCallback detect_roughness_callback = nullptr;
void *detect_roughness_callback_ud = nullptr;
CanvasTexture *canvas_texture = nullptr;
void cleanup();
};
// Textures can be created from threads, so this RID_Owner is thread safe.
mutable RID_Owner<Texture, true> texture_owner;
Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); }
struct TextureToRDFormat {
RD::DataFormat format;
RD::DataFormat format_srgb;
RD::TextureSwizzle swizzle_r;
RD::TextureSwizzle swizzle_g;
RD::TextureSwizzle swizzle_b;
RD::TextureSwizzle swizzle_a;
TextureToRDFormat() {
format = RD::DATA_FORMAT_MAX;
format_srgb = RD::DATA_FORMAT_MAX;
swizzle_r = RD::TEXTURE_SWIZZLE_R;
swizzle_g = RD::TEXTURE_SWIZZLE_G;
swizzle_b = RD::TEXTURE_SWIZZLE_B;
swizzle_a = RD::TEXTURE_SWIZZLE_A;
}
};
Ref<Image> _validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format);
void _texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0, bool p_immediate = false);
struct TextureFromRDFormat {
Image::Format image_format;
RD::DataFormat rd_format;
RD::DataFormat rd_format_srgb;
RD::TextureSwizzle swizzle_r;
RD::TextureSwizzle swizzle_g;
RD::TextureSwizzle swizzle_b;
RD::TextureSwizzle swizzle_a;
TextureFromRDFormat() {
image_format = Image::FORMAT_MAX;
rd_format = RD::DATA_FORMAT_MAX;
rd_format_srgb = RD::DATA_FORMAT_MAX;
swizzle_r = RD::TEXTURE_SWIZZLE_R;
swizzle_g = RD::TEXTURE_SWIZZLE_G;
swizzle_b = RD::TEXTURE_SWIZZLE_B;
swizzle_a = RD::TEXTURE_SWIZZLE_A;
}
};
void _texture_format_from_rd(RD::DataFormat p_rd_format, TextureFromRDFormat &r_format);
/* DECAL API */
struct DecalAtlas {
struct Texture {
int panorama_to_dp_users;
int users;
Rect2 uv_rect;
};
struct SortItem {
RID texture;
Size2i pixel_size;
Size2i size;
Point2i pos;
bool operator<(const SortItem &p_item) const {
//sort larger to smaller
if (size.height == p_item.size.height) {
return size.width > p_item.size.width;
} else {
return size.height > p_item.size.height;
}
}
};
HashMap<RID, Texture> textures;
bool dirty = true;
int mipmaps = 5;
RID texture;
RID texture_srgb;
struct MipMap {
RID fb;
RID texture;
Size2i size;
};
Vector<MipMap> texture_mipmaps;
Size2i size;
} decal_atlas;
struct Decal {
Vector3 size = Vector3(2, 2, 2);
RID textures[RS::DECAL_TEXTURE_MAX];
float emission_energy = 1.0;
float albedo_mix = 1.0;
Color modulate = Color(1, 1, 1, 1);
uint32_t cull_mask = (1 << 20) - 1;
float upper_fade = 0.3;
float lower_fade = 0.3;
bool distance_fade = false;
float distance_fade_begin = 40.0;
float distance_fade_length = 10.0;
float normal_fade = 0.0;
Dependency dependency;
};
mutable RID_Owner<Decal, true> decal_owner;
/* DECAL INSTANCE */
struct DecalInstance {
RID decal;
Transform3D transform;
float sorting_offset = 0.0;
uint32_t cull_mask = 0;
RendererRD::ForwardID forward_id = -1;
};
mutable RID_Owner<DecalInstance> decal_instance_owner;
/* DECAL DATA (UBO) */
struct DecalData {
float xform[16];
float inv_extents[3];
float albedo_mix;
float albedo_rect[4];
float normal_rect[4];
float orm_rect[4];
float emission_rect[4];
float modulate[4];
float emission_energy;
uint32_t mask;
float upper_fade;
float lower_fade;
float normal_xform[12];
float normal[3];
float normal_fade;
};
struct DecalInstanceSort {
float depth;
DecalInstance *decal_instance;
Decal *decal;
bool operator<(const DecalInstanceSort &p_sort) const {
return depth < p_sort.depth;
}
};
uint32_t max_decals = 0;
uint32_t decal_count = 0;
DecalData *decals = nullptr;
DecalInstanceSort *decal_sort = nullptr;
RID decal_buffer;
/* RENDER TARGET API */
struct RenderTarget {
Size2i size;
uint32_t view_count;
RID color;
Vector<RID> color_slices;
RID color_multisample; // Needed when 2D MSAA is enabled.
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED; // 2D MSAA mode
bool msaa_needs_resolve = false; // 2D MSAA needs resolved
//used for retrieving from CPU
RD::DataFormat color_format = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
RD::DataFormat color_format_srgb = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
Image::Format image_format = Image::FORMAT_L8;
bool is_transparent = false;
bool use_hdr = false;
bool use_debanding = false;
bool sdf_enabled = false;
RID backbuffer; //used for effects
RID backbuffer_fb;
RID backbuffer_mipmap0;
Vector<RID> backbuffer_mipmaps;
RID framebuffer_uniform_set;
RID backbuffer_uniform_set;
RID sdf_buffer_write;
RID sdf_buffer_write_fb;
RID sdf_buffer_process[2];
RID sdf_buffer_read;
RID sdf_buffer_process_uniform_sets[2];
RS::ViewportSDFOversize sdf_oversize = RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT;
RS::ViewportSDFScale sdf_scale = RS::VIEWPORT_SDF_SCALE_50_PERCENT;
Size2i process_size;
// VRS
RS::ViewportVRSMode vrs_mode = RS::VIEWPORT_VRS_DISABLED;
RS::ViewportVRSUpdateMode vrs_update_mode = RS::VIEWPORT_VRS_UPDATE_ONCE;
RID vrs_texture;
Rect2i render_region;
// overridden textures
struct RTOverridden {
RID color;
RID depth;
RID velocity;
RID velocity_depth;
// In a multiview scenario, which is the most likely where we
// override our destination textures, we need to obtain slices
// for each layer of these textures.
// These are likely changing every frame as we loop through
// texture chains hence we add a cache to manage these slices.
// For this we define a key using the RID of the texture and
// the layer for which we create a slice.
struct SliceKey {
RID rid;
uint32_t layer = 0;
bool operator==(const SliceKey &p_val) const {
return (rid == p_val.rid) && (layer == p_val.layer);
}
static uint32_t hash(const SliceKey &p_val) {
uint32_t h = hash_one_uint64(p_val.rid.get_id());
h = hash_murmur3_one_32(p_val.layer, h);
return hash_fmix32(h);
}
SliceKey() {}
SliceKey(RID p_rid, uint32_t p_layer) {
rid = p_rid;
layer = p_layer;
}
};
mutable HashMap<SliceKey, RID, SliceKey> cached_slices;
} overridden;
//texture generated for this owner (nor RD).
RID texture;
bool was_used;
//clear request
bool clear_requested;
Color clear_color;
RID get_framebuffer();
};
mutable RID_Owner<RenderTarget> render_target_owner;
RenderTarget *get_render_target(RID p_rid) const { return render_target_owner.get_or_null(p_rid); }
void _clear_render_target(RenderTarget *rt);
void _update_render_target(RenderTarget *rt);
void _create_render_target_backbuffer(RenderTarget *rt);
void _render_target_allocate_sdf(RenderTarget *rt);
void _render_target_clear_sdf(RenderTarget *rt);
Rect2i _render_target_get_sdf_rect(const RenderTarget *rt) const;
struct RenderTargetSDF {
enum {
SHADER_LOAD,
SHADER_LOAD_SHRINK,
SHADER_PROCESS,
SHADER_PROCESS_OPTIMIZED,
SHADER_STORE,
SHADER_STORE_SHRINK,
SHADER_MAX
};
struct PushConstant {
int32_t size[2];
int32_t stride;
int32_t shift;
int32_t base_size[2];
int32_t pad[2];
};
CanvasSdfShaderRD shader;
RID shader_version;
RID pipelines[SHADER_MAX];
} rt_sdf;
public:
static TextureStorage *get_singleton();
_FORCE_INLINE_ RID texture_rd_get_default(DefaultRDTexture p_texture) {
return default_rd_textures[p_texture];
}
TextureStorage();
virtual ~TextureStorage();
bool free(RID p_rid);
/* Canvas Texture API */
bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); }
virtual RID canvas_texture_allocate() override;
virtual void canvas_texture_initialize(RID p_rid) override;
virtual void canvas_texture_free(RID p_rid) override;
virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override;
virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override;
virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override;
virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override;
CanvasTextureInfo canvas_texture_get_info(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, bool p_use_srgb, bool p_texture_is_data);
void canvas_texture_set_invalidation_callback(RID p_canvas_texture, InvalidationCallback p_callback, void *p_userdata);
/* Texture API */
bool owns_texture(RID p_rid) const { return texture_owner.owns(p_rid); }
virtual RID texture_allocate() override;
virtual void texture_free(RID p_rid) override;
virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override;
virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override;
virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override;
virtual void texture_external_initialize(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override;
virtual void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent
virtual RID texture_create_from_native_handle(RS::TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers = 1, RS::TextureLayeredType p_layered_type = RS::TEXTURE_LAYERED_2D_ARRAY) override;
virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override;
virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override;
virtual void texture_external_update(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override;
virtual void texture_proxy_update(RID p_proxy, RID p_base) override;
Ref<Image> texture_2d_placeholder;
Vector<Ref<Image>> texture_2d_array_placeholder;
Vector<Ref<Image>> cubemap_placeholder;
Vector<Ref<Image>> texture_3d_placeholder;
//these two APIs can be used together or in combination with the others.
virtual void texture_2d_placeholder_initialize(RID p_texture) override;
virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override;
virtual void texture_3d_placeholder_initialize(RID p_texture) override;
virtual Ref<Image> texture_2d_get(RID p_texture) const override;
virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override;
virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const override;
virtual void texture_replace(RID p_texture, RID p_by_texture) override;
virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) override;
virtual void texture_set_path(RID p_texture, const String &p_path) override;
virtual String texture_get_path(RID p_texture) const override;
virtual Image::Format texture_get_format(RID p_texture) const override;
virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override;
virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override;
virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override;
virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) override;
virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override;
virtual Size2 texture_size_with_proxy(RID p_proxy) override;
virtual void texture_rd_initialize(RID p_texture, const RID &p_rd_texture, const RS::TextureLayeredType p_layer_type = RS::TEXTURE_LAYERED_2D_ARRAY) override;
virtual RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) const override;
virtual uint64_t texture_get_native_handle(RID p_texture, bool p_srgb = false) const override;
//internal usage
_FORCE_INLINE_ TextureType texture_get_type(RID p_texture) {
RendererRD::TextureStorage::Texture *tex = texture_owner.get_or_null(p_texture);
if (tex == nullptr) {
return TYPE_2D;
}
return tex->type;
}
_FORCE_INLINE_ int texture_get_layers(RID p_texture) {
RendererRD::TextureStorage::Texture *tex = texture_owner.get_or_null(p_texture);
if (tex == nullptr) {
return 1;
}
return tex->layers;
}
_FORCE_INLINE_ Size2i texture_2d_get_size(RID p_texture) {
if (p_texture.is_null()) {
return Size2i();
}
RendererRD::TextureStorage::Texture *tex = texture_owner.get_or_null(p_texture);
if (!tex) {
return Size2i();
}
return Size2i(tex->width_2d, tex->height_2d);
}
/* DECAL API */
void update_decal_atlas();
bool owns_decal(RID p_rid) const { return decal_owner.owns(p_rid); }
RID decal_atlas_get_texture() const;
RID decal_atlas_get_texture_srgb() const;
_FORCE_INLINE_ Rect2 decal_atlas_get_texture_rect(RID p_texture) {
DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture);
if (!t) {
return Rect2();
}
return t->uv_rect;
}
virtual RID decal_allocate() override;
virtual void decal_initialize(RID p_decal) override;
virtual void decal_free(RID p_rid) override;
virtual void decal_set_size(RID p_decal, const Vector3 &p_size) override;
virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override;
virtual void decal_set_emission_energy(RID p_decal, float p_energy) override;
virtual void decal_set_albedo_mix(RID p_decal, float p_mix) override;
virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) override;
virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) override;
virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) override;
virtual void decal_set_fade(RID p_decal, float p_above, float p_below) override;
virtual void decal_set_normal_fade(RID p_decal, float p_fade) override;
void decal_atlas_mark_dirty_on_texture(RID p_texture);
void decal_atlas_remove_texture(RID p_texture);
virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override;
virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override;
_FORCE_INLINE_ Vector3 decal_get_size(RID p_decal) {
const Decal *decal = decal_owner.get_or_null(p_decal);
return decal->size;
}
_FORCE_INLINE_ RID decal_get_texture(RID p_decal, RS::DecalTexture p_texture) {
const Decal *decal = decal_owner.get_or_null(p_decal);
return decal->textures[p_texture];
}
_FORCE_INLINE_ Color decal_get_modulate(RID p_decal) {
const Decal *decal = decal_owner.get_or_null(p_decal);
return decal->modulate;
}
_FORCE_INLINE_ float decal_get_emission_energy(RID p_decal) {
const Decal *decal = decal_owner.get_or_null(p_decal);
return decal->emission_energy;
}
_FORCE_INLINE_ float decal_get_albedo_mix(RID p_decal) {
const Decal *decal = decal_owner.get_or_null(p_decal);
return decal->albedo_mix;
}
_FORCE_INLINE_ uint32_t decal_get_cull_mask(RID p_decal) {
const Decal *decal = decal_owner.get_or_null(p_decal);
return decal->cull_mask;
}
_FORCE_INLINE_ float decal_get_upper_fade(RID p_decal) {
const Decal *decal = decal_owner.get_or_null(p_decal);
return decal->upper_fade;
}
_FORCE_INLINE_ float decal_get_lower_fade(RID p_decal) {
const Decal *decal = decal_owner.get_or_null(p_decal);
return decal->lower_fade;
}
_FORCE_INLINE_ float decal_get_normal_fade(RID p_decal) {
const Decal *decal = decal_owner.get_or_null(p_decal);
return decal->normal_fade;
}
_FORCE_INLINE_ bool decal_is_distance_fade_enabled(RID p_decal) {
const Decal *decal = decal_owner.get_or_null(p_decal);
return decal->distance_fade;
}
_FORCE_INLINE_ float decal_get_distance_fade_begin(RID p_decal) {
const Decal *decal = decal_owner.get_or_null(p_decal);
return decal->distance_fade_begin;
}
_FORCE_INLINE_ float decal_get_distance_fade_length(RID p_decal) {
const Decal *decal = decal_owner.get_or_null(p_decal);
return decal->distance_fade_length;
}
virtual AABB decal_get_aabb(RID p_decal) const override;
virtual uint32_t decal_get_cull_mask(RID p_decal) const override;
Dependency *decal_get_dependency(RID p_decal);
/* DECAL INSTANCE API */
bool owns_decal_instance(RID p_rid) const { return decal_instance_owner.owns(p_rid); }
virtual RID decal_instance_create(RID p_decal) override;
virtual void decal_instance_free(RID p_decal_instance) override;
virtual void decal_instance_set_transform(RID p_decal_instance, const Transform3D &p_transform) override;
virtual void decal_instance_set_sorting_offset(RID p_decal_instance, float p_sorting_offset) override;
_FORCE_INLINE_ RID decal_instance_get_base(RID p_decal_instance) const {
DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance);
return di->decal;
}
_FORCE_INLINE_ RendererRD::ForwardID decal_instance_get_forward_id(RID p_decal_instance) const {
DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance);
return di->forward_id;
}
_FORCE_INLINE_ Transform3D decal_instance_get_transform(RID p_decal_instance) const {
DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance);
return di->transform;
}
_FORCE_INLINE_ ForwardID decal_instance_get_forward_id(RID p_decal_instance) {
DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance);
return di->forward_id;
}
_FORCE_INLINE_ void decal_instance_set_cullmask(RID p_decal_instance, uint32_t p_cull_mask) const {
DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance);
di->cull_mask = p_cull_mask;
}
/* DECAL DATA API */
void free_decal_data();
void set_max_decals(const uint32_t p_max_decals);
RID get_decal_buffer() { return decal_buffer; }
void update_decal_buffer(const PagedArray<RID> &p_decals, const Transform3D &p_camera_xform);
/* RENDER TARGET API */
bool owns_render_target(RID p_rid) const { return render_target_owner.owns(p_rid); }
virtual RID render_target_create() override;
virtual void render_target_free(RID p_rid) override;
virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) override;
virtual Point2i render_target_get_position(RID p_render_target) const override;
virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override;
virtual Size2i render_target_get_size(RID p_render_target) const override;
virtual void render_target_set_transparent(RID p_render_target, bool p_is_transparent) override;
virtual bool render_target_get_transparent(RID p_render_target) const override;
virtual void render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) override;
virtual bool render_target_get_direct_to_screen(RID p_render_target) const override;
virtual bool render_target_was_used(RID p_render_target) const override;
virtual void render_target_set_as_unused(RID p_render_target) override;
virtual void render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) override;
virtual RS::ViewportMSAA render_target_get_msaa(RID p_render_target) const override;
virtual void render_target_set_msaa_needs_resolve(RID p_render_target, bool p_needs_resolve) override;
virtual bool render_target_get_msaa_needs_resolve(RID p_render_target) const override;
virtual void render_target_do_msaa_resolve(RID p_render_target) override;
virtual void render_target_set_use_hdr(RID p_render_target, bool p_use_hdr) override;
virtual bool render_target_is_using_hdr(RID p_render_target) const override;
virtual void render_target_set_use_debanding(RID p_render_target, bool p_use_debanding) override;
virtual bool render_target_is_using_debanding(RID p_render_target) const override;
void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps);
void render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color);
void render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region);
RID render_target_get_back_buffer_uniform_set(RID p_render_target, RID p_base_shader);
virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color) override;
virtual bool render_target_is_clear_requested(RID p_render_target) override;
virtual Color render_target_get_clear_request_color(RID p_render_target) override;
virtual void render_target_disable_clear_request(RID p_render_target) override;
virtual void render_target_do_clear_request(RID p_render_target) override;
virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override;
RID render_target_get_sdf_texture(RID p_render_target);
RID render_target_get_sdf_framebuffer(RID p_render_target);
void render_target_sdf_process(RID p_render_target);
virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const override;
virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override;
bool render_target_is_sdf_enabled(RID p_render_target) const;
virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override;
virtual RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const override;
virtual void render_target_set_vrs_update_mode(RID p_render_target, RS::ViewportVRSUpdateMode p_mode) override;
virtual RS::ViewportVRSUpdateMode render_target_get_vrs_update_mode(RID p_render_target) const override;
virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override;
virtual RID render_target_get_vrs_texture(RID p_render_target) const override;
virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture, RID p_velocity_depth_texture) override;
virtual RID render_target_get_override_color(RID p_render_target) const override;
virtual RID render_target_get_override_depth(RID p_render_target) const override;
RID render_target_get_override_depth_slice(RID p_render_target, const uint32_t p_layer) const;
virtual RID render_target_get_override_velocity(RID p_render_target) const override;
RID render_target_get_override_velocity_slice(RID p_render_target, const uint32_t p_layer) const;
virtual RID render_target_get_override_velocity_depth(RID p_render_target) const override;
virtual void render_target_set_render_region(RID p_render_target, const Rect2i &p_render_region) override;
virtual Rect2i render_target_get_render_region(RID p_render_target) const override;
virtual RID render_target_get_texture(RID p_render_target) override;
virtual void render_target_set_velocity_target_size(RID p_render_target, const Size2i &p_target_size) override {}
virtual Size2i render_target_get_velocity_target_size(RID p_render_target) const override { return Size2i(0, 0); }
RID render_target_get_rd_framebuffer(RID p_render_target);
RID render_target_get_rd_texture(RID p_render_target);
RID render_target_get_rd_texture_slice(RID p_render_target, uint32_t p_layer);
RID render_target_get_rd_texture_msaa(RID p_render_target);
RID render_target_get_rd_backbuffer(RID p_render_target);
RID render_target_get_rd_backbuffer_framebuffer(RID p_render_target);
RID render_target_get_framebuffer_uniform_set(RID p_render_target);
RID render_target_get_backbuffer_uniform_set(RID p_render_target);
void render_target_set_framebuffer_uniform_set(RID p_render_target, RID p_uniform_set);
void render_target_set_backbuffer_uniform_set(RID p_render_target, RID p_uniform_set);
static RD::DataFormat render_target_get_color_format(bool p_use_hdr, bool p_srgb);
static uint32_t render_target_get_color_usage_bits(bool p_msaa);
};
} // namespace RendererRD

View File

@@ -0,0 +1,343 @@
/**************************************************************************/
/* utilities.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#include "utilities.h"
#include "../environment/fog.h"
#include "../environment/gi.h"
#include "light_storage.h"
#include "mesh_storage.h"
#include "particles_storage.h"
#include "texture_storage.h"
using namespace RendererRD;
Utilities *Utilities::singleton = nullptr;
Utilities::Utilities() {
singleton = this;
}
Utilities::~Utilities() {
singleton = nullptr;
}
/* INSTANCES */
RS::InstanceType Utilities::get_base_type(RID p_rid) const {
if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_rid)) {
return RS::INSTANCE_MESH;
}
if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_rid)) {
return RS::INSTANCE_MULTIMESH;
}
if (RendererRD::LightStorage::get_singleton()->owns_reflection_probe(p_rid)) {
return RS::INSTANCE_REFLECTION_PROBE;
}
if (RendererRD::TextureStorage::get_singleton()->owns_decal(p_rid)) {
return RS::INSTANCE_DECAL;
}
if (RendererRD::GI::get_singleton()->owns_voxel_gi(p_rid)) {
return RS::INSTANCE_VOXEL_GI;
}
if (RendererRD::LightStorage::get_singleton()->owns_light(p_rid)) {
return RS::INSTANCE_LIGHT;
}
if (RendererRD::LightStorage::get_singleton()->owns_lightmap(p_rid)) {
return RS::INSTANCE_LIGHTMAP;
}
if (RendererRD::ParticlesStorage::get_singleton()->owns_particles(p_rid)) {
return RS::INSTANCE_PARTICLES;
}
if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision(p_rid)) {
return RS::INSTANCE_PARTICLES_COLLISION;
}
if (RendererRD::Fog::get_singleton()->owns_fog_volume(p_rid)) {
return RS::INSTANCE_FOG_VOLUME;
}
if (owns_visibility_notifier(p_rid)) {
return RS::INSTANCE_VISIBLITY_NOTIFIER;
}
return RS::INSTANCE_NONE;
}
bool Utilities::free(RID p_rid) {
if (RendererRD::LightStorage::get_singleton()->free(p_rid)) {
return true;
} else if (RendererRD::MaterialStorage::get_singleton()->free(p_rid)) {
return true;
} else if (RendererRD::MeshStorage::get_singleton()->free(p_rid)) {
return true;
} else if (RendererRD::ParticlesStorage::get_singleton()->free(p_rid)) {
return true;
} else if (RendererRD::TextureStorage::get_singleton()->free(p_rid)) {
return true;
} else if (RendererRD::GI::get_singleton()->owns_voxel_gi(p_rid)) {
RendererRD::GI::get_singleton()->voxel_gi_free(p_rid);
return true;
} else if (RendererRD::Fog::get_singleton()->owns_fog_volume(p_rid)) {
RendererRD::Fog::get_singleton()->fog_volume_free(p_rid);
return true;
} else if (owns_visibility_notifier(p_rid)) {
visibility_notifier_free(p_rid);
return true;
} else {
return false;
}
}
/* DEPENDENCIES */
void Utilities::base_update_dependency(RID p_base, DependencyTracker *p_instance) {
if (MeshStorage::get_singleton()->owns_mesh(p_base)) {
Dependency *dependency = MeshStorage::get_singleton()->mesh_get_dependency(p_base);
p_instance->update_dependency(dependency);
} else if (MeshStorage::get_singleton()->owns_multimesh(p_base)) {
Dependency *dependency = MeshStorage::get_singleton()->multimesh_get_dependency(p_base);
p_instance->update_dependency(dependency);
RID mesh = MeshStorage::get_singleton()->multimesh_get_mesh(p_base);
if (mesh.is_valid()) {
base_update_dependency(mesh, p_instance);
}
} else if (LightStorage::get_singleton()->owns_reflection_probe(p_base)) {
Dependency *dependency = LightStorage::get_singleton()->reflection_probe_get_dependency(p_base);
p_instance->update_dependency(dependency);
} else if (TextureStorage::get_singleton()->owns_decal(p_base)) {
Dependency *dependency = TextureStorage::get_singleton()->decal_get_dependency(p_base);
p_instance->update_dependency(dependency);
} else if (GI::get_singleton()->owns_voxel_gi(p_base)) {
Dependency *dependency = GI::get_singleton()->voxel_gi_get_dependency(p_base);
p_instance->update_dependency(dependency);
} else if (LightStorage::get_singleton()->owns_lightmap(p_base)) {
Dependency *dependency = LightStorage::get_singleton()->lightmap_get_dependency(p_base);
p_instance->update_dependency(dependency);
} else if (LightStorage::get_singleton()->owns_light(p_base)) {
Dependency *dependency = LightStorage::get_singleton()->light_get_dependency(p_base);
p_instance->update_dependency(dependency);
} else if (ParticlesStorage::get_singleton()->owns_particles(p_base)) {
Dependency *dependency = ParticlesStorage::get_singleton()->particles_get_dependency(p_base);
p_instance->update_dependency(dependency);
} else if (ParticlesStorage::get_singleton()->owns_particles_collision(p_base)) {
Dependency *dependency = ParticlesStorage::get_singleton()->particles_collision_get_dependency(p_base);
p_instance->update_dependency(dependency);
} else if (Fog::get_singleton()->owns_fog_volume(p_base)) {
Dependency *dependency = Fog::get_singleton()->fog_volume_get_dependency(p_base);
p_instance->update_dependency(dependency);
} else if (owns_visibility_notifier(p_base)) {
VisibilityNotifier *vn = get_visibility_notifier(p_base);
p_instance->update_dependency(&vn->dependency);
}
}
/* VISIBILITY NOTIFIER */
RID Utilities::visibility_notifier_allocate() {
return visibility_notifier_owner.allocate_rid();
}
void Utilities::visibility_notifier_initialize(RID p_notifier) {
visibility_notifier_owner.initialize_rid(p_notifier, VisibilityNotifier());
}
void Utilities::visibility_notifier_free(RID p_notifier) {
VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
vn->dependency.deleted_notify(p_notifier);
visibility_notifier_owner.free(p_notifier);
}
void Utilities::visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) {
VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
ERR_FAIL_NULL(vn);
vn->aabb = p_aabb;
vn->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
void Utilities::visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) {
VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
ERR_FAIL_NULL(vn);
vn->enter_callback = p_enter_callbable;
vn->exit_callback = p_exit_callable;
}
AABB Utilities::visibility_notifier_get_aabb(RID p_notifier) const {
const VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
ERR_FAIL_NULL_V(vn, AABB());
return vn->aabb;
}
void Utilities::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) {
VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
ERR_FAIL_NULL(vn);
if (p_enter) {
if (vn->enter_callback.is_valid()) {
if (p_deferred) {
vn->enter_callback.call_deferred();
} else {
vn->enter_callback.call();
}
}
} else {
if (vn->exit_callback.is_valid()) {
if (p_deferred) {
vn->exit_callback.call_deferred();
} else {
vn->exit_callback.call();
}
}
}
}
/* TIMING */
void Utilities::capture_timestamps_begin() {
RD::get_singleton()->capture_timestamp("Frame Begin");
}
void Utilities::capture_timestamp(const String &p_name) {
RD::get_singleton()->capture_timestamp(p_name);
}
uint32_t Utilities::get_captured_timestamps_count() const {
return RD::get_singleton()->get_captured_timestamps_count();
}
uint64_t Utilities::get_captured_timestamps_frame() const {
return RD::get_singleton()->get_captured_timestamps_frame();
}
uint64_t Utilities::get_captured_timestamp_gpu_time(uint32_t p_index) const {
return RD::get_singleton()->get_captured_timestamp_gpu_time(p_index);
}
uint64_t Utilities::get_captured_timestamp_cpu_time(uint32_t p_index) const {
return RD::get_singleton()->get_captured_timestamp_cpu_time(p_index);
}
String Utilities::get_captured_timestamp_name(uint32_t p_index) const {
return RD::get_singleton()->get_captured_timestamp_name(p_index);
}
/* MISC */
void Utilities::update_dirty_resources() {
MaterialStorage::get_singleton()->_update_global_shader_uniforms(); //must do before materials, so it can queue them for update
MaterialStorage::get_singleton()->_update_queued_materials();
MeshStorage::get_singleton()->_update_dirty_multimeshes();
MeshStorage::get_singleton()->_update_dirty_skeletons();
TextureStorage::get_singleton()->update_decal_atlas();
}
bool Utilities::has_os_feature(const String &p_feature) const {
if (!RD::get_singleton()) {
return false;
}
if (p_feature == "rgtc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC5_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
return true;
}
#if !defined(ANDROID_ENABLED) && !defined(APPLE_EMBEDDED_ENABLED)
// Some Android devices report support for S3TC but we don't expect that and don't export the textures.
// This could be fixed but so few devices support it that it doesn't seem useful (and makes bigger APKs).
// For good measure we do the same hack for iOS, just in case.
if (p_feature == "s3tc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
return true;
}
#endif
if (p_feature == "bptc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC7_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
return true;
}
if (p_feature == "etc2" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
return true;
}
if (p_feature == "astc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ASTC_4x4_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
return true;
}
if (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)) {
return true;
}
return false;
}
void Utilities::update_memory_info() {
texture_mem_cache = RenderingDevice::get_singleton()->get_memory_usage(RenderingDevice::MEMORY_TEXTURES);
buffer_mem_cache = RenderingDevice::get_singleton()->get_memory_usage(RenderingDevice::MEMORY_BUFFERS);
total_mem_cache = RenderingDevice::get_singleton()->get_memory_usage(RenderingDevice::MEMORY_TOTAL);
}
uint64_t Utilities::get_rendering_info(RS::RenderingInfo p_info) {
if (p_info == RS::RENDERING_INFO_TEXTURE_MEM_USED) {
return texture_mem_cache;
} else if (p_info == RS::RENDERING_INFO_BUFFER_MEM_USED) {
return buffer_mem_cache;
} else if (p_info == RS::RENDERING_INFO_VIDEO_MEM_USED) {
return total_mem_cache;
}
return 0;
}
String Utilities::get_video_adapter_name() const {
return RenderingDevice::get_singleton()->get_device_name();
}
String Utilities::get_video_adapter_vendor() const {
return RenderingDevice::get_singleton()->get_device_vendor_name();
}
RenderingDevice::DeviceType Utilities::get_video_adapter_type() const {
return RenderingDevice::get_singleton()->get_device_type();
}
String Utilities::get_video_adapter_api_version() const {
return RenderingDevice::get_singleton()->get_device_api_version();
}
Size2i Utilities::get_maximum_viewport_size() const {
RenderingDevice *device = RenderingDevice::get_singleton();
int max_x = device->limit_get(RenderingDevice::LIMIT_MAX_VIEWPORT_DIMENSIONS_X);
int max_y = device->limit_get(RenderingDevice::LIMIT_MAX_VIEWPORT_DIMENSIONS_Y);
return Size2i(max_x, max_y);
}
uint32_t Utilities::get_maximum_shader_varyings() const {
return RenderingDevice::get_singleton()->limit_get(RenderingDevice::LIMIT_MAX_SHADER_VARYINGS);
}
uint64_t Utilities::get_maximum_uniform_buffer_size() const {
return RenderingDevice::get_singleton()->limit_get(RenderingDevice::LIMIT_MAX_UNIFORM_BUFFER_SIZE);
}

View File

@@ -0,0 +1,123 @@
/**************************************************************************/
/* utilities.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "core/templates/rid_owner.h"
#include "servers/rendering/storage/utilities.h"
namespace RendererRD {
/* VISIBILITY NOTIFIER */
struct VisibilityNotifier {
AABB aabb;
Callable enter_callback;
Callable exit_callback;
Dependency dependency;
};
class Utilities : public RendererUtilities {
private:
static Utilities *singleton;
/* VISIBILITY NOTIFIER */
mutable RID_Owner<VisibilityNotifier> visibility_notifier_owner;
/* MISC */
//keep cached since it can be called form any thread
uint64_t texture_mem_cache = 0;
uint64_t buffer_mem_cache = 0;
uint64_t total_mem_cache = 0;
public:
static Utilities *get_singleton() { return singleton; }
Utilities();
virtual ~Utilities() override;
/* INSTANCES */
virtual RS::InstanceType get_base_type(RID p_rid) const override;
virtual bool free(RID p_rid) override;
/* DEPENDENCIES */
virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) override;
/* VISIBILITY NOTIFIER */
VisibilityNotifier *get_visibility_notifier(RID p_rid) { return visibility_notifier_owner.get_or_null(p_rid); }
bool owns_visibility_notifier(RID p_rid) const { return visibility_notifier_owner.owns(p_rid); }
virtual RID visibility_notifier_allocate() override;
virtual void visibility_notifier_initialize(RID p_notifier) override;
virtual void visibility_notifier_free(RID p_notifier) override;
virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) override;
virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) override;
virtual AABB visibility_notifier_get_aabb(RID p_notifier) const override;
virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) override;
/* TIMING */
virtual void capture_timestamps_begin() override;
virtual void capture_timestamp(const String &p_name) override;
virtual uint32_t get_captured_timestamps_count() const override;
virtual uint64_t get_captured_timestamps_frame() const override;
virtual uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const override;
virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const override;
virtual String get_captured_timestamp_name(uint32_t p_index) const override;
/* MISC */
virtual void update_dirty_resources() override;
virtual void set_debug_generate_wireframes(bool p_generate) override {}
virtual bool has_os_feature(const String &p_feature) const override;
virtual void update_memory_info() override;
virtual uint64_t get_rendering_info(RS::RenderingInfo p_info) override;
virtual String get_video_adapter_name() const override;
virtual String get_video_adapter_vendor() const override;
virtual RenderingDevice::DeviceType get_video_adapter_type() const override;
virtual String get_video_adapter_api_version() const override;
virtual Size2i get_maximum_viewport_size() const override;
virtual uint32_t get_maximum_shader_varyings() const override;
virtual uint64_t get_maximum_uniform_buffer_size() const override;
};
} // namespace RendererRD