Blender V4.3
geometry_attributes.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include "bvh/bvh.h"
6#include "bvh/bvh2.h"
7
8#include "device/device.h"
9
10#include "scene/attribute.h"
11#include "scene/camera.h"
12#include "scene/geometry.h"
13#include "scene/hair.h"
14#include "scene/light.h"
15#include "scene/mesh.h"
16#include "scene/object.h"
17#include "scene/pointcloud.h"
18#include "scene/scene.h"
19#include "scene/shader.h"
20#include "scene/shader_nodes.h"
21#include "scene/stats.h"
22#include "scene/volume.h"
23
24#include "subd/patch_table.h"
25#include "subd/split.h"
26
27#include "kernel/osl/globals.h"
28
29#include "util/foreach.h"
30#include "util/log.h"
31#include "util/progress.h"
32#include "util/task.h"
33
35
37{
38 if (std == ATTR_STD_NONE) {
39 return false;
40 }
41
42 if (scene->need_global_attribute(std)) {
43 return true;
44 }
45
46 foreach (Node *node, used_shaders) {
47 Shader *shader = static_cast<Shader *>(node);
48 if (shader->attributes.find(std)) {
49 return true;
50 }
51 }
52
53 return false;
54}
55
56bool Geometry::need_attribute(Scene * /*scene*/, ustring name)
57{
58 if (name == ustring()) {
59 return false;
60 }
61
62 foreach (Node *node, used_shaders) {
63 Shader *shader = static_cast<Shader *>(node);
64 if (shader->attributes.find(name)) {
65 return true;
66 }
67 }
68
69 return false;
70}
71
73{
75
76 foreach (Node *node, used_shaders) {
77 Shader *shader = static_cast<Shader *>(node);
78 result.add(shader->attributes);
79 }
80
81 return result;
82}
83
85{
86 foreach (const Attribute &attr, attributes.attributes) {
87 if (attr.element == ATTR_ELEMENT_VOXEL) {
88 return true;
89 }
90 }
91
92 return false;
93}
94
95/* Generate a normal attribute map entry from an attribute descriptor. */
97 size_t index,
98 uint64_t id,
99 TypeDesc type,
100 const AttributeDescriptor &desc)
101{
102 attr_map[index].id = id;
103 attr_map[index].element = desc.element;
104 attr_map[index].offset = as_uint(desc.offset);
105
106 if (type == TypeDesc::TypeFloat) {
107 attr_map[index].type = NODE_ATTR_FLOAT;
108 }
109 else if (type == TypeDesc::TypeMatrix) {
110 attr_map[index].type = NODE_ATTR_MATRIX;
111 }
112 else if (type == TypeFloat2) {
113 attr_map[index].type = NODE_ATTR_FLOAT2;
114 }
115 else if (type == TypeFloat4) {
116 attr_map[index].type = NODE_ATTR_FLOAT4;
117 }
118 else if (type == TypeRGBA) {
119 attr_map[index].type = NODE_ATTR_RGBA;
120 }
121 else {
122 attr_map[index].type = NODE_ATTR_FLOAT3;
123 }
124
125 attr_map[index].flags = desc.flags;
126}
127
128/* Generate an attribute map end marker, optionally including a link to another map.
129 * Links are used to connect object attribute maps to mesh attribute maps. */
131 size_t index,
132 bool chain,
133 uint chain_link)
134{
135 for (int j = 0; j < ATTR_PRIM_TYPES; j++) {
136 attr_map[index + j].id = ATTR_STD_NONE;
137 attr_map[index + j].element = chain; /* link is valid flag */
138 attr_map[index + j].offset = chain ? chain_link + j : 0; /* link to the correct sub-entry */
139 attr_map[index + j].type = 0;
140 attr_map[index + j].flags = 0;
141 }
142}
143
144/* Generate all necessary attribute map entries from the attribute request. */
146 AttributeMap *attr_map, size_t index, uint64_t id, AttributeRequest &req, Geometry *geom)
147{
148 emit_attribute_map_entry(attr_map, index, id, req.type, req.desc);
149
150 if (geom->is_mesh()) {
151 Mesh *mesh = static_cast<Mesh *>(geom);
152 if (mesh->get_num_subd_faces()) {
153 emit_attribute_map_entry(attr_map, index + 1, id, req.subd_type, req.subd_desc);
154 }
155 }
156}
157
159 DeviceScene *dscene,
160 Scene *scene,
161 vector<AttributeRequestSet> &geom_attributes,
162 vector<AttributeRequestSet> &object_attributes)
163{
164 /* for SVM, the attributes_map table is used to lookup the offset of an
165 * attribute, based on a unique shader attribute id. */
166
167 /* compute array stride */
168 size_t attr_map_size = 0;
169
170 for (size_t i = 0; i < scene->geometry.size(); i++) {
171 Geometry *geom = scene->geometry[i];
172 geom->attr_map_offset = attr_map_size;
173
174#ifdef WITH_OSL
175 size_t attr_count = 0;
176 foreach (AttributeRequest &req, geom_attributes[i].requests) {
177 if (req.std != ATTR_STD_NONE &&
178 scene->shader_manager->get_attribute_id(req.std) != (uint64_t)req.std)
179 attr_count += 2;
180 else
181 attr_count += 1;
182 }
183#else
184 const size_t attr_count = geom_attributes[i].size();
185#endif
186
187 attr_map_size += (attr_count + 1) * ATTR_PRIM_TYPES;
188 }
189
190 for (size_t i = 0; i < scene->objects.size(); i++) {
191 Object *object = scene->objects[i];
192
193 /* only allocate a table for the object if it actually has attributes */
194 if (object_attributes[i].size() == 0) {
195 object->attr_map_offset = 0;
196 }
197 else {
198 object->attr_map_offset = attr_map_size;
199 attr_map_size += (object_attributes[i].size() + 1) * ATTR_PRIM_TYPES;
200 }
201 }
202
203 if (attr_map_size == 0) {
204 return;
205 }
206
207 if (!dscene->attributes_map.need_realloc()) {
208 return;
209 }
210
211 /* create attribute map */
212 AttributeMap *attr_map = dscene->attributes_map.alloc(attr_map_size);
213 memset(attr_map, 0, dscene->attributes_map.size() * sizeof(*attr_map));
214
215 for (size_t i = 0; i < scene->geometry.size(); i++) {
216 Geometry *geom = scene->geometry[i];
217 AttributeRequestSet &attributes = geom_attributes[i];
218
219 /* set geometry attributes */
220 size_t index = geom->attr_map_offset;
221
222 foreach (AttributeRequest &req, attributes.requests) {
223 uint64_t id;
224 if (req.std == ATTR_STD_NONE) {
225 id = scene->shader_manager->get_attribute_id(req.name);
226 }
227 else {
228 id = scene->shader_manager->get_attribute_id(req.std);
229 }
230
231 emit_attribute_mapping(attr_map, index, id, req, geom);
232 index += ATTR_PRIM_TYPES;
233
234#ifdef WITH_OSL
235 /* Some standard attributes are explicitly referenced via their standard ID, so add those
236 * again in case they were added under a different attribute ID. */
237 if (req.std != ATTR_STD_NONE && id != (uint64_t)req.std) {
238 emit_attribute_mapping(attr_map, index, (uint64_t)req.std, req, geom);
239 index += ATTR_PRIM_TYPES;
240 }
241#endif
242 }
243
244 emit_attribute_map_terminator(attr_map, index, false, 0);
245 }
246
247 for (size_t i = 0; i < scene->objects.size(); i++) {
248 Object *object = scene->objects[i];
249 AttributeRequestSet &attributes = object_attributes[i];
250
251 /* set object attributes */
252 if (attributes.size() > 0) {
253 size_t index = object->attr_map_offset;
254
255 foreach (AttributeRequest &req, attributes.requests) {
256 uint64_t id;
257 if (req.std == ATTR_STD_NONE) {
258 id = scene->shader_manager->get_attribute_id(req.name);
259 }
260 else {
261 id = scene->shader_manager->get_attribute_id(req.std);
262 }
263
264 emit_attribute_mapping(attr_map, index, id, req, object->geometry);
265 index += ATTR_PRIM_TYPES;
266 }
267
268 emit_attribute_map_terminator(attr_map, index, true, object->geometry->attr_map_offset);
269 }
270 }
271
272 /* copy to device */
274}
275
276void GeometryManager::update_attribute_element_offset(Geometry *geom,
277 device_vector<float> &attr_float,
278 size_t &attr_float_offset,
279 device_vector<float2> &attr_float2,
280 size_t &attr_float2_offset,
281 device_vector<packed_float3> &attr_float3,
282 size_t &attr_float3_offset,
283 device_vector<float4> &attr_float4,
284 size_t &attr_float4_offset,
285 device_vector<uchar4> &attr_uchar4,
286 size_t &attr_uchar4_offset,
287 Attribute *mattr,
289 TypeDesc &type,
291{
292 if (mattr) {
293 /* store element and type */
294 desc.element = mattr->element;
295 desc.flags = mattr->flags;
296 type = mattr->type;
297
298 /* store attribute data in arrays */
299 size_t size = mattr->element_size(geom, prim);
300
301 AttributeElement &element = desc.element;
302 int &offset = desc.offset;
303
304 if (mattr->element == ATTR_ELEMENT_VOXEL) {
305 /* store slot in offset value */
306 ImageHandle &handle = mattr->data_voxel();
307 offset = handle.svm_slot();
308 }
309 else if (mattr->element == ATTR_ELEMENT_CORNER_BYTE) {
310 uchar4 *data = mattr->data_uchar4();
311 offset = attr_uchar4_offset;
312
313 assert(attr_uchar4.size() >= offset + size);
314 if (mattr->modified) {
315 for (size_t k = 0; k < size; k++) {
316 attr_uchar4[offset + k] = data[k];
317 }
318 attr_uchar4.tag_modified();
319 }
320 attr_uchar4_offset += size;
321 }
322 else if (mattr->type == TypeDesc::TypeFloat) {
323 float *data = mattr->data_float();
324 offset = attr_float_offset;
325
326 assert(attr_float.size() >= offset + size);
327 if (mattr->modified) {
328 for (size_t k = 0; k < size; k++) {
329 attr_float[offset + k] = data[k];
330 }
331 attr_float.tag_modified();
332 }
333 attr_float_offset += size;
334 }
335 else if (mattr->type == TypeFloat2) {
336 float2 *data = mattr->data_float2();
337 offset = attr_float2_offset;
338
339 assert(attr_float2.size() >= offset + size);
340 if (mattr->modified) {
341 for (size_t k = 0; k < size; k++) {
342 attr_float2[offset + k] = data[k];
343 }
344 attr_float2.tag_modified();
345 }
346 attr_float2_offset += size;
347 }
348 else if (mattr->type == TypeDesc::TypeMatrix) {
349 Transform *tfm = mattr->data_transform();
350 offset = attr_float4_offset;
351
352 assert(attr_float4.size() >= offset + size * 3);
353 if (mattr->modified) {
354 for (size_t k = 0; k < size * 3; k++) {
355 attr_float4[offset + k] = (&tfm->x)[k];
356 }
357 attr_float4.tag_modified();
358 }
359 attr_float4_offset += size * 3;
360 }
361 else if (mattr->type == TypeFloat4 || mattr->type == TypeRGBA) {
362 float4 *data = mattr->data_float4();
363 offset = attr_float4_offset;
364
365 assert(attr_float4.size() >= offset + size);
366 if (mattr->modified) {
367 for (size_t k = 0; k < size; k++) {
368 attr_float4[offset + k] = data[k];
369 }
370 attr_float4.tag_modified();
371 }
372 attr_float4_offset += size;
373 }
374 else {
375 float3 *data = mattr->data_float3();
376 offset = attr_float3_offset;
377
378 assert(attr_float3.size() >= offset + size);
379 if (mattr->modified) {
380 for (size_t k = 0; k < size; k++) {
381 attr_float3[offset + k] = data[k];
382 }
383 attr_float3.tag_modified();
384 }
385 attr_float3_offset += size;
386 }
387
388 /* mesh vertex/curve index is global, not per object, so we sneak
389 * a correction for that in here */
390 if (geom->is_mesh()) {
391 Mesh *mesh = static_cast<Mesh *>(geom);
392 if (mesh->subdivision_type == Mesh::SUBDIVISION_CATMULL_CLARK &&
393 desc.flags & ATTR_SUBDIVIDED)
394 {
395 /* Indices for subdivided attributes are retrieved
396 * from patch table so no need for correction here. */
397 }
398 else if (element == ATTR_ELEMENT_VERTEX) {
399 offset -= mesh->vert_offset;
400 }
401 else if (element == ATTR_ELEMENT_VERTEX_MOTION) {
402 offset -= mesh->vert_offset;
403 }
404 else if (element == ATTR_ELEMENT_FACE) {
405 if (prim == ATTR_PRIM_GEOMETRY) {
406 offset -= mesh->prim_offset;
407 }
408 else {
409 offset -= mesh->face_offset;
410 }
411 }
412 else if (element == ATTR_ELEMENT_CORNER || element == ATTR_ELEMENT_CORNER_BYTE) {
413 if (prim == ATTR_PRIM_GEOMETRY) {
414 offset -= 3 * mesh->prim_offset;
415 }
416 else {
417 offset -= mesh->corner_offset;
418 }
419 }
420 }
421 else if (geom->is_hair()) {
422 Hair *hair = static_cast<Hair *>(geom);
423 if (element == ATTR_ELEMENT_CURVE) {
424 offset -= hair->prim_offset;
425 }
426 else if (element == ATTR_ELEMENT_CURVE_KEY) {
427 offset -= hair->curve_key_offset;
428 }
429 else if (element == ATTR_ELEMENT_CURVE_KEY_MOTION) {
430 offset -= hair->curve_key_offset;
431 }
432 }
433 else if (geom->is_pointcloud()) {
434 if (element == ATTR_ELEMENT_VERTEX) {
435 offset -= geom->prim_offset;
436 }
437 else if (element == ATTR_ELEMENT_VERTEX_MOTION) {
438 offset -= geom->prim_offset;
439 }
440 }
441 }
442 else {
443 /* attribute not found */
445 desc.offset = 0;
446 }
447}
448
450 Attribute *mattr,
452 size_t *attr_float_size,
453 size_t *attr_float2_size,
454 size_t *attr_float3_size,
455 size_t *attr_float4_size,
456 size_t *attr_uchar4_size)
457{
458 if (mattr) {
459 size_t size = mattr->element_size(geom, prim);
460
461 if (mattr->element == ATTR_ELEMENT_VOXEL) {
462 /* pass */
463 }
464 else if (mattr->element == ATTR_ELEMENT_CORNER_BYTE) {
465 *attr_uchar4_size += size;
466 }
467 else if (mattr->type == TypeDesc::TypeFloat) {
468 *attr_float_size += size;
469 }
470 else if (mattr->type == TypeFloat2) {
471 *attr_float2_size += size;
472 }
473 else if (mattr->type == TypeDesc::TypeMatrix) {
474 *attr_float4_size += size * 4;
475 }
476 else if (mattr->type == TypeFloat4 || mattr->type == TypeRGBA) {
477 *attr_float4_size += size;
478 }
479 else {
480 *attr_float3_size += size;
481 }
482 }
483}
484
486 DeviceScene *dscene,
487 Scene *scene,
488 Progress &progress)
489{
490 progress.set_status("Updating Mesh", "Computing attributes");
491
492 /* gather per mesh requested attributes. as meshes may have multiple
493 * shaders assigned, this merges the requested attributes that have
494 * been set per shader by the shader manager */
495 vector<AttributeRequestSet> geom_attributes(scene->geometry.size());
496
497 for (size_t i = 0; i < scene->geometry.size(); i++) {
498 Geometry *geom = scene->geometry[i];
499
500 geom->index = i;
501 scene->need_global_attributes(geom_attributes[i]);
502
503 foreach (Node *node, geom->get_used_shaders()) {
504 Shader *shader = static_cast<Shader *>(node);
505 geom_attributes[i].add(shader->attributes);
506 }
507
508 if (geom->is_hair() && static_cast<Hair *>(geom)->need_shadow_transparency()) {
509 geom_attributes[i].add(ATTR_STD_SHADOW_TRANSPARENCY);
510 }
511 }
512
513 /* convert object attributes to use the same data structures as geometry ones */
514 vector<AttributeRequestSet> object_attributes(scene->objects.size());
515 vector<AttributeSet> object_attribute_values;
516
517 object_attribute_values.reserve(scene->objects.size());
518
519 for (size_t i = 0; i < scene->objects.size(); i++) {
520 Object *object = scene->objects[i];
521 Geometry *geom = object->geometry;
522 size_t geom_idx = geom->index;
523
524 assert(geom_idx < scene->geometry.size() && scene->geometry[geom_idx] == geom);
525
526 object_attribute_values.push_back(AttributeSet(geom, ATTR_PRIM_GEOMETRY));
527
528 AttributeRequestSet &geom_requests = geom_attributes[geom_idx];
529 AttributeRequestSet &attributes = object_attributes[i];
530 AttributeSet &values = object_attribute_values[i];
531
532 for (size_t j = 0; j < object->attributes.size(); j++) {
533 ParamValue &param = object->attributes[j];
534
535 /* add attributes that are requested and not already handled by the mesh */
536 if (geom_requests.find(param.name()) && !geom->attributes.find(param.name())) {
537 attributes.add(param.name());
538
539 Attribute *attr = values.add(param.name(), param.type(), ATTR_ELEMENT_OBJECT);
540 assert(param.datasize() == attr->buffer.size());
541 memcpy(attr->buffer.data(), param.data(), param.datasize());
542 }
543 }
544 }
545
546 /* mesh attribute are stored in a single array per data type. here we fill
547 * those arrays, and set the offset and element type to create attribute
548 * maps next */
549
550 /* Pre-allocate attributes to avoid arrays re-allocation which would
551 * take 2x of overall attribute memory usage.
552 */
553 size_t attr_float_size = 0;
554 size_t attr_float2_size = 0;
555 size_t attr_float3_size = 0;
556 size_t attr_float4_size = 0;
557 size_t attr_uchar4_size = 0;
558
559 for (size_t i = 0; i < scene->geometry.size(); i++) {
560 Geometry *geom = scene->geometry[i];
561 AttributeRequestSet &attributes = geom_attributes[i];
562 foreach (AttributeRequest &req, attributes.requests) {
563 Attribute *attr = geom->attributes.find(req);
564
566 attr,
568 &attr_float_size,
569 &attr_float2_size,
570 &attr_float3_size,
571 &attr_float4_size,
572 &attr_uchar4_size);
573
574 if (geom->is_mesh()) {
575 Mesh *mesh = static_cast<Mesh *>(geom);
576 Attribute *subd_attr = mesh->subd_attributes.find(req);
577
579 subd_attr,
581 &attr_float_size,
582 &attr_float2_size,
583 &attr_float3_size,
584 &attr_float4_size,
585 &attr_uchar4_size);
586 }
587 }
588 }
589
590 for (size_t i = 0; i < scene->objects.size(); i++) {
591 Object *object = scene->objects[i];
592
593 foreach (Attribute &attr, object_attribute_values[i].attributes) {
594 update_attribute_element_size(object->geometry,
595 &attr,
597 &attr_float_size,
598 &attr_float2_size,
599 &attr_float3_size,
600 &attr_float4_size,
601 &attr_uchar4_size);
602 }
603 }
604
605 dscene->attributes_float.alloc(attr_float_size);
606 dscene->attributes_float2.alloc(attr_float2_size);
607 dscene->attributes_float3.alloc(attr_float3_size);
608 dscene->attributes_float4.alloc(attr_float4_size);
609 dscene->attributes_uchar4.alloc(attr_uchar4_size);
610
611 /* The order of those flags needs to match that of AttrKernelDataType. */
612 const bool attributes_need_realloc[AttrKernelDataType::NUM] = {
618 };
619
620 size_t attr_float_offset = 0;
621 size_t attr_float2_offset = 0;
622 size_t attr_float3_offset = 0;
623 size_t attr_float4_offset = 0;
624 size_t attr_uchar4_offset = 0;
625
626 /* Fill in attributes. */
627 for (size_t i = 0; i < scene->geometry.size(); i++) {
628 Geometry *geom = scene->geometry[i];
629 AttributeRequestSet &attributes = geom_attributes[i];
630
631 /* todo: we now store std and name attributes from requests even if
632 * they actually refer to the same mesh attributes, optimize */
633 foreach (AttributeRequest &req, attributes.requests) {
634 Attribute *attr = geom->attributes.find(req);
635
636 if (attr) {
637 /* force a copy if we need to reallocate all the data */
638 attr->modified |= attributes_need_realloc[Attribute::kernel_type(*attr)];
639 }
640
641 update_attribute_element_offset(geom,
642 dscene->attributes_float,
643 attr_float_offset,
644 dscene->attributes_float2,
645 attr_float2_offset,
646 dscene->attributes_float3,
647 attr_float3_offset,
648 dscene->attributes_float4,
649 attr_float4_offset,
650 dscene->attributes_uchar4,
651 attr_uchar4_offset,
652 attr,
654 req.type,
655 req.desc);
656
657 if (geom->is_mesh()) {
658 Mesh *mesh = static_cast<Mesh *>(geom);
659 Attribute *subd_attr = mesh->subd_attributes.find(req);
660
661 if (subd_attr) {
662 /* force a copy if we need to reallocate all the data */
663 subd_attr->modified |= attributes_need_realloc[Attribute::kernel_type(*subd_attr)];
664 }
665
666 update_attribute_element_offset(mesh,
667 dscene->attributes_float,
668 attr_float_offset,
669 dscene->attributes_float2,
670 attr_float2_offset,
671 dscene->attributes_float3,
672 attr_float3_offset,
673 dscene->attributes_float4,
674 attr_float4_offset,
675 dscene->attributes_uchar4,
676 attr_uchar4_offset,
677 subd_attr,
679 req.subd_type,
680 req.subd_desc);
681 }
682
683 if (progress.get_cancel()) {
684 return;
685 }
686 }
687 }
688
689 for (size_t i = 0; i < scene->objects.size(); i++) {
690 Object *object = scene->objects[i];
691 AttributeRequestSet &attributes = object_attributes[i];
692 AttributeSet &values = object_attribute_values[i];
693
694 foreach (AttributeRequest &req, attributes.requests) {
695 Attribute *attr = values.find(req);
696
697 if (attr) {
698 attr->modified |= attributes_need_realloc[Attribute::kernel_type(*attr)];
699 }
700
701 update_attribute_element_offset(object->geometry,
702 dscene->attributes_float,
703 attr_float_offset,
704 dscene->attributes_float2,
705 attr_float2_offset,
706 dscene->attributes_float3,
707 attr_float3_offset,
708 dscene->attributes_float4,
709 attr_float4_offset,
710 dscene->attributes_uchar4,
711 attr_uchar4_offset,
712 attr,
714 req.type,
715 req.desc);
716
717 /* object attributes don't care about subdivision */
718 req.subd_type = req.type;
719 req.subd_desc = req.desc;
720
721 if (progress.get_cancel()) {
722 return;
723 }
724 }
725 }
726
727 /* create attribute lookup maps */
728 if (scene->shader_manager->use_osl()) {
729 update_osl_globals(device, scene);
730 }
731
732 update_svm_attributes(device, dscene, scene, geom_attributes, object_attributes);
733
734 if (progress.get_cancel()) {
735 return;
736 }
737
738 /* copy to device */
739 progress.set_status("Updating Mesh", "Copying Attributes to device");
740
746
747 if (progress.get_cancel()) {
748 return;
749 }
750
751 /* After mesh attributes and patch tables have been copied to device memory,
752 * we need to update offsets in the objects. */
753 scene->object_manager->device_update_geom_offsets(device, dscene, scene);
754}
755
unsigned int uint
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
bool find(ustring name)
AttributeDescriptor subd_desc
AttributeDescriptor desc
AttributeStandard std
Attribute * find(ustring name) const
AttributeElement element
uchar4 * data_uchar4()
static AttrKernelDataType kernel_type(const Attribute &attr)
TypeDesc type
size_t element_size(Geometry *geom, AttributePrimitive prim) const
vector< char > buffer
float * data_float()
ImageHandle & data_voxel()
float3 * data_float3()
float4 * data_float4()
Transform * data_transform()
void add(const float &f)
float2 * data_float2()
device_vector< float4 > attributes_float4
Definition devicescene.h:62
device_vector< float2 > attributes_float2
Definition devicescene.h:60
device_vector< AttributeMap > attributes_map
Definition devicescene.h:58
device_vector< packed_float3 > attributes_float3
Definition devicescene.h:61
device_vector< float > attributes_float
Definition devicescene.h:59
device_vector< uchar4 > attributes_uchar4
Definition devicescene.h:63
void device_update_attributes(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress)
void update_osl_globals(Device *device, Scene *scene)
void update_svm_attributes(Device *device, DeviceScene *dscene, Scene *scene, vector< AttributeRequestSet > &geom_attributes, vector< AttributeRequestSet > &object_attributes)
bool has_voxel_attributes() const
bool is_pointcloud() const
bool is_hair() const
AttributeRequestSet needed_attributes()
size_t attr_map_offset
size_t prim_offset
bool need_attribute(Scene *scene, AttributeStandard std)
AttributeSet attributes
bool is_mesh() const
Definition hair.h:14
int svm_slot(const int tile_index=0) const
bool get_cancel() const
Definition progress.h:93
void set_status(const string &status_, const string &substatus_="")
Definition progress.h:263
size_t size() const
T * alloc(size_t width, size_t height=0, size_t depth=0)
OperationNode * node
#define CCL_NAMESPACE_END
static void emit_attribute_map_entry(AttributeMap *attr_map, size_t index, uint64_t id, TypeDesc type, const AttributeDescriptor &desc)
static void update_attribute_element_size(Geometry *geom, Attribute *mattr, AttributePrimitive prim, size_t *attr_float_size, size_t *attr_float2_size, size_t *attr_float3_size, size_t *attr_float4_size, size_t *attr_uchar4_size)
static void emit_attribute_map_terminator(AttributeMap *attr_map, size_t index, bool chain, uint chain_link)
static void emit_attribute_mapping(AttributeMap *attr_map, size_t index, uint64_t id, AttributeRequest &req, Geometry *geom)
@ NODE_ATTR_FLOAT
@ NODE_ATTR_FLOAT3
@ NODE_ATTR_RGBA
@ NODE_ATTR_FLOAT2
@ NODE_ATTR_FLOAT4
@ NODE_ATTR_MATRIX
AttributeStandard
@ ATTR_STD_NONE
@ ATTR_STD_SHADOW_TRANSPARENCY
@ ATTR_SUBDIVIDED
AttributeElement
@ ATTR_ELEMENT_NONE
@ ATTR_ELEMENT_CORNER_BYTE
@ ATTR_ELEMENT_CURVE_KEY
@ ATTR_ELEMENT_CURVE_KEY_MOTION
@ ATTR_ELEMENT_VOXEL
@ ATTR_ELEMENT_CORNER
@ ATTR_ELEMENT_OBJECT
@ ATTR_ELEMENT_VERTEX_MOTION
@ ATTR_ELEMENT_VERTEX
@ ATTR_ELEMENT_FACE
@ ATTR_ELEMENT_CURVE
AttributePrimitive
@ ATTR_PRIM_SUBD
@ ATTR_PRIM_TYPES
@ ATTR_PRIM_GEOMETRY
VecBase< float, 4 > float4
static constexpr TypeDesc TypeRGBA(TypeDesc::FLOAT, TypeDesc::VEC4, TypeDesc::COLOR)
CCL_NAMESPACE_BEGIN static OIIO_NAMESPACE_USING constexpr TypeDesc TypeFloat2(TypeDesc::FLOAT, TypeDesc::VEC2)
@ NUM
long long TypeDesc
unsigned __int64 uint64_t
Definition stdint.h:90
AttributeElement element
uint16_t element
@ SUBDIVISION_CATMULL_CLARK
Definition scene/mesh.h:123
size_t attr_map_offset
float4 x
Definition transform.h:24
ccl_device_inline uint as_uint(int i)
Definition util/math.h:234