forked from blender/blender
index-of-nearest-104619 #2
@ -15,8 +15,12 @@ set(SRC
|
||||
camera.cpp
|
||||
colorspace.cpp
|
||||
constant_fold.cpp
|
||||
devicescene.cpp
|
||||
film.cpp
|
||||
geometry.cpp
|
||||
geometry_attributes.cpp
|
||||
geometry_bvh.cpp
|
||||
geometry_mesh.cpp
|
||||
hair.cpp
|
||||
image.cpp
|
||||
image_oiio.cpp
|
||||
@ -55,6 +59,7 @@ set(SRC_HEADERS
|
||||
camera.h
|
||||
colorspace.h
|
||||
constant_fold.h
|
||||
devicescene.h
|
||||
film.h
|
||||
geometry.h
|
||||
hair.h
|
||||
|
64
intern/cycles/scene/devicescene.cpp
Normal file
64
intern/cycles/scene/devicescene.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2011-2022 Blender Foundation */
|
||||
|
||||
#include "scene/devicescene.h"
|
||||
#include "device/device.h"
|
||||
#include "device/memory.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
DeviceScene::DeviceScene(Device *device)
|
||||
: bvh_nodes(device, "bvh_nodes", MEM_GLOBAL),
|
||||
bvh_leaf_nodes(device, "bvh_leaf_nodes", MEM_GLOBAL),
|
||||
object_node(device, "object_node", MEM_GLOBAL),
|
||||
prim_type(device, "prim_type", MEM_GLOBAL),
|
||||
prim_visibility(device, "prim_visibility", MEM_GLOBAL),
|
||||
prim_index(device, "prim_index", MEM_GLOBAL),
|
||||
prim_object(device, "prim_object", MEM_GLOBAL),
|
||||
prim_time(device, "prim_time", MEM_GLOBAL),
|
||||
tri_verts(device, "tri_verts", MEM_GLOBAL),
|
||||
tri_shader(device, "tri_shader", MEM_GLOBAL),
|
||||
tri_vnormal(device, "tri_vnormal", MEM_GLOBAL),
|
||||
tri_vindex(device, "tri_vindex", MEM_GLOBAL),
|
||||
tri_patch(device, "tri_patch", MEM_GLOBAL),
|
||||
tri_patch_uv(device, "tri_patch_uv", MEM_GLOBAL),
|
||||
curves(device, "curves", MEM_GLOBAL),
|
||||
curve_keys(device, "curve_keys", MEM_GLOBAL),
|
||||
curve_segments(device, "curve_segments", MEM_GLOBAL),
|
||||
patches(device, "patches", MEM_GLOBAL),
|
||||
points(device, "points", MEM_GLOBAL),
|
||||
points_shader(device, "points_shader", MEM_GLOBAL),
|
||||
objects(device, "objects", MEM_GLOBAL),
|
||||
object_motion_pass(device, "object_motion_pass", MEM_GLOBAL),
|
||||
object_motion(device, "object_motion", MEM_GLOBAL),
|
||||
object_flag(device, "object_flag", MEM_GLOBAL),
|
||||
object_volume_step(device, "object_volume_step", MEM_GLOBAL),
|
||||
object_prim_offset(device, "object_prim_offset", MEM_GLOBAL),
|
||||
camera_motion(device, "camera_motion", MEM_GLOBAL),
|
||||
attributes_map(device, "attributes_map", MEM_GLOBAL),
|
||||
attributes_float(device, "attributes_float", MEM_GLOBAL),
|
||||
attributes_float2(device, "attributes_float2", MEM_GLOBAL),
|
||||
attributes_float3(device, "attributes_float3", MEM_GLOBAL),
|
||||
attributes_float4(device, "attributes_float4", MEM_GLOBAL),
|
||||
attributes_uchar4(device, "attributes_uchar4", MEM_GLOBAL),
|
||||
light_distribution(device, "light_distribution", MEM_GLOBAL),
|
||||
lights(device, "lights", MEM_GLOBAL),
|
||||
light_background_marginal_cdf(device, "light_background_marginal_cdf", MEM_GLOBAL),
|
||||
light_background_conditional_cdf(device, "light_background_conditional_cdf", MEM_GLOBAL),
|
||||
light_tree_nodes(device, "light_tree_nodes", MEM_GLOBAL),
|
||||
light_tree_emitters(device, "light_tree_emitters", MEM_GLOBAL),
|
||||
light_to_tree(device, "light_to_tree", MEM_GLOBAL),
|
||||
object_to_tree(device, "object_to_tree", MEM_GLOBAL),
|
||||
object_lookup_offset(device, "object_lookup_offset", MEM_GLOBAL),
|
||||
triangle_to_tree(device, "triangle_to_tree", MEM_GLOBAL),
|
||||
particles(device, "particles", MEM_GLOBAL),
|
||||
svm_nodes(device, "svm_nodes", MEM_GLOBAL),
|
||||
shaders(device, "shaders", MEM_GLOBAL),
|
||||
lookup_table(device, "lookup_table", MEM_GLOBAL),
|
||||
sample_pattern_lut(device, "sample_pattern_lut", MEM_GLOBAL),
|
||||
ies_lights(device, "ies", MEM_GLOBAL)
|
||||
{
|
||||
memset((void *)&data, 0, sizeof(data));
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
101
intern/cycles/scene/devicescene.h
Normal file
101
intern/cycles/scene/devicescene.h
Normal file
@ -0,0 +1,101 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2011-2022 Blender Foundation */
|
||||
|
||||
#ifndef __DEVICESCENE_H__
|
||||
#define __DEVICESCENE_H__
|
||||
|
||||
#include "device/device.h"
|
||||
#include "device/memory.h"
|
||||
|
||||
#include "util/types.h"
|
||||
#include "util/vector.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
class DeviceScene {
|
||||
public:
|
||||
/* BVH */
|
||||
device_vector<int4> bvh_nodes;
|
||||
device_vector<int4> bvh_leaf_nodes;
|
||||
device_vector<int> object_node;
|
||||
device_vector<int> prim_type;
|
||||
device_vector<uint> prim_visibility;
|
||||
device_vector<int> prim_index;
|
||||
device_vector<int> prim_object;
|
||||
device_vector<float2> prim_time;
|
||||
|
||||
/* mesh */
|
||||
device_vector<packed_float3> tri_verts;
|
||||
device_vector<uint> tri_shader;
|
||||
device_vector<packed_float3> tri_vnormal;
|
||||
device_vector<packed_uint3> tri_vindex;
|
||||
device_vector<uint> tri_patch;
|
||||
device_vector<float2> tri_patch_uv;
|
||||
|
||||
device_vector<KernelCurve> curves;
|
||||
device_vector<float4> curve_keys;
|
||||
device_vector<KernelCurveSegment> curve_segments;
|
||||
|
||||
device_vector<uint> patches;
|
||||
|
||||
/* point-cloud */
|
||||
device_vector<float4> points;
|
||||
device_vector<uint> points_shader;
|
||||
|
||||
/* objects */
|
||||
device_vector<KernelObject> objects;
|
||||
device_vector<Transform> object_motion_pass;
|
||||
device_vector<DecomposedTransform> object_motion;
|
||||
device_vector<uint> object_flag;
|
||||
device_vector<float> object_volume_step;
|
||||
device_vector<uint> object_prim_offset;
|
||||
|
||||
/* cameras */
|
||||
device_vector<DecomposedTransform> camera_motion;
|
||||
|
||||
/* attributes */
|
||||
device_vector<AttributeMap> attributes_map;
|
||||
device_vector<float> attributes_float;
|
||||
device_vector<float2> attributes_float2;
|
||||
device_vector<packed_float3> attributes_float3;
|
||||
device_vector<float4> attributes_float4;
|
||||
device_vector<uchar4> attributes_uchar4;
|
||||
|
||||
/* lights */
|
||||
device_vector<KernelLightDistribution> light_distribution;
|
||||
device_vector<KernelLight> lights;
|
||||
device_vector<float2> light_background_marginal_cdf;
|
||||
device_vector<float2> light_background_conditional_cdf;
|
||||
|
||||
/* light tree */
|
||||
device_vector<KernelLightTreeNode> light_tree_nodes;
|
||||
device_vector<KernelLightTreeEmitter> light_tree_emitters;
|
||||
device_vector<uint> light_to_tree;
|
||||
device_vector<uint> object_to_tree;
|
||||
device_vector<uint> object_lookup_offset;
|
||||
device_vector<uint> triangle_to_tree;
|
||||
|
||||
/* particles */
|
||||
device_vector<KernelParticle> particles;
|
||||
|
||||
/* shaders */
|
||||
device_vector<int4> svm_nodes;
|
||||
device_vector<KernelShader> shaders;
|
||||
|
||||
/* lookup tables */
|
||||
device_vector<float> lookup_table;
|
||||
|
||||
/* integrator */
|
||||
device_vector<float> sample_pattern_lut;
|
||||
|
||||
/* IES lights */
|
||||
device_vector<float> ies_lights;
|
||||
|
||||
KernelData data;
|
||||
|
||||
DeviceScene(Device *device);
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __DEVICESCENE_H__ */
|
File diff suppressed because it is too large
Load Diff
@ -30,6 +30,38 @@ class Shader;
|
||||
class Volume;
|
||||
struct PackedBVH;
|
||||
|
||||
/* Set of flags used to help determining what data has been modified or needs reallocation, so we
|
||||
* can decide which device data to free or update. */
|
||||
enum {
|
||||
DEVICE_CURVE_DATA_MODIFIED = (1 << 0),
|
||||
DEVICE_MESH_DATA_MODIFIED = (1 << 1),
|
||||
DEVICE_POINT_DATA_MODIFIED = (1 << 2),
|
||||
|
||||
ATTR_FLOAT_MODIFIED = (1 << 3),
|
||||
ATTR_FLOAT2_MODIFIED = (1 << 4),
|
||||
ATTR_FLOAT3_MODIFIED = (1 << 5),
|
||||
ATTR_FLOAT4_MODIFIED = (1 << 6),
|
||||
ATTR_UCHAR4_MODIFIED = (1 << 7),
|
||||
|
||||
CURVE_DATA_NEED_REALLOC = (1 << 8),
|
||||
MESH_DATA_NEED_REALLOC = (1 << 9),
|
||||
POINT_DATA_NEED_REALLOC = (1 << 10),
|
||||
|
||||
ATTR_FLOAT_NEEDS_REALLOC = (1 << 11),
|
||||
ATTR_FLOAT2_NEEDS_REALLOC = (1 << 12),
|
||||
ATTR_FLOAT3_NEEDS_REALLOC = (1 << 13),
|
||||
ATTR_FLOAT4_NEEDS_REALLOC = (1 << 14),
|
||||
|
||||
ATTR_UCHAR4_NEEDS_REALLOC = (1 << 15),
|
||||
|
||||
ATTRS_NEED_REALLOC = (ATTR_FLOAT_NEEDS_REALLOC | ATTR_FLOAT2_NEEDS_REALLOC |
|
||||
ATTR_FLOAT3_NEEDS_REALLOC | ATTR_FLOAT4_NEEDS_REALLOC |
|
||||
ATTR_UCHAR4_NEEDS_REALLOC),
|
||||
DEVICE_MESH_DATA_NEEDS_REALLOC = (MESH_DATA_NEED_REALLOC | ATTRS_NEED_REALLOC),
|
||||
DEVICE_POINT_DATA_NEEDS_REALLOC = (POINT_DATA_NEED_REALLOC | ATTRS_NEED_REALLOC),
|
||||
DEVICE_CURVE_DATA_NEEDS_REALLOC = (CURVE_DATA_NEED_REALLOC | ATTRS_NEED_REALLOC),
|
||||
};
|
||||
|
||||
/* Geometry
|
||||
*
|
||||
* Base class for geometric types like Mesh and Hair. */
|
||||
|
722
intern/cycles/scene/geometry_attributes.cpp
Normal file
722
intern/cycles/scene/geometry_attributes.cpp
Normal file
@ -0,0 +1,722 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2011-2022 Blender Foundation */
|
||||
|
||||
#include "bvh/bvh.h"
|
||||
#include "bvh/bvh2.h"
|
||||
|
||||
#include "device/device.h"
|
||||
|
||||
#include "scene/attribute.h"
|
||||
#include "scene/camera.h"
|
||||
#include "scene/geometry.h"
|
||||
#include "scene/hair.h"
|
||||
#include "scene/light.h"
|
||||
#include "scene/mesh.h"
|
||||
#include "scene/object.h"
|
||||
#include "scene/pointcloud.h"
|
||||
#include "scene/scene.h"
|
||||
#include "scene/shader.h"
|
||||
#include "scene/shader_nodes.h"
|
||||
#include "scene/stats.h"
|
||||
#include "scene/volume.h"
|
||||
|
||||
#include "subd/patch_table.h"
|
||||
#include "subd/split.h"
|
||||
|
||||
#include "kernel/osl/globals.h"
|
||||
|
||||
#include "util/foreach.h"
|
||||
#include "util/log.h"
|
||||
#include "util/progress.h"
|
||||
#include "util/task.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
bool Geometry::need_attribute(Scene *scene, AttributeStandard std)
|
||||
{
|
||||
if (std == ATTR_STD_NONE)
|
||||
return false;
|
||||
|
||||
if (scene->need_global_attribute(std))
|
||||
return true;
|
||||
|
||||
foreach (Node *node, used_shaders) {
|
||||
Shader *shader = static_cast<Shader *>(node);
|
||||
if (shader->attributes.find(std))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Geometry::need_attribute(Scene * /*scene*/, ustring name)
|
||||
{
|
||||
if (name == ustring())
|
||||
return false;
|
||||
|
||||
foreach (Node *node, used_shaders) {
|
||||
Shader *shader = static_cast<Shader *>(node);
|
||||
if (shader->attributes.find(name))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
AttributeRequestSet Geometry::needed_attributes()
|
||||
{
|
||||
AttributeRequestSet result;
|
||||
|
||||
foreach (Node *node, used_shaders) {
|
||||
Shader *shader = static_cast<Shader *>(node);
|
||||
result.add(shader->attributes);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Geometry::has_voxel_attributes() const
|
||||
{
|
||||
foreach (const Attribute &attr, attributes.attributes) {
|
||||
if (attr.element == ATTR_ELEMENT_VOXEL) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Generate a normal attribute map entry from an attribute descriptor. */
|
||||
static void emit_attribute_map_entry(AttributeMap *attr_map,
|
||||
size_t index,
|
||||
uint64_t id,
|
||||
TypeDesc type,
|
||||
const AttributeDescriptor &desc)
|
||||
{
|
||||
attr_map[index].id = id;
|
||||
attr_map[index].element = desc.element;
|
||||
attr_map[index].offset = as_uint(desc.offset);
|
||||
|
||||
if (type == TypeDesc::TypeFloat)
|
||||
attr_map[index].type = NODE_ATTR_FLOAT;
|
||||
else if (type == TypeDesc::TypeMatrix)
|
||||
attr_map[index].type = NODE_ATTR_MATRIX;
|
||||
else if (type == TypeFloat2)
|
||||
attr_map[index].type = NODE_ATTR_FLOAT2;
|
||||
else if (type == TypeFloat4)
|
||||
attr_map[index].type = NODE_ATTR_FLOAT4;
|
||||
else if (type == TypeRGBA)
|
||||
attr_map[index].type = NODE_ATTR_RGBA;
|
||||
else
|
||||
attr_map[index].type = NODE_ATTR_FLOAT3;
|
||||
|
||||
attr_map[index].flags = desc.flags;
|
||||
}
|
||||
|
||||
/* Generate an attribute map end marker, optionally including a link to another map.
|
||||
* Links are used to connect object attribute maps to mesh attribute maps. */
|
||||
static void emit_attribute_map_terminator(AttributeMap *attr_map,
|
||||
size_t index,
|
||||
bool chain,
|
||||
uint chain_link)
|
||||
{
|
||||
for (int j = 0; j < ATTR_PRIM_TYPES; j++) {
|
||||
attr_map[index + j].id = ATTR_STD_NONE;
|
||||
attr_map[index + j].element = chain; /* link is valid flag */
|
||||
attr_map[index + j].offset = chain ? chain_link + j : 0; /* link to the correct sub-entry */
|
||||
attr_map[index + j].type = 0;
|
||||
attr_map[index + j].flags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate all necessary attribute map entries from the attribute request. */
|
||||
static void emit_attribute_mapping(
|
||||
AttributeMap *attr_map, size_t index, uint64_t id, AttributeRequest &req, Geometry *geom)
|
||||
{
|
||||
emit_attribute_map_entry(attr_map, index, id, req.type, req.desc);
|
||||
|
||||
if (geom->is_mesh()) {
|
||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||
if (mesh->get_num_subd_faces()) {
|
||||
emit_attribute_map_entry(attr_map, index + 1, id, req.subd_type, req.subd_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GeometryManager::update_svm_attributes(Device *,
|
||||
DeviceScene *dscene,
|
||||
Scene *scene,
|
||||
vector<AttributeRequestSet> &geom_attributes,
|
||||
vector<AttributeRequestSet> &object_attributes)
|
||||
{
|
||||
/* for SVM, the attributes_map table is used to lookup the offset of an
|
||||
* attribute, based on a unique shader attribute id. */
|
||||
|
||||
/* compute array stride */
|
||||
size_t attr_map_size = 0;
|
||||
|
||||
for (size_t i = 0; i < scene->geometry.size(); i++) {
|
||||
Geometry *geom = scene->geometry[i];
|
||||
geom->attr_map_offset = attr_map_size;
|
||||
|
||||
#ifdef WITH_OSL
|
||||
size_t attr_count = 0;
|
||||
foreach (AttributeRequest &req, geom_attributes[i].requests) {
|
||||
if (req.std != ATTR_STD_NONE &&
|
||||
scene->shader_manager->get_attribute_id(req.std) != (uint64_t)req.std)
|
||||
attr_count += 2;
|
||||
else
|
||||
attr_count += 1;
|
||||
}
|
||||
#else
|
||||
const size_t attr_count = geom_attributes[i].size();
|
||||
#endif
|
||||
|
||||
attr_map_size += (attr_count + 1) * ATTR_PRIM_TYPES;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < scene->objects.size(); i++) {
|
||||
Object *object = scene->objects[i];
|
||||
|
||||
/* only allocate a table for the object if it actually has attributes */
|
||||
if (object_attributes[i].size() == 0) {
|
||||
object->attr_map_offset = 0;
|
||||
}
|
||||
else {
|
||||
object->attr_map_offset = attr_map_size;
|
||||
attr_map_size += (object_attributes[i].size() + 1) * ATTR_PRIM_TYPES;
|
||||
}
|
||||
}
|
||||
|
||||
if (attr_map_size == 0)
|
||||
return;
|
||||
|
||||
if (!dscene->attributes_map.need_realloc()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* create attribute map */
|
||||
AttributeMap *attr_map = dscene->attributes_map.alloc(attr_map_size);
|
||||
memset(attr_map, 0, dscene->attributes_map.size() * sizeof(*attr_map));
|
||||
|
||||
for (size_t i = 0; i < scene->geometry.size(); i++) {
|
||||
Geometry *geom = scene->geometry[i];
|
||||
AttributeRequestSet &attributes = geom_attributes[i];
|
||||
|
||||
/* set geometry attributes */
|
||||
size_t index = geom->attr_map_offset;
|
||||
|
||||
foreach (AttributeRequest &req, attributes.requests) {
|
||||
uint64_t id;
|
||||
if (req.std == ATTR_STD_NONE)
|
||||
id = scene->shader_manager->get_attribute_id(req.name);
|
||||
else
|
||||
id = scene->shader_manager->get_attribute_id(req.std);
|
||||
|
||||
emit_attribute_mapping(attr_map, index, id, req, geom);
|
||||
index += ATTR_PRIM_TYPES;
|
||||
|
||||
#ifdef WITH_OSL
|
||||
/* Some standard attributes are explicitly referenced via their standard ID, so add those
|
||||
* again in case they were added under a different attribute ID. */
|
||||
if (req.std != ATTR_STD_NONE && id != (uint64_t)req.std) {
|
||||
emit_attribute_mapping(attr_map, index, (uint64_t)req.std, req, geom);
|
||||
index += ATTR_PRIM_TYPES;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
emit_attribute_map_terminator(attr_map, index, false, 0);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < scene->objects.size(); i++) {
|
||||
Object *object = scene->objects[i];
|
||||
AttributeRequestSet &attributes = object_attributes[i];
|
||||
|
||||
/* set object attributes */
|
||||
if (attributes.size() > 0) {
|
||||
size_t index = object->attr_map_offset;
|
||||
|
||||
foreach (AttributeRequest &req, attributes.requests) {
|
||||
uint64_t id;
|
||||
if (req.std == ATTR_STD_NONE)
|
||||
id = scene->shader_manager->get_attribute_id(req.name);
|
||||
else
|
||||
id = scene->shader_manager->get_attribute_id(req.std);
|
||||
|
||||
emit_attribute_mapping(attr_map, index, id, req, object->geometry);
|
||||
index += ATTR_PRIM_TYPES;
|
||||
}
|
||||
|
||||
emit_attribute_map_terminator(attr_map, index, true, object->geometry->attr_map_offset);
|
||||
}
|
||||
}
|
||||
|
||||
/* copy to device */
|
||||
dscene->attributes_map.copy_to_device();
|
||||
}
|
||||
|
||||
void GeometryManager::update_attribute_element_offset(Geometry *geom,
|
||||
device_vector<float> &attr_float,
|
||||
size_t &attr_float_offset,
|
||||
device_vector<float2> &attr_float2,
|
||||
size_t &attr_float2_offset,
|
||||
device_vector<packed_float3> &attr_float3,
|
||||
size_t &attr_float3_offset,
|
||||
device_vector<float4> &attr_float4,
|
||||
size_t &attr_float4_offset,
|
||||
device_vector<uchar4> &attr_uchar4,
|
||||
size_t &attr_uchar4_offset,
|
||||
Attribute *mattr,
|
||||
AttributePrimitive prim,
|
||||
TypeDesc &type,
|
||||
AttributeDescriptor &desc)
|
||||
{
|
||||
if (mattr) {
|
||||
/* store element and type */
|
||||
desc.element = mattr->element;
|
||||
desc.flags = mattr->flags;
|
||||
type = mattr->type;
|
||||
|
||||
/* store attribute data in arrays */
|
||||
size_t size = mattr->element_size(geom, prim);
|
||||
|
||||
AttributeElement &element = desc.element;
|
||||
int &offset = desc.offset;
|
||||
|
||||
if (mattr->element == ATTR_ELEMENT_VOXEL) {
|
||||
/* store slot in offset value */
|
||||
ImageHandle &handle = mattr->data_voxel();
|
||||
offset = handle.svm_slot();
|
||||
}
|
||||
else if (mattr->element == ATTR_ELEMENT_CORNER_BYTE) {
|
||||
uchar4 *data = mattr->data_uchar4();
|
||||
offset = attr_uchar4_offset;
|
||||
|
||||
assert(attr_uchar4.size() >= offset + size);
|
||||
if (mattr->modified) {
|
||||
for (size_t k = 0; k < size; k++) {
|
||||
attr_uchar4[offset + k] = data[k];
|
||||
}
|
||||
attr_uchar4.tag_modified();
|
||||
}
|
||||
attr_uchar4_offset += size;
|
||||
}
|
||||
else if (mattr->type == TypeDesc::TypeFloat) {
|
||||
float *data = mattr->data_float();
|
||||
offset = attr_float_offset;
|
||||
|
||||
assert(attr_float.size() >= offset + size);
|
||||
if (mattr->modified) {
|
||||
for (size_t k = 0; k < size; k++) {
|
||||
attr_float[offset + k] = data[k];
|
||||
}
|
||||
attr_float.tag_modified();
|
||||
}
|
||||
attr_float_offset += size;
|
||||
}
|
||||
else if (mattr->type == TypeFloat2) {
|
||||
float2 *data = mattr->data_float2();
|
||||
offset = attr_float2_offset;
|
||||
|
||||
assert(attr_float2.size() >= offset + size);
|
||||
if (mattr->modified) {
|
||||
for (size_t k = 0; k < size; k++) {
|
||||
attr_float2[offset + k] = data[k];
|
||||
}
|
||||
attr_float2.tag_modified();
|
||||
}
|
||||
attr_float2_offset += size;
|
||||
}
|
||||
else if (mattr->type == TypeDesc::TypeMatrix) {
|
||||
Transform *tfm = mattr->data_transform();
|
||||
offset = attr_float4_offset;
|
||||
|
||||
assert(attr_float4.size() >= offset + size * 3);
|
||||
if (mattr->modified) {
|
||||
for (size_t k = 0; k < size * 3; k++) {
|
||||
attr_float4[offset + k] = (&tfm->x)[k];
|
||||
}
|
||||
attr_float4.tag_modified();
|
||||
}
|
||||
attr_float4_offset += size * 3;
|
||||
}
|
||||
else if (mattr->type == TypeFloat4 || mattr->type == TypeRGBA) {
|
||||
float4 *data = mattr->data_float4();
|
||||
offset = attr_float4_offset;
|
||||
|
||||
assert(attr_float4.size() >= offset + size);
|
||||
if (mattr->modified) {
|
||||
for (size_t k = 0; k < size; k++) {
|
||||
attr_float4[offset + k] = data[k];
|
||||
}
|
||||
attr_float4.tag_modified();
|
||||
}
|
||||
attr_float4_offset += size;
|
||||
}
|
||||
else {
|
||||
float3 *data = mattr->data_float3();
|
||||
offset = attr_float3_offset;
|
||||
|
||||
assert(attr_float3.size() >= offset + size);
|
||||
if (mattr->modified) {
|
||||
for (size_t k = 0; k < size; k++) {
|
||||
attr_float3[offset + k] = data[k];
|
||||
}
|
||||
attr_float3.tag_modified();
|
||||
}
|
||||
attr_float3_offset += size;
|
||||
}
|
||||
|
||||
/* mesh vertex/curve index is global, not per object, so we sneak
|
||||
* a correction for that in here */
|
||||
if (geom->is_mesh()) {
|
||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||
if (mesh->subdivision_type == Mesh::SUBDIVISION_CATMULL_CLARK &&
|
||||
desc.flags & ATTR_SUBDIVIDED) {
|
||||
/* Indices for subdivided attributes are retrieved
|
||||
* from patch table so no need for correction here. */
|
||||
}
|
||||
else if (element == ATTR_ELEMENT_VERTEX)
|
||||
offset -= mesh->vert_offset;
|
||||
else if (element == ATTR_ELEMENT_VERTEX_MOTION)
|
||||
offset -= mesh->vert_offset;
|
||||
else if (element == ATTR_ELEMENT_FACE) {
|
||||
if (prim == ATTR_PRIM_GEOMETRY)
|
||||
offset -= mesh->prim_offset;
|
||||
else
|
||||
offset -= mesh->face_offset;
|
||||
}
|
||||
else if (element == ATTR_ELEMENT_CORNER || element == ATTR_ELEMENT_CORNER_BYTE) {
|
||||
if (prim == ATTR_PRIM_GEOMETRY)
|
||||
offset -= 3 * mesh->prim_offset;
|
||||
else
|
||||
offset -= mesh->corner_offset;
|
||||
}
|
||||
}
|
||||
else if (geom->is_hair()) {
|
||||
Hair *hair = static_cast<Hair *>(geom);
|
||||
if (element == ATTR_ELEMENT_CURVE)
|
||||
offset -= hair->prim_offset;
|
||||
else if (element == ATTR_ELEMENT_CURVE_KEY)
|
||||
offset -= hair->curve_key_offset;
|
||||
else if (element == ATTR_ELEMENT_CURVE_KEY_MOTION)
|
||||
offset -= hair->curve_key_offset;
|
||||
}
|
||||
else if (geom->is_pointcloud()) {
|
||||
if (element == ATTR_ELEMENT_VERTEX)
|
||||
offset -= geom->prim_offset;
|
||||
else if (element == ATTR_ELEMENT_VERTEX_MOTION)
|
||||
offset -= geom->prim_offset;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* attribute not found */
|
||||
desc.element = ATTR_ELEMENT_NONE;
|
||||
desc.offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (mattr) {
|
||||
size_t size = mattr->element_size(geom, prim);
|
||||
|
||||
if (mattr->element == ATTR_ELEMENT_VOXEL) {
|
||||
/* pass */
|
||||
}
|
||||
else if (mattr->element == ATTR_ELEMENT_CORNER_BYTE) {
|
||||
*attr_uchar4_size += size;
|
||||
}
|
||||
else if (mattr->type == TypeDesc::TypeFloat) {
|
||||
*attr_float_size += size;
|
||||
}
|
||||
else if (mattr->type == TypeFloat2) {
|
||||
*attr_float2_size += size;
|
||||
}
|
||||
else if (mattr->type == TypeDesc::TypeMatrix) {
|
||||
*attr_float4_size += size * 4;
|
||||
}
|
||||
else if (mattr->type == TypeFloat4 || mattr->type == TypeRGBA) {
|
||||
*attr_float4_size += size;
|
||||
}
|
||||
else {
|
||||
*attr_float3_size += size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GeometryManager::device_update_attributes(Device *device,
|
||||
DeviceScene *dscene,
|
||||
Scene *scene,
|
||||
Progress &progress)
|
||||
{
|
||||
progress.set_status("Updating Mesh", "Computing attributes");
|
||||
|
||||
/* gather per mesh requested attributes. as meshes may have multiple
|
||||
* shaders assigned, this merges the requested attributes that have
|
||||
* been set per shader by the shader manager */
|
||||
vector<AttributeRequestSet> geom_attributes(scene->geometry.size());
|
||||
|
||||
for (size_t i = 0; i < scene->geometry.size(); i++) {
|
||||
Geometry *geom = scene->geometry[i];
|
||||
|
||||
geom->index = i;
|
||||
scene->need_global_attributes(geom_attributes[i]);
|
||||
|
||||
foreach (Node *node, geom->get_used_shaders()) {
|
||||
Shader *shader = static_cast<Shader *>(node);
|
||||
geom_attributes[i].add(shader->attributes);
|
||||
}
|
||||
|
||||
if (geom->is_hair() && static_cast<Hair *>(geom)->need_shadow_transparency()) {
|
||||
geom_attributes[i].add(ATTR_STD_SHADOW_TRANSPARENCY);
|
||||
}
|
||||
}
|
||||
|
||||
/* convert object attributes to use the same data structures as geometry ones */
|
||||
vector<AttributeRequestSet> object_attributes(scene->objects.size());
|
||||
vector<AttributeSet> object_attribute_values;
|
||||
|
||||
object_attribute_values.reserve(scene->objects.size());
|
||||
|
||||
for (size_t i = 0; i < scene->objects.size(); i++) {
|
||||
Object *object = scene->objects[i];
|
||||
Geometry *geom = object->geometry;
|
||||
size_t geom_idx = geom->index;
|
||||
|
||||
assert(geom_idx < scene->geometry.size() && scene->geometry[geom_idx] == geom);
|
||||
|
||||
object_attribute_values.push_back(AttributeSet(geom, ATTR_PRIM_GEOMETRY));
|
||||
|
||||
AttributeRequestSet &geom_requests = geom_attributes[geom_idx];
|
||||
AttributeRequestSet &attributes = object_attributes[i];
|
||||
AttributeSet &values = object_attribute_values[i];
|
||||
|
||||
for (size_t j = 0; j < object->attributes.size(); j++) {
|
||||
ParamValue ¶m = object->attributes[j];
|
||||
|
||||
/* add attributes that are requested and not already handled by the mesh */
|
||||
if (geom_requests.find(param.name()) && !geom->attributes.find(param.name())) {
|
||||
attributes.add(param.name());
|
||||
|
||||
Attribute *attr = values.add(param.name(), param.type(), ATTR_ELEMENT_OBJECT);
|
||||
assert(param.datasize() == attr->buffer.size());
|
||||
memcpy(attr->buffer.data(), param.data(), param.datasize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* mesh attribute are stored in a single array per data type. here we fill
|
||||
* those arrays, and set the offset and element type to create attribute
|
||||
* maps next */
|
||||
|
||||
/* Pre-allocate attributes to avoid arrays re-allocation which would
|
||||
* take 2x of overall attribute memory usage.
|
||||
*/
|
||||
size_t attr_float_size = 0;
|
||||
size_t attr_float2_size = 0;
|
||||
size_t attr_float3_size = 0;
|
||||
size_t attr_float4_size = 0;
|
||||
size_t attr_uchar4_size = 0;
|
||||
|
||||
for (size_t i = 0; i < scene->geometry.size(); i++) {
|
||||
Geometry *geom = scene->geometry[i];
|
||||
AttributeRequestSet &attributes = geom_attributes[i];
|
||||
foreach (AttributeRequest &req, attributes.requests) {
|
||||
Attribute *attr = geom->attributes.find(req);
|
||||
|
||||
update_attribute_element_size(geom,
|
||||
attr,
|
||||
ATTR_PRIM_GEOMETRY,
|
||||
&attr_float_size,
|
||||
&attr_float2_size,
|
||||
&attr_float3_size,
|
||||
&attr_float4_size,
|
||||
&attr_uchar4_size);
|
||||
|
||||
if (geom->is_mesh()) {
|
||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||
Attribute *subd_attr = mesh->subd_attributes.find(req);
|
||||
|
||||
update_attribute_element_size(mesh,
|
||||
subd_attr,
|
||||
ATTR_PRIM_SUBD,
|
||||
&attr_float_size,
|
||||
&attr_float2_size,
|
||||
&attr_float3_size,
|
||||
&attr_float4_size,
|
||||
&attr_uchar4_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < scene->objects.size(); i++) {
|
||||
Object *object = scene->objects[i];
|
||||
|
||||
foreach (Attribute &attr, object_attribute_values[i].attributes) {
|
||||
update_attribute_element_size(object->geometry,
|
||||
&attr,
|
||||
ATTR_PRIM_GEOMETRY,
|
||||
&attr_float_size,
|
||||
&attr_float2_size,
|
||||
&attr_float3_size,
|
||||
&attr_float4_size,
|
||||
&attr_uchar4_size);
|
||||
}
|
||||
}
|
||||
|
||||
dscene->attributes_float.alloc(attr_float_size);
|
||||
dscene->attributes_float2.alloc(attr_float2_size);
|
||||
dscene->attributes_float3.alloc(attr_float3_size);
|
||||
dscene->attributes_float4.alloc(attr_float4_size);
|
||||
dscene->attributes_uchar4.alloc(attr_uchar4_size);
|
||||
|
||||
/* The order of those flags needs to match that of AttrKernelDataType. */
|
||||
const bool attributes_need_realloc[AttrKernelDataType::NUM] = {
|
||||
dscene->attributes_float.need_realloc(),
|
||||
dscene->attributes_float2.need_realloc(),
|
||||
dscene->attributes_float3.need_realloc(),
|
||||
dscene->attributes_float4.need_realloc(),
|
||||
dscene->attributes_uchar4.need_realloc(),
|
||||
};
|
||||
|
||||
size_t attr_float_offset = 0;
|
||||
size_t attr_float2_offset = 0;
|
||||
size_t attr_float3_offset = 0;
|
||||
size_t attr_float4_offset = 0;
|
||||
size_t attr_uchar4_offset = 0;
|
||||
|
||||
/* Fill in attributes. */
|
||||
for (size_t i = 0; i < scene->geometry.size(); i++) {
|
||||
Geometry *geom = scene->geometry[i];
|
||||
AttributeRequestSet &attributes = geom_attributes[i];
|
||||
|
||||
/* todo: we now store std and name attributes from requests even if
|
||||
* they actually refer to the same mesh attributes, optimize */
|
||||
foreach (AttributeRequest &req, attributes.requests) {
|
||||
Attribute *attr = geom->attributes.find(req);
|
||||
|
||||
if (attr) {
|
||||
/* force a copy if we need to reallocate all the data */
|
||||
attr->modified |= attributes_need_realloc[Attribute::kernel_type(*attr)];
|
||||
}
|
||||
|
||||
update_attribute_element_offset(geom,
|
||||
dscene->attributes_float,
|
||||
attr_float_offset,
|
||||
dscene->attributes_float2,
|
||||
attr_float2_offset,
|
||||
dscene->attributes_float3,
|
||||
attr_float3_offset,
|
||||
dscene->attributes_float4,
|
||||
attr_float4_offset,
|
||||
dscene->attributes_uchar4,
|
||||
attr_uchar4_offset,
|
||||
attr,
|
||||
ATTR_PRIM_GEOMETRY,
|
||||
req.type,
|
||||
req.desc);
|
||||
|
||||
if (geom->is_mesh()) {
|
||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||
Attribute *subd_attr = mesh->subd_attributes.find(req);
|
||||
|
||||
if (subd_attr) {
|
||||
/* force a copy if we need to reallocate all the data */
|
||||
subd_attr->modified |= attributes_need_realloc[Attribute::kernel_type(*subd_attr)];
|
||||
}
|
||||
|
||||
update_attribute_element_offset(mesh,
|
||||
dscene->attributes_float,
|
||||
attr_float_offset,
|
||||
dscene->attributes_float2,
|
||||
attr_float2_offset,
|
||||
dscene->attributes_float3,
|
||||
attr_float3_offset,
|
||||
dscene->attributes_float4,
|
||||
attr_float4_offset,
|
||||
dscene->attributes_uchar4,
|
||||
attr_uchar4_offset,
|
||||
subd_attr,
|
||||
ATTR_PRIM_SUBD,
|
||||
req.subd_type,
|
||||
req.subd_desc);
|
||||
}
|
||||
|
||||
if (progress.get_cancel())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < scene->objects.size(); i++) {
|
||||
Object *object = scene->objects[i];
|
||||
AttributeRequestSet &attributes = object_attributes[i];
|
||||
AttributeSet &values = object_attribute_values[i];
|
||||
|
||||
foreach (AttributeRequest &req, attributes.requests) {
|
||||
Attribute *attr = values.find(req);
|
||||
|
||||
if (attr) {
|
||||
attr->modified |= attributes_need_realloc[Attribute::kernel_type(*attr)];
|
||||
}
|
||||
|
||||
update_attribute_element_offset(object->geometry,
|
||||
dscene->attributes_float,
|
||||
attr_float_offset,
|
||||
dscene->attributes_float2,
|
||||
attr_float2_offset,
|
||||
dscene->attributes_float3,
|
||||
attr_float3_offset,
|
||||
dscene->attributes_float4,
|
||||
attr_float4_offset,
|
||||
dscene->attributes_uchar4,
|
||||
attr_uchar4_offset,
|
||||
attr,
|
||||
ATTR_PRIM_GEOMETRY,
|
||||
req.type,
|
||||
req.desc);
|
||||
|
||||
/* object attributes don't care about subdivision */
|
||||
req.subd_type = req.type;
|
||||
req.subd_desc = req.desc;
|
||||
|
||||
if (progress.get_cancel())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* create attribute lookup maps */
|
||||
if (scene->shader_manager->use_osl())
|
||||
update_osl_globals(device, scene);
|
||||
|
||||
update_svm_attributes(device, dscene, scene, geom_attributes, object_attributes);
|
||||
|
||||
if (progress.get_cancel())
|
||||
return;
|
||||
|
||||
/* copy to device */
|
||||
progress.set_status("Updating Mesh", "Copying Attributes to device");
|
||||
|
||||
dscene->attributes_float.copy_to_device_if_modified();
|
||||
dscene->attributes_float2.copy_to_device_if_modified();
|
||||
dscene->attributes_float3.copy_to_device_if_modified();
|
||||
dscene->attributes_float4.copy_to_device_if_modified();
|
||||
dscene->attributes_uchar4.copy_to_device_if_modified();
|
||||
|
||||
if (progress.get_cancel())
|
||||
return;
|
||||
|
||||
/* After mesh attributes and patch tables have been copied to device memory,
|
||||
* we need to update offsets in the objects. */
|
||||
scene->object_manager->device_update_geom_offsets(device, dscene, scene);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
196
intern/cycles/scene/geometry_bvh.cpp
Normal file
196
intern/cycles/scene/geometry_bvh.cpp
Normal file
@ -0,0 +1,196 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2011-2022 Blender Foundation */
|
||||
|
||||
#include "bvh/bvh.h"
|
||||
#include "bvh/bvh2.h"
|
||||
|
||||
#include "device/device.h"
|
||||
|
||||
#include "scene/attribute.h"
|
||||
#include "scene/camera.h"
|
||||
#include "scene/geometry.h"
|
||||
#include "scene/hair.h"
|
||||
#include "scene/light.h"
|
||||
#include "scene/mesh.h"
|
||||
#include "scene/object.h"
|
||||
#include "scene/pointcloud.h"
|
||||
#include "scene/scene.h"
|
||||
#include "scene/shader.h"
|
||||
#include "scene/shader_nodes.h"
|
||||
#include "scene/stats.h"
|
||||
#include "scene/volume.h"
|
||||
|
||||
#include "subd/patch_table.h"
|
||||
#include "subd/split.h"
|
||||
|
||||
#include "kernel/osl/globals.h"
|
||||
|
||||
#include "util/foreach.h"
|
||||
#include "util/log.h"
|
||||
#include "util/progress.h"
|
||||
#include "util/task.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
void Geometry::compute_bvh(Device *device,
|
||||
DeviceScene *dscene,
|
||||
SceneParams *params,
|
||||
Progress *progress,
|
||||
size_t n,
|
||||
size_t total)
|
||||
{
|
||||
if (progress->get_cancel())
|
||||
return;
|
||||
|
||||
compute_bounds();
|
||||
|
||||
const BVHLayout bvh_layout = BVHParams::best_bvh_layout(
|
||||
params->bvh_layout, device->get_bvh_layout_mask(dscene->data.kernel_features));
|
||||
if (need_build_bvh(bvh_layout)) {
|
||||
string msg = "Updating Geometry BVH ";
|
||||
if (name.empty())
|
||||
msg += string_printf("%u/%u", (uint)(n + 1), (uint)total);
|
||||
else
|
||||
msg += string_printf("%s %u/%u", name.c_str(), (uint)(n + 1), (uint)total);
|
||||
|
||||
Object object;
|
||||
|
||||
/* Ensure all visibility bits are set at the geometry level BVH. In
|
||||
* the object level BVH is where actual visibility is tested. */
|
||||
object.set_is_shadow_catcher(true);
|
||||
object.set_visibility(~0);
|
||||
|
||||
object.set_geometry(this);
|
||||
|
||||
vector<Geometry *> geometry;
|
||||
geometry.push_back(this);
|
||||
vector<Object *> objects;
|
||||
objects.push_back(&object);
|
||||
|
||||
if (bvh && !need_update_rebuild) {
|
||||
progress->set_status(msg, "Refitting BVH");
|
||||
|
||||
bvh->replace_geometry(geometry, objects);
|
||||
|
||||
device->build_bvh(bvh, *progress, true);
|
||||
}
|
||||
else {
|
||||
progress->set_status(msg, "Building BVH");
|
||||
|
||||
BVHParams bparams;
|
||||
bparams.use_spatial_split = params->use_bvh_spatial_split;
|
||||
bparams.use_compact_structure = params->use_bvh_compact_structure;
|
||||
bparams.bvh_layout = bvh_layout;
|
||||
bparams.use_unaligned_nodes = dscene->data.bvh.have_curves &&
|
||||
params->use_bvh_unaligned_nodes;
|
||||
bparams.num_motion_triangle_steps = params->num_bvh_time_steps;
|
||||
bparams.num_motion_curve_steps = params->num_bvh_time_steps;
|
||||
bparams.num_motion_point_steps = params->num_bvh_time_steps;
|
||||
bparams.bvh_type = params->bvh_type;
|
||||
bparams.curve_subdivisions = params->curve_subdivisions();
|
||||
|
||||
delete bvh;
|
||||
bvh = BVH::create(bparams, geometry, objects, device);
|
||||
MEM_GUARDED_CALL(progress, device->build_bvh, bvh, *progress, false);
|
||||
}
|
||||
}
|
||||
|
||||
need_update_rebuild = false;
|
||||
need_update_bvh_for_offset = false;
|
||||
}
|
||||
|
||||
void GeometryManager::device_update_bvh(Device *device,
|
||||
DeviceScene *dscene,
|
||||
Scene *scene,
|
||||
Progress &progress)
|
||||
{
|
||||
/* bvh build */
|
||||
progress.set_status("Updating Scene BVH", "Building");
|
||||
|
||||
BVHParams bparams;
|
||||
bparams.top_level = true;
|
||||
bparams.bvh_layout = BVHParams::best_bvh_layout(
|
||||
scene->params.bvh_layout, device->get_bvh_layout_mask(dscene->data.kernel_features));
|
||||
bparams.use_spatial_split = scene->params.use_bvh_spatial_split;
|
||||
bparams.use_unaligned_nodes = dscene->data.bvh.have_curves &&
|
||||
scene->params.use_bvh_unaligned_nodes;
|
||||
bparams.num_motion_triangle_steps = scene->params.num_bvh_time_steps;
|
||||
bparams.num_motion_curve_steps = scene->params.num_bvh_time_steps;
|
||||
bparams.num_motion_point_steps = scene->params.num_bvh_time_steps;
|
||||
bparams.bvh_type = scene->params.bvh_type;
|
||||
bparams.curve_subdivisions = scene->params.curve_subdivisions();
|
||||
|
||||
VLOG_INFO << "Using " << bvh_layout_name(bparams.bvh_layout) << " layout.";
|
||||
|
||||
const bool can_refit = scene->bvh != nullptr &&
|
||||
(bparams.bvh_layout == BVHLayout::BVH_LAYOUT_OPTIX ||
|
||||
bparams.bvh_layout == BVHLayout::BVH_LAYOUT_METAL);
|
||||
|
||||
BVH *bvh = scene->bvh;
|
||||
if (!scene->bvh) {
|
||||
bvh = scene->bvh = BVH::create(bparams, scene->geometry, scene->objects, device);
|
||||
}
|
||||
|
||||
device->build_bvh(bvh, progress, can_refit);
|
||||
|
||||
if (progress.get_cancel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bool has_bvh2_layout = (bparams.bvh_layout == BVH_LAYOUT_BVH2);
|
||||
|
||||
PackedBVH pack;
|
||||
if (has_bvh2_layout) {
|
||||
pack = std::move(static_cast<BVH2 *>(bvh)->pack);
|
||||
}
|
||||
else {
|
||||
pack.root_index = -1;
|
||||
}
|
||||
|
||||
/* copy to device */
|
||||
progress.set_status("Updating Scene BVH", "Copying BVH to device");
|
||||
|
||||
/* When using BVH2, we always have to copy/update the data as its layout is dependent on the
|
||||
* BVH's leaf nodes which may be different when the objects or vertices move. */
|
||||
|
||||
if (pack.nodes.size()) {
|
||||
dscene->bvh_nodes.steal_data(pack.nodes);
|
||||
dscene->bvh_nodes.copy_to_device();
|
||||
}
|
||||
if (pack.leaf_nodes.size()) {
|
||||
dscene->bvh_leaf_nodes.steal_data(pack.leaf_nodes);
|
||||
dscene->bvh_leaf_nodes.copy_to_device();
|
||||
}
|
||||
if (pack.object_node.size()) {
|
||||
dscene->object_node.steal_data(pack.object_node);
|
||||
dscene->object_node.copy_to_device();
|
||||
}
|
||||
if (pack.prim_type.size()) {
|
||||
dscene->prim_type.steal_data(pack.prim_type);
|
||||
dscene->prim_type.copy_to_device();
|
||||
}
|
||||
if (pack.prim_visibility.size()) {
|
||||
dscene->prim_visibility.steal_data(pack.prim_visibility);
|
||||
dscene->prim_visibility.copy_to_device();
|
||||
}
|
||||
if (pack.prim_index.size()) {
|
||||
dscene->prim_index.steal_data(pack.prim_index);
|
||||
dscene->prim_index.copy_to_device();
|
||||
}
|
||||
if (pack.prim_object.size()) {
|
||||
dscene->prim_object.steal_data(pack.prim_object);
|
||||
dscene->prim_object.copy_to_device();
|
||||
}
|
||||
if (pack.prim_time.size()) {
|
||||
dscene->prim_time.steal_data(pack.prim_time);
|
||||
dscene->prim_time.copy_to_device();
|
||||
}
|
||||
|
||||
dscene->data.bvh.root = pack.root_index;
|
||||
dscene->data.bvh.use_bvh_steps = (scene->params.num_bvh_time_steps != 0);
|
||||
dscene->data.bvh.curve_subdivisions = scene->params.curve_subdivisions();
|
||||
/* The scene handle is set in 'CPUDevice::const_copy_to' and 'OptiXDevice::const_copy_to' */
|
||||
dscene->data.device_bvh = 0;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
223
intern/cycles/scene/geometry_mesh.cpp
Normal file
223
intern/cycles/scene/geometry_mesh.cpp
Normal file
@ -0,0 +1,223 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2011-2022 Blender Foundation */
|
||||
|
||||
#include "bvh/bvh.h"
|
||||
#include "bvh/bvh2.h"
|
||||
|
||||
#include "device/device.h"
|
||||
|
||||
#include "scene/attribute.h"
|
||||
#include "scene/camera.h"
|
||||
#include "scene/geometry.h"
|
||||
#include "scene/hair.h"
|
||||
#include "scene/light.h"
|
||||
#include "scene/mesh.h"
|
||||
#include "scene/object.h"
|
||||
#include "scene/osl.h"
|
||||
#include "scene/pointcloud.h"
|
||||
#include "scene/scene.h"
|
||||
#include "scene/shader.h"
|
||||
#include "scene/shader_nodes.h"
|
||||
#include "scene/stats.h"
|
||||
#include "scene/volume.h"
|
||||
|
||||
#include "subd/patch_table.h"
|
||||
#include "subd/split.h"
|
||||
|
||||
#ifdef WITH_OSL
|
||||
# include "kernel/osl/globals.h"
|
||||
#endif
|
||||
|
||||
#include "util/foreach.h"
|
||||
#include "util/log.h"
|
||||
#include "util/progress.h"
|
||||
#include "util/task.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
void GeometryManager::device_update_mesh(Device *,
|
||||
DeviceScene *dscene,
|
||||
Scene *scene,
|
||||
Progress &progress)
|
||||
{
|
||||
/* Count. */
|
||||
size_t vert_size = 0;
|
||||
size_t tri_size = 0;
|
||||
|
||||
size_t curve_key_size = 0;
|
||||
size_t curve_size = 0;
|
||||
size_t curve_segment_size = 0;
|
||||
|
||||
size_t point_size = 0;
|
||||
|
||||
size_t patch_size = 0;
|
||||
|
||||
foreach (Geometry *geom, scene->geometry) {
|
||||
if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) {
|
||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||
|
||||
vert_size += mesh->verts.size();
|
||||
tri_size += mesh->num_triangles();
|
||||
|
||||
if (mesh->get_num_subd_faces()) {
|
||||
Mesh::SubdFace last = mesh->get_subd_face(mesh->get_num_subd_faces() - 1);
|
||||
patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8;
|
||||
|
||||
/* patch tables are stored in same array so include them in patch_size */
|
||||
if (mesh->patch_table) {
|
||||
mesh->patch_table_offset = patch_size;
|
||||
patch_size += mesh->patch_table->total_size();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (geom->is_hair()) {
|
||||
Hair *hair = static_cast<Hair *>(geom);
|
||||
|
||||
curve_key_size += hair->get_curve_keys().size();
|
||||
curve_size += hair->num_curves();
|
||||
curve_segment_size += hair->num_segments();
|
||||
}
|
||||
else if (geom->is_pointcloud()) {
|
||||
PointCloud *pointcloud = static_cast<PointCloud *>(geom);
|
||||
point_size += pointcloud->num_points();
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill in all the arrays. */
|
||||
if (tri_size != 0) {
|
||||
/* normals */
|
||||
progress.set_status("Updating Mesh", "Computing normals");
|
||||
|
||||
packed_float3 *tri_verts = dscene->tri_verts.alloc(vert_size);
|
||||
uint *tri_shader = dscene->tri_shader.alloc(tri_size);
|
||||
packed_float3 *vnormal = dscene->tri_vnormal.alloc(vert_size);
|
||||
packed_uint3 *tri_vindex = dscene->tri_vindex.alloc(tri_size);
|
||||
uint *tri_patch = dscene->tri_patch.alloc(tri_size);
|
||||
float2 *tri_patch_uv = dscene->tri_patch_uv.alloc(vert_size);
|
||||
|
||||
const bool copy_all_data = dscene->tri_shader.need_realloc() ||
|
||||
dscene->tri_vindex.need_realloc() ||
|
||||
dscene->tri_vnormal.need_realloc() ||
|
||||
dscene->tri_patch.need_realloc() ||
|
||||
dscene->tri_patch_uv.need_realloc();
|
||||
|
||||
foreach (Geometry *geom, scene->geometry) {
|
||||
if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) {
|
||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||
|
||||
if (mesh->shader_is_modified() || mesh->smooth_is_modified() ||
|
||||
mesh->triangles_is_modified() || copy_all_data) {
|
||||
mesh->pack_shaders(scene, &tri_shader[mesh->prim_offset]);
|
||||
}
|
||||
|
||||
if (mesh->verts_is_modified() || copy_all_data) {
|
||||
mesh->pack_normals(&vnormal[mesh->vert_offset]);
|
||||
}
|
||||
|
||||
if (mesh->verts_is_modified() || mesh->triangles_is_modified() ||
|
||||
mesh->vert_patch_uv_is_modified() || copy_all_data) {
|
||||
mesh->pack_verts(&tri_verts[mesh->vert_offset],
|
||||
&tri_vindex[mesh->prim_offset],
|
||||
&tri_patch[mesh->prim_offset],
|
||||
&tri_patch_uv[mesh->vert_offset]);
|
||||
}
|
||||
|
||||
if (progress.get_cancel())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* vertex coordinates */
|
||||
progress.set_status("Updating Mesh", "Copying Mesh to device");
|
||||
|
||||
dscene->tri_verts.copy_to_device_if_modified();
|
||||
dscene->tri_shader.copy_to_device_if_modified();
|
||||
dscene->tri_vnormal.copy_to_device_if_modified();
|
||||
dscene->tri_vindex.copy_to_device_if_modified();
|
||||
dscene->tri_patch.copy_to_device_if_modified();
|
||||
dscene->tri_patch_uv.copy_to_device_if_modified();
|
||||
}
|
||||
|
||||
if (curve_segment_size != 0) {
|
||||
progress.set_status("Updating Mesh", "Copying Curves to device");
|
||||
|
||||
float4 *curve_keys = dscene->curve_keys.alloc(curve_key_size);
|
||||
KernelCurve *curves = dscene->curves.alloc(curve_size);
|
||||
KernelCurveSegment *curve_segments = dscene->curve_segments.alloc(curve_segment_size);
|
||||
|
||||
const bool copy_all_data = dscene->curve_keys.need_realloc() ||
|
||||
dscene->curves.need_realloc() ||
|
||||
dscene->curve_segments.need_realloc();
|
||||
|
||||
foreach (Geometry *geom, scene->geometry) {
|
||||
if (geom->is_hair()) {
|
||||
Hair *hair = static_cast<Hair *>(geom);
|
||||
|
||||
bool curve_keys_co_modified = hair->curve_radius_is_modified() ||
|
||||
hair->curve_keys_is_modified();
|
||||
bool curve_data_modified = hair->curve_shader_is_modified() ||
|
||||
hair->curve_first_key_is_modified();
|
||||
|
||||
if (!curve_keys_co_modified && !curve_data_modified && !copy_all_data) {
|
||||
continue;
|
||||
}
|
||||
|
||||
hair->pack_curves(scene,
|
||||
&curve_keys[hair->curve_key_offset],
|
||||
&curves[hair->prim_offset],
|
||||
&curve_segments[hair->curve_segment_offset]);
|
||||
if (progress.get_cancel())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dscene->curve_keys.copy_to_device_if_modified();
|
||||
dscene->curves.copy_to_device_if_modified();
|
||||
dscene->curve_segments.copy_to_device_if_modified();
|
||||
}
|
||||
|
||||
if (point_size != 0) {
|
||||
progress.set_status("Updating Mesh", "Copying Point clouds to device");
|
||||
|
||||
float4 *points = dscene->points.alloc(point_size);
|
||||
uint *points_shader = dscene->points_shader.alloc(point_size);
|
||||
|
||||
foreach (Geometry *geom, scene->geometry) {
|
||||
if (geom->is_pointcloud()) {
|
||||
PointCloud *pointcloud = static_cast<PointCloud *>(geom);
|
||||
pointcloud->pack(
|
||||
scene, &points[pointcloud->prim_offset], &points_shader[pointcloud->prim_offset]);
|
||||
if (progress.get_cancel())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dscene->points.copy_to_device();
|
||||
dscene->points_shader.copy_to_device();
|
||||
}
|
||||
|
||||
if (patch_size != 0 && dscene->patches.need_realloc()) {
|
||||
progress.set_status("Updating Mesh", "Copying Patches to device");
|
||||
|
||||
uint *patch_data = dscene->patches.alloc(patch_size);
|
||||
|
||||
foreach (Geometry *geom, scene->geometry) {
|
||||
if (geom->is_mesh()) {
|
||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||
mesh->pack_patches(&patch_data[mesh->patch_offset]);
|
||||
|
||||
if (mesh->patch_table) {
|
||||
mesh->patch_table->copy_adjusting_offsets(&patch_data[mesh->patch_table_offset],
|
||||
mesh->patch_table_offset);
|
||||
}
|
||||
|
||||
if (progress.get_cancel())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dscene->patches.copy_to_device();
|
||||
}
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
@ -24,6 +24,7 @@
|
||||
#include "scene/svm.h"
|
||||
#include "scene/tables.h"
|
||||
#include "scene/volume.h"
|
||||
#include "scene/devicescene.h"
|
||||
#include "session/session.h"
|
||||
|
||||
#include "util/foreach.h"
|
||||
@ -33,59 +34,7 @@
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
DeviceScene::DeviceScene(Device *device)
|
||||
: bvh_nodes(device, "bvh_nodes", MEM_GLOBAL),
|
||||
bvh_leaf_nodes(device, "bvh_leaf_nodes", MEM_GLOBAL),
|
||||
object_node(device, "object_node", MEM_GLOBAL),
|
||||
prim_type(device, "prim_type", MEM_GLOBAL),
|
||||
prim_visibility(device, "prim_visibility", MEM_GLOBAL),
|
||||
prim_index(device, "prim_index", MEM_GLOBAL),
|
||||
prim_object(device, "prim_object", MEM_GLOBAL),
|
||||
prim_time(device, "prim_time", MEM_GLOBAL),
|
||||
tri_verts(device, "tri_verts", MEM_GLOBAL),
|
||||
tri_shader(device, "tri_shader", MEM_GLOBAL),
|
||||
tri_vnormal(device, "tri_vnormal", MEM_GLOBAL),
|
||||
tri_vindex(device, "tri_vindex", MEM_GLOBAL),
|
||||
tri_patch(device, "tri_patch", MEM_GLOBAL),
|
||||
tri_patch_uv(device, "tri_patch_uv", MEM_GLOBAL),
|
||||
curves(device, "curves", MEM_GLOBAL),
|
||||
curve_keys(device, "curve_keys", MEM_GLOBAL),
|
||||
curve_segments(device, "curve_segments", MEM_GLOBAL),
|
||||
patches(device, "patches", MEM_GLOBAL),
|
||||
points(device, "points", MEM_GLOBAL),
|
||||
points_shader(device, "points_shader", MEM_GLOBAL),
|
||||
objects(device, "objects", MEM_GLOBAL),
|
||||
object_motion_pass(device, "object_motion_pass", MEM_GLOBAL),
|
||||
object_motion(device, "object_motion", MEM_GLOBAL),
|
||||
object_flag(device, "object_flag", MEM_GLOBAL),
|
||||
object_volume_step(device, "object_volume_step", MEM_GLOBAL),
|
||||
object_prim_offset(device, "object_prim_offset", MEM_GLOBAL),
|
||||
camera_motion(device, "camera_motion", MEM_GLOBAL),
|
||||
attributes_map(device, "attributes_map", MEM_GLOBAL),
|
||||
attributes_float(device, "attributes_float", MEM_GLOBAL),
|
||||
attributes_float2(device, "attributes_float2", MEM_GLOBAL),
|
||||
attributes_float3(device, "attributes_float3", MEM_GLOBAL),
|
||||
attributes_float4(device, "attributes_float4", MEM_GLOBAL),
|
||||
attributes_uchar4(device, "attributes_uchar4", MEM_GLOBAL),
|
||||
light_distribution(device, "light_distribution", MEM_GLOBAL),
|
||||
lights(device, "lights", MEM_GLOBAL),
|
||||
light_background_marginal_cdf(device, "light_background_marginal_cdf", MEM_GLOBAL),
|
||||
light_background_conditional_cdf(device, "light_background_conditional_cdf", MEM_GLOBAL),
|
||||
light_tree_nodes(device, "light_tree_nodes", MEM_GLOBAL),
|
||||
light_tree_emitters(device, "light_tree_emitters", MEM_GLOBAL),
|
||||
light_to_tree(device, "light_to_tree", MEM_GLOBAL),
|
||||
object_to_tree(device, "object_to_tree", MEM_GLOBAL),
|
||||
object_lookup_offset(device, "object_lookup_offset", MEM_GLOBAL),
|
||||
triangle_to_tree(device, "triangle_to_tree", MEM_GLOBAL),
|
||||
particles(device, "particles", MEM_GLOBAL),
|
||||
svm_nodes(device, "svm_nodes", MEM_GLOBAL),
|
||||
shaders(device, "shaders", MEM_GLOBAL),
|
||||
lookup_table(device, "lookup_table", MEM_GLOBAL),
|
||||
sample_pattern_lut(device, "sample_pattern_lut", MEM_GLOBAL),
|
||||
ies_lights(device, "ies", MEM_GLOBAL)
|
||||
{
|
||||
memset((void *)&data, 0, sizeof(data));
|
||||
}
|
||||
|
||||
|
||||
Scene::Scene(const SceneParams ¶ms_, Device *device)
|
||||
: name("Scene"),
|
||||
|
@ -6,20 +6,16 @@
|
||||
|
||||
#include "bvh/params.h"
|
||||
|
||||
#include "scene/devicescene.h"
|
||||
#include "scene/film.h"
|
||||
#include "scene/image.h"
|
||||
#include "scene/shader.h"
|
||||
|
||||
#include "device/device.h"
|
||||
#include "device/memory.h"
|
||||
|
||||
#include "util/param.h"
|
||||
#include "util/string.h"
|
||||
#include "util/system.h"
|
||||
#include "util/texture.h"
|
||||
#include "util/thread.h"
|
||||
#include "util/types.h"
|
||||
#include "util/vector.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
@ -54,92 +50,6 @@ class RenderStats;
|
||||
class SceneUpdateStats;
|
||||
class Volume;
|
||||
|
||||
/* Scene Device Data */
|
||||
|
||||
class DeviceScene {
|
||||
public:
|
||||
/* BVH */
|
||||
device_vector<int4> bvh_nodes;
|
||||
device_vector<int4> bvh_leaf_nodes;
|
||||
device_vector<int> object_node;
|
||||
device_vector<int> prim_type;
|
||||
device_vector<uint> prim_visibility;
|
||||
device_vector<int> prim_index;
|
||||
device_vector<int> prim_object;
|
||||
device_vector<float2> prim_time;
|
||||
|
||||
/* mesh */
|
||||
device_vector<packed_float3> tri_verts;
|
||||
device_vector<uint> tri_shader;
|
||||
device_vector<packed_float3> tri_vnormal;
|
||||
device_vector<packed_uint3> tri_vindex;
|
||||
device_vector<uint> tri_patch;
|
||||
device_vector<float2> tri_patch_uv;
|
||||
|
||||
device_vector<KernelCurve> curves;
|
||||
device_vector<float4> curve_keys;
|
||||
device_vector<KernelCurveSegment> curve_segments;
|
||||
|
||||
device_vector<uint> patches;
|
||||
|
||||
/* point-cloud */
|
||||
device_vector<float4> points;
|
||||
device_vector<uint> points_shader;
|
||||
|
||||
/* objects */
|
||||
device_vector<KernelObject> objects;
|
||||
device_vector<Transform> object_motion_pass;
|
||||
device_vector<DecomposedTransform> object_motion;
|
||||
device_vector<uint> object_flag;
|
||||
device_vector<float> object_volume_step;
|
||||
device_vector<uint> object_prim_offset;
|
||||
|
||||
/* cameras */
|
||||
device_vector<DecomposedTransform> camera_motion;
|
||||
|
||||
/* attributes */
|
||||
device_vector<AttributeMap> attributes_map;
|
||||
device_vector<float> attributes_float;
|
||||
device_vector<float2> attributes_float2;
|
||||
device_vector<packed_float3> attributes_float3;
|
||||
device_vector<float4> attributes_float4;
|
||||
device_vector<uchar4> attributes_uchar4;
|
||||
|
||||
/* lights */
|
||||
device_vector<KernelLightDistribution> light_distribution;
|
||||
device_vector<KernelLight> lights;
|
||||
device_vector<float2> light_background_marginal_cdf;
|
||||
device_vector<float2> light_background_conditional_cdf;
|
||||
|
||||
/* light tree */
|
||||
device_vector<KernelLightTreeNode> light_tree_nodes;
|
||||
device_vector<KernelLightTreeEmitter> light_tree_emitters;
|
||||
device_vector<uint> light_to_tree;
|
||||
device_vector<uint> object_to_tree;
|
||||
device_vector<uint> object_lookup_offset;
|
||||
device_vector<uint> triangle_to_tree;
|
||||
|
||||
/* particles */
|
||||
device_vector<KernelParticle> particles;
|
||||
|
||||
/* shaders */
|
||||
device_vector<int4> svm_nodes;
|
||||
device_vector<KernelShader> shaders;
|
||||
|
||||
/* lookup tables */
|
||||
device_vector<float> lookup_table;
|
||||
|
||||
/* integrator */
|
||||
device_vector<float> sample_pattern_lut;
|
||||
|
||||
/* IES lights */
|
||||
device_vector<float> ies_lights;
|
||||
|
||||
KernelData data;
|
||||
|
||||
DeviceScene(Device *device);
|
||||
};
|
||||
|
||||
/* Scene Parameters */
|
||||
|
||||
class SceneParams {
|
||||
|
Loading…
Reference in New Issue
Block a user