Blender V5.0
kernel/svm/attribute.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#pragma once
6
7#include "kernel/globals.h"
8
10#include "kernel/geom/object.h"
12#include "kernel/geom/volume.h"
13
14#include "kernel/svm/util.h"
15
17
19
20/* Attribute Node */
21
23 ccl_private ShaderData *sd,
24 const uint4 node,
26 ccl_private uint *out_offset)
27{
28 uint type_value;
29 svm_unpack_node_uchar2(node.z, out_offset, &type_value);
30 *type = (NodeAttributeOutputType)type_value;
31
33
34 if (sd->object != OBJECT_NONE) {
35 desc = find_attribute(kg, sd, node.y);
36 if (desc.offset == ATTR_STD_NOT_FOUND) {
37 desc = attribute_not_found();
38 desc.offset = 0;
39 desc.type = (NodeAttributeType)type_value;
40 }
41 }
42 else {
43 /* background */
44 desc = attribute_not_found();
45 desc.offset = 0;
46 desc.type = (NodeAttributeType)type_value;
47 }
48
49 return desc;
50}
51
53 ccl_private float *stack,
54 const uint out_offset,
55 const float f)
56{
57 if (type == NODE_ATTR_OUTPUT_FLOAT) {
58 stack_store_float(stack, out_offset, f);
59 }
60 else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
61 stack_store_float3(stack, out_offset, make_float3(f));
62 }
63 else {
64 stack_store_float(stack, out_offset, 1.0f);
65 }
66}
67
69 ccl_private float *stack,
70 const uint out_offset,
71 const ccl_private float2 &f)
72{
73 if (type == NODE_ATTR_OUTPUT_FLOAT) {
74 stack_store_float(stack, out_offset, f.x);
75 }
76 else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
77 stack_store_float3(stack, out_offset, make_float3(f));
78 }
79 else {
80 stack_store_float(stack, out_offset, 1.0f);
81 }
82}
83
85 ccl_private float *stack,
86 const uint out_offset,
87 const ccl_private float3 &f)
88{
89 if (type == NODE_ATTR_OUTPUT_FLOAT) {
90 stack_store_float(stack, out_offset, average(f));
91 }
92 else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
93 stack_store_float3(stack, out_offset, f);
94 }
95 else {
96 stack_store_float(stack, out_offset, 1.0f);
97 }
98}
99
101 ccl_private float *stack,
102 const uint out_offset,
103 const ccl_private float4 &f)
104{
105 if (type == NODE_ATTR_OUTPUT_FLOAT) {
106 stack_store_float(stack, out_offset, average(make_float3(f)));
107 }
108 else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
109 stack_store_float3(stack, out_offset, make_float3(f));
110 }
111 else {
113 stack_store_float(stack, out_offset, f.w);
114 }
115}
116
117template<class T>
119 const ccl_private ShaderData *sd,
120 const AttributeDescriptor desc,
121 const NodeAttributeOutputType type,
122 ccl_private float *stack,
123 const uint out_offset)
124{
125 T f = primitive_surface_attribute<T>(kg, sd, desc).val;
126 svm_node_attr_store(type, stack, out_offset, f);
127}
128
129template<class T>
131 const ccl_private ShaderData *sd,
132 const AttributeDescriptor desc,
133 const float bump_filter_width,
134 const NodeAttributeOutputType type,
135 ccl_private float *stack,
136 const uint out_offset)
137{
138 dual<T> f = primitive_surface_attribute<T>(kg, sd, desc, true, false);
139 f.val += f.dx * bump_filter_width;
140 svm_node_attr_store(type, stack, out_offset, f.val);
141}
142
143template<class T>
145 const ccl_private ShaderData *sd,
146 const AttributeDescriptor desc,
147 const float bump_filter_width,
148 const NodeAttributeOutputType type,
149 ccl_private float *stack,
150 const uint out_offset)
151{
152 dual<T> f = primitive_surface_attribute<T>(kg, sd, desc, false, true);
153 f.val += f.dy * bump_filter_width;
154 svm_node_attr_store(type, stack, out_offset, f.val);
155}
156
157template<uint node_feature_mask>
159 ccl_private ShaderData *sd,
160 ccl_private float *stack,
161 const uint4 node)
162{
164 uint out_offset = 0;
165 const AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
166
167#ifdef __VOLUME__
169 {
170 /* Volumes
171 * NOTE: moving this into its own node type might help improve performance. */
172 if (primitive_is_volume_attribute(sd)) {
173 const bool stochastic_sample = node.w;
174 const float4 value = volume_attribute_float4(kg, sd, desc, stochastic_sample);
175
176 if (type == NODE_ATTR_OUTPUT_FLOAT) {
177 const float f = volume_attribute_value<float>(value);
178 stack_store_float(stack, out_offset, f);
179 }
180 else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
181 const float3 f = volume_attribute_value<float3>(value);
182 stack_store_float3(stack, out_offset, f);
183 }
184 else {
185 const float f = volume_attribute_alpha(value);
186 stack_store_float(stack, out_offset, f);
187 }
188 return;
189 }
190 }
191#endif
192
193 if (sd->type == PRIMITIVE_LAMP && node.y == ATTR_STD_UV) {
194 stack_store_float3(stack, out_offset, make_float3(1.0f - sd->u - sd->v, sd->u, 0.0f));
195 return;
196 }
197
198 if (node.y == ATTR_STD_GENERATED && desc.element == ATTR_ELEMENT_NONE) {
199 /* No generated attribute, fall back to object coordinates. */
200 float3 f = sd->P;
201 if (sd->object != OBJECT_NONE) {
203 }
204 svm_node_attr_store(type, stack, out_offset, f);
205 return;
206 }
207
208 /* Surface. */
209 if (desc.type == NODE_ATTR_FLOAT) {
210 svm_surface_attr<float>(kg, sd, desc, type, stack, out_offset);
211 }
212 else if (desc.type == NODE_ATTR_FLOAT2) {
213 svm_surface_attr<float2>(kg, sd, desc, type, stack, out_offset);
214 }
215 else if (desc.type == NODE_ATTR_FLOAT4 || desc.type == NODE_ATTR_RGBA) {
216 svm_surface_attr<float4>(kg, sd, desc, type, stack, out_offset);
217 }
218 else {
219 svm_surface_attr<float3>(kg, sd, desc, type, stack, out_offset);
220 }
221}
222
223/* Position offsetted in x direction. */
225 const float bump_filter_width)
226{
227 return sd->P + dPdx(sd) * bump_filter_width;
228}
229
230/* Position offsetted in y direction. */
232 const float bump_filter_width)
233{
234 return sd->P + dPdy(sd) * bump_filter_width;
235}
236
237/* Evaluate attributes at a position shifted in x direction. */
239 ccl_private ShaderData *sd,
240 ccl_private float *stack,
241 const uint4 node)
242{
244 uint out_offset = 0;
245 const AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
246 const float bump_filter_width = __uint_as_float(node.w);
247
248#ifdef __VOLUME__
249 /* Volume */
250 if (primitive_is_volume_attribute(sd)) {
251 svm_node_attr_store(type, stack, out_offset, 0.0f);
252 return;
253 }
254#endif
255
256 if (node.y == ATTR_STD_GENERATED && desc.element == ATTR_ELEMENT_NONE) {
257 /* No generated attribute, fall back to object coordinates. */
258 float3 f_x = svm_node_bump_P_dx(sd, bump_filter_width);
259 if (sd->object != OBJECT_NONE) {
261 }
262 svm_node_attr_store(type, stack, out_offset, f_x);
263 return;
264 }
265
266 /* Surface */
267 if (desc.type == NODE_ATTR_FLOAT) {
268 svm_surface_attr_dx<float>(kg, sd, desc, bump_filter_width, type, stack, out_offset);
269 }
270 else if (desc.type == NODE_ATTR_FLOAT2) {
271 svm_surface_attr_dx<float2>(kg, sd, desc, bump_filter_width, type, stack, out_offset);
272 }
273 else if (desc.type == NODE_ATTR_FLOAT4 || desc.type == NODE_ATTR_RGBA) {
274 svm_surface_attr_dx<float4>(kg, sd, desc, bump_filter_width, type, stack, out_offset);
275 }
276 else {
277 svm_surface_attr_dx<float3>(kg, sd, desc, bump_filter_width, type, stack, out_offset);
278 }
279}
280
281/* Evaluate attributes at a position shifted in y direction. */
283 ccl_private ShaderData *sd,
284 ccl_private float *stack,
285 const uint4 node)
286{
288 uint out_offset = 0;
289 const AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
290 const float bump_filter_width = __uint_as_float(node.w);
291
292#ifdef __VOLUME__
293 /* Volume */
294 if (primitive_is_volume_attribute(sd)) {
295 svm_node_attr_store(type, stack, out_offset, 0.0f);
296 return;
297 }
298#endif
299
300 if (node.y == ATTR_STD_GENERATED && desc.element == ATTR_ELEMENT_NONE) {
301 /* No generated attribute, fall back to object coordinates. */
302 /* TODO:(weizhen) */
303 float3 f_y = svm_node_bump_P_dy(sd, bump_filter_width);
304 if (sd->object != OBJECT_NONE) {
306 }
307 svm_node_attr_store(type, stack, out_offset, f_y);
308 return;
309 }
310
311 /* Surface */
312 if (desc.type == NODE_ATTR_FLOAT) {
313 svm_surface_attr_dy<float>(kg, sd, desc, bump_filter_width, type, stack, out_offset);
314 }
315 else if (desc.type == NODE_ATTR_FLOAT2) {
316 svm_surface_attr_dy<float2>(kg, sd, desc, bump_filter_width, type, stack, out_offset);
317 }
318 else if (desc.type == NODE_ATTR_FLOAT4 || desc.type == NODE_ATTR_RGBA) {
319 svm_surface_attr_dy<float4>(kg, sd, desc, bump_filter_width, type, stack, out_offset);
320 }
321 else {
322 svm_surface_attr_dy<float3>(kg, sd, desc, bump_filter_width, type, stack, out_offset);
323 }
324}
325
unsigned int uint
ccl_device_forceinline float3 dPdx(const ccl_private ShaderData *sd)
ccl_device_inline void stack_store_float(ccl_private float *stack, const uint a, const float f)
ccl_device_inline void stack_store_float3(ccl_private float *stack, const uint a, const float3 f)
ccl_device_forceinline void svm_unpack_node_uchar2(const uint i, ccl_private uint *x, ccl_private uint *y)
ccl_device_forceinline float3 dPdy(const ccl_private ShaderData *sd)
#define kernel_assert(cond)
#define ccl_device_forceinline
#define IF_KERNEL_NODES_FEATURE(feature)
#define OBJECT_NONE
#define ccl_private
const ThreadKernelGlobalsCPU * KernelGlobals
#define ccl_device_inline
#define ccl_device_noinline
#define CCL_NAMESPACE_END
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
#define __uint_as_float(x)
CCL_NAMESPACE_BEGIN ccl_device_inline AttributeDescriptor attribute_not_found()
ccl_device_inline void object_inverse_position_transform(KernelGlobals kg, const ccl_private ShaderData *sd, ccl_private float3 *P)
ccl_device_forceinline float3 svm_node_bump_P_dx(const ccl_private ShaderData *sd, const float bump_filter_width)
ccl_device_forceinline float3 svm_node_bump_P_dy(const ccl_private ShaderData *sd, const float bump_filter_width)
ccl_device_inline void svm_node_attr_store(const NodeAttributeOutputType type, ccl_private float *stack, const uint out_offset, const float f)
CCL_NAMESPACE_BEGIN ccl_device AttributeDescriptor svm_node_attr_init(KernelGlobals kg, ccl_private ShaderData *sd, const uint4 node, ccl_private NodeAttributeOutputType *type, ccl_private uint *out_offset)
ccl_device_noinline void svm_node_attr_bump_dx(KernelGlobals kg, ccl_private ShaderData *sd, ccl_private float *stack, const uint4 node)
ccl_device_inline void svm_surface_attr_dy(KernelGlobals kg, const ccl_private ShaderData *sd, const AttributeDescriptor desc, const float bump_filter_width, const NodeAttributeOutputType type, ccl_private float *stack, const uint out_offset)
ccl_device_inline void svm_surface_attr(KernelGlobals kg, const ccl_private ShaderData *sd, const AttributeDescriptor desc, const NodeAttributeOutputType type, ccl_private float *stack, const uint out_offset)
ccl_device_inline void svm_surface_attr_dx(KernelGlobals kg, const ccl_private ShaderData *sd, const AttributeDescriptor desc, const float bump_filter_width, const NodeAttributeOutputType type, ccl_private float *stack, const uint out_offset)
ccl_device_noinline void svm_node_attr_bump_dy(KernelGlobals kg, ccl_private ShaderData *sd, ccl_private float *stack, const uint4 node)
ccl_device_noinline void svm_node_attr(KernelGlobals kg, ccl_private ShaderData *sd, ccl_private float *stack, const uint4 node)
NodeAttributeOutputType
@ NODE_ATTR_OUTPUT_FLOAT
@ NODE_ATTR_OUTPUT_FLOAT_ALPHA
@ NODE_ATTR_OUTPUT_FLOAT3
NodeAttributeType
@ NODE_ATTR_FLOAT
@ NODE_ATTR_RGBA
@ NODE_ATTR_FLOAT2
@ NODE_ATTR_FLOAT4
@ PRIMITIVE_LAMP
@ ATTR_STD_UV
@ ATTR_STD_NOT_FOUND
@ ATTR_STD_GENERATED
@ ATTR_ELEMENT_NONE
#define T
float average(point a)
Definition node_math.h:144
CCL_NAMESPACE_BEGIN ccl_device_forceinline dual< T > primitive_surface_attribute(KernelGlobals kg, const ccl_private ShaderData *sd, const AttributeDescriptor desc, const bool dx=false, const bool dy=false)
Definition primitive.h:32
#define ccl_device
static bool find_attribute(const std::string &attributes, const char *search_attribute)
AttributeElement element
NodeAttributeType type
T val
Definition types_dual.h:14
uint y
Definition types_uint4.h:13
uint z
Definition types_uint4.h:13
uint w
Definition types_uint4.h:13