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--intern/cycles/blender/id_map.h32
-rw-r--r--intern/cycles/blender/object.cpp10
-rw-r--r--intern/cycles/blender/shader.cpp111
-rw-r--r--intern/cycles/blender/sync.cpp8
-rw-r--r--intern/cycles/blender/sync.h10
-rw-r--r--source/blender/blenkernel/BKE_duplilist.h8
-rw-r--r--source/blender/blenkernel/intern/object_dupli.cc28
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_instance.cc17
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_instance.hh1
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_material.cc5
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_sync.cc14
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_sync.hh10
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_world.cc3
-rw-r--r--source/blender/draw/intern/draw_defines.h2
-rw-r--r--source/blender/draw/intern/draw_instance_data.c56
-rw-r--r--source/blender/draw/intern/draw_manager.c23
-rw-r--r--source/blender/draw/intern/draw_manager.cc34
-rw-r--r--source/blender/draw/intern/draw_manager.h8
-rw-r--r--source/blender/draw/intern/draw_manager.hh32
-rw-r--r--source/blender/draw/intern/draw_manager_data.cc7
-rw-r--r--source/blender/draw/intern/draw_manager_exec.c9
-rw-r--r--source/blender/draw/intern/draw_manager_shader.c41
-rw-r--r--source/blender/draw/intern/draw_resource.cc13
-rw-r--r--source/blender/draw/intern/draw_shader_shared.h17
-rw-r--r--source/blender/draw/intern/shaders/draw_object_infos_info.hh8
-rw-r--r--source/blender/gpu/GPU_material.h15
-rw-r--r--source/blender/gpu/GPU_uniform_buffer.h1
-rw-r--r--source/blender/gpu/intern/gpu_codegen.cc6
-rw-r--r--source/blender/gpu/intern/gpu_material.c6
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.c77
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.h9
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_attribute.glsl25
-rw-r--r--source/blender/makesdna/DNA_node_types.h1
-rw-r--r--source/blender/makesdna/DNA_scene_types.h2
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c5
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_attribute.cc17
36 files changed, 649 insertions, 22 deletions
diff --git a/intern/cycles/blender/id_map.h b/intern/cycles/blender/id_map.h
index e77d2f647bf..5fb17bb0d50 100644
--- a/intern/cycles/blender/id_map.h
+++ b/intern/cycles/blender/id_map.h
@@ -20,7 +20,7 @@ CCL_NAMESPACE_BEGIN
* Utility class to map between Blender datablocks and Cycles data structures,
* and keep track of recalc tags from the dependency graph. */
-template<typename K, typename T> class id_map {
+template<typename K, typename T, typename Flags = uint> class id_map {
public:
id_map(Scene *scene_) : scene(scene_)
{
@@ -63,6 +63,11 @@ template<typename K, typename T> class id_map {
b_recalc.insert(id_ptr);
}
+ bool check_recalc(const BL::ID &id)
+ {
+ return id.ptr.data && b_recalc.find(id.ptr.data) != b_recalc.end();
+ }
+
bool has_recalc()
{
return !(b_recalc.empty());
@@ -154,6 +159,7 @@ template<typename K, typename T> class id_map {
TMapPair &pair = *jt;
if (do_delete && used_set.find(pair.second) == used_set.end()) {
+ flags.erase(pair.second);
scene->delete_node(pair.second);
}
else {
@@ -171,9 +177,33 @@ template<typename K, typename T> class id_map {
return b_map;
}
+ bool test_flag(T *data, Flags val)
+ {
+ typename map<T *, uint>::iterator it = flags.find(data);
+ return it != flags.end() && (it->second & (1 << val)) != 0;
+ }
+
+ void set_flag(T *data, Flags val)
+ {
+ flags[data] |= (1 << val);
+ }
+
+ void clear_flag(T *data, Flags val)
+ {
+ typename map<T *, uint>::iterator it = flags.find(data);
+ if (it != flags.end()) {
+ it->second &= ~(1 << val);
+
+ if (it->second == 0) {
+ flags.erase(it);
+ }
+ }
+ }
+
protected:
map<K, T *> b_map;
set<T *> used_set;
+ map<T *, uint> flags;
set<void *> b_recalc;
Scene *scene;
};
diff --git a/intern/cycles/blender/object.cpp b/intern/cycles/blender/object.cpp
index 8a3c1136104..5af1e18a597 100644
--- a/intern/cycles/blender/object.cpp
+++ b/intern/cycles/blender/object.cpp
@@ -96,6 +96,13 @@ bool BlenderSync::object_is_light(BL::Object &b_ob)
return (b_ob_data && b_ob_data.is_a(&RNA_Light));
}
+bool BlenderSync::object_is_camera(BL::Object &b_ob)
+{
+ BL::ID b_ob_data = b_ob.data();
+
+ return (b_ob_data && b_ob_data.is_a(&RNA_Camera));
+}
+
void BlenderSync::sync_object_motion_init(BL::Object &b_parent, BL::Object &b_ob, Object *object)
{
/* Initialize motion blur for object, detecting if it's enabled and creating motion
@@ -400,7 +407,8 @@ bool BlenderSync::sync_object_attributes(BL::DepsgraphObjectInstance &b_instance
std::string real_name;
BlenderAttributeType type = blender_attribute_name_split_type(name, &real_name);
- if (type != BL::ShaderNodeAttribute::attribute_type_GEOMETRY) {
+ if (type == BL::ShaderNodeAttribute::attribute_type_OBJECT ||
+ type == BL::ShaderNodeAttribute::attribute_type_INSTANCER) {
bool use_instancer = (type == BL::ShaderNodeAttribute::attribute_type_INSTANCER);
float4 value = lookup_instance_property(b_instance, real_name, use_instancer);
diff --git a/intern/cycles/blender/shader.cpp b/intern/cycles/blender/shader.cpp
index 9505f4ba58f..fd32e7ca1d7 100644
--- a/intern/cycles/blender/shader.cpp
+++ b/intern/cycles/blender/shader.cpp
@@ -22,6 +22,8 @@
#include "util/string.h"
#include "util/task.h"
+#include "BKE_duplilist.h"
+
CCL_NAMESPACE_BEGIN
typedef map<void *, ShaderInput *> PtrInputMap;
@@ -103,6 +105,7 @@ static ImageAlphaType get_image_alpha_type(BL::Image &b_image)
static const string_view object_attr_prefix("\x01object:");
static const string_view instancer_attr_prefix("\x01instancer:");
+static const string_view view_layer_attr_prefix("\x01layer:");
static ustring blender_attribute_name_add_type(const string &name, BlenderAttributeType type)
{
@@ -111,6 +114,8 @@ static ustring blender_attribute_name_add_type(const string &name, BlenderAttrib
return ustring::concat(object_attr_prefix, name);
case BL::ShaderNodeAttribute::attribute_type_INSTANCER:
return ustring::concat(instancer_attr_prefix, name);
+ case BL::ShaderNodeAttribute::attribute_type_VIEW_LAYER:
+ return ustring::concat(view_layer_attr_prefix, name);
default:
return ustring(name);
}
@@ -130,6 +135,11 @@ BlenderAttributeType blender_attribute_name_split_type(ustring name, string *r_r
return BL::ShaderNodeAttribute::attribute_type_INSTANCER;
}
+ if (sname.substr(0, view_layer_attr_prefix.size()) == view_layer_attr_prefix) {
+ *r_real_name = sname.substr(view_layer_attr_prefix.size());
+ return BL::ShaderNodeAttribute::attribute_type_VIEW_LAYER;
+ }
+
return BL::ShaderNodeAttribute::attribute_type_GEOMETRY;
}
@@ -1420,6 +1430,89 @@ static void add_nodes(Scene *scene,
empty_proxy_map);
}
+/* Look up and constant fold all references to View Layer attributes. */
+void BlenderSync::resolve_view_layer_attributes(Shader *shader,
+ ShaderGraph *graph,
+ BL::Depsgraph &b_depsgraph)
+{
+ bool updated = false;
+
+ foreach (ShaderNode *node, graph->nodes) {
+ if (node->is_a(AttributeNode::node_type)) {
+ AttributeNode *attr_node = static_cast<AttributeNode *>(node);
+
+ std::string real_name;
+ BlenderAttributeType type = blender_attribute_name_split_type(attr_node->get_attribute(),
+ &real_name);
+
+ if (type == BL::ShaderNodeAttribute::attribute_type_VIEW_LAYER) {
+ /* Look up the value. */
+ BL::ViewLayer b_layer = b_depsgraph.view_layer_eval();
+ BL::Scene b_scene = b_depsgraph.scene_eval();
+ float4 value;
+
+ BKE_view_layer_find_rgba_attribute((::Scene *)b_scene.ptr.data,
+ (::ViewLayer *)b_layer.ptr.data,
+ real_name.c_str(),
+ &value.x);
+
+ /* Replace all outgoing links, using appropriate output types. */
+ float val_avg = (value.x + value.y + value.z) / 3.0f;
+
+ foreach (ShaderOutput *output, node->outputs) {
+ float val_float;
+ float3 val_float3;
+
+ if (output->type() == SocketType::FLOAT) {
+ val_float = (output->name() == "Alpha") ? value.w : val_avg;
+ val_float3 = make_float3(val_float);
+ }
+ else {
+ val_float = val_avg;
+ val_float3 = float4_to_float3(value);
+ }
+
+ foreach (ShaderInput *sock, output->links) {
+ if (sock->type() == SocketType::FLOAT) {
+ sock->set(val_float);
+ }
+ else if (SocketType::is_float3(sock->type())) {
+ sock->set(val_float3);
+ }
+
+ sock->constant_folded_in = true;
+ }
+
+ graph->disconnect(output);
+ }
+
+ /* Clear the attribute name to avoid further attempts to look up. */
+ attr_node->set_attribute(ustring());
+ updated = true;
+ }
+ }
+ }
+
+ if (updated) {
+ shader_map.set_flag(shader, SHADER_WITH_LAYER_ATTRS);
+ }
+ else {
+ shader_map.clear_flag(shader, SHADER_WITH_LAYER_ATTRS);
+ }
+}
+
+bool BlenderSync::scene_attr_needs_recalc(Shader *shader, BL::Depsgraph &b_depsgraph)
+{
+ if (shader && shader_map.test_flag(shader, SHADER_WITH_LAYER_ATTRS)) {
+ BL::Scene scene = b_depsgraph.scene_eval();
+
+ return shader_map.check_recalc(scene) || shader_map.check_recalc(scene.world()) ||
+ shader_map.check_recalc(scene.camera());
+ }
+
+ return false;
+}
+
/* Sync Materials */
void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
@@ -1438,7 +1531,8 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
Shader *shader;
/* test if we need to sync */
- if (shader_map.add_or_update(&shader, b_mat) || update_all) {
+ if (shader_map.add_or_update(&shader, b_mat) || update_all ||
+ scene_attr_needs_recalc(shader, b_depsgraph)) {
ShaderGraph *graph = new ShaderGraph();
shader->name = b_mat.name().c_str();
@@ -1459,6 +1553,8 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
graph->connect(diffuse->output("BSDF"), out->input("Surface"));
}
+ resolve_view_layer_attributes(shader, graph, b_depsgraph);
+
/* settings */
PointerRNA cmat = RNA_pointer_get(&b_mat.ptr, "cycles");
shader->set_use_mis(get_boolean(cmat, "sample_as_light"));
@@ -1515,9 +1611,11 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
BlenderViewportParameters new_viewport_parameters(b_v3d, use_developer_ui);
+ Shader *shader = scene->default_background;
+
if (world_recalc || update_all || b_world.ptr.data != world_map ||
- viewport_parameters.shader_modified(new_viewport_parameters)) {
- Shader *shader = scene->default_background;
+ viewport_parameters.shader_modified(new_viewport_parameters) ||
+ scene_attr_needs_recalc(shader, b_depsgraph)) {
ShaderGraph *graph = new ShaderGraph();
/* create nodes */
@@ -1615,6 +1713,8 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
background->set_visibility(visibility);
}
+ resolve_view_layer_attributes(shader, graph, b_depsgraph);
+
shader->set_graph(graph);
shader->tag_update(scene);
}
@@ -1681,7 +1781,8 @@ void BlenderSync::sync_lights(BL::Depsgraph &b_depsgraph, bool update_all)
Shader *shader;
/* test if we need to sync */
- if (shader_map.add_or_update(&shader, b_light) || update_all) {
+ if (shader_map.add_or_update(&shader, b_light) || update_all ||
+ scene_attr_needs_recalc(shader, b_depsgraph)) {
ShaderGraph *graph = new ShaderGraph();
/* create nodes */
@@ -1702,6 +1803,8 @@ void BlenderSync::sync_lights(BL::Depsgraph &b_depsgraph, bool update_all)
graph->connect(emission->output("Emission"), out->input("Surface"));
}
+ resolve_view_layer_attributes(shader, graph, b_depsgraph);
+
shader->set_graph(graph);
shader->tag_update(scene);
}
diff --git a/intern/cycles/blender/sync.cpp b/intern/cycles/blender/sync.cpp
index 23bc92de022..a69a94614d3 100644
--- a/intern/cycles/blender/sync.cpp
+++ b/intern/cycles/blender/sync.cpp
@@ -206,6 +206,9 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
}
}
}
+ else if (object_is_camera(b_ob)) {
+ shader_map.set_recalc(b_ob);
+ }
}
/* Mesh */
else if (b_id.is_a(&RNA_Mesh)) {
@@ -218,6 +221,11 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
if (world_map == b_world.ptr.data) {
world_recalc = true;
}
+ shader_map.set_recalc(b_world);
+ }
+ /* World */
+ else if (b_id.is_a(&RNA_Scene)) {
+ shader_map.set_recalc(b_id);
}
/* Volume */
else if (b_id.is_a(&RNA_Volume)) {
diff --git a/intern/cycles/blender/sync.h b/intern/cycles/blender/sync.h
index ae6c2420e55..fbb17bab0c8 100644
--- a/intern/cycles/blender/sync.h
+++ b/intern/cycles/blender/sync.h
@@ -120,6 +120,11 @@ class BlenderSync {
void sync_shaders(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, bool update_all);
void sync_nodes(Shader *shader, BL::ShaderNodeTree &b_ntree);
+ bool scene_attr_needs_recalc(Shader *shader, BL::Depsgraph &b_depsgraph);
+ void resolve_view_layer_attributes(Shader *shader,
+ ShaderGraph *graph,
+ BL::Depsgraph &b_depsgraph);
+
/* Object */
Object *sync_object(BL::Depsgraph &b_depsgraph,
BL::ViewLayer &b_view_layer,
@@ -207,13 +212,16 @@ class BlenderSync {
bool object_is_geometry(BObjectInfo &b_ob_info);
bool object_can_have_geometry(BL::Object &b_ob);
bool object_is_light(BL::Object &b_ob);
+ bool object_is_camera(BL::Object &b_ob);
/* variables */
BL::RenderEngine b_engine;
BL::BlendData b_data;
BL::Scene b_scene;
- id_map<void *, Shader> shader_map;
+ enum ShaderFlags { SHADER_WITH_LAYER_ATTRS };
+
+ id_map<void *, Shader, ShaderFlags> shader_map;
id_map<ObjectKey, Object> object_map;
id_map<void *, Procedural> procedural_map;
id_map<GeometryKey, Geometry> geometry_map;
diff --git a/source/blender/blenkernel/BKE_duplilist.h b/source/blender/blenkernel/BKE_duplilist.h
index 8a37348377a..44c4df1fc2e 100644
--- a/source/blender/blenkernel/BKE_duplilist.h
+++ b/source/blender/blenkernel/BKE_duplilist.h
@@ -16,6 +16,7 @@ struct ListBase;
struct Object;
struct ParticleSystem;
struct Scene;
+struct ViewLayer;
struct ViewerPath;
struct GeometrySet;
@@ -83,6 +84,13 @@ bool BKE_object_dupli_find_rgba_attribute(struct Object *ob,
const char *name,
float r_value[4]);
+/** Look up the RGBA value of a view layer/scene/world shader attribute.
+ * \return true if the attribute was found; if not, r_value is also set to zero. */
+bool BKE_view_layer_find_rgba_attribute(struct Scene *scene,
+ struct ViewLayer *layer,
+ const char *name,
+ float r_value[4]);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc
index a56176b7d9b..306e508dc83 100644
--- a/source/blender/blenkernel/intern/object_dupli.cc
+++ b/source/blender/blenkernel/intern/object_dupli.cc
@@ -57,10 +57,12 @@
#include "DEG_depsgraph_query.h"
#include "BLI_hash.h"
+#include "DNA_world_types.h"
#include "NOD_geometry_nodes_log.hh"
#include "RNA_access.h"
#include "RNA_path.h"
+#include "RNA_prototypes.h"
#include "RNA_types.h"
using blender::Array;
@@ -1916,4 +1918,30 @@ bool BKE_object_dupli_find_rgba_attribute(
return false;
}
+bool BKE_view_layer_find_rgba_attribute(struct Scene *scene,
+ struct ViewLayer *layer,
+ const char *name,
+ float r_value[4])
+{
+ if (layer) {
+ PointerRNA layer_ptr;
+ RNA_pointer_create(&scene->id, &RNA_ViewLayer, layer, &layer_ptr);
+
+ if (find_rna_property_rgba(&layer_ptr, name, r_value)) {
+ return true;
+ }
+ }
+
+ if (find_rna_property_rgba(&scene->id, name, r_value)) {
+ return true;
+ }
+
+ if (scene->world && find_rna_property_rgba(&scene->world->id, name, r_value)) {
+ return true;
+ }
+
+ copy_v4_fl(r_value, 0.0f);
+ return false;
+}
+
/** \} */
diff --git a/source/blender/draw/engines/eevee_next/eevee_instance.cc b/source/blender/draw/engines/eevee_next/eevee_instance.cc
index 8005b27c30e..a0bdf70e254 100644
--- a/source/blender/draw/engines/eevee_next/eevee_instance.cc
+++ b/source/blender/draw/engines/eevee_next/eevee_instance.cc
@@ -106,6 +106,8 @@ void Instance::begin_sync()
gpencil_engine_enabled = false;
+ scene_sync();
+
depth_of_field.sync();
motion_blur.sync();
hiz_buffer.sync();
@@ -115,6 +117,21 @@ void Instance::begin_sync()
film.sync();
}
+void Instance::scene_sync()
+{
+ SceneHandle &sc_handle = sync.sync_scene(scene);
+
+ sc_handle.reset_recalc_flag();
+
+ /* This refers specifically to the Scene camera that can be accessed
+ * via View Layer Attribute nodes, rather than the actual render camera. */
+ if (scene->camera != nullptr) {
+ ObjectHandle &ob_handle = sync.sync_object(scene->camera);
+
+ ob_handle.reset_recalc_flag();
+ }
+}
+
void Instance::object_sync(Object *ob)
{
const bool is_renderable_type = ELEM(ob->type, OB_CURVES, OB_GPENCIL, OB_MESH, OB_LAMP);
diff --git a/source/blender/draw/engines/eevee_next/eevee_instance.hh b/source/blender/draw/engines/eevee_next/eevee_instance.hh
index c8eecbd812d..bc610cd0642 100644
--- a/source/blender/draw/engines/eevee_next/eevee_instance.hh
+++ b/source/blender/draw/engines/eevee_next/eevee_instance.hh
@@ -162,6 +162,7 @@ class Instance {
void render_sample();
void render_read_result(RenderLayer *render_layer, const char *view_name);
+ void scene_sync();
void mesh_sync(Object *ob, ObjectHandle &ob_handle);
void update_eval_members();
diff --git a/source/blender/draw/engines/eevee_next/eevee_material.cc b/source/blender/draw/engines/eevee_next/eevee_material.cc
index b63002df2e3..d190a1f17a3 100644
--- a/source/blender/draw/engines/eevee_next/eevee_material.cc
+++ b/source/blender/draw/engines/eevee_next/eevee_material.cc
@@ -187,6 +187,8 @@ MaterialPass MaterialModule::material_pass_get(Object *ob,
/* Returned material should be ready to be drawn. */
BLI_assert(GPU_material_status(matpass.gpumat) == GPU_MAT_SUCCESS);
+ inst_.manager->register_layer_attributes(matpass.gpumat);
+
if (GPU_material_recalc_flag_get(matpass.gpumat)) {
inst_.sampling.reset();
}
@@ -217,6 +219,9 @@ MaterialPass MaterialModule::material_pass_get(Object *ob,
matpass.sub_pass = &shader_sub->sub(GPU_material_get_name(matpass.gpumat));
matpass.sub_pass->material_set(*inst_.manager, matpass.gpumat);
}
+ else {
+ matpass.sub_pass = nullptr;
+ }
}
return matpass;
diff --git a/source/blender/draw/engines/eevee_next/eevee_sync.cc b/source/blender/draw/engines/eevee_next/eevee_sync.cc
index f2daba48d7a..08cda6f47cf 100644
--- a/source/blender/draw/engines/eevee_next/eevee_sync.cc
+++ b/source/blender/draw/engines/eevee_next/eevee_sync.cc
@@ -68,6 +68,20 @@ WorldHandle &SyncModule::sync_world(::World *world)
return eevee_dd;
}
+SceneHandle &SyncModule::sync_scene(::Scene *scene)
+{
+ DrawEngineType *owner = (DrawEngineType *)&DRW_engine_viewport_eevee_next_type;
+ struct DrawData *dd = DRW_drawdata_ensure(
+ (ID *)scene, owner, sizeof(eevee::SceneHandle), draw_data_init_cb, nullptr);
+ SceneHandle &eevee_dd = *reinterpret_cast<SceneHandle *>(dd);
+
+ const int recalc_flags = ID_RECALC_ALL;
+ if ((eevee_dd.recalc & recalc_flags) != 0) {
+ inst_.sampling.reset();
+ }
+ return eevee_dd;
+}
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/draw/engines/eevee_next/eevee_sync.hh b/source/blender/draw/engines/eevee_next/eevee_sync.hh
index ab883ce44c2..eda0342c4b6 100644
--- a/source/blender/draw/engines/eevee_next/eevee_sync.hh
+++ b/source/blender/draw/engines/eevee_next/eevee_sync.hh
@@ -139,6 +139,15 @@ struct WorldHandle : public DrawData {
}
};
+struct SceneHandle : public DrawData {
+ void reset_recalc_flag()
+ {
+ if (recalc != 0) {
+ recalc = 0;
+ }
+ }
+};
+
class SyncModule {
private:
Instance &inst_;
@@ -149,6 +158,7 @@ class SyncModule {
ObjectHandle &sync_object(Object *ob);
WorldHandle &sync_world(::World *world);
+ SceneHandle &sync_scene(::Scene *scene);
void sync_mesh(Object *ob,
ObjectHandle &ob_handle,
diff --git a/source/blender/draw/engines/eevee_next/eevee_world.cc b/source/blender/draw/engines/eevee_next/eevee_world.cc
index 313c0bda42e..37f90570028 100644
--- a/source/blender/draw/engines/eevee_next/eevee_world.cc
+++ b/source/blender/draw/engines/eevee_next/eevee_world.cc
@@ -87,6 +87,9 @@ void World::sync()
default_tree.nodetree_get(bl_world);
GPUMaterial *gpumat = inst_.shaders.world_shader_get(bl_world, ntree);
+
+ inst_.manager->register_layer_attributes(gpumat);
+
inst_.pipelines.world.sync(gpumat);
}
diff --git a/source/blender/draw/intern/draw_defines.h b/source/blender/draw/intern/draw_defines.h
index f5976ddd34e..57035717bd7 100644
--- a/source/blender/draw/intern/draw_defines.h
+++ b/source/blender/draw/intern/draw_defines.h
@@ -15,6 +15,8 @@
#define DRW_VIEW_CULLING_UBO_SLOT 1
#define DRW_CLIPPING_UBO_SLOT 2
+#define DRW_LAYER_ATTR_UBO_SLOT 3
+
#define DRW_RESOURCE_ID_SLOT 11
#define DRW_OBJ_MAT_SLOT 10
#define DRW_OBJ_INFOS_SLOT 9
diff --git a/source/blender/draw/intern/draw_instance_data.c b/source/blender/draw/intern/draw_instance_data.c
index a56883ce304..b44c1364af9 100644
--- a/source/blender/draw/intern/draw_instance_data.c
+++ b/source/blender/draw/intern/draw_instance_data.c
@@ -622,6 +622,62 @@ void drw_uniform_attrs_pool_update(GHash *table,
}
}
+GPUUniformBuf *drw_ensure_layer_attribute_buffer()
+{
+ DRWData *data = DST.vmempool;
+
+ if (data->vlattrs_ubo_ready && data->vlattrs_ubo != NULL) {
+ return data->vlattrs_ubo;
+ }
+
+ /* Allocate the buffer data. */
+ const int buf_size = DRW_RESOURCE_CHUNK_LEN;
+
+ if (data->vlattrs_buf == NULL) {
+ data->vlattrs_buf = MEM_calloc_arrayN(
+ buf_size, sizeof(LayerAttribute), "View Layer Attr Data");
+ }
+
+ /* Look up attributes.
+ *
+ * Mirrors code in draw_resource.cc and cycles/blender/shader.cpp.
+ */
+ LayerAttribute *buffer = data->vlattrs_buf;
+ int count = 0;
+
+ LISTBASE_FOREACH (GPULayerAttr *, attr, &data->vlattrs_name_list) {
+ float value[4];
+
+ if (BKE_view_layer_find_rgba_attribute(
+ DST.draw_ctx.scene, DST.draw_ctx.view_layer, attr->name, value)) {
+ LayerAttribute *item = &buffer[count++];
+
+ memcpy(item->data, value, sizeof(item->data));
+ item->hash_code = attr->hash_code;
+
+ /* Check if the buffer is full just in case. */
+ if (count >= buf_size) {
+ break;
+ }
+ }
+ }
+
+ buffer[0].buffer_length = count;
+
+ /* Update or create the UBO object. */
+ if (data->vlattrs_ubo != NULL) {
+ GPU_uniformbuf_update(data->vlattrs_ubo, buffer);
+ }
+ else {
+ data->vlattrs_ubo = GPU_uniformbuf_create_ex(
+ sizeof(*buffer) * buf_size, buffer, "View Layer Attributes");
+ }
+
+ data->vlattrs_ubo_ready = true;
+
+ return data->vlattrs_ubo;
+}
+
DRWSparseUniformBuf *DRW_uniform_attrs_pool_find_ubo(GHash *table,
const struct GPUUniformAttrList *key)
{
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 6dfd434d5c7..28abbc6ab71 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -378,6 +378,8 @@ DRWData *DRW_viewport_data_create(void)
drw_data->views = BLI_memblock_create(sizeof(DRWView));
drw_data->images = BLI_memblock_create(sizeof(GPUTexture *));
drw_data->obattrs_ubo_pool = DRW_uniform_attrs_pool_new();
+ drw_data->vlattrs_name_cache = BLI_ghash_new(
+ BLI_ghashutil_inthash_p_simple, BLI_ghashutil_intcmp, "View Layer Attribute names");
{
uint chunk_len = sizeof(DRWObjectMatrix) * DRW_RESOURCE_CHUNK_LEN;
drw_data->obmats = BLI_memblock_create_ex(sizeof(DRWObjectMatrix), chunk_len);
@@ -413,9 +415,23 @@ static void draw_texture_release(DRWData *drw_data)
}
}
+static void draw_prune_vlattrs(DRWData *drw_data)
+{
+ drw_data->vlattrs_ubo_ready = false;
+
+ /* Forget known attributes after they are unused for a few frames. */
+ LISTBASE_FOREACH_MUTABLE (GPULayerAttr *, attr, &drw_data->vlattrs_name_list) {
+ if (++attr->users > 10) {
+ BLI_ghash_remove(drw_data->vlattrs_name_cache, (void *)attr->hash_code, NULL, NULL);
+ BLI_freelinkN(&drw_data->vlattrs_name_list, attr);
+ }
+ }
+}
+
static void drw_viewport_data_reset(DRWData *drw_data)
{
draw_texture_release(drw_data);
+ draw_prune_vlattrs(drw_data);
BLI_memblock_clear(drw_data->commands, NULL);
BLI_memblock_clear(drw_data->commands_small, NULL);
@@ -451,6 +467,12 @@ void DRW_viewport_data_free(DRWData *drw_data)
BLI_memblock_destroy(drw_data->passes, NULL);
BLI_memblock_destroy(drw_data->images, NULL);
DRW_uniform_attrs_pool_free(drw_data->obattrs_ubo_pool);
+ BLI_ghash_free(drw_data->vlattrs_name_cache, NULL, NULL);
+ BLI_freelistN(&drw_data->vlattrs_name_list);
+ if (drw_data->vlattrs_ubo) {
+ GPU_uniformbuf_free(drw_data->vlattrs_ubo);
+ MEM_freeN(drw_data->vlattrs_buf);
+ }
DRW_instance_data_list_free(drw_data->idatalist);
DRW_texture_pool_free(drw_data->texture_pool);
for (int i = 0; i < 2; i++) {
@@ -811,6 +833,7 @@ static bool id_type_can_have_drawdata(const short id_type)
/* has DrawData */
case ID_OB:
case ID_WO:
+ case ID_SCE:
return true;
/* no DrawData */
diff --git a/source/blender/draw/intern/draw_manager.cc b/source/blender/draw/intern/draw_manager.cc
index 169d86b2ea1..c644cadd18c 100644
--- a/source/blender/draw/intern/draw_manager.cc
+++ b/source/blender/draw/intern/draw_manager.cc
@@ -35,6 +35,7 @@ void Manager::begin_sync()
}
acquired_textures.clear();
+ layer_attributes.clear();
#ifdef DEBUG
/* Detect uninitialized data. */
@@ -52,14 +53,46 @@ void Manager::begin_sync()
resource_handle(float4x4::identity());
}
+void Manager::sync_layer_attributes()
+{
+ /* Sort the attribute IDs - the shaders use binary search. */
+ Vector<uint32_t> id_list;
+
+ id_list.reserve(layer_attributes.size());
+
+ for (uint32_t id : layer_attributes.keys()) {
+ id_list.append(id);
+ }
+
+ std::sort(id_list.begin(), id_list.end());
+
+ /* Look up the attributes. */
+ int count = 0, size = layer_attributes_buf.end() - layer_attributes_buf.begin();
+
+ for (uint32_t id : id_list) {
+ if (layer_attributes_buf[count].sync(
+ DST.draw_ctx.scene, DST.draw_ctx.view_layer, layer_attributes.lookup(id))) {
+ /* Check if the buffer is full. */
+ if (++count == size) {
+ break;
+ }
+ }
+ }
+
+ layer_attributes_buf[0].buffer_length = count;
+}
+
void Manager::end_sync()
{
GPU_debug_group_begin("Manager.end_sync");
+ sync_layer_attributes();
+
matrix_buf.push_update();
bounds_buf.push_update();
infos_buf.push_update();
attributes_buf.push_update();
+ layer_attributes_buf.push_update();
attributes_buf_legacy.push_update();
/* Useful for debugging the following resource finalize. But will trigger the drawing of the GPU
@@ -100,6 +133,7 @@ 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);
+ GPU_uniformbuf_bind(layer_attributes_buf, DRW_LAYER_ATTR_UBO_SLOT);
/* 2 is the hardcoded location of the uniform attr UBO. */
/* TODO(@fclem): Remove this workaround. */
GPU_uniformbuf_bind(attributes_buf_legacy, 2);
diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h
index 6b5a2cc4f6f..ce316a31cf9 100644
--- a/source/blender/draw/intern/draw_manager.h
+++ b/source/blender/draw/intern/draw_manager.h
@@ -335,6 +335,7 @@ typedef enum {
DRW_UNIFORM_BLOCK_OBMATS,
DRW_UNIFORM_BLOCK_OBINFOS,
DRW_UNIFORM_BLOCK_OBATTRS,
+ DRW_UNIFORM_BLOCK_VLATTRS,
DRW_UNIFORM_RESOURCE_CHUNK,
DRW_UNIFORM_RESOURCE_ID,
/** Legacy / Fallback */
@@ -527,6 +528,11 @@ typedef struct DRWData {
struct GPUUniformBuf **matrices_ubo;
struct GPUUniformBuf **obinfos_ubo;
struct GHash *obattrs_ubo_pool;
+ struct GHash *vlattrs_name_cache;
+ struct ListBase vlattrs_name_list;
+ struct LayerAttribute *vlattrs_buf;
+ struct GPUUniformBuf *vlattrs_ubo;
+ bool vlattrs_ubo_ready;
uint ubo_len;
/** Per draw-call volume object data. */
void *volume_grids_ubos; /* VolumeUniformBufPool */
@@ -691,6 +697,8 @@ void drw_uniform_attrs_pool_update(struct GHash *table,
struct Object *dupli_parent,
struct DupliObject *dupli_source);
+GPUUniformBuf *drw_ensure_layer_attribute_buffer();
+
double *drw_engine_data_cache_time_get(GPUViewport *viewport);
void *drw_engine_data_engine_data_create(GPUViewport *viewport, void *engine_type);
void *drw_engine_data_engine_data_get(GPUViewport *viewport, void *engine_handle);
diff --git a/source/blender/draw/intern/draw_manager.hh b/source/blender/draw/intern/draw_manager.hh
index fbd3d28d3f4..0a865179cee 100644
--- a/source/blender/draw/intern/draw_manager.hh
+++ b/source/blender/draw/intern/draw_manager.hh
@@ -44,6 +44,7 @@ class Manager {
using ObjectBoundsBuf = StorageArrayBuffer<ObjectBounds, 128>;
using ObjectInfosBuf = StorageArrayBuffer<ObjectInfos, 128>;
using ObjectAttributeBuf = StorageArrayBuffer<ObjectAttribute, 128>;
+ using LayerAttributeBuf = UniformArrayBuffer<LayerAttribute, 512>;
/**
* TODO(@fclem): Remove once we get rid of old EEVEE code-base.
* `DRW_RESOURCE_CHUNK_LEN = 512`.
@@ -87,6 +88,16 @@ class Manager {
ObjectAttributeLegacyBuf attributes_buf_legacy;
/**
+ * Table of all View Layer attributes required by shaders, used to populate the buffer below.
+ */
+ Map<uint32_t, GPULayerAttr> layer_attributes;
+
+ /**
+ * Buffer of layer attribute values, indexed and sorted by the hash.
+ */
+ LayerAttributeBuf layer_attributes_buf;
+
+ /**
* List of textures coming from Image data-blocks.
* They need to be reference-counted in order to avoid being freed in another thread.
*/
@@ -131,6 +142,11 @@ class Manager {
Span<GPUMaterial *> materials);
/**
+ * Collect necessary View Layer attributes.
+ */
+ void register_layer_attributes(GPUMaterial *material);
+
+ /**
* Submit a pass for drawing. All resource reference will be dereferenced and commands will be
* sent to GPU.
*/
@@ -169,6 +185,9 @@ class Manager {
void debug_bind();
void resource_bind();
+
+ private:
+ void sync_layer_attributes();
};
inline ResourceHandle Manager::resource_handle(const ObjectRef ref)
@@ -229,6 +248,19 @@ inline void Manager::extract_object_attributes(ResourceHandle handle,
}
}
+inline void Manager::register_layer_attributes(GPUMaterial *material)
+{
+ const ListBase *attr_list = GPU_material_layer_attributes(material);
+
+ if (attr_list != nullptr) {
+ LISTBASE_FOREACH (const GPULayerAttr *, attr, attr_list) {
+ /** Since layer attributes are global to the whole render pass,
+ * this only collects a table of their names. */
+ layer_attributes.add(attr->hash_code, *attr);
+ }
+ }
+}
+
} // namespace blender::draw
/* TODO(@fclem): This is for testing. The manager should be passed to the engine through the
diff --git a/source/blender/draw/intern/draw_manager_data.cc b/source/blender/draw/intern/draw_manager_data.cc
index 06677344132..030b13177f1 100644
--- a/source/blender/draw/intern/draw_manager_data.cc
+++ b/source/blender/draw/intern/draw_manager_data.cc
@@ -1840,6 +1840,13 @@ void DRW_shgroup_add_material_resources(DRWShadingGroup *grp, GPUMaterial *mater
grp, loc, DRW_UNIFORM_BLOCK_OBATTRS, uattrs, GPU_SAMPLER_DEFAULT, 0, 1);
grp->uniform_attrs = uattrs;
}
+
+ if (GPU_material_layer_attributes(material) != NULL) {
+ int loc = GPU_shader_get_uniform_block_binding(grp->shader,
+ GPU_LAYER_ATTRIBUTE_UBO_BLOCK_NAME);
+ drw_shgroup_uniform_create_ex(
+ grp, loc, DRW_UNIFORM_BLOCK_VLATTRS, nullptr, GPU_SAMPLER_DEFAULT, 0, 1);
+ }
}
GPUVertFormat *DRW_shgroup_instance_format_array(const DRWInstanceAttrFormat attrs[],
diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c
index 3627b0fbf10..8b1b35b5f03 100644
--- a/source/blender/draw/intern/draw_manager_exec.c
+++ b/source/blender/draw/intern/draw_manager_exec.c
@@ -44,6 +44,7 @@ typedef struct DRWCommandsState {
int obmats_loc;
int obinfos_loc;
int obattrs_loc;
+ int vlattrs_loc;
int baseinst_loc;
int chunkid_loc;
int resourceid_loc;
@@ -682,6 +683,10 @@ static void draw_update_uniforms(DRWShadingGroup *shgroup,
uni->uniform_attrs);
DRW_sparse_uniform_buffer_bind(state->obattrs_ubo, 0, uni->location);
break;
+ case DRW_UNIFORM_BLOCK_VLATTRS:
+ state->vlattrs_loc = uni->location;
+ GPU_uniformbuf_bind(drw_ensure_layer_attribute_buffer(), uni->location);
+ break;
case DRW_UNIFORM_RESOURCE_CHUNK:
state->chunkid_loc = uni->location;
GPU_shader_uniform_int(shgroup->shader, uni->location, 0);
@@ -960,6 +965,9 @@ static void draw_call_batching_finish(DRWShadingGroup *shgroup, DRWCommandsState
if (state->obattrs_loc != -1) {
DRW_sparse_uniform_buffer_unbind(state->obattrs_ubo, state->resource_chunk);
}
+ if (state->vlattrs_loc != -1) {
+ GPU_uniformbuf_unbind(DST.vmempool->vlattrs_ubo);
+ }
}
static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
@@ -970,6 +978,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
.obmats_loc = -1,
.obinfos_loc = -1,
.obattrs_loc = -1,
+ .vlattrs_loc = -1,
.baseinst_loc = -1,
.chunkid_loc = -1,
.resourceid_loc = -1,
diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c
index 04a9f3fdd2d..8b287e116bc 100644
--- a/source/blender/draw/intern/draw_manager_shader.c
+++ b/source/blender/draw/intern/draw_manager_shader.c
@@ -237,6 +237,42 @@ static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred)
WM_jobs_start(wm, wm_job);
}
+static void drw_register_shader_vlattrs(GPUMaterial *mat)
+{
+ const ListBase *attrs = GPU_material_layer_attributes(mat);
+
+ if (!attrs) {
+ return;
+ }
+
+ GHash *hash = DST.vmempool->vlattrs_name_cache;
+ ListBase *list = &DST.vmempool->vlattrs_name_list;
+
+ LISTBASE_FOREACH (GPULayerAttr *, attr, attrs) {
+ GPULayerAttr **p_val;
+
+ /* Add to the table and list if newly seen. */
+ if (!BLI_ghash_ensure_p(hash, (void *)attr->hash_code, (void ***)&p_val)) {
+ DST.vmempool->vlattrs_ubo_ready = false;
+
+ GPULayerAttr *new_link = *p_val = MEM_dupallocN(attr);
+
+ /* Insert into the list ensuring sorted order. */
+ GPULayerAttr *link = list->first;
+
+ while (link && link->hash_code <= attr->hash_code) {
+ link = link->next;
+ }
+
+ new_link->prev = new_link->next = NULL;
+ BLI_insertlinkbefore(list, link, new_link);
+ }
+
+ /* Reset the unused frames counter. */
+ (*p_val)->users = 0;
+ }
+}
+
void DRW_deferred_shader_remove(GPUMaterial *mat)
{
LISTBASE_FOREACH (wmWindowManager *, wm, &G_MAIN->wm) {
@@ -382,6 +418,9 @@ GPUMaterial *DRW_shader_from_world(World *wo,
false,
callback,
thunk);
+
+ drw_register_shader_vlattrs(mat);
+
if (DRW_state_is_image_render()) {
/* Do not deferred if doing render. */
deferred = false;
@@ -411,6 +450,8 @@ GPUMaterial *DRW_shader_from_material(Material *ma,
callback,
thunk);
+ drw_register_shader_vlattrs(mat);
+
if (DRW_state_is_image_render()) {
/* Do not deferred if doing render. */
deferred = false;
diff --git a/source/blender/draw/intern/draw_resource.cc b/source/blender/draw/intern/draw_resource.cc
index f57058190fb..c1f83c3a5ae 100644
--- a/source/blender/draw/intern/draw_resource.cc
+++ b/source/blender/draw/intern/draw_resource.cc
@@ -38,3 +38,16 @@ bool ObjectAttribute::sync(const blender::draw::ObjectRef &ref, const GPUUniform
}
/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name LayerAttributes
+ * \{ */
+
+bool LayerAttribute::sync(Scene *scene, ViewLayer *layer, const GPULayerAttr &attr)
+{
+ hash_code = attr.hash_code;
+
+ return BKE_view_layer_find_rgba_attribute(scene, layer, attr.name, &data.x);
+}
+
+/** \} */
diff --git a/source/blender/draw/intern/draw_shader_shared.h b/source/blender/draw/intern/draw_shader_shared.h
index 37899e36d8a..75a7e28fa75 100644
--- a/source/blender/draw/intern/draw_shader_shared.h
+++ b/source/blender/draw/intern/draw_shader_shared.h
@@ -15,6 +15,7 @@ typedef struct ObjectBounds ObjectBounds;
typedef struct VolumeInfos VolumeInfos;
typedef struct CurvesInfos CurvesInfos;
typedef struct ObjectAttribute ObjectAttribute;
+typedef struct LayerAttribute LayerAttribute;
typedef struct DrawCommand DrawCommand;
typedef struct DispatchCommand DispatchCommand;
typedef struct DRWDebugPrintBuffer DRWDebugPrintBuffer;
@@ -24,8 +25,10 @@ typedef struct DRWDebugDrawBuffer DRWDebugDrawBuffer;
# ifdef __cplusplus
/* C++ only forward declarations. */
struct Object;
+struct ViewLayer;
struct ID;
struct GPUUniformAttr;
+struct GPULayerAttr;
namespace blender::draw {
@@ -192,6 +195,20 @@ struct ObjectAttribute {
* C++ compiler gives us the same size. */
BLI_STATIC_ASSERT_ALIGN(ObjectAttribute, 20)
+#pragma pack(push, 4)
+struct LayerAttribute {
+ float4 data;
+ uint hash_code;
+ uint buffer_length; /* Only in the first record. */
+ uint _pad1, _pad2;
+
+#if !defined(GPU_SHADER) && defined(__cplusplus)
+ bool sync(Scene *scene, ViewLayer *layer, const GPULayerAttr &attr);
+#endif
+};
+#pragma pack(pop)
+BLI_STATIC_ASSERT_ALIGN(LayerAttribute, 32)
+
/** \} */
/* -------------------------------------------------------------------- */
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 ad0426e6d3f..33634fb5fcb 100644
--- a/source/blender/draw/intern/shaders/draw_object_infos_info.hh
+++ b/source/blender/draw/intern/shaders/draw_object_infos_info.hh
@@ -19,6 +19,14 @@ GPU_SHADER_CREATE_INFO(draw_curves_infos)
.typedef_source("draw_shader_shared.h")
.uniform_buf(3, "CurvesInfos", "drw_curves", Frequency::BATCH);
+GPU_SHADER_CREATE_INFO(draw_layer_attributes)
+ .typedef_source("draw_shader_shared.h")
+ .define("VLATTR_LIB")
+ .uniform_buf(DRW_LAYER_ATTR_UBO_SLOT,
+ "LayerAttribute",
+ "drw_layer_attrs[DRW_RESOURCE_CHUNK_LEN]",
+ Frequency::BATCH);
+
GPU_SHADER_CREATE_INFO(draw_object_infos_new)
.typedef_source("draw_shader_shared.h")
.define("OBINFO_LIB")
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 31354585308..3dad2a1a19a 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -162,6 +162,7 @@ GPUNodeLink *GPU_uniform_attribute(GPUMaterial *mat,
const char *name,
bool use_dupli,
uint32_t *r_hash);
+GPUNodeLink *GPU_layer_attribute(GPUMaterial *mat, const char *name);
GPUNodeLink *GPU_image(GPUMaterial *mat,
struct Image *ima,
struct ImageUser *iuser,
@@ -357,6 +358,20 @@ struct GHash *GPU_uniform_attr_list_hash_new(const char *info);
void GPU_uniform_attr_list_copy(GPUUniformAttrList *dest, const GPUUniformAttrList *src);
void GPU_uniform_attr_list_free(GPUUniformAttrList *set);
+typedef struct GPULayerAttr {
+ struct GPULayerAttr *next, *prev;
+
+ /* Meaningful part of the attribute set key. */
+ char name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
+ /** Hash of name[64]. */
+ uint32_t hash_code;
+
+ /* Helper fields used by code generation. */
+ int users;
+} GPULayerAttr;
+
+const ListBase *GPU_material_layer_attributes(const GPUMaterial *material);
+
/* A callback passed to GPU_material_from_callbacks to construct the material graph by adding and
* linking the necessary GPU material nodes. */
typedef void (*ConstructGPUMaterialFn)(void *thunk, GPUMaterial *material);
diff --git a/source/blender/gpu/GPU_uniform_buffer.h b/source/blender/gpu/GPU_uniform_buffer.h
index f78719d1963..28f06d6071d 100644
--- a/source/blender/gpu/GPU_uniform_buffer.h
+++ b/source/blender/gpu/GPU_uniform_buffer.h
@@ -44,6 +44,7 @@ void GPU_uniformbuf_unbind_all(void);
#define GPU_UBO_BLOCK_NAME "node_tree"
#define GPU_ATTRIBUTE_UBO_BLOCK_NAME "unf_attrs"
+#define GPU_LAYER_ATTRIBUTE_UBO_BLOCK_NAME "drw_layer_attrs"
#ifdef __cplusplus
}
diff --git a/source/blender/gpu/intern/gpu_codegen.cc b/source/blender/gpu/intern/gpu_codegen.cc
index b02d8a02704..4adeac1b49a 100644
--- a/source/blender/gpu/intern/gpu_codegen.cc
+++ b/source/blender/gpu/intern/gpu_codegen.cc
@@ -183,6 +183,8 @@ static std::ostream &operator<<(std::ostream &stream, const GPUInput *input)
return stream << "var_attrs.v" << input->attr->id;
case GPU_SOURCE_UNIFORM_ATTR:
return stream << "unf_attrs[resource_id].attr" << input->uniform_attr->id;
+ case GPU_SOURCE_LAYER_ATTR:
+ return stream << "attr_load_layer(" << input->layer_attr->hash_code << ")";
case GPU_SOURCE_STRUCT:
return stream << "strct" << input->id;
case GPU_SOURCE_TEX:
@@ -432,6 +434,10 @@ void GPUCodegen::generate_resources()
info.uniform_buf(2, "UniformAttrs", GPU_ATTRIBUTE_UBO_BLOCK_NAME "[512]", Frequency::BATCH);
}
+ if (!BLI_listbase_is_empty(&graph.layer_attrs)) {
+ info.additional_info("draw_layer_attributes");
+ }
+
info.typedef_source_generated = ss.str();
}
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 0f9dc8be9c5..ca2a9f5cf28 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -291,6 +291,12 @@ const GPUUniformAttrList *GPU_material_uniform_attributes(const GPUMaterial *mat
return attrs->count > 0 ? attrs : NULL;
}
+const ListBase *GPU_material_layer_attributes(const GPUMaterial *material)
+{
+ const ListBase *attrs = &material->graph.layer_attrs;
+ return !BLI_listbase_is_empty(attrs) ? attrs : NULL;
+}
+
#if 1 /* End of life code. */
/* Eevee Subsurface scattering. */
/* Based on Separable SSS. by Jorge Jimenez and Diego Gutierrez */
diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c
index e1ae731d49c..c72e7097b33 100644
--- a/source/blender/gpu/intern/gpu_node_graph.c
+++ b/source/blender/gpu/intern/gpu_node_graph.c
@@ -83,6 +83,9 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType
case GPU_SOURCE_UNIFORM_ATTR:
input->uniform_attr->users++;
break;
+ case GPU_SOURCE_LAYER_ATTR:
+ input->layer_attr->users++;
+ break;
case GPU_SOURCE_TEX:
case GPU_SOURCE_TEX_TILED_MAPPING:
input->texture->users++;
@@ -133,6 +136,10 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType
input->source = GPU_SOURCE_UNIFORM_ATTR;
input->uniform_attr = link->uniform_attr;
break;
+ case GPU_NODE_LINK_LAYER_ATTR:
+ input->source = GPU_SOURCE_LAYER_ATTR;
+ input->layer_attr = link->layer_attr;
+ break;
case GPU_NODE_LINK_CONSTANT:
input->source = (type == GPU_CLOSURE) ? GPU_SOURCE_STRUCT : GPU_SOURCE_CONSTANT;
break;
@@ -430,6 +437,34 @@ static GPUUniformAttr *gpu_node_graph_add_uniform_attribute(GPUNodeGraph *graph,
return attr;
}
+/** Add a new uniform attribute of given type and name. Returns NULL if out of slots. */
+static GPULayerAttr *gpu_node_graph_add_layer_attribute(GPUNodeGraph *graph, const char *name)
+{
+ /* Find existing attribute. */
+ ListBase *attrs = &graph->layer_attrs;
+ GPULayerAttr *attr = attrs->first;
+
+ for (; attr; attr = attr->next) {
+ if (STREQ(attr->name, name)) {
+ break;
+ }
+ }
+
+ /* Add new requested attribute to the list. */
+ if (attr == NULL) {
+ attr = MEM_callocN(sizeof(*attr), __func__);
+ STRNCPY(attr->name, name);
+ attr->hash_code = BLI_ghashutil_strhash_p(attr->name);
+ BLI_addtail(attrs, attr);
+ }
+
+ if (attr != NULL) {
+ attr->users++;
+ }
+
+ return attr;
+}
+
static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph,
Image *ima,
ImageUser *iuser,
@@ -546,6 +581,17 @@ GPUNodeLink *GPU_uniform_attribute(GPUMaterial *mat,
return link;
}
+GPUNodeLink *GPU_layer_attribute(GPUMaterial *mat, const char *name)
+{
+ GPUNodeGraph *graph = gpu_material_node_graph(mat);
+ GPULayerAttr *attr = gpu_node_graph_add_layer_attribute(graph, name);
+
+ GPUNodeLink *link = gpu_node_link_create();
+ link->link_type = GPU_NODE_LINK_LAYER_ATTR;
+ link->layer_attr = attr;
+ return link;
+}
+
GPUNodeLink *GPU_constant(const float *num)
{
GPUNodeLink *link = gpu_node_link_create();
@@ -767,14 +813,22 @@ static void gpu_inputs_free(ListBase *inputs)
GPUInput *input;
for (input = inputs->first; input; input = input->next) {
- if (input->source == GPU_SOURCE_ATTR) {
- input->attr->users--;
- }
- else if (input->source == GPU_SOURCE_UNIFORM_ATTR) {
- input->uniform_attr->users--;
- }
- else if (ELEM(input->source, GPU_SOURCE_TEX, GPU_SOURCE_TEX_TILED_MAPPING)) {
- input->texture->users--;
+ switch (input->source) {
+ case GPU_SOURCE_ATTR:
+ input->attr->users--;
+ break;
+ case GPU_SOURCE_UNIFORM_ATTR:
+ input->uniform_attr->users--;
+ break;
+ case GPU_SOURCE_LAYER_ATTR:
+ input->layer_attr->users--;
+ break;
+ case GPU_SOURCE_TEX:
+ case GPU_SOURCE_TEX_TILED_MAPPING:
+ input->texture->users--;
+ break;
+ default:
+ break;
}
if (input->link) {
@@ -826,6 +880,7 @@ void gpu_node_graph_free(GPUNodeGraph *graph)
BLI_freelistN(&graph->textures);
BLI_freelistN(&graph->attributes);
GPU_uniform_attr_list_free(&graph->uniform_attrs);
+ BLI_freelistN(&graph->layer_attrs);
if (graph->used_libraries) {
BLI_gset_free(graph->used_libraries, NULL);
@@ -908,4 +963,10 @@ void gpu_node_graph_prune_unused(GPUNodeGraph *graph)
uattrs->count--;
}
}
+
+ LISTBASE_FOREACH_MUTABLE (GPULayerAttr *, attr, &graph->layer_attrs) {
+ if (attr->users == 0) {
+ BLI_freelinkN(&graph->layer_attrs, attr);
+ }
+ }
}
diff --git a/source/blender/gpu/intern/gpu_node_graph.h b/source/blender/gpu/intern/gpu_node_graph.h
index 7db22151f86..de0a0687b13 100644
--- a/source/blender/gpu/intern/gpu_node_graph.h
+++ b/source/blender/gpu/intern/gpu_node_graph.h
@@ -31,6 +31,7 @@ typedef enum eGPUDataSource {
GPU_SOURCE_UNIFORM,
GPU_SOURCE_ATTR,
GPU_SOURCE_UNIFORM_ATTR,
+ GPU_SOURCE_LAYER_ATTR,
GPU_SOURCE_STRUCT,
GPU_SOURCE_TEX,
GPU_SOURCE_TEX_TILED_MAPPING,
@@ -42,6 +43,7 @@ typedef enum {
GPU_NODE_LINK_NONE = 0,
GPU_NODE_LINK_ATTR,
GPU_NODE_LINK_UNIFORM_ATTR,
+ GPU_NODE_LINK_LAYER_ATTR,
GPU_NODE_LINK_COLORBAND,
GPU_NODE_LINK_CONSTANT,
GPU_NODE_LINK_IMAGE,
@@ -95,6 +97,8 @@ struct GPUNodeLink {
struct GPUMaterialAttribute *attr;
/* GPU_NODE_LINK_UNIFORM_ATTR */
struct GPUUniformAttr *uniform_attr;
+ /* GPU_NODE_LINK_LAYER_ATTR */
+ struct GPULayerAttr *layer_attr;
/* GPU_NODE_LINK_IMAGE_BLENDER */
struct GPUMaterialTexture *texture;
/* GPU_NODE_LINK_DIFFERENTIATE_FLOAT_FN */
@@ -131,6 +135,8 @@ typedef struct GPUInput {
struct GPUMaterialAttribute *attr;
/* GPU_SOURCE_UNIFORM_ATTR */
struct GPUUniformAttr *uniform_attr;
+ /* GPU_SOURCE_LAYER_ATTR */
+ struct GPULayerAttr *layer_attr;
/* GPU_SOURCE_FUNCTION_CALL */
char function_call[64];
};
@@ -171,6 +177,9 @@ typedef struct GPUNodeGraph {
/* The list of uniform attributes. */
GPUUniformAttrList uniform_attrs;
+ /* The list of layer attributes. */
+ ListBase layer_attrs;
+
/** Set of all the GLSL lib code blocks . */
GSet *used_libraries;
} GPUNodeGraph;
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 bacf089deb1..8d0016a2206 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_attribute.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_attribute.glsl
@@ -29,6 +29,31 @@ void node_attribute_uniform(vec4 attr, const float attr_hash, out vec4 out_attr)
out_attr = attr_load_uniform(attr, floatBitsToUint(attr_hash));
}
+vec4 attr_load_layer(const uint attr_hash)
+{
+#ifdef VLATTR_LIB
+ /* The first record of the buffer stores the length. */
+ uint left = 0, right = drw_layer_attrs[0].buffer_length;
+
+ while (left < right) {
+ uint mid = (left + right) / 2;
+ uint hash = drw_layer_attrs[mid].hash_code;
+
+ if (hash < attr_hash) {
+ left = mid + 1;
+ }
+ else if (hash > attr_hash) {
+ right = mid;
+ }
+ else {
+ return drw_layer_attrs[mid].data;
+ }
+ }
+#endif
+
+ return vec4(0.0);
+}
+
void node_attribute(
vec4 attr, out vec4 outcol, out vec3 outvec, out float outf, out float outalpha)
{
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 963567133d9..4715543ebaf 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -1686,6 +1686,7 @@ enum {
SHD_ATTRIBUTE_GEOMETRY = 0,
SHD_ATTRIBUTE_OBJECT = 1,
SHD_ATTRIBUTE_INSTANCER = 2,
+ SHD_ATTRIBUTE_VIEW_LAYER = 3,
};
/* toon modes */
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 2db81693f51..5fa5d4c7787 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -1761,6 +1761,8 @@ typedef struct Scene {
ID id;
/** Animation data (must be immediately after id for utilities to use it). */
struct AnimData *adt;
+ /* runtime (must be immediately after id for utilities to use it). */
+ DrawDataList drawdata;
struct Object *camera;
struct World *world;
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index a0a933c3f90..dde3a3d8d14 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -5242,6 +5242,11 @@ static void def_sh_attribute(StructRNA *srna)
"The attribute is associated with the instancer particle system or object, "
"falling back to the Object mode if the attribute isn't found, or the object "
"is not instanced"},
+ {SHD_ATTRIBUTE_VIEW_LAYER,
+ "VIEW_LAYER",
+ 0,
+ "View Layer",
+ "The attribute is associated with the View Layer, Scene or World that is being rendered"},
{0, NULL, 0, NULL, NULL},
};
PropertyRNA *prop;
diff --git a/source/blender/nodes/shader/nodes/node_shader_attribute.cc b/source/blender/nodes/shader/nodes/node_shader_attribute.cc
index 77cf6b163d0..4694599f064 100644
--- a/source/blender/nodes/shader/nodes/node_shader_attribute.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_attribute.cc
@@ -42,6 +42,16 @@ static int node_shader_gpu_attribute(GPUMaterial *mat,
if (is_varying) {
cd_attr = GPU_attribute(mat, CD_AUTO_FROM_NAME, attr->name);
+
+ if (STREQ(attr->name, "color")) {
+ GPU_link(mat, "node_attribute_color", cd_attr, &cd_attr);
+ }
+ else if (STREQ(attr->name, "temperature")) {
+ GPU_link(mat, "node_attribute_temperature", cd_attr, &cd_attr);
+ }
+ }
+ else if (attr->type == SHD_ATTRIBUTE_VIEW_LAYER) {
+ cd_attr = GPU_layer_attribute(mat, attr->name);
}
else {
cd_attr = GPU_uniform_attribute(mat,
@@ -52,13 +62,6 @@ static int node_shader_gpu_attribute(GPUMaterial *mat,
GPU_link(mat, "node_attribute_uniform", cd_attr, GPU_constant(&attr_hash), &cd_attr);
}
- if (STREQ(attr->name, "color")) {
- GPU_link(mat, "node_attribute_color", cd_attr, &cd_attr);
- }
- else if (STREQ(attr->name, "temperature")) {
- GPU_link(mat, "node_attribute_temperature", cd_attr, &cd_attr);
- }
-
GPU_stack_link(mat, node, "node_attribute", in, out, cd_attr);
if (is_varying) {