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:
-rw-r--r--source/blender/draw/CMakeLists.txt2
-rw-r--r--source/blender/draw/engines/eevee/shaders/shadow_vert.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/surface_frag.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/surface_vert.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl5
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl23
-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
-rw-r--r--source/blender/gpu/GPU_material.h5
-rw-r--r--source/blender/gpu/intern/gpu_codegen.cc10
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.c28
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_attribute.glsl7
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_attribute.cc16
19 files changed, 295 insertions, 44 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 5704c9e6774..f0c0a435e2a 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -227,6 +227,8 @@ set(SRC
intern/draw_manager.h
intern/draw_manager.hh
intern/draw_pass.hh
+ intern/draw_resource.cc
+ intern/draw_resource.hh
intern/draw_shader_shared.h
intern/draw_shader.h
intern/draw_subdivision.h
diff --git a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl
index 57d70334651..062a40f35c2 100644
--- a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl
@@ -152,3 +152,7 @@ vec4 attr_load_color_post(vec4 attr)
{
return attr;
}
+vec4 attr_load_uniform(vec4 attr, const uint attr_hash)
+{
+ return attr;
+}
diff --git a/source/blender/draw/engines/eevee/shaders/surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/surface_frag.glsl
index 2a212b757c2..f84db01de18 100644
--- a/source/blender/draw/engines/eevee/shaders/surface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/surface_frag.glsl
@@ -182,3 +182,7 @@ vec4 attr_load_color_post(vec4 attr)
{
return attr;
}
+vec4 attr_load_uniform(vec4 attr, const uint attr_hash)
+{
+ return attr;
+}
diff --git a/source/blender/draw/engines/eevee/shaders/surface_vert.glsl b/source/blender/draw/engines/eevee/shaders/surface_vert.glsl
index 4a3a91b8534..54aad7891dc 100644
--- a/source/blender/draw/engines/eevee/shaders/surface_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/surface_vert.glsl
@@ -165,3 +165,7 @@ vec4 attr_load_color_post(vec4 attr)
{
return attr;
}
+vec4 attr_load_uniform(vec4 attr, const uint attr_hash)
+{
+ return attr;
+}
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
index c6de723ac25..9ed21fc0bf5 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
@@ -178,3 +178,7 @@ vec4 attr_load_color_post(vec4 attr)
#endif
return attr;
}
+vec4 attr_load_uniform(vec4 attr, const uint attr_hash)
+{
+ return attr;
+}
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl
index b3b9c7af19c..2d51fbd9edc 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl
@@ -87,3 +87,8 @@ vec4 attr_load_color_post(vec4 attr)
{
return attr;
}
+
+vec4 attr_load_uniform(vec4 attr, const uint attr_hash)
+{
+ return attr;
+}
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl
index 13ad387289d..491e15341f9 100644
--- a/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl
@@ -409,3 +409,26 @@ vec4 attr_load_color_post(vec4 attr)
#endif
/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Volume Attribute post
+ *
+ * TODO(@fclem): These implementation details should concern the DRWManager and not be a fix on
+ * the engine side. But as of now, the engines are responsible for loading the attributes.
+ *
+ * \{ */
+
+vec4 attr_load_uniform(vec4 attr, const uint attr_hash)
+{
+#if defined(OBINFO_LIB) && defined(OBATTR_LIB)
+ for (int i = ObjectAttributeStart; i < ObjectAttributeLen; i++) {
+ if (drw_attrs[i].hash_code == attr_hash) {
+ return vec4(
+ drw_attrs[i].data_x, drw_attrs[i].data_y, drw_attrs[i].data_z, drw_attrs[i].data_w);
+ }
+ }
+#endif
+ return attr;
+}
+
+/** \} */
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");
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 042979b3a86..023221543ec 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -149,7 +149,10 @@ GPUNodeLink *GPU_attribute_with_default(GPUMaterial *mat,
eCustomDataType type,
const char *name,
eGPUDefaultValue default_value);
-GPUNodeLink *GPU_uniform_attribute(GPUMaterial *mat, const char *name, bool use_dupli);
+GPUNodeLink *GPU_uniform_attribute(GPUMaterial *mat,
+ const char *name,
+ bool use_dupli,
+ uint32_t *r_hash);
GPUNodeLink *GPU_image(GPUMaterial *mat,
struct Image *ima,
struct ImageUser *iuser,
diff --git a/source/blender/gpu/intern/gpu_codegen.cc b/source/blender/gpu/intern/gpu_codegen.cc
index d58ede4ccd8..f774f33e03d 100644
--- a/source/blender/gpu/intern/gpu_codegen.cc
+++ b/source/blender/gpu/intern/gpu_codegen.cc
@@ -199,8 +199,7 @@ static std::ostream &operator<<(std::ostream &stream, const GPUOutput *output)
}
/* Trick type to change overload and keep a somewhat nice syntax. */
-struct GPUConstant : public GPUInput {
-};
+struct GPUConstant : public GPUInput {};
/* Print data constructor (i.e: vec2(1.0f, 1.0f)). */
static std::ostream &operator<<(std::ostream &stream, const GPUConstant *input)
@@ -208,9 +207,10 @@ static std::ostream &operator<<(std::ostream &stream, const GPUConstant *input)
stream << input->type << "(";
for (int i = 0; i < input->type; i++) {
char formated_float[32];
- /* Print with the maximum precision for single precision float using scientific notation.
- * See https://stackoverflow.com/questions/16839658/#answer-21162120 */
- SNPRINTF(formated_float, "%.9g", input->vec[i]);
+ /* Use uint representation to allow exact same bit pattern even if NaN. This is because we can
+ * pass UINTs as floats for constants. */
+ const uint32_t *uint_vec = reinterpret_cast<const uint32_t *>(input->vec);
+ SNPRINTF(formated_float, "uintBitsToFloat(%uu)", uint_vec[i]);
stream << formated_float;
if (i < input->type - 1) {
stream << ", ";
diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c
index 4d391ff9063..f82af7538b5 100644
--- a/source/blender/gpu/intern/gpu_node_graph.c
+++ b/source/blender/gpu/intern/gpu_node_graph.c
@@ -320,20 +320,7 @@ void gpu_node_graph_finalize_uniform_attrs(GPUNodeGraph *graph)
LISTBASE_FOREACH (GPUUniformAttr *, attr, &attrs->list) {
attr->id = next_id++;
-
- attr->hash_code = BLI_ghashutil_strhash_p(attr->name);
-
- if (attr->use_dupli) {
- attr->hash_code ^= BLI_ghashutil_uinthash(attr->id);
- }
-
- attrs->hash_code ^= attr->hash_code;
-
- {
- char attr_name_esc[sizeof(attr->name) * 2];
- BLI_str_escape(attr_name_esc, attr->name, sizeof(attr_name_esc));
- SNPRINTF(attr->name_id_prop, "[\"%s\"]", attr_name_esc);
- }
+ attrs->hash_code ^= BLI_ghashutil_uinthash(attr->hash_code + (1 << (attr->id + 1)));
}
}
@@ -428,7 +415,13 @@ static GPUUniformAttr *gpu_node_graph_add_uniform_attribute(GPUNodeGraph *graph,
if (attr == NULL && attrs->count < GPU_MAX_UNIFORM_ATTR) {
attr = MEM_callocN(sizeof(*attr), __func__);
STRNCPY(attr->name, name);
+ {
+ char attr_name_esc[sizeof(attr->name) * 2];
+ BLI_str_escape(attr_name_esc, attr->name, sizeof(attr_name_esc));
+ SNPRINTF(attr->name_id_prop, "[\"%s\"]", attr_name_esc);
+ }
attr->use_dupli = use_dupli;
+ attr->hash_code = BLI_ghashutil_strhash_p(attr->name) << 1 | (attr->use_dupli ? 0 : 1);
attr->id = -1;
BLI_addtail(&attrs->list, attr);
attrs->count++;
@@ -532,16 +525,21 @@ GPUNodeLink *GPU_attribute_with_default(GPUMaterial *mat,
return link;
}
-GPUNodeLink *GPU_uniform_attribute(GPUMaterial *mat, const char *name, bool use_dupli)
+GPUNodeLink *GPU_uniform_attribute(GPUMaterial *mat,
+ const char *name,
+ bool use_dupli,
+ uint32_t *r_hash)
{
GPUNodeGraph *graph = gpu_material_node_graph(mat);
GPUUniformAttr *attr = gpu_node_graph_add_uniform_attribute(graph, name, use_dupli);
/* Dummy fallback if out of slots. */
if (attr == NULL) {
+ *r_hash = 0;
static const float zero_data[GPU_MAX_CONSTANT_DATA] = {0.0f};
return GPU_constant(zero_data);
}
+ *r_hash = attr->hash_code;
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_UNIFORM_ATTR;
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_attribute.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_attribute.glsl
index af4a511d627..bacf089deb1 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_attribute.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_attribute.glsl
@@ -22,6 +22,13 @@ void node_attribute_flame(vec4 attr, out float out_attr)
out_attr = attr.x;
}
+void node_attribute_uniform(vec4 attr, const float attr_hash, out vec4 out_attr)
+{
+ /* Temporary solution to support both old UBO attribs and new SSBO loading.
+ * Old UBO load is already done through `attr` and will just be passed through. */
+ out_attr = attr_load_uniform(attr, floatBitsToUint(attr_hash));
+}
+
void node_attribute(
vec4 attr, out vec4 outcol, out vec3 outvec, out float outf, out float outalpha)
{
diff --git a/source/blender/nodes/shader/nodes/node_shader_attribute.cc b/source/blender/nodes/shader/nodes/node_shader_attribute.cc
index d01271c15d3..65d053e6379 100644
--- a/source/blender/nodes/shader/nodes/node_shader_attribute.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_attribute.cc
@@ -36,6 +36,7 @@ static int node_shader_gpu_attribute(GPUMaterial *mat,
{
NodeShaderAttribute *attr = static_cast<NodeShaderAttribute *>(node->storage);
bool is_varying = attr->type == SHD_ATTRIBUTE_GEOMETRY;
+ float attr_hash = 0.0f;
GPUNodeLink *cd_attr;
@@ -43,7 +44,12 @@ static int node_shader_gpu_attribute(GPUMaterial *mat,
cd_attr = GPU_attribute(mat, CD_AUTO_FROM_NAME, attr->name);
}
else {
- cd_attr = GPU_uniform_attribute(mat, attr->name, attr->type == SHD_ATTRIBUTE_INSTANCER);
+ cd_attr = GPU_uniform_attribute(mat,
+ attr->name,
+ attr->type == SHD_ATTRIBUTE_INSTANCER,
+ reinterpret_cast<uint32_t *>(&attr_hash));
+
+ GPU_link(mat, "node_attribute_uniform", cd_attr, GPU_constant(&attr_hash), &cd_attr);
}
if (STREQ(attr->name, "color")) {
@@ -55,9 +61,11 @@ static int node_shader_gpu_attribute(GPUMaterial *mat,
GPU_stack_link(mat, node, "node_attribute", in, out, cd_attr);
- int i;
- LISTBASE_FOREACH_INDEX (bNodeSocket *, sock, &node->outputs, i) {
- node_shader_gpu_bump_tex_coord(mat, node, &out[i].link);
+ if (is_varying) {
+ int i;
+ LISTBASE_FOREACH_INDEX (bNodeSocket *, sock, &node->outputs, i) {
+ node_shader_gpu_bump_tex_coord(mat, node, &out[i].link);
+ }
}
return 1;