Merge branch 'blender-v4.2-release'

This commit is contained in:
Brecht Van Lommel
2024-06-26 21:30:39 +02:00
8 changed files with 196 additions and 238 deletions

View File

@@ -395,7 +395,7 @@ if(WITH_CYCLES_DEBUG_NAN)
add_definitions(-DWITH_CYCLES_DEBUG_NAN)
endif()
if(NOT OPENIMAGEIO_PUGIXML_FOUND)
if((NOT OPENIMAGEIO_PUGIXML_FOUND) OR WIN32)
add_definitions(-DWITH_SYSTEM_PUGIXML)
endif()
@@ -473,5 +473,9 @@ if(WITH_CYCLES_HYDRA_RENDER_DELEGATE OR (WITH_CYCLES_STANDALONE AND WITH_USD))
endif()
if(NOT WITH_BLENDER)
delayed_do_install(${CMAKE_BINARY_DIR}/bin)
if(CYCLES_STANDALONE_REPOSITORY)
delayed_do_install()
else()
delayed_do_install(${CMAKE_BINARY_DIR}/bin)
endif()
endif()

View File

@@ -108,17 +108,29 @@ if(WITH_CYCLES_STANDALONE)
endif()
endif()
if(UNIX AND NOT APPLE)
set_target_properties(cycles PROPERTIES INSTALL_RPATH $ORIGIN/lib)
endif()
if(CYCLES_STANDALONE_REPOSITORY)
cycles_install_libraries(cycles)
if(WITH_USD AND USD_LIBRARY_DIR)
install(DIRECTORY
${USD_LIBRARY_DIR}/usd
DESTINATION ${CMAKE_INSTALL_PREFIX}
)
install(DIRECTORY
${USD_LIBRARY_DIR}/../plugin/usd
DESTINATION ${CMAKE_INSTALL_PREFIX}
)
endif()
endif()
install(PROGRAMS
$<TARGET_FILE:cycles>
install(
TARGETS cycles
DESTINATION ${CMAKE_INSTALL_PREFIX})
add_test(
NAME cycles_version
COMMAND ${CMAKE_INSTALL_PREFIX}/$<TARGET_FILE_NAME:cycles> --version)
endif()
if(WITH_CYCLES_PRECOMPUTE)
@@ -131,11 +143,7 @@ if(WITH_CYCLES_PRECOMPUTE)
target_link_libraries(cycles_precompute PRIVATE ${LIB})
if(UNIX AND NOT APPLE)
set_target_properties(cycles_precompute PROPERTIES INSTALL_RPATH $ORIGIN/lib)
endif()
install(PROGRAMS
$<TARGET_FILE:cycles_precompute>
install(
TARGETS cycles_precompute
DESTINATION ${CMAKE_INSTALL_PREFIX})
endif()

View File

@@ -46,8 +46,9 @@ struct XMLReadState : public XMLReader {
Shader *shader; /* Current shader. */
string base; /* Base path to current file. */
float dicing_rate; /* Current dicing rate. */
Object *object; /* Current object. */
XMLReadState() : scene(NULL), smooth(false), shader(NULL), dicing_rate(1.0f)
XMLReadState() : scene(NULL), smooth(false), shader(NULL), dicing_rate(1.0f), object(NULL)
{
tfm = transform_identity();
}
@@ -405,25 +406,33 @@ static void xml_read_background(XMLReadState &state, xml_node node)
/* Mesh */
static Mesh *xml_add_mesh(Scene *scene, const Transform &tfm)
static Mesh *xml_add_mesh(Scene *scene, const Transform &tfm, Object *object)
{
/* create mesh */
Mesh *mesh = new Mesh();
scene->geometry.push_back(mesh);
if (object && object->get_geometry()->is_mesh()) {
/* Use existing object and mesh */
object->set_tfm(tfm);
Geometry *geometry = object->get_geometry();
return static_cast<Mesh *>(geometry);
}
else {
/* Create mesh */
Mesh *mesh = new Mesh();
scene->geometry.push_back(mesh);
/* Create object. */
Object *object = new Object();
object->set_geometry(mesh);
object->set_tfm(tfm);
scene->objects.push_back(object);
/* Create object. */
Object *object = new Object();
object->set_geometry(mesh);
object->set_tfm(tfm);
scene->objects.push_back(object);
return mesh;
return mesh;
}
}
static void xml_read_mesh(const XMLReadState &state, xml_node node)
{
/* add mesh */
Mesh *mesh = xml_add_mesh(state.scene, state.tfm);
Mesh *mesh = xml_add_mesh(state.scene, state.tfm, state.object);
array<Node *> used_shaders = mesh->get_used_shaders();
used_shaders.push_back_slow(state.shader);
mesh->set_used_shaders(used_shaders);
@@ -434,7 +443,10 @@ static void xml_read_mesh(const XMLReadState &state, xml_node node)
/* read vertices and polygons */
vector<float3> P;
vector<float3> VN; /* Vertex normals */
vector<float> UV;
vector<float> T; /* UV tangents */
vector<float> TS; /* UV tangent signs */
vector<int> verts, nverts;
xml_read_float3_array(P, node, "P");
@@ -481,12 +493,26 @@ static void xml_read_mesh(const XMLReadState &state, xml_node node)
index_offset += nverts[i];
}
if (xml_read_float_array(UV, node, "UV")) {
ustring name = ustring("UVMap");
Attribute *attr = mesh->attributes.add(ATTR_STD_UV, name);
/* Vertex normals */
if (xml_read_float3_array(VN, node, Attribute::standard_name(ATTR_STD_VERTEX_NORMAL))) {
Attribute *attr = mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
float3 *fdata = attr->data_float3();
/* Loop over the normals */
for (auto n : VN) {
fdata[0] = n;
fdata++;
}
}
/* UV map */
if (xml_read_float_array(UV, node, "UV") ||
xml_read_float_array(UV, node, Attribute::standard_name(ATTR_STD_UV)))
{
Attribute *attr = mesh->attributes.add(ATTR_STD_UV);
float2 *fdata = attr->data_float2();
/* loop over the triangles */
/* Loop over the triangles */
index_offset = 0;
for (size_t i = 0; i < nverts.size(); i++) {
for (int j = 0; j < nverts[i] - 2; j++) {
@@ -507,6 +533,58 @@ static void xml_read_mesh(const XMLReadState &state, xml_node node)
index_offset += nverts[i];
}
}
/* Tangents */
if (xml_read_float_array(T, node, Attribute::standard_name(ATTR_STD_UV_TANGENT))) {
Attribute *attr = mesh->attributes.add(ATTR_STD_UV_TANGENT);
float3 *fdata = attr->data_float3();
/* Loop over the triangles */
index_offset = 0;
for (size_t i = 0; i < nverts.size(); i++) {
for (int j = 0; j < nverts[i] - 2; j++) {
int v0 = index_offset;
int v1 = index_offset + j + 1;
int v2 = index_offset + j + 2;
assert(v0 * 3 + 2 < (int)T.size());
assert(v1 * 3 + 2 < (int)T.size());
assert(v2 * 3 + 2 < (int)T.size());
fdata[0] = make_float3(T[v0 * 3], T[v0 * 3 + 1], T[v0 * 3 + 2]);
fdata[1] = make_float3(T[v1 * 3], T[v1 * 3 + 1], T[v1 * 3 + 2]);
fdata[2] = make_float3(T[v2 * 3], T[v2 * 3 + 1], T[v2 * 3 + 2]);
fdata += 3;
}
index_offset += nverts[i];
}
}
/* Tangent signs */
if (xml_read_float_array(TS, node, Attribute::standard_name(ATTR_STD_UV_TANGENT_SIGN))) {
Attribute *attr = mesh->attributes.add(ATTR_STD_UV_TANGENT_SIGN);
float *fdata = attr->data_float();
/* Loop over the triangles */
index_offset = 0;
for (size_t i = 0; i < nverts.size(); i++) {
for (int j = 0; j < nverts[i] - 2; j++) {
int v0 = index_offset;
int v1 = index_offset + j + 1;
int v2 = index_offset + j + 2;
assert(v0 < (int)TS.size());
assert(v1 < (int)TS.size());
assert(v2 < (int)TS.size());
fdata[0] = TS[v0];
fdata[1] = TS[v1];
fdata[2] = TS[v2];
fdata += 3;
}
index_offset += nverts[i];
}
}
}
else {
/* create vertices */
@@ -528,10 +606,11 @@ static void xml_read_mesh(const XMLReadState &state, xml_node node)
index_offset += nverts[i];
}
/* uv map */
if (xml_read_float_array(UV, node, "UV")) {
ustring name = ustring("UVMap");
Attribute *attr = mesh->subd_attributes.add(ATTR_STD_UV, name);
/* UV map */
if (xml_read_float_array(UV, node, "UV") ||
xml_read_float_array(UV, node, Attribute::standard_name(ATTR_STD_UV)))
{
Attribute *attr = mesh->subd_attributes.add(ATTR_STD_UV);
float3 *fdata = attr->data_float3();
#if 0
@@ -613,7 +692,7 @@ static void xml_read_transform(xml_node node, Transform &tfm)
static void xml_read_state(XMLReadState &state, xml_node node)
{
/* read shader */
/* Read shader */
string shadername;
if (xml_read_string(&shadername, node, "shader")) {
@@ -632,6 +711,25 @@ static void xml_read_state(XMLReadState &state, xml_node node)
}
}
/* Read object */
string objectname;
if (xml_read_string(&objectname, node, "object")) {
bool found = false;
foreach (Object *object, state.scene->objects) {
if (object->name == objectname) {
state.object = object;
found = true;
break;
}
}
if (!found) {
fprintf(stderr, "Unknown object \"%s\".\n", objectname.c_str());
}
}
xml_read_float(&state.dicing_rate, node, "dicing_rate");
/* read smooth/flat */
@@ -643,6 +741,26 @@ static void xml_read_state(XMLReadState &state, xml_node node)
}
}
/* Object */
static void xml_read_object(XMLReadState &state, xml_node node)
{
Scene *scene = state.scene;
/* create mesh */
Mesh *mesh = new Mesh();
scene->geometry.push_back(mesh);
/* create object */
Object *object = new Object();
object->set_geometry(mesh);
object->set_tfm(state.tfm);
xml_read_node(state, object, node);
scene->objects.push_back(object);
}
/* Scene */
static void xml_read_include(XMLReadState &state, const string &src);
@@ -690,6 +808,12 @@ static void xml_read_scene(XMLReadState &state, xml_node scene_node)
xml_read_include(state, src);
}
}
else if (string_iequals(node.name(), "object")) {
XMLReadState substate = state;
xml_read_object(substate, node);
xml_read_scene(substate, node);
}
#ifdef WITH_ALEMBIC
else if (string_iequals(node.name(), "alembic")) {
xml_read_alembic(state, node);

View File

@@ -97,6 +97,9 @@ macro(cycles_external_libraries_append libraries)
endif()
if(WITH_CYCLES_EMBREE)
list(APPEND ${libraries} ${EMBREE_LIBRARIES})
if(EMBREE_SYCL_SUPPORT)
list(APPEND ${libraries} ${SYCL_LIBRARIES})
endif()
endif()
if(WITH_OPENSUBDIV)
list(APPEND ${libraries} ${OPENSUBDIV_LIBRARIES})
@@ -174,6 +177,9 @@ macro(cycles_external_libraries_append libraries)
if(UNIX AND NOT APPLE)
if(CYCLES_STANDALONE_REPOSITORY)
list(APPEND ${libraries} extern_libc_compat)
# Hack to solve linking order issue where external libs depend on
# on our compatibility lib.
list(APPEND ${libraries} $<TARGET_FILE:extern_libc_compat>)
else()
list(APPEND ${libraries} bf_intern_libc_compat)
endif()

View File

@@ -107,7 +107,7 @@ struct Node {
/* Implicitly cast enums and enum classes to integer, which matches an internal way of how
* enumerator values are stored and accessed in a generic API. */
template<class ValueType, typename std::enable_if_t<std::is_enum_v<ValueType>> * = nullptr>
template<class ValueType, std::enable_if_t<std::is_enum_v<ValueType>, bool> = true>
void set(const SocketType &input, const ValueType &value)
{
static_assert(sizeof(ValueType) <= sizeof(int), "Enumerator type should fit int");

View File

@@ -31,7 +31,7 @@ HdCyclesInstancer::~HdCyclesInstancer() {}
#if PXR_VERSION > 2011
void HdCyclesInstancer::Sync(HdSceneDelegate *sceneDelegate,
HdRenderParam *renderParam,
HdRenderParam * /*renderParam*/,
HdDirtyBits *dirtyBits)
{
_UpdateInstancer(sceneDelegate, dirtyBits);
@@ -60,6 +60,7 @@ void HdCyclesInstancer::SyncPrimvars()
continue;
}
#if PXR_VERSION < 2311
if (desc.name == HdInstancerTokens->translate) {
_translate = value.Get<VtVec3fArray>();
}
@@ -72,6 +73,20 @@ void HdCyclesInstancer::SyncPrimvars()
else if (desc.name == HdInstancerTokens->instanceTransform) {
_instanceTransform = value.Get<VtMatrix4dArray>();
}
#else
if (desc.name == HdInstancerTokens->instanceTranslations) {
_translate = value.Get<VtVec3fArray>();
}
else if (desc.name == HdInstancerTokens->instanceRotations) {
_rotate = value.Get<VtVec4fArray>();
}
else if (desc.name == HdInstancerTokens->instanceScales) {
_scale = value.Get<VtVec3fArray>();
}
else if (desc.name == HdInstancerTokens->instanceTransforms) {
_instanceTransform = value.Get<VtMatrix4dArray>();
}
#endif
}
sceneDelegate->GetRenderIndex().GetChangeTracker().MarkInstancerClean(GetId());

View File

@@ -9,8 +9,8 @@
CCL_NAMESPACE_BEGIN
#define CYCLES_VERSION_MAJOR 3
#define CYCLES_VERSION_MINOR 6
#define CYCLES_VERSION_MAJOR 4
#define CYCLES_VERSION_MINOR 2
#define CYCLES_VERSION_PATCH 0
#define CYCLES_MAKE_VERSION_STRING2(a, b, c) #a "." #b "." #c
@@ -18,10 +18,6 @@ CCL_NAMESPACE_BEGIN
#define CYCLES_VERSION_STRING \
CYCLES_MAKE_VERSION_STRING(CYCLES_VERSION_MAJOR, CYCLES_VERSION_MINOR, CYCLES_VERSION_PATCH)
/* Blender libraries version compatible with this version */
#define CYCLES_BLENDER_LIBRARIES_VERSION 3.5
CCL_NAMESPACE_END
#endif /* __UTIL_VERSION_H__ */

View File

@@ -1,195 +0,0 @@
#!/usr/bin/env python3
# SPDX-FileCopyrightText: 2023 Blender Authors
#
# SPDX-License-Identifier: GPL-2.0-or-later
import collections
import os
import subprocess
import sys
# Hashes to be ignored
#
# The system sometimes fails to match commits and suggests to back-port
# revision which was already ported. In order to solve that we can:
#
# - Explicitly ignore some of the commits.
# - Move the synchronization point forward.
IGNORE_HASHES = {
}
# Start revisions from both repositories.
CYCLES_START_COMMIT = b"b941eccba81bbb1309a0eb4977fc3a77796f4ada" # blender-v2.92
BLENDER_START_COMMIT = b"02948a2cab44f74ed101fc1b2ad9fe4431123e85" # v2.92
# Prefix which is common for all the subjects.
GIT_SUBJECT_COMMON_PREFIX = b"Subject: [PATCH] "
# Marker which indicates begin of new file in the patch set.
GIT_FILE_SECTION_MARKER = b"diff --git"
# Marker of the end of the patch-set.
GIT_PATCHSET_END_MARKER = b"-- "
# Prefix of topic to be omitted
SUBJECT_SKIP_PREFIX = (
b"Cycles: ",
b"cycles: ",
b"Cycles Standalone: ",
b"Cycles standalone: ",
b"cycles standalone: ",
)
def subject_strip(common_prefix, subject):
for prefix in SUBJECT_SKIP_PREFIX:
full_prefix = common_prefix + prefix
if subject.startswith(full_prefix):
subject = subject[len(full_prefix):].capitalize()
subject = common_prefix + subject
break
return subject
def replace_file_prefix(path, prefix, replace_prefix):
tokens = path.split(b' ')
prefix_len = len(prefix)
for i, t in enumerate(tokens):
for x in (b"a/", b"b/"):
if t.startswith(x + prefix):
tokens[i] = x + replace_prefix + t[prefix_len + 2:]
return b' '.join(tokens)
def cleanup_patch(patch, accept_prefix, replace_prefix):
assert accept_prefix[0] != b'/'
assert replace_prefix[0] != b'/'
full_accept_prefix = GIT_FILE_SECTION_MARKER + b" a/" + accept_prefix
with open(patch, "rb") as f:
content = f.readlines()
clean_content = []
do_skip = False
for line in content:
if line.startswith(GIT_SUBJECT_COMMON_PREFIX):
# Skip possible prefix like "Cycles:", we already know change is
# about Cycles since it's being committed to a Cycles repository.
line = subject_strip(GIT_SUBJECT_COMMON_PREFIX, line)
# Dots usually are omitted in the topic
line = line.replace(b".\n", b"\n")
elif line.startswith(GIT_FILE_SECTION_MARKER):
if not line.startswith(full_accept_prefix):
do_skip = True
else:
do_skip = False
line = replace_file_prefix(line, accept_prefix, replace_prefix)
elif line.startswith(GIT_PATCHSET_END_MARKER):
do_skip = False
elif line.startswith(b"---") or line.startswith(b"+++"):
line = replace_file_prefix(line, accept_prefix, replace_prefix)
if not do_skip:
clean_content.append(line)
with open(patch, "wb") as f:
f.writelines(clean_content)
# Get mapping from commit subject to commit hash.
#
# It'll actually include timestamp of the commit to the map key, so commits with
# the same subject wouldn't conflict with each other.
def commit_map_get(repository, path, start_commit):
command = (b"git",
b"--git-dir=" + os.path.join(repository, b'.git'),
b"--work-tree=" + repository,
b"log", b"--format=%H %at %s", b"--reverse",
start_commit + b'..HEAD',
b'--',
os.path.join(repository, path),
b':(exclude)' + os.path.join(repository, b'intern/cycles/blender'))
lines = subprocess.check_output(command).split(b"\n")
commit_map = collections.OrderedDict()
for line in lines:
if line:
commit_sha, stamped_subject = line.split(b' ', 1)
stamp, subject = stamped_subject.split(b' ', 1)
subject = subject_strip(b"", subject).rstrip(b".")
stamped_subject = stamp + b" " + subject
if commit_sha in IGNORE_HASHES:
continue
commit_map[stamped_subject] = commit_sha
return commit_map
# Get difference between two lists of commits.
# Returns two lists: first are the commits to be ported from Cycles to Blender,
# second one are the commits to be ported from Blender to Cycles.
def commits_get_difference(cycles_map, blender_map):
cycles_to_blender = []
for stamped_subject, commit_hash in cycles_map.items():
if stamped_subject not in blender_map:
cycles_to_blender.append(commit_hash)
blender_to_cycles = []
for stamped_subject, commit_hash in blender_map.items():
if stamped_subject not in cycles_map:
blender_to_cycles.append(commit_hash)
return cycles_to_blender, blender_to_cycles
# Transfer commits from one repository to another.
# Doesn't do actual commit just for the safety.
def transfer_commits(commit_hashes,
from_repository,
to_repository,
dst_is_cycles):
patch_index = 1
for commit_hash in commit_hashes:
command = (
b"git",
b"--git-dir=" + os.path.join(from_repository, b'.git'),
b"--work-tree=" + from_repository,
b"format-patch", b"-1",
b"--start-number", bytes(str(patch_index), 'utf-8'),
b"-o", to_repository,
commit_hash,
b'--',
b':(exclude)' + os.path.join(from_repository, b'intern/cycles/blender'),
)
patch_file = subprocess.check_output(command).rstrip(b"\n")
if dst_is_cycles:
cleanup_patch(patch_file, b"intern/cycles", b"src")
else:
cleanup_patch(patch_file, b"src", b"intern/cycles")
patch_index += 1
def main():
if len(sys.argv) != 3:
print("Usage: %s /path/to/cycles/ /path/to/blender/" % sys.argv[0])
return
cycles_repository = sys.argv[1].encode()
blender_repository = sys.argv[2].encode()
cycles_map = commit_map_get(cycles_repository, b'', CYCLES_START_COMMIT)
blender_map = commit_map_get(blender_repository, b"intern/cycles", BLENDER_START_COMMIT)
diff = commits_get_difference(cycles_map, blender_map)
transfer_commits(diff[0], cycles_repository, blender_repository, False)
transfer_commits(diff[1], blender_repository, cycles_repository, True)
print("Missing commits were saved to the blender and cycles repositories.")
print("Check them and if they're all fine run:")
print("")
print(" git am *.patch")
if __name__ == '__main__':
main()