diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt index 19a23b3d077..afeddff83ac 100644 --- a/intern/cycles/CMakeLists.txt +++ b/intern/cycles/CMakeLists.txt @@ -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() diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt index 5892564f50b..4c693deec4d 100644 --- a/intern/cycles/app/CMakeLists.txt +++ b/intern/cycles/app/CMakeLists.txt @@ -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 - $ + install( + TARGETS cycles DESTINATION ${CMAKE_INSTALL_PREFIX}) + + add_test( + NAME cycles_version + COMMAND ${CMAKE_INSTALL_PREFIX}/$ --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 - $ + install( + TARGETS cycles_precompute DESTINATION ${CMAKE_INSTALL_PREFIX}) endif() diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp index 0863519722b..337458fc1e7 100644 --- a/intern/cycles/app/cycles_xml.cpp +++ b/intern/cycles/app/cycles_xml.cpp @@ -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(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 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 P; + vector VN; /* Vertex normals */ vector UV; + vector T; /* UV tangents */ + vector TS; /* UV tangent signs */ vector 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); diff --git a/intern/cycles/cmake/macros.cmake b/intern/cycles/cmake/macros.cmake index caa10a3a5d5..1bb7283c723 100644 --- a/intern/cycles/cmake/macros.cmake +++ b/intern/cycles/cmake/macros.cmake @@ -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} $) else() list(APPEND ${libraries} bf_intern_libc_compat) endif() diff --git a/intern/cycles/graph/node.h b/intern/cycles/graph/node.h index e55278c53ec..2e5492d5900 100644 --- a/intern/cycles/graph/node.h +++ b/intern/cycles/graph/node.h @@ -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> * = nullptr> + template, bool> = true> void set(const SocketType &input, const ValueType &value) { static_assert(sizeof(ValueType) <= sizeof(int), "Enumerator type should fit int"); diff --git a/intern/cycles/hydra/instancer.cpp b/intern/cycles/hydra/instancer.cpp index 2b95903734d..ae7ced42ea7 100644 --- a/intern/cycles/hydra/instancer.cpp +++ b/intern/cycles/hydra/instancer.cpp @@ -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(); } @@ -72,6 +73,20 @@ void HdCyclesInstancer::SyncPrimvars() else if (desc.name == HdInstancerTokens->instanceTransform) { _instanceTransform = value.Get(); } +#else + if (desc.name == HdInstancerTokens->instanceTranslations) { + _translate = value.Get(); + } + else if (desc.name == HdInstancerTokens->instanceRotations) { + _rotate = value.Get(); + } + else if (desc.name == HdInstancerTokens->instanceScales) { + _scale = value.Get(); + } + else if (desc.name == HdInstancerTokens->instanceTransforms) { + _instanceTransform = value.Get(); + } +#endif } sceneDelegate->GetRenderIndex().GetChangeTracker().MarkInstancerClean(GetId()); diff --git a/intern/cycles/util/version.h b/intern/cycles/util/version.h index 01174fb704e..da120687a3c 100644 --- a/intern/cycles/util/version.h +++ b/intern/cycles/util/version.h @@ -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__ */ diff --git a/tools/utils/cycles_commits_sync.py b/tools/utils/cycles_commits_sync.py deleted file mode 100755 index ead73775f64..00000000000 --- a/tools/utils/cycles_commits_sync.py +++ /dev/null @@ -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()