Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2022-09-01 15:46:17 +0300
committerClément Foucault <foucault.clem@gmail.com>2022-09-02 20:37:15 +0300
commite48a6fcc6397e5a964f2096d937ac189f07ce999 (patch)
tree37f98d5dab5c869b7248fc65a35edfc1b618b531 /source/blender/draw/intern
parent356460f5cf659ef071daa1267ab368b733b4133e (diff)
DRW-Next: Add uniform attributes (object attributes) support
This replaces the direct shader uniform layout declaration by a linear search through a global buffer. Each instance has an attribute offset inside the global buffer and an attribute count. This removes any padding and tighly pack all uniform attributes inside a single buffer. This would also remove the limit of 8 attribute but it is kept because of compatibility with the old system that is still used by the old draw manager.
Diffstat (limited to 'source/blender/draw/intern')
-rw-r--r--source/blender/draw/intern/draw_manager.cc25
-rw-r--r--source/blender/draw/intern/draw_manager.hh52
-rw-r--r--source/blender/draw/intern/draw_resource.cc109
-rw-r--r--source/blender/draw/intern/draw_resource.hh6
-rw-r--r--source/blender/draw/intern/draw_shader_shared.h24
-rw-r--r--source/blender/draw/intern/shaders/common_attribute_lib.glsl1
-rw-r--r--source/blender/draw/intern/shaders/draw_object_infos_info.hh10
7 files changed, 208 insertions, 19 deletions
diff --git a/source/blender/draw/intern/draw_manager.cc b/source/blender/draw/intern/draw_manager.cc
index 8fb2ffb39e8..2841abb53e7 100644
--- a/source/blender/draw/intern/draw_manager.cc
+++ b/source/blender/draw/intern/draw_manager.cc
@@ -43,6 +43,7 @@ void Manager::begin_sync()
memset(infos_buf.data(), 0xF0, resource_len_ * sizeof(*infos_buf.data()));
#endif
resource_len_ = 0;
+ attribute_len_ = 0;
/* TODO(fclem): Resize buffers if too big, but with an hysteresis threshold. */
object_active = DST.draw_ctx.obact;
@@ -58,6 +59,8 @@ void Manager::end_sync()
matrix_buf.push_update();
bounds_buf.push_update();
infos_buf.push_update();
+ attributes_buf.push_update();
+ attributes_buf_legacy.push_update();
debug_bind();
@@ -90,6 +93,16 @@ void Manager::debug_bind()
#endif
}
+void Manager::resource_bind()
+{
+ GPU_storagebuf_bind(matrix_buf, DRW_OBJ_MAT_SLOT);
+ GPU_storagebuf_bind(infos_buf, DRW_OBJ_INFOS_SLOT);
+ GPU_storagebuf_bind(attributes_buf, DRW_OBJ_ATTR_SLOT);
+ /* 2 is the hardcoded location of the uniform attr UBO. */
+ /* TODO(@fclem): Remove this workaround. */
+ GPU_uniformbuf_bind(attributes_buf_legacy, 2);
+}
+
void Manager::submit(PassSimple &pass, View &view)
{
view.bind();
@@ -101,9 +114,7 @@ void Manager::submit(PassSimple &pass, View &view)
pass.draw_commands_buf_.bind(state, pass.headers_, pass.commands_);
- GPU_storagebuf_bind(matrix_buf, DRW_OBJ_MAT_SLOT);
- GPU_storagebuf_bind(infos_buf, DRW_OBJ_INFOS_SLOT);
- // GPU_storagebuf_bind(attribute_buf, DRW_OBJ_ATTR_SLOT); /* TODO */
+ resource_bind();
pass.submit(state);
@@ -126,9 +137,7 @@ void Manager::submit(PassMain &pass, View &view)
pass.draw_commands_buf_.bind(state, pass.headers_, pass.commands_, view.visibility_buf_);
- GPU_storagebuf_bind(matrix_buf, DRW_OBJ_MAT_SLOT);
- GPU_storagebuf_bind(infos_buf, DRW_OBJ_INFOS_SLOT);
- // GPU_storagebuf_bind(attribute_buf, DRW_OBJ_ATTR_SLOT); /* TODO */
+ resource_bind();
pass.submit(state);
@@ -150,9 +159,7 @@ void Manager::submit(PassSimple &pass)
pass.draw_commands_buf_.bind(state, pass.headers_, pass.commands_);
- GPU_storagebuf_bind(matrix_buf, DRW_OBJ_MAT_SLOT);
- GPU_storagebuf_bind(infos_buf, DRW_OBJ_INFOS_SLOT);
- // GPU_storagebuf_bind(attribute_buf, DRW_OBJ_ATTR_SLOT); /* TODO */
+ resource_bind();
pass.submit(state);
diff --git a/source/blender/draw/intern/draw_manager.hh b/source/blender/draw/intern/draw_manager.hh
index 5f110b8bb6b..867b376702c 100644
--- a/source/blender/draw/intern/draw_manager.hh
+++ b/source/blender/draw/intern/draw_manager.hh
@@ -13,7 +13,9 @@
* \note It is currently work in progress and should replace the old global draw manager.
*/
+#include "BLI_listbase_wrapper.hh"
#include "BLI_sys_types.h"
+#include "GPU_material.h"
#include "draw_resource.hh"
#include "draw_view.hh"
@@ -41,6 +43,9 @@ class Manager {
using ObjectMatricesBuf = StorageArrayBuffer<ObjectMatrices, 128>;
using ObjectBoundsBuf = StorageArrayBuffer<ObjectBounds, 128>;
using ObjectInfosBuf = StorageArrayBuffer<ObjectInfos, 128>;
+ using ObjectAttributeBuf = StorageArrayBuffer<ObjectAttribute, 128>;
+ /** TODO(fclem): Remove once we get rid of old EEVEE codebase. DRW_RESOURCE_CHUNK_LEN = 512 */
+ using ObjectAttributeLegacyBuf = UniformArrayBuffer<float4, 8 * 512>;
public:
struct SubmitDebugOutput {
@@ -67,14 +72,25 @@ class Manager {
ObjectBoundsBuf bounds_buf;
ObjectInfosBuf infos_buf;
+ /**
+ * Object Attributes are reference by indirection data inside ObjectInfos.
+ * This is because attribute list is arbitrary.
+ */
+ ObjectAttributeBuf attributes_buf;
+ /** TODO(fclem): Remove once we get rid of old EEVEE codebase. Only here to satisfy bindings. */
+ ObjectAttributeLegacyBuf attributes_buf_legacy;
+
/** List of textures coming from Image data-blocks. They need to be refcounted in order to avoid
* beeing freed in another thread. */
Vector<GPUTexture *> acquired_textures;
private:
+ /** Number of resource handle recorded. */
uint resource_len_ = 0;
- Object *object = nullptr;
+ /** Number of object attribute recorded. */
+ uint attribute_len_ = 0;
+ Object *object = nullptr;
Object *object_active = nullptr;
public:
@@ -104,7 +120,7 @@ class Manager {
* Populate additional per resource data on demand.
*/
void extract_object_attributes(ResourceHandle handle,
- Object &object,
+ const ObjectRef &ref,
Span<GPUMaterial *> materials);
/**
@@ -145,6 +161,7 @@ class Manager {
void end_sync();
void debug_bind();
+ void resource_bind();
};
inline ResourceHandle Manager::resource_handle(const ObjectRef ref)
@@ -175,13 +192,34 @@ inline ResourceHandle Manager::resource_handle(const float4x4 &model_matrix,
}
inline void Manager::extract_object_attributes(ResourceHandle handle,
- Object &object,
+ const ObjectRef &ref,
Span<GPUMaterial *> materials)
{
- /* TODO */
- (void)handle;
- (void)object;
- (void)materials;
+ ObjectInfos &infos = infos_buf.get_or_resize(handle.resource_index());
+ infos.object_attrs_offset = attribute_len_;
+
+ /* Simple cache solution to avoid duplicates. */
+ Vector<uint32_t, 4> hash_cache;
+
+ for (const GPUMaterial *mat : materials) {
+ const GPUUniformAttrList *attr_list = GPU_material_uniform_attributes(mat);
+ if (attr_list == nullptr) {
+ continue;
+ }
+
+ LISTBASE_FOREACH (const GPUUniformAttr *, attr, &attr_list->list) {
+ /** WATCH: Linear Search. Avoid duplicate attributes across materials. */
+ if ((mat != materials.first()) && (hash_cache.first_index_of_try(attr->hash_code) != -1)) {
+ /* Attribute has already been added to the attribute buffer by another material. */
+ continue;
+ }
+ hash_cache.append(attr->hash_code);
+ if (attributes_buf.get_or_resize(attribute_len_).sync(ref, *attr)) {
+ infos.object_attrs_len++;
+ attribute_len_++;
+ }
+ }
+ }
}
} // namespace blender::draw
diff --git a/source/blender/draw/intern/draw_resource.cc b/source/blender/draw/intern/draw_resource.cc
new file mode 100644
index 00000000000..689df4edb31
--- /dev/null
+++ b/source/blender/draw/intern/draw_resource.cc
@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. */
+
+/** \file
+ * \ingroup draw
+ */
+
+#include "DNA_particle_types.h"
+#include "RNA_access.h"
+#include "RNA_path.h"
+#include "RNA_types.h"
+
+#include "draw_handle.hh"
+#include "draw_manager.hh"
+#include "draw_shader_shared.h"
+
+/* -------------------------------------------------------------------- */
+/** \name ObjectAttributes
+ * \{ */
+
+/**
+ * Extract object attribute from RNA property.
+ * Returns true if the attribute was correctly extracted.
+ * This function mirrors lookup_property in cycles/blender/blender_object.cpp
+ */
+bool ObjectAttribute::id_property_lookup(ID *id, const char *name)
+{
+ PointerRNA ptr, id_ptr;
+ PropertyRNA *prop;
+
+ if (id == nullptr) {
+ return false;
+ }
+
+ RNA_id_pointer_create(id, &id_ptr);
+
+ if (!RNA_path_resolve(&id_ptr, name, &ptr, &prop)) {
+ return false;
+ }
+
+ if (prop == nullptr) {
+ return false;
+ }
+
+ PropertyType type = RNA_property_type(prop);
+ int array_len = RNA_property_array_length(&ptr, prop);
+
+ if (array_len == 0) {
+ float value;
+
+ if (type == PROP_FLOAT) {
+ value = RNA_property_float_get(&ptr, prop);
+ }
+ else if (type == PROP_INT) {
+ value = RNA_property_int_get(&ptr, prop);
+ }
+ else {
+ return false;
+ }
+
+ *reinterpret_cast<float4 *>(&data_x) = float4(value, value, value, 1.0f);
+ return true;
+ }
+
+ if (type == PROP_FLOAT && array_len <= 4) {
+ *reinterpret_cast<float4 *>(&data_x) = float4(0.0f, 0.0f, 0.0f, 1.0f);
+ RNA_property_float_get_array(&ptr, prop, &data_x);
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Go through all possible source of the given object uniform attribute.
+ * Returns true if the attribute was correctly filled.
+ * This function mirrors lookup_instance_property in cycles/blender/blender_object.cpp
+ */
+bool ObjectAttribute::sync(const blender::draw::ObjectRef &ref, const GPUUniformAttr &attr)
+{
+ hash_code = attr.hash_code;
+
+ /* If requesting instance data, check the parent particle system and object. */
+ if (attr.use_dupli) {
+ if ((ref.dupli_object != nullptr) && (ref.dupli_object->particle_system != nullptr)) {
+ ParticleSettings *settings = ref.dupli_object->particle_system->part;
+ if (this->id_property_lookup((ID *)settings, attr.name_id_prop) ||
+ this->id_property_lookup((ID *)settings, attr.name)) {
+ return true;
+ }
+ }
+ if (this->id_property_lookup((ID *)ref.dupli_parent, attr.name_id_prop) ||
+ this->id_property_lookup((ID *)ref.dupli_parent, attr.name)) {
+ return true;
+ }
+ }
+
+ /* Check the object and mesh. */
+ if (ref.object != nullptr) {
+ if (this->id_property_lookup((ID *)ref.object, attr.name_id_prop) ||
+ this->id_property_lookup((ID *)ref.object, attr.name) ||
+ this->id_property_lookup((ID *)ref.object->data, attr.name_id_prop) ||
+ this->id_property_lookup((ID *)ref.object->data, attr.name)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/** \} */
diff --git a/source/blender/draw/intern/draw_resource.hh b/source/blender/draw/intern/draw_resource.hh
index 503833e8a6d..22ee43592a9 100644
--- a/source/blender/draw/intern/draw_resource.hh
+++ b/source/blender/draw/intern/draw_resource.hh
@@ -59,11 +59,17 @@ ENUM_OPERATORS(eObjectInfoFlag, OBJECT_NEGATIVE_SCALE)
inline void ObjectInfos::sync()
{
+ object_attrs_len = 0;
+ object_attrs_offset = 0;
+
flag = eObjectInfoFlag::OBJECT_NO_INFO;
}
inline void ObjectInfos::sync(const blender::draw::ObjectRef ref, bool is_active_object)
{
+ object_attrs_len = 0;
+ object_attrs_offset = 0;
+
color = ref.object->color;
index = ref.object->index;
SET_FLAG_FROM_TEST(flag, is_active_object, eObjectInfoFlag::OBJECT_ACTIVE);
diff --git a/source/blender/draw/intern/draw_shader_shared.h b/source/blender/draw/intern/draw_shader_shared.h
index 00d54311548..d43bfe6b159 100644
--- a/source/blender/draw/intern/draw_shader_shared.h
+++ b/source/blender/draw/intern/draw_shader_shared.h
@@ -13,6 +13,7 @@ typedef struct ObjectInfos ObjectInfos;
typedef struct ObjectBounds ObjectBounds;
typedef struct VolumeInfos VolumeInfos;
typedef struct CurvesInfos CurvesInfos;
+typedef struct ObjectAttribute ObjectAttribute;
typedef struct DrawCommand DrawCommand;
typedef struct DispatchCommand DispatchCommand;
typedef struct DRWDebugPrintBuffer DRWDebugPrintBuffer;
@@ -22,6 +23,8 @@ typedef struct DRWDebugDrawBuffer DRWDebugDrawBuffer;
# ifdef __cplusplus
/* C++ only forward declarations. */
struct Object;
+struct ID;
+struct GPUUniformAttr;
namespace blender::draw {
@@ -130,9 +133,9 @@ struct ObjectInfos {
#else
/** Uploaded as center + size. Converted to mul+bias to local coord. */
float3 orco_add;
- float _pad0;
+ uint object_attrs_offset;
float3 orco_mul;
- float _pad1;
+ uint object_attrs_len;
float4 color;
uint index;
@@ -193,6 +196,23 @@ struct CurvesInfos {
};
BLI_STATIC_ASSERT_ALIGN(CurvesInfos, 16)
+#pragma pack(push, 4)
+struct ObjectAttribute {
+ /* Workaround the padding cost from alignment requirements.
+ * (see GL spec : 7.6.2.2 Standard Uniform Block Layout) */
+ float data_x, data_y, data_z, data_w;
+ uint hash_code;
+
+#if !defined(GPU_SHADER) && defined(__cplusplus)
+ bool sync(const blender::draw::ObjectRef &ref, const GPUUniformAttr &attr);
+ bool id_property_lookup(ID *id, const char *name);
+#endif
+};
+#pragma pack(pop)
+/** \note we only align to 4 bytes and fetch data manually so make sure
+ * C++ compiler gives us the same size. */
+BLI_STATIC_ASSERT_ALIGN(ObjectAttribute, 20)
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/draw/intern/shaders/common_attribute_lib.glsl b/source/blender/draw/intern/shaders/common_attribute_lib.glsl
index ce5e49c7f63..6b5b6fcc846 100644
--- a/source/blender/draw/intern/shaders/common_attribute_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_attribute_lib.glsl
@@ -25,3 +25,4 @@ float attr_load_float(sampler3D tex);
float attr_load_temperature_post(float attr);
vec4 attr_load_color_post(vec4 attr);
+vec4 attr_load_uniform(vec4 attr, const uint attr_hash);
diff --git a/source/blender/draw/intern/shaders/draw_object_infos_info.hh b/source/blender/draw/intern/shaders/draw_object_infos_info.hh
index 2ec40ab76e3..31fee018fbc 100644
--- a/source/blender/draw/intern/shaders/draw_object_infos_info.hh
+++ b/source/blender/draw/intern/shaders/draw_object_infos_info.hh
@@ -25,4 +25,12 @@ GPU_SHADER_CREATE_INFO(draw_object_infos_new)
.define("OrcoTexCoFactors", "(drw_infos[resource_id].orco_mul_bias)")
.define("ObjectInfo", "(drw_infos[resource_id].infos)")
.define("ObjectColor", "(drw_infos[resource_id].color)")
- .storage_buf(DRW_OBJ_INFOS_SLOT, Qualifier::READ, "ObjectInfos", "drw_infos[]"); \ No newline at end of file
+ .storage_buf(DRW_OBJ_INFOS_SLOT, Qualifier::READ, "ObjectInfos", "drw_infos[]");
+
+/** \note Requires draw_object_infos_new. */
+GPU_SHADER_CREATE_INFO(draw_object_attribute_new)
+ .define("OBATTR_LIB")
+ .define("ObjectAttributeStart", "(drw_infos[resource_id].orco_mul_bias[0].w)")
+ .define("ObjectAttributeLen", "(drw_infos[resource_id].orco_mul_bias[1].w)")
+ .storage_buf(DRW_OBJ_ATTR_SLOT, Qualifier::READ, "ObjectAttribute", "drw_attrs[]")
+ .additional_info("draw_object_infos_new");