Compare commits

...

480 Commits

Author SHA1 Message Date
cf059c950e cleanup 2022-04-06 16:13:37 +02:00
b21856dbee Merge branch 'master' into varray-improve 2022-04-06 15:51:18 +02:00
0d66f3ae0d progress 2022-04-06 15:47:58 +02:00
55661f7c21 progress 2022-04-06 15:28:36 +02:00
1777772a17 progress 2022-04-06 15:27:06 +02:00
c14ed182f5 Fix T96595: Animation not duplicated for meta children
Iterate over meta strip content and duplicate animation for all strips.
recursively.
2022-04-06 15:12:16 +02:00
8897e4a696 improve ownership hint 2022-04-06 15:11:46 +02:00
64018d55cf progress 2022-04-06 14:01:53 +02:00
6b2c1016df progress 2022-04-06 13:50:59 +02:00
55b130f0f3 progress 2022-04-06 13:13:27 +02:00
8c46337e47 materialize compressed 2022-04-06 12:40:24 +02:00
0098cf57d0 add execute_SI_SI_SI_SI_SO 2022-04-06 12:24:17 +02:00
Bastien Montagne
1ec93507e1 API doc: Tweak sphinx to get date of source commit instead of build date.
This commit disables the 'last updated' value (which is the date the
sphinx doc is generated), and instead modifies the 'commit' field from
the 'html_context' data to get:
  - a link to the commit itself.
  - the date of that commit.

This avoids having the whole documentation detected as changed every
time it is re-generated by the buildbot.

Reviewed By: dfelinto, campbellbarton

Differential Revision: https://developer.blender.org/D14429
2022-04-06 11:43:14 +02:00
Bastien Montagne
e06399c223 Fix badly broken caches handling during undo/redo.
Original rework of caches during undo/redo (see D8183) had a very bad
flaw hidden in it: using the key of a ghash as source of data.

While this was effectively working then (cache pointer itself being part
of the key, and said cache pointers not being cleared on file write),
this is a general very bad way to do things.

Now that cache pointers are more and more cleared on file write (as part
of clearing runtime-data to reduce false-positives when checking if an
ID has changed or not), this has to be fixed properly by:
* Not storing the cache pointer itself in the IDCacheKey.
* In undo context, in readfile code trying to preserve caches, store the
  cache pointers as values of the mapping, together with the usages counter

The first change potentially affects all usages of
`BKE_idtype_id_foreach_cache`, but in practice this code is only used by
memfile reading code (i.e. undo) currently.

Related to T97015.

Reviewed By: brecht

Maniphest Tasks: T97015

Differential Revision: https://developer.blender.org/D14559
2022-04-06 11:37:15 +02:00
8dd3387eb7 Cleanup: spelling & poor wording in code & comments 2022-04-06 19:08:10 +10:00
2d2baeaf04 Fix: T78228 Send all python errors to info editor
Python exceptions are now shown in the info editor,
this also resolves an old bug where errors were printed twice.

This was originally based on D9752 by @ShadowChaser although many
changes have been made from the original patch.

Details:

- BPy_errors_to_report no longer prints additional output.
- BKE_report_print_test was added so it's possible to check if calling
  BKE_report also printed to the stdout.
- Callers to BPy_errors_to_report are responsible for ensuring output
  is printed to the stdout/stderr.
- Python exceptions no longer add a trailing newline,
  needed to avoid blank-space when displayed in the info-editor.
2022-04-06 18:02:58 +10:00
e4f71e5ef3 Fix off by one error placing the text cursor from a Python exception
Off by one error placing text from an error.
2022-04-06 13:14:21 +10:00
2e9e2715ef Cleanup: use context.path_resolve instead of eval(..) 2022-04-06 11:48:56 +10:00
7bb8eeb3a8 PyAPI: Add Context.path_resolve wrapper that supports context members
This avoids script authors using `eval("context.%s" % data_path)`
to access paths starting from the context,
which isn't good practice especially if the data_path isn't trusted.

Now it's possible to resplve paths such as:

   context.path_resolve('active_object.modifiers[0].name')
2022-04-06 11:48:51 +10:00
5d31252c76 Fix accessing an empty context succeeding when it shouldn't
Internally an empty string is used to access context member `__dir__`,
which caused `getattr(context, "")` to succeed returning None.
2022-04-06 11:47:43 +10:00
f208713b02 UI: use a faster method of finding colliding layer names
Access the keys of the collection instead of the layers names
and use a set to detect collisions. There is no need to access the
duplicate layers themselves. Roughly twice as fast.
2022-04-06 11:42:44 +10:00
8bd28ef16c Doxygen: update doxyfile to 1.9.3
Resolves deprecation warnings.
2022-04-06 11:42:42 +10:00
11b0824d89 Cleanup: line wrapping, remove unused args, variables in UI scripts 2022-04-06 09:40:14 +10:00
a776385b26 Cleanup: zero initialize VColRef before setting members
Ensures new members will be zeroed, the compiler is able to optimize
this into identical compiled output.
2022-04-06 09:40:13 +10:00
20bb859d9b Cleanup: quiet compiler warnings
Ideally this wouldn't be needed, I couldn't find a good solution
to avoid casting when comparing const/non-const pointers in this case.
2022-04-06 09:40:11 +10:00
931ae424b9 BVH Utils: remove 'isolate' parameter
This is an internal usage parameter.

No functional changes.
2022-04-05 20:33:06 -03:00
9fbf7f1180 BVH Utils: Remove '_allocated' members from 'BVHTreeFromMesh'
The parameters indicating whether it is allocated are always `false` and
it is up to the caller to free them.

Also clang-format was triggered.
2022-04-05 19:56:03 -03:00
Germano Cavalcante
684b95804e Refactor: remove cache parameters from bvhtree_from_ functions
The `BVHCacheType bvh_cache_type` parameter defines specific
`BVHTrees` that cannot be customized.

So it doesn't make sense to pass this value to any
`*bvhtree_from_[...]_ex` function as the `BVHTrees` created in these
cases are custom and cannot be saved in the cache.

This also resulted in a nice cleanup in the code.

Differential Revision: https://developer.blender.org/D14479
2022-04-05 19:32:56 -03:00
bb7e3c2b56 Cleanup: Simplify if statements, clang tidy 2022-04-05 16:40:44 -05:00
228f7f1c85 Refactor: Deduplicate and simplify BVH Utils code
In summary the changes are:
- Merge all `bvhtree_from_mesh_*.*_setup_data` in a single utility
- Create `bvhtree_from_editmesh_setup_data`
- Setup data only once in `BKE_bvhtree_from_mesh_get` and `BKE_bvhtree_from_editmesh_get`

Also the behavior of `BKE_bvhtree_from_mesh_get` and
`BKE_bvhtree_from_editmesh_get` changed a bit:
- If a null tree is cached, don't set the `data` to zero. This tree is not an error and the others data can still be used.
- If a null tree is returned, don't set the `data` to zero. Matches the previous change.

Differential Revision: https://developer.blender.org/D14549
2022-04-05 18:14:22 -03:00
7a5e663843 Fix: Pass const arguments to object snapping 2022-04-05 16:13:55 -05:00
7455bb85cc GPencil: Fix buiding with GTEST 2022-04-05 22:53:10 +02:00
5f1adfc508 Cleanup: fix various typos
Contributed by luzpaz.

Differential Revision: https://developer.blender.org/D14443
2022-04-05 22:21:13 +02:00
0d43ff43a4 Fix T96904: texture paint sample tool not working with closest interpolation
For drawing pixel art. Based on patch by Philipp Oeser.
2022-04-05 21:32:03 +02:00
eae36be372 Refactor: Unify vertex and sculpt colors into new
color attribute system.

This commit removes sculpt colors from experimental
status and unifies it with vertex colors. It
introduces the concept of "color attributes", which
are any attributes that represents colors.  Color
attributes can be represented with byte or floating-point
numbers and can be stored in either vertices or
face corners.

Color attributes share a common namespace
(so you can no longer have a floating-point
sculpt color attribute and a byte vertex color
attribute with the same name).

Note: this commit does not include vertex paint mode,
      which is a separate patch, see:
      https://developer.blender.org/D14179

Differential Revision: https://developer.blender.org/D12587
Ref D12587
2022-04-05 11:42:55 -07:00
a3e122b9ae Curves: fix missing updates switching to sculpt mode
This would cause the viewport to draw stale data until a stroke
is done.
2022-04-05 20:00:31 +02:00
fc8bcd26c0 Curves: fix edit mode detection
This adds missing cases to detect edit mode for Curves objects.
Unlike other object types, Curves do not have specific edit data,
rather we edit the original data directly, and rely on `Object.mode`.

For this, `BKE_object_data_is_in_editmode` had to be modified to
take a pointer to the object. This affects two places: the outliner
and the dependency graph. For the former place, the object pointer
is readily available, and we can use it. For the latter, the object
pointer is not available, however since it is used to update edit
mode pointers, and since Curves do not have such data, we can
safely pass null to the function here.

This also fixes the assertion failure that happens when closing a file
in edit mode.

Differential Revision: https://developer.blender.org/D14330
2022-04-05 19:59:20 +02:00
4de704a6df Overlay: Fix edit mode shader compilation after recent commit
This was caused by rBd889762590a4f068aa312879976e98dbd0ee93fc
2022-04-05 18:56:31 +02:00
b84255f590 Curves: Port legacy curve viewport drawing to the new data-block
Instead of using `CurveEval` to draw the curve wire edges, use
the new `Curves` data-block, which is already built as part of
an object's evaluated geometry set whenever there is a
`CurveComponent`.

This means that we can remove `Curve`'s temporary ownership
of `CurveEval` for drawing (added in 9ec12c26f1),
which caused a memory leak as described in T96498.

In my testing this improved performance by around 1.5x during
viewport playback, back to the performance of 3.1 before the
curve data structure transition started.

The next step of using the GPU to do the final curve evaluation
for the viewport is described in T96455, but is unrelated.

Differential Revision: https://developer.blender.org/D14551
2022-04-05 11:36:12 -05:00
edcbf741df Refactor: Evaluate surface objects as mesh components
This commit furthers some of the changes that were started in
rBb9febb54a492 and subsequent commits by changing the way surface
objects are presented to render engines and other users of evaluated
objects in the same way. Instead of presenting evaluated surface objects
as an `OB_SURF` object with an evaluated mesh, `OB_SURF` objects
can now have an evaluated geometry set, which uses the same system
as other object types to deal with multi-type evaluated data.

This clarification makes it more obvious that lots of code that dealt
with the `DispList` type isn't used. It wasn't before either, now it's
just *by design*. Over 1100 lines can be removed. The legacy curve
draw cache code is much simpler now too. The idea behind the further
removal of `DispList` is that it's better to focus optimization efforts
on a single mesh data structure.

One expected functional change is that the evaluated mesh from surface
objects can now be used in geometry nodes with the object info node.

Cycles and the OBJ IO tests had to be tweaked to avoid using evaluated
surface objects instead of the newly exposed mesh objects.

Differential Revision: https://developer.blender.org/D14550
2022-04-05 11:31:18 -05:00
e513687288 Cycles: Fix a few type casting warnings
Stumbled over the `integrate_surface_volume_only_bounce` kernel
function not returning the right type. The others too showed up as
warnings when building Cycles as a standalone which didn't have
those warnings disabled.

Differential Revision: https://developer.blender.org/D14558
2022-04-05 18:09:21 +02:00
f60cffad38 Cycles: Use USD dependencies when building Hydra render delegate
Adds support for linking with some of the dependencies of a USD
build instead of the precompiled libraries from Blender, specifically
OpenSubdiv, OpenVDB and TBB. Other dependencies keep using the
precompiled libraries from Blender, since they are linked statically
anyway so it does't matter as much. Plus they have interdependencies
that are difficult to resolve when only using selected libraries from
the USD build and can't simply assume that USD was built with all
of them.

This patch also makes building the Hydra render delegate via the
standalone repository work and fixes various small issues I ran into
in general on Windows (e.g. the use of both fixed paths and
`find_package` did not seem to work correctly). Building both the
standalone Cycles application and the Hydra render delegate at the
same time is supported now as well (the paths in the USD plugin JSON
file are updated accordingly).

All that needs to be done now to build is to specify a `PXR_ROOT`
or `USD_ROOT` CMake variable pointing to the USD installation,
everything else is taken care of automatically (CMake targets are
loaded from the `pxrTargets.cmake` of USD and linked into the
render delegate and OpenSubdiv, OpenVDB and TBB are replaced
with those from USD when they exist).

Differential Revision: https://developer.blender.org/D14523
2022-04-05 17:23:52 +02:00
190334b47d Curves: new Grow/Shrink brush
This adds a new Grow/Shrink brush which is similar to the Length
brush in the old hair system.
* It's possible to switch between growing and shrinking by hold
  down ctrl and/or by changing the direction enum.
* 3d brush is supported.
* Different brush falloffs are supported.
* Supports scaling curves uniformly or shrinking/extrapolating
  them. Extrapolation is linear only in this patch.
* A minimum length settings helps to avoid creating zero-sized curves.

Differential Revision: https://developer.blender.org/D14474
2022-04-05 15:24:12 +02:00
e40b0d52cf Preferences: enable Duplicate Data for curves and point cloud objects
Those geometry types are expected to behave the same as e.g. mesh
with respect to data copying. The fact that this was not enabled
already was an oversight in the initial commit that added these types.

Differential Revision: https://developer.blender.org/D14554
2022-04-05 15:19:43 +02:00
fc848e9440 Fix T97010 GPencil: Artifacts on Grease Pencil
Was caused by wrong name for uniform update.

Regression introduced in rBeccb0b222e34
2022-04-05 15:08:05 +02:00
d5550c7b2c Fix T97071: Duplicating strip in locked channel creates overlapping strips
Add flag `SEQ_IGNORE_CHANNEL_LOCK` to indicate, that channel lock
should not apply to strip. This flag must be cleared after
transformation.
2022-04-05 14:56:50 +02:00
d889762590 Cleanup: Change globalBlock members to snake case
This avoid conflicting defines in GLSL

Fix T96998 Blender 3.2.0 Alpha crashes on startup
2022-04-05 14:36:53 +02:00
c8d658c5ed Cleanup: Overlays: Remove unused facefill shader 2022-04-05 14:35:36 +02:00
328dfab423 Fix T97003: color-management settings can't be animated
Regression in [0] which missed excluding FRAME_CHANGE from
deg_recalc_flags_for_legacy_zero causing all
DEG_id_tag_update(&scene->id, 0) calls to re-calculate animation data.

When this tagging was done in the RNA update function, changing
key-framed values in the UI would be immediate reset to their
keyed-values.

Thanks to Philipp Oeser for finding the root cause.

[0]: 35aedd87e7
2022-04-05 21:04:46 +10:00
Pratik Borhade
f87029f7b1 Fix T96424: Don't register undo step for empty knife cut
Prevents undo push when no cut has been made.

Reviewed By: campbellbarton

Ref D14329
2022-04-05 20:55:10 +10:00
Pratik Borhade
d00de988c3 WM: avoid unnecessary undo step creation when duplicating
Calling duplicate operation without selecting anything registers an undo
step. If nothing is selected (keyframe, curve, object, etc.), cancel the
operator execution to prevent undo push.

Patch improves following operators:

- ACTION_OT_duplicate
- GPENCIL_OT_duplicate
- GRAPH_OT_duplicate
- MESH_OT_duplicate
- NODE_OT_duplicate
- OBJECT_OT_duplicate

Reviewed By: campbellbarton

Ref D14511
2022-04-05 20:30:00 +10:00
d88b821d28 Fix: wrong operator return value 2022-04-05 12:04:47 +02:00
Alaska
850b887339 Fix T96745: UI: Change "Inverts" to "Invert" for selection tool
This is to improve grammatical consistency with other selection options.

Maniphest Tasks: T96745

Differential Revision: https://developer.blender.org/D14444
2022-04-05 09:24:27 +02:00
Yann Lanthony
7cf3e713f7 Gizmos: enable gizmos for the action space
Support gizmos for the the action space type based on how it is done for
other types of spaces in Blender (e.g: view3d, image).

See patch submission for sample code.

Reviewed By: campbellbarton, sybren

Ref D13999
2022-04-05 17:14:40 +10:00
c1d461bcbc Cleanup: avoid unnecessary undo steps for curves & simplify code
Some edit-curve operators used an 'ok' variable to represent
if the selection was found and if a change was made.

Previously it would only return cancel if an error was shown
causing a redundant undo step to be added without a selection.

Since this is simple behavior that shouldn't need much explanation,
use two variables with meaningful names to avoid confusion.

Reviewing D14511 highlighted this issue.
2022-04-05 13:15:57 +10:00
8333b681a7 Keymap: use "use_tweak_select_passthrough" preference for tweak tool
This experimental preference was not making much difference with
selection set to left-mouse for the 3D view and UV editor. Now dragging
the existing selection is possible when this preference is enabled.
2022-04-05 12:29:34 +10:00
53261df6f0 Fix keymap "use_tweak_tool_lmb_interaction" blocking sequencer scrub
Ignore this experimental preference for the sequencer.
2022-04-05 12:29:32 +10:00
0f530b0b03 Fix T96885: drag fallback on tweak is using active tool instead
Ensure the fallback transforms on drag when used as a fallback.
2022-04-05 12:29:31 +10:00
f2b9bbd194 Fix T97032: Tweak Select preference causes selection issues
Disable select-passthrough on release events.
2022-04-05 12:29:29 +10:00
d5f5788b10 Keymap: remove reference to missing view2d_edge_pan property
This was added [0] but the property is missing in the operator.

[0]: e49fef45ce
2022-04-05 10:24:32 +10:00
1d86d61782 Fix: Assert fails when evaluating single point Bezier curve
Return early when there is only one point,
since that means there are no segments.
2022-04-04 18:42:01 -05:00
43a582a2ab Sequencer: skip redundant F-curve GSet allocation 2022-04-05 09:30:26 +10:00
25a283acce Fix memory leak duplicating sequencer strips
Regression in [0] also skip creating a GSet when there are no F-curves.

[0]: e74420124f
2022-04-05 09:23:14 +10:00
11183ebc3c Fix T97034: tweak strips uses cursor position after threshold reached 2022-04-05 09:11:51 +10:00
e994b72812 UI: move "use_select_nearest_on_first_click" into it's own panel
Add a new panel called "Tweaks" so we can get feedback from users
about minor tweaks to behavior as exposing these minor changes.

Currently this only has a single item in it, however we may want to
get feedback from users about small changes in the future so I'd
prefer to have a place to list these kinds of options.

Ref D14542
2022-04-05 08:51:36 +10:00
521fab080b Cleanup: use doxygen links to struct members 2022-04-05 08:02:01 +10:00
b51d6d5068 Cleanup: clang-format
Also add space below file references.
2022-04-05 08:01:46 +10:00
744369c114 Cleanup: move doc-strings into headers
- The comment for create_normals was moved into an inline note
  as it's not related to the public API.
- Use a colon after parameters.

Ref T92709
2022-04-05 07:49:36 +10:00
22184f3aee Cleanup: spelling in comments 2022-04-05 07:39:40 +10:00
5eab5713c0 Fix T97019: Regression - GPencil Shrinkwrap modifier not longer working
Bug introduced in the smooth function changes done in commit rBd4e1458db3a0e0eaf80219dc8e6d10cb27620793

Differential Revision: https://developer.blender.org/D14548
2022-04-04 22:33:20 +02:00
Germano Cavalcante
0ebcc711fc Fix T95678: Thumbnails are not working with big / large Objects
The internal camera used to render the thumbnails also has to consider
`clip_start` and `clip_end`.

Reviewed By: Severin

Maniphest Tasks: T95678

Differential Revision: https://developer.blender.org/D14138
2022-04-04 16:20:34 -03:00
b5f3f8ef1d Fix collection assets hidden in old files with asset browser open
Make sure the filtering in the Asset Browser doesn't filter out
collection assets.
2022-04-04 17:54:39 +02:00
9eb4cb956b Cleanup: Remove unused function
Unused after 943b919fe8
2022-04-04 10:28:10 -05:00
432ad4c632 Cleanup: Move interface.c to C++
This is similar to 4537eb0c3b
2022-04-04 10:24:14 -05:00
9c962b2e2b Fix T96999: RNA mesh transform does not mark normals dirty 2022-04-04 09:59:45 -05:00
aa1ae1d3c8 Fix overlapping GPU device bitmasks
This did not end up affecting actual behavior, but it is wrong.
Found by Ethan Hall.

Ref D14525
2022-04-04 16:38:30 +02:00
d6f5b02940 OBJ: fix printf specifier compile warning on some compilers 2022-04-04 17:37:13 +03:00
e4289f2360 Fix errors in sequencer channel headers
Failing constraint test uncovered crashes on NULL dereference and
missing channels initialization in `SEQ_editing_ensure()`.
2022-04-04 16:30:16 +02:00
e7f4aa8f0c Fix T96838: Missing translations in link drag search 2022-04-04 08:46:53 -05:00
81b55d7988 Pose library: add deprecation notices
The legacy Pose Library operators now refer to the "Legacy Pose Library",
and their description mentions they are deprecated and will be removed
from Blender 3.3. The same was added to the `Object.pose_library` RNA
property.

Ref: T93405

The removal of these deprecated properties is tracked in T93406.
2022-04-04 15:26:02 +02:00
a824c076b7 Pose library: remove much of old pose library interface
Remove much of the old legacy pose library:
- Remove from the Pose & Armature menus.
- Remove from the default keymap.
- Pose Library panel in Armature properties: Add "(legacy)" to title.
- Add note that the functionality of that panel is obsolete, with a
  button that opens the manual on the chapter of the new pose library.
- Add button to convert the selected legacy pose library to pose assets.
- The rest of the functionality is greyed out to further communicate
  it's been deprecated. It's still functional, though.

Ref: T93405
2022-04-04 14:43:17 +02:00
068d2b0861 Fix T96575: Can't set vertex theme color
UV editor used wire color for drawing unselected vertices.
Add color variable to shader, so theme color can be used.

Reviewed By: jbakker

Differential Revision: https://developer.blender.org/D14373
2022-04-04 14:28:55 +02:00
e49fef45ce VSE: Use edge panning
Add edge panning feature to transform operator. It works in same way as
in node editor, but Y axis is limited by usable range up to 128
channels.

Reviewed By: Severin

Differential Revision: https://developer.blender.org/D14310
2022-04-04 14:28:55 +02:00
3ce6c5adfc UserDef: Add experimental flag for 3d texturing brush.
This only adds a experimental flag to enable the 3d texturing brush,
so future developments could check. Currently the flag does nothing
as no functionality of the 3d texturing brush has been implemented.
2022-04-04 14:12:33 +02:00
a818a0f427 BlenLib: Add ushort2 to math vec types.
Needed for the 3d texturing brush project.
2022-04-04 14:12:33 +02:00
9c2b5900c0 Move ImageTileWrapper to BKE.
ImageTileWrapper is a wrapper around ImageTile to centralize tile calculations when
using CPP. Currentry used by the image engine and will be used for the 3d
texturing brush project.
2022-04-04 14:12:33 +02:00
a56f53ad56 OBJ: fix mac/linux tests and compile warnings in the new obj importer
Related to D13958
2022-04-04 14:58:45 +03:00
277fa2f441 VSE: Add channel headers
This patch adds channel region to VSE timeline area for drawing channel
headers. It is synchronizedwith timeline region. 3 basic features are
implemented - channel visibility, locking and name.

Channel data is stored in `SeqTimelineChannel` which can be top-level
owned by `Editing`, or it is owned by meta strip to support nesting.
Strip properties are completely independent and channel properties are
applied on top of particular strip property, thus overriding it.

Implementation is separate from channel regions in other editors. This
is mainly because style and topology is quite different in VSE. But
also code seems to be much more readable this way.

Currently channels use functions similar to VSE timeline to draw
background to provide illusion of transparency, but only for background
and sfra/efra regions.

Great portion of this patch is change from using strip visibility and
lock status to include channel state - this is facilitated by functions
`SEQ_transform_is_locked` and `SEQ_render_is_muted`

Originally this included changes in D14263, but patch was split for
easier review.

Reviewed By: fsiddi, Severin

Differential Revision: https://developer.blender.org/D13836
2022-04-04 12:56:43 +02:00
5a0b4e97e6 Fix memleak in VSE proxy creation.
We didn't properly free allocated ffmpeg data structures.
2022-04-04 12:43:54 +02:00
e6a9b22384 OBJ: New C++ based wavefront OBJ importer
This takes state of soc-2020-io-performance branch as it was at
e9bbfd0c8c (2021 Oct 31), merges latest master (2022 Apr 4),
adds a bunch of tests, and fixes a bunch of stuff found by said
tests. The fixes are detailed in the differential.

Timings on my machine (Windows, VS2022 release build, AMD Ryzen
5950X 32 threads):

- Rungholt minecraft level (269MB file, 1 mesh): 54.2s -> 14.2s
  (memory usage: 7.0GB -> 1.9GB).
- Blender 3.0 splash scene: "I waited for 90 minutes and gave up"
  -> 109s. Now, this time is not great, but at least 20% of the
  time is spent assigning unique names for the imported objects
  (the scene has 24 thousand objects). This is not specific to obj
  importer, but rather a general issue across blender overall.

Test suite file updates done in Subversion tests repository.

Reviewed By: @howardt, @sybren
Differential Revision: https://developer.blender.org/D13958
2022-04-04 13:36:10 +03:00
ee3f71d747 Functions: allow for better compiler optimization
This extracts the inner loops into a separate function.
There are two main reasons for this:
* Allows using `__restrict` to indicate that no other parameter
  aliases with the output array. This allows for better optimization.
* Makes it easier to search for the generated assembly code,
  especially with the `BLI_NOINLINE`.
2022-04-04 11:57:58 +02:00
992d51bbcf Cleanup: Simplify zero-initializing DNA structures in C++
Avoids duplication of type which previously was specified twice in a line.
2022-04-04 11:47:28 +02:00
e5688f67aa Cleanup: Left-over debug print in own recent commit.
Kudos to Aaron Carlisle (@Blendify) for noticing it!
2022-04-04 11:36:39 +02:00
5dbd6968a6 Cleanup: clang-tidy 2022-04-04 15:43:25 +10:00
f699dbba86 Cleanup: use event parameters for functions that create key-map items
Replace 5 arguments with a single struct as the same arguments
are used in many places.

This didn't read well and was confusing with both arguments named
`val` & `value` in the case of WM_modalkeymap_add_item.
2022-04-04 14:32:42 +10:00
0ef96cd392 Cleanup: ensure space after file named in headers
Add blank lines after file references to avoid them being interpreted as
doc-strings the following declarations.
2022-04-04 13:34:42 +10:00
dc5b1d6c75 Cleanup: pass selection threshold to curve picking
Remove the extended version of ED_curve_editnurb_select_pick,
pass the size threshold directly to this function but as the distance in
pixels instead of a multiplier for ED_view3d_select_dist_px.

Using a multiplier is a less direct way to reference the threshold.
2022-04-04 13:11:44 +10:00
ff82bb5e3a Curve Pen Tool: set the first newly added points active
Other newly created points were already active, just not for newly
created curves.
2022-04-04 12:55:56 +10:00
0cb9926cd9 Fix crash removing the last point of a spline with the new pen tool 2022-04-04 12:42:11 +10:00
e26cc6aee3 Cleanup: indentation 2022-04-04 12:35:33 +10:00
85a0115c44 Cleanup: spelling in comments 2022-04-04 12:35:33 +10:00
27fea7a3a5 Cleanup: clang-format
Add ccl_gpu_kernel_postfix as a statement macro to prevent the following
declarations from being indented.
2022-04-04 12:35:33 +10:00
f6a20fca5e Cleanup: compiler warnings 2022-04-04 12:35:33 +10:00
637fe6f5ff Fix T97001: Grease pencil array modifier relative offset broken
This has been broken for two years, since rB29f3af952725,
which retrieved the bounding box from an object and immediately
overwrote it with -1, 1. That commit had another problem though--
the modifier stack shouldn't use object level data, it should use
data from the previous modifier.

Differential Revision: https://developer.blender.org/D14524
2022-04-03 12:57:37 -05:00
933d56d9e9 Curves: Support set origin and apply transform operators
Add support for the Curves object to the "Set Origin" and "Apply Object
Tansform" operators. Also change the automatic handle calculation to
avoid adding Bezier attributes if they don't need to be added.

Differential Revision: https://developer.blender.org/D14526
2022-04-03 12:54:42 -05:00
f6baba695c Curves: Inline some simple methods
These functions are very simple, but some of them were showing up in
in profiles for curves sculpt mode and various curve nodes. Making sure
they are inlined will allow avoiding the compiler to optimize this logic
much better.

Differential Revision: https://developer.blender.org/D14529
2022-04-03 12:51:05 -05:00
Dilith Jayakody
336082acba Curves: Curve Pen
This tool can be used to rapidly edit curves. The current set of
functionalities for Bezier splines are as follows:

The functionalities are divided into three versions of the operator:
* Left-Click
* Ctrl + Left-Click
* Double Click

All current functionalities and their defaults are as follows:
* Extrude Point: Add a point connected to an existing point.
Enabled for Left-Click.
* Extrude Handle Type: Type of the handles of the extruded points.
Can be either Vector or Auto. Defaults to Vector.
* Delete Point: Delete existing point.
Enabled for Ctrl + Left-Click.
* Insert Point: Insert a point into a curve segment.
Enabled for Ctrl + Left-Click.
* Move Segment: Move curve segment.
Enabled for Left-Click.
* Select Point: Select a single point or handle at a time.
Enabled for Left-Click.
* Move point: Move existing points or handles.
Enabled for Left-Click.
* Close Spline: Close spline by clicking the endpoints consecutively.
Defaults to True.
* Close Spline Method: The condition for Close Spline to activate.
Can be one of None, On Press or On Click.
Defaults to On Click for Left-Click and None for the others.
  * None: Functionality is turned off.
  * On Press: Activate on mouse down.
  This makes it possible to move the handles by dragging immediately
  after closing the spline.
  * On Click: Activate on mouse release.
  This makes it possible to avoid triggering the Close Spline
  functionality by dragging afterward.
* Toggle Vector: Toggle handle between Vector and Auto handle types.
Enabled for Double Click on a handle.
* Cycle Handle Type: Cycle between all four handle types.
Enabled for Double Click on the middle point of a Bezier point.

The keybindings for the following functionalities can be adjusted from
the modal keymap
* Free-Align Toggle: Toggle between Free and Align handle types.
Defaults to Left Shift. Activated on hold.
* Move Adjacent Handle: Move the closer handle of the adjacent vertex.
Defaults to Left Ctrl. Activated on hold.
* Move Entire: Move the entire point by moving by grabbing on the handle
Defaults to Spacebar. Activated on hold.
* Link Handles: Mirror the movement of one handle onto the other.
Defaults to Right Ctrl. Activated on press.
* Lock Handle Angle: Move the handle along its current angle.
Defaults to Left Alt. Activated on hold.

All the above functionalities, except for Move Segment and
those that work with handles, work similarly in the case of Poly
and NURBS splines.

Reviewed By: HooglyBoogly, weasel, campbellbarton
Differential Revision: http://developer.blender.org/D12155
2022-04-03 22:37:22 +05:30
1cdf8b19e5 Fix T96957: creating paint curve crashes
This was essentially double free due to a dangling pointer,
because `op->customdata` was not properly set to null after
the paint stroke was freed.
2022-04-03 10:49:20 +02:00
be699936af Cleanup: Move interface View2D files to C++
Similar to 4537eb0c3b
2022-04-03 00:00:42 -05:00
79ff65d07b Fix T96978: Objects that emit light do not appear in light groups
The initial commit only wrote direct and indirect lighting into the lightgroup passes,
but not rays that directly hit the light source itself.
2022-04-02 23:46:22 +02:00
4537eb0c3b Cleanup: Remove interface region files to C++
Moves all `interface_region*` files to C++ except for the tooptip region
which is slightly more complicated. Also move a few other files as well.
This helps to simplify and speed up code, especially through the use
of better C++ data structures. This change builds on all platforms on
the buildbot.
2022-04-02 16:17:48 -05:00
Alaska
351c00d29a Fix T96973: Re-add Cycles shading menu to lights
This patch re-adds the shading menu to lights to allow people to use lights in light groups.
This patch also hides all settings in the shading menu that are not useful for the light object.

Reviewed By: lukasstockner97

Maniphest Tasks: T96973

Differential Revision: https://developer.blender.org/D14527
2022-04-02 22:42:57 +02:00
a567bef5cc Fix: Assert with set origin operation and single active object
Array has bounds checking that a raw pointer didn't have before.
2022-04-01 23:22:51 -05:00
ad35453cd1 Cycles: Add support for light groups
Light groups are a type of pass that only contains lighting from a subset of light sources.
They are created in the View layer, and light sources (lamps, objects with emissive materials
and/or the environment) can be assigned to a group.

Currently, each light group ends up generating its own version of the Combined pass.
In the future, additional types of passes (e.g. shadowcatcher) might be getting their own
per-lightgroup versions.

The lightgroup creation and assignment is not Cycles-specific, so Eevee or external render
engines could make use of it in the future.

Note that Lightgroups are identified by their name - therefore, the name of the Lightgroup
in the View Layer and the name that's set in an object's settings must match for it to be
included.
Currently, changing a Lightgroup's name does not update objects - this is planned for the
future, along with other features such as denoising for light groups and viewing them in
preview renders.

Original patch by Alex Fuller (@mistaed), with some polishing by Lukas Stockner (@lukasstockner97).

Differential Revision: https://developer.blender.org/D12871
2022-04-02 06:14:27 +02:00
5387d33e5f Cleanup: Further use of const for object bounding boxes
Also solves two warnings from the previous similar commit,
f688e3cc31. The change to the grease pencil
modifier is quite suspicious, but doesn't change the behavior,
which was already broken.
2022-04-01 18:30:09 -05:00
69c07adb51 Cleanup: Remove object bounding box function
This abstraction doesn't serve any purpose after 11c6d4e88e.
The flag on bounding boxes isn't used, except for the dirty tag.
2022-04-01 14:58:32 -05:00
59c3194f8e Cleanup: Use float3 type
This can help make some refactoring to bounding boxes slightly easier.
2022-04-01 14:48:48 -05:00
11c6d4e88e Cleanup: Remove unused boundbox flag
This flag hasn't been used for around four years. The convention in this
header seems to be commenting out the flag and adding "UNUSED" after it.
2022-04-01 13:55:17 -05:00
f688e3cc31 Cleanup: Use const for bounding boxes where possible 2022-04-01 13:45:02 -05:00
999f6526b1 Fix compiler error when building without USD and alembic 2022-04-01 20:12:09 +02:00
Stefan Werner
65dcb5ebd3 Cycles: Semantically separate 2D and 3D texture objects
Currently there are no functional changes.

Preparing for an upcoming oneAPI integration where such separation
in types is needed.
2022-04-01 19:44:31 +02:00
Stefan Werner
9c6dff70c8 Cycles: Introduce postfix for kernel body definition
Increases flexibility of code-generation for kernel entry points.

Currently no functional changes, preparing for integration with oneAPI.
2022-04-01 19:44:02 +02:00
Stefan Werner
542c03fed5 Cycles: Use single floating point precision sine/cosine in sky
Should be no functional changes.
2022-04-01 19:43:34 +02:00
Stefan Werner
633c8fc3c8 Cycles: Optimize Nishita sky
Reduce register pressure.
Helps with kernel compile time and render time.

Should be no functional changes.
2022-04-01 19:42:00 +02:00
8bec875586 install_deps: Update Embree to 3.13.3 and OIDN to 1.4.3.
Re {T95206}.
2022-04-01 17:47:15 +02:00
Olivier Maury
1fb0247497 Cycles: approximate shadow caustics using manifold next event estimation
This adds support for selective rendering of caustics in shadows of refractive
objects. Example uses are rendering of underwater caustics and eye caustics.

This is based on "Manifold Next Event Estimation", a method developed for
production rendering. The idea is to selectively enable shadow caustics on a
few objects in the scene where they have a big visual impact, without impacting
render performance for the rest of the scene.

The Shadow Caustic option must be manually enabled on light, caustic receiver
and caster objects. For such light paths, the Filter Glossy option will be
ignored and replaced by sharp caustics.

Currently this method has a various limitations:

* Only caustics in shadows of refractive objects work, which means no caustics
  from reflection or caustics that outside shadows. Only up to 4 refractive
  caustic bounces are supported.
* Caustic caster objects should have smooth normals.
* Not currently support for Metal GPU rendering.

In the future this method may be extended for more general caustics.

TECHNICAL DETAILS

This code adds manifold next event estimation through refractive surface(s) as a
new sampling technique for direct lighting, i.e. finding the point on the
refractive surface(s) along the path to a light sample, which satisfies Fermat's
principle for a given microfacet normal and the path's end points. This
technique involves walking on the "specular manifold" using a pseudo newton
solver. Such a manifold is defined by the specular constraint matrix from the
manifold exploration framework [2]. For each refractive interface, this
constraint is defined by enforcing that the generalized half-vector projection
onto the interface local tangent plane is null. The newton solver guides the
walk by linearizing the manifold locally before reprojecting the linear solution
onto the refractive surface. See paper [1] for more details about the technique
itself and [3] for the half-vector light transport formulation, from which it is
derived.

[1] Manifold Next Event Estimation
Johannes Hanika, Marc Droske, and Luca Fascione. 2015.
Comput. Graph. Forum 34, 4 (July 2015), 87–97.
https://jo.dreggn.org/home/2015_mnee.pdf

[2] Manifold exploration: a Markov Chain Monte Carlo technique for rendering
scenes with difficult specular transport Wenzel Jakob and Steve Marschner.
2012. ACM Trans. Graph. 31, 4, Article 58 (July 2012), 13 pages.
https://www.cs.cornell.edu/projects/manifolds-sg12/

[3] The Natural-Constraint Representation of the Path Space for Efficient
Light Transport Simulation. Anton S. Kaplanyan, Johannes Hanika, and Carsten
Dachsbacher. 2014. ACM Trans. Graph. 33, 4, Article 102 (July 2014), 13 pages.
https://cg.ivd.kit.edu/english/HSLT.php

The code for this samping technique was inserted at the light sampling stage
(direct lighting). If the walk is successful, it turns off path regularization
using a specialized flag in the path state (PATH_MNEE_SUCCESS). This flag tells
the integrator not to blur the brdf roughness further down the path (in a child
ray created from BSDF sampling). In addition, using a cascading mechanism of
flag values, we cull connections to caustic lights for this and children rays,
which should be resolved through MNEE.

This mechanism also cancels the MIS bsdf counter part at the casutic receiver
depth, in essence leaving MNEE as the only sampling technique from receivers
through refractive casters to caustic lights. This choice might not be optimal
when the light gets large wrt to the receiver, though this is usually not when
you want to use MNEE.

This connection culling strategy removes a fair amount of fireflies, at the cost
of introducing a slight bias. Because of the selective nature of the culling
mechanism, reflective caustics still benefit from the native path
regularization, which further removes fireflies on other surfaces (bouncing
light off casters).

Differential Revision: https://developer.blender.org/D13533
2022-04-01 17:45:39 +02:00
253e4e7ed2 Assets: Enable collection assets (no longer experimental)
With automatic collection previews (810e225c26) and a toggle for
collection instancing (previous commit) supported, there are no known
blocking issues for collection assets. There are still further
improvements to come as part of regular developemt (e.g. bounding box
based snapping).
2022-04-01 16:51:29 +02:00
eb1ede5693 Assets: Instancing operator option for collection asset dropping
Makes it possible to toggle instancing via the "Adjust Last Operation"
panel after dropping a collection asset into the viewport.

A design task that puts this into more context is pending still, but
this is a useful option to have either way.

Differential Revision: https://developer.blender.org/D14507

Reviewed by: Bastien Montagne
2022-04-01 16:44:52 +02:00
1de051a7a9 install_deps: Updated Alembic to 1.8.3 and OSD to 3.4.4.
Re {T95206}.
2022-04-01 16:43:29 +02:00
e81d7bfcc9 Cycles: enable Alembic procedural for final renders
The Alembic procedural was only enabled during viewport renders
originally because it did not have any caching strategy. Now that
is does, we can allow its usage in final renders.

This also removes the `dag_eval_mode` argument passing to
`ModifierTypeInfo.dependsOnTime` which was originally added to detect if
we are doing a viewport render for enabling the procedural.

Differential Revision: https://developer.blender.org/D14520
2022-04-01 16:30:45 +02:00
5c80543c43 Cleanup: Move geometry set fields to a separate header
This commit moves declarations that depend on `FN_field.hh` out of
`BKE_geometry_set.hh` into `BKE_geometry_fields.hh`. This helps to
reduce the number of areas that need to depend on the functions module,
which recently came in in review of D11591.

In the future we may have a library of standard field inputs in order to
make composing algorithms easier, so it makes sense to have a header
that could contain them and some basic related utilities relating the
concepts of geometry and fields.

Reducing use of unnecessary headers may also reduce compilation time.

Differential Revision: https://developer.blender.org/D14517
2022-04-01 08:40:45 -05:00
3ecdfd0938 Geometry Nodes: Add search to named attribute input node
This commit adds attribute search the the attribute input field node.
Because it's a field node, finding which attribute to display without
increasing the complexity a lot isn't obvious. In this commit, all
attributes used by nodes in the current group are included.

When an attribute is chosen from the list, the node's data type is
updated, and links connected to the output socket are reconnected.

Ref T96271

Differential Revision: https://developer.blender.org/D14516
2022-04-01 08:33:03 -05:00
00ba51d37b Geometry Nodes: Port set handle nodes to new data-block
This commit ports the "Set Handle Positions" and "Set Hanle Type"
nodes to use the new curves data-block. The nodes become simpler
and likely much faster too, though they're usually not the bottleneck
anyway.

Most of the code is ported from `BezierSpline` directly. The majority
of the complexity comes from the interaction between different
automatically calculated handle types. In comparison `BezierSpline`,
the calculation of auto handles is done eagerly-- mostly because it's
simpler. Eventually lazy calculation might be good to add.

Differential Revision: https://developer.blender.org/D14464
2022-04-01 08:12:41 -05:00
a250d3d1b7 Fix compositor memory leak after recent color management changes 2022-04-01 15:04:18 +02:00
d120a083da Fix T96763: New OBJ Exporter Incorrectly saving the materials in the MTL file
Original report (T96763) only reported the issue of double-space before the texture path, but while adding test coverage I found some other issues that I fixed while at it:

- Incorrectly emits two spaces between `map_Xx` keyword and the texture path, leading to some 3rd party software not finding the textures,
- Emissive texture map (`map_Ke`) was not exported,
- When Mapping node is used on the texture UVs, the "Location" and "Scale" values were mixed up (location written as "scale", scale written as "location).

Added gtest coverage.

Reviewed By: Howard Trickey

Differential Revision: https://developer.blender.org/D14519
2022-04-01 14:59:19 +03:00
b073f58a8e Fix T96930: Cloth Disk cache not being saved and being deleted on files that have been linked and library override enabled.
PointCache handing is just horrible from RNA, makes dealing with
overrides a nightmare...

Ended up having to add a specific 'apply' callback for the `use_disk_cache`
property, that would explicitely NOT call the the `update` callback of
this property, to avoid having the whole disk cache nuked away...

But the whole thing remains fairly britle, to say the least.
2022-04-01 12:41:59 +02:00
1264142f78 LibOverride: RNA Apply: let apply function responsible for calling update or not on overridden properties.
While this is the desired behavior in almost cases, there are a few
hairy nightmares that may require not to do so.

NOTE: this change should should not modify any current behavior at all.
2022-04-01 12:35:25 +02:00
d34c4089f1 Fix T96931: Crash on load with library overrides + multiple cloth cache slots.
Not really clear why that would only show with multiple caches... But
point cache system is beyond brittle anyway.

This fix solves the issue at two different levels:
* General safety check in `rna_Cache_info_length` that we do get a valid
  `pid`.
* Forbid usage of this `PointCache.info` RNA property in any
  diffing/LibOverride processing (since it's by definition runtime, volatile
  data).
2022-04-01 11:05:30 +02:00
9a67f9173b Cleanup: Improve variable naming
The variable `ofs` in `widget_numslider` was referring to the radius.
`rad` is more clear and consistent with the other widget functions.
2022-04-01 07:05:50 +02:00
aab9047f9d Fix T88785: Keep value slider from clipping
Keep the value slider from clipping through rounded corners for
low values by ensuring the width of the slider rectangle is at least
twice the corner radius.

Reviewed By: Hans Goudey

Differential Revision: https://developer.blender.org/D11474
2022-04-01 06:51:22 +02:00
42853bacc9 GPencil: Fix regression with dots uvs
This was introduced by rBeccb0b222e3465baa71430223c5ee2f0206a7b02.
2022-03-31 19:14:31 +02:00
ce5428b294 install_deps: Update OCIO to 2.1.1 and OIIO to 2.3.13.
Re {T95206}.
2022-03-31 17:40:37 +02:00
59681a7ccd install_deps: Update openVDB to 9.0.
Re {T95206}.
2022-03-31 16:56:34 +02:00
3d5085375f install_deps: default boost version to 1.78 and TBB to 2020_U3.
Re  T95206.
2022-03-31 16:25:02 +02:00
ca28f376f7 OBJ: mark the new 3.1+ exporter as experimental for now
While it still has known issues/bugs/limitations. Also do not make it the very first export menu item, while at it.

Differential: D14512
2022-03-31 16:15:02 +03:00
4c1393c202 Fix T76746: Alembic, wrong result importing back exported curves
In Alembic curve topology is stored with an array of values describing
how many points each sub-curve has. Instead of writing the number of
points for the current curve, the Alembic exporter would write the
accumulated number of points.

This error has existed since the initial implementation.
2022-03-31 15:01:27 +02:00
eb4155cc1e Fix T94888: LineArt use the same triangulation as viewport.
This fixes inconsistencies between line art output and viewport triangulation result.
2022-03-31 21:00:26 +08:00
2f7171622d DRW: Rename DRW_shgroup_uniform_vec4_array_copy to mat4_copy
This function was not used for anything other than mat4. This
was because of a limitation of the DRW module/
This makes it cleaner for the GLSL and also less tempting to use
it for other unconventional purpose.
2022-03-31 13:48:17 +02:00
ca37654b63 Fix T96920 DRW: Regression: Hair strands are drawn in wrong place
This was caused by the recent changes made to the way we handle matrix
copies. The matrix copy assumed that the uniform iteration was the same
as creation order. But this was far from true. The reality was that
the iterator was reverse for `unichunk` but not for `unichunk->uniforms`
so this was recreating wrong matrix.

I rewrote this part to always use reverse iteration and fix the
copy destination.

Also I simplified the code making the assumption this won't be used for
anything else than mat4.
2022-03-31 13:36:04 +02:00
0c6dc7c59e Outliner: New "Hierarchies" view mode for Library Overrides
Adds a dropdown for the Library Overrides display mode that lets users
choose between a "Properties" and a "Hierachies" view mode. The former
is what was previously there (a mode that displays all overridden
properties with buttons to edit the values), the latter is new. It
displays the hierarchical relationships between library overridden
data-blocks. E.g. to override the mesh of an object inside a linked
collection, the entire collection > object > mesh hierarchy needs to be
overridden (whereby the former two will be automatically overridden
using system overrides).
The Hierarchies mode will also show the override hierarchies of
data-blocks that were linked and are overridden in the source file. This
information is useful to have, especially for debugging scenes.

Part of T95802.

Differential Revision: https://developer.blender.org/D14440

Reviewed by: Bastien Montagne
2022-03-31 12:21:14 +02:00
2202259e9c Fix T96909: crash when assigning new node group to group node
The node group returned by `bpy.data.node_groups.new(...)` was not
updated properly.
2022-03-31 11:57:45 +02:00
dc73c71b3b Fix T96915: GPU subdivision modifier: Smooth Shade doesn't work
Simple error in an earlier commit, the flags should be or-ed.
2022-03-31 11:52:46 +02:00
7e54f5c218 Cleanup: make format 2022-03-31 11:00:42 +02:00
0d223f6aca Cleanup: Unused variable in release build warning 2022-03-31 09:26:46 +02:00
92f2b77e78 Cleanup: Compilation warnings in gpencil code after DNA C++ changes
Direct replacement of code:
- memcpy of a single point is done as a shallow_copy() assignment.
- memcpy of a range of points is done with an explicit cast to void*
  to tell compiler that we really want to memcpy even a non-trivial
  type.

In some cases it seems that memcpy can be used more (points are copied
in a loop). Those left as-is since this is supposed to be a simple
cleanup.

Differential Revision: https://developer.blender.org/D14505
2022-03-31 09:18:21 +02:00
ae1f8315f7 Depsgraph: minor optimization in order of checks
Checking BKE_image_user_id_has_animation loops over ID users
which never needs to run for material & world data-blocks.
2022-03-31 13:07:14 +11:00
3d132ead50 Cleanup: spelling, trailing space for comment-blocks 2022-03-31 13:01:41 +11:00
41ee5382f6 Cleanup: Remove unnecessary namespace specification 2022-03-30 20:55:40 -05:00
762d3a48e8 Cleanup: Avoid storing pointers for attribute search callback
It's better to use some local/stable identifiier to avoid relying on
the data not being freed in between creating the search menu and
the exec function. This is similar to c473b2ce8b.
2022-03-30 20:54:11 -05:00
Gilberto Rodrigues
49858bf526 UI: Fix outliner and buttons icons alignment
029cf23d71 changed some icons alignment, but after 9be49a1069
the icons don't align anymore. This commit reverts 029cf23d71 and
also makes a couple of other outliner icons left aligned, instead of
right aligned, for consistency and general alignment.

Differential Revision: https://developer.blender.org/D14501
2022-03-30 18:57:24 -05:00
8466fd4bd1 Cleanup: Curves draw cache renaming, use references
Also change some remaining cases of "hair object" to "curves object".
2022-03-30 18:25:06 -05:00
4edde244da Nodes: Cut hidden links when creating node groups
Add a check to the creation of node groups to remove hidden links
that are connected to the outside of the node group. This avoids
creating sockets in the group's interface that aren't (visibly)
connected to anything within the node group.

Reviewed By: Jacques Lucke, Hans Goudey

Differential Revision: https://developer.blender.org/D14249
2022-03-30 23:07:11 +02:00
2670032038 UI: Improve node editor dot background
This commit makes the dot grid used as background in the node editor
more visually stable when zooming in and out.

The dot grid now uses a continuously subdividing pattern, where
each level of subdivision divides the previous five times, similar to
the line grid in the 3D viewport.

The maximum for the "Grid Levels" theme setting is changed to 3, since
any further subdivisions are too small to be visible.
The "Grid Levels" value for the default themes "Blender Dark" and
"Blender Light" is therefore changed to 3, as well.

Reviewed By: Hans Goudey, Pablo Vazquez

Differential Revision: http://developer.blender.org/D13302
2022-03-30 21:21:57 +02:00
Jason Fielder
922d53a791 Metal: Adding alternative support for GPU_PRIM_TRI_FAN/LINE_LOOP For Metal backend.
- Metal uniform array compatibility in DRW module.
- Guard OpenGL-specific workarounds and flushes behind GPU_type_matches_ex API guard. Add further render boundaries for render paths called outside of the main loop.

Authored by Apple: Michael Parkin-White

Ref: T96261

Reviewed By: fclem

Differential Revision: https://developer.blender.org/D14438
2022-03-30 20:31:12 +02:00
84fde382e4 Fix T85689: Assume Win32 Volumes are Valid
Skip validation when inserting items into the Win32 "Volumes" list.
This fixes some long hangs when launching Blender with disconnected
network shares.

See D14506 for more details.

Differential Revision: https://developer.blender.org/D14506

Reviewed by Brecht Van Lommel
2022-03-30 11:10:15 -07:00
Jason Fielder
49bc640b76 Metal: GLSL Shader compatibility 5
MSL does not have an implicit global scope, this is emulated via macro's adding an indirection for uniforms, attributes, shader stage inputs and outputs such as:

#define roughness shaderinst->roughness.

Variables in GLSL which exist within uniform blocks can be directly referenced via the global scope, unlike standard C++. This means that variable name pollution occurs if subsequent local variables in the code use the same name, resulting in compilation errors.

A number of these conflicting names have been renamed to ensure unique naming and no further scope pollution.

Ref T96261

Reviewed By: fclem

Maniphest Tasks: T96261

Differential Revision: https://developer.blender.org/D14452
2022-03-30 19:53:22 +02:00
Jason Fielder
7c9e128bbf Metal: GLSL Compatibility - explicit mat4_to_mat3 conversion
Explicit constructor for mat3 from a mat4 is not valid and cannot be overloaded.

Adding explicit texture resource type flags for depth textures. This is an explicit requirement for Metal Shading language. This is a temporary compatibility, as this path is already supported in GPU_SHADER_CREATE_INFO under ImageType::DEPTH_2D, though required in shader source for MSL shaders which do not have create info.

Authored by Apple: Michael Parkin-White

Ref T96261

Reviewed By: fclem

Maniphest Tasks: T96261

Differential Revision: https://developer.blender.org/D14418
2022-03-30 19:47:00 +02:00
60a6fbf5b5 Curves: Port resample node to the new data-block
This commit re-implements the resample curve node to use the new curves
type instead of CurveEval. The largest changes come from the need to
keep track of offsets into the point attribute arrays, and the fact
that the attributes for all curves are stored in a flat array.

Another difference is that a bit more of the logic is handled by
building of the field network inputs. The idea is to let the field
evaluator handle potential optimizations while making the rest of the
code simpler.

When resampling 1 million small poly curves,the node is about 6
times faster compared to 3.1 on my hardware (500ms to 80ms).

This also adds support for Catmull Rom curve inputs.

Differential Revision: https://developer.blender.org/D14435
2022-03-30 10:37:39 -05:00
ba28c10199 Fix T96344: edit mode GPU subdivision crashes with X-ray mode and modifiers
The crash happens because the origindex layers created as part of
the modifier stack evaluation are not set in the `MeshRenderData` when
they should have been.

This is because when selecting in X-ray mode, a subdivision wrapper
is created to ensure that selection happens with a subdivided
geometry, and this replaces the `MDATA` wrapper which is also used to
setup the `MeshRenderData`.

As we do not seemingly have an `MDATA` wrapper, the draw code decides
that we can extract draw buffers directly from the BMesh, instead of
the mapped Mesh with origin indices layers.

To fix this, we should also consider to use mapped extraction if a
subdivision wrapper exists on the mesh.

Differential Revision: https://developer.blender.org/D14485
2022-03-30 17:31:40 +02:00
9b9fda2122 Overlay: Port Armature shader to ShaderCreateInfo
Should have no regression.
2022-03-30 15:50:06 +02:00
883326040e GL: Fix Invalid enum error on Apple Silicon
Guard shader storage related gets and bypass a buggy enum.

Fix T95592 OpenGL Invalid Enum
2022-03-30 15:50:05 +02:00
05a77bb0d8 Overlay: Port Edit Mode shaders to ShaderCreateInfo
This should have no regression.
2022-03-30 15:50:05 +02:00
4cd409ca98 DRW: Port draw_common.c to use shared definition with GLSL
# Conflicts:
#	source/blender/draw/intern/draw_common_shader_shared.h
#	source/blender/draw/intern/shaders/draw_view_info.hh
2022-03-30 15:50:05 +02:00
fb524d1675 GPUShaderCreateInfo: Add DepthWrite option
This option lets specify explicitely how the fragment shader will change
the fragment's depth.
2022-03-30 15:13:25 +02:00
5aa81594e6 GPU: ShaderBuilder: Remove do_static_compilation_ inheritance
This is because the inheritance is not done before checking if the shader
should be statically compiled. Also some inheritance scheme
might have intermediate permutation that are not compilable.
2022-03-30 15:13:25 +02:00
Pratik Borhade
66010b6deb Add soft limit for Bevel segments in modifier.
The recent change to allow a max segments of 1000 in the modifier
causes a lag when dragging or wheeling in the segments box.
This change makes the soft limit back to 100, but you can still
type numbers up to 1000 in the box.

Reviewed By: Howard Trickey
Differential Revision: https://developer.blender.org/D14477
2022-03-30 08:51:20 -04:00
9c3adb789a GPU: ShaderBuilder: Fix compilation on non-Mac platform
Regression introduced in rB664eb1936946a077498a17c22576763c664e3186
2022-03-30 14:02:11 +02:00
ecafa4c27c Compositor: Fix Missing output UI for Normal node
There were multiple issues at hand here:

- The default value has been changed to `{0, 0, 1}` see: rB25f1783673de636a6f0ca4457df8c05bc685981a
- The output needs the subtype set `PROP_DIRECTION`
- The noder properties were missing in `node_composit_set_butfunc`

Fixes T96860
2022-03-30 08:00:23 -04:00
3656e66ac2 Curves: support converting curves to legacy hair system
This adds a new operator that converts all selected curves objects
into hair particle systems on their respective surface objects. Existing
particle systems with the correct name are updated, otherwise a new
particle system is added.

The purpose of the operator is the make the new curve sculpting tools
useful even before all functionality is ported over from the old hair system.

The operator can be found in the `Object > Convert` menu in object mode,
when a curves object is active.

Differential Revision: https://developer.blender.org/D14441
2022-03-30 13:29:49 +02:00
9b25fafbec Cleanup: Left over from review of apply transform
I miss the review notes about this for the
8621fdb10d commit.
2022-03-30 12:24:46 +02:00
ebb49ddd83 GPencil: Fix double-free issue in update cache
When a `GPencilUpdateCacheNode` is created, it always allocates the
`children` pointer. This should not be freed until the whole cache is
deleted.
The `cache_node_update` would free the `children` pointer in a specific
case, causing a double-free later when the cache was removed.
2022-03-30 11:41:27 +02:00
8621fdb10d Apply Object Transform: Multi-user data support
The current behaviour is to prevent multi-user data from having its
transformation applied.

However in some particular cases it is possible to apply them:
* If all the users of the multi-user data are part of the selection.
* If not all the users are in the selection but the selection is made
single-user.

The active object is used as reference to set the transformation of the
other selected objects.

Note: For simplicity sake, this new behaviour is only available if all
the selection is using the same data.

Differential Revision: https://developer.blender.org/D14377
2022-03-30 11:07:57 +02:00
35f34a3cf8 Modifiers: Support applying modifiers for multi-user data
The current behaviour is to prevent multi-user data from having its
modifier applied.

Instead, with this patch, we now warn the user that if they want to
proceed the object will be made single-user.

Note that this only makes the object data single-user. Not the material
or actions.

As a future step we can apply the same behaviour for the Grease Pencil modifiers

Differential Revision: https://developer.blender.org/D14381
2022-03-30 11:06:10 +02:00
218bcff32d Iterator to loop over objects based on a flag 2022-03-30 11:06:01 +02:00
0f94c99ee7 Cleanup: clang-format 2022-03-30 18:02:59 +11:00
a8ec7845e0 Cleanup: use "num" as a suffix in: source/blender/blenlib
Also replace "num" with:
- "number" when it's not used to denote the number of items.
- "digits" when digits in a string are being manipulated.
2022-03-30 18:01:22 +11:00
af3aaf8034 Cleanup: use "num" as a suffix in: source/blender/gpencil_modifiers 2022-03-30 17:41:34 +11:00
e26c89cd76 Fix: Failing curves test after recent commit
87e9451d66 missed updating the behavior for Catmull Rom curves.
2022-03-29 23:39:03 -05:00
e74880a659 Cleanup: use utility function to initialize SelectPick_Params 2022-03-30 15:03:12 +11:00
0f33f0de00 Fix leak transforming in the node-editor without a selection 2022-03-30 14:05:33 +11:00
573b78b351 Cleanup: remove redundant lattice de-selection 2022-03-30 13:18:46 +11:00
Aleksi Juvani
eddffdd398 Cleanup: Move UV edit parameterize code to geometry module
This will allow reusing it elsewhere, such as in a geometry node.

Differential Revision: https://developer.blender.org/D14453
2022-03-29 20:57:59 -05:00
4a93c4bf1d Geometry Nodes: Remove soft min from extrude node scale
Extusion with a negative offset is possible and expected.
2022-03-29 20:46:41 -05:00
2499768e07 Keymap: "Mouse Select & Move" now uses click to de-select others
While it's useful for click-drag to leave the selection as-is
(when clicking on items that are already selected), it's useful
for a single click to de-select all other elements.

This also removes the need for the initial selection to set the object
as active since this is possible by clicking on it.
2022-03-30 12:34:14 +11:00
400ea40dca Curves: Port curves total length node to the new data-block
Ref T95443
2022-03-29 20:24:41 -05:00
62334c6ee4 Curves: Port length node to the new data-block
Ref T95443
2022-03-29 20:17:35 -05:00
f4f89a76a8 Curves: Port parameter node to the new data-block
Using the evaluated lengths cache from 72d25fa41d, re-implement
the curve parameter node with the new data structure. Conceptually
it works the same way, but the code is restructured and cleaned up
a bit as well. This also adds support for Catmull Rom curves.

Differential Revision: https://developer.blender.org/D14461
2022-03-29 20:11:38 -05:00
87e9451d66 Fix: Remove special case from curve segment size function
The idea that curves with two points cannot be cyclic came from some
existing code, but there's not fundamental reason for it, so remove the
check in this function. The case can be handled elsewhere if necessary.
2022-03-29 19:56:38 -05:00
72d25fa41d Curves: Add length cache, length paramerterize utility
This commit adds calculation of lengths along the curve for each
evaluated point. This is used for sampling, resampling, the "curve
parameter" node, and potentially more places in the future.

This commit also includes a utility for calculation of uniform samples
in blenlib. It can find evenlyspaced samples along a sequence of points
and use linear interpolation to move data from those points to the
samples. Making the utility more general aligns better with the more
functional approach of the new curves code and makes the behavior
available elsewhere.

A "color math" header is added to allow very basic interpolation
between two colors in the `blender::math` namespace.

Differential Revision: https://developer.blender.org/D14382
2022-03-29 19:45:59 -05:00
bcb9379c6d Cleanup: quiet warning for description ending with a full stop 2022-03-30 11:41:34 +11:00
9ae98f305a Cleanup: spelling in comments 2022-03-30 11:38:24 +11:00
be8270bc76 Cleanup: use equality instead of contains for single-item sets 2022-03-30 11:27:54 +11:00
87e5c4230f Cleanup: unbalanced doxy sections 2022-03-30 11:17:16 +11:00
ee1d5fb9e4 UI: Fix cosmetic papercuts of the reroute node
Fix small cosmetic issues with the reroute node:
1. Remove special case that allowed curved links to attach vertically.
2. Center align the reroute node's label.

The vertically attached node links could lead to kinks in the otherwise
smooth curves. This would break the visual flow and make the link
potentially intersect the node's label.

The center alignment of the label gives more consistent results for
different label lengths and also reduces the chance of the label
interfering with the node links.

Reviewed By: Hans Goudey, Pablo Vazquez

Differential Revision: D14457
2022-03-29 23:39:50 +02:00
08b4b657b6 Geometry Nodes: Don't create node tree when adding nodes modifier
Don't always create a new geometry nodes node tree when adding a
geometry nodes modifier.

This avoids files getting cluttered with empty and unused geometry node
trees that are created every time a nodes modifier is added to an
object - even if only to apply an already existing.
This is also more consistent with other modifiers that also don't
automatically create new data blocks.

The new modifier still automatically gets populated with a new node
tree when adding it via the "New" button in the header of the
geometry nodes editor.

Reviewed By: Hans Goudey, Dalai Felinto, Pablo Vazquez

Differential Revision: D14458
2022-03-29 22:30:51 +02:00
4eb4c90cf6 GPencil: Remove UI prefix Use in Dot-Dash modifier
The "Use" word must not be used in UI.
2022-03-29 22:26:44 +02:00
ac9ddf54a0 Fix: incorrect assert in new code 2022-03-29 14:39:18 -05:00
ac40d40cb7 GPencil: Fix Windows compiler errors
For non trivial data must be used `MEM_new`
2022-03-29 19:32:28 +02:00
5596f79821 LibOverride: Massive edits to 'editable' IDs checks in editors code.
Add new `BKE_id_is_editable` helper in `BKE_lib_id.h`, that supercedes
previous check (simple `ID_IS_LINKED()` macro) for many editing cases.

This allows to also take into account 'system override' (aka
non-editable override) case.

Ref: {T95707}.
2022-03-29 17:59:55 +02:00
354db59fb1 LibOverride: Rename 'delete hierarchy' to 'clear hierarchy', add 'clear single' operations.
'Delete' was a confusing name, even though it would delete the overrides
it would replace them by linked data.

Adding the 'single' version of that operation made it even more
confusing, since often it has to keep the override ID for sakes of
hierarchy, and just reset it and turn it back into a non-editable system
override.

Ref: {T95707}.
2022-03-29 17:59:43 +02:00
6cc9ba94b7 LibOverride: Implement default 'user override' behavior.
Implement default behavior to decide which overrides remain 'system'
ones, and which become 'user editable' ones, when creating hierarchy
override from 3DView or the Outliner.

3DView:
If from an Empty-instanced collection, only Armature objects in
that collection are user overrides.
If from a set of selected objects, all overrides created from selected
objects are user overrides.

Outliner:
All override IDs created from selected elements in the Outliner are user
overrides.
There is one special case: When a collection is selected, and is
'closed' in the outliner, all its inner armature objects are also user
overrides.

Ref: {T95707}.
2022-03-29 17:59:31 +02:00
d7c802c25f LibOverride: Add initial handling of system overrides in creation/duplication/resync code, and some basic do_version.
When creating with hierarchies, core code only generates system
overrides, responsibility to define 'user overrides' is then for the
higher-level calling code (Editor/Operator-level).

do_version code uses fairly basic euristics, should be good enough here
though in most cases. and can always be refined later if needed.

Ref: {T95707}.
2022-03-29 17:59:17 +02:00
b5f2c77658 LibOverride: make some override properties 'overridable'.
The whole liboverride data is still ignored by override diffing etc.,
but some of their flags should be editable (from script and/or advanced
technical/debug UI). So using a weird combination of flags to achieve
this.

Ref: {T95707}.
2022-03-29 17:59:05 +02:00
9394d455af LibOverride: Add a new 'virtual' non-editable override icon and use it in Outliner.
Ref: {T95707}.
2022-03-29 17:58:53 +02:00
5adcf6c85e LibOverride: Add initial System Override flag.
This merely adds the flag, exposes it in RMA, and uses it in some of the
most common 'is editable' checks (RNA, `BASE_EDITABLE` macro...).

Next step: do_version and defining systemoverrides at creation.

Ref: {T95707}.
2022-03-29 17:58:40 +02:00
1013084038 GPencil: Small UI tweaks to Build modifier
Changes in some names.
2022-03-29 17:38:22 +02:00
9a0e1950ea Cover DNA_gpencil_types.h with C++ structure methods
Ref T96847

Maniphest Tasks: T96847

Differential Revision: https://developer.blender.org/D14487
2022-03-29 17:21:02 +02:00
1f6c2507f8 Cleanup: Remove legacy dupli system from point cloud object
The "dupli" system now has a faster, more powerful, and more flexible
alternative with geometry nodes. Since the point cloud objects haven't
been exposed in the non-experimental UI yet, we can remove the dupli
implementation and the panel for the object type.

Differential Revision: https://developer.blender.org/D14482
2022-03-29 10:16:05 -05:00
c4e4924096 GPencil: Fading for build modifier.
Adds fading support for build modifier so it's not a hard cut off

Reviewed By: Antonio Vazquez (antoniov), Matias Mendiola (mendio)

Differential Revision: https://developer.blender.org/D14309
2022-03-29 22:46:56 +08:00
Henrik Dick
0e0977f3e6 GPencil: Fix sculpt mask ignoring one point strokes
The check for the selected status was missing in the case
where the stroke one has one point.

Differential Revision: http://developer.blender.org/D14490
2022-03-29 16:22:52 +02:00
810e225c26 Assets: Support automatic collection previews
Adds supports for collection previews that are rendered automatically when
collections are marked as assets. (Or when preview rendering is triggered
differently, e.g. through the //Refresh Data-Block Previews// operator).

Idea in this patch is to create a collection instance empty outside of main for
the collection, and then reuse the object rendering code to render the preview.
This keeps things very simple and works just fine.

Differential Revision: https://developer.blender.org/D14460

Reviewed by: Bastien Montagne
2022-03-29 15:37:22 +02:00
Yuki Hashimoto
9ec77d709c Fix T63795: Display custom properties with brackets in info
When custom properties are changed, they are displayed with brackets in
info.

Ref D14380
2022-03-30 00:29:15 +11:00
4a5cd4e6c7 Fix T96844: Crash when switching workspaces and outliner modes
Error exposed by ba49345705. Code just assumed that the tree-element
pointed to a real ID, but this is often not the case, and the ID pointer
contains completely different data. E.g. before ba49345705, it would
be a pointer to one of the `Main` listbases, so this code would have
undefined behavior. Now the pointer is null for elements in the "Current
File" element, causing a null-pointer dereference rather than undefined
behavior (that just happened to virtually always result in the intended
code path).
2022-03-29 15:24:02 +02:00
fced604acf Curves: improve Snake Hook brush
This implements the spherical brush and different falloff
modes for the Snake Hook brush.

Differential Revision: https://developer.blender.org/D14408
2022-03-29 14:46:14 +02:00
4def6e8072 Icons: Programmatically create indirect library icon, remove from SVG
The indirect library data icon was just a grayed out version of the
regular one. This graying out is now done in code, so the icon can be
removed from the SVG. Note that the icon is still defined as
`ICON_LIBRARY_DATA_INDIRECT` (or `LIBRARY_DATA_INDIRECT` in BPY).
2022-03-29 14:36:06 +02:00
62c73db734 Fix T96835: Grease pencil tweak tool selects but doesn't drag
Use the pass-through matching the view3d.select operator.
2022-03-29 22:20:38 +11:00
2aa49107a2 Fix T96356: artefacts with GPU subdivision and vertex paint mask
The lines paint mask IBO extraction was not implemented for GPU subdivision.
For it to work, we also now need to preserve the subdivision loop to
subdivision edge map, which until now was overwritten to store coarse edges
(the map to coarse edges is still preserved).

Also the paint flag stored in the 4th dimension of the loop normal buffer
was not properly set for flat shaded faces, leading to other kind of
artefacts and render issues.
2022-03-29 12:04:51 +02:00
17757eabc7 Cleanup: Remove commented lines of previous commit 2022-03-29 11:28:38 +02:00
9450057b43 Fix T96799: GPencil weight_get API cannot retrieve weights
The problem was when the stroke had less weights that the total number of vertex groups.

The API checked the total number of groups, but this is not required because `BKE_defvert_find_index` returns NULL is the vertex group index does not exist.
2022-03-29 11:26:13 +02:00
31bcab0ecb Fix (unreported) LibOverride: re-creation of overrides in consecutive partial overrides of a same hierarchy.
If creating partial hierarchy overrides (from the outliner e.g.), that
need to create extra overrides, those could be re-created everytime,
leading to very bad situation where there would be several overrides of
the same reference ID in the same override hierarchy.

This fix makes it so that existing overrides in a given hierarchy will
always be re-used in case other overrides are added to the hierarchy.
2022-03-29 11:21:39 +02:00
c772461741 Cleanup: Use higher level semantic for zeroing DNA objects in C++
Replaces old-style memzero-style of call with zero-initializer.
Allows to shorten typical initialization code to a single line:

  Object foo = blender:🧬:shallow_zero_initialize<Object>()

This will allow to more easily convert designated initializer
which is often used to fill object with zeroes to the explicit
function calls:

  MyDNAStruct foo = {};

will be translated to

  MyDNAStruct foo = blender:🧬:shallow_zero_initialize<MyDNAStruct>();

Differential Revision: https://developer.blender.org/D14486
2022-03-29 11:04:50 +02:00
a264dff4fa BLI: optimize Map/Set/VectorSet.clear methods
Previously, those methods would destruct and reconstruct
the data structure. While that was more simple in initial
implementation, it has some downsides which are not resolved:
* Already allocated memory is lost. So new memory would have
  to be allocated when the data structure is refilled.
* The clearing process itself was slower because it did unnecessary
  work.
2022-03-29 10:41:01 +02:00
29d9bb89ce Cleanup: Remove redundant DNA C++ helper function
Use shallow_copy, no need in copy_memory.

The latter appeared as some last minute solution for a compilation
warning on Friday.
2022-03-29 10:14:57 +02:00
3c6c15d676 Functions: move loops into function builders
This simplifies debugging, and can help improve performance
by making it easier for the compiler.

More optimization might still be possible by using `__restrict` in
a few places.
2022-03-29 10:11:49 +02:00
c55afdf30b BLI: add utility to convert IndexMask to best mask type 2022-03-29 10:07:18 +02:00
7bd614d431 Cleanup: use value initialization instead of copying default value
Value-initialization has the potential to be more efficient.
Also, the code becomes simpler.
2022-03-29 09:29:09 +02:00
d7c6442118 BLI: support value initialization in CPPType
Value initialization differs from default-construction in that it
also zero-initializes trivial types.
2022-03-29 09:29:09 +02:00
d4bdf21929 Fix T96701: RMB select fails to show gizmo on mouse button release
Regression in [0] which removed a special check when tweak events ended.
Add a similar check for drag events that runs drag is disabled in the
main event handling loop.

[0]: 4986f71848
2022-03-29 16:56:55 +11:00
540bfbbb27 Fix T96582: Wipe effect not working
Caused by oversight in 0e38002dd5. Constant x/y value was used to
calculate transition instead of pixel x/y coords.
2022-03-29 05:07:58 +02:00
e74420124f Fix T96699: Splitting strip does not copy animation
Since e49bf4019b, animation is handled explicitly. Split operator
wasn't updated.

Re-use backup-duplicate-restore animation functions, that other
operators use for splitting.
2022-03-29 04:19:27 +02:00
f99beb730a Fix T96347: Pose gizmo shown at wrong location with multiple objects
Regression in [0] error iterating over pose bones which only used the
active-object, also follow the same logic as edit-mode for using the
local-matrix.

[0]: d052169e7e
2022-03-29 12:57:33 +11:00
87d9d33c00 Fix T96691: Heap corruption in file_browse_exec
Regression in [0], also use pad buffer by 1 instead of 2 which is no
longer needed as the trailing slash is no longer added
after allocating the string.

0682af0d63
2022-03-29 11:39:22 +11:00
27424b758a Cleanup: Move two grease pencil files to C++
This is meant to allow using C++ data structures in this file
as a performance improvement. Particularly `Vector` instead
of `ListBase` for `duplilist`. This changes builds on all
platforms on the buildbot.
2022-03-28 16:29:36 -05:00
fc288d3970 Cleanup: Move scene.c to C++
This is meant to allow using C++ data structures in this file
as a performance improvement. Particularly `Vector` instead
of `ListBase` for `duplilist`. This change builds and passes
tests on all platforms on the buildbot.
2022-03-28 15:53:19 -05:00
c9f54cd644 Cleanup: Use const mesh arguments
Also correct an enum value from review of D14475.
2022-03-28 15:12:30 -05:00
037f789111 Cleanup: Move transform_snap_object.c to C++
This is meant to allow using C++ data structures in this file
as a performance improvement. Particularly `Vector` instead
of `ListBase` for `duplilist`.

Differential Revision: https://developer.blender.org/D14475
2022-03-28 14:59:42 -05:00
21e72496a6 Fix T96728: 'Automatic Constraint' using the wrong orientation
If the `Automatic Constraint` modifier was activated while an axis
constraint was already set, the orientation used would be the default
orientation of the mode and not that of the scene.

This was because the `initSelectConstraint` function was not called in
this case and the `Automatic Constraint` mode was enabled by other
indirect means.

So the solution is to call `initSelectConstraint` in either case and
remove these "indirect means" of enabling `Automatic Constraint`.
2022-03-28 14:21:33 -03:00
df4d6c22cf Transform: avoid excessive recalculation with 'TREDRAW_SOFT'
Contrary to the initial intention (in rB9916e0193c36), `TREDRAW_SOFT`
flag, when isolated, is not cleared in `transformApply` and therefore is
used in the `drawTransformApply` callback which basically recalculates
the `transformation` which finally clears the flag.

So remove the `drawTransformApply` callback so `transformApply` is not
called when unnecessary.

Differential Revision: https://developer.blender.org/D14430
2022-03-28 14:18:56 -03:00
854af0cd09 Cleanup/Refactor: remove unused 'SNAP_ONLY_ACTIVE' enum parameter
`SNAP_ONLY_ACTIVE` was implemented in order to be used in the Knife tool,
but the project did not go ahead.
2022-03-28 13:55:13 -03:00
39df927b4a Transform: Improve 'absolute grid snap' support detection
The solution supposedly listed all cases that `absolute grid snapping`
was supported. But it ignored some occasions like: Editing Surface
objects, Texture Space.

List now only the cases where this feature should not be supported.
2022-03-28 13:55:13 -03:00
4c66021ccc Cleanup: transform, use early returns
This makes the flow clearer and avoids many `else` conditions.
2022-03-28 13:55:12 -03:00
8b5292a60e Outliner: Don't show indirectly linked Library Overrides properties
The Library Overrides display mode is meant to show overridden
properties from the current file only, not library overrides in
data-blocks that just were linked in. The upcoming Hierarchies view mode
for Library Overrides will also display linked in data-blocks that have
overrides in the source file (but not the individual overridden
properties), see T95802.
2022-03-28 18:03:57 +02:00
2e99295d5e Fix T96812: Regression: Snapping is broken with proportional editing
This was a mistake in the conditional structure introduced in 4b35d6950d

This commit also adds a new type of snap exclusion: `SNAP_NOT_EDITED`.

Thanks to @Ethan1080 for pointing out the error.
2022-03-28 11:26:48 -03:00
e6dfe570cc Fix T96828: GPencil primitives handlers not working
Following the logic is not necessary to check the mouse button because the status has changed before.
2022-03-28 13:11:07 +02:00
555e7c2091 Cleanup: Use bool literals in return statements of text editor poll functions. 2022-03-28 12:11:44 +02:00
da130d751f Fix various UI messages issues. 2022-03-28 10:40:14 +02:00
587efa9949 Fix (unreported) crash in some mesh-from-object code.
Crashed e.g. FBX exporter.

Mistake in rB0c33e84020deca.
2022-03-28 09:53:17 +02:00
af1341322f Fix T96670: bake from multires not reflected in the Image Editor. 2022-03-28 08:28:09 +02:00
387b34f0c2 Cleanup: return success from python_script_error_jump
Relying on checks for the assignment of return arguments isn't so
clear especially when there are multiple return arguments.
2022-03-28 17:15:41 +11:00
1466f480c4 Python: select the start-end range of syntax errors
Python 3.10's syntax errors can specify a range.
Use this for text editor error selection.
2022-03-28 17:06:38 +11:00
0ce6ed4753 Cleanup: variable/argument naming for Python exception access
Names filename/filepath/fn were used interchangeably.
2022-03-28 16:54:31 +11:00
3ea90de9e6 Fix text editor failure to move the cursor for syntax errors
This broke between 3.0 and 3.1, upgrading to Python 3.10 seems the
likely cause as this code didn't change.
2022-03-28 16:44:25 +11:00
e8fd2d8469 Cleanup: early exit when there is no exception
Reduces noise in D9752, no functional change as PyErr_NormalizeException
doesn't do anything when there is no exception set.
2022-03-28 15:06:47 +11:00
6f305577b3 Cleanup: use "num" as a suffix in: source/blender/modifiers
Also rename DNA struct members.
2022-03-28 14:41:31 +11:00
24839fdefa Cleanup: use "num" as a suffix in: source/blender/nodes 2022-03-28 14:14:31 +11:00
556384ca1d Cleanup: use "num" as a suffix in: source/blender/render
See T85728
2022-03-28 14:14:31 +11:00
83c274ccfc Cleanup: use "num" as a suffix in: source/blender/python
See T85728
2022-03-28 14:14:31 +11:00
77155ae1c0 Cleanup: Reduce duplication to prepare for UDIM packing
In preparation for supporting packing of UDIM tiled textures, this patch
refactors a small portion of image.cc. The refactor should lead to less
duplicate code now and when Tiled images are added in the near future.

This patch is based on the prior work done for D6492 where it was
requested this part be split and can be summarized as follows:
 - `load_sequence_single` is removed and merged with `load_image_single`
 - `image_load_sequence_file` is removed and merged with `image_load_image_file`

Reviewed By: lukasstockner97

Differential Revision: https://developer.blender.org/D14327
2022-03-27 17:49:26 -07:00
e2e4c1daaa OBJ: use fmt library instead of sprintf for faster formatting
On Windows/MSVC this gives a minor (~20%) speedup presumably due to a faster float/int formatter. On macOS (Xcode13), this gives a massive speedup, since snprintf that is in system libraries ends up spending almost all the time inside some locale-related mutex lock.

The actual exporter code becomes quite a bit smaller too, since it does not have to do any juggling to support std::string arguments, and the buffer handling code is smaller as well.

Windows (VS2022 release build, Ryzen 5950X 32 threads) timings:
- Blender 3.0 splash scene (2.4GB obj): 4.57s -> 3.86s
- Monkey subdivided level 6 (330MB obj): 1.10s -> 0.99s

macOS (Xcode 13 release build, Apple M1Max) timings:
- Blender 3.0 splash scene (2.4GB obj): 21.03s -> 5.52s
- Monkey subdivided level 6 (330MB obj): 3.28s -> 1.20s

Linux (ThreadRipper 3960X 48 threads) timings:
- Blender 3.0 splash scene (2.4GB obj): 10.10s -> 4.40s
- Monkey subdivided level 6 (330MB obj): 2.16s -> 1.37s

The produced obj/mtl files are identical to before.

Reviewed By: Howard Trickey, Dalai Felinto

Differential Revision: https://developer.blender.org/D13998
2022-03-27 14:25:48 +03:00
3e12488b4e Cleanup: Remove frameserver cmake definition
Left over from rBaab5ac25f2c2e6fbc50f9fb352e71ef0ae0ba2f1
2022-03-26 21:59:22 -04:00
Lictex Steaven
08d2428632 GPencil: Add an xray toggle for each annotation layer
so a layer can be occluded by the scene instead of always showing in front

---

{F12827163}

Reviewed By: fclem, antoniov

Differential Revision: https://developer.blender.org/D13931
2022-03-26 18:26:43 +01:00
082b063f2a Increase bevel segment limit in modifier from 100 to 1000.
A user asked for this increase. The performance lags when reaching
the upper limit of this number of segments, but if you need that
many segments, I guess you are willing to wait.
2022-03-26 13:20:16 -04:00
ffafe494f6 Cleanup: Remove double #ifdef WITH_TBB check 2022-03-26 09:55:08 -06:00
9d25418a52 Fix T95901: Crash in Fill curve (set to N-gon)
The code that eats away faces until you find input faces in
the Constrained Delaunay Triangulation goes too far and crashes
when there are no input faces. In the test case there were input
faces but they only had two vertices, so were all ignored.
2022-03-26 10:47:09 -04:00
4039e94422 Fix T96790: Gpencil Inverted Fill makes extra stroke at origin
The problem was the stroke was created in the inverted loop before checking if the total of points is 0 and exit the loop.

Also some code Cleanup.
2022-03-26 13:20:46 +01:00
23bbc0d748 DRW: Port draw_common.c to use shared definition with GLSL 2022-03-26 13:16:01 +01:00
6073b6b874 GPU: ShaderBuilder: Skip shader compilation for unsupported shaders. 2022-03-26 13:16:01 +01:00
ab97add5fa GL: Fix shader error logging on Apple M1 hardware 2022-03-26 13:16:01 +01:00
664eb19369 GPU: ShaderBuilder: Fix compilation on Mac
This is less than ideal as it seems to link against all
of blender disregarding the stubs.
2022-03-26 13:16:01 +01:00
9c41767d57 Cleanup: move eFileSel_Action from DNA to WM_api.h
This isn't stored in blend files so it can be moved out of DNA.

Also use an enum for `WM_FILESEL_*` members.
2022-03-26 18:42:33 +11:00
4d5e8e5477 Fix incorrect argument for rigid-body world export 2022-03-26 18:36:28 +11:00
c01afe9562 Cleanup: use "use_" prefix for booleans 2022-03-26 18:04:27 +11:00
c330c7a5da Cleanup: quiet compiler warning 2022-03-26 18:04:19 +11:00
1909fd2781 Windows/Installer: Fix capital B in shortcut
the shortcut placed on the desktop and in the start
menu on windows were labelled `blender` rather than `Blender`

spotted by @Severin
2022-03-25 15:17:48 -06:00
6bf51ab03a CMake: Give some extra space to info_cfg_option
WITH_PYTHON_INSTALL_ZSTANDARD was too long and
didn't align very well compared to the other
items in the list.
2022-03-25 14:33:39 -06:00
ba49345705 Fix Outliner highlighting multiple base elements in different libraries
In the Blender File display mode of the Outliner, mouse hovering a
"base" element (e.g. "Objects", "Materials", ...) would also highlight
that same base element in other libraries linked into the scene. In fact
operations like (un)collapsing would be applied to both too.
Issue was that we'd always use the listbase containing the data-blocks
from the current main as a way to identify the tree element. So for the
same data-block types we'd use the same listbase pointers. Instead use
the the library pointer + a per library index.
2022-03-25 19:00:04 +01:00
2631b44e71 MSVC: Fix linker issue with USD
USD requires to be linked with /WHOLEARCHIVE so
the linker won't remove their static initializers.

This strangely has never worked for MSVC since
the flags were set on the LINK_FLAGS property
which is only used to link .dll and .exe files,
given this is a static lib, the flags were not
used, nor did CMake propagate the link directive
to the final targets that did link. Not quite sure
how this has not lead to more problems in the past.

Setting the link directive on the INTERFACE_LINK_OPTIONS
makes cmake do the right thing.

Differential Revision: https://developer.blender.org/D14394
Reviewed by: sybren
2022-03-25 10:15:11 -06:00
19bcfba56f USD I/O: explicitly set or clear the OPTYPE_UNDO flag
Exporting USD cannot be undone, but importing should be undo'able.
2022-03-25 16:53:17 +01:00
2fc77071b5 Image editor: not updating after image operation.
Fixes T96324, T96312, T96323
2022-03-25 16:36:50 +01:00
c671a26637 USD: Support building against USD 21.11+
For 3.2 USD will be bumped to a newer version with some
slight API changes, however since we cannot simultaneously
land the libs for all platforms as well as these code changes,
we'll have to support both 21.02 and 21.11+ for at least a
short period of time making the code slightly more messy than
it could have been.

Differential Revision: https://developer.blender.org/D14184
Reviewed by: sybren
2022-03-25 09:29:39 -06:00
378022c797 BLI: Adjust interpolation to support integers, other tweaks
In order to allow interpolation of integers with a float, add a separate
template parameter for the factor and multiplication types.
Also move some helper constexpr variables to the "base" header
(reversing the dependency to "base" -> "vector").

This also adds a distance function for scalar types, which is
helpful to allow sharing code between vectors and basic types.

Differential Revision: https://developer.blender.org/D14446
2022-03-25 09:57:10 -05:00
1243cb803e Cleanup: Add asserts, remove default case 2022-03-25 09:12:31 -05:00
cea51c1bb5 Curves: Bezier and general interpolate to evaluated utility
This commit implements generic evaluation for Bezier curves (which is
really just linear interpolation, since attributes are not stored on
Bezier handles). For complete parity with the old curve type, we would
have to add options for this (RNA: `Spline.radius_interpolation`),
but it's not clear that we want to do that.

This also adds a generic `interpolate_to_evaluate` utility on curves
that hides the implementation details. Though there is theoretically
a performance cost to that, without some abstraction calling code
would usually be too complex.

Differential Revision: https://developer.blender.org/D14447
2022-03-25 09:03:35 -05:00
c0016d85b2 Curves: Add a utility to count curves of each type
This commit adds a utility that returns an array with the number
of curves of every type. One use case for this is detecting whether
to remove handle or NURBS attributes when changing curve types.
It's best to avoid using this when it's not necessary, but sometimes
it can't really be avoided, and having a utility at least makes using
an optimized version simple.

In the future, this information can be cached in the curves runtime.

Differential Revision: https://developer.blender.org/D14448
2022-03-25 09:00:30 -05:00
59de9ceda0 MSVC: Fix build issue with webp
The webp variables should only be set if
the libs actually exist in the lib folder
2022-03-25 07:31:15 -06:00
97f2210157 GPencil: Cyclic flag for dot dash modifier
Cyclic option per segment, allows interesting "loop" visual effects.

Reviewed by: Antonio Vazquez (antoniov)

Differential Revision: https://developer.blender.org/D14439
2022-03-25 20:13:50 +08:00
Henrik Dick
d4e1458db3 GPencil: Improve smooth operation
This patch makes the grease pencil smooth operation symmetric.
It also increases the performance a lot if strong smoothing is
required. Additionally there is an option for the position smooth
operation to keep the shape closer to the original for more iterations.

Since the result differs from the previous algorithm, versioning is used
to change the iterations and factor to match the old result.

Differential Revision: http://developer.blender.org/D14325
2022-03-25 11:51:45 +01:00
0c33e84020 Fix compilation warnings after previous change
Thanks Jacques for finding solution for deprecation warning
which was generated by GCC for constructor.

The rest of the change is related on fixing memaccess warning
which was happening when memset/memcpy was used directly on
the DNA object pointer. Now there are two utility functions
for this:

- blender:🧬:zero_memory
- blender:🧬:copy_memory
2022-03-25 11:45:50 +01:00
03df72ee4e Implement C++ methods for DNA structures
This change makes it possible to add implementation of common
C++ methods for DNA structures which helps ensuring unsafe
operations like shallow copy are done explicitly.

For example, creating a shallow copy used to be:

  Object temp_object = *input_object;

In the C++ context it was seen like the temp_object is
properly decoupled from the input object, while in the
reality is it not. Now this code becomes:

  Object temp_object = blender:🧬:shallow_copy(*input_object);

The copy and move constructor and assignment operators are
now explicitly disabled.

Other than a more explicit resource management this change
also solves a lot of warnings generated by the implicitly
defined copy constructors w.r.t dealing with deprecated fields.
These warnings were generated by Apple Clang when a shallow
object copy was created via implicitly defined copy constructor.

In order to enable C++ methods for DNA structures a newly added
macro `DNA_DEFINE_CXX_METHODS()` is to be used:

  tpyedef struct Object {
    DNA_DEFINE_CXX_METHODS(Object)
    ...
  } Object;

For the shallow copy use `blender:🧬:shallow_copy()`.

The implementation of the memcpy is hidden via an internal DNA
function to avoid pulling `string.h` into every DNA header.
This means that the solution does not affect on the headers
dependencies.

---

Ideally `DNA_shallow_copy` would be defined in a more explicit
header, but don;t think we have a suitable one already. Maybe
we can introduce `DNA_access.h` ?

Differential Revision: https://developer.blender.org/D14427
2022-03-25 11:45:50 +01:00
75b8c4fc18 LibOverride: Prevent some more potential modification of overridden collections. 2022-03-25 11:39:06 +01:00
484af996aa Revert "Implement C++ methods for DNA structures"
This reverts commit 8c44793228.

Apparently, this generated a lot of warnings in GCC.

Didn't find a quick solution and is it not something I want to be
trading between (more quiet Clang in an expense of less quiet GCC).

Will re-iterate on the patch are re-commit it.
2022-03-25 10:57:13 +01:00
8c44793228 Implement C++ methods for DNA structures
This change makes it possible to add implementation of common
C++ methods for DNA structures which helps ensuring unsafe
operations like shallow copy are done explicitly.

For example, creating a shallow copy used to be:

  Object temp_object = *input_object;

In the C++ context it was seen like the temp_object is
properly decoupled from the input object, while in the
reality is it not. Now this code becomes:

  Object temp_object = blender:🧬:shallow_copy(*input_object);

The copy and move constructor and assignment operators are
now explicitly disabled.

Other than a more explicit resource management this change
also solves a lot of warnings generated by the implicitly
defined copy constructors w.r.t dealing with deprecated fields.
These warnings were generated by Apple Clang when a shallow
object copy was created via implicitly defined copy constructor.

In order to enable C++ methods for DNA structures a newly added
macro `DNA_DEFINE_CXX_METHODS()` is to be used:

  tpyedef struct Object {
    DNA_DEFINE_CXX_METHODS(Object)
    ...
  } Object;

For the shallow copy use `blender:🧬:shallow_copy()`.

The implementation of the memcpy is hidden via an internal DNA
function to avoid pulling `string.h` into every DNA header.
This means that the solution does not affect on the headers
dependencies.

---

Ideally `DNA_shallow_copy` would be defined in a more explicit
header, but don;t think we have a suitable one already. Maybe
we can introduce `DNA_access.h` ?

Differential Revision: https://developer.blender.org/D14427
2022-03-25 10:37:56 +01:00
315210c22b XR: Fix crash on executing some action operators
Since the XR area does not have any region geometry, hud updates from
operators would cause invalid access when updating region sizes.
2022-03-25 13:22:04 +09:00
93f2ebe7dd Cleanup: use doxy sections for customdata.cc 2022-03-25 14:54:16 +11:00
8ed4638960 Fix: Small fixes for NURBS evaluation
Clear the nurbs basis cache dirty flag when its evaluation finishes.
Remove an incorrect assert that the evaluated size couldn't be zero.
It can, when `check_valid_size_and_order` returns false.
2022-03-24 22:31:50 -05:00
9b2879f8b3 Cleanup: Simplify logic, rename variables
Return the map of gathered attributes directly, use simpler
naming for "attributes" and "gathered_attributes".
2022-03-24 22:29:23 -05:00
83c99ccb21 Cleanup: Use more specific variable name 2022-03-24 22:17:54 -05:00
797a1356ca Curves: Tweak evaluated offset functions
Add a function to retrieve the points for an index range of curves,
and move "ensuring" the offsets to a separate function, since it's
often nicer to call that if you don't need the result span immediately.
2022-03-24 20:58:01 -05:00
6e72e3fdb2 Cleanup: Further renaming in new curves code
A follow-up to e253f9f66d. Follow the policy from T85728
completely (using "num" as a prefix) and rename another function.
2022-03-24 20:48:08 -05:00
d3999683ff WebP: Fix use after free 2022-03-24 21:21:18 -04:00
6e86cf0daa Docs: include WEBP in --help text 2022-03-25 12:10:30 +11:00
2eeb79805c Cleanup: remove argument to doxygen \file
Doxygen doesn't require this to be set.
2022-03-25 12:10:30 +11:00
1ba20947cc Cleanup: rename CustomDataExternal.filename => filepath
Reserve "filename" when only the name component is used.
2022-03-25 12:10:30 +11:00
7d1d9e6015 Cleanup: rename ParticleSettings.child_nbr => child_percent
child_nbr was used as a percentage as well as the final
number of particles. Rename to avoid confusion.
2022-03-25 12:10:21 +11:00
4d46fac65d Cleanup: use count or num instead of nbr
Follow conventions from T85728.
2022-03-25 12:04:20 +11:00
c594cfbe50 Cleanup: use array syntax for sizeof, zero before float suffix 2022-03-25 12:04:19 +11:00
bbd787275f Cleanup: spelling in comments, strings 2022-03-25 12:04:16 +11:00
1d2dfc5e9e Cleanup: sort cmake file lists 2022-03-25 12:04:14 +11:00
a446c53f16 Cleanup: unused warnings 2022-03-25 12:04:12 +11:00
d3a1e9cbb9 Geometry Nodes: Multi-thread creation of selection from field
When boolean fields are evaluated and used as selections, we create
a vector of indices. This process is currently single-threaded, but
226f0c4fef added a more optimized multi-threaded version
of this process. It's simple to use this in the field evaluator.

I tested this with the set position node and a random
value node set to boolean mode on a Ryzen 2700x:
|              | Before  |  After  | Improvement |
| 10% Selected | 40.5 ms | 29.0 ms | 1.4x        |
| 90% Selected | 115 ms  | 45.3 ms | 2.5x        |

In the future there could be a specialized version for non-span
virtual array selections that uses `materialize` to lower virtual
call overhead.

Differential Revision: https://developer.blender.org/D14436
2022-03-24 18:48:38 -05:00
b030ec8760 BLF Cleanup: Use FreeType Enum FT_Err_Ok
Replace comparisons of FT_Error against 0 with FT_Err_Ok instead.

See D14052 for more details.

Differential Revision: https://developer.blender.org/D14052

Reviewed by Campbell Barton
2022-03-24 16:20:10 -07:00
4fd0a69d7b ImBuf: Add support for WebP image format
Currently only supports single image frames (no animation possible).

If quality slider is set to 100 then lossless compression will be used,
otherwise lossy compression is used.

Gives about 35% reduction of filesize  save when re-saving splash screens with lossless
compression.
Also saves much faster, up to 15x faster than PNG with a better compression ratio as a plus.

Note, this is currently left disabled until we have WebP libs (see T95206)

For testing precompiled libs can be downloaded from Google:
https://storage.googleapis.com/downloads.webmproject.org/releases/webp/index.html

Differential Revision: https://developer.blender.org/D1598
2022-03-24 18:24:06 -04:00
Jesse Yurkovich
07846b31f3 Cleanup: Optimize viewport view data creation
Each time the user clicks the viewport 2 sets of engine views are
created. Each set is currently composed of 8 view objects, each of size
592 bytes.

Because space is not reserved in the vector that holds them, several
unnecessary re-allocation/copy cycles occur as the vector resizes and
the total allocation load is 8880 bytes. This happens twice.

Reduce to just the allocations necessary and with exactly 4736 bytes
allocated for each set
 - Before: 8 allocations and 8 deallocations totaling 17760 bytes
 - After: 2 allocations and 2 deallocations totaling 9472 bytes

Reviewed By: fclem, jbakker

Differential Revision: https://developer.blender.org/D13782
2022-03-24 21:26:11 +01:00
3c4947cdaa Fix T96756: Blender hanges on rendering after file save, after recent changes 2022-03-24 19:42:59 +01:00
9ef400ddf7 Cycles: don't write light passes for shadow catcher objects
Makes it easier to composite the Combined image from these passes.

Fixes T96758
2022-03-24 19:42:59 +01:00
4a1b0ea902 Fix T94001: OpenColorIO configuration with 1D textures not working 2022-03-24 19:42:59 +01:00
067d0d4466 Fix: Missing "Hair" to "Curves" rename
Missed in fe1816f67f
2022-03-24 13:10:16 -05:00
fb3a0a34b4 Fix: Build error with flag usage and strict warnings 2022-03-24 12:54:30 -05:00
a6214ce7ac Outliner: Don't show empty base elements in the library overrides mode
In the library overrides mode, in some situations there would be empty
base elements like "Collections" or "Objects". Don't show them, it's
confusing wihout use. Code just failed to consider that case.
2022-03-24 18:38:21 +01:00
511dfb7743 Outliner: Don't draw library overrides indicator for override buttons
All the buttons in the Library Overrides display mode would be shown in cyan,
indicating that they are library overrides. Given that this is solely what this
display mode is about, the indicator is just redundant, confusing (why are the
buttons purple?) and looks weird.

Part of T95802.

Reviewed by: Bastien Montagne

Differential Revision: https://developer.blender.org/D14416
2022-03-24 18:17:44 +01:00
ef228d92f2 Fix: Volume grid duplication on USD import.
Fix provided by Piotr Makal in patch D14204.

This patch fixes volume grid duplication which was occurring during
importing USD files. This was caused by calling BKE_volume_grid_add
twice per grid (excluding 'density' grid) for the same Volume
object: (1) in USDVolumeReader::read_object_data and (2) later in
BKE_volume_load.

Differential Revision: https://developer.blender.org/D14204
2022-03-24 12:42:11 -04:00
Lictex Steaven
db4d5d1583 Fix T90110: Dupli Window Not Immediately Active
When creating a new window from a duplicated area - by shift-dragging
on corner action zones - on the Windows platform the resulting window
is initially unresponsive. This patch fixes this by releasing the parent
window's mouse capture.

See D14085 for more details.

Differential Revision: https://developer.blender.org/D14085

Reviewed by Ray Molenkamp
2022-03-24 09:41:29 -07:00
dcb520a7af Outliner: Remove list of library overrides from general display modes
There is a dedicated Library Override display mode now, and showing
these elsewhere just adds noise and makes the code problematic to
maintain (since the same element hierarchy will be used in two entirely
different contexts). The corresponding filter settings are removed too.

Part of T95802.

Reviewed by: Bastien Montagne

Differential Revision: https://developer.blender.org/D14411
2022-03-24 17:25:24 +01:00
1ff853a3f0 Outliner: Don't display library overrides from linked files
Instead of having the "Current File" and then the individual libraries
containing indirect library overrides in the Library Overrides display
mode, only show what's in the current file. Agreement was that this
isn't very useful in this view, we may want to add it to the Hierarchy
view though (see T95802).

Part of T95802.

Also expands the top level ID type items ("Objects", "Materials", ...)
by default. See D14410 for details.

Reviewed by: Bastien Montagne

Differential Revision: https://developer.blender.org/D14410
2022-03-24 17:22:37 +01:00
00018bfaa2 Tracking: Fix incorrect angle calculation on marker slide
Now the mouse cursor will exactly follow the tilt/scale sliding area.
2022-03-24 16:56:31 +01:00
dd7250efb1 Tracking: Fix jump when sliding tild/scale of marker
Was a mistake in coordinate handling: need to take possible offset
from the sliding area.

Mouse us still not fully perfectly follows changes of the tilt slide
area, but that is a separate issue.
2022-03-24 16:21:59 +01:00
Henrik Dick
cee6af0056 GPencil: New Envelope Modifier
This new modifier creates a shape known as envelope. It connects all
points that are n points apart. There is also a mode which fits a
single stroke to the envelope shape that is determined by that rule.

For more details, refer to the patch.

Reviewed By: NicksBest, antoniov, frogstomp, mendio

Differential Revision: http://developer.blender.org/D14341
2022-03-24 13:01:46 +01:00
Henrik Dick
dd161ff7a4 Complex Solidify: handle vertex creases
This implements the same interpolation method as for bevel weights
now for vertex and edge creases as well to improve the flexibility.

Differential Revision: http://developer.blender.org/D14170
2022-03-24 12:30:48 +01:00
4a674d08dd Outliner: tweak handling of liboverrides in delete code.
Essentially, we only allow deletion of hierarchy roots of liboverrides,
when hierarchy deletion option is enabled.

Also add some checking code in the generic, non-object/collection ID
delete code, to prevent any deletion of liboverrides that would be part
of a hierarchy.
2022-03-24 12:01:48 +01:00
24c30e001f 3D View: preference to disable selection cycling on first click
Object mode selection does a kind of cycling that excludes the active
selected object. This is separate from regular selection cycling which
is enabled when clicking multiple times without moving the cursor.

This has the down-side that clicking on an object to drag it always
selects the object behind it (in the case of overlapping objects).

Since object mode selection is fundamental functionality, this is
exposed as an experimental preference for user feedback & testing.

See T96752 for details.
2022-03-24 21:48:22 +11:00
643da14a4e Fix make source_archive_complete for release branches
In Blender 3.1 we can't run the source_archive_complete because the
cmake program is trying to download the packages from svn trunk. However
3.2 (aka master) already changed the version of some of the source
packages.

For example the OpenXR-SDK. It should be looking for
OpenXR-SDK-1.0.17.tar.gz in:
https://svn.blender.org/svnroot/bf-blender/tags/blender-3.1-release/lib/packages/

But instead it tries to look for it in:
https://svn.blender.org/svnroot/bf-blender/trunk/lib/packages/

Which can't be found since it was replaced with OpenXR-SDK-1.0.22.tar.gz

---

Release checklist: https://wiki.blender.org/wiki/Process/Release_Checklist

The release checklist was updated to include the new instructions:
`In the release branch, update and uncomment BLENDER_VERSION in download.cmake`

Differential Revision: http://developer.blender.org/D14292
2022-03-24 11:39:34 +01:00
Henrik Dick
acd7a648b1 GPencil: Add Scale Thickness to Pivot Point Pie Menu similar to Only Locations
In my opinion Scale Thickness feels similar to Only Locations and was missing from the pie menu in grease pencil edit mode, so here I added it.

Differential Revision: https://developer.blender.org/D12530
2022-03-24 11:22:33 +01:00
a2c2f6a39e Correct syntax error for MSVC 2022-03-24 21:13:58 +11:00
7a028330d2 Cleanup: clang-format 2022-03-24 11:01:12 +01:00
Henrik Dick
8d4244691a GPencil: lower bounds for gap in dot dash modifier
This patch maximizes the possible bounds for the dash and
gap parameters in the dot dash modifier. This makes e.g.
chopping up lines without gaps possible.

Differential Revision: http://developer.blender.org/D14428
2022-03-24 10:51:14 +01:00
bc290b47cd Keymap: experimental preference always use "Mouse Select & Move"
This was already as a preference for the tweak tool,
this preference enables the option for all selection
in the 3D view & UV editor.

This extends on changes from T96544.
2022-03-24 20:45:13 +11:00
e006e66084 Cleanup: use struct member identifiers for initialization
Relying on the order of struct members can be error prone. Update other
instances of ObjectsVisibleIteratorData initialization for MSVC/C++.
2022-03-24 17:30:45 +11:00
4682a0882f Cleanup: use "filepath" instead of "filename" for full paths
Reserve "filename" when only the name component is used.
2022-03-24 16:54:01 +11:00
5058c4b144 Cleanup: localize finding the nearest non-active object on selection
Move this into it's own block since it only needs to run if the
nearest object is currently selected & active.
2022-03-24 15:56:05 +11:00
0ee95e83ea View 3D: Don't prioritize pose objects unless in pose-mode
Always prioritizing bones caused pose-objects to be selected in object
mode even if they were behind other objects.

Now prioritizing pose bones is limited to pose mode.
2022-03-24 15:56:05 +11:00
3e5e204c81 3D View: order by depth when selecting cycles through objects
When cycling through objects select the nearest first
instead of using the order of object-bases in the view_layer.

This matches how pose selection works.
2022-03-24 15:56:05 +11:00
e67cd1f9a8 Cleanup: remove redundant argument for key-map selection template 2022-03-24 15:56:05 +11:00
6d61cf4e80 Cleanup: Typo, improve variable names
`accumulate_counts_to_offsets` wasn't just used for the point domain.
2022-03-23 23:50:10 -05:00
7ef3a1a6e6 BLI: Add utility for tacking average and min runtime
This is useful to save time manually averaging many timing results.
The minimum is included because often it can be more stable than an
average, and it can help to expose calls from other contexts with lower
times that would make the average useless.

Differential Revision: https://developer.blender.org/D14417
2022-03-23 23:35:23 -05:00
610ec34c1f Geometry Nodes: Improve performance writing to vertex groups
In a test file from T96282, this commit reduces the runtime of the
delete geometry node from 82 ms to 23 ms, a 3.6x improvement.
Writing to vertex groups in other cases should be faster too.

The largest improvement comes from not writing a new weight
of zero if the vertex is not in the group. This mirrors the behavior
of custom data interpolation in `layerInterp_mdeformvert`.
Other improvements come from using `set_all` for writing
output attributes and implementing that method for vertex groups.

I also implemented `materialize` methods. Though I didn't obverse
an improvement from this, I think it's best to remove virtual method
call overhead where it's simple to do so.

The test file for the delete geometry node needs to be updated.
These methods could be parallelized too, but better to do that later.

Differential Revision: https://developer.blender.org/D14420
2022-03-23 23:27:26 -05:00
aeb2c2afaf Cleanup: Clang tidy
- Deprecated headers
- Else after return
- Inconsistent parameter names (I used the most recently modified)
- Raw string literals
2022-03-23 23:24:54 -05:00
e253f9f66d Cleanup: Adjust naming in new curves code
Rename "size" variables and functions to use "num" instead,
based on T85728 (though this doesn't apply to simple C++
containers, it applies here). Rename "range" to "points" in
some functions, so be more specific.

Differential Revision: https://developer.blender.org/D14431
2022-03-23 23:05:46 -05:00
a1598d6835 UDIM: Improve tile format detection in filenames
There are some filenames where the UDIM pattern guessing would fail
unnecessarily. The user can fix these up afterwards but it would be
nicer if they would detect properly in the first place.

Examples:
`test.1001.ver0023.png` would guess wrong since it uses the image
sequence detection code which finds the first sequence from the end. It
would guess `filename.1001.ver<UDIM>.png`

`uv-test.u1_v2.png` would fail detection due to a bug in the processing.

Make this much more reliable and add tests for the most important tile
related get/set/detection functions.

Differential Revision: https://developer.blender.org/D14320
2022-03-23 21:01:36 -07:00
ead2c71a90 Cleanup/fix wrong enum items for object.gpencil_modifier_add
No functional changes as the actual list used for display is generated
at runtime via a callback.
2022-03-24 03:43:41 +01:00
ead9ed7e16 Cleanup: extra property update for ShaderFxGlow.opacity 2022-03-24 03:25:10 +01:00
98d4872d7f Cleanup: remove debug prints 2022-03-24 01:35:27 +01:00
Brian Savery
c46e58817c Cycles: enable HIP for Vega and Vega II (Radeon 7) GPUs on Windows
Basic testing on windows only so far. Will need some testing on Linux as well
when the Linux enablement patch is ready.

Does not enable Vega APUs yet (which would be gfx902 or gfx90c).

Differential Revision: https://developer.blender.org/D14432
2022-03-24 01:12:45 +01:00
ad976c0dd7 Fix missing updates for external render engines rendering tiles
For render image buffers to be acquired, a lock must be provided. Also
fixed wrong usage of release, it must always be called regardless if the
returned image buffer is NULL.
2022-03-24 01:03:47 +01:00
51380b9346 Fix Cycles Metal build error and GCC warning after recent changes
Function overloading of make_float4() doesn't work since it's a macro, just
don't do this minor cleanup then.
2022-03-23 23:25:31 +01:00
d84b4becd3 Fix compile error on GCC
Explicit template specialization has to happen outside of class
definition (some compilers are more lenient). Since it is not possible to
specialize the method without also specializing the enclosing class for
all of its possible types, the method is moved outside of the class, and
specialized there.
2022-03-23 22:01:32 +01:00
945dfd200b Cleanup: add const qualifier
This adds a const qualifier to some code path in the Alembic and USD
importers. More could be added elsewhere. This change is done as it will
be required when GeometrySets are supported and helps keeping diff noise
in the patch to a bare minimum.
2022-03-23 21:32:09 +01:00
03a7747aa6 Cleanup: use nullptr 2022-03-23 21:32:09 +01:00
300239b01f UI: Correct error message wording
Fixes T96724
2022-03-23 16:13:09 -04:00
Yuki Hashimoto
31bfa17a1f Cleanup: delete unused ViewMapIO files in Freestyle
ViewMapIO.h is only included in Controller.cpp init_options().
However, g_models_path and g_flags set here are never used elsewhere.
Therefore, ViewMapIO files can be deleted without affecting anything.

Differential Revision: https://developer.blender.org/D14423
2022-03-23 20:06:12 +01:00
Charles Flèche
e7b1be52e0 Cycles: add Alembic procedural to Cycles standalone xml
Example:

<alembic filepath="/tmp/cube.abc" scale="1.45">
  <object path="/Cube/Cube" />
</alembic>

Differential Revision: https://developer.blender.org/D14391
2022-03-23 20:06:12 +01:00
Ethan-Hall
f5066d43ae Cleanup: use make_float4(f) zero_float4() to simplify code
Differential Revision: https://developer.blender.org/D14426
2022-03-23 20:06:12 +01:00
Ethan-Hall
4e56e738a8 Cycles: optimize CPU texture sampler interpolation
Use templates to optimize the CPU texture sampler to interpolate using
float for single component datatypes instead of using float4 for all types.

Differential Revision: https://developer.blender.org/D14424
2022-03-23 20:06:12 +01:00
d67f9820b8 Curves: improve Comb brush
New supported features:
* 3D/spherical brush that samples a good position on the curves.
* Falloff.

The custom falloff curve mapping is not yet available in the ui because that
requires some more ui reorganization. This is better done when we have
a better understanding of what settings we need exactly.

Currently, the depth of the 3d brush is only sampled once per stroke, when
first pressing LMB. Sometimes it is expected that the depth of the brush can
change within a single brush. However, implementing that in a good way
is not straight forward and might need additional options. Therefore that
will be handled separately. Some experimentation results are in D14376.

Ref T96445.

Differential Revision: https://developer.blender.org/D14376
2022-03-23 18:19:59 +01:00
5d38b13e61 CMake: Rename "USD_LIBRARY_PREFIX" to "PXR_LIB_PREFIX" for consistency
rBc1909770e7f192574ea62449dd14b4254637e604 introduced "PXR_LIB_PREFIX" for building the
dependencies, so only makes sense to use the same name in the Hydra render delegate CMake too
2022-03-23 16:52:02 +01:00
d350976ba0 Cycles: Add Hydra render delegate
This patch adds a Hydra render delegate to Cycles, allowing Cycles to be used for rendering
in applications that provide a Hydra viewport. The implementation was written from scratch
against Cycles X, for integration into the Blender repository to make it possible to continue
developing it in step with the rest of Cycles. For this purpose it follows the style of the rest of
the Cycles code and can be built with a CMake option
(`WITH_CYCLES_HYDRA_RENDER_DELEGATE=1`) similar to the existing standalone version
of Cycles.

Since Hydra render delegates need to be built against the exact USD version and other
dependencies as the target application is using, this is intended to be built separate from
Blender (`WITH_BLENDER=0` CMake option) and with support for library versions different
from what Blender is using. As such the CMake build scripts for Windows had to be modified
slightly, so that the Cycles Hydra render delegate can e.g. be built with MSVC 2017 again
even though Blender requires MSVC 2019 now, and it's possible to specify custom paths to
the USD SDK etc. The codebase supports building against the latest USD release 22.03 and all
the way back to USD 20.08 (with some limitations).

Reviewed By: brecht, LazyDodo

Differential Revision: https://developer.blender.org/D14398
2022-03-23 16:39:05 +01:00
827e9ccb29 Revert "Fix T96728: 'Automatic Constraint' using the wrong orientation"
This reverts commit 6cc83f9079.

That commit removed the feature of cancel the 'Auto Constraint'
if it is enabled without drag.
2022-03-23 12:26:58 -03:00
6cc83f9079 Fix T96728: 'Automatic Constraint' using the wrong orientation
If the `Automatic Constraint` modifier was activated while an axis
constraint was already set, the orientation used would be the default
orientation of the mode and not that of the scene.

This was because the `initSelectConstraint` function was not called in
this case and the `Automatic Constraint` mode was enabled by other
indirect means

So the solution is to call `initSelectConstraint` in either case and
remove these "indirect means" of enabling `Automatic Constraint`.
2022-03-23 12:20:39 -03:00
e25238e146 Fix build error on GCC after recent changes 2022-03-23 16:12:55 +01:00
d40d5e8d0f Cleanup: move Mesh Sequence Cache modifier to C++
This moves `MOD_meshsequencecache.c` to C++ and fixes compile warnings
introduced from the change. This uses C++ style casts, as well as
`nullptr` instead of `NULL`.

This will allow to output `GeometrySets` from the modifier, which is C++.

Differential Revision: https://developer.blender.org/D13662
2022-03-23 15:34:13 +01:00
5ac4e6c911 Color Management: add support for OpenColorIO color space aliases
This enables the configuration to specify aliases for compatibility with other
configurations.

When a colorspace name is saved in a.blend, that is the alias of a colorspace
in the current configuration, it will show the main colorspace from the
configuration in the user interface and Python API instead.

Loading & saving the .blend file does not make any changes to the stored name,
so as to not make hidden modifications. Only when setting the property again
will the alias name be overwritten by the main colorspace name.

Fixes T96049

Differential Revision: https://developer.blender.org/D14419
2022-03-23 15:21:58 +01:00
7aab508e32 Color Management: support different settings for render and compositing output
The Output Properties > Output panel now has a Color Management subpanel to
override scene settings. When set to Override instead of Follow Scene, there
are settings to:

* For OpenEXR, choose a (linear) colorspace for RGBA passes
* For other file formats, use different display/view/look/exposure/gamma

These settings affect animation render output, image save of renders and the
compositor file output node. Additionally, the image save operator and
compositor file output nodes also support overriding color management.

Includes some layout changes to the relevant panels to accomdate the new
settings and to improve consistency. Ideally subpanels would be used to better
organize these settings, however nodes and operators don't currently support
creating subpanels.

Differential Revision: https://developer.blender.org/D14402
2022-03-23 15:21:58 +01:00
Jeroen Bakker
51727fe86f Fix T96502: Compilation error OCIO when using GradingPrimaryTransform.
When using GradingPrimaryTransform the generated GLSL code fails to compile. The actual issue is
inside OCIO (https://github.com/AcademySoftwareFoundation/OpenColorIO/issues/1603).

The reason is that unset clamping values are rendered out as `inf`, which isn't recognizable
by GLSL.

The issue is worked around by defining a default for `inf`.

Reviewed By: brecht

Maniphest Tasks: T96502

Differential Revision: https://developer.blender.org/D14425
2022-03-23 14:13:09 +01:00
3d5d8b7f71 Cleanup: Run clang-format on the OBJ exporter 2022-03-23 12:43:03 +01:00
f22331ad21 Cleanup: Move include statements outside of extern "C"
The linking type is to be specified in thew header when
it is really needed.
2022-03-23 12:43:03 +01:00
2d3a62fe16 Fix invalid NULL check in GPU_viewport_unbind_from_offscreen
Mistake from 1d49293b80.
2022-03-23 21:52:01 +11:00
f634010c6e Event System: improve handling of unknown keys
When converting ghost keys to Blender's event system:

- All keys that aren't part of the GHOST_TKey enum map to EVENT_NONE
  (ignored), note that it's an internal error if the value of key isn't
  a known value.

- Modify the switch statement so any missing members of GHOST_TKey
  warn at compile time (GCC & Clang only).

- GHOST_kKeyUnknown maps to EVT_UNKNOWNKEY.
  We could ignore this key, changing can be evaluated separately.
2022-03-23 21:30:36 +11:00
8f63dccaa9 Event System: ignore keys such as print-screen & num-lock
Avoid adding events with their type set to EVENT_NONE as these
can't be categorized usefully (keyboard/mouse/NDOF ... etc),
and add an extra case that needs to be accounted for.

Adding these events seems to be an unintentional change from [0],
these keys used to be ignored in 2.4x.

[0]: a1c8543f2a
2022-03-23 21:17:59 +11:00
ad370868a2 Fix T96712: Debug Assert with PrintScrn & ScrollLock keys
Caused by 08d8eee006.
2022-03-23 20:52:12 +11:00
94b2d83421 Cleanup: move documentation to headers, other minor corrections 2022-03-23 17:18:42 +11:00
56dba4df3c Revert "Fix T89560: Keymap editor no longer shows keying set dropdown"
This reverts commit e55f4657f7.

It's not intended to support assigning shortcuts to this operator,
which could only work for built-in keying sets caused warnings to be
reported warnings when exporting key-maps.

Prefer D14289, preventing users running into this problem to begin with.
2022-03-23 16:47:47 +11:00
d356edf420 UV: support "Tweak Tool: Left Mouse Select & Move"
- Follow the same conventions as the 3D viewport for UV selection
  (using SelectPick_Params internally).

- Use WM_operator_properties_mouse_select for selection properties.
2022-03-23 16:09:22 +11:00
cf1a0ca612 UI: Change subdiv to subdivision for EEVEE hair
Reviewed By: Blendify

Author: @Alaska

Differential Revision: https://developer.blender.org/D14346
2022-03-22 23:09:36 -04:00
612ec0ecdf Fix T96372: UV editor selection display wrong with GPU subdivision
Vertices were not drawn properly as the logic for mapped mesh was used
in the BMesh case.

Edge display would ignore subdivided edges which would come from coarse
edges when setting display flags.
2022-03-23 04:01:12 +01:00
694fe9f77b Fix outliner/selection updates when selecting in the 3D view
The checks for calling outliner flushing didn't account for
entering pose mode for the first time or that pose-bone selection
can also change the object selection.

Resolve by recording what changed and refresh accordingly.

Also de-duplicate calls to DEG_id_tag_update.
2022-03-23 13:44:15 +11:00
5f350a4acd Cleanup: various improvements to ed_object_select_pick
- Document parameters.
- Add code-comments.
- Remove some historic/unhelpful code-comments.
- Rename argument names that were ambiguous
  (object was a boolean for e.g.).
- Move `gpu` picking into an allocated struct which is only
  allocated & used when using GPU picking.
- Move variable declarations after menu picking has been handled.
2022-03-23 13:44:15 +11:00
4822153b85 Cleanup: spelling in comments 2022-03-23 12:15:50 +11:00
6bb28a1a52 Cleanup: follow Python code-style/conventions 2022-03-23 12:00:33 +11:00
3a038f8a60 CMake: add missing headers to source list 2022-03-23 11:58:59 +11:00
d2336237cf License headers: add license header to source/blender/gpu/metal 2022-03-23 11:47:05 +11:00
366abae3e7 Cleanup: use ifdef to disable enum string allocation
Restore variable removed in [0], using an ifdef to avoid the warning.

[0]: c3ecfdf40b
2022-03-23 11:43:21 +11:00
5c27391b0f UI: Clarify fluid sim CFL Number tooltip
Fixes T93863
2022-03-22 18:06:02 -04:00
cc3ec1fc6f Fix minor error in last commit (4b35d6)
If there is no active object, it is to be expected that we are in
object mode as well.
2022-03-22 17:30:03 -03:00
4b35d6950d Fix T96711: snap in edit mode for selected objects does not work
Regression introduced in 52be063012

The `SNAP_NOT_SELECTED` option should only consider base selected if
we are in object mode.
2022-03-22 17:21:58 -03:00
b7b3c4c40c Fix T96705: Crash when pressing F3 outside a Blender window if Developer extras
If the mouse is not hovering the window, there is no active region. This is a
valid state, but the UI-list filter operator didn't account for that case.
2022-03-22 18:35:28 +01:00
b40ac9684c Tiny visual fixes/tweaks for new library override buttons in Outliner
Tweaks:
- Increase horizontal padding for the buttons from 1 point to 2, looked like an
  unintentional placement error before.

Fixes:
- Missing horizontal padding for array buttons
- Small gap between separator line and right column when using a high interface
  scale
- Properly center buttons vertically.
2022-03-22 18:09:46 +01:00
87a0770bb9 Fix T96361: missing update when changing texture mapping properties 2022-03-22 16:33:55 +01:00
8344ef7394 Fix T96524: Regression: The Material Preview doesn't show
The preview does not work well with deferred render result pixels
allocation: it breaks the refresh and requires to toggle current
panels.

Since there is no tiled rendering for previews we don't save any
memory by deferring pixels allocations, so do it for the render
result during the render result creation.

Differential Revision: https://developer.blender.org/D14414
2022-03-22 16:00:09 +01:00
Leon Schittek
7de3caa05d Fix: Drag link search doesn't always connect to socket
Connecting to some sockets of a few nodes via the drag link search
would fail and trigger an assert, because the picked socket wasn't
available. This was due to some sockets only being available with
certain settings.

This patch fixes these cases by adding the availability conditions of
the socket to the node declaration with the `make_available` method
or manually adding a `node_link_gather_search` function.

Differential Revision: https://developer.blender.org/D14283
2022-03-22 09:57:50 -05:00
Laurynas Duburas
6bbc3b5610 Curve: Validation message split from nurb_check_valid
Split retrieval of translated text for the "invalid" messages for NURBS
curves from the actual calculation, which is a lower-level function.
Also fixes an issue where "At least two points required" would always
display in the "Active Spline" panel.

Differential Revision: https://developer.blender.org/D14315
2022-03-22 09:54:13 -05:00
b0aaf6ff4a Fix T96294: Crash and error with shape key normal calculation
A mistake in the mesh normal refactor caused the wrong mesh to
be used when calculating normals with a shape key's deformation.

This commit fixes the normal calculation by using the correct mesh,
with just adjusted vertex positions, and calculating the results
directly into the result arrays when possible. This completely avoids
the need to make a local copy of the mesh, which makes sense,
since the only thing that changes is the vertex positions.

Differential Revision: https://developer.blender.org/D14317
2022-03-22 09:43:02 -05:00
1c790555a0 Cleanup: Use bool for BMesh creation params
These boolean options are passed as uint, but they would be
easier to understand if using bool.

Differential Revision: https://developer.blender.org/D14405
2022-03-22 09:38:12 -05:00
64cd927519 Fix T96308: Mesh to BMesh conversion doesn't calculate vertex normals
Currently there is a "calc_face_normal" argument to mesh to bmesh
conversion, but vertex normals had always implicitly inherited whatever
dirty state the mesh input's vertex normals were in. Probably they were
most often assumed to not be dirty, but this was never really correct in
the general case.

Ever since the refactor to move vertex normals out of mesh vertices,
cfa53e0fbe, the copying logic has been explicit: copy the
normals when they are not dirty. But it turns out that more control is
needed, and sometimes normals should be calculated for the resulting
BMesh.

This commit adds an option to the conversion to calculate vertex
normals, true by default. In almost all places except the decimate
and edge split modifiers, I just copied the value of the
"calc_face_normals" argument.

Differential Revision: https://developer.blender.org/D14406
2022-03-22 09:33:50 -05:00
86d87fcbdb GL: Fix compilation error on MSVC (for real) 2022-03-22 14:52:51 +01:00
a43f3c761e GL: Fix compilation error on MSVC 2022-03-22 14:51:32 +01:00
e0ce1c45f8 Fix T96577: setting curve handles not working correctly with multiple curves
Differential Revision: https://developer.blender.org/D14409
2022-03-22 14:41:43 +01:00
3b5224b57c Cleanup: refactor passing of color management settings for image save
Make a copy of ImageFormatData that contains the effective color management
settings, and pass that along to the various functions. This will make it
possible to add more complex logic later.

For compositing nodes, passing along view and display settings through
many functions made it harder to add additional settings, so just get those
from the scene now.

Differential Revision: https://developer.blender.org/D14401
2022-03-22 14:15:20 +01:00
2ebcb7fab3 Cleanup: make format and fix warning 2022-03-22 13:44:15 +01:00
Jason Fielder
19c793af35 Metal: Make GLSL shader source MSL compliant also
Metal shading language follows the C++ 14 standard and in some cases requires a greater level of explicitness than GLSL. There are also some small language differences:

- Explicit type-casts (C++ requirements)
- Explicit constant values (C++ requirements, e.g. floating point values using 0.0 instead of 0).
- Metal/OpenGL compatibility paths
- GLSL Function prototypes
- Explicit accessors for vector types when sampling textures.

Authored by Apple: Michael Parkin-White

Ref T96261

Reviewed By: fclem

Maniphest Tasks: T96261

Differential Revision: https://developer.blender.org/D14378
2022-03-22 12:54:44 +01:00
Jason Fielder
309ea31485 Metal: Initial Implementation of Metal Backend for GPU Module.
Adding WITH_METAL option to CMAKE to guard compilation for macOS only. Implemented stub METALBackend to mirror GPUBackend interface and added capabilities initialisation, along with API initialisation paths.

Global rendering coordination commands added to backend with GPU_render_begin and GPU_render_end() commands globally wrapping GPU work. This is required for Metal to ensure temporary resources are generated within an NSAutoReleasePool and freed accordingly.

Authored by Apple: Michael Parkin-White, Vil Harvey, Marco Giordano, Michael Jones, Morteza Mostajabodaveh, Jason Fielder

Ref T96261

Reviewed By: fclem

Maniphest Tasks: T96261

Differential Revision: https://developer.blender.org/D14293
2022-03-22 12:54:34 +01:00
Pratik Borhade
913b6b9ec1 Fix T96624: NLA crash when reordering tracks if no object is selected.
Caused by rBc0bd240ad0a1.
To avoid crash, make boolean value false if active object data is NULL.

Should be backported to 2.93 LTS and 3.1 corrective releases.
2022-03-22 12:04:41 +01:00
3b745f3455 Cleanup: make format + extra parenthesis
Nested ? : get better formatted with some parenthesis around the expressions.
2022-03-22 11:36:10 +01:00
2ba72d847b Fix (unreported) Crash in Array modifier.
Typo (copy/paste mistake) in rB923b28aab85768e2b.
2022-03-22 11:25:54 +01:00
ceaa787e42 Fix T96420: Set ID node not working for instances
Previously, instances used the point domain, but now there is a special
domain for instance attributes that the node has to use.
2022-03-22 11:09:53 +01:00
c1909770e7 CMake: prep USD build & find scripts for USD >= 21.11
Since USD 21.11 the libraries are prefixed with "usd_", i.e.
"libusd_m.a" became "libusd_usd_m.a". This commit adjusts our
`usd.cmake` (for building USD) and `FindUSD.cmake` (for finding the USD
libraries) so that they work with and without this `usd_` prefix.

See for more info:
https://github.com/PixarAnimationStudios/USD/blob/release/CHANGELOG.md#2111---2021-11-01

Reviewed By: LazyDodo, brecht, mont29

Differential Revision: https://developer.blender.org/D14334
2022-03-22 10:56:21 +01:00
47451af027 Cleanup: remove unused code from ed_object_select_pick
- No need to store is_pose_mode, check the object_mode flag instead.

- Remove redundant pose-mode check which now skips object selection.

- Remove disabled grease pencil cursor toggling,
  since I couldn't manage to reproduce a situation where the cursor
  failed to update - also, as there are other places the active object
  can change this would need a more general solution anyway.
2022-03-22 18:07:47 +11:00
6d9de230df Cleanup: refactor 3D view selection picking to early exit for menus
Selecting that opens a menu is now returns early. Handling the menu
selection in-line made this function more difficult to follow.

Also split out selecting an object by it's center into it's own function.
2022-03-22 17:34:37 +11:00
fa96f7381c Cleanup: de-duplicate object-mode locking when selecting 2022-03-22 17:34:37 +11:00
8c072cdc93 Obj: try to fix Linux tests
Related to previous D14368 bug fix, the sorting
operator was not necessarily a stable order sort.
2022-03-22 06:39:50 +02:00
127baac44d Fix pose-selection from menu not activating the object
Unlike the regression from T96663 selecting pose bones from menus
never activated the object.
2022-03-22 13:42:37 +11:00
59870796ea Fix T96663: Selecting a pose-bone doesn't activate the object
Regression in [0] that removed object selection changes while remaining
in pose-mode. This unintentionally removed object activation.

[0]: 859c062a2a
2022-03-22 13:39:01 +11:00
4046f61b39 Fix pose-bone menu selecting before activating the menu
Regression in 1d88aeb95f.
2022-03-22 12:07:00 +11:00
4e1e057ced Cleanup: variable names for menu selection
- Rename baseCount to bone_count, was copy-pasted from object code.
- Also rename baseCount to base_count for object selection,
  following snake case naming conventions.
- Use int instead of short for counters, as there is no reason to use
  short ints.
2022-03-22 11:57:25 +11:00
8bccc7d861 Cleanup: add proper IMB_openexr.h instead of including file from intern/ 2022-03-22 01:30:19 +01:00
9cf40eee4b Fix build error when WITH_OPENEXR=OFF, after recent refactor 2022-03-22 01:30:19 +01:00
fab14f7854 Fix build when using WITH_TBB=OFF after recent changes
And wrap tbb::parallel_sort in blender namespace similar to other TBB
functionality.
2022-03-22 01:30:19 +01:00
976c91cd77 Cleanup: Clang tidy 2022-03-21 17:12:22 -05:00
def1c0c538 Cleanup: Small changes to multires bake normals access
- Order return arguments last, add `r_` prefix
- Use explicit size on array argument
- Avoid double negative in if statement
2022-03-21 17:11:39 -05:00
3a8a7d93f9 Fix T96401: Broken multires baked normals result
A 7 year old commit, 2ec00ea0c1, used incorrect indexing for
the optional array of precomputed poly normals. Apparently that code
path was never used, or this issue would have been discovered earlier.
Recent changes calculate normals on a temporary mesh and use those
for the "low-res" layer, meaning the precomputed path was always taken.
2022-03-21 16:55:55 -05:00
923b28aab8 Fix T96494: Array modifier with caps crash on curve objects
Since 3b6ee8cee7, a list of vertex groups cannot be retrieved
from curve objects for merging because curve objects do not support
vertex groups. Previously the empty list on the object was returned.
Only mesh objects are supported for the caps.
2022-03-21 14:44:39 -05:00
eb1755be35 Fix T96511: New OBJ exporter no longer groups faces by material
Old python exporter in 3.0 and earlier ordered faces by material,
but the new C++ exporter in 3.1+ did not, and was just writing them
in whatever is the order of the mesh data structure.

This mostly does not cause problems, except in some apps e.g.
Procreate -- for large enough meshes, this lack of
"order by material" (which ends up having more usemtl lines)
ends up creating more mesh subsets than necessary inside Procreate.

The change is not computationally heavy, e.g. exporting 6-level
subdivided Monkey mesh goes 1085ms -> 1105ms on my machine.

Reviewed By: @howardt
Differential Revision: https://developer.blender.org/D14368
2022-03-21 20:20:09 +02:00
a58be397e2 Curves: new Add brush
This adds a new Add brush for the new curves object type in sculpt mode.
The brush is used to insert new curves (typically hair) on the surface object.

Supported features:
* Add single curve exactly at the cursor position when `Add Amount` is 1.
* Front faces only.
* Independent interpolate shape and interpolate length settings.
* Smooth and flat shading affects curve shape interpolation.
* Spherical and projection brush.

This also adds the `surface_triangle_index` and `surface_triangle_coordinate`
attributes. Those store information about what position on the surface each
added curve is attached to:
* `surface_triangle_index` (`int`): Index of the internal triangle that a curve
  is attached to. `-1` when the curve is not attached to the surface.
* `surface_triangle_coordinate` (`float2`): First two numbers of a barycentric
  coordinate that reference a specific position within the triangle.

Ref T96444.

Differential Revision: https://developer.blender.org/D14340
2022-03-21 18:59:03 +01:00
Ethan-Hall
f8d19ec5a3 UI: improve names and tooltips in viewport preferences
Rename OpenGL to GPU, Show to Text Info Overlay, and various other tweaks.

Differential Revision: https://developer.blender.org/D14344
2022-03-21 18:09:43 +01:00
Hallam Roberts
c7e25a25b0 Fix T96132: Cycles RGB/Vector/Float Curve shaders ignore extrapolation setting
Differential Revision: https://developer.blender.org/D14393
2022-03-21 17:41:17 +01:00
f92e3b39f1 UI: Use title case for labels 2022-03-21 11:35:17 -05:00
8530e48f86 Cleanup: move render image and multilayer EXR write code to image_save.cc
These share a lot of logic with regular image saving and should be unified
more in the future.
2022-03-21 16:38:13 +01:00
b96462519f Cleanup: move image_save.c to c++ 2022-03-21 16:38:13 +01:00
1897df891c Cleanup: move OpenEXR channel name construction to OpenEXR code 2022-03-21 16:38:13 +01:00
6e4d2fa914 Cleanup: add image_format.cc for functions related to ImageFormatData
Also fixes missing code to read/write/free/copy color management settings
in various places. This can't be set through the UI currently, but still
should be handled consistently.
2022-03-21 16:38:13 +01:00
Ethan-Hall
4abb8a14a2 Cycles: make 3D texture sampling at boundaries more similar to GPU
CPU code for cubic interpolation with clip texture extension only performed
texture interpolation inside the range of [0,1]. As a result, even though the
volume's color is sampled using cubic interpolation, the boundary is not
being interpolated. The GPU appears was interpolating samples that span the
clip boundary softening the edge, which the CPU now does also.

This commit also includes refactoring of 2D and 3D texture sampling in
preparation of adding new extension modes.

Differential Revision: https://developer.blender.org/D14295
2022-03-21 16:38:13 +01:00
Ethan-Hall
be3eef19c0 GPU: Allow the user to set an anisotropic filtering setting below the implementation-defined value of GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
Allow the user to set an anisotropic filtering setting below the implementation-defined value of `GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT`.

This bug-fix is also needed for 2.93 LTS.

Reviewed By: fclem

Differential Revision: https://developer.blender.org/D14392
2022-03-21 13:47:08 +01:00
Hallam Roberts
c5456819ee Fix T96655: Bloom crashes Eevee
This patch fixes T96655, bloom crashing Eevee.

The error occurs because rB472fc0c55848b2e2d428cfb4f7debb80a4e12081 added `vec3 safe_color(vec3 c)` to `common_math_lib.glsl`.

However, `vec3 safe_color(vec3 c)` already exists in `effect_bloom_frag.glsl`.
This means `vec3 safe_color(vec3 c)` is duplicated within `common_math_lib.glsl` and `effect_bloom_frag.glsl`.

{F12938060 size=full}

The duplicate code in `effect_bloom_frag.glsl` can be removed since it's no longer needed.

(I checked the remaining methods, there shouldn't be any additional duplicate code)

Reviewed By: fclem

Maniphest Tasks: T96655

Differential Revision: https://developer.blender.org/D14396
2022-03-21 13:20:06 +01:00
Sergey Sharybin
ae21729557 Cycles: Un-pause render when switching to rendered viewport
Consider switching to rendered shading type as a request to start
rendering, without requiring to un-pause.

This minimizes amount of clicks needed to start rendering after
viewport was paused once, and then shading mode got changed.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D14244
2022-03-21 10:59:08 +01:00
Pierre Risch
e4278b72bb T84815: Missing preview image in compositing file output node
Hello,
I saw that this revision was stalled for a few months so I tried to update it.
https://developer.blender.org/D10995
I added a function that adds a preview on the first connected input of the file output node.
I removed the preview on the single layer format
Thanks

Reviewed By: #compositing, jbakker

Maniphest Tasks: T84815

Differential Revision: https://developer.blender.org/D14219
2022-03-21 10:56:40 +01:00
9ed63ebb45 Fix T96572: eevee crash with motion blur and stereoscopy
This was a use-after-free bug due to dangling pointers.
2022-03-21 10:05:39 +01:00
fb87578698 Fix T96255: Node socket fails to drag
This is a general issue exposed by moving from tweak to click-drag
events [0], however this bug would have existed for both click &
click-drag events beforehand.

Since [1] the following behavior could occur:

- Click-drag the cursor away from the button.
- Leaving the button would flag it as disabled.
- The disabled button would then break
  causing the event to be considered handled.
- Once handled no click / click-drag action would be tested.

The bug would only happen if the cursor left the button before the drag
threshold was reached which tended to happen with an UI-scale 2 or more.
Or with an increased drag threshold.

Revert [1] (fix for T78503), which is no longer needed since as of [2].

[0]: 4986f71848
[1]: 6f96dd8576
[2]: 87c13ac68c
2022-03-21 18:20:44 +11:00
c4ce1b70e3 Correct error in 3dc44f8c89
The array for event.flag was too big, harmless but incorrect.
Remove the size from the declaration as it's not needed.
2022-03-21 17:21:28 +11:00
3dc44f8c89 Event System: improve event printing
- Use set-style printing of modifier flags instead of booleans.
- Include event.flag.
- Print on a single line (so output can be more easily filtered).
2022-03-21 17:19:26 +11:00
52af3b20d4 Cleanup: cursor motion events now have value set to KM_NOTHING
In some cases value of cursor motion events was set from the last event
written to the wmWindow.eventstate. Avoid potential errors by ensuring
cursor motion events always have their value set to KM_NOTHING.
2022-03-21 15:49:15 +11:00
8ecaa2d624 Fix T96510: ASAN failure when selecting text in Text Editor
Regression in 541ba68991
2022-03-21 13:36:07 +11:00
Aras Pranckevicius
b9123b806f Fix T96470 new obj exporter writing material groups
This is patch D14349 from Aras Pranckevicius.

The logic in the code was _completely different_ from the documentation
and what the python exporter in 3.0 did. The new code assumed that
"export material groups" meant "append material name to the object name",
and was only ever kicking in when the "export object groups" option was
also checked. But the proper behavior (as in 3.0 exporter & the online docs),
is to emit g objectname_materialname before each usemtl line. Which is something entirely else.
2022-03-20 08:59:16 -04:00
Aras Pranckevicius
5bfdaaa800 Fix T96415: new OBJ exporter was applying scaling factor incorrectly
This is patch D14347 from Aras Pranckevicius.

Instead of scaling "the scene" (i.e. transform vertices by object matrix,
then multiply by scale factor), it was instead first applying the scale
factor in local space, and then transforming by the object matrix.
2022-03-19 17:14:53 -04:00
eccb0b222e GPencil: Port main object shader to ShaderCreateInfo
This is quite a huge cleanup. Making use of the `common_gpencil_lib.glsl`
to share more codes and use more consistent codestyle.

The gpencil engine specifics are now out of the `gpencil_vertex()`
function making it easier to add more features.

There should be no regression as all workarounds are kept as is.
2022-03-19 22:05:34 +01:00
36b02c3815 GPUSource: Fix failure case in the enum preprocessor
Some C headers might define the typedefs of the enum themselves.
Even if they are guarded by preprocessor `#if`, our enum preprocessor
has no idea of the validity of the statement. So we just bypass
if there is a typedef just before any `enum` keywords.

Note that the typedef matching is quite fragile.
2022-03-19 22:05:34 +01:00
472fc0c558 DRW: Port improvements in common_math_lib.glsl from eevee-rewrite
Mostly quality of life functions and macros.
2022-03-19 22:05:34 +01:00
6ae03375b6 DRW: Make use of shader shared header
# Conflicts:
#	source/blender/draw/intern/draw_manager.h
#	source/blender/draw/intern/draw_manager_exec.c
#	source/blender/draw/intern/draw_shader_shared.h
2022-03-19 22:05:34 +01:00
3eaf345352 DRW: Introduce GPencil common GLSL library
This library contains the needed functions to render GPencil object
geometry. Centralizing these will make it possible for other draw
engines (EEVEE, Overlay) to reuse the same vertex shader code and
possibly the same fragment rejection methods.
2022-03-19 22:05:34 +01:00
84a0e04296 GPencil: Use ShaderCreateInfo for fullscreen shaders
Simple port. Shouldn't break anything.
2022-03-19 22:05:34 +01:00
568c453ff3 GPencil: Use ShaderCreateInfo for antialiasing shaders
Simple port. Shouldn't break anything.
2022-03-19 22:05:34 +01:00
337343ecc9 GPencil: Use ShaderCreateInfo for vfx shaders
Simple port. Shouldn't break anything.
2022-03-19 22:05:34 +01:00
d7ecd4a0f3 DRW: Add new texture from pool acquire/release mechanism
This adds a simple and more manageable temp texture behavior.

The texture is garanteed to be available only between the acquire/release pair.
This makes the same engine able to reuse the textures and even overlap the acquire
& release calls.
2022-03-19 22:05:34 +01:00
dbf1e7c07f DRW: GPU wrappers: Some quality of life improvements
- Add name support to storage buffers
- Delete view functions for TextureFromPool
- Add support for different size acquire and assert on mulitple acquire
- Allow multiple release
2022-03-19 22:05:34 +01:00
Aras Pranckevicius
8aa365745a Fix T96430: new OBJ exporter wrong normals for non-uniform scale, and wrong face order for negative scale
This applies patch D14343 from Aras Pranckevicius, with a description:

The new 3.1+ OBJ exporter did not have correct logic when faced with
non-uniform & mirrored (negative on odd number of axes) object scale:

- Normals were not transformed correctly (should use inverse transpose of the matrix),
 and were not normalized,
- Face order was not "flipped" when transform has negative scale on odd number of axes
 (visible when using "face orientation" viewport overlay).
2022-03-19 16:20:22 -04:00
873801d25e Make Format Changes
Only formatting changes found by running "make format", no functional
changes

Committed without review, but with verbal approval by Hans Goudey
2022-03-19 10:24:56 -07:00
f381c73a21 Fix T95257: Filter files on "name" and "relpath"
When filtering File Browser items by name, use entry's "name" field as
well as the "relpath" field since they can vary.

See D13940 for details.

Differential Revision: https://developer.blender.org/D13940

Reviewed by Bastien Montagne
2022-03-19 09:23:05 -07:00
82c852f387 Fix D14173: Chinese IME Full Width Numbers
Windows IME: Fix duplicated initial character when entering numbers
while in Chinese full width character mode.

See D14354 for more details.

Differential Revision: https://developer.blender.org/D14354

Reviewed by Brecht Van Lommel
2022-03-19 09:05:10 -07:00
8711483632 BLI: generalize converting CPPType to static type
Previously, the conversion was done manually for a fixed set of types.
Now, there is a more general utility that can be used in other contexts
(outside of geometry nodes attribute processing) as well.
2022-03-19 10:57:40 +01:00
3e16f3b3ef BLI: move generic data structures to blenlib
This is a follow up to rB2252bc6a5527cd7360d1ccfe7a2d1bc640a8dfa6.
2022-03-19 08:26:29 +01:00
c655146b87 Fix T96584: Properly translate operator on splash screen
The previous fix looks to have been accidentally removed as part of
rB7aec5b06227.

Restore the change.
2022-03-18 20:31:24 -07:00
7fed213ba4 Revert "Compositor: Support backdrop offset for the Viewer node"
This reverts commit 33409f9f1c, as it breaks
panning in the image editor.

Fixes T96543
2022-03-19 00:37:30 +01:00
356073c13e Cleanup: Move object_transform.c to C++
Compilation and clang tidy fixes, use Vector instead of the
macro-based C array system. Builds on all platforms on the
buildbot.
2022-03-18 15:50:46 -05:00
1425 changed files with 55519 additions and 19640 deletions

View File

@@ -205,6 +205,7 @@ ForEachMacros:
- FOREACH_SCENE_COLLECTION_BEGIN
- FOREACH_SCENE_OBJECT_BEGIN
- FOREACH_SELECTED_BASE_BEGIN
- FOREACH_SELECTED_BEZT_BEGIN
- FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN
- FOREACH_SELECTED_OBJECT_BEGIN
- FOREACH_TRANS_DATA_CONTAINER
@@ -268,6 +269,7 @@ ForEachMacros:
StatementMacros:
- PyObject_HEAD
- PyObject_VAR_HEAD
- ccl_gpu_kernel_postfix
MacroBlockBegin: "^BSDF_CLOSURE_CLASS_BEGIN$"
MacroBlockEnd: "^BSDF_CLOSURE_CLASS_END$"

View File

@@ -284,6 +284,7 @@ option(WITH_IMAGE_TIFF "Enable LibTIFF Support" ON)
option(WITH_IMAGE_DDS "Enable DDS Image Support" ON)
option(WITH_IMAGE_CINEON "Enable CINEON and DPX Image Support" ON)
option(WITH_IMAGE_HDR "Enable HDR Image Support" ON)
option(WITH_IMAGE_WEBP "Enable WebP Image Support" OFF)
# Audio/Video format support
option(WITH_CODEC_AVI "Enable Blenders own AVI file support (raw/jpeg)" ON)
@@ -408,6 +409,8 @@ option(WITH_CYCLES_DEBUG "Build Cycles with options useful for debug
option(WITH_CYCLES_STANDALONE "Build Cycles standalone application" OFF)
option(WITH_CYCLES_STANDALONE_GUI "Build Cycles standalone with GUI" OFF)
option(WITH_CYCLES_HYDRA_RENDER_DELEGATE "Build Cycles Hydra render delegate" OFF)
option(WITH_CYCLES_DEBUG_NAN "Build Cycles with additional asserts for detecting NaNs and invalid values" OFF)
option(WITH_CYCLES_NATIVE_ONLY "Build Cycles with native kernel only (which fits current CPU, use for development only)" OFF)
option(WITH_CYCLES_KERNEL_ASAN "Build Cycles kernels with address sanitizer when WITH_COMPILER_ASAN is on, even if it's very slow" OFF)
@@ -443,7 +446,7 @@ if(NOT APPLE)
endif()
option(WITH_CYCLES_HIP_BINARIES "Build Cycles AMD HIP binaries" OFF)
set(CYCLES_HIP_BINARIES_ARCH gfx1010 gfx1011 gfx1012 gfx1030 gfx1031 gfx1032 gfx1034 CACHE STRING "AMD HIP architectures to build binaries for")
set(CYCLES_HIP_BINARIES_ARCH gfx900 gfx906 gfx1010 gfx1011 gfx1012 gfx1030 gfx1031 gfx1032 gfx1034 CACHE STRING "AMD HIP architectures to build binaries for")
mark_as_advanced(WITH_CYCLES_DEVICE_HIP)
mark_as_advanced(CYCLES_HIP_BINARIES_ARCH)
endif()
@@ -531,6 +534,19 @@ mark_as_advanced(
WITH_GPU_SHADER_BUILDER
)
# Metal
if (APPLE)
option(WITH_METAL_BACKEND "Use Metal for graphics instead of (or as well as) OpenGL on macOS." OFF)
mark_as_advanced(WITH_METAL_BACKEND)
else()
set(WITH_METAL_BACKEND OFF)
endif()
if (WITH_METAL_BACKEND)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version" FORCE)
endif()
if(WIN32)
option(WITH_GL_ANGLE "Link with the ANGLE library, an OpenGL ES 2.0 implementation based on Direct3D, instead of the system OpenGL library." OFF)
mark_as_advanced(WITH_GL_ANGLE)
@@ -729,9 +745,10 @@ endif()
#-----------------------------------------------------------------------------
# Check for conflicting/unsupported configurations
if(NOT WITH_BLENDER AND NOT WITH_CYCLES_STANDALONE)
if(NOT WITH_BLENDER AND NOT WITH_CYCLES_STANDALONE AND NOT WITH_CYCLES_HYDRA_RENDER_DELEGATE)
message(FATAL_ERROR
"At least one of WITH_BLENDER or WITH_CYCLES_STANDALONE "
"or WITH_CYCLES_HYDRA_RENDER_DELEGATE "
"must be enabled, nothing to do!"
)
endif()
@@ -1274,6 +1291,16 @@ else()
list(APPEND GL_DEFINITIONS -DWITH_GL_PROFILE_CORE)
endif()
#-----------------------------------------------------------------------------
# Configure Metal.
if (WITH_METAL_BACKEND)
add_definitions(-DWITH_METAL_BACKEND)
# No need to add frameworks here, all the ones we need for Metal and
# Metal-OpenGL Interop are already being added by
# build_files/cmake/platform/platform_apple.cmake
endif()
#-----------------------------------------------------------------------------
# Configure OpenMP.
if(WITH_OPENMP)
@@ -1884,14 +1911,13 @@ if(WITH_BLENDER)
# source after intern and extern to gather all
# internal and external library information first, for test linking
add_subdirectory(source)
elseif(WITH_CYCLES_STANDALONE)
elseif(WITH_CYCLES_STANDALONE OR WITH_CYCLES_HYDRA_RENDER_DELEGATE)
add_subdirectory(intern/glew-mx)
add_subdirectory(intern/guardedalloc)
add_subdirectory(intern/libc_compat)
add_subdirectory(intern/sky)
add_subdirectory(intern/cycles)
add_subdirectory(extern/clew)
if(WITH_CYCLES_LOGGING)
if(NOT WITH_SYSTEM_GFLAGS)
add_subdirectory(extern/gflags)
@@ -1948,7 +1974,7 @@ if(FIRST_RUN)
set(_msg " - ${_setting}")
string(LENGTH "${_msg}" _len)
while("32" GREATER "${_len}")
while("36" GREATER "${_len}")
string(APPEND _msg " ")
math(EXPR _len "${_len} + 1")
endwhile()

View File

@@ -1,11 +1,16 @@
# SPDX-License-Identifier: GPL-2.0-or-later
## Update and uncomment this in the release branch
# set(BLENDER_VERSION 3.1)
function(download_source dep)
set(TARGET_FILE ${${dep}_FILE})
set(TARGET_HASH_TYPE ${${dep}_HASH_TYPE})
set(TARGET_HASH ${${dep}_HASH})
if(PACKAGE_USE_UPSTREAM_SOURCES)
set(TARGET_URI ${${dep}_URI})
elseif(BLENDER_VERSION)
set(TARGET_URI https://svn.blender.org/svnroot/bf-blender/tags/blender-${BLENDER_VERSION}-release/lib/packages/${TARGET_FILE})
else()
set(TARGET_URI https://svn.blender.org/svnroot/bf-blender/trunk/lib/packages/${TARGET_FILE})
endif()

View File

@@ -52,6 +52,14 @@ add_dependencies(
external_boost
)
# Since USD 21.11 the libraries are prefixed with "usd_", i.e. "libusd_m.a" became "libusd_usd_m.a".
# See https://github.com/PixarAnimationStudios/USD/blob/release/CHANGELOG.md#2111---2021-11-01
if (USD_VERSION VERSION_LESS 21.11)
set(PXR_LIB_PREFIX "")
else()
set(PXR_LIB_PREFIX "usd_")
endif()
if(WIN32)
# USD currently demands python be available at build time
# and then proceeds not to use it, but still checks that the
@@ -65,14 +73,14 @@ if(WIN32)
if(BUILD_MODE STREQUAL Release)
ExternalProject_Add_Step(external_usd after_install
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/usd/ ${HARVEST_TARGET}/usd
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/usd/src/external_usd-build/pxr/Release/usd_m.lib ${HARVEST_TARGET}/usd/lib/libusd_m.lib
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/usd/src/external_usd-build/pxr/Release/${PXR_LIB_PREFIX}usd_m.lib ${HARVEST_TARGET}/usd/lib/lib${PXR_LIB_PREFIX}usd_m.lib
DEPENDEES install
)
endif()
if(BUILD_MODE STREQUAL Debug)
ExternalProject_Add_Step(external_usd after_install
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/usd/lib ${HARVEST_TARGET}/usd/lib
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/usd/src/external_usd-build/pxr/Debug/usd_m_d.lib ${HARVEST_TARGET}/usd/lib/libusd_m_d.lib
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/usd/src/external_usd-build/pxr/Debug/${PXR_LIB_PREFIX}usd_m_d.lib ${HARVEST_TARGET}/usd/lib/lib${PXR_LIB_PREFIX}usd_m_d.lib
DEPENDEES install
)
endif()
@@ -84,7 +92,7 @@ else()
# case (only the shared library). As a result, we need to grab the `libusd_m.a`
# file from the build directory instead of from the install directory.
ExternalProject_Add_Step(external_usd after_install
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/usd/src/external_usd-build/pxr/libusd_m.a ${HARVEST_TARGET}/usd/lib/libusd_m.a
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/usd/src/external_usd-build/pxr/lib${PXR_LIB_PREFIX}usd_m.a ${HARVEST_TARGET}/usd/lib/lib${PXR_LIB_PREFIX}usd_m.a
DEPENDEES install
)
endif()

View File

@@ -432,8 +432,8 @@ PYTHON_MODULES_PIP=(
)
BOOST_VERSION="1.73.0"
BOOST_VERSION_SHORT="1.73"
BOOST_VERSION="1.78.0"
BOOST_VERSION_SHORT="1.78"
BOOST_VERSION_MIN="1.49"
BOOST_VERSION_MEX="2.0"
BOOST_FORCE_BUILD=false
@@ -442,15 +442,15 @@ BOOST_SKIP=false
TBB_VERSION="2020"
TBB_VERSION_SHORT="2020"
TBB_VERSION_UPDATE="_U2" # Used for source packages...
TBB_VERSION_UPDATE="_U3" # Used for source packages...
TBB_VERSION_MIN="2018"
TBB_VERSION_MEX="2022"
TBB_FORCE_BUILD=false
TBB_FORCE_REBUILD=false
TBB_SKIP=false
OCIO_VERSION="2.0.0"
OCIO_VERSION_SHORT="2.0"
OCIO_VERSION="2.1.1"
OCIO_VERSION_SHORT="2.1"
OCIO_VERSION_MIN="2.0"
OCIO_VERSION_MEX="3.0"
OCIO_FORCE_BUILD=false
@@ -466,10 +466,10 @@ OPENEXR_FORCE_REBUILD=false
OPENEXR_SKIP=false
_with_built_openexr=false
OIIO_VERSION="2.2.15.1"
OIIO_VERSION_SHORT="2.2"
OIIO_VERSION="2.3.13.0"
OIIO_VERSION_SHORT="2.3"
OIIO_VERSION_MIN="2.1.12"
OIIO_VERSION_MEX="2.3.0"
OIIO_VERSION_MEX="2.4.0"
OIIO_FORCE_BUILD=false
OIIO_FORCE_REBUILD=false
OIIO_SKIP=false
@@ -493,7 +493,7 @@ OSL_FORCE_REBUILD=false
OSL_SKIP=false
# OpenSubdiv needs to be compiled for now
OSD_VERSION="3.4.3"
OSD_VERSION="3.4.4"
OSD_VERSION_SHORT="3.4"
OSD_VERSION_MIN="3.4"
OSD_VERSION_MEX="4.0"
@@ -502,19 +502,19 @@ OSD_FORCE_REBUILD=false
OSD_SKIP=false
# OpenVDB needs to be compiled for now
OPENVDB_BLOSC_VERSION="1.5.0"
OPENVDB_BLOSC_VERSION="1.21.1"
OPENVDB_VERSION="8.0.1"
OPENVDB_VERSION_SHORT="8.0"
OPENVDB_VERSION_MIN="8.0"
OPENVDB_VERSION_MEX="8.1"
OPENVDB_VERSION="9.0.0"
OPENVDB_VERSION_SHORT="9.0"
OPENVDB_VERSION_MIN="9.0"
OPENVDB_VERSION_MEX="9.1"
OPENVDB_FORCE_BUILD=false
OPENVDB_FORCE_REBUILD=false
OPENVDB_SKIP=false
# Alembic needs to be compiled for now
ALEMBIC_VERSION="1.7.16"
ALEMBIC_VERSION_SHORT="1.7"
ALEMBIC_VERSION="1.8.3"
ALEMBIC_VERSION_SHORT="1.8"
ALEMBIC_VERSION_MIN="1.7"
ALEMBIC_VERSION_MEX="2.0"
ALEMBIC_FORCE_BUILD=false
@@ -537,15 +537,15 @@ OPENCOLLADA_FORCE_BUILD=false
OPENCOLLADA_FORCE_REBUILD=false
OPENCOLLADA_SKIP=false
EMBREE_VERSION="3.10.0"
EMBREE_VERSION_SHORT="3.10"
EMBREE_VERSION_MIN="3.10"
EMBREE_VERSION="3.13.3"
EMBREE_VERSION_SHORT="3.13"
EMBREE_VERSION_MIN="3.13"
EMBREE_VERSION_MEX="4.0"
EMBREE_FORCE_BUILD=false
EMBREE_FORCE_REBUILD=false
EMBREE_SKIP=false
OIDN_VERSION="1.4.1"
OIDN_VERSION="1.4.3"
OIDN_VERSION_SHORT="1.4"
OIDN_VERSION_MIN="1.4.0"
OIDN_VERSION_MEX="1.5"
@@ -553,7 +553,7 @@ OIDN_FORCE_BUILD=false
OIDN_FORCE_REBUILD=false
OIDN_SKIP=false
ISPC_VERSION="1.16.0"
ISPC_VERSION="1.17.0"
FFMPEG_VERSION="4.4"
FFMPEG_VERSION_SHORT="4.4"
@@ -1029,7 +1029,7 @@ OPENEXR_SOURCE_REPO_UID="0ac2ea34c8f3134148a5df4052e40f155b76f6fb"
#~ OPENEXR_SOURCE=( "https://github.com/openexr/openexr/archive/$OPENEXR_SOURCE_REPO_UID.tar.gz" )
OIIO_USE_REPO=false
OIIO_SOURCE=( "https://github.com/OpenImageIO/oiio/archive/Release-$OIIO_VERSION.tar.gz" )
OIIO_SOURCE=( "https://github.com/OpenImageIO/oiio/archive/refs/tags/v$OIIO_VERSION.tar.gz" )
#~ OIIO_SOURCE_REPO=( "https://github.com/OpenImageIO/oiio.git" )
#~ OIIO_SOURCE_REPO_UID="c9e67275a0b248ead96152f6d2221cc0c0f278a4"
@@ -2034,7 +2034,7 @@ compile_OIIO() {
else
download OIIO_SOURCE[@] "$_src.tar.gz"
INFO "Unpacking OpenImageIO-$OIIO_VERSION"
tar -C $SRC --transform "s,(.*/?)oiio-Release-[^/]*(.*),\1OpenImageIO-$OIIO_VERSION\2,x" -xf $_src.tar.gz
tar -C $SRC --transform "s,(.*/?)oiio-[^/]*(.*),\1OpenImageIO-$OIIO_VERSION\2,x" -xf $_src.tar.gz
fi
fi

View File

@@ -32,9 +32,12 @@ FIND_PATH(USD_INCLUDE_DIR
DOC "Universal Scene Description (USD) header files"
)
# Since USD 21.11 the libraries are prefixed with "usd_", i.e. "libusd_m.a" became "libusd_usd_m.a".
# See https://github.com/PixarAnimationStudios/USD/blob/release/CHANGELOG.md#2111---2021-11-01
FIND_LIBRARY(USD_LIBRARY
NAMES
usd_m usd_ms
usd_usd_m usd_usd_ms usd_m usd_ms
${PXR_LIB_PREFIX}usd
NAMES_PER_DIR
HINTS
${_usd_SEARCH_DIRS}

View File

@@ -0,0 +1,77 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright 2022 Blender Foundation.
# - Find WebP library
# Find the native WebP includes and library
# This module defines
# WEBP_INCLUDE_DIRS, where to find WebP headers, Set when WebP is found.
# WEBP_LIBRARIES, libraries to link against to use WebP.
# WEBP_ROOT_DIR, The base directory to search for WebP.
# This can also be an environment variable.
# WEBP_FOUND, If false, do not try to use WebP.
#
# also defined, but not for general use are
# WEBP_LIBRARY, where to find the WEBP library.
# If WEBP_ROOT_DIR was defined in the environment, use it.
IF(NOT WEBP_ROOT_DIR AND NOT $ENV{WEBP_ROOT_DIR} STREQUAL "")
SET(WEBP_ROOT_DIR $ENV{WEBP_ROOT_DIR})
ENDIF()
SET(_webp_SEARCH_DIRS
${WEBP_ROOT_DIR}
/opt/lib/webp
)
FIND_PATH(WEBP_INCLUDE_DIR
NAMES
webp/types.h
HINTS
${_webp_SEARCH_DIRS}
PATH_SUFFIXES
include
)
SET(_webp_FIND_COMPONENTS
webp
webpmux
webpdemux
)
SET(_webp_LIBRARIES)
FOREACH(COMPONENT ${_webp_FIND_COMPONENTS})
STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT)
FIND_LIBRARY(WEBP_${UPPERCOMPONENT}_LIBRARY
NAMES
${COMPONENT}
NAMES_PER_DIR
HINTS
${_webp_SEARCH_DIRS}
PATH_SUFFIXES
lib64 lib lib/static
)
LIST(APPEND _webp_LIBRARIES "${WEBP_${UPPERCOMPONENT}_LIBRARY}")
ENDFOREACH()
IF(${WEBP_WEBP_LIBRARY_NOTFOUND})
set(WEBP_FOUND FALSE)
ELSE()
# handle the QUIETLY and REQUIRED arguments and set WEBP_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(WebP DEFAULT_MSG _webp_LIBRARIES WEBP_INCLUDE_DIR)
IF(WEBP_FOUND)
get_filename_component(WEBP_LIBRARY_DIR ${WEBP_WEBP_LIBRARY} DIRECTORY)
SET(WEBP_INCLUDE_DIRS ${WEBP_INCLUDE_DIR})
SET(WEBP_LIBRARIES ${_webp_LIBRARIES})
ELSE()
SET(WEBPL_PUGIXML_FOUND FALSE)
ENDIF()
ENDIF()
MARK_AS_ADVANCED(
WEBP_INCLUDE_DIR
WEBP_LIBRARY_DIR
)

View File

@@ -879,7 +879,7 @@ function(delayed_install
destination)
foreach(f ${files})
if(IS_ABSOLUTE ${f})
if(IS_ABSOLUTE ${f} OR "${base}" STREQUAL "")
set_property(GLOBAL APPEND PROPERTY DELAYED_INSTALL_FILES ${f})
else()
set_property(GLOBAL APPEND PROPERTY DELAYED_INSTALL_FILES ${base}/${f})

View File

@@ -106,8 +106,8 @@ if(WIN32)
set(CPACK_WIX_LIGHT_EXTRA_FLAGS -dcl:medium)
endif()
set(CPACK_PACKAGE_EXECUTABLES "blender-launcher" "blender")
set(CPACK_CREATE_DESKTOP_LINKS "blender-launcher" "blender")
set(CPACK_PACKAGE_EXECUTABLES "blender-launcher" "Blender")
set(CPACK_CREATE_DESKTOP_LINKS "blender-launcher" "Blender")
include(CPack)

View File

@@ -232,6 +232,15 @@ if(WITH_IMAGE_TIFF)
endif()
endif()
if(WITH_IMAGE_WEBP)
set(WEBP_ROOT_DIR ${LIBDIR}/webp)
find_package(WebP)
if(NOT WEBP_FOUND)
message(WARNING "WebP not found, disabling WITH_IMAGE_WEBP")
set(WITH_IMAGE_WEBP OFF)
endif()
endif()
if(WITH_BOOST)
set(Boost_NO_BOOST_CMAKE ON)
set(BOOST_ROOT ${LIBDIR}/boost)

View File

@@ -368,6 +368,14 @@ if(WITH_PUGIXML)
endif()
endif()
if(WITH_IMAGE_WEBP)
set(WEBP_ROOT_DIR ${LIBDIR}/webp)
find_package_wrapper(WebP)
if(NOT WEBP_FOUND)
set(WITH_IMAGE_WEBP OFF)
endif()
endif()
if(WITH_OPENIMAGEIO)
find_package_wrapper(OpenImageIO)
set(OPENIMAGEIO_LIBRARIES

View File

@@ -39,12 +39,12 @@ if(CMAKE_C_COMPILER_ID MATCHES "Clang")
set(WITH_WINDOWS_STRIPPED_PDB OFF)
endif()
else()
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.28.29921) # MSVC 2019 16.9.16
if(WITH_BLENDER AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.28.29921) # MSVC 2019 16.9.16
message(FATAL_ERROR "Compiler is unsupported, MSVC 2019 16.9.16 or newer is required for building blender.")
endif()
endif()
if(NOT WITH_PYTHON_MODULE)
if(WITH_BLENDER AND NOT WITH_PYTHON_MODULE)
set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT blender)
endif()
@@ -238,7 +238,6 @@ else()
endif()
if(NOT DEFINED LIBDIR)
# Setup 64bit and 64bit windows systems
if(CMAKE_CL_64)
message(STATUS "64 bit compiler detected.")
@@ -252,6 +251,9 @@ if(NOT DEFINED LIBDIR)
elseif(MSVC_VERSION GREATER 1919)
message(STATUS "Visual Studio 2019 detected.")
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc15)
elseif(MSVC_VERSION GREATER 1909)
message(STATUS "Visual Studio 2017 detected.")
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc15)
endif()
else()
message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}")
@@ -300,9 +302,8 @@ set(ZLIB_INCLUDE_DIR ${LIBDIR}/zlib/include)
set(ZLIB_LIBRARY ${LIBDIR}/zlib/lib/libz_st.lib)
set(ZLIB_DIR ${LIBDIR}/zlib)
windows_find_package(zlib) # we want to find before finding things that depend on it like png
windows_find_package(png)
windows_find_package(ZLIB) # we want to find before finding things that depend on it like png
windows_find_package(PNG)
if(NOT PNG_FOUND)
warn_hardcoded_paths(libpng)
set(PNG_PNG_INCLUDE_DIR ${LIBDIR}/png/include)
@@ -313,9 +314,9 @@ if(NOT PNG_FOUND)
endif()
set(JPEG_NAMES ${JPEG_NAMES} libjpeg)
windows_find_package(jpeg REQUIRED)
windows_find_package(JPEG REQUIRED)
if(NOT JPEG_FOUND)
warn_hardcoded_paths(jpeg)
warn_hardcoded_paths(libjpeg)
set(JPEG_INCLUDE_DIR ${LIBDIR}/jpeg/include)
set(JPEG_LIBRARIES ${LIBDIR}/jpeg/lib/libjpeg.lib)
endif()
@@ -333,7 +334,7 @@ set(FREETYPE_LIBRARIES
${LIBDIR}/brotli/lib/brotlidec-static.lib
${LIBDIR}/brotli/lib/brotlicommon-static.lib
)
windows_find_package(freetype REQUIRED)
windows_find_package(Freetype REQUIRED)
if(WITH_FFTW3)
set(FFTW3 ${LIBDIR}/fftw3)
@@ -342,6 +343,16 @@ if(WITH_FFTW3)
set(FFTW3_LIBPATH ${FFTW3}/lib)
endif()
windows_find_package(WebP)
if(NOT WEBP_FOUND)
if(EXISTS ${LIBDIR}/webp)
set(WEBP_INCLUDE_DIRS ${LIBDIR}/webp/include)
set(WEBP_ROOT_DIR ${LIBDIR}/webp)
set(WEBP_LIBRARIES ${LIBDIR}/webp/lib/webp.lib ${LIBDIR}/webp/lib/webpdemux.lib ${LIBDIR}/webp/lib/webpmux.lib)
set(WEBP_FOUND ON)
endif()
endif()
if(WITH_OPENCOLLADA)
set(OPENCOLLADA ${LIBDIR}/opencollada)
@@ -389,9 +400,9 @@ if(WITH_CODEC_FFMPEG)
${LIBDIR}/ffmpeg/include
${LIBDIR}/ffmpeg/include/msvc
)
windows_find_package(FFMPEG)
if(NOT FFMPEG_FOUND)
warn_hardcoded_paths(ffmpeg)
windows_find_package(FFmpeg)
if(NOT FFmpeg_FOUND)
warn_hardcoded_paths(FFmpeg)
set(FFMPEG_LIBRARIES
${LIBDIR}/ffmpeg/lib/avcodec.lib
${LIBDIR}/ffmpeg/lib/avformat.lib
@@ -403,10 +414,10 @@ if(WITH_CODEC_FFMPEG)
endif()
if(WITH_IMAGE_OPENEXR)
set(OPENEXR_ROOT_DIR ${LIBDIR}/openexr)
set(OPENEXR_VERSION "2.1")
windows_find_package(OPENEXR REQUIRED)
if(NOT OPENEXR_FOUND)
windows_find_package(OpenEXR REQUIRED)
if(NOT OpenEXR_FOUND)
set(OPENEXR_ROOT_DIR ${LIBDIR}/openexr)
set(OPENEXR_VERSION "2.1")
warn_hardcoded_paths(OpenEXR)
set(OPENEXR ${LIBDIR}/openexr)
set(OPENEXR_INCLUDE_DIR ${OPENEXR}/include)
@@ -520,17 +531,20 @@ if(WITH_BOOST)
set(BOOST_LIBRARIES ${Boost_LIBRARIES})
set(BOOST_LIBPATH ${Boost_LIBRARY_DIRS})
endif()
set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB")
endif()
if(WITH_OPENIMAGEIO)
windows_find_package(OpenImageIO)
set(OPENIMAGEIO ${LIBDIR}/OpenImageIO)
set(OPENIMAGEIO_LIBPATH ${OPENIMAGEIO}/lib)
set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO}/include)
set(OIIO_OPTIMIZED optimized ${OPENIMAGEIO_LIBPATH}/OpenImageIO.lib optimized ${OPENIMAGEIO_LIBPATH}/OpenImageIO_Util.lib)
set(OIIO_DEBUG debug ${OPENIMAGEIO_LIBPATH}/OpenImageIO_d.lib debug ${OPENIMAGEIO_LIBPATH}/OpenImageIO_Util_d.lib)
set(OPENIMAGEIO_LIBRARIES ${OIIO_OPTIMIZED} ${OIIO_DEBUG})
if(NOT OpenImageIO_FOUND)
set(OPENIMAGEIO ${LIBDIR}/OpenImageIO)
set(OPENIMAGEIO_LIBPATH ${OPENIMAGEIO}/lib)
set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO}/include)
set(OIIO_OPTIMIZED optimized ${OPENIMAGEIO_LIBPATH}/OpenImageIO.lib optimized ${OPENIMAGEIO_LIBPATH}/OpenImageIO_Util.lib)
set(OIIO_DEBUG debug ${OPENIMAGEIO_LIBPATH}/OpenImageIO_d.lib debug ${OPENIMAGEIO_LIBPATH}/OpenImageIO_Util_d.lib)
set(OPENIMAGEIO_LIBRARIES ${OIIO_OPTIMIZED} ${OIIO_DEBUG})
endif()
set(OPENIMAGEIO_DEFINITIONS "-DUSE_TBB=0")
set(OPENIMAGEIO_IDIFF "${OPENIMAGEIO}/bin/idiff.exe")
@@ -561,31 +575,38 @@ if(WITH_LLVM)
message(WARNING "LLVM debug libs not present on this system. Using release libs for debug builds.")
set(LLVM_LIBRARY ${LLVM_LIBRARY_OPTIMIZED})
endif()
endif()
if(WITH_OPENCOLORIO)
set(OPENCOLORIO ${LIBDIR}/OpenColorIO)
set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO}/include)
set(OPENCOLORIO_LIBPATH ${OPENCOLORIO}/lib)
set(OPENCOLORIO_LIBRARIES
optimized ${OPENCOLORIO_LIBPATH}/OpenColorIO.lib
optimized ${OPENCOLORIO_LIBPATH}/libyaml-cpp.lib
optimized ${OPENCOLORIO_LIBPATH}/libexpatMD.lib
optimized ${OPENCOLORIO_LIBPATH}/pystring.lib
debug ${OPENCOLORIO_LIBPATH}/OpencolorIO_d.lib
debug ${OPENCOLORIO_LIBPATH}/libyaml-cpp_d.lib
debug ${OPENCOLORIO_LIBPATH}/libexpatdMD.lib
debug ${OPENCOLORIO_LIBPATH}/pystring_d.lib
)
windows_find_package(OpenColorIO)
if(NOT OpenColorIO_FOUND)
set(OPENCOLORIO ${LIBDIR}/OpenColorIO)
set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO}/include)
set(OPENCOLORIO_LIBPATH ${OPENCOLORIO}/lib)
set(OPENCOLORIO_LIBRARIES
optimized ${OPENCOLORIO_LIBPATH}/OpenColorIO.lib
optimized ${OPENCOLORIO_LIBPATH}/libyaml-cpp.lib
optimized ${OPENCOLORIO_LIBPATH}/libexpatMD.lib
optimized ${OPENCOLORIO_LIBPATH}/pystring.lib
debug ${OPENCOLORIO_LIBPATH}/OpencolorIO_d.lib
debug ${OPENCOLORIO_LIBPATH}/libyaml-cpp_d.lib
debug ${OPENCOLORIO_LIBPATH}/libexpatdMD.lib
debug ${OPENCOLORIO_LIBPATH}/pystring_d.lib
)
endif()
set(OPENCOLORIO_DEFINITIONS "-DOpenColorIO_SKIP_IMPORTS")
endif()
if(WITH_OPENVDB)
set(OPENVDB ${LIBDIR}/openVDB)
set(OPENVDB_LIBPATH ${OPENVDB}/lib)
set(OPENVDB_INCLUDE_DIRS ${OPENVDB}/include)
set(OPENVDB_LIBRARIES optimized ${OPENVDB_LIBPATH}/openvdb.lib debug ${OPENVDB_LIBPATH}/openvdb_d.lib )
windows_find_package(OpenVDB)
if(NOT OpenVDB_FOUND)
set(OPENVDB ${LIBDIR}/openVDB)
set(OPENVDB_LIBPATH ${OPENVDB}/lib)
set(OPENVDB_INCLUDE_DIRS ${OPENVDB}/include)
set(OPENVDB_LIBRARIES optimized ${OPENVDB_LIBPATH}/openvdb.lib debug ${OPENVDB_LIBPATH}/openvdb_d.lib)
endif()
set(OPENVDB_DEFINITIONS -DNOMINMAX -D_USE_MATH_DEFINES)
endif()
@@ -624,21 +645,24 @@ if(WITH_IMAGE_OPENJPEG)
endif()
if(WITH_OPENSUBDIV)
set(OPENSUBDIV_INCLUDE_DIRS ${LIBDIR}/opensubdiv/include)
set(OPENSUBDIV_LIBPATH ${LIBDIR}/opensubdiv/lib)
set(OPENSUBDIV_LIBRARIES
optimized ${OPENSUBDIV_LIBPATH}/osdCPU.lib
optimized ${OPENSUBDIV_LIBPATH}/osdGPU.lib
debug ${OPENSUBDIV_LIBPATH}/osdCPU_d.lib
debug ${OPENSUBDIV_LIBPATH}/osdGPU_d.lib
)
set(OPENSUBDIV_HAS_OPENMP TRUE)
set(OPENSUBDIV_HAS_TBB FALSE)
set(OPENSUBDIV_HAS_OPENCL TRUE)
set(OPENSUBDIV_HAS_CUDA FALSE)
set(OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK TRUE)
set(OPENSUBDIV_HAS_GLSL_COMPUTE TRUE)
windows_find_package(OpenSubdiv)
if(NOT OpenSubdiv_FOUND)
set(OPENSUBDIV ${LIBDIR}/opensubdiv)
set(OPENSUBDIV_INCLUDE_DIRS ${OPENSUBDIV}/include)
set(OPENSUBDIV_LIBPATH ${OPENSUBDIV}/lib)
set(OPENSUBDIV_LIBRARIES
optimized ${OPENSUBDIV_LIBPATH}/osdCPU.lib
optimized ${OPENSUBDIV_LIBPATH}/osdGPU.lib
debug ${OPENSUBDIV_LIBPATH}/osdCPU_d.lib
debug ${OPENSUBDIV_LIBPATH}/osdGPU_d.lib
)
set(OPENSUBDIV_HAS_OPENMP TRUE)
set(OPENSUBDIV_HAS_TBB FALSE)
set(OPENSUBDIV_HAS_OPENCL TRUE)
set(OPENSUBDIV_HAS_CUDA FALSE)
set(OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK TRUE)
set(OPENSUBDIV_HAS_GLSL_COMPUTE TRUE)
endif()
endif()
if(WITH_SDL)
@@ -659,12 +683,15 @@ if(WITH_SYSTEM_AUDASPACE)
endif()
if(WITH_TBB)
set(TBB_LIBRARIES optimized ${LIBDIR}/tbb/lib/tbb.lib debug ${LIBDIR}/tbb/lib/tbb_debug.lib)
set(TBB_INCLUDE_DIR ${LIBDIR}/tbb/include)
set(TBB_INCLUDE_DIRS ${TBB_INCLUDE_DIR})
if(WITH_TBB_MALLOC_PROXY)
set(TBB_MALLOC_LIBRARIES optimized ${LIBDIR}/tbb/lib/tbbmalloc.lib debug ${LIBDIR}/tbb/lib/tbbmalloc_debug.lib)
add_definitions(-DWITH_TBB_MALLOC)
windows_find_package(TBB)
if(NOT TBB_FOUND)
set(TBB_LIBRARIES optimized ${LIBDIR}/tbb/lib/tbb.lib debug ${LIBDIR}/tbb/lib/tbb_debug.lib)
set(TBB_INCLUDE_DIR ${LIBDIR}/tbb/include)
set(TBB_INCLUDE_DIRS ${TBB_INCLUDE_DIR})
if(WITH_TBB_MALLOC_PROXY)
set(TBB_MALLOC_LIBRARIES optimized ${LIBDIR}/tbb/lib/tbbmalloc.lib debug ${LIBDIR}/tbb/lib/tbbmalloc_debug.lib)
add_definitions(-DWITH_TBB_MALLOC)
endif()
endif()
endif()
@@ -683,7 +710,6 @@ if(WITH_OPENAL)
else()
set(OPENAL_LIBRARY ${OPENAL_LIBPATH}/wrap_oal.lib)
endif()
endif()
if(WITH_CODEC_SNDFILE)
@@ -728,7 +754,7 @@ endif()
if(WITH_CYCLES AND WITH_CYCLES_EMBREE)
windows_find_package(Embree)
if(NOT EMBREE_FOUND)
if(NOT Embree_FOUND)
set(EMBREE_INCLUDE_DIRS ${LIBDIR}/embree/include)
set(EMBREE_LIBRARIES
optimized ${LIBDIR}/embree/lib/embree3.lib
@@ -756,7 +782,6 @@ endif()
if(WITH_USD)
windows_find_package(USD)
if(NOT USD_FOUND)
set(USD_FOUND ON)
set(USD_INCLUDE_DIRS ${LIBDIR}/usd/include)
set(USD_RELEASE_LIB ${LIBDIR}/usd/lib/libusd_m.lib)
set(USD_DEBUG_LIB ${LIBDIR}/usd/lib/libusd_m_d.lib)

View File

@@ -1,4 +1,4 @@
# Doxyfile 1.9.1
# Doxyfile 1.9.3
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
@@ -93,14 +93,6 @@ ALLOW_UNICODE_NAMES = NO
OUTPUT_LANGUAGE = English
# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all generated output in the proper direction.
# Possible values are: None, LTR, RTL and Context.
# The default value is: None.
OUTPUT_TEXT_DIRECTION = None
# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
# descriptions after the members that are listed in the file and class
# documentation (similar to Javadoc). Set to NO to disable this.
@@ -258,16 +250,16 @@ TAB_SIZE = 4
# the documentation. An alias has the form:
# name=value
# For example adding
# "sideeffect=@par Side Effects:\n"
# "sideeffect=@par Side Effects:^^"
# will allow you to put the command \sideeffect (or @sideeffect) in the
# documentation, which will result in a user-defined paragraph with heading
# "Side Effects:". You can put \n's in the value part of an alias to insert
# newlines (in the resulting output). You can put ^^ in the value part of an
# alias to insert a newline as if a physical newline was in the original file.
# When you need a literal { or } or , in the value part of an alias you have to
# escape them by means of a backslash (\), this can lead to conflicts with the
# commands \{ and \} for these it is advised to use the version @{ and @} or use
# a double escape (\\{ and \\})
# "Side Effects:". Note that you cannot put \n's in the value part of an alias
# to insert newlines (in the resulting output). You can put ^^ in the value part
# of an alias to insert a newline as if a physical newline was in the original
# file. When you need a literal { or } or , in the value part of an alias you
# have to escape them by means of a backslash (\), this can lead to conflicts
# with the commands \{ and \} for these it is advised to use the version @{ and
# @} or use a double escape (\\{ and \\})
ALIASES =
@@ -312,8 +304,8 @@ OPTIMIZE_OUTPUT_SLICE = NO
# extension. Doxygen has a built-in mapping, but you can override or extend it
# using this tag. The format is ext=language, where ext is a file extension, and
# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL,
# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice,
# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
# tries to guess whether the code is fixed or free formatted code, this is the
# default for Fortran type files). For instance to make doxygen treat .inc files
@@ -466,7 +458,7 @@ LOOKUP_CACHE_SIZE = 3
# than 0 to get more control over the balance between CPU load and processing
# speed. At this moment only the input processing can be done using multiple
# threads. Since this is still an experimental feature the default is set to 1,
# which efficively disables parallel processing. Please report any issues you
# which effectively disables parallel processing. Please report any issues you
# encounter. Generating dot graphs in parallel is controlled by the
# DOT_NUM_THREADS setting.
# Minimum value: 0, maximum value: 32, default value: 1.
@@ -610,6 +602,12 @@ HIDE_SCOPE_NAMES = NO
HIDE_COMPOUND_REFERENCE= NO
# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class
# will show which file needs to be included to use the class.
# The default value is: YES.
SHOW_HEADERFILE = YES
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
# the files that are included by a file in the documentation of that file.
# The default value is: YES.
@@ -767,7 +765,8 @@ FILE_VERSION_FILTER =
# output files in an output format independent way. To create the layout file
# that represents doxygen's defaults, run doxygen with the -l option. You can
# optionally specify a file name after the option, if omitted DoxygenLayout.xml
# will be used as the name of the layout file.
# will be used as the name of the layout file. See also section "Changing the
# layout of pages" for information.
#
# Note that if you run doxygen from a directory containing a file called
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
@@ -813,18 +812,26 @@ WARNINGS = YES
WARN_IF_UNDOCUMENTED = NO
# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
# potential errors in the documentation, such as not documenting some parameters
# in a documented function, or documenting parameters that don't exist or using
# markup commands wrongly.
# potential errors in the documentation, such as documenting some parameters in
# a documented function twice, or documenting parameters that don't exist or
# using markup commands wrongly.
# The default value is: YES.
WARN_IF_DOC_ERROR = YES
# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete
# function parameter documentation. If set to NO, doxygen will accept that some
# parameters have no documentation without warning.
# The default value is: YES.
WARN_IF_INCOMPLETE_DOC = YES
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
# are documented, but have no documentation for their parameters or return
# value. If set to NO, doxygen will only warn about wrong or incomplete
# parameter documentation, but not about the absence of documentation. If
# EXTRACT_ALL is set to YES then this flag will automatically be disabled.
# value. If set to NO, doxygen will only warn about wrong parameter
# documentation, but not about the absence of documentation. If EXTRACT_ALL is
# set to YES then this flag will automatically be disabled. See also
# WARN_IF_INCOMPLETE_DOC
# The default value is: NO.
WARN_NO_PARAMDOC = NO
@@ -850,7 +857,10 @@ WARN_FORMAT = "$file:$line: $text"
# The WARN_LOGFILE tag can be used to specify a file to which warning and error
# messages should be written. If left blank the output is written to standard
# error (stderr).
# error (stderr). In case the file specified cannot be opened for writing the
# warning and error messages are written to standard error. When as file - is
# specified the warning and error messages are written to standard output
# (stdout).
WARN_LOGFILE =
@@ -894,10 +904,10 @@ INPUT_ENCODING = UTF-8
#
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment),
# *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl,
# *.ucf, *.qsf and *.ice.
# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml,
# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C
# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
# *.vhdl, *.ucf, *.qsf and *.ice.
FILE_PATTERNS =
@@ -939,7 +949,7 @@ EXCLUDE_PATTERNS = .svn \
# (namespaces, classes, functions, etc.) that should be excluded from the
# output. The symbol name can be a fully qualified name, a word, or if the
# wildcard * is used, a substring. Examples: ANamespace, AClass,
# AClass::ANamespace, ANamespace::*Test
# ANamespace::AClass, ANamespace::*Test
#
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories use the pattern */test/*
@@ -1224,7 +1234,7 @@ HTML_EXTRA_FILES =
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
# will adjust the colors in the style sheet and background images according to
# this color. Hue is specified as an angle on a colorwheel, see
# this color. Hue is specified as an angle on a color-wheel, see
# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
# purple, and 360 is red again.
@@ -1234,7 +1244,7 @@ HTML_EXTRA_FILES =
HTML_COLORSTYLE_HUE = 220
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
# in the HTML output. For a value of 0 the output will use grayscales only. A
# in the HTML output. For a value of 0 the output will use gray-scales only. A
# value of 255 will produce the most vivid colors.
# Minimum value: 0, maximum value: 255, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES.
@@ -1316,6 +1326,13 @@ GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs"
# This tag determines the URL of the docset feed. A documentation feed provides
# an umbrella under which multiple documentation sets from a single provider
# (such as a company or product suite) can be grouped.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_FEEDURL =
# This tag specifies a string that should uniquely identify the documentation
# set bundle. This should be a reverse domain-name style string, e.g.
# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
@@ -1341,8 +1358,12 @@ DOCSET_PUBLISHER_NAME = Publisher
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
# (see:
# https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows.
# on Windows. In the beginning of 2021 Microsoft took the original page, with
# a.o. the download links, offline the HTML help workshop was already many years
# in maintenance mode). You can download the HTML help workshop from the web
# archives at Installation executable (see:
# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo
# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe).
#
# The HTML Help Workshop contains a compiler that can convert all HTML output
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
@@ -1501,16 +1522,28 @@ DISABLE_INDEX = NO
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
# (i.e. any modern browser). Windows users are probably better off using the
# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
# further fine-tune the look of the index. As an example, the default style
# sheet generated by doxygen has an example that shows how to put an image at
# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
# the same information as the tab index, you could consider setting
# DISABLE_INDEX to YES when enabling this option.
# further fine tune the look of the index (see "Fine-tuning the output"). As an
# example, the default style sheet generated by doxygen has an example that
# shows how to put an image at the root of the tree instead of the PROJECT_NAME.
# Since the tree basically has the same information as the tab index, you could
# consider setting DISABLE_INDEX to YES when enabling this option.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_TREEVIEW = NO
# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
# area (value NO) or if it should extend to the full height of the window (value
# YES). Setting this to YES gives a layout similar to
# https://docs.readthedocs.io with more room for contents, but less room for the
# project logo, title, and description. If either GENERATE_TREEVIEW or
# DISABLE_INDEX is set to NO, this option has no effect.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
FULL_SIDEBAR = NO
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
# doxygen will group on one line in the generated HTML documentation.
#
@@ -1535,6 +1568,13 @@ TREEVIEW_WIDTH = 246
EXT_LINKS_IN_WINDOW = NO
# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email
# addresses.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
OBFUSCATE_EMAILS = YES
# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
@@ -1583,11 +1623,29 @@ FORMULA_MACROFILE =
USE_MATHJAX = NO
# With MATHJAX_VERSION it is possible to specify the MathJax version to be used.
# Note that the different versions of MathJax have different requirements with
# regards to the different settings, so it is possible that also other MathJax
# settings have to be changed when switching between the different MathJax
# versions.
# Possible values are: MathJax_2 and MathJax_3.
# The default value is: MathJax_2.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_VERSION = MathJax_2
# When MathJax is enabled you can set the default output format to be used for
# the MathJax output. See the MathJax site (see:
# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details.
# the MathJax output. For more details about the output format see MathJax
# version 2 (see:
# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3
# (see:
# http://docs.mathjax.org/en/latest/web/components/output.html).
# Possible values are: HTML-CSS (which is slower, but has the best
# compatibility), NativeMML (i.e. MathML) and SVG.
# compatibility. This is the name for Mathjax version 2, for MathJax version 3
# this will be translated into chtml), NativeMML (i.e. MathML. Only supported
# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This
# is the name for Mathjax version 3, for MathJax version 2 this will be
# translated into HTML-CSS) and SVG.
# The default value is: HTML-CSS.
# This tag requires that the tag USE_MATHJAX is set to YES.
@@ -1600,15 +1658,21 @@ MATHJAX_FORMAT = HTML-CSS
# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
# Content Delivery Network so you can quickly see the result without installing
# MathJax. However, it is strongly recommended to install a local copy of
# MathJax from https://www.mathjax.org before deployment.
# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2.
# MathJax from https://www.mathjax.org before deployment. The default value is:
# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2
# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_RELPATH = http://www.mathjax.org/mathjax
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
# extension names that should be enabled during MathJax rendering. For example
# for MathJax version 2 (see
# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions):
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
# For example for MathJax version 3 (see
# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html):
# MATHJAX_EXTENSIONS = ams
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_EXTENSIONS =
@@ -1788,29 +1852,31 @@ PAPER_TYPE = a4
EXTRA_PACKAGES =
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
# generated LaTeX document. The header should contain everything until the first
# chapter. If it is left blank doxygen will generate a standard header. See
# section "Doxygen usage" for information on how to let doxygen write the
# default header to a separate file.
# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for
# the generated LaTeX document. The header should contain everything until the
# first chapter. If it is left blank doxygen will generate a standard header. It
# is highly recommended to start with a default header using
# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
# and then modify the file new_header.tex. See also section "Doxygen usage" for
# information on how to generate the default header that doxygen normally uses.
#
# Note: Only use a user-defined header if you know what you are doing! The
# following commands have a special meaning inside the header: $title,
# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
# string, for the replacement values of the other commands the user is referred
# to HTML_HEADER.
# Note: Only use a user-defined header if you know what you are doing!
# Note: The header is subject to change so you typically have to regenerate the
# default header when upgrading to a newer version of doxygen. The following
# commands have a special meaning inside the header (and footer): For a
# description of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HEADER =
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
# generated LaTeX document. The footer should contain everything after the last
# chapter. If it is left blank doxygen will generate a standard footer. See
# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for
# the generated LaTeX document. The footer should contain everything after the
# last chapter. If it is left blank doxygen will generate a standard footer. See
# LATEX_HEADER for more information on how to generate a default footer and what
# special commands can be used inside the footer.
#
# Note: Only use a user-defined footer if you know what you are doing!
# special commands can be used inside the footer. See also section "Doxygen
# usage" for information on how to generate the default footer that doxygen
# normally uses. Note: Only use a user-defined footer if you know what you are
# doing!
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_FOOTER =
@@ -1855,8 +1921,7 @@ USE_PDFLATEX = NO
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
# command to the generated LaTeX files. This will instruct LaTeX to keep running
# if errors occur, instead of asking the user for help. This option is also used
# when generating formulas in HTML.
# if errors occur, instead of asking the user for help.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
@@ -1869,16 +1934,6 @@ LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
# code with syntax highlighting in the LaTeX output.
#
# Note that which sources are shown also depends on other settings such as
# SOURCE_BROWSER.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_SOURCE_CODE = NO
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
# bibliography, e.g. plainnat, or ieeetr. See
# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
@@ -1959,16 +2014,6 @@ RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
# with syntax highlighting in the RTF output.
#
# Note that which sources are shown also depends on other settings such as
# SOURCE_BROWSER.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_SOURCE_CODE = NO
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
@@ -2065,15 +2110,6 @@ GENERATE_DOCBOOK = NO
DOCBOOK_OUTPUT = docbook
# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
# program listings (including syntax highlighting and cross-referencing
# information) to the DOCBOOK output. Note that enabling this will significantly
# increase the size of the DOCBOOK output.
# The default value is: NO.
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
DOCBOOK_PROGRAMLISTING = NO
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
@@ -2254,15 +2290,6 @@ EXTERNAL_PAGES = YES
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
# NO turns the diagrams off. Note that this option also works with HAVE_DOT
# disabled, but it is recommended to install and use dot, since it yields more
# powerful graphs.
# The default value is: YES.
CLASS_DIAGRAMS = NO
# You can include diagrams made with dia in doxygen documentation. Doxygen will
# then run dia to produce the diagram and insert it in the documentation. The
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
@@ -2319,13 +2346,16 @@ DOT_FONTSIZE = 10
DOT_FONTPATH =
# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
# each documented class showing the direct and indirect inheritance relations.
# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
# If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a
# graph for each documented class showing the direct and indirect inheritance
# relations. In case HAVE_DOT is set as well dot will be used to draw the graph,
# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set
# to TEXT the direct and indirect inheritance relations will be shown as texts /
# links.
# Possible values are: NO, YES, TEXT and GRAPH.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
CLASS_GRAPH = YES
CLASS_GRAPH = TEXT
# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
# graph for each documented class showing the direct and indirect implementation
@@ -2452,6 +2482,13 @@ GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels
# of child directories generated in directory dependency graphs by dot.
# Minimum value: 1, maximum value: 25, default value: 1.
# This tag requires that the tag DIRECTORY_GRAPH is set to YES.
DIR_GRAPH_MAX_DEPTH = 1
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
# generated by dot. For an explanation of the image formats see the section
# output formats in the documentation of the dot tool (Graphviz (see:
@@ -2505,10 +2542,10 @@ MSCFILE_DIRS =
DIAFILE_DIRS =
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
# path where java can find the plantuml.jar file. If left blank, it is assumed
# PlantUML is not used or called during a preprocessing step. Doxygen will
# generate a warning when it encounters a \startuml command in this case and
# will not generate output for the diagram.
# path where java can find the plantuml.jar file or to the filename of jar file
# to be used. If left blank, it is assumed PlantUML is not used or called during
# a preprocessing step. Doxygen will generate a warning when it encounters a
# \startuml command in this case and will not generate output for the diagram.
PLANTUML_JAR_PATH =
@@ -2570,6 +2607,8 @@ DOT_MULTI_TARGETS = YES
# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
# explaining the meaning of the various boxes and arrows in the dot generated
# graphs.
# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal
# graphical representation for inheritance and collaboration diagrams is used.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
@@ -2578,8 +2617,8 @@ GENERATE_LEGEND = YES
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
# files that are used to generate the various graphs.
#
# Note: This setting is not only used for dot files but also for msc and
# plantuml temporary files.
# Note: This setting is not only used for dot files but also for msc temporary
# files.
# The default value is: YES.
DOT_CLEANUP = YES

View File

@@ -41,7 +41,7 @@ class MATERIAL_UL_matslots_example(bpy.types.UIList):
else:
layout.label(text="", translate=False, icon_value=icon)
# 'GRID' layout type should be as compact as possible (typically a single icon!).
elif self.layout_type in {'GRID'}:
elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.label(text="", icon_value=icon)

View File

@@ -73,7 +73,7 @@ class MESH_UL_vgroups_slow(bpy.types.UIList):
layout.prop(vgroup, "name", text="", emboss=False, icon_value=icon)
icon = 'LOCKED' if vgroup.lock_weight else 'UNLOCKED'
layout.prop(vgroup, "lock_weight", text="", icon=icon, emboss=False)
elif self.layout_type in {'GRID'}:
elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
if flt_flag & self.VGROUP_EMPTY:
layout.enabled = False

View File

@@ -63,6 +63,7 @@ import os
import sys
import inspect
import shutil
import time
import logging
import warnings
@@ -399,6 +400,7 @@ MODULE_GROUPING = {
# converting bytes to strings, due to T30154
BLENDER_REVISION = str(bpy.app.build_hash, 'utf_8')
BLENDER_REVISION_TIMESTAMP = bpy.app.build_commit_timestamp
# '2.83.0 Beta' or '2.83.0' or '2.83.1'
BLENDER_VERSION_STRING = bpy.app.version_string
@@ -407,9 +409,13 @@ BLENDER_VERSION_DOTS = "%d.%d" % (bpy.app.version[0], bpy.app.version[1])
if BLENDER_REVISION != "Unknown":
# SHA1 Git hash
BLENDER_VERSION_HASH = BLENDER_REVISION
BLENDER_VERSION_HASH_HTML_LINK = "<a href=https://developer.blender.org/rB%s>%s</a>" % (BLENDER_VERSION_HASH, BLENDER_VERSION_HASH)
BLENDER_VERSION_DATE = time.strftime("%d/%m/%Y", time.localtime(BLENDER_REVISION_TIMESTAMP))
else:
# Fallback: Should not be used
BLENDER_VERSION_HASH = "Hash Unknown"
BLENDER_VERSION_HASH_HTML_LINK = BLENDER_VERSION_HASH
BLENDER_VERSION_DATE = time.strftime("%Y-%m-%d")
# '2_83'
BLENDER_VERSION_PATH = "%d_%d" % (bpy.app.version[0], bpy.app.version[1])
@@ -1752,11 +1758,12 @@ except ModuleNotFoundError:
fw("html_split_index = True\n")
fw("html_static_path = ['static']\n")
fw("templates_path = ['templates']\n")
fw("html_context = {'commit': '%s'}\n" % BLENDER_VERSION_HASH)
fw("html_context = {'commit': '%s - %s'}\n" % (BLENDER_VERSION_HASH_HTML_LINK, BLENDER_VERSION_DATE))
fw("html_extra_path = ['static/favicon.ico', 'static/blender_logo.svg']\n")
fw("html_favicon = 'static/favicon.ico'\n")
fw("html_logo = 'static/blender_logo.svg'\n")
fw("html_last_updated_fmt = '%m/%d/%Y'\n\n")
# Disable default `last_updated` value, since this is the date of doc generation, not the one of the source commit.
fw("html_last_updated_fmt = None\n\n")
fw("if html_theme == 'sphinx_rtd_theme':\n")
fw(" html_css_files = ['css/version_switch.css']\n")
fw(" html_js_files = ['js/version_switch.js']\n")

27
extern/fmtlib/LICENSE.rst vendored Normal file
View File

@@ -0,0 +1,27 @@
Copyright (c) 2012 - present, Victor Zverovich
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--- Optional exception to the license ---
As an exception, if, as a result of your compiling your source code, portions
of this Software are embedded into a machine-executable object form of such
source code, you may redistribute such embedded portions in such object form
without including the above copyright and permission notices.

8
extern/fmtlib/README.blender vendored Normal file
View File

@@ -0,0 +1,8 @@
Project: {fmt}
URL: https://github.com/fmtlib/fmt
License: MIT
Upstream version: 8.1.1 (b6f4cea)
Local modifications:
- Took only files needed for Blender: LICENSE, README and include/fmt
folder's core.h, format-inl.h, format.h

528
extern/fmtlib/README.rst vendored Normal file
View File

@@ -0,0 +1,528 @@
{fmt}
=====
.. image:: https://github.com/fmtlib/fmt/workflows/linux/badge.svg
:target: https://github.com/fmtlib/fmt/actions?query=workflow%3Alinux
.. image:: https://github.com/fmtlib/fmt/workflows/macos/badge.svg
:target: https://github.com/fmtlib/fmt/actions?query=workflow%3Amacos
.. image:: https://github.com/fmtlib/fmt/workflows/windows/badge.svg
:target: https://github.com/fmtlib/fmt/actions?query=workflow%3Awindows
.. image:: https://ci.appveyor.com/api/projects/status/ehjkiefde6gucy1v?svg=true
:target: https://ci.appveyor.com/project/vitaut/fmt
.. image:: https://oss-fuzz-build-logs.storage.googleapis.com/badges/fmt.svg
:alt: fmt is continuously fuzzed at oss-fuzz
:target: https://bugs.chromium.org/p/oss-fuzz/issues/list?\
colspec=ID%20Type%20Component%20Status%20Proj%20Reported%20Owner%20\
Summary&q=proj%3Dfmt&can=1
.. image:: https://img.shields.io/badge/stackoverflow-fmt-blue.svg
:alt: Ask questions at StackOverflow with the tag fmt
:target: https://stackoverflow.com/questions/tagged/fmt
**{fmt}** is an open-source formatting library providing a fast and safe
alternative to C stdio and C++ iostreams.
If you like this project, please consider donating to the BYSOL
Foundation that helps victims of political repressions in Belarus:
https://bysol.org/en/bs/general/.
`Documentation <https://fmt.dev>`__
Q&A: ask questions on `StackOverflow with the tag fmt
<https://stackoverflow.com/questions/tagged/fmt>`_.
Try {fmt} in `Compiler Explorer <https://godbolt.org/z/Eq5763>`_.
Features
--------
* Simple `format API <https://fmt.dev/latest/api.html>`_ with positional arguments
for localization
* Implementation of `C++20 std::format
<https://en.cppreference.com/w/cpp/utility/format>`__
* `Format string syntax <https://fmt.dev/latest/syntax.html>`_ similar to Python's
`format <https://docs.python.org/3/library/stdtypes.html#str.format>`_
* Fast IEEE 754 floating-point formatter with correct rounding, shortness and
round-trip guarantees
* Safe `printf implementation
<https://fmt.dev/latest/api.html#printf-formatting>`_ including the POSIX
extension for positional arguments
* Extensibility: `support for user-defined types
<https://fmt.dev/latest/api.html#formatting-user-defined-types>`_
* High performance: faster than common standard library implementations of
``(s)printf``, iostreams, ``to_string`` and ``to_chars``, see `Speed tests`_
and `Converting a hundred million integers to strings per second
<http://www.zverovich.net/2020/06/13/fast-int-to-string-revisited.html>`_
* Small code size both in terms of source code with the minimum configuration
consisting of just three files, ``core.h``, ``format.h`` and ``format-inl.h``,
and compiled code; see `Compile time and code bloat`_
* Reliability: the library has an extensive set of `tests
<https://github.com/fmtlib/fmt/tree/master/test>`_ and is `continuously fuzzed
<https://bugs.chromium.org/p/oss-fuzz/issues/list?colspec=ID%20Type%20
Component%20Status%20Proj%20Reported%20Owner%20Summary&q=proj%3Dfmt&can=1>`_
* Safety: the library is fully type safe, errors in format strings can be
reported at compile time, automatic memory management prevents buffer overflow
errors
* Ease of use: small self-contained code base, no external dependencies,
permissive MIT `license
<https://github.com/fmtlib/fmt/blob/master/LICENSE.rst>`_
* `Portability <https://fmt.dev/latest/index.html#portability>`_ with
consistent output across platforms and support for older compilers
* Clean warning-free codebase even on high warning levels such as
``-Wall -Wextra -pedantic``
* Locale-independence by default
* Optional header-only configuration enabled with the ``FMT_HEADER_ONLY`` macro
See the `documentation <https://fmt.dev>`_ for more details.
Examples
--------
**Print to stdout** (`run <https://godbolt.org/z/Tevcjh>`_)
.. code:: c++
#include <fmt/core.h>
int main() {
fmt::print("Hello, world!\n");
}
**Format a string** (`run <https://godbolt.org/z/oK8h33>`_)
.. code:: c++
std::string s = fmt::format("The answer is {}.", 42);
// s == "The answer is 42."
**Format a string using positional arguments** (`run <https://godbolt.org/z/Yn7Txe>`_)
.. code:: c++
std::string s = fmt::format("I'd rather be {1} than {0}.", "right", "happy");
// s == "I'd rather be happy than right."
**Print chrono durations** (`run <https://godbolt.org/z/K8s4Mc>`_)
.. code:: c++
#include <fmt/chrono.h>
int main() {
using namespace std::literals::chrono_literals;
fmt::print("Default format: {} {}\n", 42s, 100ms);
fmt::print("strftime-like format: {:%H:%M:%S}\n", 3h + 15min + 30s);
}
Output::
Default format: 42s 100ms
strftime-like format: 03:15:30
**Print a container** (`run <https://godbolt.org/z/MjsY7c>`_)
.. code:: c++
#include <vector>
#include <fmt/ranges.h>
int main() {
std::vector<int> v = {1, 2, 3};
fmt::print("{}\n", v);
}
Output::
[1, 2, 3]
**Check a format string at compile time**
.. code:: c++
std::string s = fmt::format("{:d}", "I am not a number");
This gives a compile-time error in C++20 because ``d`` is an invalid format
specifier for a string.
**Write a file from a single thread**
.. code:: c++
#include <fmt/os.h>
int main() {
auto out = fmt::output_file("guide.txt");
out.print("Don't {}", "Panic");
}
This can be `5 to 9 times faster than fprintf
<http://www.zverovich.net/2020/08/04/optimal-file-buffer-size.html>`_.
**Print with colors and text styles**
.. code:: c++
#include <fmt/color.h>
int main() {
fmt::print(fg(fmt::color::crimson) | fmt::emphasis::bold,
"Hello, {}!\n", "world");
fmt::print(fg(fmt::color::floral_white) | bg(fmt::color::slate_gray) |
fmt::emphasis::underline, "Hello, {}!\n", "мир");
fmt::print(fg(fmt::color::steel_blue) | fmt::emphasis::italic,
"Hello, {}!\n", "世界");
}
Output on a modern terminal:
.. image:: https://user-images.githubusercontent.com/
576385/88485597-d312f600-cf2b-11ea-9cbe-61f535a86e28.png
Benchmarks
----------
Speed tests
~~~~~~~~~~~
================= ============= ===========
Library Method Run Time, s
================= ============= ===========
libc printf 1.04
libc++ std::ostream 3.05
{fmt} 6.1.1 fmt::print 0.75
Boost Format 1.67 boost::format 7.24
Folly Format folly::format 2.23
================= ============= ===========
{fmt} is the fastest of the benchmarked methods, ~35% faster than ``printf``.
The above results were generated by building ``tinyformat_test.cpp`` on macOS
10.14.6 with ``clang++ -O3 -DNDEBUG -DSPEED_TEST -DHAVE_FORMAT``, and taking the
best of three runs. In the test, the format string ``"%0.10f:%04d:%+g:%s:%p:%c:%%\n"``
or equivalent is filled 2,000,000 times with output sent to ``/dev/null``; for
further details refer to the `source
<https://github.com/fmtlib/format-benchmark/blob/master/src/tinyformat-test.cc>`_.
{fmt} is up to 20-30x faster than ``std::ostringstream`` and ``sprintf`` on
floating-point formatting (`dtoa-benchmark <https://github.com/fmtlib/dtoa-benchmark>`_)
and faster than `double-conversion <https://github.com/google/double-conversion>`_ and
`ryu <https://github.com/ulfjack/ryu>`_:
.. image:: https://user-images.githubusercontent.com/576385/
95684665-11719600-0ba8-11eb-8e5b-972ff4e49428.png
:target: https://fmt.dev/unknown_mac64_clang12.0.html
Compile time and code bloat
~~~~~~~~~~~~~~~~~~~~~~~~~~~
The script `bloat-test.py
<https://github.com/fmtlib/format-benchmark/blob/master/bloat-test.py>`_
from `format-benchmark <https://github.com/fmtlib/format-benchmark>`_
tests compile time and code bloat for nontrivial projects.
It generates 100 translation units and uses ``printf()`` or its alternative
five times in each to simulate a medium sized project. The resulting
executable size and compile time (Apple LLVM version 8.1.0 (clang-802.0.42),
macOS Sierra, best of three) is shown in the following tables.
**Optimized build (-O3)**
============= =============== ==================== ==================
Method Compile Time, s Executable size, KiB Stripped size, KiB
============= =============== ==================== ==================
printf 2.6 29 26
printf+string 16.4 29 26
iostreams 31.1 59 55
{fmt} 19.0 37 34
Boost Format 91.9 226 203
Folly Format 115.7 101 88
============= =============== ==================== ==================
As you can see, {fmt} has 60% less overhead in terms of resulting binary code
size compared to iostreams and comes pretty close to ``printf``. Boost Format
and Folly Format have the largest overheads.
``printf+string`` is the same as ``printf`` but with extra ``<string>``
include to measure the overhead of the latter.
**Non-optimized build**
============= =============== ==================== ==================
Method Compile Time, s Executable size, KiB Stripped size, KiB
============= =============== ==================== ==================
printf 2.2 33 30
printf+string 16.0 33 30
iostreams 28.3 56 52
{fmt} 18.2 59 50
Boost Format 54.1 365 303
Folly Format 79.9 445 430
============= =============== ==================== ==================
``libc``, ``lib(std)c++`` and ``libfmt`` are all linked as shared libraries to
compare formatting function overhead only. Boost Format is a
header-only library so it doesn't provide any linkage options.
Running the tests
~~~~~~~~~~~~~~~~~
Please refer to `Building the library`__ for the instructions on how to build
the library and run the unit tests.
__ https://fmt.dev/latest/usage.html#building-the-library
Benchmarks reside in a separate repository,
`format-benchmarks <https://github.com/fmtlib/format-benchmark>`_,
so to run the benchmarks you first need to clone this repository and
generate Makefiles with CMake::
$ git clone --recursive https://github.com/fmtlib/format-benchmark.git
$ cd format-benchmark
$ cmake .
Then you can run the speed test::
$ make speed-test
or the bloat test::
$ make bloat-test
Migrating code
--------------
`clang-tidy-fmt <https://github.com/mikecrowe/clang-tidy-fmt>`_ provides clang
tidy checks for converting occurrences of ``printf`` and ``fprintf`` to
``fmt::print``.
Projects using this library
---------------------------
* `0 A.D. <https://play0ad.com/>`_: a free, open-source, cross-platform
real-time strategy game
* `2GIS <https://2gis.ru/>`_: free business listings with a city map
* `AMPL/MP <https://github.com/ampl/mp>`_:
an open-source library for mathematical programming
* `Aseprite <https://github.com/aseprite/aseprite>`_:
animated sprite editor & pixel art tool
* `AvioBook <https://www.aviobook.aero/en>`_: a comprehensive aircraft
operations suite
* `Blizzard Battle.net <https://battle.net/>`_: an online gaming platform
* `Celestia <https://celestia.space/>`_: real-time 3D visualization of space
* `Ceph <https://ceph.com/>`_: a scalable distributed storage system
* `ccache <https://ccache.dev/>`_: a compiler cache
* `ClickHouse <https://github.com/ClickHouse/ClickHouse>`_: analytical database
management system
* `CUAUV <https://cuauv.org/>`_: Cornell University's autonomous underwater
vehicle
* `Drake <https://drake.mit.edu/>`_: a planning, control, and analysis toolbox
for nonlinear dynamical systems (MIT)
* `Envoy <https://lyft.github.io/envoy/>`_: C++ L7 proxy and communication bus
(Lyft)
* `FiveM <https://fivem.net/>`_: a modification framework for GTA V
* `fmtlog <https://github.com/MengRao/fmtlog>`_: a performant fmtlib-style
logging library with latency in nanoseconds
* `Folly <https://github.com/facebook/folly>`_: Facebook open-source library
* `Grand Mountain Adventure
<https://store.steampowered.com/app/1247360/Grand_Mountain_Adventure/>`_:
A beautiful open-world ski & snowboarding game
* `HarpyWar/pvpgn <https://github.com/pvpgn/pvpgn-server>`_:
Player vs Player Gaming Network with tweaks
* `KBEngine <https://github.com/kbengine/kbengine>`_: an open-source MMOG server
engine
* `Keypirinha <https://keypirinha.com/>`_: a semantic launcher for Windows
* `Kodi <https://kodi.tv/>`_ (formerly xbmc): home theater software
* `Knuth <https://kth.cash/>`_: high-performance Bitcoin full-node
* `Microsoft Verona <https://github.com/microsoft/verona>`_:
research programming language for concurrent ownership
* `MongoDB <https://mongodb.com/>`_: distributed document database
* `MongoDB Smasher <https://github.com/duckie/mongo_smasher>`_: a small tool to
generate randomized datasets
* `OpenSpace <https://openspaceproject.com/>`_: an open-source
astrovisualization framework
* `PenUltima Online (POL) <https://www.polserver.com/>`_:
an MMO server, compatible with most Ultima Online clients
* `PyTorch <https://github.com/pytorch/pytorch>`_: an open-source machine
learning library
* `quasardb <https://www.quasardb.net/>`_: a distributed, high-performance,
associative database
* `Quill <https://github.com/odygrd/quill>`_: asynchronous low-latency logging library
* `QKW <https://github.com/ravijanjam/qkw>`_: generalizing aliasing to simplify
navigation, and executing complex multi-line terminal command sequences
* `redis-cerberus <https://github.com/HunanTV/redis-cerberus>`_: a Redis cluster
proxy
* `redpanda <https://vectorized.io/redpanda>`_: a 10x faster Kafka® replacement
for mission critical systems written in C++
* `rpclib <http://rpclib.net/>`_: a modern C++ msgpack-RPC server and client
library
* `Salesforce Analytics Cloud
<https://www.salesforce.com/analytics-cloud/overview/>`_:
business intelligence software
* `Scylla <https://www.scylladb.com/>`_: a Cassandra-compatible NoSQL data store
that can handle 1 million transactions per second on a single server
* `Seastar <http://www.seastar-project.org/>`_: an advanced, open-source C++
framework for high-performance server applications on modern hardware
* `spdlog <https://github.com/gabime/spdlog>`_: super fast C++ logging library
* `Stellar <https://www.stellar.org/>`_: financial platform
* `Touch Surgery <https://www.touchsurgery.com/>`_: surgery simulator
* `TrinityCore <https://github.com/TrinityCore/TrinityCore>`_: open-source
MMORPG framework
* `Windows Terminal <https://github.com/microsoft/terminal>`_: the new Windows
terminal
`More... <https://github.com/search?q=fmtlib&type=Code>`_
If you are aware of other projects using this library, please let me know
by `email <mailto:victor.zverovich@gmail.com>`_ or by submitting an
`issue <https://github.com/fmtlib/fmt/issues>`_.
Motivation
----------
So why yet another formatting library?
There are plenty of methods for doing this task, from standard ones like
the printf family of function and iostreams to Boost Format and FastFormat
libraries. The reason for creating a new library is that every existing
solution that I found either had serious issues or didn't provide
all the features I needed.
printf
~~~~~~
The good thing about ``printf`` is that it is pretty fast and readily available
being a part of the C standard library. The main drawback is that it
doesn't support user-defined types. ``printf`` also has safety issues although
they are somewhat mitigated with `__attribute__ ((format (printf, ...))
<https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html>`_ in GCC.
There is a POSIX extension that adds positional arguments required for
`i18n <https://en.wikipedia.org/wiki/Internationalization_and_localization>`_
to ``printf`` but it is not a part of C99 and may not be available on some
platforms.
iostreams
~~~~~~~~~
The main issue with iostreams is best illustrated with an example:
.. code:: c++
std::cout << std::setprecision(2) << std::fixed << 1.23456 << "\n";
which is a lot of typing compared to printf:
.. code:: c++
printf("%.2f\n", 1.23456);
Matthew Wilson, the author of FastFormat, called this "chevron hell". iostreams
don't support positional arguments by design.
The good part is that iostreams support user-defined types and are safe although
error handling is awkward.
Boost Format
~~~~~~~~~~~~
This is a very powerful library which supports both ``printf``-like format
strings and positional arguments. Its main drawback is performance. According to
various benchmarks, it is much slower than other methods considered here. Boost
Format also has excessive build times and severe code bloat issues (see
`Benchmarks`_).
FastFormat
~~~~~~~~~~
This is an interesting library which is fast, safe and has positional arguments.
However, it has significant limitations, citing its author:
Three features that have no hope of being accommodated within the
current design are:
* Leading zeros (or any other non-space padding)
* Octal/hexadecimal encoding
* Runtime width/alignment specification
It is also quite big and has a heavy dependency, STLSoft, which might be too
restrictive for using it in some projects.
Boost Spirit.Karma
~~~~~~~~~~~~~~~~~~
This is not really a formatting library but I decided to include it here for
completeness. As iostreams, it suffers from the problem of mixing verbatim text
with arguments. The library is pretty fast, but slower on integer formatting
than ``fmt::format_to`` with format string compilation on Karma's own benchmark,
see `Converting a hundred million integers to strings per second
<http://www.zverovich.net/2020/06/13/fast-int-to-string-revisited.html>`_.
License
-------
{fmt} is distributed under the MIT `license
<https://github.com/fmtlib/fmt/blob/master/LICENSE.rst>`_.
Documentation License
---------------------
The `Format String Syntax <https://fmt.dev/latest/syntax.html>`_
section in the documentation is based on the one from Python `string module
documentation <https://docs.python.org/3/library/string.html#module-string>`_.
For this reason the documentation is distributed under the Python Software
Foundation license available in `doc/python-license.txt
<https://raw.github.com/fmtlib/fmt/master/doc/python-license.txt>`_.
It only applies if you distribute the documentation of {fmt}.
Maintainers
-----------
The {fmt} library is maintained by Victor Zverovich (`vitaut
<https://github.com/vitaut>`_) and Jonathan Müller (`foonathan
<https://github.com/foonathan>`_) with contributions from many other people.
See `Contributors <https://github.com/fmtlib/fmt/graphs/contributors>`_ and
`Releases <https://github.com/fmtlib/fmt/releases>`_ for some of the names.
Let us know if your contribution is not listed or mentioned incorrectly and
we'll make it right.

3236
extern/fmtlib/include/fmt/core.h vendored Normal file

File diff suppressed because it is too large Load Diff

2643
extern/fmtlib/include/fmt/format-inl.h vendored Normal file

File diff suppressed because it is too large Load Diff

3104
extern/fmtlib/include/fmt/format.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
# Copyright 2011-2022 Blender Foundation
# Standalone or with Blender
if(NOT WITH_BLENDER AND WITH_CYCLES_STANDALONE)
if(NOT WITH_BLENDER)
set(CYCLES_INSTALL_PATH ${CMAKE_INSTALL_PREFIX})
else()
set(WITH_CYCLES_BLENDER ON)
@@ -215,6 +215,15 @@ add_definitions(
-DCCL_NAMESPACE_END=}
)
include_directories(
SYSTEM
${BOOST_INCLUDE_DIR}
${OPENIMAGEIO_INCLUDE_DIRS}
${OPENEXR_INCLUDE_DIRS}
${PUGIXML_INCLUDE_DIR}
${TBB_INCLUDE_DIRS}
)
if(WITH_CYCLES_DEBUG)
add_definitions(-DWITH_CYCLES_DEBUG)
endif()
@@ -255,7 +264,6 @@ endif()
if(WITH_CYCLES_EMBREE)
add_definitions(-DWITH_EMBREE)
add_definitions(-DEMBREE_STATIC_LIB)
include_directories(
SYSTEM
${EMBREE_INCLUDE_DIRS}
@@ -280,7 +288,6 @@ endif()
if(WITH_OPENIMAGEDENOISE)
add_definitions(-DWITH_OPENIMAGEDENOISE)
add_definitions(-DOIDN_STATIC_LIB)
include_directories(
SYSTEM
${OPENIMAGEDENOISE_INCLUDE_DIRS}
@@ -308,17 +315,6 @@ if(NOT OPENIMAGEIO_PUGIXML_FOUND)
add_definitions(-DWITH_SYSTEM_PUGIXML)
endif()
include_directories(
SYSTEM
${BOOST_INCLUDE_DIR}
${OPENIMAGEIO_INCLUDE_DIRS}
${OPENIMAGEIO_INCLUDE_DIRS}/OpenImageIO
${OPENEXR_INCLUDE_DIR}
${OPENEXR_INCLUDE_DIRS}
${PUGIXML_INCLUDE_DIR}
${TBB_INCLUDE_DIRS}
)
if(CYCLES_STANDALONE_REPOSITORY)
include_directories(../third_party/atomic)
else()
@@ -335,6 +331,14 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_C_COMPILER_ID MATCHES "Clang")
unset(_has_no_error_unused_macros)
endif()
if(WITH_CYCLES_HYDRA_RENDER_DELEGATE AND (NOT WITH_USD))
message(STATUS "USD not found, disabling WITH_CYCLES_HYDRA_RENDER_DELEGATE")
set(WITH_CYCLES_HYDRA_RENDER_DELEGATE OFF)
endif()
if(WITH_CYCLES_HYDRA_RENDER_DELEGATE AND (NOT WITH_BLENDER) AND (NOT WITH_CYCLES_STANDALONE))
set(CYCLES_INSTALL_PATH ${CYCLES_INSTALL_PATH}/hdCycles/resources)
endif()
if(WITH_CYCLES_CUDA_BINARIES AND (NOT WITH_CYCLES_CUBIN_COMPILER))
if(MSVC)
set(MAX_MSVC 1800)
@@ -395,6 +399,10 @@ if(WITH_GTESTS)
add_subdirectory(test)
endif()
if(NOT WITH_BLENDER AND WITH_CYCLES_STANDALONE)
if(WITH_CYCLES_HYDRA_RENDER_DELEGATE)
add_subdirectory(hydra)
endif()
if(NOT WITH_BLENDER)
delayed_do_install(${CMAKE_BINARY_DIR}/bin)
endif()

View File

@@ -22,6 +22,16 @@ set(LIBRARIES
cycles_util
)
if(WITH_ALEMBIC)
add_definitions(-DWITH_ALEMBIC)
list(APPEND INC_SYS
${ALEMBIC_INCLUDE_DIRS}
)
list(APPEND LIB
${ALEMBIC_LIBRARIES}
)
endif()
if(WITH_CYCLES_OSL)
list(APPEND LIBRARIES cycles_kernel_osl)
endif()

View File

@@ -9,6 +9,7 @@
#include "graph/node_xml.h"
#include "scene/alembic.h"
#include "scene/background.h"
#include "scene/camera.h"
#include "scene/film.h"
@@ -192,6 +193,31 @@ static void xml_read_camera(XMLReadState &state, xml_node node)
cam->update(state.scene);
}
/* Alembic */
#ifdef WITH_ALEMBIC
static void xml_read_alembic(XMLReadState &state, xml_node graph_node)
{
AlembicProcedural *proc = state.scene->create_node<AlembicProcedural>();
xml_read_node(state, proc, graph_node);
for (xml_node node = graph_node.first_child(); node; node = node.next_sibling()) {
if (string_iequals(node.name(), "object")) {
string path;
if (xml_read_string(&path, node, "path")) {
ustring object_path(path, 0);
AlembicObject *object = static_cast<AlembicObject *>(
proc->get_or_create_object(object_path));
array<Node *> used_shaders = object->get_used_shaders();
used_shaders.push_back_slow(state.shader);
object->set_used_shaders(used_shaders);
}
}
}
}
#endif
/* Shader */
static void xml_read_shader_graph(XMLReadState &state, Shader *shader, xml_node graph_node)
@@ -647,6 +673,11 @@ static void xml_read_scene(XMLReadState &state, xml_node scene_node)
if (xml_read_string(&src, node, "src"))
xml_read_include(state, src);
}
#ifdef WITH_ALEMBIC
else if (string_iequals(node.name(), "alembic")) {
xml_read_alembic(state, node);
}
#endif
else
fprintf(stderr, "Unknown node \"%s\".\n", node.name());
}

View File

@@ -83,6 +83,17 @@ class CyclesRender(bpy.types.RenderEngine):
# viewport render
def view_update(self, context, depsgraph):
if not self.session:
# When starting a new render session in viewport (by switching
# viewport to Rendered shading) unpause the render. The way to think
# of it is: artist requests render, so we start to render.
# Do it for both original and evaluated scene so that Cycles
# immediately reacts to un-paused render.
cscene = context.scene.cycles
cscene_eval = depsgraph.scene_eval.cycles
if cscene.preview_pause or cscene_eval.preview_pause:
cscene.preview_pause = False
cscene_eval.preview_pause = False
engine.create(self, context.blend_data,
context.region, context.space_data, context.region_data)

View File

@@ -228,6 +228,10 @@ def list_render_passes(scene, srl):
else:
yield (aov.name, "RGB", 'COLOR')
# Light groups.
for lightgroup in srl.lightgroups:
yield ("Combined_%s" % lightgroup.name, "RGB", 'COLOR')
def register_passes(engine, scene, view_layer):
for name, channelids, channeltype in list_render_passes(scene, view_layer):

View File

@@ -1012,6 +1012,12 @@ class CyclesLightSettings(bpy.types.PropertyGroup):
"note that this will make the light invisible",
default=False,
)
is_caustics_light: BoolProperty(
name="Shadow Caustics",
description="Generate approximate caustics in shadows of refractive surfaces. "
"Lights, caster and receiver objects must have shadow caustics options set to enable this",
default=False,
)
@classmethod
def register(cls):
@@ -1028,6 +1034,12 @@ class CyclesLightSettings(bpy.types.PropertyGroup):
class CyclesWorldSettings(bpy.types.PropertyGroup):
is_caustics_light: BoolProperty(
name="Shadow Caustics",
description="Generate approximate caustics in shadows of refractive surfaces. "
"Lights, caster and receiver objects must have shadow caustics options set to enable this",
default=False,
)
sampling_method: EnumProperty(
name="Sampling Method",
description="How to sample the background light",
@@ -1226,6 +1238,21 @@ class CyclesObjectSettings(bpy.types.PropertyGroup):
subtype='DISTANCE',
)
is_caustics_caster: BoolProperty(
name="Cast Shadow Caustics",
description="With refractive materials, generate approximate caustics in shadows of this object. "
"Up to 10 bounces inside this object are taken into account. Lights, caster and receiver objects "
"must have shadow caustics options set to enable this",
default=False,
)
is_caustics_receiver: BoolProperty(
name="Receive Shadow Caustics",
description="Receive approximate caustics from refractive materials in shadows on this object. "
"Lights, caster and receiver objects must have shadow caustics options set to enable this",
default=False,
)
@classmethod
def register(cls):
bpy.types.Object.cycles = PointerProperty(
@@ -1480,7 +1507,7 @@ class CyclesPreferences(bpy.types.AddonPreferences):
col.label(text="and NVIDIA driver version 470 or newer", icon='BLANK1')
elif device_type == 'HIP':
import sys
col.label(text="Requires discrete AMD GPU with RDNA architecture", icon='BLANK1')
col.label(text="Requires discrete AMD GPU with Vega architecture", icon='BLANK1')
if sys.platform[:3] == "win":
col.label(text="and AMD Radeon Pro 21.Q4 driver or newer", icon='BLANK1')
elif device_type == 'METAL':

View File

@@ -12,7 +12,7 @@ from bpy.types import Panel
from bl_ui.properties_grease_pencil_common import GreasePencilSimplifyPanel
from bl_ui.properties_render import draw_hair_settings
from bl_ui.properties_view_layer import ViewLayerCryptomattePanel, ViewLayerAOVPanel
from bl_ui.properties_view_layer import ViewLayerCryptomattePanel, ViewLayerAOVPanel, ViewLayerLightgroupsPanel
class CyclesPresetPanel(PresetPanel, Panel):
COMPAT_ENGINES = {'CYCLES'}
@@ -883,6 +883,12 @@ class CYCLES_RENDER_PT_passes_aov(CyclesButtonsPanel, ViewLayerAOVPanel):
bl_parent_id = "CYCLES_RENDER_PT_passes"
class CYCLES_RENDER_PT_passes_lightgroups(CyclesButtonsPanel, ViewLayerLightgroupsPanel):
bl_label = "Light Groups"
bl_context = "view_layer"
bl_parent_id = "CYCLES_RENDER_PT_passes"
class CYCLES_PT_post_processing(CyclesButtonsPanel, Panel):
bl_label = "Post Processing"
bl_options = {'DEFAULT_CLOSED'}
@@ -1093,6 +1099,10 @@ class CYCLES_OBJECT_PT_shading_shadow_terminator(CyclesButtonsPanel, Panel):
bl_parent_id = "CYCLES_OBJECT_PT_shading"
bl_context = "object"
@classmethod
def poll(cls, context):
return context.object.type != 'LIGHT'
def draw(self, context):
layout = self.layout
layout.use_property_split = True
@@ -1110,6 +1120,10 @@ class CYCLES_OBJECT_PT_shading_gi_approximation(CyclesButtonsPanel, Panel):
bl_parent_id = "CYCLES_OBJECT_PT_shading"
bl_context = "object"
@classmethod
def poll(cls, context):
return context.object.type != 'LIGHT'
def draw(self, context):
layout = self.layout
layout.use_property_split = True
@@ -1125,6 +1139,45 @@ class CYCLES_OBJECT_PT_shading_gi_approximation(CyclesButtonsPanel, Panel):
col.prop(cob, "ao_distance")
class CYCLES_OBJECT_PT_shading_caustics(CyclesButtonsPanel, Panel):
bl_label = "Caustics"
bl_parent_id = "CYCLES_OBJECT_PT_shading"
bl_context = "object"
@classmethod
def poll(cls, context):
return CyclesButtonsPanel.poll(context) and not use_metal(context) and context.object.type != 'LIGHT'
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
col = layout.column()
ob = context.object
cob = ob.cycles
col.prop(cob, "is_caustics_caster")
col.prop(cob, "is_caustics_receiver")
class CYCLES_OBJECT_PT_lightgroup(CyclesButtonsPanel, Panel):
bl_label = "Light Group"
bl_parent_id = "CYCLES_OBJECT_PT_shading"
bl_context = "object"
def draw(self, context):
layout = self.layout
layout.use_property_split = True
ob = context.object
view_layer = context.view_layer
col = layout.column(align=True)
col.prop_search(ob, "lightgroup", view_layer, "lightgroups", text="Light Group")
class CYCLES_OBJECT_PT_visibility(CyclesButtonsPanel, Panel):
bl_label = "Visibility"
bl_context = "object"
@@ -1300,6 +1353,8 @@ class CYCLES_LIGHT_PT_light(CyclesButtonsPanel, Panel):
sub.active = not (light.type == 'AREA' and clamp.is_portal)
sub.prop(clamp, "cast_shadow")
sub.prop(clamp, "use_multiple_importance_sampling", text="Multiple Importance")
if not use_metal(context):
sub.prop(clamp, "is_caustics_light", text="Shadow Caustics")
if light.type == 'AREA':
col.prop(clamp, "is_portal", text="Portal")
@@ -1375,10 +1430,14 @@ class CYCLES_WORLD_PT_surface(CyclesButtonsPanel, Panel):
layout.use_property_split = True
world = context.world
view_layer = context.view_layer
if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'):
layout.prop(world, "color")
col = layout.column(align=True)
col.prop_search(world, "lightgroup", view_layer, "lightgroups", text="Light Group")
class CYCLES_WORLD_PT_volume(CyclesButtonsPanel, Panel):
bl_label = "Volume"
@@ -1496,6 +1555,8 @@ class CYCLES_WORLD_PT_settings_surface(CyclesButtonsPanel, Panel):
subsub.active = cworld.sampling_method == 'MANUAL'
subsub.prop(cworld, "sample_map_resolution")
sub.prop(cworld, "max_bounces")
sub.prop(cworld, "is_caustics_light", text="Shadow Caustics")
class CYCLES_WORLD_PT_settings_volume(CyclesButtonsPanel, Panel):
@@ -2183,6 +2244,7 @@ classes = (
CYCLES_RENDER_PT_passes_light,
CYCLES_RENDER_PT_passes_crypto,
CYCLES_RENDER_PT_passes_aov,
CYCLES_RENDER_PT_passes_lightgroups,
CYCLES_RENDER_PT_filter,
CYCLES_RENDER_PT_override,
CYCLES_PT_post_processing,
@@ -2193,6 +2255,8 @@ classes = (
CYCLES_OBJECT_PT_shading,
CYCLES_OBJECT_PT_shading_shadow_terminator,
CYCLES_OBJECT_PT_shading_gi_approximation,
CYCLES_OBJECT_PT_shading_caustics,
CYCLES_OBJECT_PT_lightgroup,
CYCLES_OBJECT_PT_visibility,
CYCLES_OBJECT_PT_visibility_ray_visibility,
CYCLES_OBJECT_PT_visibility_culling,

View File

@@ -114,6 +114,9 @@ void BlenderSync::sync_light(BL::Object &b_parent,
light->set_cast_shadow(get_boolean(clight, "cast_shadow"));
light->set_use_mis(get_boolean(clight, "use_multiple_importance_sampling"));
/* caustics light */
light->set_use_caustics(get_boolean(clight, "is_caustics_light"));
light->set_max_bounces(get_int(clight, "max_bounces"));
if (b_ob_info.real_object != b_ob_info.iter_object) {
@@ -140,6 +143,9 @@ void BlenderSync::sync_light(BL::Object &b_parent,
light->set_use_scatter((visibility & PATH_RAY_VOLUME_SCATTER) != 0);
light->set_is_shadow_catcher(b_ob_info.real_object.is_shadow_catcher());
/* lightgroup */
light->set_lightgroup(ustring(b_ob_info.real_object.lightgroup()));
/* tag */
light->tag_update(scene);
}
@@ -176,6 +182,9 @@ void BlenderSync::sync_background_light(BL::SpaceView3D &b_v3d, bool use_portal)
/* force enable light again when world is resynced */
light->set_is_enabled(true);
/* caustic light */
light->set_use_caustics(get_boolean(cworld, "is_caustics_light"));
light->tag_update(scene);
light_map.set_recalc(b_world);
}

View File

@@ -66,9 +66,8 @@ bool BlenderSync::object_is_geometry(BObjectInfo &b_ob_info)
}
/* Other object types that are not meshes but evaluate to meshes are presented to render engines
* as separate instance objects. Metaballs and surface objects have not been affected by that
* change yet. */
if (type == BL::Object::type_SURFACE || type == BL::Object::type_META) {
* as separate instance objects. Metaballs have not been affected by that change yet. */
if (type == BL::Object::type_META) {
return true;
}
@@ -298,6 +297,12 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
}
object->set_ao_distance(ao_distance);
bool is_caustics_caster = get_boolean(cobject, "is_caustics_caster");
object->set_is_caustics_caster(is_caustics_caster);
bool is_caustics_receiver = get_boolean(cobject, "is_caustics_receiver");
object->set_is_caustics_receiver(is_caustics_receiver);
/* sync the asset name for Cryptomatte */
BL::Object parent = b_ob.parent();
ustring parent_name;
@@ -337,6 +342,9 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
object->set_random_id(hash_uint2(hash_string(object->name.c_str()), 0));
}
/* lightgroup */
object->set_lightgroup(ustring(b_ob.lightgroup()));
object->tag_update(scene);
}
@@ -422,7 +430,7 @@ static float4 lookup_instance_property(BL::DepsgraphObjectInstance &b_instance,
return value;
}
return make_float4(0.0f);
return zero_float4();
}
bool BlenderSync::sync_object_attributes(BL::DepsgraphObjectInstance &b_instance, Object *object)
@@ -621,10 +629,8 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
bool has_subdivision_modifier = false;
BL::MeshSequenceCacheModifier b_mesh_cache(PointerRNA_NULL);
/* Experimental as Blender does not have good support for procedurals at the moment, also
* only available in preview renders since currently do not have a good cache policy, the
* data being loaded at once for all the frames. */
if (experimental && b_v3d) {
/* Experimental as Blender does not have good support for procedurals at the moment. */
if (experimental) {
b_mesh_cache = object_mesh_cache_find(b_ob, &has_subdivision_modifier);
use_procedural = b_mesh_cache && b_mesh_cache.cache_file().use_render_procedural();
}

View File

@@ -271,6 +271,7 @@ static ShaderNode *add_node(Scene *scene,
curves->set_min_x(min_x);
curves->set_max_x(max_x);
curves->set_curves(curve_mapping_curves);
curves->set_extrapolate(mapping.extend() == mapping.extend_EXTRAPOLATED);
node = curves;
}
if (b_node.is_a(&RNA_ShaderNodeVectorCurve)) {
@@ -284,6 +285,7 @@ static ShaderNode *add_node(Scene *scene,
curves->set_min_x(min_x);
curves->set_max_x(max_x);
curves->set_curves(curve_mapping_curves);
curves->set_extrapolate(mapping.extend() == mapping.extend_EXTRAPOLATED);
node = curves;
}
else if (b_node.is_a(&RNA_ShaderNodeFloatCurve)) {
@@ -297,6 +299,7 @@ static ShaderNode *add_node(Scene *scene,
curve->set_min_x(min_x);
curve->set_max_x(max_x);
curve->set_curve(curve_mapping_curve);
curve->set_extrapolate(mapping.extend() == mapping.extend_EXTRAPOLATED);
node = curve;
}
else if (b_node.is_a(&RNA_ShaderNodeValToRGB)) {
@@ -1529,6 +1532,8 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
background->set_use_shader(view_layer.use_background_shader ||
viewport_parameters.use_custom_shader());
background->set_lightgroup(ustring(b_world ? b_world.lightgroup() : ""));
background->tag_update(scene);
}

View File

@@ -745,6 +745,20 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v
}
}
/* Light Group passes. */
BL::ViewLayer::lightgroups_iterator b_lightgroup_iter;
for (b_view_layer.lightgroups.begin(b_lightgroup_iter);
b_lightgroup_iter != b_view_layer.lightgroups.end();
++b_lightgroup_iter) {
BL::Lightgroup b_lightgroup(*b_lightgroup_iter);
string name = string_printf("Combined_%s", b_lightgroup.name().c_str());
b_engine.add_pass(name.c_str(), 3, "RGB", b_view_layer.name().c_str());
Pass *pass = pass_add(scene, PASS_COMBINED, name.c_str(), PassMode::NOISY);
pass->set_lightgroup(ustring(b_lightgroup.name()));
}
scene->film->set_pass_alpha_threshold(b_view_layer.pass_alpha_threshold());
}

View File

@@ -203,7 +203,7 @@ BVHObjectBinning::BVHObjectBinning(const BVHRange &job,
bestSAH = min(sah, bestSAH);
}
int4 mask = float3_to_float4(cent_bounds_.size()) <= make_float4(0.0f);
int4 mask = float3_to_float4(cent_bounds_.size()) <= zero_float4();
bestSAH = insert<3>(select(mask, make_float4(FLT_MAX), bestSAH), FLT_MAX);
/* find best dimension */

View File

@@ -69,6 +69,7 @@ if(CYCLES_STANDALONE_REPOSITORY)
_set_default(OPENVDB_ROOT_DIR "${_cycles_lib_dir}/openvdb")
_set_default(OSL_ROOT_DIR "${_cycles_lib_dir}/osl")
_set_default(PNG_ROOT "${_cycles_lib_dir}/png")
_set_default(PUGIXML_ROOT_DIR "${_cycles_lib_dir}/pugixml")
_set_default(TBB_ROOT_DIR "${_cycles_lib_dir}/tbb")
_set_default(TIFF_ROOT "${_cycles_lib_dir}/tiff")
_set_default(ZLIB_ROOT "${_cycles_lib_dir}/zlib")
@@ -80,6 +81,23 @@ if(CYCLES_STANDALONE_REPOSITORY)
endif()
endif()
###########################################################################
# USD
###########################################################################
if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_HYDRA_RENDER_DELEGATE)
set(WITH_USD ON)
endif()
if(WITH_CYCLES_HYDRA_RENDER_DELEGATE)
find_package(pxr CONFIG REQUIRED PATHS ${PXR_ROOT} ${USD_ROOT} NO_DEFAULT_PATH)
if(pxr_FOUND)
set(PXR_LIBRARY_DIR ${PXR_CMAKE_DIR}/lib)
set(USD_INCLUDE_DIRS ${PXR_INCLUDE_DIRS})
else()
set(WITH_USD OFF)
endif()
endif()
###########################################################################
# Zlib
###########################################################################
@@ -126,31 +144,40 @@ if(CYCLES_STANDALONE_REPOSITORY)
-DOIIO_STATIC_DEFINE
)
set(OPENIMAGEIO_INCLUDE_DIR ${OPENIMAGEIO_ROOT_DIR}/include)
set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO_INCLUDE_DIR} ${OPENIMAGEIO_INCLUDE_DIR}/OpenImageIO)
# Special exceptions for libraries which needs explicit debug version
set(OPENIMAGEIO_LIBRARY
set(OPENIMAGEIO_LIBRARIES
optimized ${OPENIMAGEIO_ROOT_DIR}/lib/OpenImageIO.lib
optimized ${OPENIMAGEIO_ROOT_DIR}/lib/OpenImageIO_Util.lib
debug ${OPENIMAGEIO_ROOT_DIR}/lib/OpenImageIO_d.lib
debug ${OPENIMAGEIO_ROOT_DIR}/lib/OpenImageIO_Util_d.lib
)
endif()
find_package(OpenImageIO REQUIRED)
if(OPENIMAGEIO_PUGIXML_FOUND)
set(PUGIXML_INCLUDE_DIR "${OPENIMAGEIO_INCLUDE_DIR/OpenImageIO}")
set(PUGIXML_LIBRARIES "")
set(PUGIXML_INCLUDE_DIR ${PUGIXML_ROOT_DIR}/include)
set(PUGIXML_LIBRARIES
optimized ${PUGIXML_ROOT_DIR}/lib/pugixml.lib
debug ${PUGIXML_ROOT_DIR}/lib/pugixml_d.lib
)
else()
find_package(PugiXML REQUIRED)
find_package(OpenImageIO REQUIRED)
if(OPENIMAGEIO_PUGIXML_FOUND)
set(PUGIXML_INCLUDE_DIR "${OPENIMAGEIO_INCLUDE_DIR}/OpenImageIO")
set(PUGIXML_LIBRARIES "")
else()
find_package(PugiXML REQUIRED)
endif()
endif()
# Dependencies
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(OPENJPEG_INCLUDE_DIR ${OPENJPEG}/include/openjpeg-2.3)
set(OPENJPEG_LIBRARY ${_cycles_lib_dir}/openjpeg/lib/openjp2${CMAKE_STATIC_LIBRARY_SUFFIX})
set(OPENJPEG_LIBRARIES ${_cycles_lib_dir}/openjpeg/lib/openjp2${CMAKE_STATIC_LIBRARY_SUFFIX})
else()
find_package(OpenJPEG REQUIRED)
endif()
find_package(JPEG REQUIRED)
find_package(OpenJPEG REQUIRED)
find_package(TIFF REQUIRED)
find_package(PNG REQUIRED)
endif()
@@ -161,76 +188,70 @@ endif()
if(CYCLES_STANDALONE_REPOSITORY)
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(OPENEXR_IEX_LIBRARY
set(OPENEXR_INCLUDE_DIR ${OPENEXR_ROOT_DIR}/include)
set(OPENEXR_INCLUDE_DIRS ${OPENEXR_INCLUDE_DIR} ${OPENEXR_ROOT_DIR}/include/OpenEXR)
set(OPENEXR_LIBRARIES
optimized ${OPENEXR_ROOT_DIR}/lib/Iex_s.lib
debug ${OPENEXR_ROOT_DIR}/lib/Iex_s_d.lib
)
set(OPENEXR_HALF_LIBRARY
optimized ${OPENEXR_ROOT_DIR}/lib/Half_s.lib
debug ${OPENEXR_ROOT_DIR}/lib/Half_s_d.lib
)
set(OPENEXR_ILMIMF_LIBRARY
optimized ${OPENEXR_ROOT_DIR}/lib/IlmImf_s.lib
debug ${OPENEXR_ROOT_DIR}/lib/IlmImf_s_d.lib
)
set(OPENEXR_IMATH_LIBRARY
optimized ${OPENEXR_ROOT_DIR}/lib/Imath_s.lib
debug ${OPENEXR_ROOT_DIR}/lib/Imath_s_d.lib
)
set(OPENEXR_ILMTHREAD_LIBRARY
optimized ${OPENEXR_ROOT_DIR}/lib/IlmThread_s.lib
debug ${OPENEXR_ROOT_DIR}/lib/Iex_s_d.lib
debug ${OPENEXR_ROOT_DIR}/lib/Half_s_d.lib
debug ${OPENEXR_ROOT_DIR}/lib/IlmImf_s_d.lib
debug ${OPENEXR_ROOT_DIR}/lib/Imath_s_d.lib
debug ${OPENEXR_ROOT_DIR}/lib/IlmThread_s_d.lib
)
else()
find_package(OpenEXR REQUIRED)
endif()
find_package(OpenEXR REQUIRED)
endif()
###########################################################################
# OpenShadingLanguage & LLVM
###########################################################################
if(WITH_CYCLES_OSL)
if(CYCLES_STANDALONE_REPOSITORY)
if(EXISTS ${_cycles_lib_dir})
set(LLVM_STATIC ON)
endif()
if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_OSL)
if(EXISTS ${_cycles_lib_dir})
set(LLVM_STATIC ON)
endif()
if(MSVC AND EXISTS ${_cycles_lib_dir})
# TODO(sergey): On Windows llvm-config doesn't give proper results for the
# library names, use hardcoded libraries for now.
file(GLOB _llvm_libs_release ${LLVM_ROOT_DIR}/lib/*.lib)
file(GLOB _llvm_libs_debug ${LLVM_ROOT_DIR}/debug/lib/*.lib)
set(_llvm_libs)
foreach(_llvm_lib_path ${_llvm_libs_release})
get_filename_component(_llvm_lib_name ${_llvm_lib_path} ABSOLUTE)
list(APPEND _llvm_libs optimized ${_llvm_lib_name})
endforeach()
foreach(_llvm_lib_path ${_llvm_libs_debug})
get_filename_component(_llvm_lib_name ${_llvm_lib_path} ABSOLUTE)
list(APPEND _llvm_libs debug ${_llvm_lib_name})
endforeach()
set(LLVM_LIBRARY ${_llvm_libs})
unset(_llvm_lib_name)
unset(_llvm_lib_path)
unset(_llvm_libs)
unset(_llvm_libs_debug)
unset(_llvm_libs_release)
set(OSL_INCLUDE_DIR ${OSL_ROOT_DIR}/include)
set(OSL_LIBRARIES
optimized ${OSL_ROOT_DIR}/lib/oslcomp.lib
optimized ${OSL_ROOT_DIR}/lib/oslexec.lib
optimized ${OSL_ROOT_DIR}/lib/oslquery.lib
debug ${OSL_ROOT_DIR}/lib/oslcomp_d.lib
debug ${OSL_ROOT_DIR}/lib/oslexec_d.lib
debug ${OSL_ROOT_DIR}/lib/oslquery_d.lib
${PUGIXML_LIBRARIES}
)
find_program(OSL_COMPILER NAMES oslc PATHS ${OSL_ROOT_DIR}/bin)
else()
find_package(OSL REQUIRED)
find_package(LLVM REQUIRED)
if(MSVC AND EXISTS ${_cycles_lib_dir})
# TODO(sergey): On Windows llvm-config doesn't give proper results for the
# library names, use hardcoded libraries for now.
file(GLOB _llvm_libs_release ${LLVM_ROOT_DIR}/lib/*.lib)
file(GLOB _llvm_libs_debug ${LLVM_ROOT_DIR}/debug/lib/*.lib)
set(_llvm_libs)
foreach(_llvm_lib_path ${_llvm_libs_release})
get_filename_component(_llvm_lib_name ${_llvm_lib_path} ABSOLUTE)
list(APPEND _llvm_libs optimized ${_llvm_lib_name})
endforeach()
foreach(_llvm_lib_path ${_llvm_libs_debug})
get_filename_component(_llvm_lib_name ${_llvm_lib_path} ABSOLUTE)
list(APPEND _llvm_libs debug ${_llvm_lib_name})
endforeach()
set(LLVM_LIBRARY ${_llvm_libs})
unset(_llvm_lib_name)
unset(_llvm_lib_path)
unset(_llvm_libs)
unset(_llvm_libs_debug)
unset(_llvm_libs_release)
set(OSL_LIBRARIES
optimized ${OSL_ROOT_DIR}/lib/oslcomp.lib
optimized ${OSL_ROOT_DIR}/lib/oslexec.lib
optimized ${OSL_ROOT_DIR}/lib/oslquery.lib
optimized ${OSL_ROOT_DIR}/lib/pugixml.lib
debug ${OSL_ROOT_DIR}/lib/oslcomp_d.lib
debug ${OSL_ROOT_DIR}/lib/oslexec_d.lib
debug ${OSL_ROOT_DIR}/lib/oslquery_d.lib
debug ${OSL_ROOT_DIR}/lib/pugixml_d.lib
)
endif()
endif()
endif()
@@ -238,22 +259,23 @@ endif()
# OpenColorIO
###########################################################################
if(WITH_CYCLES_OPENCOLORIO)
if(CYCLES_STANDALONE_REPOSITORY)
find_package(OpenColorIO REQUIRED)
set(WITH_OPENCOLORIO ON)
if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_OPENCOLORIO)
set(WITH_OPENCOLORIO ON)
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(OPENCOLORIO_LIBPATH ${_cycles_lib_dir}/opencolorio/lib)
set(OPENCOLORIO_LIBRARIES
optimized ${OPENCOLORIO_LIBPATH}/OpenColorIO.lib
optimized ${OPENCOLORIO_LIBPATH}/tinyxml.lib
optimized ${OPENCOLORIO_LIBPATH}/libyaml-cpp.lib
debug ${OPENCOLORIO_LIBPATH}/OpencolorIO_d.lib
debug ${OPENCOLORIO_LIBPATH}/tinyxml_d.lib
debug ${OPENCOLORIO_LIBPATH}/libyaml-cpp_d.lib
)
endif()
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO_ROOT_DIR}/include)
set(OPENCOLORIO_LIBRARIES
optimized ${OPENCOLORIO_ROOT_DIR}/lib/OpenColorIO.lib
optimized ${OPENCOLORIO_ROOT_DIR}/lib/libyaml-cpp.lib
optimized ${OPENCOLORIO_ROOT_DIR}/lib/libexpatMD.lib
optimized ${OPENCOLORIO_ROOT_DIR}/lib/pystring.lib
debug ${OPENCOLORIO_ROOT_DIR}/lib/OpencolorIO_d.lib
debug ${OPENCOLORIO_ROOT_DIR}/lib/libyaml-cpp_d.lib
debug ${OPENCOLORIO_ROOT_DIR}/lib/libexpatdMD.lib
debug ${OPENCOLORIO_ROOT_DIR}/lib/pystring_d.lib
)
else()
find_package(OpenColorIO REQUIRED)
endif()
endif()
@@ -274,22 +296,59 @@ if(CYCLES_STANDALONE_REPOSITORY)
endif()
endif()
set(__boost_packages filesystem regex system thread date_time)
if(WITH_CYCLES_OSL)
list(APPEND __boost_packages wave)
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(BOOST_INCLUDE_DIR ${BOOST_ROOT}/include)
set(BOOST_VERSION_HEADER ${BOOST_INCLUDE_DIR}/boost/version.hpp)
if(EXISTS ${BOOST_VERSION_HEADER})
file(STRINGS "${BOOST_VERSION_HEADER}" BOOST_LIB_VERSION REGEX "#define BOOST_LIB_VERSION ")
if(BOOST_LIB_VERSION MATCHES "#define BOOST_LIB_VERSION \"([0-9_]+)\"")
set(BOOST_VERSION "${CMAKE_MATCH_1}")
endif()
endif()
if(NOT BOOST_VERSION)
message(FATAL_ERROR "Unable to determine Boost version")
endif()
set(BOOST_POSTFIX "vc141-mt-x64-${BOOST_VERSION}.lib")
set(BOOST_DEBUG_POSTFIX "vc141-mt-gd-x64-${BOOST_VERSION}.lib")
set(BOOST_LIBRARIES
optimized ${BOOST_ROOT}/lib/libboost_date_time-${BOOST_POSTFIX}
optimized ${BOOST_ROOT}/lib/libboost_filesystem-${BOOST_POSTFIX}
optimized ${BOOST_ROOT}/lib/libboost_regex-${BOOST_POSTFIX}
optimized ${BOOST_ROOT}/lib/libboost_system-${BOOST_POSTFIX}
optimized ${BOOST_ROOT}/lib/libboost_thread-${BOOST_POSTFIX}
optimized ${BOOST_ROOT}/lib/libboost_chrono-${BOOST_POSTFIX}
debug ${BOOST_ROOT}/lib/libboost_date_time-${BOOST_DEBUG_POSTFIX}
debug ${BOOST_ROOT}/lib/libboost_filesystem-${BOOST_DEBUG_POSTFIX}
debug ${BOOST_ROOT}/lib/libboost_regex-${BOOST_DEBUG_POSTFIX}
debug ${BOOST_ROOT}/lib/libboost_system-${BOOST_DEBUG_POSTFIX}
debug ${BOOST_ROOT}/lib/libboost_thread-${BOOST_DEBUG_POSTFIX}
debug ${BOOST_ROOT}/lib/libboost_chrono-${BOOST_DEBUG_POSTFIX}
)
if(WITH_CYCLES_OSL)
set(BOOST_LIBRARIES ${BOOST_LIBRARIES}
optimized ${BOOST_ROOT}/lib/libboost_wave-${BOOST_POSTFIX}
debug ${BOOST_ROOT}/lib/libboost_wave-${BOOST_DEBUG_POSTFIX})
endif()
else()
set(__boost_packages filesystem regex system thread date_time)
if(WITH_CYCLES_OSL)
list(APPEND __boost_packages wave)
endif()
find_package(Boost 1.48 COMPONENTS ${__boost_packages} REQUIRED)
if(NOT Boost_FOUND)
# Try to find non-multithreaded if -mt not found, this flag
# doesn't matter for us, it has nothing to do with thread
# safety, but keep it to not disturb build setups.
set(Boost_USE_MULTITHREADED OFF)
find_package(Boost 1.48 COMPONENTS ${__boost_packages})
endif()
unset(__boost_packages)
set(BOOST_INCLUDE_DIR ${Boost_INCLUDE_DIRS})
set(BOOST_LIBRARIES ${Boost_LIBRARIES})
set(BOOST_LIBPATH ${Boost_LIBRARY_DIRS})
endif()
find_package(Boost 1.48 COMPONENTS ${__boost_packages} REQUIRED)
if(NOT Boost_FOUND)
# Try to find non-multithreaded if -mt not found, this flag
# doesn't matter for us, it has nothing to do with thread
# safety, but keep it to not disturb build setups.
set(Boost_USE_MULTITHREADED OFF)
find_package(Boost 1.48 COMPONENTS ${__boost_packages})
endif()
unset(__boost_packages)
set(BOOST_INCLUDE_DIR ${Boost_INCLUDE_DIRS})
set(BOOST_LIBRARIES ${Boost_LIBRARIES})
set(BOOST_LIBPATH ${Boost_LIBRARY_DIRS})
set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB")
endif()
@@ -297,47 +356,30 @@ endif()
# Embree
###########################################################################
if(WITH_CYCLES_EMBREE)
if(CYCLES_STANDALONE_REPOSITORY)
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(EMBREE_TASKING_LIBRARY
optimized ${EMBREE_ROOT_DIR}/lib/tasking.lib
debug ${EMBREE_ROOT_DIR}/lib/tasking_d.lib
)
set(EMBREE_EMBREE3_LIBRARY
optimized ${EMBREE_ROOT_DIR}/lib/embree3.lib
debug ${EMBREE_ROOT_DIR}/lib/embree3_d.lib
)
set(EMBREE_EMBREE_AVX_LIBRARY
optimized ${EMBREE_ROOT_DIR}/lib/embree_avx.lib
debug ${EMBREE_ROOT_DIR}/lib/embree_avx_d.lib
)
set(EMBREE_EMBREE_AVX2_LIBRARY
optimized ${EMBREE_ROOT_DIR}/lib/embree_avx2.lib
debug ${EMBREE_ROOT_DIR}/lib/embree_avx2_d.lib
)
set(EMBREE_EMBREE_SSE42_LIBRARY
optimized ${EMBREE_ROOT_DIR}/lib/embree_sse42.lib
debug ${EMBREE_ROOT_DIR}/lib/embree_sse42_d.lib
)
set(EMBREE_LEXERS_LIBRARY
optimized ${EMBREE_ROOT_DIR}/lib/lexers.lib
debug ${EMBREE_ROOT_DIR}/lib/lexers_d.lib
)
set(EMBREE_MATH_LIBRARY
optimized ${EMBREE_ROOT_DIR}/lib/math.lib
debug ${EMBREE_ROOT_DIR}/lib/math_d.lib
)
set(EMBREE_SIMD_LIBRARY
optimized ${EMBREE_ROOT_DIR}/lib/simd.lib
debug ${EMBREE_ROOT_DIR}/lib/simd_d.lib
)
set(EMBREE_SYS_LIBRARY
optimized ${EMBREE_ROOT_DIR}/lib/sys.lib
debug ${EMBREE_ROOT_DIR}/lib/sys_d.lib
)
endif()
if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_EMBREE)
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(EMBREE_INCLUDE_DIRS ${EMBREE_ROOT_DIR}/include)
set(EMBREE_LIBRARIES
optimized ${EMBREE_ROOT_DIR}/lib/embree3.lib
optimized ${EMBREE_ROOT_DIR}/lib/embree_avx2.lib
optimized ${EMBREE_ROOT_DIR}/lib/embree_avx.lib
optimized ${EMBREE_ROOT_DIR}/lib/embree_sse42.lib
optimized ${EMBREE_ROOT_DIR}/lib/lexers.lib
optimized ${EMBREE_ROOT_DIR}/lib/math.lib
optimized ${EMBREE_ROOT_DIR}/lib/simd.lib
optimized ${EMBREE_ROOT_DIR}/lib/tasking.lib
optimized ${EMBREE_ROOT_DIR}/lib/sys.lib
debug ${EMBREE_ROOT_DIR}/lib/embree3_d.lib
debug ${EMBREE_ROOT_DIR}/lib/embree_avx2_d.lib
debug ${EMBREE_ROOT_DIR}/lib/embree_avx_d.lib
debug ${EMBREE_ROOT_DIR}/lib/embree_sse42_d.lib
debug ${EMBREE_ROOT_DIR}/lib/lexers_d.lib
debug ${EMBREE_ROOT_DIR}/lib/math_d.lib
debug ${EMBREE_ROOT_DIR}/lib/simd_d.lib
debug ${EMBREE_ROOT_DIR}/lib/sys_d.lib
debug ${EMBREE_ROOT_DIR}/lib/tasking_d.lib
)
else()
find_package(Embree 3.8.0 REQUIRED)
endif()
endif()
@@ -346,29 +388,45 @@ endif()
# Logging
###########################################################################
if(WITH_CYCLES_LOGGING)
if(CYCLES_STANDALONE_REPOSITORY)
find_package(Glog REQUIRED)
find_package(Gflags REQUIRED)
endif()
if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_LOGGING)
find_package(Glog REQUIRED)
find_package(Gflags REQUIRED)
endif()
###########################################################################
# OpenSubdiv
###########################################################################
if(WITH_CYCLES_OPENSUBDIV)
if(CYCLES_STANDALONE_REPOSITORY)
find_package(OpenSubdiv REQUIRED)
set(WITH_OPENSUBDIV ON)
if(WITH_CYCLES_HYDRA_RENDER_DELEGATE AND PXR_LIBRARY_DIR AND (WITH_OPENSUBDIV OR WITH_CYCLES_OPENSUBDIV))
find_library(OPENSUBDIV_LIBRARY_CPU_DEBUG_PXR NAMES osdCPU_d osdCPU PATHS ${PXR_LIBRARY_DIR} NO_CACHE NO_DEFAULT_PATH)
find_library(OPENSUBDIV_LIBRARY_GPU_DEBUG_PXR NAMES osdGPU_d osdGPU PATHS ${PXR_LIBRARY_DIR} NO_CACHE NO_DEFAULT_PATH)
find_library(OPENSUBDIV_LIBRARY_CPU_RELEASE_PXR NAMES osdCPU PATHS ${PXR_LIBRARY_DIR} NO_CACHE NO_DEFAULT_PATH)
find_library(OPENSUBDIV_LIBRARY_GPU_RELEASE_PXR NAMES osdGPU PATHS ${PXR_LIBRARY_DIR} NO_CACHE NO_DEFAULT_PATH)
if(OPENSUBDIV_LIBRARY_CPU_RELEASE_PXR AND OPENSUBDIV_LIBRARY_GPU_RELEASE_PXR)
set(OPENSUBDIV_INCLUDE_DIRS ${PXR_INCLUDE_DIRS})
set(OPENSUBDIV_LIBRARIES
optimized ${OPENSUBDIV_LIBRARY_CPU_RELEASE_PXR}
optimized ${OPENSUBDIV_LIBRARY_GPU_RELEASE_PXR}
debug ${OPENSUBDIV_LIBRARY_CPU_DEBUG_PXR}
debug ${OPENSUBDIV_LIBRARY_GPU_DEBUG_PXR}
)
endif()
endif()
if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_OPENSUBDIV)
set(WITH_OPENSUBDIV ON)
if(NOT OPENSUBDIV_LIBRARY_CPU_RELEASE_PXR OR NOT OPENSUBDIV_LIBRARY_GPU_RELEASE_PXR)
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(OPENSUBDIV_INCLUDE_DIRS ${OPENSUBDIV_ROOT_DIR}/include)
set(OPENSUBDIV_LIBRARIES
optimized ${OPENSUBDIV_ROOT_DIR}/lib/osdCPU.lib
optimized ${OPENSUBDIV_ROOT_DIR}/lib/osdGPU.lib
debug ${OPENSUBDIV_ROOT_DIR}/lib/osdCPU_d.lib
debug ${OPENSUBDIV_ROOT_DIR}/lib/osdGPU_d.lib
)
else()
find_package(OpenSubdiv REQUIRED)
endif()
endif()
endif()
@@ -377,18 +435,29 @@ endif()
# OpenVDB
###########################################################################
if(WITH_CYCLES_OPENVDB)
if(CYCLES_STANDALONE_REPOSITORY)
if(WITH_CYCLES_HYDRA_RENDER_DELEGATE AND PXR_LIBRARY_DIR AND (WITH_OPENVDB OR WITH_CYCLES_OPENVDB))
find_library(OPENVDB_LIBRARY_PXR NAMES openvdb PATHS ${PXR_LIBRARY_DIR} NO_CACHE NO_DEFAULT_PATH)
if(OPENVDB_LIBRARY_PXR)
set(OPENVDB_INCLUDE_DIRS ${PXR_INCLUDE_DIRS})
set(OPENVDB_LIBRARIES ${OPENVDB_LIBRARY_PXR})
endif()
endif()
if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_OPENVDB)
set(WITH_OPENVDB ON)
set(OPENVDB_DEFINITIONS -DNOMINMAX -D_USE_MATH_DEFINES)
if(NOT OPENVDB_LIBRARY_PXR)
find_package(OpenVDB REQUIRED)
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(BLOSC_LIBRARY
optimized ${BLOSC_ROOT_DIR}/lib/libblosc.lib
debug ${BLOSC_ROOT_DIR}/lib/libblosc_d.lib)
optimized ${BLOSC_ROOT_DIR}/lib/libblosc.lib
debug ${BLOSC_ROOT_DIR}/lib/libblosc_d.lib
)
else()
find_package(Blosc REQUIRED)
endif()
find_package(OpenVDB REQUIRED)
find_package(Blosc REQUIRED)
set(WITH_OPENVDB ON)
set(OPENVDB_DEFINITIONS -DNOMINMAX -D_USE_MATH_DEFINES)
endif()
endif()
@@ -396,21 +465,21 @@ endif()
# OpenImageDenoise
###########################################################################
if(WITH_CYCLES_OPENIMAGEDENOISE)
if(CYCLES_STANDALONE_REPOSITORY)
if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_OPENIMAGEDENOISE)
set(WITH_OPENIMAGEDENOISE ON)
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(OPENIMAGEDENOISE_INCLUDE_DIRS ${OPENIMAGEDENOISE_ROOT_DIR}/include)
set(OPENIMAGEDENOISE_LIBRARIES
optimized ${OPENIMAGEDENOISE_ROOT_DIR}/lib/OpenImageDenoise.lib
optimized ${OPENIMAGEDENOISE_ROOT_DIR}/lib/common.lib
optimized ${OPENIMAGEDENOISE_ROOT_DIR}/lib/dnnl.lib
debug ${OPENIMAGEDENOISE_ROOT_DIR}/lib/OpenImageDenoise_d.lib
debug ${OPENIMAGEDENOISE_ROOT_DIR}/lib/common_d.lib
debug ${OPENIMAGEDENOISE_ROOT_DIR}/lib/dnnl_d.lib
)
else()
find_package(OpenImageDenoise REQUIRED)
set(WITH_OPENIMAGEDENOISE ON)
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(OPENIMAGEDENOISE_LIBRARIES
optimized ${OPENIMAGEDENOISE_ROOT_DIR}/lib/OpenImageDenoise.lib
optimized ${OPENIMAGEDENOISE_ROOT_DIR}/lib/common.lib
optimized ${OPENIMAGEDENOISE_ROOT_DIR}/lib/dnnl.lib
debug ${OPENIMAGEDENOISE_ROOT_DIR}/lib/OpenImageDenoise_d.lib
debug ${OPENIMAGEDENOISE_ROOT_DIR}/lib/common_d.lib
debug ${OPENIMAGEDENOISE_ROOT_DIR}/lib/dnnl_d.lib)
endif()
endif()
endif()
@@ -418,15 +487,30 @@ endif()
# TBB
###########################################################################
if(CYCLES_STANDALONE_REPOSITORY)
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(TBB_LIBRARY
optimized ${TBB_ROOT_DIR}/lib/tbb.lib
debug ${TBB_ROOT_DIR}/lib/debug/tbb_debug.lib
if(WITH_CYCLES_HYDRA_RENDER_DELEGATE AND PXR_LIBRARY_DIR)
find_library(TBB_LIBRARY_DEBUG_PXR NAMES tbb_debug tbb PATHS ${PXR_LIBRARY_DIR} NO_CACHE NO_DEFAULT_PATH)
find_library(TBB_LIBRARY_RELEASE_PXR NAMES tbb PATHS ${PXR_LIBRARY_DIR} NO_CACHE NO_DEFAULT_PATH)
if(TBB_LIBRARY_RELEASE_PXR)
set(TBB_INCLUDE_DIRS ${PXR_INCLUDE_DIRS})
set(TBB_LIBRARIES
optimized ${TBB_LIBRARY_RELEASE_PXR}
debug ${TBB_LIBRARY_DEBUG_PXR}
)
endif()
endif()
find_package(TBB REQUIRED)
if(CYCLES_STANDALONE_REPOSITORY)
if(NOT TBB_LIBRARY_RELEASE_PXR)
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(TBB_INCLUDE_DIRS ${TBB_ROOT_DIR}/include)
set(TBB_LIBRARIES
optimized ${TBB_ROOT_DIR}/lib/tbb.lib
debug ${TBB_ROOT_DIR}/lib/tbb_debug.lib
)
else()
find_package(TBB REQUIRED)
endif()
endif()
endif()
###########################################################################
@@ -438,9 +522,9 @@ if(CYCLES_STANDALONE_REPOSITORY)
set(GLEW_LIBRARY "${_cycles_lib_dir}/opengl/lib/glew.lib")
set(GLEW_INCLUDE_DIR "${_cycles_lib_dir}/opengl/include")
add_definitions(-DGLEW_STATIC)
else()
find_package(GLEW REQUIRED)
endif()
find_package(GLEW REQUIRED)
else()
# Workaround for unconventional variable name use in Blender.
set(GLEW_INCLUDE_DIR "${GLEW_INCLUDE_PATH}")
@@ -466,11 +550,11 @@ if(CYCLES_STANDALONE_REPOSITORY)
find_package(OpenGL REQUIRED)
set(CYCLES_GL_LIBRARIES
${OPENGL_gl_LIBRARY}
${OPENGL_glu_LIBRARY}
${GLEW_LIBRARY}
)
set(CYCLES_GL_LIBRARIES
${OPENGL_gl_LIBRARY}
${OPENGL_glu_LIBRARY}
${GLEW_LIBRARY}
)
else()
set(CYCLES_GL_LIBRARIES
bf_intern_glew_mx

View File

@@ -101,6 +101,7 @@ macro(cycles_target_link_libraries target)
${PNG_LIBRARIES}
${JPEG_LIBRARIES}
${TIFF_LIBRARY}
${WEBP_LIBRARIES}
${OPENJPEG_LIBRARIES}
${OPENEXR_LIBRARIES}
${OPENEXR_LIBRARIES} # For circular dependencies between libs.
@@ -143,13 +144,13 @@ macro(cycles_install_libraries target)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
install(
FILES
${TBB_ROOT_DIR}/lib/debug/tbb_debug${CMAKE_SHARED_LIBRARY_SUFFIX}
${TBB_ROOT_DIR}/bin/tbb_debug${CMAKE_SHARED_LIBRARY_SUFFIX}
${OPENVDB_ROOT_DIR}/bin/openvdb_d${CMAKE_SHARED_LIBRARY_SUFFIX}
DESTINATION $<TARGET_FILE_DIR:${target}>)
else()
install(
FILES
${TBB_ROOT_DIR}/lib/tbb${CMAKE_SHARED_LIBRARY_SUFFIX}
${TBB_ROOT_DIR}/bin/tbb${CMAKE_SHARED_LIBRARY_SUFFIX}
${OPENVDB_ROOT_DIR}/bin/openvdb${CMAKE_SHARED_LIBRARY_SUFFIX}
DESTINATION $<TARGET_FILE_DIR:${target}>)
endif()

View File

@@ -197,7 +197,8 @@ cycles_add_library(cycles_device "${LIB}" ${SRC})
source_group("cpu" FILES ${SRC_CPU})
source_group("cuda" FILES ${SRC_CUDA})
source_group("dummy" FILES ${SRC_DUMMY})
source_group("hip" FILES ${SRC_HIP})
source_group("multi" FILES ${SRC_MULTI})
source_group("metal" FILES ${SRC_METAL})
source_group("optix" FILES ${SRC_OPTIX})
source_group("common" FILES ${SRC} ${SRC_HEADERS})
source_group("common" FILES ${SRC_BASE} ${SRC_HEADERS})

View File

@@ -51,7 +51,7 @@ static inline bool hipSupportsDevice(const int hipDevId)
hipDeviceGetAttribute(&major, hipDeviceAttributeComputeCapabilityMajor, hipDevId);
hipDeviceGetAttribute(&minor, hipDeviceAttributeComputeCapabilityMinor, hipDevId);
return (major > 10) || (major == 10 && minor >= 1);
return (major >= 9);
}
CCL_NAMESPACE_END

View File

@@ -0,0 +1,149 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2022 Blender Foundation
#####################################################################
# Cycles Hydra render delegate
#####################################################################
set(INC
..
)
set(INC_SYS
${USD_INCLUDE_DIRS}
${GLEW_INCLUDE_DIR}
)
set(INC_HD_CYCLES
attribute.h
camera.h
config.h
curves.h
display_driver.h
field.h
geometry.h
geometry.inl
instancer.h
light.h
material.h
mesh.h
node_util.h
output_driver.h
pointcloud.h
render_buffer.h
render_delegate.h
render_pass.h
session.h
volume.h
)
set(SRC_HD_CYCLES
attribute.cpp
curves.cpp
camera.cpp
display_driver.cpp
field.cpp
instancer.cpp
light.cpp
material.cpp
mesh.cpp
node_util.cpp
output_driver.cpp
pointcloud.cpp
render_buffer.cpp
render_delegate.cpp
render_pass.cpp
session.cpp
volume.cpp
)
add_definitions(${GL_DEFINITIONS})
if(WITH_OPENVDB)
add_definitions(-DWITH_OPENVDB ${OPENVDB_DEFINITIONS})
list(APPEND INC_SYS
${OPENVDB_INCLUDE_DIRS}
)
list(APPEND LIB
${OPENVDB_LIBRARIES}
)
endif()
include_directories(${INC})
include_directories(SYSTEM ${INC_SYS})
add_library(hdCyclesStatic STATIC
${SRC_HD_CYCLES}
${INC_HD_CYCLES}
)
target_compile_options(hdCyclesStatic
PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:/wd4003 /wd4244 /wd4506>
$<$<CXX_COMPILER_ID:GNU>:-Wno-float-conversion -Wno-double-promotion -Wno-deprecated>
)
target_compile_definitions(hdCyclesStatic
PRIVATE
GLOG_NO_ABBREVIATED_SEVERITIES=1
OSL_DEBUG=$<CONFIG:DEBUG>
TBB_USE_DEBUG=$<CONFIG:DEBUG>
$<$<CXX_COMPILER_ID:MSVC>:NOMINMAX=1>
)
target_link_libraries(hdCyclesStatic
PUBLIC
hd
hgi
PRIVATE
cycles_scene
cycles_session
cycles_graph
)
set(HdCyclesPluginName hdCycles)
add_library(${HdCyclesPluginName} SHARED
plugin.h
plugin.cpp
)
set_target_properties(${HdCyclesPluginName}
PROPERTIES PREFIX ""
)
target_compile_definitions(${HdCyclesPluginName}
PRIVATE
MFB_PACKAGE_NAME=${HdCyclesPluginName}
MFB_ALT_PACKAGE_NAME=${HdCyclesPluginName}
GLOG_NO_ABBREVIATED_SEVERITIES=1
OSL_DEBUG=$<CONFIG:DEBUG>
TBB_USE_DEBUG=$<CONFIG:DEBUG>
$<$<CXX_COMPILER_ID:MSVC>:NOMINMAX=1>
)
target_link_libraries(${HdCyclesPluginName}
hdCyclesStatic
)
cycles_target_link_libraries(${HdCyclesPluginName})
if(WITH_CYCLES_BLENDER)
set(CYCLES_HYDRA_INSTALL_PATH "../")
else()
set(CYCLES_HYDRA_INSTALL_PATH ${CMAKE_INSTALL_PREFIX})
# Put the root plugInfo.json one level up
delayed_install("${CMAKE_CURRENT_SOURCE_DIR}" "plugInfo.json" ${CMAKE_INSTALL_PREFIX})
endif()
delayed_install("" $<TARGET_FILE:${HdCyclesPluginName}> ${CYCLES_HYDRA_INSTALL_PATH})
set(PLUG_INFO_ROOT "..")
file(RELATIVE_PATH PLUG_INFO_LIBRARY_PATH "${CYCLES_HYDRA_INSTALL_PATH}/${HdCyclesPluginName}" "${CYCLES_HYDRA_INSTALL_PATH}/${HdCyclesPluginName}${CMAKE_SHARED_LIBRARY_SUFFIX}")
file(RELATIVE_PATH PLUG_INFO_RESOURCE_PATH "${CYCLES_HYDRA_INSTALL_PATH}/${HdCyclesPluginName}" "${CYCLES_INSTALL_PATH}")
configure_file(resources/plugInfo.json
${CMAKE_CURRENT_BINARY_DIR}/resources/plugInfo.json
@ONLY
)
delayed_install("${CMAKE_CURRENT_BINARY_DIR}/resources" "plugInfo.json" "${CYCLES_HYDRA_INSTALL_PATH}/${HdCyclesPluginName}/resources")

View File

@@ -0,0 +1,71 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#include "hydra/attribute.h"
#include "scene/attribute.h"
#include "scene/geometry.h"
#include "scene/scene.h"
#include <pxr/base/gf/vec2f.h>
#include <pxr/base/gf/vec3f.h>
#include <pxr/base/gf/vec4f.h>
#include <pxr/base/vt/array.h>
#include <pxr/imaging/hd/tokens.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
void ApplyPrimvars(AttributeSet &attributes,
const ustring &name,
VtValue value,
AttributeElement elem,
AttributeStandard std)
{
const void *data = HdGetValueData(value);
size_t size = value.GetArraySize();
const HdType valueType = HdGetValueTupleType(value).type;
TypeDesc attrType = CCL_NS::TypeUnknown;
switch (valueType) {
case HdTypeFloat:
attrType = CCL_NS::TypeFloat;
size *= sizeof(float);
break;
case HdTypeFloatVec2:
attrType = CCL_NS::TypeFloat2;
size *= sizeof(float2);
static_assert(sizeof(GfVec2f) == sizeof(float2));
break;
case HdTypeFloatVec3: {
attrType = CCL_NS::TypeVector;
size *= sizeof(float3);
// The Cycles "float3" data type is padded to "float4", so need to convert the array
const auto &valueData = value.Get<VtVec3fArray>();
VtArray<float3> valueConverted;
valueConverted.reserve(valueData.size());
for (const GfVec3f &vec : valueData) {
valueConverted.push_back(make_float3(vec[0], vec[1], vec[2]));
}
data = valueConverted.data();
value = std::move(valueConverted);
break;
}
case HdTypeFloatVec4:
attrType = CCL_NS::TypeFloat4;
size *= sizeof(float4);
static_assert(sizeof(GfVec4f) == sizeof(float4));
break;
default:
TF_WARN("Unsupported attribute type %d", static_cast<int>(valueType));
return;
}
Attribute *const attr = attributes.add(name, attrType, elem);
attr->std = std;
assert(size == attr->buffer.size());
std::memcpy(attr->data(), data, size);
}
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,21 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#pragma once
#include "hydra/config.h"
#include "scene/attribute.h"
#include <pxr/base/vt/value.h>
#include <pxr/imaging/hd/types.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
void ApplyPrimvars(CCL_NS::AttributeSet &attributes,
const CCL_NS::ustring &name,
PXR_NS::VtValue value,
CCL_NS::AttributeElement elem,
CCL_NS::AttributeStandard std);
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,308 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#include "hydra/camera.h"
#include "scene/camera.h"
#include <pxr/base/gf/frustum.h>
#include <pxr/imaging/hd/sceneDelegate.h>
#include <pxr/usd/usdGeom/tokens.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
extern Transform convert_transform(const GfMatrix4d &matrix);
#if PXR_VERSION < 2102
// clang-format off
TF_DEFINE_PRIVATE_TOKENS(_tokens,
(projection)
(orthographic)
);
// clang-format on
#endif
HdCyclesCamera::HdCyclesCamera(const SdfPath &sprimId) : HdCamera(sprimId)
{
#if PXR_VERSION >= 2102
// Synchronize default values
_horizontalAperture = _data.GetHorizontalAperture() * GfCamera::APERTURE_UNIT;
_verticalAperture = _data.GetVerticalAperture() * GfCamera::APERTURE_UNIT;
_horizontalApertureOffset = _data.GetHorizontalApertureOffset() * GfCamera::APERTURE_UNIT;
_verticalApertureOffset = _data.GetVerticalApertureOffset() * GfCamera::APERTURE_UNIT;
_focalLength = _data.GetFocalLength() * GfCamera::FOCAL_LENGTH_UNIT;
_clippingRange = _data.GetClippingRange();
_fStop = _data.GetFStop();
_focusDistance = _data.GetFocusDistance();
#endif
}
HdCyclesCamera::~HdCyclesCamera()
{
}
HdDirtyBits HdCyclesCamera::GetInitialDirtyBitsMask() const
{
return DirtyBits::AllDirty;
}
void HdCyclesCamera::Sync(HdSceneDelegate *sceneDelegate,
HdRenderParam *renderParam,
HdDirtyBits *dirtyBits)
{
if (*dirtyBits == DirtyBits::Clean) {
return;
}
VtValue value;
const SdfPath &id = GetId();
#if PXR_VERSION >= 2102
if (*dirtyBits & DirtyBits::DirtyTransform) {
sceneDelegate->SampleTransform(id, &_transformSamples);
for (size_t i = 0; i < _transformSamples.count; ++i) {
if (_transformSamples.times[i] == 0.0f) {
_transform = _transformSamples.values[i];
_data.SetTransform(_transform);
break;
}
}
}
#else
if (*dirtyBits & DirtyBits::DirtyViewMatrix) {
sceneDelegate->SampleTransform(id, &_transformSamples);
value = sceneDelegate->GetCameraParamValue(id, HdCameraTokens->worldToViewMatrix);
if (!value.IsEmpty()) {
_worldToViewMatrix = value.Get<GfMatrix4d>();
_worldToViewInverseMatrix = _worldToViewMatrix.GetInverse();
_data.SetTransform(_worldToViewInverseMatrix);
}
}
#endif
#if PXR_VERSION < 2111
if (*dirtyBits & DirtyBits::DirtyProjMatrix) {
value = sceneDelegate->GetCameraParamValue(id, HdCameraTokens->projectionMatrix);
if (!value.IsEmpty()) {
_projectionMatrix = value.Get<GfMatrix4d>();
const float focalLength = _data.GetFocalLength(); // Get default focal length
#if PXR_VERSION >= 2102
_data.SetFromViewAndProjectionMatrix(GetViewMatrix(), _projectionMatrix, focalLength);
#else
if (_projectionMatrix[2][3] < -0.5) {
_data.SetProjection(GfCamera::Perspective);
const float horizontalAperture = (2.0 * focalLength) / _projectionMatrix[0][0];
_data.SetHorizontalAperture(horizontalAperture);
_data.SetHorizontalApertureOffset(0.5 * horizontalAperture * _projectionMatrix[2][0]);
const float verticalAperture = (2.0 * focalLength) / _projectionMatrix[1][1];
_data.SetVerticalAperture(verticalAperture);
_data.SetVerticalApertureOffset(0.5 * verticalAperture * _projectionMatrix[2][1]);
_data.SetClippingRange(
GfRange1f(_projectionMatrix[3][2] / (_projectionMatrix[2][2] - 1.0),
_projectionMatrix[3][2] / (_projectionMatrix[2][2] + 1.0)));
}
else {
_data.SetProjection(GfCamera::Orthographic);
const float horizontalAperture = (2.0 / GfCamera::APERTURE_UNIT) / _projectionMatrix[0][0];
_data.SetHorizontalAperture(horizontalAperture);
_data.SetHorizontalApertureOffset(-0.5 * horizontalAperture * _projectionMatrix[3][0]);
const float verticalAperture = (2.0 / GfCamera::APERTURE_UNIT) / _projectionMatrix[1][1];
_data.SetVerticalAperture(verticalAperture);
_data.SetVerticalApertureOffset(-0.5 * verticalAperture * _projectionMatrix[3][1]);
const double nearMinusFarHalf = 1.0 / _projectionMatrix[2][2];
const double nearPlusFarHalf = nearMinusFarHalf * _projectionMatrix[3][2];
_data.SetClippingRange(
GfRange1f(nearPlusFarHalf + nearMinusFarHalf, nearPlusFarHalf - nearMinusFarHalf));
}
#endif
}
}
#endif
if (*dirtyBits & DirtyBits::DirtyWindowPolicy) {
value = sceneDelegate->GetCameraParamValue(id, HdCameraTokens->windowPolicy);
if (!value.IsEmpty()) {
_windowPolicy = value.Get<CameraUtilConformWindowPolicy>();
}
}
if (*dirtyBits & DirtyBits::DirtyClipPlanes) {
value = sceneDelegate->GetCameraParamValue(id, HdCameraTokens->clipPlanes);
if (!value.IsEmpty()) {
_clipPlanes = value.Get<std::vector<GfVec4d>>();
}
}
if (*dirtyBits & DirtyBits::DirtyParams) {
#if PXR_VERSION >= 2102
value = sceneDelegate->GetCameraParamValue(id, HdCameraTokens->projection);
if (!value.IsEmpty()) {
_projection = value.Get<Projection>();
_data.SetProjection(_projection != Orthographic ? GfCamera::Perspective :
GfCamera::Orthographic);
}
#else
value = sceneDelegate->GetCameraParamValue(id, _tokens->projection);
if (!value.IsEmpty()) {
_data.SetProjection(value.Get<TfToken>() != _tokens->orthographic ?
GfCamera::Perspective :
GfCamera::Orthographic);
}
#endif
value = sceneDelegate->GetCameraParamValue(id, HdCameraTokens->horizontalAperture);
if (!value.IsEmpty()) {
const auto horizontalAperture = value.Get<float>();
#if PXR_VERSION >= 2102
_horizontalAperture = horizontalAperture;
#endif
_data.SetHorizontalAperture(horizontalAperture / GfCamera::APERTURE_UNIT);
}
value = sceneDelegate->GetCameraParamValue(id, HdCameraTokens->verticalAperture);
if (!value.IsEmpty()) {
const auto verticalAperture = value.Get<float>();
#if PXR_VERSION >= 2102
_verticalAperture = verticalAperture;
#endif
_data.SetVerticalAperture(verticalAperture / GfCamera::APERTURE_UNIT);
}
value = sceneDelegate->GetCameraParamValue(id, HdCameraTokens->horizontalApertureOffset);
if (!value.IsEmpty()) {
const auto horizontalApertureOffset = value.Get<float>();
#if PXR_VERSION >= 2102
_horizontalApertureOffset = horizontalApertureOffset;
#endif
_data.SetHorizontalApertureOffset(horizontalApertureOffset / GfCamera::APERTURE_UNIT);
}
value = sceneDelegate->GetCameraParamValue(id, HdCameraTokens->verticalApertureOffset);
if (!value.IsEmpty()) {
const auto verticalApertureOffset = value.Get<float>();
#if PXR_VERSION >= 2102
_verticalApertureOffset = verticalApertureOffset;
#endif
_data.SetVerticalApertureOffset(verticalApertureOffset / GfCamera::APERTURE_UNIT);
}
value = sceneDelegate->GetCameraParamValue(id, HdCameraTokens->focalLength);
if (!value.IsEmpty()) {
const auto focalLength = value.Get<float>();
#if PXR_VERSION >= 2102
_focalLength = focalLength;
#endif
_data.SetFocalLength(focalLength / GfCamera::FOCAL_LENGTH_UNIT);
}
value = sceneDelegate->GetCameraParamValue(id, HdCameraTokens->clippingRange);
if (!value.IsEmpty()) {
const auto clippingRange = value.Get<GfRange1f>();
#if PXR_VERSION >= 2102
_clippingRange = clippingRange;
#endif
_data.SetClippingRange(clippingRange);
}
value = sceneDelegate->GetCameraParamValue(id, HdCameraTokens->fStop);
if (!value.IsEmpty()) {
const auto fStop = value.Get<float>();
#if PXR_VERSION >= 2102
_fStop = fStop;
#endif
_data.SetFStop(fStop);
}
value = sceneDelegate->GetCameraParamValue(id, HdCameraTokens->focusDistance);
if (!value.IsEmpty()) {
const auto focusDistance = value.Get<float>();
#if PXR_VERSION >= 2102
_focusDistance = focusDistance;
#endif
_data.SetFocusDistance(focusDistance);
}
}
*dirtyBits = DirtyBits::Clean;
}
void HdCyclesCamera::Finalize(HdRenderParam *renderParam)
{
HdCamera::Finalize(renderParam);
}
void HdCyclesCamera::ApplyCameraSettings(Camera *cam) const
{
ApplyCameraSettings(_data, _windowPolicy, cam);
array<Transform> motion(_transformSamples.count);
for (size_t i = 0; i < _transformSamples.count; ++i)
motion[i] = convert_transform(_transformSamples.values[i]) *
transform_scale(1.0f, 1.0f, -1.0f);
cam->set_motion(motion);
}
void HdCyclesCamera::ApplyCameraSettings(const GfCamera &dataUnconformedWindow,
CameraUtilConformWindowPolicy windowPolicy,
Camera *cam)
{
const float width = cam->get_full_width();
const float height = cam->get_full_height();
auto data = dataUnconformedWindow;
CameraUtilConformWindow(&data, windowPolicy, width / height);
static_assert(GfCamera::Perspective == CAMERA_PERSPECTIVE &&
GfCamera::Orthographic == CAMERA_ORTHOGRAPHIC);
cam->set_camera_type(static_cast<CameraType>(data.GetProjection()));
auto viewplane = data.GetFrustum().GetWindow();
auto focalLength = 1.0f;
if (data.GetProjection() == GfCamera::Perspective) {
viewplane *= 2.0 / viewplane.GetSize()[1]; // Normalize viewplane
focalLength = data.GetFocalLength() * 1e-3f;
cam->set_fov(GfDegreesToRadians(data.GetFieldOfView(GfCamera::FOVVertical)));
}
cam->set_sensorwidth(data.GetHorizontalAperture() * GfCamera::APERTURE_UNIT);
cam->set_sensorheight(data.GetVerticalAperture() * GfCamera::APERTURE_UNIT);
cam->set_nearclip(data.GetClippingRange().GetMin());
cam->set_farclip(data.GetClippingRange().GetMax());
cam->set_viewplane_left(viewplane.GetMin()[0]);
cam->set_viewplane_right(viewplane.GetMax()[0]);
cam->set_viewplane_bottom(viewplane.GetMin()[1]);
cam->set_viewplane_top(viewplane.GetMax()[1]);
if (data.GetFStop() != 0.0f) {
cam->set_focaldistance(data.GetFocusDistance());
cam->set_aperturesize(focalLength / (2.0f * data.GetFStop()));
}
cam->set_matrix(convert_transform(data.GetTransform()) * transform_scale(1.0f, 1.0f, -1.0f));
}
void HdCyclesCamera::ApplyCameraSettings(const GfMatrix4d &worldToViewMatrix,
const GfMatrix4d &projectionMatrix,
const std::vector<GfVec4d> &clipPlanes,
Camera *cam)
{
#if PXR_VERSION >= 2102
GfCamera data;
data.SetFromViewAndProjectionMatrix(worldToViewMatrix, projectionMatrix);
ApplyCameraSettings(data, CameraUtilFit, cam);
#else
TF_CODING_ERROR("Not implemented");
#endif
}
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,43 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#pragma once
#include "hydra/config.h"
#include <pxr/base/gf/camera.h>
#include <pxr/imaging/hd/camera.h>
#include <pxr/imaging/hd/timeSampleArray.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
class HdCyclesCamera final : public PXR_NS::HdCamera {
public:
HdCyclesCamera(const PXR_NS::SdfPath &sprimId);
~HdCyclesCamera() override;
void ApplyCameraSettings(CCL_NS::Camera *targetCamera) const;
static void ApplyCameraSettings(const PXR_NS::GfCamera &cameraData,
PXR_NS::CameraUtilConformWindowPolicy windowPolicy,
CCL_NS::Camera *targetCamera);
static void ApplyCameraSettings(const PXR_NS::GfMatrix4d &worldToViewMatrix,
const PXR_NS::GfMatrix4d &projectionMatrix,
const std::vector<PXR_NS::GfVec4d> &clipPlanes,
CCL_NS::Camera *targetCamera);
PXR_NS::HdDirtyBits GetInitialDirtyBitsMask() const override;
void Sync(PXR_NS::HdSceneDelegate *sceneDelegate,
PXR_NS::HdRenderParam *renderParam,
PXR_NS::HdDirtyBits *dirtyBits) override;
void Finalize(PXR_NS::HdRenderParam *renderParam) override;
private:
PXR_NS::GfCamera _data;
PXR_NS::HdTimeSampleArray<PXR_NS::GfMatrix4d, 2> _transformSamples;
};
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,45 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#pragma once
#include <pxr/pxr.h>
#define CCL_NS ccl
#define CCL_NAMESPACE_USING_DIRECTIVE using namespace CCL_NS;
#define HD_CYCLES_NS HdCycles
#define HDCYCLES_NAMESPACE_OPEN_SCOPE \
namespace HD_CYCLES_NS { \
CCL_NAMESPACE_USING_DIRECTIVE; \
PXR_NAMESPACE_USING_DIRECTIVE;
#define HDCYCLES_NAMESPACE_CLOSE_SCOPE }
namespace HD_CYCLES_NS {
class HdCyclesCamera;
class HdCyclesDelegate;
class HdCyclesSession;
class HdCyclesRenderBuffer;
} // namespace HD_CYCLES_NS
namespace CCL_NS {
class AttributeSet;
class BufferParams;
class Camera;
class Geometry;
class Hair;
class Light;
class Mesh;
class Object;
class ParticleSystem;
class Pass;
class PointCloud;
class Scene;
class Session;
class SessionParams;
class Shader;
class ShaderGraph;
class ShaderNode;
class Volume;
} // namespace CCL_NS

View File

@@ -0,0 +1,210 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#include "hydra/curves.h"
#include "hydra/geometry.inl"
#include "scene/hair.h"
#include <pxr/imaging/hd/extComputationUtils.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
HdCyclesCurves::HdCyclesCurves(const SdfPath &rprimId
#if PXR_VERSION < 2102
,
const SdfPath &instancerId
#endif
)
: HdCyclesGeometry(rprimId
#if PXR_VERSION < 2102
,
instancerId
#endif
)
{
}
HdCyclesCurves::~HdCyclesCurves()
{
}
HdDirtyBits HdCyclesCurves::GetInitialDirtyBitsMask() const
{
HdDirtyBits bits = HdCyclesGeometry::GetInitialDirtyBitsMask();
bits |= HdChangeTracker::DirtyPoints | HdChangeTracker::DirtyWidths |
HdChangeTracker::DirtyPrimvar | HdChangeTracker::DirtyTopology;
return bits;
}
HdDirtyBits HdCyclesCurves::_PropagateDirtyBits(HdDirtyBits bits) const
{
if (bits & (HdChangeTracker::DirtyTopology)) {
// Changing topology clears the geometry, so need to populate everything again
bits |= HdChangeTracker::DirtyPoints | HdChangeTracker::DirtyWidths |
HdChangeTracker::DirtyPrimvar;
}
return bits;
}
void HdCyclesCurves::Populate(HdSceneDelegate *sceneDelegate, HdDirtyBits dirtyBits, bool &rebuild)
{
if (HdChangeTracker::IsTopologyDirty(dirtyBits, GetId())) {
PopulateTopology(sceneDelegate);
}
if (dirtyBits & HdChangeTracker::DirtyPoints) {
PopulatePoints(sceneDelegate);
}
if (dirtyBits & HdChangeTracker::DirtyWidths) {
PopulateWidths(sceneDelegate);
}
if (dirtyBits & HdChangeTracker::DirtyPrimvar) {
PopulatePrimvars(sceneDelegate);
}
rebuild = (_geom->curve_keys_is_modified()) || (_geom->curve_radius_is_modified());
}
void HdCyclesCurves::PopulatePoints(HdSceneDelegate *sceneDelegate)
{
VtValue value;
for (const HdExtComputationPrimvarDescriptor &desc :
sceneDelegate->GetExtComputationPrimvarDescriptors(GetId(), HdInterpolationVertex)) {
if (desc.name == HdTokens->points) {
auto valueStore = HdExtComputationUtils::GetComputedPrimvarValues({desc}, sceneDelegate);
const auto valueStoreIt = valueStore.find(desc.name);
if (valueStoreIt != valueStore.end()) {
value = std::move(valueStoreIt->second);
}
break;
}
}
if (value.IsEmpty()) {
value = GetPrimvar(sceneDelegate, HdTokens->points);
}
if (!value.IsHolding<VtVec3fArray>()) {
TF_WARN("Invalid points data for %s", GetId().GetText());
return;
}
const auto &points = value.UncheckedGet<VtVec3fArray>();
array<float3> pointsDataCycles;
pointsDataCycles.reserve(points.size());
for (const GfVec3f &point : points) {
pointsDataCycles.push_back_reserved(make_float3(point[0], point[1], point[2]));
}
_geom->set_curve_keys(pointsDataCycles);
}
void HdCyclesCurves::PopulateWidths(HdSceneDelegate *sceneDelegate)
{
VtValue value = GetPrimvar(sceneDelegate, HdTokens->widths);
const HdInterpolation interpolation = GetPrimvarInterpolation(sceneDelegate, HdTokens->widths);
if (!value.IsHolding<VtFloatArray>()) {
TF_WARN("Invalid widths data for %s", GetId().GetText());
return;
}
const auto &widths = value.UncheckedGet<VtFloatArray>();
array<float> radiusDataCycles;
radiusDataCycles.reserve(widths.size());
if (interpolation == HdInterpolationConstant) {
TF_VERIFY(widths.size() == 1);
const float constantRadius = widths[0] * 0.5f;
for (size_t i = 0; i < _geom->num_keys(); ++i) {
radiusDataCycles.push_back_reserved(constantRadius);
}
}
else if (interpolation == HdInterpolationVertex) {
TF_VERIFY(widths.size() == _geom->num_keys());
for (size_t i = 0; i < _geom->num_keys(); ++i) {
radiusDataCycles.push_back_reserved(widths[i] * 0.5f);
}
}
_geom->set_curve_radius(radiusDataCycles);
}
void HdCyclesCurves::PopulatePrimvars(HdSceneDelegate *sceneDelegate)
{
Scene *const scene = (Scene *)_geom->get_owner();
const std::pair<HdInterpolation, AttributeElement> interpolations[] = {
std::make_pair(HdInterpolationVertex, ATTR_ELEMENT_CURVE_KEY),
std::make_pair(HdInterpolationVarying, ATTR_ELEMENT_CURVE_KEY),
std::make_pair(HdInterpolationUniform, ATTR_ELEMENT_CURVE),
std::make_pair(HdInterpolationConstant, ATTR_ELEMENT_OBJECT),
};
for (const auto &interpolation : interpolations) {
for (const HdPrimvarDescriptor &desc :
GetPrimvarDescriptors(sceneDelegate, interpolation.first)) {
// Skip special primvars that are handled separately
if (desc.name == HdTokens->points || desc.name == HdTokens->widths) {
continue;
}
VtValue value = GetPrimvar(sceneDelegate, desc.name);
if (value.IsEmpty()) {
continue;
}
const ustring name(desc.name.GetString());
AttributeStandard std = ATTR_STD_NONE;
if (desc.role == HdPrimvarRoleTokens->textureCoordinate) {
std = ATTR_STD_UV;
}
else if (desc.name == HdTokens->displayColor &&
interpolation.first == HdInterpolationConstant) {
if (value.IsHolding<VtVec3fArray>() && value.GetArraySize() == 1) {
const GfVec3f color = value.UncheckedGet<VtVec3fArray>()[0];
_instances[0]->set_color(make_float3(color[0], color[1], color[2]));
}
}
// Skip attributes that are not needed
if ((std != ATTR_STD_NONE && _geom->need_attribute(scene, std)) ||
_geom->need_attribute(scene, name)) {
ApplyPrimvars(_geom->attributes, name, value, interpolation.second, std);
}
}
}
}
void HdCyclesCurves::PopulateTopology(HdSceneDelegate *sceneDelegate)
{
// Clear geometry before populating it again with updated topology
_geom->clear(true);
HdBasisCurvesTopology topology = GetBasisCurvesTopology(sceneDelegate);
_geom->reserve_curves(topology.GetNumCurves(), topology.CalculateNeededNumberOfControlPoints());
const VtIntArray vertCounts = topology.GetCurveVertexCounts();
for (int curve = 0, key = 0; curve < topology.GetNumCurves(); ++curve) {
// Always reference shader at index zero, which is the primitive material
_geom->add_curve(key, 0);
key += vertCounts[curve];
}
}
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,42 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#pragma once
#include "hydra/config.h"
#include "hydra/geometry.h"
#include <pxr/imaging/hd/basisCurves.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
class HdCyclesCurves final : public HdCyclesGeometry<PXR_NS::HdBasisCurves, CCL_NS::Hair> {
public:
HdCyclesCurves(
const PXR_NS::SdfPath &rprimId
#if PXR_VERSION < 2102
,
const PXR_NS::SdfPath &instancerId = {}
#endif
);
~HdCyclesCurves() override;
PXR_NS::HdDirtyBits GetInitialDirtyBitsMask() const override;
private:
PXR_NS::HdDirtyBits _PropagateDirtyBits(PXR_NS::HdDirtyBits bits) const override;
void Populate(PXR_NS::HdSceneDelegate *sceneDelegate,
PXR_NS::HdDirtyBits dirtyBits,
bool &rebuild) override;
void PopulatePoints(PXR_NS::HdSceneDelegate *sceneDelegate);
void PopulateWidths(PXR_NS::HdSceneDelegate *sceneDelegate);
void PopulatePrimvars(PXR_NS::HdSceneDelegate *sceneDelegate);
void PopulateTopology(PXR_NS::HdSceneDelegate *sceneDelegate);
};
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,240 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#ifdef _WIN32
// Include first to avoid "NOGDI" definition set in Cycles headers
# include <Windows.h>
#endif
#include "hydra/display_driver.h"
#include "hydra/render_buffer.h"
#include "hydra/session.h"
#include <GL/glew.h>
#include <pxr/imaging/hgiGL/texture.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
HdCyclesDisplayDriver::HdCyclesDisplayDriver(HdCyclesSession *renderParam, Hgi *hgi)
: _renderParam(renderParam), _hgi(hgi)
{
#ifdef _WIN32
hdc_ = GetDC(CreateWindowA("STATIC",
"HdCycles",
WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
0,
0,
64,
64,
NULL,
NULL,
GetModuleHandle(NULL),
NULL));
int pixelFormat = GetPixelFormat(wglGetCurrentDC());
PIXELFORMATDESCRIPTOR pfd = {sizeof(pfd)};
DescribePixelFormat((HDC)hdc_, pixelFormat, sizeof(pfd), &pfd);
SetPixelFormat((HDC)hdc_, pixelFormat, &pfd);
TF_VERIFY(gl_context_ = wglCreateContext((HDC)hdc_));
TF_VERIFY(wglShareLists(wglGetCurrentContext(), (HGLRC)gl_context_));
#endif
glewInit();
glGenBuffers(1, &gl_pbo_id_);
}
HdCyclesDisplayDriver::~HdCyclesDisplayDriver()
{
if (texture_) {
_hgi->DestroyTexture(&texture_);
}
glDeleteBuffers(1, &gl_pbo_id_);
#ifdef _WIN32
TF_VERIFY(wglDeleteContext((HGLRC)gl_context_));
DestroyWindow(WindowFromDC((HDC)hdc_));
#endif
}
void HdCyclesDisplayDriver::next_tile_begin()
{
}
bool HdCyclesDisplayDriver::update_begin(const Params &params,
int texture_width,
int texture_height)
{
#ifdef _WIN32
if (!hdc_ || !gl_context_) {
return false;
}
#endif
graphics_interop_activate();
if (gl_render_sync_) {
glWaitSync((GLsync)gl_render_sync_, 0, GL_TIMEOUT_IGNORED);
}
if (pbo_size_.x != params.full_size.x || pbo_size_.y != params.full_size.y) {
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_pbo_id_);
glBufferData(GL_PIXEL_UNPACK_BUFFER,
sizeof(half4) * params.full_size.x * params.full_size.y,
0,
GL_DYNAMIC_DRAW);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
pbo_size_ = params.full_size;
}
need_update_ = true;
return true;
}
void HdCyclesDisplayDriver::update_end()
{
gl_upload_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
glFlush();
graphics_interop_deactivate();
}
void HdCyclesDisplayDriver::flush()
{
graphics_interop_activate();
if (gl_upload_sync_) {
glWaitSync((GLsync)gl_upload_sync_, 0, GL_TIMEOUT_IGNORED);
}
if (gl_render_sync_) {
glWaitSync((GLsync)gl_render_sync_, 0, GL_TIMEOUT_IGNORED);
}
graphics_interop_deactivate();
}
half4 *HdCyclesDisplayDriver::map_texture_buffer()
{
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_pbo_id_);
const auto mapped_rgba_pixels = static_cast<half4 *>(
glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY));
if (need_clear_ && mapped_rgba_pixels) {
memset(mapped_rgba_pixels, 0, sizeof(half4) * pbo_size_.x * pbo_size_.y);
need_clear_ = false;
}
return mapped_rgba_pixels;
}
void HdCyclesDisplayDriver::unmap_texture_buffer()
{
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
DisplayDriver::GraphicsInterop HdCyclesDisplayDriver::graphics_interop_get()
{
GraphicsInterop interop_dst;
interop_dst.buffer_width = pbo_size_.x;
interop_dst.buffer_height = pbo_size_.y;
interop_dst.opengl_pbo_id = gl_pbo_id_;
interop_dst.need_clear = need_clear_;
need_clear_ = false;
return interop_dst;
}
void HdCyclesDisplayDriver::graphics_interop_activate()
{
mutex_.lock();
#ifdef _WIN32
// Do not change context if this is called in the main thread
if (wglGetCurrentContext() == nullptr) {
TF_VERIFY(wglMakeCurrent((HDC)hdc_, (HGLRC)gl_context_));
}
#endif
}
void HdCyclesDisplayDriver::graphics_interop_deactivate()
{
#ifdef _WIN32
if (wglGetCurrentContext() == gl_context_) {
TF_VERIFY(wglMakeCurrent(nullptr, nullptr));
}
#endif
mutex_.unlock();
}
void HdCyclesDisplayDriver::clear()
{
need_clear_ = true;
}
void HdCyclesDisplayDriver::draw(const Params &params)
{
const auto renderBuffer = static_cast<HdCyclesRenderBuffer *>(
_renderParam->GetDisplayAovBinding().renderBuffer);
if (!renderBuffer || // Ensure this render buffer matches the texture dimensions
(renderBuffer->GetWidth() != params.size.x || renderBuffer->GetHeight() != params.size.y)) {
return;
}
// Cycles 'DisplayDriver' only supports 'half4' format
TF_VERIFY(renderBuffer->GetFormat() == HdFormatFloat16Vec4);
const thread_scoped_lock lock(mutex_);
const GfVec3i dimensions(params.size.x, params.size.y, 1);
if (!texture_ || texture_->GetDescriptor().dimensions != dimensions) {
if (texture_) {
_hgi->DestroyTexture(&texture_);
}
HgiTextureDesc texDesc;
texDesc.usage = 0;
texDesc.format = HgiFormatFloat16Vec4;
texDesc.type = HgiTextureType2D;
texDesc.dimensions = dimensions;
texDesc.sampleCount = HgiSampleCount1;
texture_ = _hgi->CreateTexture(texDesc);
renderBuffer->SetResource(VtValue(texture_));
}
HgiGLTexture *const texture = dynamic_cast<HgiGLTexture *>(texture_.Get());
if (!texture || !need_update_ || pbo_size_.x != params.size.x || pbo_size_.y != params.size.y) {
return;
}
if (gl_upload_sync_) {
glWaitSync((GLsync)gl_upload_sync_, 0, GL_TIMEOUT_IGNORED);
}
glBindTexture(GL_TEXTURE_2D, texture->GetTextureId());
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_pbo_id_);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pbo_size_.x, pbo_size_.y, GL_RGBA, GL_HALF_FLOAT, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
gl_render_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
glFlush();
need_update_ = false;
}
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,61 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#pragma once
#include "hydra/config.h"
#include "session/display_driver.h"
#include "util/thread.h"
#include <pxr/imaging/hgi/hgi.h>
#include <pxr/imaging/hgi/texture.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
class HdCyclesDisplayDriver final : public CCL_NS::DisplayDriver {
public:
HdCyclesDisplayDriver(HdCyclesSession *renderParam, Hgi *hgi);
~HdCyclesDisplayDriver();
private:
void next_tile_begin() override;
bool update_begin(const Params &params, int texture_width, int texture_height) override;
void update_end() override;
void flush() override;
CCL_NS::half4 *map_texture_buffer() override;
void unmap_texture_buffer() override;
GraphicsInterop graphics_interop_get() override;
void graphics_interop_activate() override;
void graphics_interop_deactivate() override;
void clear() override;
void draw(const Params &params) override;
HdCyclesSession *const _renderParam;
Hgi *const _hgi;
#ifdef _WIN32
void *hdc_ = nullptr;
void *gl_context_ = nullptr;
#endif
CCL_NS::thread_mutex mutex_;
PXR_NS::HgiTextureHandle texture_;
unsigned int gl_pbo_id_ = 0;
CCL_NS::int2 pbo_size_ = CCL_NS::make_int2(0, 0);
bool need_update_ = false;
std::atomic_bool need_clear_ = false;
void *gl_render_sync_ = nullptr;
void *gl_upload_sync_ = nullptr;
};
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,90 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#include "hydra/field.h"
#include "hydra/session.h"
#include "scene/image_vdb.h"
#include "scene/scene.h"
#include <pxr/imaging/hd/sceneDelegate.h>
#include <pxr/usd/sdf/assetPath.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
#if PXR_VERSION < 2108
// clang-format off
TF_DEFINE_PRIVATE_TOKENS(_tokens,
(fieldName)
);
// clang-format on
#endif
#ifdef WITH_OPENVDB
class HdCyclesVolumeLoader : public VDBImageLoader {
public:
HdCyclesVolumeLoader(const std::string &filePath, const std::string &gridName)
: VDBImageLoader(gridName)
{
openvdb::io::File file(filePath);
file.setCopyMaxBytes(0);
if (file.open()) {
grid = file.readGrid(gridName);
}
}
};
#endif
HdCyclesField::HdCyclesField(const SdfPath &bprimId, const TfToken &typeId) : HdField(bprimId)
{
}
HdCyclesField::~HdCyclesField()
{
}
HdDirtyBits HdCyclesField::GetInitialDirtyBitsMask() const
{
return DirtyBits::DirtyParams;
}
void HdCyclesField::Sync(HdSceneDelegate *sceneDelegate,
HdRenderParam *renderParam,
HdDirtyBits *dirtyBits)
{
#ifdef WITH_OPENVDB
VtValue value;
const SdfPath &id = GetId();
if (*dirtyBits & DirtyBits::DirtyParams) {
value = sceneDelegate->Get(id, HdFieldTokens->filePath);
if (value.IsHolding<SdfAssetPath>()) {
std::string filename = value.UncheckedGet<SdfAssetPath>().GetResolvedPath();
if (filename.empty()) {
filename = value.UncheckedGet<SdfAssetPath>().GetAssetPath();
}
# if PXR_VERSION >= 2108
value = sceneDelegate->Get(id, HdFieldTokens->fieldName);
# else
value = sceneDelegate->Get(id, _tokens->fieldName);
# endif
if (value.IsHolding<TfToken>()) {
ImageLoader *const loader = new HdCyclesVolumeLoader(
filename, value.UncheckedGet<TfToken>().GetString());
const SceneLock lock(renderParam);
ImageParams params;
params.frame = 0.0f;
_handle = lock.scene->image_manager->add_image(loader, params, false);
}
}
}
#endif
*dirtyBits = DirtyBits::Clean;
}
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,34 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#pragma once
#include "hydra/config.h"
#include "scene/image.h"
#include <pxr/imaging/hd/field.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
class HdCyclesField final : public PXR_NS::HdField {
public:
HdCyclesField(const PXR_NS::SdfPath &bprimId, const PXR_NS::TfToken &typeId);
~HdCyclesField() override;
PXR_NS::HdDirtyBits GetInitialDirtyBitsMask() const override;
void Sync(PXR_NS::HdSceneDelegate *sceneDelegate,
PXR_NS::HdRenderParam *renderParam,
PXR_NS::HdDirtyBits *dirtyBits) override;
CCL_NS::ImageHandle GetImageHandle() const
{
return _handle;
}
private:
CCL_NS::ImageHandle _handle;
};
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,54 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#pragma once
#include "hydra/config.h"
#include <pxr/imaging/hd/rprim.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
template<typename Base, typename CyclesBase> class HdCyclesGeometry : public Base {
public:
HdCyclesGeometry(const PXR_NS::SdfPath &rprimId
#if PXR_VERSION < 2102
,
const PXR_NS::SdfPath &instancerId
#endif
);
void Sync(PXR_NS::HdSceneDelegate *sceneDelegate,
PXR_NS::HdRenderParam *renderParam,
PXR_NS::HdDirtyBits *dirtyBits,
const PXR_NS::TfToken &reprToken) override;
PXR_NS::HdDirtyBits GetInitialDirtyBitsMask() const override;
virtual void Finalize(PXR_NS::HdRenderParam *renderParam) override;
protected:
void _InitRepr(const PXR_NS::TfToken &reprToken, PXR_NS::HdDirtyBits *dirtyBits) override;
PXR_NS::HdDirtyBits _PropagateDirtyBits(PXR_NS::HdDirtyBits bits) const override;
virtual void Populate(PXR_NS::HdSceneDelegate *sceneDelegate,
PXR_NS::HdDirtyBits dirtyBits,
bool &rebuild) = 0;
PXR_NS::HdInterpolation GetPrimvarInterpolation(PXR_NS::HdSceneDelegate *sceneDelegate,
const PXR_NS::TfToken &name) const;
CyclesBase *_geom = nullptr;
std::vector<CCL_NS::Object *> _instances;
private:
void Initialize(PXR_NS::HdRenderParam *renderParam);
void InitializeInstance(int index);
PXR_NS::GfMatrix4d _geomTransform;
};
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,247 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#include "hydra/attribute.h"
#include "hydra/geometry.h"
#include "hydra/instancer.h"
#include "hydra/material.h"
#include "hydra/session.h"
#include "scene/geometry.h"
#include "scene/object.h"
#include "scene/scene.h"
#include "util/hash.h"
#include <pxr/imaging/hd/sceneDelegate.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
extern Transform convert_transform(const GfMatrix4d &matrix);
template<typename Base, typename CyclesBase>
HdCyclesGeometry<Base, CyclesBase>::HdCyclesGeometry(const SdfPath &rprimId
#if PXR_VERSION < 2102
,
const SdfPath &instancerId
#endif
)
: Base(rprimId
#if PXR_VERSION < 2102
,
instancerId
#endif
),
_geomTransform(1.0)
{
}
template<typename Base, typename CyclesBase>
void HdCyclesGeometry<Base, CyclesBase>::_InitRepr(const TfToken &reprToken,
HdDirtyBits *dirtyBits)
{
TF_UNUSED(reprToken);
TF_UNUSED(dirtyBits);
}
template<typename Base, typename CyclesBase>
HdDirtyBits HdCyclesGeometry<Base, CyclesBase>::GetInitialDirtyBitsMask() const
{
return HdChangeTracker::DirtyPrimID | HdChangeTracker::DirtyTransform |
HdChangeTracker::DirtyMaterialId | HdChangeTracker::DirtyVisibility |
HdChangeTracker::DirtyInstancer;
}
template<typename Base, typename CyclesBase>
HdDirtyBits HdCyclesGeometry<Base, CyclesBase>::_PropagateDirtyBits(HdDirtyBits bits) const
{
return bits;
}
template<typename Base, typename CyclesBase>
void HdCyclesGeometry<Base, CyclesBase>::Sync(HdSceneDelegate *sceneDelegate,
HdRenderParam *renderParam,
HdDirtyBits *dirtyBits,
const TfToken &reprToken)
{
TF_UNUSED(reprToken);
if (*dirtyBits == HdChangeTracker::Clean) {
return;
}
Initialize(renderParam);
#if PXR_VERSION >= 2102
Base::_UpdateInstancer(sceneDelegate, dirtyBits);
HdInstancer::_SyncInstancerAndParents(sceneDelegate->GetRenderIndex(), Base::GetInstancerId());
#endif
Base::_UpdateVisibility(sceneDelegate, dirtyBits);
const SceneLock lock(renderParam);
if (*dirtyBits & HdChangeTracker::DirtyMaterialId) {
#if HD_API_VERSION >= 37 && PXR_VERSION >= 2105
Base::SetMaterialId(sceneDelegate->GetMaterialId(Base::GetId()));
#else
Base::_SetMaterialId(sceneDelegate->GetRenderIndex().GetChangeTracker(),
sceneDelegate->GetMaterialId(Base::GetId()));
#endif
const auto material = static_cast<const HdCyclesMaterial *>(
sceneDelegate->GetRenderIndex().GetSprim(HdPrimTypeTokens->material,
Base::GetMaterialId()));
array<Node *> usedShaders(1);
if (material && material->GetCyclesShader()) {
usedShaders[0] = material->GetCyclesShader();
}
else {
usedShaders[0] = lock.scene->default_surface;
}
for (Node *shader : usedShaders) {
static_cast<Shader *>(shader)->tag_used(lock.scene);
}
_geom->set_used_shaders(usedShaders);
}
const SdfPath &id = Base::GetId();
if (HdChangeTracker::IsPrimIdDirty(*dirtyBits, id)) {
// This needs to be corrected in the AOV
_instances[0]->set_pass_id(Base::GetPrimId() + 1);
}
if (HdChangeTracker::IsTransformDirty(*dirtyBits, id)) {
_geomTransform = sceneDelegate->GetTransform(id);
}
if (HdChangeTracker::IsTransformDirty(*dirtyBits, id) ||
HdChangeTracker::IsInstancerDirty(*dirtyBits, id)) {
const auto instancer = static_cast<HdCyclesInstancer *>(
sceneDelegate->GetRenderIndex().GetInstancer(Base::GetInstancerId()));
// Make sure the first object attribute is the instanceId
assert(_instances[0]->attributes.size() >= 1 &&
_instances[0]->attributes.front().name() == HdAovTokens->instanceId.GetString());
VtMatrix4dArray transforms;
if (instancer) {
transforms = instancer->ComputeInstanceTransforms(id);
_instances[0]->attributes.front() = ParamValue(HdAovTokens->instanceId.GetString(), +0.0f);
}
else {
// Default to a single instance with an identity transform
transforms.push_back(GfMatrix4d(1.0));
_instances[0]->attributes.front() = ParamValue(HdAovTokens->instanceId.GetString(), -1.0f);
}
const size_t oldSize = _instances.size();
const size_t newSize = transforms.size();
// Resize instance list
for (size_t i = newSize; i < oldSize; ++i) {
lock.scene->delete_node(_instances[i]);
}
_instances.resize(newSize);
for (size_t i = oldSize; i < newSize; ++i) {
_instances[i] = lock.scene->create_node<Object>();
InitializeInstance(static_cast<int>(i));
}
// Update transforms of all instances
for (size_t i = 0; i < transforms.size(); ++i) {
const Transform tfm = convert_transform(_geomTransform * transforms[i]);
_instances[i]->set_tfm(tfm);
}
}
if (HdChangeTracker::IsVisibilityDirty(*dirtyBits, id)) {
for (Object *instance : _instances) {
instance->set_visibility(Base::IsVisible() ? ~0 : 0);
}
}
// Must happen after material ID update, so that attribute decisions can be made
// based on it (e.g. check whether an attribute is actually needed)
bool rebuild = false;
Populate(sceneDelegate, *dirtyBits, rebuild);
if (_geom->is_modified() || rebuild) {
_geom->tag_update(lock.scene, rebuild);
}
for (Object *instance : _instances) {
instance->tag_update(lock.scene);
}
*dirtyBits = HdChangeTracker::Clean;
}
template<typename Base, typename CyclesBase>
void HdCyclesGeometry<Base, CyclesBase>::Finalize(HdRenderParam *renderParam)
{
if (!_geom && _instances.empty()) {
return;
}
const SceneLock lock(renderParam);
lock.scene->delete_node(_geom);
_geom = nullptr;
lock.scene->delete_nodes(set<Object *>(_instances.begin(), _instances.end()));
_instances.clear();
_instances.shrink_to_fit();
}
template<typename Base, typename CyclesBase>
void HdCyclesGeometry<Base, CyclesBase>::Initialize(HdRenderParam *renderParam)
{
if (_geom) {
return;
}
const SceneLock lock(renderParam);
// Create geometry
_geom = lock.scene->create_node<CyclesBase>();
_geom->name = Base::GetId().GetString();
// Create default instance
_instances.push_back(lock.scene->create_node<Object>());
InitializeInstance(0);
}
template<typename Base, typename CyclesBase>
void HdCyclesGeometry<Base, CyclesBase>::InitializeInstance(int index)
{
Object *instance = _instances[index];
instance->set_geometry(_geom);
instance->attributes.emplace_back(HdAovTokens->instanceId.GetString(),
_instances.size() == 1 ? -1.0f : static_cast<float>(index));
instance->set_color(make_float3(0.8f, 0.8f, 0.8f));
instance->set_random_id(hash_uint2(hash_string(_geom->name.c_str()), index));
}
template<typename Base, typename CyclesBase>
HdInterpolation HdCyclesGeometry<Base, CyclesBase>::GetPrimvarInterpolation(
HdSceneDelegate *sceneDelegate, const TfToken &name) const
{
for (int i = 0; i < HdInterpolationCount; ++i) {
for (const HdPrimvarDescriptor &desc :
Base::GetPrimvarDescriptors(sceneDelegate, static_cast<HdInterpolation>(i))) {
if (desc.name == name) {
return static_cast<HdInterpolation>(i);
}
}
}
return HdInterpolationCount;
}
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,138 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#include "hydra/instancer.h"
#include <pxr/base/gf/quatd.h>
#include <pxr/imaging/hd/sceneDelegate.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
HdCyclesInstancer::HdCyclesInstancer(HdSceneDelegate *delegate,
const SdfPath &instancerId
#if PXR_VERSION <= 2011
,
const SdfPath &parentId
#endif
)
: HdInstancer(delegate,
instancerId
#if PXR_VERSION <= 2011
,
parentId
#endif
)
{
}
HdCyclesInstancer::~HdCyclesInstancer()
{
}
#if PXR_VERSION > 2011
void HdCyclesInstancer::Sync(HdSceneDelegate *sceneDelegate,
HdRenderParam *renderParam,
HdDirtyBits *dirtyBits)
{
_UpdateInstancer(sceneDelegate, dirtyBits);
if (HdChangeTracker::IsAnyPrimvarDirty(*dirtyBits, GetId())) {
SyncPrimvars();
}
}
#endif
void HdCyclesInstancer::SyncPrimvars()
{
HdSceneDelegate *const sceneDelegate = GetDelegate();
const HdDirtyBits dirtyBits =
sceneDelegate->GetRenderIndex().GetChangeTracker().GetInstancerDirtyBits(GetId());
for (const HdPrimvarDescriptor &desc :
sceneDelegate->GetPrimvarDescriptors(GetId(), HdInterpolationInstance)) {
if (!HdChangeTracker::IsPrimvarDirty(dirtyBits, GetId(), desc.name)) {
continue;
}
const VtValue value = sceneDelegate->Get(GetId(), desc.name);
if (value.IsEmpty()) {
continue;
}
if (desc.name == HdInstancerTokens->translate) {
_translate = value.Get<VtVec3fArray>();
}
else if (desc.name == HdInstancerTokens->rotate) {
_rotate = value.Get<VtVec4fArray>();
}
else if (desc.name == HdInstancerTokens->scale) {
_scale = value.Get<VtVec3fArray>();
}
else if (desc.name == HdInstancerTokens->instanceTransform) {
_instanceTransform = value.Get<VtMatrix4dArray>();
}
}
sceneDelegate->GetRenderIndex().GetChangeTracker().MarkInstancerClean(GetId());
}
VtMatrix4dArray HdCyclesInstancer::ComputeInstanceTransforms(const SdfPath &prototypeId)
{
#if PXR_VERSION <= 2011
SyncPrimvars();
#endif
const VtIntArray instanceIndices = GetDelegate()->GetInstanceIndices(GetId(), prototypeId);
const GfMatrix4d instanceTransform = GetDelegate()->GetInstancerTransform(GetId());
VtMatrix4dArray transforms;
transforms.reserve(instanceIndices.size());
for (int index : instanceIndices) {
GfMatrix4d transform = instanceTransform;
if (index < _translate.size()) {
GfMatrix4d translateMat(1);
translateMat.SetTranslate(_translate[index]);
transform *= translateMat;
}
if (index < _rotate.size()) {
GfMatrix4d rotateMat(1);
const GfVec4f &quat = _rotate[index];
rotateMat.SetRotate(GfQuatd(quat[0], quat[1], quat[2], quat[3]));
transform *= rotateMat;
}
if (index < _scale.size()) {
GfMatrix4d scaleMat(1);
scaleMat.SetScale(_scale[index]);
transform *= scaleMat;
}
if (index < _instanceTransform.size()) {
transform *= _instanceTransform[index];
}
transforms.push_back(transform);
}
VtMatrix4dArray resultTransforms;
if (const auto instancer = static_cast<HdCyclesInstancer *>(
GetDelegate()->GetRenderIndex().GetInstancer(GetParentId()))) {
for (const GfMatrix4d &parentTransform : instancer->ComputeInstanceTransforms(GetId())) {
for (const GfMatrix4d &localTransform : transforms) {
resultTransforms.push_back(parentTransform * localTransform);
}
}
}
else {
resultTransforms = std::move(transforms);
}
return resultTransforms;
}
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,45 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#pragma once
#include "hydra/config.h"
#include <pxr/base/gf/matrix4d.h>
#include <pxr/base/gf/vec3f.h>
#include <pxr/base/gf/vec4f.h>
#include <pxr/base/vt/array.h>
#include <pxr/imaging/hd/instancer.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
class HdCyclesInstancer final : public PXR_NS::HdInstancer {
public:
HdCyclesInstancer(PXR_NS::HdSceneDelegate *delegate,
const PXR_NS::SdfPath &instancerId
#if PXR_VERSION <= 2011
,
const PXR_NS::SdfPath &parentId
#endif
);
~HdCyclesInstancer() override;
#if PXR_VERSION > 2011
void Sync(PXR_NS::HdSceneDelegate *sceneDelegate,
PXR_NS::HdRenderParam *renderParam,
PXR_NS::HdDirtyBits *dirtyBits) override;
#endif
PXR_NS::VtMatrix4dArray ComputeInstanceTransforms(const PXR_NS::SdfPath &prototypeId);
private:
void SyncPrimvars();
PXR_NS::VtVec3fArray _translate;
PXR_NS::VtVec4fArray _rotate;
PXR_NS::VtVec3fArray _scale;
PXR_NS::VtMatrix4dArray _instanceTransform;
};
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,399 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#include "hydra/light.h"
#include "hydra/session.h"
#include "scene/light.h"
#include "scene/scene.h"
#include "scene/shader.h"
#include "scene/shader_graph.h"
#include "scene/shader_nodes.h"
#include "util/hash.h"
#include <pxr/imaging/hd/sceneDelegate.h>
#include <pxr/usd/sdf/assetPath.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
extern Transform convert_transform(const GfMatrix4d &matrix);
// clang-format off
TF_DEFINE_PRIVATE_TOKENS(_tokens,
(visibleInPrimaryRay)
);
// clang-format on
HdCyclesLight::HdCyclesLight(const SdfPath &sprimId, const TfToken &lightType)
: HdLight(sprimId), _lightType(lightType)
{
}
HdCyclesLight::~HdCyclesLight()
{
}
HdDirtyBits HdCyclesLight::GetInitialDirtyBitsMask() const
{
return DirtyBits::DirtyTransform | DirtyBits::DirtyParams;
}
void HdCyclesLight::Sync(HdSceneDelegate *sceneDelegate,
HdRenderParam *renderParam,
HdDirtyBits *dirtyBits)
{
if (*dirtyBits == DirtyBits::Clean) {
return;
}
Initialize(renderParam);
const SceneLock lock(renderParam);
VtValue value;
const SdfPath &id = GetId();
if (*dirtyBits & DirtyBits::DirtyTransform) {
#if PXR_VERSION >= 2011
const Transform tfm = convert_transform(sceneDelegate->GetTransform(id));
#else
const Transform tfm = convert_transform(
sceneDelegate->GetLightParamValue(id, HdTokens->transform).Get<GfMatrix4d>());
#endif
_light->set_tfm(tfm);
_light->set_co(transform_get_column(&tfm, 3));
_light->set_dir(-transform_get_column(&tfm, 2));
if (_lightType == HdPrimTypeTokens->diskLight || _lightType == HdPrimTypeTokens->rectLight) {
_light->set_axisu(transform_get_column(&tfm, 0));
_light->set_axisv(transform_get_column(&tfm, 1));
}
}
if (*dirtyBits & DirtyBits::DirtyParams) {
float3 strength = make_float3(1.0f, 1.0f, 1.0f);
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->color);
if (!value.IsEmpty()) {
const auto color = value.Get<GfVec3f>();
strength = make_float3(color[0], color[1], color[2]);
}
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->exposure);
if (!value.IsEmpty()) {
strength *= exp2(value.Get<float>());
}
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->intensity);
if (!value.IsEmpty()) {
strength *= value.Get<float>();
}
// Cycles lights are normalized by default, so need to scale intensity if Hydra light is not
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->normalize);
const bool normalize = value.IsHolding<bool>() && value.UncheckedGet<bool>();
value = sceneDelegate->GetLightParamValue(id, _tokens->visibleInPrimaryRay);
if (!value.IsEmpty()) {
_light->set_use_camera(value.Get<bool>());
}
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->shadowEnable);
if (!value.IsEmpty()) {
_light->set_cast_shadow(value.Get<bool>());
}
if (_lightType == HdPrimTypeTokens->distantLight) {
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->angle);
if (!value.IsEmpty()) {
_light->set_angle(GfDegreesToRadians(value.Get<float>()));
}
}
else if (_lightType == HdPrimTypeTokens->diskLight) {
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->radius);
if (!value.IsEmpty()) {
const float size = value.Get<float>() * 2.0f;
_light->set_sizeu(size);
_light->set_sizev(size);
}
if (!normalize) {
const float radius = _light->get_sizeu() * 0.5f;
strength *= M_PI * radius * radius;
}
}
else if (_lightType == HdPrimTypeTokens->rectLight) {
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->width);
if (!value.IsEmpty()) {
_light->set_sizeu(value.Get<float>());
}
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->height);
if (!value.IsEmpty()) {
_light->set_sizev(value.Get<float>());
}
if (!normalize) {
strength *= _light->get_sizeu() * _light->get_sizeu();
}
}
else if (_lightType == HdPrimTypeTokens->sphereLight) {
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->radius);
if (!value.IsEmpty()) {
_light->set_size(value.Get<float>());
}
bool shaping = false;
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->shapingConeAngle);
if (!value.IsEmpty()) {
_light->set_spot_angle(GfDegreesToRadians(value.Get<float>()) * 2.0f);
shaping = true;
}
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->shapingConeSoftness);
if (!value.IsEmpty()) {
_light->set_spot_smooth(value.Get<float>());
shaping = true;
}
_light->set_light_type(shaping ? LIGHT_SPOT : LIGHT_POINT);
if (!normalize) {
const float radius = _light->get_size();
strength *= M_PI * radius * radius * 4.0f;
}
}
const bool visible = sceneDelegate->GetVisible(id);
// Disable invisible lights by zeroing the strength
// So 'LightManager::test_enabled_lights' updates the enabled flag correctly
if (!visible) {
strength = zero_float3();
}
_light->set_strength(strength);
_light->set_is_enabled(visible);
PopulateShaderGraph(sceneDelegate);
}
// Need to update shader graph when transform changes in case transform was baked into it
else if (_light->tfm_is_modified() && (_lightType == HdPrimTypeTokens->domeLight ||
_light->get_shader()->has_surface_spatial_varying)) {
PopulateShaderGraph(sceneDelegate);
}
if (_light->is_modified()) {
_light->tag_update(lock.scene);
}
*dirtyBits = DirtyBits::Clean;
}
void HdCyclesLight::PopulateShaderGraph(HdSceneDelegate *sceneDelegate)
{
auto graph = new ShaderGraph();
ShaderNode *outputNode = nullptr;
if (_lightType == HdPrimTypeTokens->domeLight) {
BackgroundNode *bgNode = graph->create_node<BackgroundNode>();
// Bake strength into shader graph, since only the shader is used for background lights
bgNode->set_color(_light->get_strength());
graph->add(bgNode);
graph->connect(bgNode->output("Background"), graph->output()->input("Surface"));
outputNode = bgNode;
}
else {
EmissionNode *emissionNode = graph->create_node<EmissionNode>();
emissionNode->set_color(one_float3());
emissionNode->set_strength(1.0f);
graph->add(emissionNode);
graph->connect(emissionNode->output("Emission"), graph->output()->input("Surface"));
outputNode = emissionNode;
}
VtValue value;
const SdfPath &id = GetId();
bool hasSpatialVarying = false;
bool hasColorTemperature = false;
if (sceneDelegate != nullptr) {
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->enableColorTemperature);
const bool enableColorTemperature = value.IsHolding<bool>() && value.UncheckedGet<bool>();
if (enableColorTemperature) {
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->colorTemperature);
if (value.IsHolding<float>()) {
BlackbodyNode *blackbodyNode = graph->create_node<BlackbodyNode>();
blackbodyNode->set_temperature(value.UncheckedGet<float>());
graph->add(blackbodyNode);
if (_lightType == HdPrimTypeTokens->domeLight) {
VectorMathNode *mathNode = graph->create_node<VectorMathNode>();
mathNode->set_math_type(NODE_VECTOR_MATH_MULTIPLY);
mathNode->set_vector2(_light->get_strength());
graph->add(mathNode);
graph->connect(blackbodyNode->output("Color"), mathNode->input("Vector1"));
graph->connect(mathNode->output("Vector"), outputNode->input("Color"));
}
else {
graph->connect(blackbodyNode->output("Color"), outputNode->input("Color"));
}
hasColorTemperature = true;
}
}
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->shapingIesFile);
if (value.IsHolding<SdfAssetPath>()) {
std::string filename = value.UncheckedGet<SdfAssetPath>().GetResolvedPath();
if (filename.empty()) {
filename = value.UncheckedGet<SdfAssetPath>().GetAssetPath();
}
TextureCoordinateNode *coordNode = graph->create_node<TextureCoordinateNode>();
coordNode->set_ob_tfm(_light->get_tfm());
coordNode->set_use_transform(true);
graph->add(coordNode);
IESLightNode *iesNode = graph->create_node<IESLightNode>();
iesNode->set_filename(ustring(filename));
graph->connect(coordNode->output("Normal"), iesNode->input("Vector"));
graph->connect(iesNode->output("Fac"), outputNode->input("Strength"));
hasSpatialVarying = true;
}
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->textureFile);
if (value.IsHolding<SdfAssetPath>()) {
std::string filename = value.UncheckedGet<SdfAssetPath>().GetResolvedPath();
if (filename.empty()) {
filename = value.UncheckedGet<SdfAssetPath>().GetAssetPath();
}
ImageSlotTextureNode *textureNode = nullptr;
if (_lightType == HdPrimTypeTokens->domeLight) {
Transform tfm = _light->get_tfm();
transform_set_column(&tfm, 3, zero_float3()); // Remove translation
TextureCoordinateNode *coordNode = graph->create_node<TextureCoordinateNode>();
coordNode->set_ob_tfm(tfm);
coordNode->set_use_transform(true);
graph->add(coordNode);
textureNode = graph->create_node<EnvironmentTextureNode>();
static_cast<EnvironmentTextureNode *>(textureNode)->set_filename(ustring(filename));
graph->add(textureNode);
graph->connect(coordNode->output("Object"), textureNode->input("Vector"));
hasSpatialVarying = true;
}
else {
GeometryNode *coordNode = graph->create_node<GeometryNode>();
graph->add(coordNode);
textureNode = graph->create_node<ImageTextureNode>();
static_cast<ImageTextureNode *>(textureNode)->set_filename(ustring(filename));
graph->add(textureNode);
graph->connect(coordNode->output("Parametric"), textureNode->input("Vector"));
}
if (hasColorTemperature) {
VectorMathNode *mathNode = graph->create_node<VectorMathNode>();
mathNode->set_math_type(NODE_VECTOR_MATH_MULTIPLY);
graph->add(mathNode);
graph->connect(textureNode->output("Color"), mathNode->input("Vector1"));
ShaderInput *const outputNodeInput = outputNode->input("Color");
graph->connect(outputNodeInput->link, mathNode->input("Vector2"));
graph->disconnect(outputNodeInput);
graph->connect(mathNode->output("Vector"), outputNodeInput);
}
else if (_lightType == HdPrimTypeTokens->domeLight) {
VectorMathNode *mathNode = graph->create_node<VectorMathNode>();
mathNode->set_math_type(NODE_VECTOR_MATH_MULTIPLY);
mathNode->set_vector2(_light->get_strength());
graph->add(mathNode);
graph->connect(textureNode->output("Color"), mathNode->input("Vector1"));
graph->connect(mathNode->output("Vector"), outputNode->input("Color"));
}
else {
graph->connect(textureNode->output("Color"), outputNode->input("Color"));
}
}
}
Shader *const shader = _light->get_shader();
shader->set_graph(graph);
shader->tag_update((Scene *)_light->get_owner());
shader->has_surface_spatial_varying = hasSpatialVarying;
}
void HdCyclesLight::Finalize(HdRenderParam *renderParam)
{
if (!_light) {
return;
}
const SceneLock lock(renderParam);
lock.scene->delete_node(_light);
_light = nullptr;
}
void HdCyclesLight::Initialize(HdRenderParam *renderParam)
{
if (_light) {
return;
}
const SceneLock lock(renderParam);
_light = lock.scene->create_node<Light>();
_light->name = GetId().GetString();
_light->set_random_id(hash_uint2(hash_string(_light->name.c_str()), 0));
if (_lightType == HdPrimTypeTokens->domeLight) {
_light->set_light_type(LIGHT_BACKGROUND);
}
else if (_lightType == HdPrimTypeTokens->distantLight) {
_light->set_light_type(LIGHT_DISTANT);
}
else if (_lightType == HdPrimTypeTokens->diskLight) {
_light->set_light_type(LIGHT_AREA);
_light->set_round(true);
_light->set_size(1.0f);
}
else if (_lightType == HdPrimTypeTokens->rectLight) {
_light->set_light_type(LIGHT_AREA);
_light->set_round(false);
_light->set_size(1.0f);
}
else if (_lightType == HdPrimTypeTokens->sphereLight) {
_light->set_light_type(LIGHT_POINT);
_light->set_size(1.0f);
}
_light->set_use_mis(true);
_light->set_use_camera(false);
Shader *const shader = lock.scene->create_node<Shader>();
_light->set_shader(shader);
// Create default shader graph
PopulateShaderGraph(nullptr);
}
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,35 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#pragma once
#include "hydra/config.h"
#include <pxr/imaging/hd/light.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
class HdCyclesLight final : public PXR_NS::HdLight {
public:
HdCyclesLight(const PXR_NS::SdfPath &sprimId, const PXR_NS::TfToken &lightType);
~HdCyclesLight() override;
PXR_NS::HdDirtyBits GetInitialDirtyBitsMask() const override;
void Sync(PXR_NS::HdSceneDelegate *sceneDelegate,
PXR_NS::HdRenderParam *renderParam,
PXR_NS::HdDirtyBits *dirtyBits) override;
void Finalize(PXR_NS::HdRenderParam *renderParam) override;
private:
void Initialize(PXR_NS::HdRenderParam *renderParam);
void PopulateShaderGraph(PXR_NS::HdSceneDelegate *sceneDelegate);
CCL_NS::Light *_light = nullptr;
PXR_NS::TfToken _lightType;
};
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,584 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#include "hydra/material.h"
#include "hydra/node_util.h"
#include "hydra/session.h"
#include "scene/scene.h"
#include "scene/shader.h"
#include "scene/shader_graph.h"
#include "scene/shader_nodes.h"
#include <pxr/imaging/hd/sceneDelegate.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
// clang-format off
TF_DEFINE_PRIVATE_TOKENS(CyclesMaterialTokens,
((cyclesSurface, "cycles:surface"))
((cyclesDisplacement, "cycles:displacement"))
((cyclesVolume, "cycles:volume"))
(UsdPreviewSurface)
(UsdUVTexture)
(UsdPrimvarReader_float)
(UsdPrimvarReader_float2)
(UsdPrimvarReader_float3)
(UsdPrimvarReader_float4)
(UsdPrimvarReader_int)
(UsdTransform2d)
(a)
(rgb)
(r)
(g)
(b)
(result)
(st)
(wrapS)
(wrapT)
(periodic)
);
// clang-format on
// Simple class to handle remapping of USDPreviewSurface nodes and parameters to Cycles equivalents
class UsdToCyclesMapping {
using ParamMap = std::unordered_map<TfToken, ustring, TfToken::HashFunctor>;
public:
UsdToCyclesMapping(const char *nodeType, ParamMap paramMap)
: _nodeType(nodeType), _paramMap(std::move(paramMap))
{
}
ustring nodeType() const
{
return _nodeType;
}
virtual std::string parameterName(const TfToken &name,
const ShaderInput *inputConnection,
VtValue *value = nullptr) const
{
// UsdNode.name -> Node.input
// These all follow a simple pattern that we can just remap
// based on the name or 'Node.input' type
if (inputConnection) {
if (name == CyclesMaterialTokens->a) {
return "alpha";
}
if (name == CyclesMaterialTokens->rgb) {
return "color";
}
// TODO: Is there a better mapping than 'color'?
if (name == CyclesMaterialTokens->r || name == CyclesMaterialTokens->g ||
name == CyclesMaterialTokens->b) {
return "color";
}
if (name == CyclesMaterialTokens->result) {
switch (inputConnection->socket_type.type) {
case SocketType::BOOLEAN:
case SocketType::FLOAT:
case SocketType::INT:
case SocketType::UINT:
return "alpha";
case SocketType::COLOR:
case SocketType::VECTOR:
case SocketType::POINT:
case SocketType::NORMAL:
default:
return "color";
}
}
}
// Simple mapping case
const auto it = _paramMap.find(name);
return it != _paramMap.end() ? it->second.string() : name.GetString();
}
private:
const ustring _nodeType;
ParamMap _paramMap;
};
class UsdToCyclesTexture : public UsdToCyclesMapping {
public:
using UsdToCyclesMapping::UsdToCyclesMapping;
std::string parameterName(const TfToken &name,
const ShaderInput *inputConnection,
VtValue *value) const override
{
if (value) {
// Remap UsdUVTexture.wrapS and UsdUVTexture.wrapT to cycles_image_texture.extension
if (name == CyclesMaterialTokens->wrapS || name == CyclesMaterialTokens->wrapT) {
std::string valueString = VtValue::Cast<std::string>(*value).Get<std::string>();
// A value of 'repeat' in USD is equivalent to 'periodic' in Cycles
if (valueString == "repeat") {
*value = VtValue(CyclesMaterialTokens->periodic);
}
return "extension";
}
}
return UsdToCyclesMapping::parameterName(name, inputConnection, value);
}
};
namespace {
class UsdToCycles {
const UsdToCyclesMapping UsdPreviewSurface = {
"principled_bsdf",
{
{TfToken("diffuseColor"), ustring("base_color")},
{TfToken("emissiveColor"), ustring("emission")},
{TfToken("specularColor"), ustring("specular")},
{TfToken("clearcoatRoughness"), ustring("clearcoat_roughness")},
{TfToken("opacity"), ustring("alpha")},
// opacityThreshold
// occlusion
// displacement
}};
const UsdToCyclesTexture UsdUVTexture = {
"image_texture",
{
{CyclesMaterialTokens->st, ustring("vector")},
{CyclesMaterialTokens->wrapS, ustring("extension")},
{CyclesMaterialTokens->wrapT, ustring("extension")},
{TfToken("file"), ustring("filename")},
{TfToken("sourceColorSpace"), ustring("colorspace")},
}};
const UsdToCyclesMapping UsdPrimvarReader = {"attribute",
{{TfToken("varname"), ustring("attribute")}}};
public:
const UsdToCyclesMapping *findUsd(const TfToken &usdNodeType)
{
if (usdNodeType == CyclesMaterialTokens->UsdPreviewSurface) {
return &UsdPreviewSurface;
}
if (usdNodeType == CyclesMaterialTokens->UsdUVTexture) {
return &UsdUVTexture;
}
if (usdNodeType == CyclesMaterialTokens->UsdPrimvarReader_float ||
usdNodeType == CyclesMaterialTokens->UsdPrimvarReader_float2 ||
usdNodeType == CyclesMaterialTokens->UsdPrimvarReader_float3 ||
usdNodeType == CyclesMaterialTokens->UsdPrimvarReader_float4 ||
usdNodeType == CyclesMaterialTokens->UsdPrimvarReader_int) {
return &UsdPrimvarReader;
}
return nullptr;
}
const UsdToCyclesMapping *findCycles(const ustring &cyclesNodeType)
{
return nullptr;
}
};
TfStaticData<UsdToCycles> sUsdToCyles;
} // namespace
HdCyclesMaterial::HdCyclesMaterial(const SdfPath &sprimId) : HdMaterial(sprimId)
{
}
HdCyclesMaterial::~HdCyclesMaterial()
{
}
HdDirtyBits HdCyclesMaterial::GetInitialDirtyBitsMask() const
{
return DirtyBits::DirtyResource | DirtyBits::DirtyParams;
}
void HdCyclesMaterial::Sync(HdSceneDelegate *sceneDelegate,
HdRenderParam *renderParam,
HdDirtyBits *dirtyBits)
{
if (*dirtyBits == DirtyBits::Clean) {
return;
}
Initialize(renderParam);
const SceneLock lock(renderParam);
const bool dirtyParams = (*dirtyBits & DirtyBits::DirtyParams);
const bool dirtyResource = (*dirtyBits & DirtyBits::DirtyResource);
VtValue value;
const SdfPath &id = GetId();
if (dirtyResource || dirtyParams) {
value = sceneDelegate->GetMaterialResource(id);
#if 1
const HdMaterialNetwork2 *network = nullptr;
std::unique_ptr<HdMaterialNetwork2> networkConverted;
if (value.IsHolding<HdMaterialNetwork2>()) {
network = &value.UncheckedGet<HdMaterialNetwork2>();
}
else if (value.IsHolding<HdMaterialNetworkMap>()) {
const auto &networkOld = value.UncheckedGet<HdMaterialNetworkMap>();
// In the case of only parameter updates, there is no need to waste time converting to a
// HdMaterialNetwork2, as supporting HdMaterialNetworkMap for parameters only is trivial.
if (!_nodes.empty() && !dirtyResource) {
for (const auto &networkEntry : networkOld.map) {
UpdateParameters(networkEntry.second);
}
_shader->tag_modified();
}
else {
networkConverted = std::make_unique<HdMaterialNetwork2>();
HdMaterialNetwork2ConvertFromHdMaterialNetworkMap(networkOld, networkConverted.get());
network = networkConverted.get();
}
}
else {
TF_RUNTIME_ERROR("Could not get a HdMaterialNetwork2.");
}
if (network) {
if (!_nodes.empty() && !dirtyResource) {
UpdateParameters(*network);
_shader->tag_modified();
}
else {
PopulateShaderGraph(*network);
}
}
#endif
}
if (_shader->is_modified()) {
_shader->tag_update(lock.scene);
}
*dirtyBits = DirtyBits::Clean;
}
void HdCyclesMaterial::UpdateParameters(NodeDesc &nodeDesc,
const std::map<TfToken, VtValue> &parameters,
const SdfPath &nodePath)
{
for (const std::pair<TfToken, VtValue> &param : parameters) {
VtValue value = param.second;
// See if the parameter name is in USDPreviewSurface terms, and needs to be converted
const UsdToCyclesMapping *inputMapping = nodeDesc.mapping;
const std::string inputName = inputMapping ?
inputMapping->parameterName(param.first, nullptr, &value) :
param.first.GetString();
// Find the input to write the parameter value to
const SocketType *input = nullptr;
for (const SocketType &socket : nodeDesc.node->type->inputs) {
if (string_iequals(socket.name.string(), inputName) || socket.ui_name == inputName) {
input = &socket;
break;
}
}
if (!input) {
TF_WARN("Could not find parameter '%s' on node '%s' ('%s')",
param.first.GetText(),
nodePath.GetText(),
nodeDesc.node->name.c_str());
continue;
}
SetNodeValue(nodeDesc.node, *input, value);
}
}
void HdCyclesMaterial::UpdateParameters(const HdMaterialNetwork &network)
{
for (const HdMaterialNode &nodeEntry : network.nodes) {
const SdfPath &nodePath = nodeEntry.path;
const auto nodeIt = _nodes.find(nodePath);
if (nodeIt == _nodes.end()) {
TF_RUNTIME_ERROR("Could not update parameters on missing node '%s'", nodePath.GetText());
continue;
}
UpdateParameters(nodeIt->second, nodeEntry.parameters, nodePath);
}
}
void HdCyclesMaterial::UpdateParameters(const HdMaterialNetwork2 &network)
{
for (const std::pair<SdfPath, HdMaterialNode2> &nodeEntry : network.nodes) {
const SdfPath &nodePath = nodeEntry.first;
const auto nodeIt = _nodes.find(nodePath);
if (nodeIt == _nodes.end()) {
TF_RUNTIME_ERROR("Could not update parameters on missing node '%s'", nodePath.GetText());
continue;
}
UpdateParameters(nodeIt->second, nodeEntry.second.parameters, nodePath);
}
}
void HdCyclesMaterial::UpdateConnections(NodeDesc &nodeDesc,
const HdMaterialNode2 &matNode,
const SdfPath &nodePath,
ShaderGraph *shaderGraph)
{
for (const std::pair<TfToken, std::vector<HdMaterialConnection2>> &connection :
matNode.inputConnections) {
const TfToken &dstSocketName = connection.first;
const UsdToCyclesMapping *inputMapping = nodeDesc.mapping;
const std::string inputName = inputMapping ?
inputMapping->parameterName(dstSocketName, nullptr) :
dstSocketName.GetString();
// Find the input to connect to on the passed in node
ShaderInput *input = nullptr;
for (ShaderInput *in : nodeDesc.node->inputs) {
if (string_iequals(in->socket_type.name.string(), inputName)) {
input = in;
break;
}
}
if (!input) {
TF_WARN("Ignoring connection on '%s.%s', input '%s' was not found",
nodePath.GetText(),
dstSocketName.GetText(),
dstSocketName.GetText());
continue;
}
// Now find the output to connect from
const auto &connectedNodes = connection.second;
if (connectedNodes.empty()) {
continue;
}
// TODO: Hydra allows multiple connections of the same input
// Unsure how to handle this in Cycles, so just use the first
if (connectedNodes.size() > 1) {
TF_WARN(
"Ignoring multiple connections to '%s.%s'", nodePath.GetText(), dstSocketName.GetText());
}
const SdfPath &upstreamNodePath = connectedNodes.front().upstreamNode;
const TfToken &upstreamOutputName = connectedNodes.front().upstreamOutputName;
const auto srcNodeIt = _nodes.find(upstreamNodePath);
if (srcNodeIt == _nodes.end()) {
TF_WARN("Ignoring connection from '%s.%s' to '%s.%s', node '%s' was not found",
upstreamNodePath.GetText(),
upstreamOutputName.GetText(),
nodePath.GetText(),
dstSocketName.GetText(),
upstreamNodePath.GetText());
continue;
}
const UsdToCyclesMapping *outputMapping = srcNodeIt->second.mapping;
const std::string outputName = outputMapping ?
outputMapping->parameterName(upstreamOutputName, input) :
upstreamOutputName.GetString();
ShaderOutput *output = nullptr;
for (ShaderOutput *out : srcNodeIt->second.node->outputs) {
if (string_iequals(out->socket_type.name.string(), outputName)) {
output = out;
break;
}
}
if (!output) {
TF_WARN("Ignoring connection from '%s.%s' to '%s.%s', output '%s' was not found",
upstreamNodePath.GetText(),
upstreamOutputName.GetText(),
nodePath.GetText(),
dstSocketName.GetText(),
upstreamOutputName.GetText());
continue;
}
shaderGraph->connect(output, input);
}
}
void HdCyclesMaterial::PopulateShaderGraph(const HdMaterialNetwork2 &networkMap)
{
_nodes.clear();
auto graph = new ShaderGraph();
// Iterate all the nodes first and build a complete but unconnected graph with parameters set
for (const std::pair<SdfPath, HdMaterialNode2> &nodeEntry : networkMap.nodes) {
NodeDesc nodeDesc = {};
const SdfPath &nodePath = nodeEntry.first;
const auto nodeIt = _nodes.find(nodePath);
// Create new node only if it does not exist yet
if (nodeIt != _nodes.end()) {
nodeDesc = nodeIt->second;
}
else {
// E.g. cycles_principled_bsdf or UsdPreviewSurface
const std::string &nodeTypeId = nodeEntry.second.nodeTypeId.GetString();
ustring cyclesType(nodeTypeId);
// Interpret a node type ID prefixed with cycles_<type> or cycles:<type> as a node of <type>
if (nodeTypeId.rfind("cycles", 0) == 0) {
cyclesType = nodeTypeId.substr(7);
nodeDesc.mapping = sUsdToCyles->findCycles(cyclesType);
}
else {
// Check if any remapping is needed (e.g. for USDPreviewSurface to Cycles nodes)
nodeDesc.mapping = sUsdToCyles->findUsd(nodeEntry.second.nodeTypeId);
if (nodeDesc.mapping) {
cyclesType = nodeDesc.mapping->nodeType();
}
}
// If it's a native Cycles' node-type, just do the lookup now.
if (const NodeType *nodeType = NodeType::find(cyclesType)) {
nodeDesc.node = static_cast<ShaderNode *>(nodeType->create(nodeType));
nodeDesc.node->set_owner(graph);
graph->add(nodeDesc.node);
_nodes.emplace(nodePath, nodeDesc);
}
else {
TF_RUNTIME_ERROR("Could not create node '%s'", nodePath.GetText());
continue;
}
}
UpdateParameters(nodeDesc, nodeEntry.second.parameters, nodePath);
}
// Now that all nodes have been constructed, iterate the network again and build up any
// connections between nodes
for (const std::pair<SdfPath, HdMaterialNode2> &nodeEntry : networkMap.nodes) {
const SdfPath &nodePath = nodeEntry.first;
const auto nodeIt = _nodes.find(nodePath);
if (nodeIt == _nodes.end()) {
TF_RUNTIME_ERROR("Could not find node '%s' to connect", nodePath.GetText());
continue;
}
UpdateConnections(nodeIt->second, nodeEntry.second, nodePath, graph);
}
// Finally connect the terminals to the graph output (Surface, Volume, Displacement)
for (const std::pair<TfToken, HdMaterialConnection2> &terminalEntry : networkMap.terminals) {
const TfToken &terminalName = terminalEntry.first;
const HdMaterialConnection2 &connection = terminalEntry.second;
const auto nodeIt = _nodes.find(connection.upstreamNode);
if (nodeIt == _nodes.end()) {
TF_RUNTIME_ERROR("Could not find terminal node '%s'", connection.upstreamNode.GetText());
continue;
}
ShaderNode *const node = nodeIt->second.node;
const char *inputName = nullptr;
const char *outputName = nullptr;
if (terminalName == HdMaterialTerminalTokens->surface ||
terminalName == CyclesMaterialTokens->cyclesSurface) {
inputName = "Surface";
// Find default output name based on the node if none is provided
if (node->type->name == "add_closure" || node->type->name == "mix_closure") {
outputName = "Closure";
}
else if (node->type->name == "emission") {
outputName = "Emission";
}
else {
outputName = "BSDF";
}
}
else if (terminalName == HdMaterialTerminalTokens->displacement ||
terminalName == CyclesMaterialTokens->cyclesDisplacement) {
inputName = outputName = "Displacement";
}
else if (terminalName == HdMaterialTerminalTokens->volume ||
terminalName == CyclesMaterialTokens->cyclesVolume) {
inputName = outputName = "Volume";
}
if (!connection.upstreamOutputName.IsEmpty()) {
outputName = connection.upstreamOutputName.GetText();
}
ShaderInput *const input = inputName ? graph->output()->input(inputName) : nullptr;
if (!input) {
TF_RUNTIME_ERROR("Could not find terminal input '%s.%s'",
connection.upstreamNode.GetText(),
inputName ? inputName : "<null>");
continue;
}
ShaderOutput *const output = outputName ? node->output(outputName) : nullptr;
if (!output) {
TF_RUNTIME_ERROR("Could not find terminal output '%s.%s'",
connection.upstreamNode.GetText(),
outputName ? outputName : "<null>");
continue;
}
graph->connect(output, input);
}
// Create the instanceId AOV output
{
const ustring instanceId(HdAovTokens->instanceId.GetString());
OutputAOVNode *aovNode = graph->create_node<OutputAOVNode>();
aovNode->set_name(instanceId);
graph->add(aovNode);
AttributeNode *instanceIdNode = graph->create_node<AttributeNode>();
instanceIdNode->set_attribute(instanceId);
graph->add(instanceIdNode);
graph->connect(instanceIdNode->output("Fac"), aovNode->input("Value"));
}
_shader->set_graph(graph);
}
void HdCyclesMaterial::Finalize(HdRenderParam *renderParam)
{
if (!_shader) {
return;
}
const SceneLock lock(renderParam);
_nodes.clear();
lock.scene->delete_node(_shader);
_shader = nullptr;
}
void HdCyclesMaterial::Initialize(HdRenderParam *renderParam)
{
if (_shader) {
return;
}
const SceneLock lock(renderParam);
_shader = lock.scene->create_node<Shader>();
}
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,63 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#pragma once
#include "hydra/config.h"
#include <pxr/imaging/hd/material.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
class HdCyclesMaterial final : public PXR_NS::HdMaterial {
public:
HdCyclesMaterial(const PXR_NS::SdfPath &sprimId);
~HdCyclesMaterial() override;
PXR_NS::HdDirtyBits GetInitialDirtyBitsMask() const override;
void Sync(PXR_NS::HdSceneDelegate *sceneDelegate,
PXR_NS::HdRenderParam *renderParam,
PXR_NS::HdDirtyBits *dirtyBits) override;
#if PXR_VERSION < 2011
void Reload() override
{
}
#endif
void Finalize(PXR_NS::HdRenderParam *renderParam) override;
CCL_NS::Shader *GetCyclesShader() const
{
return _shader;
}
private:
struct NodeDesc {
CCL_NS::ShaderNode *node;
const class UsdToCyclesMapping *mapping;
};
void Initialize(PXR_NS::HdRenderParam *renderParam);
void UpdateParameters(NodeDesc &nodeDesc,
const std::map<PXR_NS::TfToken, PXR_NS::VtValue> &parameters,
const PXR_NS::SdfPath &nodePath);
void UpdateParameters(const PXR_NS::HdMaterialNetwork &network);
void UpdateParameters(const PXR_NS::HdMaterialNetwork2 &network);
void UpdateConnections(NodeDesc &nodeDesc,
const PXR_NS::HdMaterialNode2 &matNode,
const PXR_NS::SdfPath &nodePath,
CCL_NS::ShaderGraph *shaderGraph);
void PopulateShaderGraph(const PXR_NS::HdMaterialNetwork2 &network);
CCL_NS::Shader *_shader = nullptr;
std::unordered_map<PXR_NS::SdfPath, NodeDesc, PXR_NS::SdfPath::Hash> _nodes;
};
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,524 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#include "hydra/mesh.h"
#include "hydra/geometry.inl"
#include "scene/mesh.h"
#include <pxr/base/gf/vec2f.h>
#include <pxr/imaging/hd/extComputationUtils.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
namespace {
template<typename T>
VtValue ComputeTriangulatedUniformPrimvar(VtValue value, const VtIntArray &primitiveParams)
{
T output;
output.reserve(primitiveParams.size());
const T &input = value.Get<T>();
for (size_t i = 0; i < primitiveParams.size(); ++i) {
const int faceIndex = HdMeshUtil::DecodeFaceIndexFromCoarseFaceParam(primitiveParams[i]);
output.push_back(input[faceIndex]);
}
return VtValue(output);
}
VtValue ComputeTriangulatedUniformPrimvar(VtValue value,
const HdType valueType,
const VtIntArray &primitiveParams)
{
switch (valueType) {
case HdTypeFloat:
return ComputeTriangulatedUniformPrimvar<VtFloatArray>(value, primitiveParams);
case HdTypeFloatVec2:
return ComputeTriangulatedUniformPrimvar<VtVec2fArray>(value, primitiveParams);
case HdTypeFloatVec3:
return ComputeTriangulatedUniformPrimvar<VtVec3fArray>(value, primitiveParams);
case HdTypeFloatVec4:
return ComputeTriangulatedUniformPrimvar<VtVec4fArray>(value, primitiveParams);
default:
TF_RUNTIME_ERROR("Unsupported attribute type %d", static_cast<int>(valueType));
return VtValue();
}
}
VtValue ComputeTriangulatedFaceVaryingPrimvar(VtValue value,
const HdType valueType,
HdMeshUtil &meshUtil)
{
if (meshUtil.ComputeTriangulatedFaceVaryingPrimvar(
HdGetValueData(value), value.GetArraySize(), valueType, &value)) {
return value;
}
return VtValue();
}
} // namespace
Transform convert_transform(const GfMatrix4d &matrix)
{
return make_transform(matrix[0][0],
matrix[1][0],
matrix[2][0],
matrix[3][0],
matrix[0][1],
matrix[1][1],
matrix[2][1],
matrix[3][1],
matrix[0][2],
matrix[1][2],
matrix[2][2],
matrix[3][2]);
}
HdCyclesMesh::HdCyclesMesh(const SdfPath &rprimId
#if PXR_VERSION < 2102
,
const SdfPath &instancerId
#endif
)
: HdCyclesGeometry(rprimId
#if PXR_VERSION < 2102
,
instancerId
#endif
),
_util(&_topology, rprimId)
{
}
HdCyclesMesh::~HdCyclesMesh()
{
}
HdDirtyBits HdCyclesMesh::GetInitialDirtyBitsMask() const
{
HdDirtyBits bits = HdCyclesGeometry::GetInitialDirtyBitsMask();
bits |= HdChangeTracker::DirtyPoints | HdChangeTracker::DirtyNormals |
HdChangeTracker::DirtyPrimvar | HdChangeTracker::DirtyTopology |
HdChangeTracker::DirtyDisplayStyle | HdChangeTracker::DirtySubdivTags;
return bits;
}
HdDirtyBits HdCyclesMesh::_PropagateDirtyBits(HdDirtyBits bits) const
{
if (bits & (HdChangeTracker::DirtyMaterialId)) {
// Update used shaders from geometry subsets if any exist in the topology
bits |= HdChangeTracker::DirtyTopology;
}
if (bits & (HdChangeTracker::DirtyTopology | HdChangeTracker::DirtyDisplayStyle |
HdChangeTracker::DirtySubdivTags)) {
// Do full topology update when display style or subdivision changes
bits |= HdChangeTracker::DirtyTopology | HdChangeTracker::DirtyDisplayStyle |
HdChangeTracker::DirtySubdivTags;
}
if (bits & (HdChangeTracker::DirtyTopology)) {
// Changing topology clears the geometry, so need to populate everything again
bits |= HdChangeTracker::DirtyPoints | HdChangeTracker::DirtyNormals |
HdChangeTracker::DirtyPrimvar;
}
return bits;
}
void HdCyclesMesh::Populate(HdSceneDelegate *sceneDelegate, HdDirtyBits dirtyBits, bool &rebuild)
{
if (HdChangeTracker::IsTopologyDirty(dirtyBits, GetId())) {
PopulateTopology(sceneDelegate);
}
if (dirtyBits & HdChangeTracker::DirtyPoints) {
PopulatePoints(sceneDelegate);
}
// Must happen after topology update, so that normals attribute size can be calculated
if (dirtyBits & HdChangeTracker::DirtyNormals) {
PopulateNormals(sceneDelegate);
}
// Must happen after topology update, so that appropriate attribute set can be selected
if (dirtyBits & HdChangeTracker::DirtyPrimvar) {
PopulatePrimvars(sceneDelegate);
}
rebuild = (_geom->triangles_is_modified()) || (_geom->subd_start_corner_is_modified()) ||
(_geom->subd_num_corners_is_modified()) || (_geom->subd_shader_is_modified()) ||
(_geom->subd_smooth_is_modified()) || (_geom->subd_ptex_offset_is_modified()) ||
(_geom->subd_face_corners_is_modified());
}
void HdCyclesMesh::PopulatePoints(HdSceneDelegate *sceneDelegate)
{
VtValue value;
for (const HdExtComputationPrimvarDescriptor &desc :
sceneDelegate->GetExtComputationPrimvarDescriptors(GetId(), HdInterpolationVertex)) {
if (desc.name == HdTokens->points) {
auto valueStore = HdExtComputationUtils::GetComputedPrimvarValues({desc}, sceneDelegate);
const auto valueStoreIt = valueStore.find(desc.name);
if (valueStoreIt != valueStore.end()) {
value = std::move(valueStoreIt->second);
}
break;
}
}
if (value.IsEmpty()) {
value = GetPoints(sceneDelegate);
}
if (!value.IsHolding<VtVec3fArray>()) {
TF_WARN("Invalid points data for %s", GetId().GetText());
return;
}
const auto &points = value.UncheckedGet<VtVec3fArray>();
TF_VERIFY(points.size() >= static_cast<size_t>(_topology.GetNumPoints()));
array<float3> pointsDataCycles;
pointsDataCycles.reserve(points.size());
for (const GfVec3f &point : points) {
pointsDataCycles.push_back_reserved(make_float3(point[0], point[1], point[2]));
}
_geom->set_verts(pointsDataCycles);
}
void HdCyclesMesh::PopulateNormals(HdSceneDelegate *sceneDelegate)
{
_geom->attributes.remove(ATTR_STD_FACE_NORMAL);
_geom->attributes.remove(ATTR_STD_VERTEX_NORMAL);
// Authored normals should only exist on triangle meshes
if (_geom->get_subdivision_type() != Mesh::SUBDIVISION_NONE) {
return;
}
VtValue value;
HdInterpolation interpolation = HdInterpolationCount;
for (int i = 0; i < HdInterpolationCount && interpolation == HdInterpolationCount; ++i) {
for (const HdExtComputationPrimvarDescriptor &desc :
sceneDelegate->GetExtComputationPrimvarDescriptors(GetId(),
static_cast<HdInterpolation>(i))) {
if (desc.name == HdTokens->normals) {
auto valueStore = HdExtComputationUtils::GetComputedPrimvarValues({desc}, sceneDelegate);
const auto valueStoreIt = valueStore.find(desc.name);
if (valueStoreIt != valueStore.end()) {
value = std::move(valueStoreIt->second);
interpolation = static_cast<HdInterpolation>(i);
}
break;
}
}
}
if (value.IsEmpty()) {
interpolation = GetPrimvarInterpolation(sceneDelegate, HdTokens->normals);
if (interpolation == HdInterpolationCount) {
return; // Ignore missing normals
}
value = GetNormals(sceneDelegate);
}
if (!value.IsHolding<VtVec3fArray>()) {
TF_WARN("Invalid normals data for %s", GetId().GetText());
return;
}
const auto &normals = value.UncheckedGet<VtVec3fArray>();
if (interpolation == HdInterpolationConstant) {
TF_VERIFY(normals.size() == 1);
const GfVec3f constantNormal = normals[0];
float3 *const N = _geom->attributes.add(ATTR_STD_VERTEX_NORMAL)->data_float3();
for (size_t i = 0; i < _geom->get_verts().size(); ++i) {
N[i] = make_float3(constantNormal[0], constantNormal[1], constantNormal[2]);
}
}
else if (interpolation == HdInterpolationUniform) {
TF_VERIFY(normals.size() == static_cast<size_t>(_topology.GetNumFaces()));
float3 *const N = _geom->attributes.add(ATTR_STD_FACE_NORMAL)->data_float3();
for (size_t i = 0; i < _geom->num_triangles(); ++i) {
const int faceIndex = HdMeshUtil::DecodeFaceIndexFromCoarseFaceParam(_primitiveParams[i]);
N[i] = make_float3(normals[faceIndex][0], normals[faceIndex][1], normals[faceIndex][2]);
}
}
else if (interpolation == HdInterpolationVertex || interpolation == HdInterpolationVarying) {
TF_VERIFY(normals.size() == static_cast<size_t>(_topology.GetNumPoints()) &&
static_cast<size_t>(_topology.GetNumPoints()) == _geom->get_verts().size());
float3 *const N = _geom->attributes.add(ATTR_STD_VERTEX_NORMAL)->data_float3();
for (size_t i = 0; i < _geom->get_verts().size(); ++i) {
N[i] = make_float3(normals[i][0], normals[i][1], normals[i][2]);
}
}
else if (interpolation == HdInterpolationFaceVarying) {
TF_VERIFY(normals.size() == static_cast<size_t>(_topology.GetNumFaceVaryings()));
if (!_util.ComputeTriangulatedFaceVaryingPrimvar(
normals.data(), normals.size(), HdTypeFloatVec3, &value)) {
return;
}
const auto &normalsTriangulated = value.UncheckedGet<VtVec3fArray>();
// Cycles has no standard attribute for face-varying normals, so this is a lossy transformation
float3 *const N = _geom->attributes.add(ATTR_STD_FACE_NORMAL)->data_float3();
for (size_t i = 0; i < _geom->num_triangles(); ++i) {
GfVec3f averageNormal = normalsTriangulated[i * 3] + normalsTriangulated[i * 3 + 1] +
normalsTriangulated[i * 3 + 2];
GfNormalize(&averageNormal);
N[i] = make_float3(averageNormal[0], averageNormal[1], averageNormal[2]);
}
}
}
void HdCyclesMesh::PopulatePrimvars(HdSceneDelegate *sceneDelegate)
{
Scene *const scene = (Scene *)_geom->get_owner();
const bool subdivision = _geom->get_subdivision_type() != Mesh::SUBDIVISION_NONE;
AttributeSet &attributes = subdivision ? _geom->subd_attributes : _geom->attributes;
const std::pair<HdInterpolation, AttributeElement> interpolations[] = {
std::make_pair(HdInterpolationFaceVarying, ATTR_ELEMENT_CORNER),
std::make_pair(HdInterpolationUniform, ATTR_ELEMENT_FACE),
std::make_pair(HdInterpolationVertex, ATTR_ELEMENT_VERTEX),
std::make_pair(HdInterpolationVarying, ATTR_ELEMENT_VERTEX),
std::make_pair(HdInterpolationConstant, ATTR_ELEMENT_OBJECT),
};
for (const auto &interpolation : interpolations) {
for (const HdPrimvarDescriptor &desc :
GetPrimvarDescriptors(sceneDelegate, interpolation.first)) {
// Skip special primvars that are handled separately
if (desc.name == HdTokens->points || desc.name == HdTokens->normals) {
continue;
}
VtValue value = GetPrimvar(sceneDelegate, desc.name);
if (value.IsEmpty()) {
continue;
}
const ustring name(desc.name.GetString());
AttributeStandard std = ATTR_STD_NONE;
if (desc.role == HdPrimvarRoleTokens->textureCoordinate) {
std = ATTR_STD_UV;
}
else if (interpolation.first == HdInterpolationVertex) {
if (desc.name == HdTokens->displayColor || desc.role == HdPrimvarRoleTokens->color) {
std = ATTR_STD_VERTEX_COLOR;
}
else if (desc.name == HdTokens->normals) {
std = ATTR_STD_VERTEX_NORMAL;
}
}
else if (desc.name == HdTokens->displayColor &&
interpolation.first == HdInterpolationConstant) {
if (value.IsHolding<VtVec3fArray>() && value.GetArraySize() == 1) {
const GfVec3f color = value.UncheckedGet<VtVec3fArray>()[0];
_instances[0]->set_color(make_float3(color[0], color[1], color[2]));
}
}
// Skip attributes that are not needed
if ((std != ATTR_STD_NONE && _geom->need_attribute(scene, std)) ||
_geom->need_attribute(scene, name)) {
const HdType valueType = HdGetValueTupleType(value).type;
if (!subdivision) {
// Adjust attributes for polygons that were triangulated
if (interpolation.first == HdInterpolationUniform) {
value = ComputeTriangulatedUniformPrimvar(value, valueType, _primitiveParams);
if (value.IsEmpty()) {
continue;
}
}
else if (interpolation.first == HdInterpolationFaceVarying) {
value = ComputeTriangulatedFaceVaryingPrimvar(value, valueType, _util);
if (value.IsEmpty()) {
continue;
}
}
}
ApplyPrimvars(attributes, name, value, interpolation.second, std);
}
}
}
}
void HdCyclesMesh::PopulateTopology(HdSceneDelegate *sceneDelegate)
{
// Clear geometry before populating it again with updated topology
_geom->clear(true);
const HdDisplayStyle displayStyle = GetDisplayStyle(sceneDelegate);
_topology = HdMeshTopology(GetMeshTopology(sceneDelegate), displayStyle.refineLevel);
const TfToken subdivScheme = _topology.GetScheme();
if (subdivScheme == PxOsdOpenSubdivTokens->bilinear && _topology.GetRefineLevel() > 0) {
_geom->set_subdivision_type(Mesh::SUBDIVISION_LINEAR);
}
else if (subdivScheme == PxOsdOpenSubdivTokens->catmullClark && _topology.GetRefineLevel() > 0) {
_geom->set_subdivision_type(Mesh::SUBDIVISION_CATMULL_CLARK);
}
else {
_geom->set_subdivision_type(Mesh::SUBDIVISION_NONE);
}
const bool smooth = !displayStyle.flatShadingEnabled;
const bool subdivision = _geom->get_subdivision_type() != Mesh::SUBDIVISION_NONE;
// Initialize lookup table from polygon face to material shader index
VtIntArray faceShaders(_topology.GetNumFaces(), 0);
HdGeomSubsets const &geomSubsets = _topology.GetGeomSubsets();
if (!geomSubsets.empty()) {
array<Node *> usedShaders = std::move(_geom->get_used_shaders());
// Remove any previous materials except for the material assigned to the prim
usedShaders.resize(1);
std::unordered_map<SdfPath, int, SdfPath::Hash> materials;
for (const HdGeomSubset &geomSubset : geomSubsets) {
TF_VERIFY(geomSubset.type == HdGeomSubset::TypeFaceSet);
int shader = 0;
const auto it = materials.find(geomSubset.materialId);
if (it != materials.end()) {
shader = it->second;
}
else {
const auto material = static_cast<const HdCyclesMaterial *>(
sceneDelegate->GetRenderIndex().GetSprim(HdPrimTypeTokens->material,
geomSubset.materialId));
if (material && material->GetCyclesShader()) {
shader = static_cast<int>(usedShaders.size());
usedShaders.push_back_slow(material->GetCyclesShader());
materials.emplace(geomSubset.materialId, shader);
}
}
for (int face : geomSubset.indices) {
faceShaders[face] = shader;
}
}
_geom->set_used_shaders(usedShaders);
}
const VtIntArray vertIndx = _topology.GetFaceVertexIndices();
const VtIntArray vertCounts = _topology.GetFaceVertexCounts();
if (!subdivision) {
VtVec3iArray triangles;
_util.ComputeTriangleIndices(&triangles, &_primitiveParams);
_geom->reserve_mesh(_topology.GetNumPoints(), triangles.size());
for (size_t i = 0; i < _primitiveParams.size(); ++i) {
const int faceIndex = HdMeshUtil::DecodeFaceIndexFromCoarseFaceParam(_primitiveParams[i]);
const GfVec3i triangle = triangles[i];
_geom->add_triangle(triangle[0], triangle[1], triangle[2], faceShaders[faceIndex], smooth);
}
}
else {
PxOsdSubdivTags subdivTags = GetSubdivTags(sceneDelegate);
_topology.SetSubdivTags(subdivTags);
size_t numNgons = 0;
size_t numCorners = 0;
for (int vertCount : vertCounts) {
numNgons += (vertCount == 4) ? 0 : 1;
numCorners += vertCount;
}
_geom->reserve_subd_faces(_topology.GetNumFaces(), numNgons, numCorners);
// TODO: Handle hole indices
size_t faceIndex = 0;
size_t indexOffset = 0;
for (int vertCount : vertCounts) {
_geom->add_subd_face(&vertIndx[indexOffset], vertCount, faceShaders[faceIndex], smooth);
faceIndex++;
indexOffset += vertCount;
}
const VtIntArray creaseLengths = subdivTags.GetCreaseLengths();
if (!creaseLengths.empty()) {
size_t numCreases = 0;
for (int creaseLength : creaseLengths) {
numCreases += creaseLength - 1;
}
_geom->reserve_subd_creases(numCreases);
const VtIntArray creaseIndices = subdivTags.GetCreaseIndices();
const VtFloatArray creaseWeights = subdivTags.GetCreaseWeights();
indexOffset = 0;
size_t creaseLengthOffset = 0;
size_t createWeightOffset = 0;
for (int creaseLength : creaseLengths) {
for (int j = 0; j < creaseLength - 1; ++j, ++createWeightOffset) {
const int v0 = creaseIndices[indexOffset + j];
const int v1 = creaseIndices[indexOffset + j + 1];
float weight = creaseWeights.size() == creaseLengths.size() ?
creaseWeights[creaseLengthOffset] :
creaseWeights[createWeightOffset];
_geom->add_edge_crease(v0, v1, weight);
}
indexOffset += creaseLength;
creaseLengthOffset++;
}
const VtIntArray cornerIndices = subdivTags.GetCornerIndices();
const VtFloatArray cornerWeights = subdivTags.GetCornerWeights();
for (size_t i = 0; i < cornerIndices.size(); ++i) {
_geom->add_vertex_crease(cornerIndices[i], cornerWeights[i]);
}
}
_geom->set_subd_dicing_rate(1.0f);
_geom->set_subd_max_level(_topology.GetRefineLevel());
_geom->set_subd_objecttoworld(_instances[0]->get_tfm());
}
}
void HdCyclesMesh::Finalize(PXR_NS::HdRenderParam *renderParam)
{
_topology = HdMeshTopology();
_primitiveParams.clear();
HdCyclesGeometry<PXR_NS::HdMesh, Mesh>::Finalize(renderParam);
}
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,49 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#pragma once
#include "hydra/config.h"
#include "hydra/geometry.h"
#include <pxr/imaging/hd/mesh.h>
#include <pxr/imaging/hd/meshUtil.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
class HdCyclesMesh final : public HdCyclesGeometry<PXR_NS::HdMesh, CCL_NS::Mesh> {
public:
HdCyclesMesh(
const PXR_NS::SdfPath &rprimId
#if PXR_VERSION < 2102
,
const PXR_NS::SdfPath &instancerId = {}
#endif
);
~HdCyclesMesh() override;
PXR_NS::HdDirtyBits GetInitialDirtyBitsMask() const override;
void Finalize(PXR_NS::HdRenderParam *renderParam) override;
private:
PXR_NS::HdDirtyBits _PropagateDirtyBits(PXR_NS::HdDirtyBits bits) const override;
void Populate(PXR_NS::HdSceneDelegate *sceneDelegate,
PXR_NS::HdDirtyBits dirtyBits,
bool &rebuild) override;
void PopulatePoints(PXR_NS::HdSceneDelegate *sceneDelegate);
void PopulateNormals(PXR_NS::HdSceneDelegate *sceneDelegate);
void PopulatePrimvars(PXR_NS::HdSceneDelegate *sceneDelegate);
void PopulateTopology(PXR_NS::HdSceneDelegate *sceneDelegate);
PXR_NS::HdMeshUtil _util;
PXR_NS::HdMeshTopology _topology;
PXR_NS::VtIntArray _primitiveParams;
};
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,561 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#include "hydra/node_util.h"
#include "util/transform.h"
#include <pxr/base/gf/matrix3d.h>
#include <pxr/base/gf/matrix3f.h>
#include <pxr/base/gf/matrix4d.h>
#include <pxr/base/gf/matrix4f.h>
#include <pxr/base/gf/vec2f.h>
#include <pxr/base/gf/vec3f.h>
#include <pxr/base/vt/array.h>
#include <pxr/usd/sdf/assetPath.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
namespace {
template<typename DstType> DstType convertToCycles(const VtValue &value)
{
if (value.IsHolding<DstType>()) {
return value.UncheckedGet<DstType>();
}
VtValue castedValue = VtValue::Cast<DstType>(value);
if (castedValue.IsHolding<DstType>()) {
return castedValue.UncheckedGet<DstType>();
}
TF_WARN("Could not convert VtValue to Cycles type");
return DstType(0);
}
template<> float2 convertToCycles<float2>(const VtValue &value)
{
const GfVec2f convertedValue = convertToCycles<GfVec2f>(value);
return make_float2(convertedValue[0], convertedValue[1]);
}
template<> float3 convertToCycles<float3>(const VtValue &value)
{
if (value.IsHolding<GfVec3f>()) {
const GfVec3f convertedValue = value.UncheckedGet<GfVec3f>();
return make_float3(convertedValue[0], convertedValue[1], convertedValue[2]);
}
if (value.IsHolding<GfVec4f>()) {
const GfVec4f convertedValue = value.UncheckedGet<GfVec4f>();
return make_float3(convertedValue[0], convertedValue[1], convertedValue[2]);
}
if (value.CanCast<GfVec3f>()) {
const GfVec3f convertedValue = VtValue::Cast<GfVec3f>(value).UncheckedGet<GfVec3f>();
return make_float3(convertedValue[0], convertedValue[1], convertedValue[2]);
}
if (value.CanCast<GfVec4f>()) {
const GfVec4f convertedValue = VtValue::Cast<GfVec4f>(value).UncheckedGet<GfVec4f>();
return make_float3(convertedValue[0], convertedValue[1], convertedValue[2]);
}
TF_WARN("Could not convert VtValue to float3");
return zero_float3();
}
template<> ustring convertToCycles<ustring>(const VtValue &value)
{
if (value.IsHolding<TfToken>()) {
return ustring(value.UncheckedGet<TfToken>().GetString());
}
if (value.IsHolding<std::string>()) {
return ustring(value.UncheckedGet<std::string>());
}
if (value.IsHolding<SdfAssetPath>()) {
const SdfAssetPath &path = value.UncheckedGet<SdfAssetPath>();
return ustring(path.GetResolvedPath());
}
if (value.CanCast<TfToken>()) {
return convertToCycles<ustring>(VtValue::Cast<TfToken>(value));
}
if (value.CanCast<std::string>()) {
return convertToCycles<ustring>(VtValue::Cast<std::string>(value));
}
if (value.CanCast<SdfAssetPath>()) {
return convertToCycles<ustring>(VtValue::Cast<SdfAssetPath>(value));
}
TF_WARN("Could not convert VtValue to ustring");
return ustring();
}
template<typename Matrix>
Transform convertMatrixToCycles(
const typename std::enable_if<Matrix::numRows == 3 && Matrix::numColumns == 3, Matrix>::type
&matrix)
{
return make_transform(matrix[0][0],
matrix[1][0],
matrix[2][0],
0,
matrix[0][1],
matrix[1][1],
matrix[2][1],
0,
matrix[0][2],
matrix[1][2],
matrix[2][2],
0);
}
template<typename Matrix>
Transform convertMatrixToCycles(
const typename std::enable_if<Matrix::numRows == 4 && Matrix::numColumns == 4, Matrix>::type
&matrix)
{
return make_transform(matrix[0][0],
matrix[1][0],
matrix[2][0],
matrix[3][0],
matrix[0][1],
matrix[1][1],
matrix[2][1],
matrix[3][1],
matrix[0][2],
matrix[1][2],
matrix[2][2],
matrix[3][2]);
}
template<> Transform convertToCycles<Transform>(const VtValue &value)
{
if (value.IsHolding<GfMatrix4f>()) {
return convertMatrixToCycles<GfMatrix4f>(value.UncheckedGet<GfMatrix4f>());
}
if (value.IsHolding<GfMatrix3f>()) {
return convertMatrixToCycles<GfMatrix3f>(value.UncheckedGet<GfMatrix3f>());
}
if (value.IsHolding<GfMatrix4d>()) {
return convertMatrixToCycles<GfMatrix4d>(value.UncheckedGet<GfMatrix4d>());
}
if (value.IsHolding<GfMatrix3d>()) {
return convertMatrixToCycles<GfMatrix3d>(value.UncheckedGet<GfMatrix3d>());
}
if (value.CanCast<GfMatrix4f>()) {
return convertToCycles<Transform>(VtValue::Cast<GfMatrix4f>(value));
}
if (value.CanCast<GfMatrix3f>()) {
return convertToCycles<Transform>(VtValue::Cast<GfMatrix3f>(value));
}
if (value.CanCast<GfMatrix4d>()) {
return convertToCycles<Transform>(VtValue::Cast<GfMatrix4d>(value));
}
if (value.CanCast<GfMatrix3d>()) {
return convertToCycles<Transform>(VtValue::Cast<GfMatrix3d>(value));
}
TF_WARN("Could not convert VtValue to Transform");
return transform_identity();
}
template<typename DstType, typename SrcType = DstType>
array<DstType> convertToCyclesArray(const VtValue &value)
{
static_assert(sizeof(DstType) == sizeof(SrcType),
"Size mismatch between VtArray and array base type");
using SrcArray = VtArray<SrcType>;
if (value.IsHolding<SrcArray>()) {
const auto &valueData = value.UncheckedGet<SrcArray>();
array<DstType> cyclesArray;
cyclesArray.resize(valueData.size());
std::memcpy(cyclesArray.data(), valueData.data(), valueData.size() * sizeof(DstType));
return cyclesArray;
}
if (value.CanCast<SrcArray>()) {
VtValue castedValue = VtValue::Cast<SrcArray>(value);
const auto &valueData = castedValue.UncheckedGet<SrcArray>();
array<DstType> cyclesArray;
cyclesArray.resize(valueData.size());
std::memcpy(cyclesArray.data(), valueData.data(), valueData.size() * sizeof(DstType));
return cyclesArray;
}
return array<DstType>();
}
template<> array<float3> convertToCyclesArray<float3, GfVec3f>(const VtValue &value)
{
if (value.IsHolding<VtVec3fArray>()) {
const auto &valueData = value.UncheckedGet<VtVec3fArray>();
array<float3> cyclesArray;
cyclesArray.reserve(valueData.size());
for (const GfVec3f &vec : valueData) {
cyclesArray.push_back_reserved(make_float3(vec[0], vec[1], vec[2]));
}
return cyclesArray;
}
if (value.IsHolding<VtVec4fArray>()) {
const auto &valueData = value.UncheckedGet<VtVec4fArray>();
array<float3> cyclesArray;
cyclesArray.reserve(valueData.size());
for (const GfVec4f &vec : valueData) {
cyclesArray.push_back_reserved(make_float3(vec[0], vec[1], vec[2]));
}
return cyclesArray;
}
if (value.CanCast<VtVec3fArray>()) {
return convertToCyclesArray<float3, GfVec3f>(VtValue::Cast<VtVec3fArray>(value));
}
if (value.CanCast<VtVec4fArray>()) {
return convertToCyclesArray<float3, GfVec3f>(VtValue::Cast<VtVec4fArray>(value));
}
return array<float3>();
}
template<> array<ustring> convertToCyclesArray<ustring, void>(const VtValue &value)
{
using SdfPathArray = VtArray<SdfAssetPath>;
if (value.IsHolding<VtStringArray>()) {
const auto &valueData = value.UncheckedGet<VtStringArray>();
array<ustring> cyclesArray;
cyclesArray.reserve(valueData.size());
for (const auto &element : valueData) {
cyclesArray.push_back_reserved(ustring(element));
}
return cyclesArray;
}
if (value.IsHolding<VtTokenArray>()) {
const auto &valueData = value.UncheckedGet<VtTokenArray>();
array<ustring> cyclesArray;
cyclesArray.reserve(valueData.size());
for (const auto &element : valueData) {
cyclesArray.push_back_reserved(ustring(element.GetString()));
}
return cyclesArray;
}
if (value.IsHolding<SdfPathArray>()) {
const auto &valueData = value.UncheckedGet<SdfPathArray>();
array<ustring> cyclesArray;
cyclesArray.reserve(valueData.size());
for (const auto &element : valueData) {
cyclesArray.push_back_reserved(ustring(element.GetResolvedPath()));
}
return cyclesArray;
}
if (value.CanCast<VtStringArray>()) {
return convertToCyclesArray<ustring, void>(VtValue::Cast<VtStringArray>(value));
}
if (value.CanCast<VtTokenArray>()) {
return convertToCyclesArray<ustring, void>(VtValue::Cast<VtTokenArray>(value));
}
if (value.CanCast<SdfPathArray>()) {
return convertToCyclesArray<ustring, void>(VtValue::Cast<SdfPathArray>(value));
}
TF_WARN("Could not convert VtValue to array<ustring>");
return array<ustring>();
}
template<typename MatrixArray> array<Transform> convertToCyclesTransformArray(const VtValue &value)
{
assert(value.IsHolding<MatrixArray>());
const auto &valueData = value.UncheckedGet<MatrixArray>();
array<Transform> cyclesArray;
cyclesArray.reserve(valueData.size());
for (const auto &element : valueData) {
cyclesArray.push_back_reserved(convertMatrixToCycles<typename MatrixArray::value_type>(element));
}
return cyclesArray;
}
template<> array<Transform> convertToCyclesArray<Transform, void>(const VtValue &value)
{
if (value.IsHolding<VtMatrix4fArray>()) {
return convertToCyclesTransformArray<VtMatrix4fArray>(value);
}
if (value.IsHolding<VtMatrix3fArray>()) {
return convertToCyclesTransformArray<VtMatrix3fArray>(value);
}
if (value.IsHolding<VtMatrix4dArray>()) {
return convertToCyclesTransformArray<VtMatrix4dArray>(value);
}
if (value.IsHolding<VtMatrix3dArray>()) {
return convertToCyclesTransformArray<VtMatrix3dArray>(value);
}
if (value.CanCast<VtMatrix4fArray>()) {
return convertToCyclesTransformArray<VtMatrix4fArray>(VtValue::Cast<VtMatrix4fArray>(value));
}
if (value.CanCast<VtMatrix3fArray>()) {
return convertToCyclesTransformArray<VtMatrix3fArray>(VtValue::Cast<VtMatrix3fArray>(value));
}
if (value.CanCast<VtMatrix4dArray>()) {
return convertToCyclesTransformArray<VtMatrix4dArray>(VtValue::Cast<VtMatrix4dArray>(value));
}
if (value.CanCast<VtMatrix3dArray>()) {
return convertToCyclesTransformArray<VtMatrix3dArray>(VtValue::Cast<VtMatrix3dArray>(value));
}
TF_WARN("Could not convert VtValue to array<Transform>");
return array<Transform>();
}
template<typename SrcType> VtValue convertFromCycles(const SrcType &value)
{
return VtValue(value);
}
template<> VtValue convertFromCycles<float2>(const float2 &value)
{
const GfVec2f convertedValue(value.x, value.y);
return VtValue(convertedValue);
}
template<> VtValue convertFromCycles<float3>(const float3 &value)
{
const GfVec3f convertedValue(value.x, value.y, value.z);
return VtValue(convertedValue);
}
template<> VtValue convertFromCycles<ustring>(const ustring &value)
{
return VtValue(value.string());
}
GfMatrix4f convertMatrixFromCycles(const Transform &matrix)
{
return GfMatrix4f(matrix[0][0],
matrix[1][0],
matrix[2][0],
0.0f,
matrix[0][1],
matrix[1][1],
matrix[2][1],
0.0f,
matrix[0][2],
matrix[1][2],
matrix[2][2],
0.0f,
0.0f,
0.0f,
0.0f,
1.0f);
}
template<> VtValue convertFromCycles<Transform>(const Transform &value)
{
return VtValue(convertMatrixFromCycles(value));
}
template<typename SrcType, typename DstType = SrcType>
VtValue convertFromCyclesArray(const array<SrcType> &value)
{
static_assert(sizeof(DstType) == sizeof(SrcType),
"Size mismatch between VtArray and array base type");
VtArray<DstType> convertedValue;
convertedValue.resize(value.size());
std::memcpy(convertedValue.data(), value.data(), value.size() * sizeof(SrcType));
return VtValue(convertedValue);
}
template<> VtValue convertFromCyclesArray<float3, GfVec3f>(const array<float3> &value)
{
VtVec3fArray convertedValue;
convertedValue.reserve(value.size());
for (const auto &element : value) {
convertedValue.push_back(GfVec3f(element.x, element.y, element.z));
}
return VtValue(convertedValue);
}
template<> VtValue convertFromCyclesArray<ustring, void>(const array<ustring> &value)
{
VtStringArray convertedValue;
convertedValue.reserve(value.size());
for (const auto &element : value) {
convertedValue.push_back(element.string());
}
return VtValue(convertedValue);
}
template<> VtValue convertFromCyclesArray<Transform, void>(const array<Transform> &value)
{
VtMatrix4fArray convertedValue;
convertedValue.reserve(value.size());
for (const auto &element : value) {
convertedValue.push_back(convertMatrixFromCycles(element));
}
return VtValue(convertedValue);
}
} // namespace
void SetNodeValue(Node *node, const SocketType &socket, const VtValue &value)
{
switch (socket.type) {
default:
case SocketType::UNDEFINED:
TF_RUNTIME_ERROR("Unexpected conversion: SocketType::UNDEFINED");
break;
case SocketType::BOOLEAN:
node->set(socket, convertToCycles<bool>(value));
break;
case SocketType::FLOAT:
node->set(socket, convertToCycles<float>(value));
break;
case SocketType::INT:
node->set(socket, convertToCycles<int>(value));
break;
case SocketType::UINT:
node->set(socket, convertToCycles<unsigned int>(value));
break;
case SocketType::COLOR:
case SocketType::VECTOR:
case SocketType::POINT:
case SocketType::NORMAL:
node->set(socket, convertToCycles<float3>(value));
break;
case SocketType::POINT2:
node->set(socket, convertToCycles<float2>(value));
break;
case SocketType::CLOSURE:
// Handled by node connections
break;
case SocketType::STRING:
node->set(socket, convertToCycles<ustring>(value));
break;
case SocketType::ENUM:
// Enum's can accept a string or an int
if (value.IsHolding<TfToken>() || value.IsHolding<std::string>()) {
node->set(socket, convertToCycles<ustring>(value));
}
else {
node->set(socket, convertToCycles<int>(value));
}
break;
case SocketType::TRANSFORM:
node->set(socket, convertToCycles<Transform>(value));
break;
case SocketType::NODE:
// TODO: renderIndex->GetRprim()->cycles_node ?
TF_WARN("Unimplemented conversion: SocketType::NODE");
break;
case SocketType::BOOLEAN_ARRAY: {
auto cyclesArray = convertToCyclesArray<bool>(value);
node->set(socket, cyclesArray);
break;
}
case SocketType::FLOAT_ARRAY: {
auto cyclesArray = convertToCyclesArray<float>(value);
node->set(socket, cyclesArray);
break;
}
case SocketType::INT_ARRAY: {
auto cyclesArray = convertToCyclesArray<int>(value);
node->set(socket, cyclesArray);
break;
}
case SocketType::COLOR_ARRAY:
case SocketType::VECTOR_ARRAY:
case SocketType::POINT_ARRAY:
case SocketType::NORMAL_ARRAY: {
auto cyclesArray = convertToCyclesArray<float3, GfVec3f>(value);
node->set(socket, cyclesArray);
break;
}
case SocketType::POINT2_ARRAY: {
auto cyclesArray = convertToCyclesArray<float2, GfVec2f>(value);
node->set(socket, cyclesArray);
break;
}
case SocketType::STRING_ARRAY: {
auto cyclesArray = convertToCyclesArray<ustring, void>(value);
node->set(socket, cyclesArray);
break;
}
case SocketType::TRANSFORM_ARRAY: {
auto cyclesArray = convertToCyclesArray<Transform, void>(value);
node->set(socket, cyclesArray);
break;
}
case SocketType::NODE_ARRAY: {
// TODO: renderIndex->GetRprim()->cycles_node ?
TF_WARN("Unimplemented conversion: SocketType::NODE_ARRAY");
break;
}
}
}
VtValue GetNodeValue(const Node *node, const SocketType &socket)
{
switch (socket.type) {
default:
case SocketType::UNDEFINED:
TF_RUNTIME_ERROR("Unexpected conversion: SocketType::UNDEFINED");
return VtValue();
case SocketType::BOOLEAN:
return convertFromCycles(node->get_bool(socket));
case SocketType::FLOAT:
return convertFromCycles(node->get_float(socket));
case SocketType::INT:
return convertFromCycles(node->get_int(socket));
case SocketType::UINT:
return convertFromCycles(node->get_uint(socket));
case SocketType::COLOR:
case SocketType::VECTOR:
case SocketType::POINT:
case SocketType::NORMAL:
return convertFromCycles(node->get_float3(socket));
case SocketType::POINT2:
return convertFromCycles(node->get_float2(socket));
case SocketType::CLOSURE:
return VtValue();
case SocketType::STRING:
return convertFromCycles(node->get_string(socket));
case SocketType::ENUM:
return convertFromCycles(node->get_int(socket));
case SocketType::TRANSFORM:
return convertFromCycles(node->get_transform(socket));
case SocketType::NODE:
TF_WARN("Unimplemented conversion: SocketType::NODE");
return VtValue();
case SocketType::BOOLEAN_ARRAY:
return convertFromCyclesArray(node->get_bool_array(socket));
case SocketType::FLOAT_ARRAY:
return convertFromCyclesArray(node->get_float_array(socket));
case SocketType::INT_ARRAY:
return convertFromCyclesArray(node->get_int_array(socket));
case SocketType::COLOR_ARRAY:
case SocketType::VECTOR_ARRAY:
case SocketType::POINT_ARRAY:
case SocketType::NORMAL_ARRAY:
return convertFromCyclesArray<float3, GfVec3f>(node->get_float3_array(socket));
case SocketType::POINT2_ARRAY:
return convertFromCyclesArray<float2, GfVec2f>(node->get_float2_array(socket));
case SocketType::STRING_ARRAY:
return convertFromCyclesArray<ustring, void>(node->get_string_array(socket));
case SocketType::TRANSFORM_ARRAY:
return convertFromCyclesArray<Transform, void>(node->get_transform_array(socket));
case SocketType::NODE_ARRAY: {
TF_WARN("Unimplemented conversion: SocketType::NODE_ARRAY");
return VtValue();
}
}
}
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,18 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#pragma once
#include "graph/node.h"
#include "hydra/config.h"
#include <pxr/base/vt/value.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
void SetNodeValue(CCL_NS::Node *node, const CCL_NS::SocketType &socket, const VtValue &value);
VtValue GetNodeValue(const CCL_NS::Node *node, const CCL_NS::SocketType &socket);
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,78 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#include "hydra/output_driver.h"
#include "hydra/render_buffer.h"
#include "hydra/session.h"
HDCYCLES_NAMESPACE_OPEN_SCOPE
HdCyclesOutputDriver::HdCyclesOutputDriver(HdCyclesSession *renderParam)
: _renderParam(renderParam)
{
}
void HdCyclesOutputDriver::write_render_tile(const Tile &tile)
{
update_render_tile(tile);
// Update convergence state of all render buffers
for (const HdRenderPassAovBinding &aovBinding : _renderParam->GetAovBindings()) {
if (const auto renderBuffer = static_cast<HdCyclesRenderBuffer *>(aovBinding.renderBuffer)) {
renderBuffer->SetConverged(true);
}
}
}
bool HdCyclesOutputDriver::update_render_tile(const Tile &tile)
{
std::vector<float> pixels;
for (const HdRenderPassAovBinding &aovBinding : _renderParam->GetAovBindings()) {
if (aovBinding == _renderParam->GetDisplayAovBinding()) {
continue; // Display AOV binding is already updated by Cycles display driver
}
if (const auto renderBuffer = static_cast<HdCyclesRenderBuffer *>(aovBinding.renderBuffer)) {
const HdFormat format = renderBuffer->GetFormat();
if (format == HdFormatInvalid) {
continue; // Skip invalid AOV bindings
}
const size_t channels = HdGetComponentCount(format);
// Avoid extra copy by mapping render buffer directly when dimensions/format match the tile
if (tile.offset.x == 0 && tile.offset.y == 0 && tile.size.x == renderBuffer->GetWidth() &&
tile.size.y == renderBuffer->GetHeight() &&
(format >= HdFormatFloat32 && format <= HdFormatFloat32Vec4)) {
float *const data = static_cast<float *>(renderBuffer->Map());
TF_VERIFY(tile.get_pass_pixels(aovBinding.aovName.GetString(), channels, data));
renderBuffer->Unmap();
}
else {
pixels.resize(channels * tile.size.x * tile.size.y);
if (tile.get_pass_pixels(aovBinding.aovName.GetString(), channels, pixels.data())) {
const bool isId = aovBinding.aovName == HdAovTokens->primId ||
aovBinding.aovName == HdAovTokens->elementId ||
aovBinding.aovName == HdAovTokens->instanceId;
renderBuffer->WritePixels(pixels.data(),
GfVec2i(tile.offset.x, tile.offset.y),
GfVec2i(tile.size.x, tile.size.y),
channels,
isId);
}
else {
// Do not warn on missing elementId, which is a standard AOV but is not implememted
if (aovBinding.aovName != HdAovTokens->elementId) {
TF_RUNTIME_ERROR("Could not find pass for AOV '%s'", aovBinding.aovName.GetText());
}
}
}
}
}
return true;
}
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,23 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#pragma once
#include "hydra/config.h"
#include "session/output_driver.h"
HDCYCLES_NAMESPACE_OPEN_SCOPE
class HdCyclesOutputDriver final : public CCL_NS::OutputDriver {
public:
HdCyclesOutputDriver(HdCyclesSession *renderParam);
private:
void write_render_tile(const Tile &tile) override;
bool update_render_tile(const Tile &tile) override;
HdCyclesSession *const _renderParam;
};
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,3 @@
{
"Includes": [ "*/resources/" ]
}

View File

@@ -0,0 +1,71 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#include "hydra/plugin.h"
#include "hydra/render_delegate.h"
#include "util/log.h"
#include "util/path.h"
#include <pxr/base/arch/filesystem.h>
#include <pxr/base/plug/plugin.h>
#include <pxr/base/plug/thisPlugin.h>
#include <pxr/base/tf/envSetting.h>
#include <pxr/imaging/hd/rendererPluginRegistry.h>
PXR_NAMESPACE_OPEN_SCOPE
#ifdef WITH_CYCLES_LOGGING
TF_DEFINE_ENV_SETTING(CYCLES_LOGGING, false, "Enable Cycles logging")
TF_DEFINE_ENV_SETTING(CYCLES_LOGGING_SEVERITY, 1, "Cycles logging verbosity")
#endif
HdCyclesPlugin::HdCyclesPlugin()
{
const PlugPluginPtr plugin = PLUG_THIS_PLUGIN;
// Initialize Cycles paths relative to the plugin resource path
std::string rootPath = PXR_NS::ArchAbsPath(plugin->GetResourcePath());
CCL_NS::path_init(std::move(rootPath));
#ifdef WITH_CYCLES_LOGGING
if (TfGetEnvSetting(CYCLES_LOGGING)) {
CCL_NS::util_logging_start();
CCL_NS::util_logging_verbosity_set(TfGetEnvSetting(CYCLES_LOGGING_SEVERITY));
}
#endif
}
HdCyclesPlugin::~HdCyclesPlugin()
{
}
bool HdCyclesPlugin::IsSupported() const
{
return true;
}
HdRenderDelegate *HdCyclesPlugin::CreateRenderDelegate()
{
return CreateRenderDelegate({});
}
HdRenderDelegate *HdCyclesPlugin::CreateRenderDelegate(const HdRenderSettingsMap &settingsMap)
{
return new HD_CYCLES_NS::HdCyclesDelegate(settingsMap);
}
void HdCyclesPlugin::DeleteRenderDelegate(HdRenderDelegate *renderDelegate)
{
delete renderDelegate;
}
// USD's type system accounts for namespace, so we'd have to register our name as
// HdCycles::HdCyclesPlugin in plugInfo.json, which isn't all that bad for JSON,
// but those colons may cause issues for any USD specific tooling. So just put our
// plugin class in the pxr namespace (which USD's type system will elide).
TF_REGISTRY_FUNCTION(TfType)
{
HdRendererPluginRegistry::Define<PXR_NS::HdCyclesPlugin>();
}
PXR_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,25 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#pragma once
#include "hydra/config.h"
#include <pxr/imaging/hd/rendererPlugin.h>
PXR_NAMESPACE_OPEN_SCOPE
class HdCyclesPlugin final : public PXR_NS::HdRendererPlugin {
public:
HdCyclesPlugin();
~HdCyclesPlugin() override;
bool IsSupported() const override;
PXR_NS::HdRenderDelegate *CreateRenderDelegate() override;
PXR_NS::HdRenderDelegate *CreateRenderDelegate(const PXR_NS::HdRenderSettingsMap &) override;
void DeleteRenderDelegate(PXR_NS::HdRenderDelegate *) override;
};
PXR_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,199 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#include "hydra/pointcloud.h"
#include "hydra/geometry.inl"
#include "scene/pointcloud.h"
#include <pxr/imaging/hd/extComputationUtils.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
HdCyclesPoints::HdCyclesPoints(const SdfPath &rprimId
#if PXR_VERSION < 2102
,
const SdfPath &instancerId
#endif
)
: HdCyclesGeometry(rprimId
#if PXR_VERSION < 2102
,
instancerId
#endif
)
{
}
HdCyclesPoints::~HdCyclesPoints()
{
}
HdDirtyBits HdCyclesPoints::GetInitialDirtyBitsMask() const
{
HdDirtyBits bits = HdCyclesGeometry::GetInitialDirtyBitsMask();
bits |= HdChangeTracker::DirtyPoints | HdChangeTracker::DirtyWidths |
HdChangeTracker::DirtyPrimvar;
return bits;
}
HdDirtyBits HdCyclesPoints::_PropagateDirtyBits(HdDirtyBits bits) const
{
// Points and widths always have to be updated together
if (bits & (HdChangeTracker::DirtyPoints | HdChangeTracker::DirtyWidths)) {
bits |= HdChangeTracker::DirtyPoints | HdChangeTracker::DirtyWidths;
}
return bits;
}
void HdCyclesPoints::Populate(HdSceneDelegate *sceneDelegate, HdDirtyBits dirtyBits, bool &rebuild)
{
if (dirtyBits & (HdChangeTracker::DirtyPoints | HdChangeTracker::DirtyWidths)) {
const size_t numPoints = _geom->num_points();
PopulatePoints(sceneDelegate);
PopulateWidths(sceneDelegate);
rebuild = _geom->num_points() != numPoints;
array<int> shaders;
shaders.reserve(_geom->num_points());
for (size_t i = 0; i < _geom->num_points(); ++i) {
shaders.push_back_reserved(0);
}
_geom->set_shader(shaders);
}
if (dirtyBits & HdChangeTracker::DirtyPrimvar) {
PopulatePrimvars(sceneDelegate);
}
}
void HdCyclesPoints::PopulatePoints(HdSceneDelegate *sceneDelegate)
{
VtValue value;
for (const HdExtComputationPrimvarDescriptor &desc :
sceneDelegate->GetExtComputationPrimvarDescriptors(GetId(), HdInterpolationVertex)) {
if (desc.name == HdTokens->points) {
auto valueStore = HdExtComputationUtils::GetComputedPrimvarValues({desc}, sceneDelegate);
const auto valueStoreIt = valueStore.find(desc.name);
if (valueStoreIt != valueStore.end()) {
value = std::move(valueStoreIt->second);
}
break;
}
}
if (value.IsEmpty()) {
value = GetPrimvar(sceneDelegate, HdTokens->points);
}
if (!value.IsHolding<VtVec3fArray>()) {
TF_WARN("Invalid points data for %s", GetId().GetText());
return;
}
const auto &points = value.UncheckedGet<VtVec3fArray>();
array<float3> pointsDataCycles;
pointsDataCycles.reserve(points.size());
for (const GfVec3f &point : points) {
pointsDataCycles.push_back_reserved(make_float3(point[0], point[1], point[2]));
}
_geom->set_points(pointsDataCycles);
}
void HdCyclesPoints::PopulateWidths(HdSceneDelegate *sceneDelegate)
{
VtValue value = GetPrimvar(sceneDelegate, HdTokens->widths);
const HdInterpolation interpolation = GetPrimvarInterpolation(sceneDelegate, HdTokens->widths);
if (!value.IsHolding<VtFloatArray>()) {
TF_WARN("Invalid widths data for %s", GetId().GetText());
return;
}
const auto &widths = value.UncheckedGet<VtFloatArray>();
array<float> radiusDataCycles;
radiusDataCycles.reserve(_geom->num_points());
if (interpolation == HdInterpolationConstant) {
TF_VERIFY(widths.size() == 1);
const float constantRadius = widths[0] * 0.5f;
for (size_t i = 0; i < _geom->num_points(); ++i) {
radiusDataCycles.push_back_reserved(constantRadius);
}
}
else if (interpolation == HdInterpolationVertex) {
TF_VERIFY(widths.size() == _geom->num_points());
for (size_t i = 0; i < _geom->num_points(); ++i) {
radiusDataCycles.push_back_reserved(widths[i] * 0.5f);
}
}
_geom->set_radius(radiusDataCycles);
}
void HdCyclesPoints::PopulatePrimvars(HdSceneDelegate *sceneDelegate)
{
Scene *const scene = (Scene *)_geom->get_owner();
const std::pair<HdInterpolation, AttributeElement> interpolations[] = {
std::make_pair(HdInterpolationVertex, ATTR_ELEMENT_VERTEX),
std::make_pair(HdInterpolationConstant, ATTR_ELEMENT_OBJECT),
};
for (const auto &interpolation : interpolations) {
for (const HdPrimvarDescriptor &desc :
GetPrimvarDescriptors(sceneDelegate, interpolation.first)) {
// Skip special primvars that are handled separately
if (desc.name == HdTokens->points || desc.name == HdTokens->widths) {
continue;
}
VtValue value = GetPrimvar(sceneDelegate, desc.name);
if (value.IsEmpty()) {
continue;
}
const ustring name(desc.name.GetString());
AttributeStandard std = ATTR_STD_NONE;
if (desc.role == HdPrimvarRoleTokens->textureCoordinate) {
std = ATTR_STD_UV;
}
else if (interpolation.first == HdInterpolationVertex) {
if (desc.name == HdTokens->displayColor || desc.role == HdPrimvarRoleTokens->color) {
std = ATTR_STD_VERTEX_COLOR;
}
else if (desc.name == HdTokens->normals) {
std = ATTR_STD_VERTEX_NORMAL;
}
}
else if (desc.name == HdTokens->displayColor &&
interpolation.first == HdInterpolationConstant) {
if (value.IsHolding<VtVec3fArray>() && value.GetArraySize() == 1) {
const GfVec3f color = value.UncheckedGet<VtVec3fArray>()[0];
_instances[0]->set_color(make_float3(color[0], color[1], color[2]));
}
}
// Skip attributes that are not needed
if ((std != ATTR_STD_NONE && _geom->need_attribute(scene, std)) ||
_geom->need_attribute(scene, name)) {
ApplyPrimvars(_geom->attributes, name, value, interpolation.second, std);
}
}
}
}
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,40 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#pragma once
#include "hydra/config.h"
#include "hydra/geometry.h"
#include <pxr/imaging/hd/points.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
class HdCyclesPoints final : public HdCyclesGeometry<PXR_NS::HdPoints, CCL_NS::PointCloud> {
public:
HdCyclesPoints(
const PXR_NS::SdfPath &rprimId
#if PXR_VERSION < 2102
,
const PXR_NS::SdfPath &instancerId = {}
#endif
);
~HdCyclesPoints() override;
PXR_NS::HdDirtyBits GetInitialDirtyBitsMask() const override;
private:
PXR_NS::HdDirtyBits _PropagateDirtyBits(PXR_NS::HdDirtyBits bits) const override;
void Populate(PXR_NS::HdSceneDelegate *sceneDelegate,
PXR_NS::HdDirtyBits dirtyBits,
bool &rebuild) override;
void PopulatePoints(PXR_NS::HdSceneDelegate *sceneDelegate);
void PopulateWidths(PXR_NS::HdSceneDelegate *sceneDelegate);
void PopulatePrimvars(PXR_NS::HdSceneDelegate *sceneDelegate);
};
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,276 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#include "hydra/render_buffer.h"
#include "hydra/session.h"
#include "util/half.h"
#include <pxr/base/gf/vec3i.h>
#include <pxr/base/gf/vec4f.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
HdCyclesRenderBuffer::HdCyclesRenderBuffer(const SdfPath &bprimId) : HdRenderBuffer(bprimId)
{
}
HdCyclesRenderBuffer::~HdCyclesRenderBuffer()
{
}
void HdCyclesRenderBuffer::Finalize(HdRenderParam *renderParam)
{
// Remove this render buffer from AOV bindings
// This ensures that 'OutputDriver' does not attempt to write to it anymore
static_cast<HdCyclesSession *>(renderParam)->RemoveAovBinding(this);
HdRenderBuffer::Finalize(renderParam);
}
bool HdCyclesRenderBuffer::Allocate(const GfVec3i &dimensions, HdFormat format, bool multiSampled)
{
if (dimensions[2] != 1) {
TF_RUNTIME_ERROR("HdCyclesRenderBuffer::Allocate called with dimensions that are not 2D.");
return false;
}
const size_t oldSize = _data.size();
const size_t newSize = dimensions[0] * dimensions[1] * HdDataSizeOfFormat(format);
if (oldSize == newSize) {
return true;
}
if (IsMapped()) {
TF_RUNTIME_ERROR("HdCyclesRenderBuffer::Allocate called while buffer is mapped.");
return false;
}
_width = dimensions[0];
_height = dimensions[1];
_format = format;
_data.resize(newSize);
return true;
}
void HdCyclesRenderBuffer::_Deallocate()
{
_width = 0u;
_height = 0u;
_format = HdFormatInvalid;
_data.clear();
_data.shrink_to_fit();
_resource = VtValue();
}
void *HdCyclesRenderBuffer::Map()
{
// Mapping is not implemented when a resource is set
if (!_resource.IsEmpty()) {
return nullptr;
}
++_mapped;
return _data.data();
}
void HdCyclesRenderBuffer::Unmap()
{
--_mapped;
}
bool HdCyclesRenderBuffer::IsMapped() const
{
return _mapped != 0;
}
void HdCyclesRenderBuffer::Resolve()
{
}
bool HdCyclesRenderBuffer::IsConverged() const
{
return _converged;
}
void HdCyclesRenderBuffer::SetConverged(bool converged)
{
_converged = converged;
}
VtValue HdCyclesRenderBuffer::GetResource(bool multiSampled) const
{
TF_UNUSED(multiSampled);
return _resource;
}
void HdCyclesRenderBuffer::SetResource(const VtValue &resource)
{
_resource = resource;
}
namespace {
struct SimpleConversion {
static float convert(float value)
{
return value;
}
};
struct IdConversion {
static int32_t convert(float value)
{
return static_cast<int32_t>(value) - 1;
}
};
struct UInt8Conversion {
static uint8_t convert(float value)
{
return static_cast<uint8_t>(value * 255.f);
}
};
struct SInt8Conversion {
static int8_t convert(float value)
{
return static_cast<int8_t>(value * 127.f);
}
};
struct HalfConversion {
static half convert(float value)
{
return float_to_half_image(value);
}
};
template<typename SrcT, typename DstT, typename Convertor = SimpleConversion>
void writePixels(const SrcT *srcPtr,
const GfVec2i &srcSize,
int srcChannelCount,
DstT *dstPtr,
const GfVec2i &dstSize,
int dstChannelCount,
const Convertor &convertor = {})
{
const auto writeSize = GfVec2i(GfMin(srcSize[0], dstSize[0]), GfMin(srcSize[1], dstSize[1]));
const auto writeChannelCount = GfMin(srcChannelCount, dstChannelCount);
for (int y = 0; y < writeSize[1]; ++y) {
for (int x = 0; x < writeSize[0]; ++x) {
for (int c = 0; c < writeChannelCount; ++c) {
dstPtr[x * dstChannelCount + c] = convertor.convert(srcPtr[x * srcChannelCount + c]);
}
}
srcPtr += srcSize[0] * srcChannelCount;
dstPtr += dstSize[0] * dstChannelCount;
}
}
} // namespace
void HdCyclesRenderBuffer::WritePixels(const float *srcPixels,
const PXR_NS::GfVec2i &srcOffset,
const GfVec2i &srcDims,
int srcChannels,
bool isId)
{
uint8_t *dstPixels = _data.data();
const size_t formatSize = HdDataSizeOfFormat(_format);
dstPixels += srcOffset[1] * (formatSize * _width) + srcOffset[0] * formatSize;
switch (_format) {
case HdFormatUNorm8:
case HdFormatUNorm8Vec2:
case HdFormatUNorm8Vec3:
case HdFormatUNorm8Vec4:
writePixels(srcPixels,
srcDims,
srcChannels,
dstPixels,
GfVec2i(_width, _height),
1 + (_format - HdFormatUNorm8),
UInt8Conversion());
break;
case HdFormatSNorm8:
case HdFormatSNorm8Vec2:
case HdFormatSNorm8Vec3:
case HdFormatSNorm8Vec4:
writePixels(srcPixels,
srcDims,
srcChannels,
dstPixels,
GfVec2i(_width, _height),
1 + (_format - HdFormatSNorm8),
SInt8Conversion());
break;
case HdFormatFloat16:
case HdFormatFloat16Vec2:
case HdFormatFloat16Vec3:
case HdFormatFloat16Vec4:
writePixels(srcPixels,
srcDims,
srcChannels,
reinterpret_cast<half *>(dstPixels),
GfVec2i(_width, _height),
1 + (_format - HdFormatFloat16),
HalfConversion());
break;
case HdFormatFloat32:
case HdFormatFloat32Vec2:
case HdFormatFloat32Vec3:
case HdFormatFloat32Vec4:
writePixels(srcPixels,
srcDims,
srcChannels,
reinterpret_cast<float *>(dstPixels),
GfVec2i(_width, _height),
1 + (_format - HdFormatFloat32));
break;
case HdFormatInt32:
// Special case for ID AOVs (see 'HdCyclesMesh::Sync')
if (isId) {
writePixels(srcPixels,
srcDims,
srcChannels,
reinterpret_cast<int *>(dstPixels),
GfVec2i(_width, _height),
1,
IdConversion());
}
else {
writePixels(srcPixels,
srcDims,
srcChannels,
reinterpret_cast<int *>(dstPixels),
GfVec2i(_width, _height),
1);
}
break;
case HdFormatInt32Vec2:
case HdFormatInt32Vec3:
case HdFormatInt32Vec4:
writePixels(srcPixels,
srcDims,
srcChannels,
reinterpret_cast<int *>(dstPixels),
GfVec2i(_width, _height),
1 + (_format - HdFormatInt32));
break;
default:
TF_RUNTIME_ERROR("HdCyclesRenderBuffer::WritePixels called with unsupported format.");
break;
}
}
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,85 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#pragma once
#include "hydra/config.h"
#include <pxr/imaging/hd/renderBuffer.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
class HdCyclesRenderBuffer final : public PXR_NS::HdRenderBuffer {
public:
HdCyclesRenderBuffer(const PXR_NS::SdfPath &bprimId);
~HdCyclesRenderBuffer() override;
void Finalize(PXR_NS::HdRenderParam *renderParam) override;
bool Allocate(const PXR_NS::GfVec3i &dimensions,
PXR_NS::HdFormat format,
bool multiSampled) override;
unsigned int GetWidth() const override
{
return _width;
}
unsigned int GetHeight() const override
{
return _height;
}
unsigned int GetDepth() const override
{
return 1u;
}
PXR_NS::HdFormat GetFormat() const override
{
return _format;
}
bool IsMultiSampled() const override
{
return false;
}
void *Map() override;
void Unmap() override;
bool IsMapped() const override;
void Resolve() override;
bool IsConverged() const override;
void SetConverged(bool converged);
PXR_NS::VtValue GetResource(bool multiSampled = false) const override;
void SetResource(const PXR_NS::VtValue &resource);
void WritePixels(const float *pixels,
const PXR_NS::GfVec2i &offset,
const PXR_NS::GfVec2i &dims,
int channels,
bool isId = false);
private:
void _Deallocate() override;
unsigned int _width = 0u;
unsigned int _height = 0u;
PXR_NS::HdFormat _format = PXR_NS::HdFormatInvalid;
std::vector<uint8_t> _data;
PXR_NS::VtValue _resource;
std::atomic_int _mapped = 0;
std::atomic_bool _converged = false;
};
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,514 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#include "hydra/render_delegate.h"
#include "hydra/camera.h"
#include "hydra/curves.h"
#include "hydra/field.h"
#include "hydra/instancer.h"
#include "hydra/light.h"
#include "hydra/material.h"
#include "hydra/mesh.h"
#include "hydra/node_util.h"
#include "hydra/pointcloud.h"
#include "hydra/render_buffer.h"
#include "hydra/render_pass.h"
#include "hydra/session.h"
#include "hydra/volume.h"
#include "scene/integrator.h"
#include "scene/scene.h"
#include "session/session.h"
#include <pxr/base/tf/getenv.h>
#include <pxr/imaging/hd/extComputation.h>
#include <pxr/imaging/hgi/tokens.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
// clang-format off
TF_DEFINE_PRIVATE_TOKENS(_tokens,
(cycles)
(openvdbAsset)
);
TF_DEFINE_PRIVATE_TOKENS(HdCyclesRenderSettingsTokens,
((device, "cycles:device"))
((threads, "cycles:threads"))
((time_limit, "cycles:time_limit"))
((samples, "cycles:samples"))
((sample_offset, "cycles:sample_offset"))
);
// clang-format on
namespace {
const TfTokenVector kSupportedRPrimTypes = {
HdPrimTypeTokens->basisCurves,
HdPrimTypeTokens->mesh,
HdPrimTypeTokens->points,
#ifdef WITH_OPENVDB
HdPrimTypeTokens->volume,
#endif
};
const TfTokenVector kSupportedSPrimTypes = {
HdPrimTypeTokens->camera,
HdPrimTypeTokens->material,
HdPrimTypeTokens->diskLight,
HdPrimTypeTokens->distantLight,
HdPrimTypeTokens->domeLight,
HdPrimTypeTokens->rectLight,
HdPrimTypeTokens->sphereLight,
HdPrimTypeTokens->extComputation,
};
const TfTokenVector kSupportedBPrimTypes = {
HdPrimTypeTokens->renderBuffer,
#ifdef WITH_OPENVDB
_tokens->openvdbAsset,
#endif
};
SessionParams GetSessionParams(const HdRenderSettingsMap &settings)
{
SessionParams params;
params.threads = 0;
params.background = false;
params.use_resolution_divider = false;
HdRenderSettingsMap::const_iterator it;
// Pull all setting that contribute to device creation first
it = settings.find(HdCyclesRenderSettingsTokens->threads);
if (it != settings.end()) {
params.threads = VtValue::Cast<int>(it->second).GetWithDefault(params.threads);
}
// Get the Cycles device from settings or environment, falling back to CPU
std::string deviceType = Device::string_from_type(DEVICE_CPU);
it = settings.find(HdCyclesRenderSettingsTokens->device);
if (it != settings.end()) {
deviceType = VtValue::Cast<std::string>(it->second).GetWithDefault(deviceType);
}
else {
const std::string deviceTypeEnv = TfGetenv("CYCLES_DEVICE");
if (!deviceTypeEnv.empty()) {
deviceType = deviceTypeEnv;
}
}
// Move to all uppercase for Device::type_from_string
std::transform(deviceType.begin(), deviceType.end(), deviceType.begin(), ::toupper);
vector<DeviceInfo> devices = Device::available_devices(
DEVICE_MASK(Device::type_from_string(deviceType.c_str())));
if (devices.empty()) {
devices = Device::available_devices(DEVICE_MASK_CPU);
if (!devices.empty()) {
params.device = devices.front();
}
}
else {
params.device = Device::get_multi_device(devices, params.threads, params.background);
}
return params;
}
} // namespace
HdCyclesDelegate::HdCyclesDelegate(const HdRenderSettingsMap &settingsMap, Session *session_)
: HdRenderDelegate()
{
_renderParam = session_ ? std::make_unique<HdCyclesSession>(session_) :
std::make_unique<HdCyclesSession>(GetSessionParams(settingsMap));
// If the delegate owns the session, pull any remaining settings
if (!session_) {
for (const auto &setting : settingsMap) {
// Skip over the settings known to be used for initialization only
if (setting.first == HdCyclesRenderSettingsTokens->device ||
setting.first == HdCyclesRenderSettingsTokens->threads) {
continue;
}
SetRenderSetting(setting.first, setting.second);
}
}
}
HdCyclesDelegate::~HdCyclesDelegate()
{
}
void HdCyclesDelegate::SetDrivers(const HdDriverVector &drivers)
{
for (HdDriver *hdDriver : drivers) {
if (hdDriver->name == HgiTokens->renderDriver && hdDriver->driver.IsHolding<Hgi *>()) {
_hgi = hdDriver->driver.UncheckedGet<Hgi *>();
break;
}
}
}
bool HdCyclesDelegate::IsDisplaySupported() const
{
#ifdef _WIN32
return _hgi && _hgi->GetAPIName() == HgiTokens->OpenGL;
#else
return false;
#endif
}
const TfTokenVector &HdCyclesDelegate::GetSupportedRprimTypes() const
{
return kSupportedRPrimTypes;
}
const TfTokenVector &HdCyclesDelegate::GetSupportedSprimTypes() const
{
return kSupportedSPrimTypes;
}
const TfTokenVector &HdCyclesDelegate::GetSupportedBprimTypes() const
{
return kSupportedBPrimTypes;
}
HdRenderParam *HdCyclesDelegate::GetRenderParam() const
{
return _renderParam.get();
}
HdResourceRegistrySharedPtr HdCyclesDelegate::GetResourceRegistry() const
{
return HdResourceRegistrySharedPtr();
}
bool HdCyclesDelegate::IsPauseSupported() const
{
return true;
}
bool HdCyclesDelegate::Pause()
{
_renderParam->session->set_pause(true);
return true;
}
bool HdCyclesDelegate::Resume()
{
_renderParam->session->set_pause(false);
return true;
}
HdRenderPassSharedPtr HdCyclesDelegate::CreateRenderPass(HdRenderIndex *index,
const HdRprimCollection &collection)
{
return HdRenderPassSharedPtr(new HdCyclesRenderPass(index, collection, _renderParam.get()));
}
HdInstancer *HdCyclesDelegate::CreateInstancer(HdSceneDelegate *delegate,
const SdfPath &instancerId
#if PXR_VERSION < 2102
,
const SdfPath &parentId
#endif
)
{
return new HdCyclesInstancer(delegate,
instancerId
#if PXR_VERSION < 2102
,
parentId
#endif
);
}
void HdCyclesDelegate::DestroyInstancer(HdInstancer *instancer)
{
delete instancer;
}
HdRprim *HdCyclesDelegate::CreateRprim(const TfToken &typeId,
const SdfPath &rprimId
#if PXR_VERSION < 2102
,
const SdfPath &instancerId
#endif
)
{
if (typeId == HdPrimTypeTokens->mesh) {
return new HdCyclesMesh(rprimId
#if PXR_VERSION < 2102
,
instancerId
#endif
);
}
if (typeId == HdPrimTypeTokens->basisCurves) {
return new HdCyclesCurves(rprimId
#if PXR_VERSION < 2102
,
instancerId
#endif
);
}
if (typeId == HdPrimTypeTokens->points) {
return new HdCyclesPoints(rprimId
#if PXR_VERSION < 2102
,
instancerId
#endif
);
}
#ifdef WITH_OPENVDB
if (typeId == HdPrimTypeTokens->volume) {
return new HdCyclesVolume(rprimId
# if PXR_VERSION < 2102
,
instancerId
# endif
);
}
#endif
TF_CODING_ERROR("Unknown Rprim type %s", typeId.GetText());
return nullptr;
}
void HdCyclesDelegate::DestroyRprim(HdRprim *rPrim)
{
delete rPrim;
}
HdSprim *HdCyclesDelegate::CreateSprim(const TfToken &typeId, const SdfPath &sprimId)
{
if (typeId == HdPrimTypeTokens->camera) {
return new HdCyclesCamera(sprimId);
}
if (typeId == HdPrimTypeTokens->material) {
return new HdCyclesMaterial(sprimId);
}
if (typeId == HdPrimTypeTokens->diskLight || typeId == HdPrimTypeTokens->distantLight ||
typeId == HdPrimTypeTokens->domeLight || typeId == HdPrimTypeTokens->rectLight ||
typeId == HdPrimTypeTokens->sphereLight) {
return new HdCyclesLight(sprimId, typeId);
}
if (typeId == HdPrimTypeTokens->extComputation) {
return new HdExtComputation(sprimId);
}
TF_CODING_ERROR("Unknown Sprim type %s", typeId.GetText());
return nullptr;
}
HdSprim *HdCyclesDelegate::CreateFallbackSprim(const TfToken &typeId)
{
return CreateSprim(typeId, SdfPath::EmptyPath());
}
void HdCyclesDelegate::DestroySprim(HdSprim *sPrim)
{
delete sPrim;
}
HdBprim *HdCyclesDelegate::CreateBprim(const TfToken &typeId, const SdfPath &bprimId)
{
if (typeId == HdPrimTypeTokens->renderBuffer) {
return new HdCyclesRenderBuffer(bprimId);
}
#ifdef WITH_OPENVDB
if (typeId == _tokens->openvdbAsset) {
return new HdCyclesField(bprimId, typeId);
}
#endif
TF_RUNTIME_ERROR("Unknown Bprim type %s", typeId.GetText());
return nullptr;
}
HdBprim *HdCyclesDelegate::CreateFallbackBprim(const TfToken &typeId)
{
return CreateBprim(typeId, SdfPath::EmptyPath());
}
void HdCyclesDelegate::DestroyBprim(HdBprim *bPrim)
{
delete bPrim;
}
void HdCyclesDelegate::CommitResources(HdChangeTracker *tracker)
{
TF_UNUSED(tracker);
const SceneLock lock(_renderParam.get());
_renderParam->UpdateScene();
}
TfToken HdCyclesDelegate::GetMaterialBindingPurpose() const
{
return HdTokens->full;
}
#if HD_API_VERSION < 41
TfToken HdCyclesDelegate::GetMaterialNetworkSelector() const
{
return _tokens->cycles;
}
#else
TfTokenVector HdCyclesDelegate::GetMaterialRenderContexts() const
{
return {_tokens->cycles};
}
#endif
VtDictionary HdCyclesDelegate::GetRenderStats() const
{
const Stats &stats = _renderParam->session->stats;
const Progress &progress = _renderParam->session->progress;
double totalTime, renderTime;
progress.get_time(totalTime, renderTime);
double fractionDone = progress.get_progress();
std::string status, substatus;
progress.get_status(status, substatus);
if (!substatus.empty()) {
status += " | " + substatus;
}
return {{"rendererName", VtValue("Cycles")},
{"rendererVersion", VtValue(GfVec3i(0, 0, 0))},
{"percentDone", VtValue(floor_to_int(fractionDone * 100))},
{"fractionDone", VtValue(fractionDone)},
{"loadClockTime", VtValue(totalTime - renderTime)},
{"peakMemory", VtValue(stats.mem_peak)},
{"totalClockTime", VtValue(totalTime)},
{"totalMemory", VtValue(stats.mem_used)},
{"renderProgressAnnotation", VtValue(status)}};
}
HdAovDescriptor HdCyclesDelegate::GetDefaultAovDescriptor(const TfToken &name) const
{
if (name == HdAovTokens->color) {
HdFormat colorFormat = HdFormatFloat32Vec4;
if (IsDisplaySupported()) {
// Can use Cycles 'DisplayDriver' in OpenGL, but it only supports 'half4' format
colorFormat = HdFormatFloat16Vec4;
}
return HdAovDescriptor(colorFormat, false, VtValue(GfVec4f(0.0f)));
}
if (name == HdAovTokens->depth) {
return HdAovDescriptor(HdFormatFloat32, false, VtValue(1.0f));
}
if (name == HdAovTokens->normal) {
return HdAovDescriptor(HdFormatFloat32Vec3, false, VtValue(GfVec3f(0.0f)));
}
if (name == HdAovTokens->primId || name == HdAovTokens->instanceId ||
name == HdAovTokens->elementId) {
return HdAovDescriptor(HdFormatInt32, false, VtValue(-1));
}
return HdAovDescriptor();
}
HdRenderSettingDescriptorList HdCyclesDelegate::GetRenderSettingDescriptors() const
{
Scene *const scene = _renderParam->session->scene;
HdRenderSettingDescriptorList descriptors;
descriptors.push_back({
"Time Limit",
HdCyclesRenderSettingsTokens->time_limit,
VtValue(0.0),
});
descriptors.push_back({
"Sample Count",
HdCyclesRenderSettingsTokens->samples,
VtValue(1024),
});
descriptors.push_back({
"Sample Offset",
HdCyclesRenderSettingsTokens->sample_offset,
VtValue(0),
});
for (const SocketType &socket : scene->integrator->type->inputs) {
descriptors.push_back({socket.ui_name.string(),
TfToken("cycles:integrator:" + socket.name.string()),
GetNodeValue(scene->integrator, socket)});
}
return descriptors;
}
void HdCyclesDelegate::SetRenderSetting(const PXR_NS::TfToken &key, const PXR_NS::VtValue &value)
{
Scene *const scene = _renderParam->session->scene;
Session *const session = _renderParam->session;
if (key == HdCyclesRenderSettingsTokens->time_limit) {
session->set_time_limit(
VtValue::Cast<double>(value).GetWithDefault(session->params.time_limit));
}
else if (key == HdCyclesRenderSettingsTokens->samples) {
int samples = VtValue::Cast<int>(value).GetWithDefault(session->params.samples);
samples = std::min(std::max(1, samples), Integrator::MAX_SAMPLES);
session->set_samples(samples);
}
else if (key == HdCyclesRenderSettingsTokens->sample_offset) {
session->params.sample_offset = VtValue::Cast<int>(value).GetWithDefault(
session->params.sample_offset);
++_settingsVersion;
}
else {
const std::string &keyString = key.GetString();
if (keyString.rfind("cycles:integrator:", 0) == 0) {
ustring socketName(keyString, sizeof("cycles:integrator:") - 1);
if (const SocketType *socket = scene->integrator->type->find_input(socketName)) {
SetNodeValue(scene->integrator, *socket, value);
++_settingsVersion;
}
}
}
}
VtValue HdCyclesDelegate::GetRenderSetting(const TfToken &key) const
{
Scene *const scene = _renderParam->session->scene;
Session *const session = _renderParam->session;
if (key == HdCyclesRenderSettingsTokens->device) {
return VtValue(TfToken(Device::string_from_type(session->params.device.type)));
}
else if (key == HdCyclesRenderSettingsTokens->threads) {
return VtValue(session->params.threads);
}
else if (key == HdCyclesRenderSettingsTokens->time_limit) {
return VtValue(session->params.time_limit);
}
else if (key == HdCyclesRenderSettingsTokens->samples) {
return VtValue(session->params.samples);
}
else if (key == HdCyclesRenderSettingsTokens->sample_offset) {
return VtValue(session->params.sample_offset);
}
else {
const std::string &keyString = key.GetString();
if (keyString.rfind("cycles:integrator:", 0) == 0) {
ustring socketName(keyString, sizeof("cycles:integrator:") - 1);
if (const SocketType *socket = scene->integrator->type->find_input(socketName)) {
return GetNodeValue(scene->integrator, *socket);
}
}
}
return VtValue();
}
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,98 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#pragma once
#include "hydra/config.h"
#include <pxr/imaging/hd/renderDelegate.h>
#include <pxr/imaging/hgi/hgi.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
class HdCyclesDelegate final : public PXR_NS::HdRenderDelegate {
public:
HdCyclesDelegate(const PXR_NS::HdRenderSettingsMap &settingsMap,
CCL_NS::Session *session_ = nullptr);
~HdCyclesDelegate() override;
void SetDrivers(const PXR_NS::HdDriverVector &drivers) override;
bool IsDisplaySupported() const;
PXR_NS::Hgi *GetHgi() const
{
return _hgi;
}
const PXR_NS::TfTokenVector &GetSupportedRprimTypes() const override;
const PXR_NS::TfTokenVector &GetSupportedSprimTypes() const override;
const PXR_NS::TfTokenVector &GetSupportedBprimTypes() const override;
PXR_NS::HdRenderParam *GetRenderParam() const override;
PXR_NS::HdResourceRegistrySharedPtr GetResourceRegistry() const override;
PXR_NS::HdRenderSettingDescriptorList GetRenderSettingDescriptors() const override;
bool IsPauseSupported() const override;
bool Pause() override;
bool Resume() override;
PXR_NS::HdRenderPassSharedPtr CreateRenderPass(
PXR_NS::HdRenderIndex *index, const PXR_NS::HdRprimCollection &collection) override;
PXR_NS::HdInstancer *CreateInstancer(PXR_NS::HdSceneDelegate *delegate,
const PXR_NS::SdfPath &id
#if PXR_VERSION < 2102
,
const PXR_NS::SdfPath &instancerId
#endif
) override;
void DestroyInstancer(PXR_NS::HdInstancer *instancer) override;
PXR_NS::HdRprim *CreateRprim(const PXR_NS::TfToken &typeId,
const PXR_NS::SdfPath &rprimId
#if PXR_VERSION < 2102
,
const PXR_NS::SdfPath &instancerId
#endif
) override;
void DestroyRprim(PXR_NS::HdRprim *rPrim) override;
PXR_NS::HdSprim *CreateSprim(const PXR_NS::TfToken &typeId,
const PXR_NS::SdfPath &sprimId) override;
PXR_NS::HdSprim *CreateFallbackSprim(const PXR_NS::TfToken &typeId) override;
void DestroySprim(PXR_NS::HdSprim *sPrim) override;
PXR_NS::HdBprim *CreateBprim(const PXR_NS::TfToken &typeId,
const PXR_NS::SdfPath &bprimId) override;
PXR_NS::HdBprim *CreateFallbackBprim(const PXR_NS::TfToken &typeId) override;
void DestroyBprim(PXR_NS::HdBprim *bPrim) override;
void CommitResources(PXR_NS::HdChangeTracker *tracker) override;
PXR_NS::TfToken GetMaterialBindingPurpose() const override;
#if HD_API_VERSION < 41
PXR_NS::TfToken GetMaterialNetworkSelector() const override;
#else
PXR_NS::TfTokenVector GetMaterialRenderContexts() const override;
#endif
PXR_NS::VtDictionary GetRenderStats() const override;
PXR_NS::HdAovDescriptor GetDefaultAovDescriptor(const PXR_NS::TfToken &name) const override;
void SetRenderSetting(const PXR_NS::TfToken &key, const PXR_NS::VtValue &value) override;
PXR_NS::VtValue GetRenderSetting(const PXR_NS::TfToken &key) const override;
private:
PXR_NS::Hgi *_hgi = nullptr;
std::unique_ptr<HdCyclesSession> _renderParam;
};
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,175 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#include "hydra/render_pass.h"
#include "hydra/camera.h"
#include "hydra/display_driver.h"
#include "hydra/output_driver.h"
#include "hydra/render_buffer.h"
#include "hydra/render_delegate.h"
#include "hydra/session.h"
#include "scene/camera.h"
#include "scene/integrator.h"
#include "scene/scene.h"
#include "session/session.h"
#include <pxr/imaging/hd/renderPassState.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
HdCyclesRenderPass::HdCyclesRenderPass(HdRenderIndex *index,
HdRprimCollection const &collection,
HdCyclesSession *renderParam)
: HdRenderPass(index, collection), _renderParam(renderParam)
{
Session *const session = _renderParam->session;
// Reset cancel state so session thread can continue rendering
session->progress.reset();
session->set_output_driver(make_unique<HdCyclesOutputDriver>(renderParam));
const auto renderDelegate = static_cast<const HdCyclesDelegate *>(
GetRenderIndex()->GetRenderDelegate());
if (renderDelegate->IsDisplaySupported()) {
session->set_display_driver(
make_unique<HdCyclesDisplayDriver>(renderParam, renderDelegate->GetHgi()));
}
}
HdCyclesRenderPass::~HdCyclesRenderPass()
{
Session *const session = _renderParam->session;
session->cancel(true);
}
bool HdCyclesRenderPass::IsConverged() const
{
for (const HdRenderPassAovBinding &aovBinding : _renderParam->GetAovBindings()) {
if (aovBinding.renderBuffer && !aovBinding.renderBuffer->IsConverged()) {
return false;
}
}
return true;
}
void HdCyclesRenderPass::ResetConverged()
{
for (const HdRenderPassAovBinding &aovBinding : _renderParam->GetAovBindings()) {
if (const auto renderBuffer = static_cast<HdCyclesRenderBuffer *>(aovBinding.renderBuffer)) {
renderBuffer->SetConverged(false);
}
}
}
void HdCyclesRenderPass::_Execute(const HdRenderPassStateSharedPtr &renderPassState,
const TfTokenVector &renderTags)
{
Scene *const scene = _renderParam->session->scene;
Session *const session = _renderParam->session;
if (session->progress.get_cancel()) {
return; // Something went wrong and cannot continue without recreating the session
}
if (scene->mutex.try_lock()) {
const auto renderDelegate = static_cast<HdCyclesDelegate *>(
GetRenderIndex()->GetRenderDelegate());
const unsigned int settingsVersion = renderDelegate->GetRenderSettingsVersion();
// Update requested AOV bindings
const HdRenderPassAovBindingVector &aovBindings = renderPassState->GetAovBindings();
if (_renderParam->GetAovBindings() != aovBindings ||
// Need to resync passes when denoising is enabled or disabled to update the pass mode
(settingsVersion != _lastSettingsVersion &&
scene->integrator->use_denoise_is_modified())) {
_renderParam->SyncAovBindings(aovBindings);
if (renderDelegate->IsDisplaySupported()) {
// Update display pass to the first requested color AOV
HdRenderPassAovBinding displayAovBinding = !aovBindings.empty() ? aovBindings.front() :
HdRenderPassAovBinding();
if (displayAovBinding.aovName == HdAovTokens->color && displayAovBinding.renderBuffer) {
_renderParam->SetDisplayAovBinding(displayAovBinding);
}
else {
_renderParam->SetDisplayAovBinding(HdRenderPassAovBinding());
}
}
}
// Update camera dimensions to the viewport size
#if PXR_VERSION >= 2102
CameraUtilFraming framing = renderPassState->GetFraming();
if (!framing.IsValid()) {
const GfVec4f vp = renderPassState->GetViewport();
framing = CameraUtilFraming(GfRect2i(GfVec2i(0), int(vp[2]), int(vp[3])));
}
scene->camera->set_full_width(framing.dataWindow.GetWidth());
scene->camera->set_full_height(framing.dataWindow.GetHeight());
#else
const GfVec4f vp = renderPassState->GetViewport();
scene->camera->set_full_width(int(vp[2]));
scene->camera->set_full_height(int(vp[3]));
#endif
if (const auto camera = static_cast<const HdCyclesCamera *>(renderPassState->GetCamera())) {
camera->ApplyCameraSettings(scene->camera);
}
else {
HdCyclesCamera::ApplyCameraSettings(renderPassState->GetWorldToViewMatrix(),
renderPassState->GetProjectionMatrix(),
renderPassState->GetClipPlanes(),
scene->camera);
}
// Reset session if the session, scene, camera or AOV bindings changed
if (scene->need_reset() || settingsVersion != _lastSettingsVersion) {
_lastSettingsVersion = settingsVersion;
// Reset convergence state of all render buffers
ResetConverged();
BufferParams buffer_params;
#if PXR_VERSION >= 2102
buffer_params.full_x = static_cast<int>(framing.displayWindow.GetMin()[0]);
buffer_params.full_y = static_cast<int>(framing.displayWindow.GetMin()[1]);
buffer_params.full_width = static_cast<int>(framing.displayWindow.GetSize()[0]);
buffer_params.full_height = static_cast<int>(framing.displayWindow.GetSize()[1]);
buffer_params.window_x = framing.dataWindow.GetMinX() - buffer_params.full_x;
buffer_params.window_y = framing.dataWindow.GetMinY() - buffer_params.full_y;
buffer_params.window_width = framing.dataWindow.GetWidth();
buffer_params.window_height = framing.dataWindow.GetHeight();
buffer_params.width = buffer_params.window_width;
buffer_params.height = buffer_params.window_height;
#else
buffer_params.width = static_cast<int>(vp[2]);
buffer_params.height = static_cast<int>(vp[3]);
buffer_params.full_width = buffer_params.width;
buffer_params.full_height = buffer_params.height;
buffer_params.window_width = buffer_params.width;
buffer_params.window_height = buffer_params.height;
#endif
session->reset(session->params, buffer_params);
}
scene->mutex.unlock();
// Start Cycles render thread if not already running
session->start();
}
session->draw();
}
void HdCyclesRenderPass::_MarkCollectionDirty()
{
}
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,34 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#pragma once
#include "hydra/config.h"
#include <pxr/imaging/hd/renderPass.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
class HdCyclesRenderPass final : public PXR_NS::HdRenderPass {
public:
HdCyclesRenderPass(PXR_NS::HdRenderIndex *index,
const PXR_NS::HdRprimCollection &collection,
HdCyclesSession *renderParam);
~HdCyclesRenderPass() override;
bool IsConverged() const override;
private:
void ResetConverged();
void _Execute(const PXR_NS::HdRenderPassStateSharedPtr &renderPassState,
const PXR_NS::TfTokenVector &renderTags) override;
void _MarkCollectionDirty() override;
HdCyclesSession *_renderParam;
unsigned int _lastSettingsVersion = 0;
};
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,22 @@
{
"Plugins": [
{
"Info": {
"Types": {
"HdCyclesPlugin": {
"bases": [
"HdRendererPlugin"
],
"displayName": "Cycles",
"priority": 0
}
}
},
"LibraryPath": "@PLUG_INFO_LIBRARY_PATH@",
"Name": "hdCycles",
"ResourcePath": "@PLUG_INFO_RESOURCE_PATH@",
"Root": "@PLUG_INFO_ROOT@",
"Type": "library"
}
]
}

View File

@@ -0,0 +1,170 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#include "hydra/session.h"
#include "scene/shader.h"
// Have to include shader.h before background.h so that 'set_shader' uses the correct 'set'
// overload taking a 'Node *', rather than the one taking a 'bool'
#include "scene/background.h"
#include "scene/light.h"
#include "scene/shader_graph.h"
#include "scene/shader_nodes.h"
#include "session/session.h"
HDCYCLES_NAMESPACE_OPEN_SCOPE
namespace {
const std::unordered_map<TfToken, PassType, TfToken::HashFunctor> kAovToPass = {
{HdAovTokens->color, PASS_COMBINED},
{HdAovTokens->depth, PASS_DEPTH},
{HdAovTokens->normal, PASS_NORMAL},
{HdAovTokens->primId, PASS_OBJECT_ID},
{HdAovTokens->instanceId, PASS_AOV_VALUE},
};
} // namespace
SceneLock::SceneLock(const HdRenderParam *renderParam)
: scene(static_cast<const HdCyclesSession *>(renderParam)->session->scene),
sceneLock(scene->mutex)
{
}
SceneLock::~SceneLock()
{
}
HdCyclesSession::HdCyclesSession(Session *session_) : session(session_), _ownCyclesSession(false)
{
}
HdCyclesSession::HdCyclesSession(const SessionParams &params)
: session(new Session(params, SceneParams())), _ownCyclesSession(true)
{
Scene *const scene = session->scene;
// Create background with ambient light
{
ShaderGraph *graph = new ShaderGraph();
BackgroundNode *bgNode = graph->create_node<BackgroundNode>();
bgNode->set_color(one_float3());
graph->add(bgNode);
graph->connect(bgNode->output("Background"), graph->output()->input("Surface"));
scene->default_background->set_graph(graph);
scene->default_background->tag_update(scene);
}
// Wire up object color in default surface material
{
ShaderGraph *graph = new ShaderGraph();
ObjectInfoNode *objectNode = graph->create_node<ObjectInfoNode>();
graph->add(objectNode);
DiffuseBsdfNode *diffuseNode = graph->create_node<DiffuseBsdfNode>();
graph->add(diffuseNode);
graph->connect(objectNode->output("Color"), diffuseNode->input("Color"));
graph->connect(diffuseNode->output("BSDF"), graph->output()->input("Surface"));
#if 1
// Create the instanceId AOV output
const ustring instanceId(HdAovTokens->instanceId.GetString());
OutputAOVNode *aovNode = graph->create_node<OutputAOVNode>();
aovNode->set_name(instanceId);
graph->add(aovNode);
AttributeNode *instanceIdNode = graph->create_node<AttributeNode>();
instanceIdNode->set_attribute(instanceId);
graph->add(instanceIdNode);
graph->connect(instanceIdNode->output("Fac"), aovNode->input("Value"));
#endif
scene->default_surface->set_graph(graph);
scene->default_surface->tag_update(scene);
}
}
HdCyclesSession::~HdCyclesSession()
{
if (_ownCyclesSession) {
delete session;
}
}
void HdCyclesSession::UpdateScene()
{
Scene *const scene = session->scene;
// Update background depending on presence of a background light
if (scene->light_manager->need_update()) {
Light *background_light = nullptr;
for (Light *light : scene->lights) {
if (light->get_light_type() == LIGHT_BACKGROUND) {
background_light = light;
break;
}
}
if (!background_light) {
scene->background->set_shader(scene->default_background);
scene->background->set_transparent(true);
}
else {
scene->background->set_shader(background_light->get_shader());
scene->background->set_transparent(false);
}
scene->background->tag_update(scene);
}
}
void HdCyclesSession::SyncAovBindings(const HdRenderPassAovBindingVector &aovBindings)
{
Scene *const scene = session->scene;
// Delete all existing passes
scene->delete_nodes(set<Pass *>(scene->passes.begin(), scene->passes.end()));
// Update passes with requested AOV bindings
_aovBindings = aovBindings;
for (const HdRenderPassAovBinding &aovBinding : aovBindings) {
const auto cyclesAov = kAovToPass.find(aovBinding.aovName);
if (cyclesAov == kAovToPass.end()) {
// TODO: Use PASS_AOV_COLOR and PASS_AOV_VALUE for these?
TF_WARN("Unknown pass %s", aovBinding.aovName.GetText());
continue;
}
const PassType type = cyclesAov->second;
const PassMode mode = PassMode::DENOISED;
Pass *pass = scene->create_node<Pass>();
pass->set_type(type);
pass->set_mode(mode);
pass->set_name(ustring(aovBinding.aovName.GetString()));
}
}
void HdCyclesSession::RemoveAovBinding(HdRenderBuffer *renderBuffer)
{
for (HdRenderPassAovBinding &aovBinding : _aovBindings) {
if (renderBuffer == aovBinding.renderBuffer) {
aovBinding.renderBuffer = nullptr;
break;
}
}
if (renderBuffer == _displayAovBinding.renderBuffer) {
_displayAovBinding.renderBuffer = nullptr;
}
}
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,59 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#pragma once
#include "hydra/config.h"
#include "util/thread.h"
#include <pxr/imaging/hd/renderDelegate.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
struct SceneLock {
SceneLock(const PXR_NS::HdRenderParam *renderParam);
~SceneLock();
CCL_NS::Scene *scene;
private:
CCL_NS::thread_scoped_lock sceneLock;
};
class HdCyclesSession final : public PXR_NS::HdRenderParam {
public:
HdCyclesSession(CCL_NS::Session *session_);
HdCyclesSession(const CCL_NS::SessionParams &params);
~HdCyclesSession() override;
void UpdateScene();
PXR_NS::HdRenderPassAovBinding GetDisplayAovBinding() const
{
return _displayAovBinding;
}
void SetDisplayAovBinding(const PXR_NS::HdRenderPassAovBinding &aovBinding)
{
_displayAovBinding = aovBinding;
}
const PXR_NS::HdRenderPassAovBindingVector &GetAovBindings() const
{
return _aovBindings;
}
void SyncAovBindings(const PXR_NS::HdRenderPassAovBindingVector &aovBindings);
void RemoveAovBinding(PXR_NS::HdRenderBuffer *renderBuffer);
CCL_NS::Session *session;
private:
const bool _ownCyclesSession;
PXR_NS::HdRenderPassAovBindingVector _aovBindings;
PXR_NS::HdRenderPassAovBinding _displayAovBinding;
};
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,91 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#include "hydra/volume.h"
#include "hydra/field.h"
#include "hydra/geometry.inl"
#include "scene/volume.h"
HDCYCLES_NAMESPACE_OPEN_SCOPE
// clang-format off
TF_DEFINE_PRIVATE_TOKENS(_tokens,
(openvdbAsset)
);
// clang-format on
HdCyclesVolume::HdCyclesVolume(const SdfPath &rprimId
#if PXR_VERSION < 2102
,
const SdfPath &instancerId
#endif
)
: HdCyclesGeometry(rprimId
#if PXR_VERSION < 2102
,
instancerId
#endif
)
{
}
HdCyclesVolume::~HdCyclesVolume()
{
}
HdDirtyBits HdCyclesVolume::GetInitialDirtyBitsMask() const
{
HdDirtyBits bits = HdCyclesGeometry::GetInitialDirtyBitsMask();
bits |= HdChangeTracker::DirtyVolumeField;
return bits;
}
void HdCyclesVolume::Populate(HdSceneDelegate *sceneDelegate, HdDirtyBits dirtyBits, bool &rebuild)
{
Scene *const scene = (Scene *)_geom->get_owner();
if (dirtyBits & HdChangeTracker::DirtyVolumeField) {
for (const HdVolumeFieldDescriptor &field :
sceneDelegate->GetVolumeFieldDescriptors(GetId())) {
if (const auto openvdbAsset = static_cast<HdCyclesField *>(
sceneDelegate->GetRenderIndex().GetBprim(_tokens->openvdbAsset, field.fieldId))) {
const ustring name(field.fieldName.GetString());
AttributeStandard std = ATTR_STD_NONE;
if (name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY)) {
std = ATTR_STD_VOLUME_DENSITY;
}
else if (name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR)) {
std = ATTR_STD_VOLUME_COLOR;
}
else if (name == Attribute::standard_name(ATTR_STD_VOLUME_FLAME)) {
std = ATTR_STD_VOLUME_FLAME;
}
else if (name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) {
std = ATTR_STD_VOLUME_HEAT;
}
else if (name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE)) {
std = ATTR_STD_VOLUME_TEMPERATURE;
}
else if (name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY)) {
std = ATTR_STD_VOLUME_VELOCITY;
}
// Skip attributes that are not needed
if ((std != ATTR_STD_NONE && _geom->need_attribute(scene, std)) ||
_geom->need_attribute(scene, name)) {
Attribute *const attr = (std != ATTR_STD_NONE) ?
_geom->attributes.add(std) :
_geom->attributes.add(
name, TypeDesc::TypeFloat, ATTR_ELEMENT_VOXEL);
attr->data_voxel() = openvdbAsset->GetImageHandle();
}
}
}
rebuild = true;
}
}
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -0,0 +1,33 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2022 NVIDIA Corporation
* Copyright 2022 Blender Foundation */
#pragma once
#include "hydra/config.h"
#include "hydra/geometry.h"
#include <pxr/imaging/hd/volume.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
class HdCyclesVolume final : public HdCyclesGeometry<PXR_NS::HdVolume, CCL_NS::Volume> {
public:
HdCyclesVolume(
const PXR_NS::SdfPath &rprimId
#if PXR_VERSION < 2102
,
const PXR_NS::SdfPath &instancerId = {}
#endif
);
~HdCyclesVolume() override;
PXR_NS::HdDirtyBits GetInitialDirtyBitsMask() const override;
private:
void Populate(PXR_NS::HdSceneDelegate *sceneDelegate,
PXR_NS::HdDirtyBits dirtyBits,
bool &rebuild) override;
};
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@@ -18,7 +18,11 @@ CCL_NAMESPACE_BEGIN
*/
PassAccessor::PassAccessInfo::PassAccessInfo(const BufferPass &pass)
: type(pass.type), mode(pass.mode), include_albedo(pass.include_albedo), offset(pass.offset)
: type(pass.type),
mode(pass.mode),
include_albedo(pass.include_albedo),
is_lightgroup(!pass.lightgroup.empty()),
offset(pass.offset)
{
}
@@ -127,7 +131,8 @@ bool PassAccessor::get_render_tile_pixels(const RenderBuffers *render_buffers,
const PassType type = pass_access_info_.type;
const PassMode mode = pass_access_info_.mode;
const PassInfo pass_info = Pass::get_info(type, pass_access_info_.include_albedo);
const PassInfo pass_info = Pass::get_info(
type, pass_access_info_.include_albedo, pass_access_info_.is_lightgroup);
int num_written_components = pass_info.num_components;
if (pass_info.num_components == 1) {
@@ -215,8 +220,8 @@ void PassAccessor::init_kernel_film_convert(KernelFilmConvert *kfilm_convert,
const Destination &destination) const
{
const PassMode mode = pass_access_info_.mode;
const PassInfo &pass_info = Pass::get_info(pass_access_info_.type,
pass_access_info_.include_albedo);
const PassInfo &pass_info = Pass::get_info(
pass_access_info_.type, pass_access_info_.include_albedo, pass_access_info_.is_lightgroup);
kfilm_convert->pass_offset = pass_access_info_.offset;
kfilm_convert->pass_stride = buffer_params.pass_stride;
@@ -279,8 +284,8 @@ bool PassAccessor::set_render_tile_pixels(RenderBuffers *render_buffers, const S
return false;
}
const PassInfo pass_info = Pass::get_info(pass_access_info_.type,
pass_access_info_.include_albedo);
const PassInfo pass_info = Pass::get_info(
pass_access_info_.type, pass_access_info_.include_albedo, pass_access_info_.is_lightgroup);
const BufferParams &buffer_params = render_buffers->params;

View File

@@ -28,6 +28,7 @@ class PassAccessor {
PassType type = PASS_NONE;
PassMode mode = PassMode::NOISY;
bool include_albedo = false;
bool is_lightgroup = false;
int offset = -1;
/* For the shadow catcher matte pass: whether to approximate shadow catcher pass into its

View File

@@ -20,7 +20,7 @@ RenderScheduler::RenderScheduler(TileManager &tile_manager, const SessionParams
background_(params.background),
pixel_size_(params.pixel_size),
tile_manager_(tile_manager),
default_start_resolution_divider_(pixel_size_ * 8)
default_start_resolution_divider_(params.use_resolution_divider ? pixel_size_ * 8 : 0)
{
use_progressive_noise_floor_ = !background_;
}
@@ -119,7 +119,7 @@ void RenderScheduler::reset(const BufferParams &buffer_params, int num_samples,
/* In background mode never do lower resolution render preview, as it is not really supported
* by the software. */
if (background_) {
if (background_ || start_resolution_divider_ == 0) {
state_.resolution_divider = 1;
}
else {
@@ -1050,6 +1050,10 @@ bool RenderScheduler::work_need_rebalance()
void RenderScheduler::update_start_resolution_divider()
{
if (default_start_resolution_divider_ == 0) {
return;
}
if (start_resolution_divider_ == 0) {
/* Resolution divider has never been calculated before: use default resolution, so that we have
* somewhat good initial behavior, giving a chance to collect real numbers. */

View File

@@ -223,6 +223,7 @@ set(SRC_KERNEL_INTEGRATOR_HEADERS
integrator/intersect_subsurface.h
integrator/intersect_volume_stack.h
integrator/megakernel.h
integrator/mnee.h
integrator/path_state.h
integrator/shade_background.h
integrator/shade_light.h

View File

@@ -31,7 +31,17 @@ ccl_device_inline float frac(float x, int *ix)
return x - (float)i;
}
template<typename T> struct TextureInterpolator {
template<typename TexT, typename OutT = float4> struct TextureInterpolator {
static ccl_always_inline OutT zero()
{
if constexpr (std::is_same<OutT, float4>::value) {
return zero_float4();
}
else {
return 0.0f;
}
}
static ccl_always_inline float4 read(float4 r)
{
@@ -40,21 +50,18 @@ template<typename T> struct TextureInterpolator {
static ccl_always_inline float4 read(uchar4 r)
{
float f = 1.0f / 255.0f;
const float f = 1.0f / 255.0f;
return make_float4(r.x * f, r.y * f, r.z * f, r.w * f);
}
static ccl_always_inline float4 read(uchar r)
static ccl_always_inline float read(uchar r)
{
float f = r * (1.0f / 255.0f);
return make_float4(f, f, f, 1.0f);
return r * (1.0f / 255.0f);
}
static ccl_always_inline float4 read(float r)
static ccl_always_inline float read(float r)
{
/* TODO(dingto): Optimize this, so interpolation
* happens on float instead of float4 */
return make_float4(r, r, r, 1.0f);
return r;
}
static ccl_always_inline float4 read(half4 r)
@@ -62,37 +69,131 @@ template<typename T> struct TextureInterpolator {
return half4_to_float4_image(r);
}
static ccl_always_inline float4 read(half r)
static ccl_always_inline float read(half r)
{
float f = half_to_float_image(r);
return make_float4(f, f, f, 1.0f);
return half_to_float_image(r);
}
static ccl_always_inline float4 read(uint16_t r)
static ccl_always_inline float read(uint16_t r)
{
float f = r * (1.0f / 65535.0f);
return make_float4(f, f, f, 1.0f);
return r * (1.0f / 65535.0f);
}
static ccl_always_inline float4 read(ushort4 r)
{
float f = 1.0f / 65535.0f;
const float f = 1.0f / 65535.0f;
return make_float4(r.x * f, r.y * f, r.z * f, r.w * f);
}
static ccl_always_inline float4 read(const T *data, int x, int y, int width, int height)
/* Read 2D Texture Data
* Does not check if data request is in bounds. */
static ccl_always_inline OutT read(const TexT *data, int x, int y, int width, int height)
{
if (x < 0 || y < 0 || x >= width || y >= height) {
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
return read(data[y * width + x]);
}
/* Read 2D Texture Data Clip
* Returns transparent black if data request is out of bounds. */
static ccl_always_inline OutT read_clip(const TexT *data, int x, int y, int width, int height)
{
if (x < 0 || x >= width || y < 0 || y >= height) {
return zero();
}
return read(data[y * width + x]);
}
/* Read 3D Texture Data
* Does not check if data request is in bounds. */
static ccl_always_inline OutT
read(const TexT *data, int x, int y, int z, int width, int height, int depth)
{
return read(data[x + y * width + z * width * height]);
}
/* Read 3D Texture Data Clip
* Returns transparent black if data request is out of bounds. */
static ccl_always_inline OutT
read_clip(const TexT *data, int x, int y, int z, int width, int height, int depth)
{
if (x < 0 || x >= width || y < 0 || y >= height || z < 0 || z >= depth) {
return zero();
}
return read(data[x + y * width + z * width * height]);
}
/* Trilinear Interpolation */
static ccl_always_inline OutT
trilinear_lookup(const TexT *data,
float tx,
float ty,
float tz,
int ix,
int iy,
int iz,
int nix,
int niy,
int niz,
int width,
int height,
int depth,
OutT read(const TexT *, int, int, int, int, int, int))
{
OutT r = (1.0f - tz) * (1.0f - ty) * (1.0f - tx) *
read(data, ix, iy, iz, width, height, depth);
r += (1.0f - tz) * (1.0f - ty) * tx * read(data, nix, iy, iz, width, height, depth);
r += (1.0f - tz) * ty * (1.0f - tx) * read(data, ix, niy, iz, width, height, depth);
r += (1.0f - tz) * ty * tx * read(data, nix, niy, iz, width, height, depth);
r += tz * (1.0f - ty) * (1.0f - tx) * read(data, ix, iy, niz, width, height, depth);
r += tz * (1.0f - ty) * tx * read(data, nix, iy, niz, width, height, depth);
r += tz * ty * (1.0f - tx) * read(data, ix, niy, niz, width, height, depth);
r += tz * ty * tx * read(data, nix, niy, niz, width, height, depth);
return r;
}
/** Tricubic Interpolation */
static ccl_always_inline OutT
tricubic_lookup(const TexT *data,
float tx,
float ty,
float tz,
const int xc[4],
const int yc[4],
const int zc[4],
int width,
int height,
int depth,
OutT read(const TexT *, int, int, int, int, int, int))
{
float u[4], v[4], w[4];
/* Some helper macros to keep code size reasonable.
* Lets the compiler inline all the matrix multiplications.
*/
#define DATA(x, y, z) (read(data, xc[x], yc[y], zc[z], width, height, depth))
#define COL_TERM(col, row) \
(v[col] * (u[0] * DATA(0, col, row) + u[1] * DATA(1, col, row) + u[2] * DATA(2, col, row) + \
u[3] * DATA(3, col, row)))
#define ROW_TERM(row) \
(w[row] * (COL_TERM(0, row) + COL_TERM(1, row) + COL_TERM(2, row) + COL_TERM(3, row)))
SET_CUBIC_SPLINE_WEIGHTS(u, tx);
SET_CUBIC_SPLINE_WEIGHTS(v, ty);
SET_CUBIC_SPLINE_WEIGHTS(w, tz);
/* Actual interpolation. */
return ROW_TERM(0) + ROW_TERM(1) + ROW_TERM(2) + ROW_TERM(3);
#undef COL_TERM
#undef ROW_TERM
#undef DATA
}
static ccl_always_inline int wrap_periodic(int x, int width)
{
x %= width;
if (x < 0)
if (x < 0) {
x += width;
}
return x;
}
@@ -103,9 +204,8 @@ template<typename T> struct TextureInterpolator {
/* ******** 2D interpolation ******** */
static ccl_always_inline float4 interp_closest(const TextureInfo &info, float x, float y)
static ccl_always_inline OutT interp_closest(const TextureInfo &info, float x, float y)
{
const T *data = (const T *)info.data;
const int width = info.width;
const int height = info.height;
int ix, iy;
@@ -117,105 +217,134 @@ template<typename T> struct TextureInterpolator {
iy = wrap_periodic(iy, height);
break;
case EXTENSION_CLIP:
if (x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f) {
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
/* No samples are inside the clip region. */
if (ix < 0 || ix >= width || iy < 0 || iy >= height) {
return zero();
}
ATTR_FALLTHROUGH;
break;
case EXTENSION_EXTEND:
ix = wrap_clamp(ix, width);
iy = wrap_clamp(iy, height);
break;
default:
kernel_assert(0);
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
return zero();
}
return read(data[ix + iy * width]);
const TexT *data = (const TexT *)info.data;
return read((const TexT *)data, ix, iy, width, height);
}
static ccl_always_inline float4 interp_linear(const TextureInfo &info, float x, float y)
static ccl_always_inline OutT interp_linear(const TextureInfo &info, float x, float y)
{
const T *data = (const T *)info.data;
const int width = info.width;
const int height = info.height;
int ix, iy, nix, niy;
/* A -0.5 offset is used to center the linear samples around the sample point. */
int ix, iy;
int nix, niy;
const float tx = frac(x * (float)width - 0.5f, &ix);
const float ty = frac(y * (float)height - 0.5f, &iy);
switch (info.extension) {
case EXTENSION_REPEAT:
ix = wrap_periodic(ix, width);
iy = wrap_periodic(iy, height);
nix = wrap_periodic(ix + 1, width);
iy = wrap_periodic(iy, height);
niy = wrap_periodic(iy + 1, height);
break;
case EXTENSION_CLIP:
/* No linear samples are inside the clip region. */
if (ix < -1 || ix >= width || iy < -1 || iy >= height) {
return zero();
}
nix = ix + 1;
niy = iy + 1;
break;
case EXTENSION_EXTEND:
nix = wrap_clamp(ix + 1, width);
niy = wrap_clamp(iy + 1, height);
ix = wrap_clamp(ix, width);
niy = wrap_clamp(iy + 1, height);
iy = wrap_clamp(iy, height);
break;
default:
kernel_assert(0);
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
return zero();
}
return (1.0f - ty) * (1.0f - tx) * read(data, ix, iy, width, height) +
(1.0f - ty) * tx * read(data, nix, iy, width, height) +
ty * (1.0f - tx) * read(data, ix, niy, width, height) +
ty * tx * read(data, nix, niy, width, height);
const TexT *data = (const TexT *)info.data;
return (1.0f - ty) * (1.0f - tx) * read_clip(data, ix, iy, width, height) +
(1.0f - ty) * tx * read_clip(data, nix, iy, width, height) +
ty * (1.0f - tx) * read_clip(data, ix, niy, width, height) +
ty * tx * read_clip(data, nix, niy, width, height);
}
static ccl_always_inline float4 interp_cubic(const TextureInfo &info, float x, float y)
static ccl_always_inline OutT interp_cubic(const TextureInfo &info, float x, float y)
{
const T *data = (const T *)info.data;
const int width = info.width;
const int height = info.height;
int ix, iy, nix, niy;
/* A -0.5 offset is used to center the cubic samples around the sample point. */
int ix, iy;
const float tx = frac(x * (float)width - 0.5f, &ix);
const float ty = frac(y * (float)height - 0.5f, &iy);
int pix, piy, nnix, nniy;
int pix, piy;
int nix, niy;
int nnix, nniy;
switch (info.extension) {
case EXTENSION_REPEAT:
ix = wrap_periodic(ix, width);
iy = wrap_periodic(iy, height);
pix = wrap_periodic(ix - 1, width);
piy = wrap_periodic(iy - 1, height);
nix = wrap_periodic(ix + 1, width);
niy = wrap_periodic(iy + 1, height);
nnix = wrap_periodic(ix + 2, width);
iy = wrap_periodic(iy, height);
piy = wrap_periodic(iy - 1, height);
niy = wrap_periodic(iy + 1, height);
nniy = wrap_periodic(iy + 2, height);
break;
case EXTENSION_CLIP:
/* No cubic samples are inside the clip region. */
if (ix < -2 || ix > width || iy < -2 || iy > height) {
return zero();
}
pix = ix - 1;
piy = iy - 1;
nix = ix + 1;
niy = iy + 1;
nnix = ix + 2;
piy = iy - 1;
niy = iy + 1;
nniy = iy + 2;
break;
case EXTENSION_EXTEND:
pix = wrap_clamp(ix - 1, width);
piy = wrap_clamp(iy - 1, height);
nix = wrap_clamp(ix + 1, width);
niy = wrap_clamp(iy + 1, height);
nnix = wrap_clamp(ix + 2, width);
nniy = wrap_clamp(iy + 2, height);
ix = wrap_clamp(ix, width);
piy = wrap_clamp(iy - 1, height);
niy = wrap_clamp(iy + 1, height);
nniy = wrap_clamp(iy + 2, height);
iy = wrap_clamp(iy, height);
break;
default:
kernel_assert(0);
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
return zero();
}
const TexT *data = (const TexT *)info.data;
const int xc[4] = {pix, ix, nix, nnix};
const int yc[4] = {piy, iy, niy, nniy};
float u[4], v[4];
/* Some helper macro to keep code reasonable size,
* let compiler to inline all the matrix multiplications.
/* Some helper macros to keep code size reasonable.
* Lets the compiler inline all the matrix multiplications.
*/
#define DATA(x, y) (read(data, xc[x], yc[y], width, height))
#define DATA(x, y) (read_clip(data, xc[x], yc[y], width, height))
#define TERM(col) \
(v[col] * \
(u[0] * DATA(0, col) + u[1] * DATA(1, col) + u[2] * DATA(2, col) + u[3] * DATA(3, col)))
@@ -229,11 +358,8 @@ template<typename T> struct TextureInterpolator {
#undef DATA
}
static ccl_always_inline float4 interp(const TextureInfo &info, float x, float y)
static ccl_always_inline OutT interp(const TextureInfo &info, float x, float y)
{
if (UNLIKELY(!info.data)) {
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
}
switch (info.interpolation) {
case INTERPOLATION_CLOSEST:
return interp_closest(info, x, y);
@@ -246,14 +372,14 @@ template<typename T> struct TextureInterpolator {
/* ******** 3D interpolation ******** */
static ccl_always_inline float4 interp_3d_closest(const TextureInfo &info,
float x,
float y,
float z)
static ccl_always_inline OutT interp_3d_closest(const TextureInfo &info,
float x,
float y,
float z)
{
int width = info.width;
int height = info.height;
int depth = info.depth;
const int width = info.width;
const int height = info.height;
const int depth = info.depth;
int ix, iy, iz;
frac(x * (float)width, &ix);
@@ -267,10 +393,11 @@ template<typename T> struct TextureInterpolator {
iz = wrap_periodic(iz, depth);
break;
case EXTENSION_CLIP:
if (x < 0.0f || y < 0.0f || z < 0.0f || x > 1.0f || y > 1.0f || z > 1.0f) {
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
/* No samples are inside the clip region. */
if (ix < 0 || ix >= width || iy < 0 || iy >= height || iz < 0 || iz >= depth) {
return zero();
}
ATTR_FALLTHROUGH;
break;
case EXTENSION_EXTEND:
ix = wrap_clamp(ix, width);
iy = wrap_clamp(iy, height);
@@ -278,24 +405,25 @@ template<typename T> struct TextureInterpolator {
break;
default:
kernel_assert(0);
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
return zero();
}
const T *data = (const T *)info.data;
return read(data[ix + iy * width + iz * width * height]);
const TexT *data = (const TexT *)info.data;
return read(data, ix, iy, iz, width, height, depth);
}
static ccl_always_inline float4 interp_3d_linear(const TextureInfo &info,
float x,
float y,
float z)
static ccl_always_inline OutT interp_3d_linear(const TextureInfo &info,
float x,
float y,
float z)
{
int width = info.width;
int height = info.height;
int depth = info.depth;
const int width = info.width;
const int height = info.height;
const int depth = info.depth;
int ix, iy, iz;
int nix, niy, niz;
/* A -0.5 offset is used to center the linear samples around the sample point. */
float tx = frac(x * (float)width - 0.5f, &ix);
float ty = frac(y * (float)height - 0.5f, &iy);
float tz = frac(z * (float)depth - 0.5f, &iz);
@@ -303,50 +431,79 @@ template<typename T> struct TextureInterpolator {
switch (info.extension) {
case EXTENSION_REPEAT:
ix = wrap_periodic(ix, width);
iy = wrap_periodic(iy, height);
iz = wrap_periodic(iz, depth);
nix = wrap_periodic(ix + 1, width);
iy = wrap_periodic(iy, height);
niy = wrap_periodic(iy + 1, height);
iz = wrap_periodic(iz, depth);
niz = wrap_periodic(iz + 1, depth);
break;
case EXTENSION_CLIP:
if (x < 0.0f || y < 0.0f || z < 0.0f || x > 1.0f || y > 1.0f || z > 1.0f) {
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
/* No linear samples are inside the clip region. */
if (ix < -1 || ix >= width || iy < -1 || iy >= height || iz < -1 || iz >= depth) {
return zero();
}
ATTR_FALLTHROUGH;
nix = ix + 1;
niy = iy + 1;
niz = iz + 1;
/* All linear samples are inside the clip region. */
if (ix >= 0 && nix < width && iy >= 0 && niy < height && iz >= 0 && niz < depth) {
break;
}
/* The linear samples span the clip border.
* #read_clip is used to ensure proper interpolation across the clip border. */
return trilinear_lookup((const TexT *)info.data,
tx,
ty,
tz,
ix,
iy,
iz,
nix,
niy,
niz,
width,
height,
depth,
read_clip);
case EXTENSION_EXTEND:
nix = wrap_clamp(ix + 1, width);
niy = wrap_clamp(iy + 1, height);
niz = wrap_clamp(iz + 1, depth);
ix = wrap_clamp(ix, width);
niy = wrap_clamp(iy + 1, height);
iy = wrap_clamp(iy, height);
niz = wrap_clamp(iz + 1, depth);
iz = wrap_clamp(iz, depth);
break;
default:
kernel_assert(0);
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
return zero();
}
const T *data = (const T *)info.data;
float4 r;
r = (1.0f - tz) * (1.0f - ty) * (1.0f - tx) *
read(data[ix + iy * width + iz * width * height]);
r += (1.0f - tz) * (1.0f - ty) * tx * read(data[nix + iy * width + iz * width * height]);
r += (1.0f - tz) * ty * (1.0f - tx) * read(data[ix + niy * width + iz * width * height]);
r += (1.0f - tz) * ty * tx * read(data[nix + niy * width + iz * width * height]);
r += tz * (1.0f - ty) * (1.0f - tx) * read(data[ix + iy * width + niz * width * height]);
r += tz * (1.0f - ty) * tx * read(data[nix + iy * width + niz * width * height]);
r += tz * ty * (1.0f - tx) * read(data[ix + niy * width + niz * width * height]);
r += tz * ty * tx * read(data[nix + niy * width + niz * width * height]);
return r;
return trilinear_lookup((const TexT *)info.data,
tx,
ty,
tz,
ix,
iy,
iz,
nix,
niy,
niz,
width,
height,
depth,
read);
}
/* TODO(sergey): For some unspeakable reason both GCC-6 and Clang-3.9 are
/* Tricubic b-spline interpolation.
*
* TODO(sergey): For some unspeakable reason both GCC-6 and Clang-3.9 are
* causing stack overflow issue in this function unless it is inlined.
*
* Only happens for AVX2 kernel and global __KERNEL_SSE__ vectorization
@@ -357,100 +514,101 @@ template<typename T> struct TextureInterpolator {
#else
static ccl_never_inline
#endif
float4
OutT
interp_3d_cubic(const TextureInfo &info, float x, float y, float z)
{
int width = info.width;
int height = info.height;
int depth = info.depth;
int ix, iy, iz;
int nix, niy, niz;
/* Tricubic b-spline interpolation. */
/* A -0.5 offset is used to center the cubic samples around the sample point. */
const float tx = frac(x * (float)width - 0.5f, &ix);
const float ty = frac(y * (float)height - 0.5f, &iy);
const float tz = frac(z * (float)depth - 0.5f, &iz);
int pix, piy, piz, nnix, nniy, nniz;
int pix, piy, piz;
int nix, niy, niz;
int nnix, nniy, nniz;
switch (info.extension) {
case EXTENSION_REPEAT:
ix = wrap_periodic(ix, width);
iy = wrap_periodic(iy, height);
iz = wrap_periodic(iz, depth);
pix = wrap_periodic(ix - 1, width);
piy = wrap_periodic(iy - 1, height);
piz = wrap_periodic(iz - 1, depth);
nix = wrap_periodic(ix + 1, width);
niy = wrap_periodic(iy + 1, height);
niz = wrap_periodic(iz + 1, depth);
nnix = wrap_periodic(ix + 2, width);
iy = wrap_periodic(iy, height);
niy = wrap_periodic(iy + 1, height);
piy = wrap_periodic(iy - 1, height);
nniy = wrap_periodic(iy + 2, height);
iz = wrap_periodic(iz, depth);
piz = wrap_periodic(iz - 1, depth);
niz = wrap_periodic(iz + 1, depth);
nniz = wrap_periodic(iz + 2, depth);
break;
case EXTENSION_CLIP:
if (x < 0.0f || y < 0.0f || z < 0.0f || x > 1.0f || y > 1.0f || z > 1.0f) {
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
case EXTENSION_CLIP: {
/* No cubic samples are inside the clip region. */
if (ix < -2 || ix > width || iy < -2 || iy > height || iz < -2 || iz > depth) {
return zero();
}
ATTR_FALLTHROUGH;
pix = ix - 1;
nnix = ix + 2;
nix = ix + 1;
piy = iy - 1;
niy = iy + 1;
nniy = iy + 2;
piz = iz - 1;
niz = iz + 1;
nniz = iz + 2;
/* All cubic samples are inside the clip region. */
if (pix >= 0 && nnix < width && piy >= 0 && nniy < height && piz >= 0 && nniz < depth) {
break;
}
/* The Cubic samples span the clip border.
* read_clip is used to ensure proper interpolation across the clip border. */
const int xc[4] = {pix, ix, nix, nnix};
const int yc[4] = {piy, iy, niy, nniy};
const int zc[4] = {piz, iz, niz, nniz};
return tricubic_lookup(
(const TexT *)info.data, tx, ty, tz, xc, yc, zc, width, height, depth, read_clip);
}
case EXTENSION_EXTEND:
pix = wrap_clamp(ix - 1, width);
piy = wrap_clamp(iy - 1, height);
piz = wrap_clamp(iz - 1, depth);
nix = wrap_clamp(ix + 1, width);
niy = wrap_clamp(iy + 1, height);
niz = wrap_clamp(iz + 1, depth);
nnix = wrap_clamp(ix + 2, width);
nniy = wrap_clamp(iy + 2, height);
nniz = wrap_clamp(iz + 2, depth);
ix = wrap_clamp(ix, width);
piy = wrap_clamp(iy - 1, height);
niy = wrap_clamp(iy + 1, height);
nniy = wrap_clamp(iy + 2, height);
iy = wrap_clamp(iy, height);
piz = wrap_clamp(iz - 1, depth);
niz = wrap_clamp(iz + 1, depth);
nniz = wrap_clamp(iz + 2, depth);
iz = wrap_clamp(iz, depth);
break;
default:
kernel_assert(0);
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
return zero();
}
const int xc[4] = {pix, ix, nix, nnix};
const int yc[4] = {width * piy, width * iy, width * niy, width * nniy};
const int zc[4] = {
width * height * piz, width * height * iz, width * height * niz, width * height * nniz};
float u[4], v[4], w[4];
/* Some helper macro to keep code reasonable size,
* let compiler to inline all the matrix multiplications.
*/
#define DATA(x, y, z) (read(data[xc[x] + yc[y] + zc[z]]))
#define COL_TERM(col, row) \
(v[col] * (u[0] * DATA(0, col, row) + u[1] * DATA(1, col, row) + u[2] * DATA(2, col, row) + \
u[3] * DATA(3, col, row)))
#define ROW_TERM(row) \
(w[row] * (COL_TERM(0, row) + COL_TERM(1, row) + COL_TERM(2, row) + COL_TERM(3, row)))
SET_CUBIC_SPLINE_WEIGHTS(u, tx);
SET_CUBIC_SPLINE_WEIGHTS(v, ty);
SET_CUBIC_SPLINE_WEIGHTS(w, tz);
/* Actual interpolation. */
const T *data = (const T *)info.data;
return ROW_TERM(0) + ROW_TERM(1) + ROW_TERM(2) + ROW_TERM(3);
#undef COL_TERM
#undef ROW_TERM
#undef DATA
const int yc[4] = {piy, iy, niy, nniy};
const int zc[4] = {piz, iz, niz, nniz};
const TexT *data = (const TexT *)info.data;
return tricubic_lookup(data, tx, ty, tz, xc, yc, zc, width, height, depth, read);
}
static ccl_always_inline float4
static ccl_always_inline OutT
interp_3d(const TextureInfo &info, float x, float y, float z, InterpolationType interp)
{
if (UNLIKELY(!info.data))
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
switch ((interp == INTERPOLATION_NONE) ? info.interpolation : interp) {
case INTERPOLATION_CLOSEST:
return interp_3d_closest(info, x, y, z);
@@ -463,13 +621,13 @@ template<typename T> struct TextureInterpolator {
};
#ifdef WITH_NANOVDB
template<typename T> struct NanoVDBInterpolator {
template<typename TexT, typename OutT = float4> struct NanoVDBInterpolator {
typedef typename nanovdb::NanoGrid<T>::AccessorType AccessorType;
typedef typename nanovdb::NanoGrid<TexT>::AccessorType AccessorType;
static ccl_always_inline float4 read(float r)
static ccl_always_inline float read(float r)
{
return make_float4(r, r, r, 1.0f);
return r;
}
static ccl_always_inline float4 read(nanovdb::Vec3f r)
@@ -477,40 +635,43 @@ template<typename T> struct NanoVDBInterpolator {
return make_float4(r[0], r[1], r[2], 1.0f);
}
static ccl_always_inline float4 interp_3d_closest(const AccessorType &acc,
float x,
float y,
float z)
static ccl_always_inline OutT interp_3d_closest(const AccessorType &acc,
float x,
float y,
float z)
{
const nanovdb::Vec3f xyz(x, y, z);
return read(nanovdb::SampleFromVoxels<AccessorType, 0, false>(acc)(xyz));
}
static ccl_always_inline float4 interp_3d_linear(const AccessorType &acc,
float x,
float y,
float z)
static ccl_always_inline OutT interp_3d_linear(const AccessorType &acc,
float x,
float y,
float z)
{
const nanovdb::Vec3f xyz(x - 0.5f, y - 0.5f, z - 0.5f);
return read(nanovdb::SampleFromVoxels<AccessorType, 1, false>(acc)(xyz));
}
/* Tricubic b-spline interpolation. */
# if defined(__GNUC__) || defined(__clang__)
static ccl_always_inline
# else
static ccl_never_inline
# endif
float4
OutT
interp_3d_cubic(const AccessorType &acc, float x, float y, float z)
{
int ix, iy, iz;
int nix, niy, niz;
int pix, piy, piz;
int nnix, nniy, nniz;
/* Tricubic b-spline interpolation. */
/* A -0.5 offset is used to center the cubic samples around the sample point. */
const float tx = frac(x - 0.5f, &ix);
const float ty = frac(y - 0.5f, &iy);
const float tz = frac(z - 0.5f, &iz);
pix = ix - 1;
piy = iy - 1;
piz = iz - 1;
@@ -526,8 +687,8 @@ template<typename T> struct NanoVDBInterpolator {
const int zc[4] = {piz, iz, niz, nniz};
float u[4], v[4], w[4];
/* Some helper macro to keep code reasonable size,
* let compiler to inline all the matrix multiplications.
/* Some helper macros to keep code size reasonable.
* Lets the compiler inline all the matrix multiplications.
*/
# define DATA(x, y, z) (read(acc.getValue(nanovdb::Coord(xc[x], yc[y], zc[z]))))
# define COL_TERM(col, row) \
@@ -548,12 +709,12 @@ template<typename T> struct NanoVDBInterpolator {
# undef DATA
}
static ccl_always_inline float4
static ccl_always_inline OutT
interp_3d(const TextureInfo &info, float x, float y, float z, InterpolationType interp)
{
using namespace nanovdb;
NanoGrid<T> *const grid = (NanoGrid<T> *)info.data;
NanoGrid<TexT> *const grid = (NanoGrid<TexT> *)info.data;
AccessorType acc = grid->getAccessor();
switch ((interp == INTERPOLATION_NONE) ? info.interpolation : interp) {
@@ -574,15 +735,27 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals kg, int id, float x, flo
{
const TextureInfo &info = kernel_tex_fetch(__texture_info, id);
if (UNLIKELY(!info.data)) {
return zero_float4();
}
switch (info.data_type) {
case IMAGE_DATA_TYPE_HALF:
return TextureInterpolator<half>::interp(info, x, y);
case IMAGE_DATA_TYPE_BYTE:
return TextureInterpolator<uchar>::interp(info, x, y);
case IMAGE_DATA_TYPE_USHORT:
return TextureInterpolator<uint16_t>::interp(info, x, y);
case IMAGE_DATA_TYPE_FLOAT:
return TextureInterpolator<float>::interp(info, x, y);
case IMAGE_DATA_TYPE_HALF: {
const float f = TextureInterpolator<half, float>::interp(info, x, y);
return make_float4(f, f, f, 1.0f);
}
case IMAGE_DATA_TYPE_BYTE: {
const float f = TextureInterpolator<uchar, float>::interp(info, x, y);
return make_float4(f, f, f, 1.0f);
}
case IMAGE_DATA_TYPE_USHORT: {
const float f = TextureInterpolator<uint16_t, float>::interp(info, x, y);
return make_float4(f, f, f, 1.0f);
}
case IMAGE_DATA_TYPE_FLOAT: {
const float f = TextureInterpolator<float, float>::interp(info, x, y);
return make_float4(f, f, f, 1.0f);
}
case IMAGE_DATA_TYPE_HALF4:
return TextureInterpolator<half4>::interp(info, x, y);
case IMAGE_DATA_TYPE_BYTE4:
@@ -605,19 +778,30 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals kg,
{
const TextureInfo &info = kernel_tex_fetch(__texture_info, id);
if (UNLIKELY(!info.data)) {
return zero_float4();
}
if (info.use_transform_3d) {
P = transform_point(&info.transform_3d, P);
}
switch (info.data_type) {
case IMAGE_DATA_TYPE_HALF:
return TextureInterpolator<half>::interp_3d(info, P.x, P.y, P.z, interp);
case IMAGE_DATA_TYPE_BYTE:
return TextureInterpolator<uchar>::interp_3d(info, P.x, P.y, P.z, interp);
case IMAGE_DATA_TYPE_USHORT:
return TextureInterpolator<uint16_t>::interp_3d(info, P.x, P.y, P.z, interp);
case IMAGE_DATA_TYPE_FLOAT:
return TextureInterpolator<float>::interp_3d(info, P.x, P.y, P.z, interp);
case IMAGE_DATA_TYPE_HALF: {
const float f = TextureInterpolator<half, float>::interp_3d(info, P.x, P.y, P.z, interp);
return make_float4(f, f, f, 1.0f);
}
case IMAGE_DATA_TYPE_BYTE: {
const float f = TextureInterpolator<uchar, float>::interp_3d(info, P.x, P.y, P.z, interp);
return make_float4(f, f, f, 1.0f);
}
case IMAGE_DATA_TYPE_USHORT: {
const float f = TextureInterpolator<uint16_t, float>::interp_3d(info, P.x, P.y, P.z, interp);
return make_float4(f, f, f, 1.0f);
}
case IMAGE_DATA_TYPE_FLOAT: {
const float f = TextureInterpolator<float, float>::interp_3d(info, P.x, P.y, P.z, interp);
return make_float4(f, f, f, 1.0f);
}
case IMAGE_DATA_TYPE_HALF4:
return TextureInterpolator<half4>::interp_3d(info, P.x, P.y, P.z, interp);
case IMAGE_DATA_TYPE_BYTE4:
@@ -627,8 +811,10 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals kg,
case IMAGE_DATA_TYPE_FLOAT4:
return TextureInterpolator<float4>::interp_3d(info, P.x, P.y, P.z, interp);
#ifdef WITH_NANOVDB
case IMAGE_DATA_TYPE_NANOVDB_FLOAT:
return NanoVDBInterpolator<float>::interp_3d(info, P.x, P.y, P.z, interp);
case IMAGE_DATA_TYPE_NANOVDB_FLOAT: {
const float f = NanoVDBInterpolator<float, float>::interp_3d(info, P.x, P.y, P.z, interp);
return make_float4(f, f, f, 1.0f);
}
case IMAGE_DATA_TYPE_NANOVDB_FLOAT3:
return NanoVDBInterpolator<nanovdb::Vec3f>::interp_3d(info, P.x, P.y, P.z, interp);
#endif

View File

@@ -76,10 +76,11 @@ typedef unsigned long long uint64_t;
/* GPU texture objects */
typedef unsigned long long CUtexObject;
typedef CUtexObject ccl_gpu_tex_object;
typedef CUtexObject ccl_gpu_tex_object_2D;
typedef CUtexObject ccl_gpu_tex_object_3D;
template<typename T>
ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object texobj,
ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object_2D texobj,
const float x,
const float y)
{
@@ -87,7 +88,7 @@ ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object tex
}
template<typename T>
ccl_device_forceinline T ccl_gpu_tex_object_read_3D(const ccl_gpu_tex_object texobj,
ccl_device_forceinline T ccl_gpu_tex_object_read_3D(const ccl_gpu_tex_object_3D texobj,
const float x,
const float y,
const float z)

View File

@@ -88,6 +88,7 @@
extern "C" __global__ void __launch_bounds__(block_num_threads)
#define ccl_gpu_kernel_signature(name, ...) kernel_gpu_##name(__VA_ARGS__)
#define ccl_gpu_kernel_postfix
#define ccl_gpu_kernel_call(x) x

View File

@@ -56,7 +56,7 @@ ccl_device_noinline T kernel_tex_image_interp_bicubic(ccl_global const TextureIn
float x,
float y)
{
ccl_gpu_tex_object tex = (ccl_gpu_tex_object)info.data;
ccl_gpu_tex_object_2D tex = (ccl_gpu_tex_object_2D)info.data;
x = (x * info.width) - 0.5f;
y = (y * info.height) - 0.5f;
@@ -85,7 +85,7 @@ template<typename T>
ccl_device_noinline T
kernel_tex_image_interp_tricubic(ccl_global const TextureInfo &info, float x, float y, float z)
{
ccl_gpu_tex_object tex = (ccl_gpu_tex_object)info.data;
ccl_gpu_tex_object_3D tex = (ccl_gpu_tex_object_3D)info.data;
x = (x * info.width) - 0.5f;
y = (y * info.height) - 0.5f;
@@ -190,7 +190,7 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals kg, int id, float x, flo
return kernel_tex_image_interp_bicubic<float4>(info, x, y);
}
else {
ccl_gpu_tex_object tex = (ccl_gpu_tex_object)info.data;
ccl_gpu_tex_object_2D tex = (ccl_gpu_tex_object_2D)info.data;
return ccl_gpu_tex_object_read_2D<float4>(tex, x, y);
}
}
@@ -202,7 +202,7 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals kg, int id, float x, flo
f = kernel_tex_image_interp_bicubic<float>(info, x, y);
}
else {
ccl_gpu_tex_object tex = (ccl_gpu_tex_object)info.data;
ccl_gpu_tex_object_2D tex = (ccl_gpu_tex_object_2D)info.data;
f = ccl_gpu_tex_object_read_2D<float>(tex, x, y);
}
@@ -245,7 +245,7 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals kg,
return kernel_tex_image_interp_tricubic<float4>(info, x, y, z);
}
else {
ccl_gpu_tex_object tex = (ccl_gpu_tex_object)info.data;
ccl_gpu_tex_object_3D tex = (ccl_gpu_tex_object_3D)info.data;
return ccl_gpu_tex_object_read_3D<float4>(tex, x, y, z);
}
}
@@ -256,7 +256,7 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals kg,
f = kernel_tex_image_interp_tricubic<float>(info, x, y, z);
}
else {
ccl_gpu_tex_object tex = (ccl_gpu_tex_object)info.data;
ccl_gpu_tex_object_3D tex = (ccl_gpu_tex_object_3D)info.data;
f = ccl_gpu_tex_object_read_3D<float>(tex, x, y, z);
}

View File

@@ -58,6 +58,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
INTEGRATOR_STATE_WRITE(state, shadow_path, queued_kernel) = 0;
}
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(integrator_init_from_camera,
@@ -89,6 +90,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(
integrator_init_from_camera(nullptr, state, tile, render_buffer, x, y, sample));
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(integrator_init_from_bake,
@@ -120,6 +122,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(
integrator_init_from_bake(nullptr, state, tile, render_buffer, x, y, sample));
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(integrator_intersect_closest,
@@ -134,6 +137,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(integrator_intersect_closest(NULL, state, render_buffer));
}
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(integrator_intersect_shadow,
@@ -147,6 +151,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(integrator_intersect_shadow(NULL, state));
}
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(integrator_intersect_subsurface,
@@ -160,6 +165,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(integrator_intersect_subsurface(NULL, state));
}
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(integrator_intersect_volume_stack,
@@ -173,6 +179,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(integrator_intersect_volume_stack(NULL, state));
}
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(integrator_shade_background,
@@ -187,6 +194,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(integrator_shade_background(NULL, state, render_buffer));
}
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(integrator_shade_light,
@@ -201,6 +209,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(integrator_shade_light(NULL, state, render_buffer));
}
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(integrator_shade_shadow,
@@ -215,6 +224,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(integrator_shade_shadow(NULL, state, render_buffer));
}
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(integrator_shade_surface,
@@ -229,6 +239,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(integrator_shade_surface(NULL, state, render_buffer));
}
}
ccl_gpu_kernel_postfix
#ifdef __KERNEL_METAL__
constant int __dummy_constant [[function_constant(0)]];
@@ -256,6 +267,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
#endif
}
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(integrator_shade_volume,
@@ -270,6 +282,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(integrator_shade_volume(NULL, state, render_buffer));
}
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
ccl_gpu_kernel_signature(integrator_queued_paths_array,
@@ -288,6 +301,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
num_indices,
ccl_gpu_kernel_lambda_pass);
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
ccl_gpu_kernel_signature(integrator_queued_shadow_paths_array,
@@ -306,6 +320,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
num_indices,
ccl_gpu_kernel_lambda_pass);
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
ccl_gpu_kernel_signature(integrator_active_paths_array,
@@ -321,6 +336,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
num_indices,
ccl_gpu_kernel_lambda_pass);
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
ccl_gpu_kernel_signature(integrator_terminated_paths_array,
@@ -337,6 +353,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
num_indices,
ccl_gpu_kernel_lambda_pass);
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
ccl_gpu_kernel_signature(integrator_terminated_shadow_paths_array,
@@ -353,6 +370,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
num_indices,
ccl_gpu_kernel_lambda_pass);
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
ccl_gpu_kernel_signature(integrator_sorted_paths_array,
@@ -380,6 +398,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
key_prefix_sum,
ccl_gpu_kernel_lambda_pass);
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
ccl_gpu_kernel_signature(integrator_compact_paths_array,
@@ -399,6 +418,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
num_indices,
ccl_gpu_kernel_lambda_pass);
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
ccl_gpu_kernel_signature(integrator_compact_states,
@@ -416,6 +436,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
ccl_gpu_kernel_call(integrator_state_move(NULL, to_state, from_state));
}
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
ccl_gpu_kernel_signature(integrator_compact_shadow_paths_array,
@@ -435,6 +456,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
num_indices,
ccl_gpu_kernel_lambda_pass);
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
ccl_gpu_kernel_signature(integrator_compact_shadow_states,
@@ -452,12 +474,14 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
ccl_gpu_kernel_call(integrator_shadow_state_move(NULL, to_state, from_state));
}
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel_threads(GPU_PARALLEL_PREFIX_SUM_DEFAULT_BLOCK_SIZE) ccl_gpu_kernel_signature(
prefix_sum, ccl_global int *counter, ccl_global int *prefix_sum, int num_values)
{
gpu_parallel_prefix_sum(ccl_gpu_global_id_x(), counter, prefix_sum, num_values);
}
ccl_gpu_kernel_postfix
/* --------------------------------------------------------------------
* Adaptive sampling.
@@ -494,6 +518,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
atomic_fetch_and_add_uint32(num_active_pixels, popcount(num_active_pixels_mask));
}
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(adaptive_sampling_filter_x,
@@ -512,6 +537,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
kernel_adaptive_sampling_filter_x(NULL, render_buffer, sy + y, sx, sw, offset, stride));
}
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(adaptive_sampling_filter_y,
@@ -530,6 +556,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
kernel_adaptive_sampling_filter_y(NULL, render_buffer, sx + x, sy, sh, offset, stride));
}
}
ccl_gpu_kernel_postfix
/* --------------------------------------------------------------------
* Cryptomatte.
@@ -546,6 +573,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(kernel_cryptomatte_post(nullptr, render_buffer, pixel_index));
}
}
ccl_gpu_kernel_postfix
/* --------------------------------------------------------------------
* Film.
@@ -627,6 +655,7 @@ ccl_device_inline void kernel_gpu_film_convert_half_write(ccl_global uchar4 *rgb
\
FILM_GET_PASS_PIXEL_F32(variant, input_channel_count); \
} \
ccl_gpu_kernel_postfix \
\
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) \
ccl_gpu_kernel_signature(film_convert_##variant##_half_rgba, \
@@ -666,7 +695,8 @@ ccl_device_inline void kernel_gpu_film_convert_half_write(ccl_global uchar4 *rgb
const half4 half_pixel = float4_to_half4_display( \
make_float4(pixel[0], pixel[1], pixel[2], pixel[3])); \
kernel_gpu_film_convert_half_write(rgba, rgba_offset, rgba_stride, x, y, half_pixel); \
}
} \
ccl_gpu_kernel_postfix
/* 1 channel inputs */
KERNEL_FILM_CONVERT_VARIANT(depth, 1)
@@ -706,6 +736,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(kernel_displace_evaluate(NULL, input, output, offset + i));
}
}
ccl_gpu_kernel_postfix
/* Background */
@@ -721,6 +752,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(kernel_background_evaluate(NULL, input, output, offset + i));
}
}
ccl_gpu_kernel_postfix
/* Curve Shadow Transparency */
@@ -737,6 +769,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
kernel_curve_shadow_transparency_evaluate(NULL, input, output, offset + i));
}
}
ccl_gpu_kernel_postfix
/* --------------------------------------------------------------------
* Denoising.
@@ -770,6 +803,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
color_out[1] = clamp(color_out[1], 0.0f, 10000.0f);
color_out[2] = clamp(color_out[2], 0.0f, 10000.0f);
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(filter_guiding_preprocess,
@@ -849,6 +883,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
flow_out[1] = -motion_in[1] * pixel_scale;
}
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(filter_guiding_set_fake_albedo,
@@ -877,6 +912,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
albedo_out[1] = 0.5f;
albedo_out[2] = 0.5f;
}
ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(filter_color_postprocess,
@@ -936,6 +972,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
denoised_pixel[3] = 0;
}
}
ccl_gpu_kernel_postfix
/* --------------------------------------------------------------------
* Shadow catcher.
@@ -961,3 +998,4 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
atomic_fetch_and_add_uint32(num_possible_splits, popcount(can_split_mask));
}
}
ccl_gpu_kernel_postfix

View File

@@ -73,10 +73,11 @@ typedef unsigned long long uint64_t;
#define ccl_gpu_ballot(predicate) __ballot(predicate)
/* GPU texture objects */
typedef hipTextureObject_t ccl_gpu_tex_object;
typedef hipTextureObject_t ccl_gpu_tex_object_2D;
typedef hipTextureObject_t ccl_gpu_tex_object_3D;
template<typename T>
ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object texobj,
ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object_2D texobj,
const float x,
const float y)
{
@@ -84,7 +85,7 @@ ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object tex
}
template<typename T>
ccl_device_forceinline T ccl_gpu_tex_object_read_3D(const ccl_gpu_tex_object texobj,
ccl_device_forceinline T ccl_gpu_tex_object_read_3D(const ccl_gpu_tex_object_3D texobj,
const float x,
const float y,
const float z)

View File

@@ -31,6 +31,7 @@
extern "C" __global__ void __launch_bounds__(block_num_threads)
#define ccl_gpu_kernel_signature(name, ...) kernel_gpu_##name(__VA_ARGS__)
#define ccl_gpu_kernel_postfix
#define ccl_gpu_kernel_call(x) x

View File

@@ -132,6 +132,7 @@ void kernel_gpu_##name::run(thread MetalKernelContext& context, \
uint simd_group_index, \
uint num_simd_groups) ccl_global const
#define ccl_gpu_kernel_postfix
#define ccl_gpu_kernel_call(x) context.x
/* define a function object where "func" is the lambda body, and additional parameters are used to specify captured state */

View File

@@ -19,17 +19,18 @@ class MetalKernelContext {
{}
/* texture fetch adapter functions */
typedef uint64_t ccl_gpu_tex_object;
typedef uint64_t ccl_gpu_tex_object_2D;
typedef uint64_t ccl_gpu_tex_object_3D;
template<typename T>
inline __attribute__((__always_inline__))
T ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object tex, float x, float y) const {
T ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object_2D tex, float x, float y) const {
kernel_assert(0);
return 0;
}
template<typename T>
inline __attribute__((__always_inline__))
T ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object tex, float x, float y, float z) const {
T ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object_3D tex, float x, float y, float z) const {
kernel_assert(0);
return 0;
}
@@ -37,14 +38,14 @@ class MetalKernelContext {
// texture2d
template<>
inline __attribute__((__always_inline__))
float4 ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object tex, float x, float y) const {
float4 ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object_2D tex, float x, float y) const {
const uint tid(tex);
const uint sid(tex >> 32);
return metal_ancillaries->textures_2d[tid].tex.sample(metal_samplers[sid], float2(x, y));
}
template<>
inline __attribute__((__always_inline__))
float ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object tex, float x, float y) const {
float ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object_2D tex, float x, float y) const {
const uint tid(tex);
const uint sid(tex >> 32);
return metal_ancillaries->textures_2d[tid].tex.sample(metal_samplers[sid], float2(x, y)).x;
@@ -53,14 +54,14 @@ class MetalKernelContext {
// texture3d
template<>
inline __attribute__((__always_inline__))
float4 ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object tex, float x, float y, float z) const {
float4 ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object_3D tex, float x, float y, float z) const {
const uint tid(tex);
const uint sid(tex >> 32);
return metal_ancillaries->textures_3d[tid].tex.sample(metal_samplers[sid], float3(x, y, z));
}
template<>
inline __attribute__((__always_inline__))
float ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object tex, float x, float y, float z) const {
float ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object_3D tex, float x, float y, float z) const {
const uint tid(tex);
const uint sid(tex >> 32);
return metal_ancillaries->textures_3d[tid].tex.sample(metal_samplers[sid], float3(x, y, z)).x;

View File

@@ -78,10 +78,11 @@ typedef unsigned long long uint64_t;
/* GPU texture objects */
typedef unsigned long long CUtexObject;
typedef CUtexObject ccl_gpu_tex_object;
typedef CUtexObject ccl_gpu_tex_object_2D;
typedef CUtexObject ccl_gpu_tex_object_3D;
template<typename T>
ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object texobj,
ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object_2D texobj,
const float x,
const float y)
{
@@ -89,7 +90,7 @@ ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object tex
}
template<typename T>
ccl_device_forceinline T ccl_gpu_tex_object_read_3D(const ccl_gpu_tex_object texobj,
ccl_device_forceinline T ccl_gpu_tex_object_read_3D(const ccl_gpu_tex_object_3D texobj,
const float x,
const float y,
const float z)

View File

@@ -320,12 +320,13 @@ ccl_device_inline void kernel_accum_combined_transparent_pass(KernelGlobals kg,
}
/* Write background or emission to appropriate pass. */
ccl_device_inline void kernel_accum_emission_or_background_pass(KernelGlobals kg,
ConstIntegratorState state,
float3 contribution,
ccl_global float *ccl_restrict
buffer,
const int pass)
ccl_device_inline void kernel_accum_emission_or_background_pass(
KernelGlobals kg,
ConstIntegratorState state,
float3 contribution,
ccl_global float *ccl_restrict buffer,
const int pass,
const int lightgroup = LIGHTGROUP_NONE)
{
if (!(kernel_data.film.light_pass_flag & PASS_ANY)) {
return;
@@ -347,11 +348,22 @@ ccl_device_inline void kernel_accum_emission_or_background_pass(KernelGlobals kg
}
# endif /* __DENOISING_FEATURES__ */
if (lightgroup != LIGHTGROUP_NONE && kernel_data.film.pass_lightgroup != PASS_UNUSED) {
kernel_write_pass_float3(buffer + kernel_data.film.pass_lightgroup + 3 * lightgroup,
contribution);
}
if (!(path_flag & PATH_RAY_ANY_PASS)) {
/* Directly visible, write to emission or background pass. */
pass_offset = pass;
}
else if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
/* Don't write any light passes for shadow catcher, for easier
* compositing back together of the combined pass. */
if (path_flag & PATH_RAY_SHADOW_CATCHER_HIT) {
return;
}
if (path_flag & PATH_RAY_SURFACE_PASS) {
/* Indirectly visible through reflection. */
const float3 diffuse_weight = INTEGRATOR_STATE(state, path, pass_diffuse_weight);
@@ -437,6 +449,19 @@ ccl_device_inline void kernel_accum_light(KernelGlobals kg,
if (kernel_data.film.light_pass_flag & PASS_ANY) {
const uint32_t path_flag = INTEGRATOR_STATE(state, shadow_path, flag);
/* Don't write any light passes for shadow catcher, for easier
* compositing back together of the combined pass. */
if (path_flag & PATH_RAY_SHADOW_CATCHER_HIT) {
return;
}
/* Write lightgroup pass. LIGHTGROUP_NONE is ~0 so decode from unsigned to signed */
const int lightgroup = (int)(INTEGRATOR_STATE(state, shadow_path, lightgroup)) - 1;
if (lightgroup != LIGHTGROUP_NONE && kernel_data.film.pass_lightgroup != PASS_UNUSED) {
kernel_write_pass_float3(buffer + kernel_data.film.pass_lightgroup + 3 * lightgroup,
contribution);
}
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
int pass_offset = PASS_UNUSED;
@@ -554,15 +579,20 @@ ccl_device_inline void kernel_accum_background(KernelGlobals kg,
kernel_accum_combined_transparent_pass(
kg, path_flag, sample, contribution, transparent, buffer);
}
kernel_accum_emission_or_background_pass(
kg, state, contribution, buffer, kernel_data.film.pass_background);
kernel_accum_emission_or_background_pass(kg,
state,
contribution,
buffer,
kernel_data.film.pass_background,
kernel_data.background.lightgroup);
}
/* Write emission to render buffer. */
ccl_device_inline void kernel_accum_emission(KernelGlobals kg,
ConstIntegratorState state,
const float3 L,
ccl_global float *ccl_restrict render_buffer)
ccl_global float *ccl_restrict render_buffer,
const int lightgroup = LIGHTGROUP_NONE)
{
float3 contribution = L;
kernel_accum_clamp(kg, &contribution, INTEGRATOR_STATE(state, path, bounce) - 1);
@@ -573,7 +603,7 @@ ccl_device_inline void kernel_accum_emission(KernelGlobals kg,
kernel_accum_combined_pass(kg, path_flag, sample, contribution, buffer);
kernel_accum_emission_or_background_pass(
kg, state, contribution, buffer, kernel_data.film.pass_emission);
kg, state, contribution, buffer, kernel_data.film.pass_emission, lightgroup);
}
CCL_NAMESPACE_END

View File

@@ -451,7 +451,7 @@ ccl_device_inline float4 film_calculate_shadow_catcher_matte_with_shadow(
float scale, scale_exposure;
if (!film_get_scale_and_scale_exposure(kfilm_convert, buffer, &scale, &scale_exposure)) {
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
return zero_float4();
}
ccl_global const float *in_matte = buffer + kfilm_convert->pass_shadow_catcher_matte;

View File

@@ -164,7 +164,7 @@ ccl_device float4 curve_attribute_float4(KernelGlobals kg,
if (dx)
*dx = sd->du.dx * (f1 - f0);
if (dy)
*dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
*dy = zero_float4();
# endif
return (1.0f - sd->u) * f0 + sd->u * f1;
@@ -172,9 +172,9 @@ ccl_device float4 curve_attribute_float4(KernelGlobals kg,
else {
# ifdef __RAY_DIFFERENTIALS__
if (dx)
*dx = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
*dx = zero_float4();
if (dy)
*dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
*dy = zero_float4();
# endif
if (desc.element & (ATTR_ELEMENT_CURVE | ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) {
@@ -183,7 +183,7 @@ ccl_device float4 curve_attribute_float4(KernelGlobals kg,
return kernel_tex_fetch(__attributes_float4, offset);
}
else {
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
return zero_float4();
}
}
}

View File

@@ -283,6 +283,26 @@ ccl_device_inline float object_pass_id(KernelGlobals kg, int object)
return kernel_tex_fetch(__objects, object).pass_id;
}
/* Lightgroup of lamp */
ccl_device_inline int lamp_lightgroup(KernelGlobals kg, int lamp)
{
if (lamp == LAMP_NONE)
return LIGHTGROUP_NONE;
return kernel_tex_fetch(__lights, lamp).lightgroup;
}
/* Lightgroup of object */
ccl_device_inline int object_lightgroup(KernelGlobals kg, int object)
{
if (object == OBJECT_NONE)
return LIGHTGROUP_NONE;
return kernel_tex_fetch(__objects, object).lightgroup;
}
/* Per lamp random number for shader variation */
ccl_device_inline float lamp_random_number(KernelGlobals kg, int lamp)

View File

@@ -391,11 +391,11 @@ ccl_device float4 patch_eval_float4(KernelGlobals kg,
int num_control = patch_eval_control_verts(
kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv);
float4 val = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
float4 val = zero_float4();
if (du)
*du = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
*du = zero_float4();
if (dv)
*dv = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
*dv = zero_float4();
for (int i = 0; i < num_control; i++) {
float4 v = kernel_tex_fetch(__attributes_float4, offset + indices[i]);
@@ -428,11 +428,11 @@ ccl_device float4 patch_eval_uchar4(KernelGlobals kg,
int num_control = patch_eval_control_verts(
kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv);
float4 val = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
float4 val = zero_float4();
if (du)
*du = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
*du = zero_float4();
if (dv)
*dv = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
*dv = zero_float4();
for (int i = 0; i < num_control; i++) {
float4 v = color_srgb_to_linear_v4(

View File

@@ -83,16 +83,16 @@ ccl_device float4 point_attribute_float4(KernelGlobals kg,
{
# ifdef __RAY_DIFFERENTIALS__
if (dx)
*dx = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
*dx = zero_float4();
if (dy)
*dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
*dy = zero_float4();
# endif
if (desc.element == ATTR_ELEMENT_VERTEX) {
return kernel_tex_fetch(__attributes_float4, desc.offset + sd->prim);
}
else {
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
return zero_float4();
}
}

Some files were not shown because too many files have changed in this diff Show More