Compare commits

...

701 Commits

Author SHA1 Message Date
8c13b539b8 temp-sculpt-colors: remove unrelated icons 2022-03-29 15:17:14 -07:00
572c52d2a3 temp-sculpt-colors: comment formatting 2022-03-29 15:12:02 -07:00
176b331c43 Merge branch 'master' into temp-sculpt-colors 2022-03-28 22:54:24 -07: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
2f3ace4024 Merge branch 'master' into temp-sculpt-colors 2022-03-23 14:24:46 -07:00
f42d3caecd temp-sculpt-colors: fix data transfer modifier 2022-03-23 14:10:18 -07: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
09eb086779 temp-sculpt-colors:
* Updated reverse face colors to use color attribute api.
* Updated rotate face colors to use color attribute api.
* Fixed mask by color not redrawing.
* Fixed duplicate mask by color keymap entry.
* Change bunches of UI strings from "vertex color" to "color attribute."
  - But not in git submodules.
2022-03-23 09:19:00 -07: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
51c3ce1353 temp-sculpt-colors: Fix alpha being mangled for byte colors 2022-03-22 10:44:39 -07: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
19ea75f8cf temp-sculpt-colors: Fix vertex paint color attribute
auto creation.
2022-03-22 10:09:16 -07:00
4c7ea01cbd temp-sculpt-colors: Fix crash in redoing after
undoing first stroke of
		    paint brush.
2022-03-22 09:54:27 -07:00
bb3584e3cb temp-sculpt-colors: fix edit mode vcol drawing 2022-03-22 09:42:25 -07: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
9e3e80780c temp-sculpt-colors: Fix smear brush
Smear brush now:
* Walks two rings around vertices instead of one
* Accumulates a single weighted average instead of
  blending individually.
* Weights by how close vertices are to the desired smear
  distance, as well as their edge lengths (in the future
  edge length weighting will be replaced with either
  face areas or cotangent weights).
2022-03-22 05:59:29 -07: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
bf087a92dd Merge branch 'master' into temp-sculpt-colors 2022-03-21 20:09:00 -07: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
2297db5c49 DRW: gpu wrappers: Fix compilation in release mode 2022-03-18 20:59:48 +01:00
16dd382f06 GPUTexture: Add Cube view as 2D array
This is useful to read/write to the textures directly using compute
shaders and imageLoad/Store.
2022-03-18 20:59:44 +01:00
c509a12fd8 DRW: Expose stencil view in gpu_wrapper 2022-03-18 20:59:40 +01:00
daa26ac0f5 Cleanup: DRW: Fix comments in DRW_gpu_wrapper 2022-03-18 20:59:37 +01:00
e5c2bfb341 DRW: Add support for compute indirect command.
This just expose the GPU API through DRW.
2022-03-18 20:59:33 +01:00
d7df0dcccb GPU: Add indirect dispatch support.
This uses a StorageBuf as the source of indirect dispatch argument.
The user needs to make sure the parameters are in the right order.

There is no support for argument offset for the moment as there is no
need for it. But this might be added in the future.

Note that the indirect buffer is synchronized at the backend level. This is
done for practical reasons and because this feature is almost always used
for GPU driven pipeline.
2022-03-18 20:59:27 +01:00
7ee816e32f GPU: StorageBuf: Add method to clear the buffer in place.
This is a faster way to clear a buffer instead of reuploading new data.
It is equivalent to `memset` and runs directly on the GPU.

This is better to clear huge buffers and to avoid the sync cost of data upload.
2022-03-18 20:59:20 +01:00
5bd38f3be8 Cleanup: GPUStorageBuf: Fix header license 2022-03-18 20:57:15 +01:00
33b4e21820 Cleanup: SSBO: Rename ubo to ssbo in arguments. 2022-03-18 20:54:58 +01:00
93bf17d952 GPU: Add support for stencil buffer texturing mode.
This adds the possibility to read the stencil buffer inside shaders.
This is only available on GL 4.3 so use it accordingly.
2022-03-18 20:54:42 +01:00
054957659f GL: Check texture framebuffer feedback only if not using compute pipeline.
This was getting in the way in multiple instances. Compute shaders dispatch
are still made in the presence of the last bound framebuffer even if they
do not interact with it.
2022-03-18 20:54:27 +01:00
935136f844 GPUTexture: Fix bug in texture view creation
The switch case was based on an uninitialized value.
2022-03-18 20:54:18 +01:00
081255671a GL: Add missing format in image layout conversion 2022-03-18 20:54:02 +01:00
3f484c502f GPUShaderCreateInfo: Add explicit early_fragment_test 2022-03-18 20:53:52 +01:00
0f08453ea9 DRW: Add simple texture view wrappers to draw::Texture 2022-03-18 20:53:41 +01:00
3b75ca2f60 GPUTexture: Expose layer & mip count 2022-03-18 20:53:17 +01:00
374cb32d4a GLShader: Fix two small issues with compute shader generated code 2022-03-18 20:53:04 +01:00
2580869901 DRW: Add support for GPUStorageBuf in wrappers
# Conflicts:
#	source/blender/draw/engines/eevee/eevee_light.cc
#	source/blender/draw/engines/eevee/eevee_shadow.cc
2022-03-18 20:50:25 +01:00
8c93f8c6cc DRW: Add support for GPUStorageBuf 2022-03-18 20:49:45 +01:00
bacfd55a0e GPU/GL: Add StorageBuf implementation
Almost 1:1 identical to UniformBuf implementation.
2022-03-18 20:49:41 +01:00
4544761a2d GPUShader: Fix crash when compilation error is a linking error 2022-03-18 20:49:22 +01:00
59f53f5802 EEVEE: Add new experimental "EEVEE Next" option
This is supposed to hold the latest improvement from the EEVEE rewrite branch.
Note that a restart is necessary in order for the engine to appear.

The registration code is a bit convoluted as it needs to be after the WM_init.
2022-03-18 20:49:09 +01:00
Christoph Lendenfeld
37b93b5df8 Animation: Blend To Default Implementation
Add a new operator to the Graph Editor that blends selected keyframes
to their default value.
The operator can be accessed from
Key>Slider Operators>Blend To Default Value

Reviewed by: Sybren A. Stüvel
Differential Revision: https://developer.blender.org/D9376
Ref: D9367
2022-03-18 20:07:16 +01:00
63f9cb5a0b Fix T96608: GPencil Simplify must check general Simplify switch
As the grease pencil simplify is a subotion of general simplify, if the general switch is disabled, the grease pencil simplify must be disabled too.

This patch also disable the UI panel.
2022-03-18 19:50:38 +01:00
298d8a7b4a Curves: Port reverse curves node to the new data-block
Create a function on CurvesGeometry that can also be used for an edit
mode operator in the future. Dealing with CustomData directly means the
code is a bit more verbose than would be ideal, but this would be a
simple thing to clean up in the future if we get an attribute API here.

Also change the reverse node to first work on a read-only geometry
component, and only get write access if there is a curve selected.

Differential Revision: https://developer.blender.org/D14375
2022-03-18 12:24:05 -05:00
d2726e4626 Cleanup: Remove unnecessary namespace usage, use const 2022-03-18 12:21:13 -05:00
b2cb99d3fd Curves: Port fill curve node to the new data-block
This will mostly just remove the overhead of converting
to and from the old curves type, though it also does open
some opportunities for multi-threading in the future.
2022-03-18 12:18:19 -05:00
8146c996eb Fix: Curves last evaluated segment is empty
A mistake in 8538c69921. The offsets include the segment at the
corresponding index, but the evaluated offset calculation was adjusting
the offset for the second to last segment.
2022-03-18 12:05:14 -05:00
5d7f4f2cab Curves: Port transform node to new data-block
Make the new curves' translate and transform functions also affect
the handle position attributes.

Differential Revision: https://developer.blender.org/D14372
2022-03-18 10:30:27 -05:00
fe9e7036b0 Fix UV's not aligning with image.
This reverts a part of {rB33409f9f1cd42e899f2706fe7878e5e89b50d617}.
2022-03-18 14:17:19 +01:00
65b8b38787 Cleanup: Redundant parenthesis 2022-03-18 14:16:16 +01:00
c3ecfdf40b Cleanup: Compilation warnings
Mainly -Wset-but-unused-variable.
Makes default compilation on macOS way less noisy.

Differential Revision: https://developer.blender.org/D14357
2022-03-18 12:07:08 +01:00
2252bc6a55 BLI: move CPPType to blenlib
For more detail about `CPPType`, see `BLI_cpp_type.hh` and D14367.

Differential Revision: https://developer.blender.org/D14367
2022-03-18 10:57:45 +01:00
7509a74116 Fix T96278: missing update after alpha socket connection
Differential Revision: https://developer.blender.org/D14299
2022-03-18 10:49:54 +01:00
c7954d5904 Cleanup: Remove unused function 2022-03-18 10:34:06 +01:00
578c2f117a Curves: Port handle type selection node to new data-block
The node's structure isn't changed, it basically still works the
same way. The use of virtual arrays could be optimized in the
future if necessary.
2022-03-18 00:16:54 -05:00
389807624d Curves: Port Bezier Segment node to the new data-block
Ref T95443
2022-03-17 22:47:56 -05:00
0eb394af74 Fix resizing nodes not respecting the drag-start
Resizing nodes used the cursor location when the event was triggered
instead of the drag-start, harmless but means the drag location isn't
under the cursor especially with a high drag threshold.

Noticed when investigating other drag issues,
unrelated to recent changes to drag behavior.
2022-03-18 13:20:11 +11:00
5035fbdd23 License headers: use SPDX identifiers in intern/itasc
Added license headers based on the original LGPL files from:
gitlab.kuleuven.be/rob-itasc
2022-03-18 10:27:01 +11:00
a0e2373b7e Docs: add license text file for LGPL2.1 2022-03-18 10:27:01 +11:00
89ab3cdc56 Fix wrong documentation/UI text for NodeLink
`RNA_def_struct_ui_text(srna, ...)` was reused for `is_valid` and `is_muted`
which would set the documentation to theirs (actually to that of the last
call).

`RNA_def_property_ui_text(prop, ...)` should be used for the properties.
2022-03-17 23:57:06 +01:00
a67c7693a7 Fix typo in smooth brush tooltip 2022-03-17 23:56:55 +01:00
8407c0b64e Cleanup: unused class members. 2022-03-17 23:56:18 +01:00
d4bd9f6a27 Curves: Port convex hull node to new data-block
This uses the evaluated positions calculations from 8538c69921.
2022-03-17 17:45:37 -05:00
7bdba5f1e0 Cleanup: Remove unused includes 2022-03-17 17:16:53 -05:00
0835996cc9 Cleanup: Rename "spline" variables to "curve"
Ref T95355
2022-03-17 17:08:36 -05:00
ee2d39b3a7 Cleanup: Reorganize duplicate elements file
Use sections to keep all the code for a specific mode together,
rather than keeping the attribute duplication separate.
2022-03-17 16:46:58 -05:00
663bd38ed6 Curves: Port duplicate elements node to new data-block
Remove the conversion to and from `CurveEval` by supporting the
new Curves data-block in the node. This allows for some simplifications
to the code, as well as a fix for transfering curve domain attributes
when duplicating the curve domain.

The performance improvements (obverved through the timings overlay)
can be relatively massive with many curves. When duplicating 10000
4-point curves to become 2 million curves, I observed an approximate
150x improvement, from about 3 seconds to about 20ms.
2022-03-17 16:36:43 -05:00
6d97a5f93c Cleanup: Miscellaneous improvements to duplicate geometry node
- Pass less redundant information in function arguments.
- Use `IndexRange` more instead of direct offset calculations.
- Use specific geometry component types for specialized functions.
- Use const arguments.
- Declare variables closer to where they are created or used.
- Remove some redundant logic.
- Simplify the description for the output geometry.
2022-03-17 16:23:58 -05:00
7fed4c06c2 Fix keying-set selector broken
The menu for Timeline > Keying > Active Keying Set wouldn't show up.

Caused by d8e3bcf770. The function to attach search menu data to the button
would be called twice with different arguments for the same button now.
Shouldn't be an issue in general, but the first call now had the unexpected
side effect that the button would get disabled. Make sure it's re-enabled when
the second call sets the proper search data now.
2022-03-17 17:52:50 +01:00
17906794f5 Fix T96330: Three times slower 'relink to new id' process in 3.1.
Caused by rB43bc494892c3, moving this 'new id' relink to generic
remapping code added the over-head of proper, generic post-processing,
compared to the special-cases previous code was only designed to handle.

Fortunately with recent 'multi-remapping' work we can easily rewrite
that new id relink code to use the multi-remapping approach too.

No behavioral change is expected from this commit, besides the improved
performances (essentially restored to what they where before
rB43bc494892c3).
2022-03-17 17:23:57 +01:00
Henrik Dick
236ef11a07 GPencil: Fix cyclic flag cleared by simplify modifier
Change the sample mode to don't duplicate the last vertex of the
stroke and instead use the cyclic flag to close previously cyclic
strokes. This is necessary for the following modifiers.

Reviewed By: NicksBest

Differential Revision: http://developer.blender.org/D14359
2022-03-17 14:09:29 +01:00
d0968a9c52 BLI: add probabilistic rounding utility 2022-03-17 12:48:41 +01:00
8f68cff01b Cleanup: name enums 2022-03-17 12:42:01 +01:00
dd483215e5 Hair: Sculpt Mode Icons
From hair particle mode:
* Add
* Comb
* Cut
* Grow

New:
* Delete

Only comb and delete are used at the moment (by the new tools which are
under experimental).
2022-03-17 12:12:53 +01:00
b6702aa604 Curves: separate sculpt brushes into separate files
This makes it easier to work on these brushes in parallel.
2022-03-17 10:04:02 +01:00
884b167f74 View 3D: scale object center selection penalty by the pixel size
All screen-space UI thresholds should scale by the interface scale.
2022-03-17 20:02:37 +11:00
e0a8f9b78e Fix unintended de-selection when selecting the object center
Selecting an object that was already active & selected would de-select
it when the cursor was over the objects center.

This was caused by [0] that added a check which assumed more than one
hits from GPU_select meant there were multiple objects to select from.
This is not necessarily the case since bones, camera tracks or the
objects own center can add additional hits.

Resolve by keeping track of the best hit with & without the
active-selected object, only using the non-active-selected if it's found.

[0] 1550573360
2022-03-17 18:21:47 +11:00
bb735bd518 Tweak Tool: supports select & tweak on LMB (with RMB-select key-map)
Support for differentiating the tweak tool from the 3D cursor when
select is set to RMB.

This is currently an experimental preference:
Tweak Tool: Left Mouse Select & Drag

When enabled the tweak tool can now tweak the existing selection
without de-selecting first, a single click can be used to replace
the selection.
This matches selection in the graph & node editors.

This preferences is only available with "Developer Extras" enabled.

Ref T96544.
2022-03-17 16:47:14 +11:00
3017585ebf View 3D: the select operator now uses the cancel flag on failure
Needed so mapping selection to click doesn't pass the click event
through to setting the 3D cursor for e.g.

While this doesn't happen with the default key-map, setting selection
to LMB-click would set the 3D cursor as well (when the selection
fell through to nothing).
2022-03-17 16:22:33 +11:00
859c062a2a View 3D: multi-object pose selection no longer de-selects objects
De-selecting objects meant that selecting a bone would de-select
all the other pose objects - making exiting & entering pose-mode
loose the current set of pose objects.

Match edit-mode behavior: avoid de-selecting objects in the current mode
(unless the action is explicitly performed in the outliner for e.g.).
2022-03-17 14:39:38 +11:00
ba6d59a85a Cleanup: simplify logic for skipping object selection
Previously setting the 'basact' to NULL was done, but this wasn't
so simple to use with deselect_all which needs to check if there was
anything found at the cursor.

Add a 'handled' variable to differentiate this case, when set
don't attempt object selection.
2022-03-17 14:38:38 +11:00
42f430e9a2 Cleanup: minor clarifications to comments & use const variables 2022-03-17 14:37:23 +11:00
83fd242546 Fix 3D view movie-clip track selection
While basic single track selection worked,
toggling and de-selection has been broken since at least 2.83.

Support SelectPick_Params with the exception of deselect_all
which doesn't make sense for tracks as de-selecting all objects
is expected in that case.
2022-03-17 14:37:22 +11:00
7bc6a04767 Cleanup: split movie clip track selection into it's own function
This was an involved operation to include inline,
making ed_object_select_pick more difficult to follow.

Prepare for track selection to properly support SelectPick_Params.
2022-03-17 14:37:21 +11:00
1d88aeb95f View 3D: support for select passthrough when picking selected items
Currently this isn't used in the key-map, it will eventually
allow the 3D viewports tweak tool to match the behavior of other
editors that support tweaking a selection without first de-selecting
all other elements.
2022-03-17 14:37:20 +11:00
ea0c86e961 Cleanup: spelling in comments
Use <pre>..</pre> for pseudo-code.
2022-03-17 10:08:41 +11:00
27388f7f46 Cleanup: include argument names for drop-box callbacks
Indicates typical names for callbacks and allows them to be documented.
2022-03-17 10:08:41 +11:00
Habib Gahbiche
33409f9f1c Compositor: Support backdrop offset for the Viewer node
This is only part of the experimental "Full Frame" mode (disabled
by default). See T88150.

Currently the viewer node uses buffer paddings to display image offset
in the backdrop as a temporal solution implemented for {D12466}.
This solution is inefficient memory and performance-wise. Another
issue is that the paddings are part the image when saved.

This patch instead sets the offset in the Viewer node image
as variables and makes the backdrop take it into account
when drawing the image or any related gizmo.

Reviewed By: jbakker

Differential Revision: https://developer.blender.org/D12750
2022-03-16 23:28:36 +01:00
22de21bef1 Fix: Compiler error on windows and mac
The previous fix including `<algorithm>` was an improvement
but not the actual error, which appears to be that `int64_t` is
long long int on one platform but just long int on another.
The fix includes the template argument directly.
2022-03-16 16:49:31 -05:00
7a4af7a01b Fix: Build error after curve evaluation commit 2022-03-16 16:29:24 -05:00
8538c69921 Curves: Initial evaluation for curves data-block
This patch adds evaluation for NURBS, Bezier, and Catmull Rom
curves for the new `Curves` data-block. The main difference from
the code in `BKE_spline.hh` is that the functionality is not
encapsulated in classes. Instead, each function has arguments
for all of the information it needs. This makes the code more
reusable and removes a bunch of unnecessary complications
for keeping track of state.

NURBS and Bezier evaluation works the same way as existing code.
The Catmull Rom implementation is new, with the basis function
based on Cycles code. All three types have some basic tests.

For NURBS and Catmull Rom curves, evaluating positions is the
same as any generic attribute, so it's implemented by the generic
interpolation to evaluated points. Bezier curves are a bit special,
because the "handle" control points are stored in a separate attribute.
This patch doesn't include generic interpolation to evaluated points
for Bezier curves.

Ref T95942

Differential Revision: https://developer.blender.org/D14284
2022-03-16 15:47:00 -05:00
9af791f873 Fix: Update icons for hair to curves rename
ddf189892c missed recreating the icons with the new names.
This commit runs `make icons` and replaces the names in CMake.
2022-03-16 12:48:00 -05:00
Bastien Montagne
7e06fc11b7 Add 'multiple' variant of ID relink function.
Similar to other changes to ID remapping, gives huge speedups in some
cases, like certain types of liboverride creation.

Case from {T96092} goes from 1725 seconds (almost 30 minutes) to 45
seconds to generate the liboverride, on my machine.

Reviewed By: jbakker

Maniphest Tasks: T96092

Differential Revision: https://developer.blender.org/D14240
2022-03-16 18:34:20 +01:00
2564d152d6 Cleanup: Remove unnecessary namespace specification
Ever since d5b72fb06c, shader nodes have been in the
`blender::nodes` namespace, so they don't need to use that to access
Blender's C++ types and functions.
2022-03-16 12:33:36 -05:00
263c5b33d6 Fix: Build error from missing build dependencies
Somehow exposed after 943b919fe8, linking could fail because
bf_nodes was not properly configured as a dependency of bf_nodes_shader.
Also add the dependency to the geometry nodes module.
2022-03-16 12:20:05 -05:00
390b9f1305 Fix Cycles HIP assuming warp size 32
In HIP these masks are 64 bit, while in CUDA only 32 bit.
2022-03-16 18:05:48 +01:00
076079454f Cleanup: remove some unused Cycles GPU code
To make porting to other architectures easier, clarifying that this does not
need to be supported. The unused parallel_reduce implementation assumed warp
size 32, but is easy to update if we ever need it in the future.
2022-03-16 18:05:08 +01:00
213d00607e Cleanup: Further removal for legacy geometry nodes
943b919fe8 missed removing the experimental
option and the nodes from the add menu.
2022-03-16 10:56:53 -05:00
79e74b1486 Fix T96518: Gpencil Fill freezes when use invert and click inside areas
When using inverted filling and click inside a closed area and not outside as is expected, the algorithm to detect the contour to fill is unable to find the filling shape and try to fill outside of the valid index.

The infinite loop was adding more memory for each loop and the process continued while there was system resources and finally crashed the system.

As the tool in negative mode is designed to fill all areas when you click outside of any shape, now the algorithm check if the outline is not working as expected and cancels the filling process.
2022-03-16 16:30:53 +01:00
943b919fe8 Geometry Nodes: Remove legacy node code
This commit removes the implementations of legacy nodes,
their type definitions, and related code that becomes unused.
Now that we have two releases that included the legacy nodes,
there is not much reason to include them still. Removing the
code means refactoring will be easier, and old code doesn't
have to be tested and maintained.

After this commit, the legacy nodes will be undefined in the UI,
so 3.0 or 3.1 should be used to convert files to the fields system.

The net change is 12184 lines removed!

The tooltip for legacy nodes mentioned that we would remove
them before 4.0, which was purposefully a bit vague to allow
us this flexibility. In a poll in a devtalk post showed that the
majority of people were okay with removing the nodes.
https://devtalk.blender.org/t/geometry-nodes-backward-compatibility-poll/20199

Differential Revision: https://developer.blender.org/D14353
2022-03-16 08:51:11 -05:00
cb267cec55 Fix T96512: Crash selecting an edge
Regression in 5e5285baf6.
2022-03-16 23:42:31 +11:00
31f31496af Document some flags controlling BKE_library_foreach_ID_link behavior. 2022-03-16 13:15:41 +01:00
42e13ea4bf Cleanup: Deprecated field access in outliner_duplicate
Solved by introducing introducing a variant of MEM_cnew which behaves
as a copy-constructor for a trivial types.

Alternative approach would be to surround DNA structs with clang/gcc
diagnostics push/modify/pop so that implicitly defined constructors
and copy operators are allowed to access deprecated fields.

The downside of the DNA approach is that it will require some way to
easily apply diagnostics modifications to many structs, which is not
possible currently.

The newly added MEM_cnew has other good usecases, so is easiest to
use this route, at least for now.

Differential Revision: https://developer.blender.org/D14356
2022-03-16 12:38:23 +01:00
ddc54a2a6b Cleanup: Remove use of deprecated std::iterator in Freestyle
Resolves a fair amount of noisy warnings with default build on macOS.

Tested using render_layer render test which includes Freestyle layer.

Differential Revision: https://developer.blender.org/D14355
2022-03-16 11:56:30 +01:00
fbc36c77b0 Fix error with pose & deselect_all with 5e5285baf6 2022-03-16 21:25:38 +11:00
79ae5f5014 Fix T96386: crash when changing shader to node group in properties
The previous code updated the wrong node tree. The result was that
the new group node did not have the socket that was supposed to
be linked.
2022-03-16 11:23:45 +01:00
a45108840e CMake: Extra flags to ignore for strict compiler
Solves warnings generated by default build on macOS.
2022-03-16 10:33:04 +01:00
2d42187395 View 3D: refactor edit-mode meta-element selection
Meta-element selection now follows conventions for other picking
functions (e.g. EDBM_select_pick).

- Split meta-element find-nearest into a separate function.

- Cycle the meta-element starting from the active & selected
  instead of comparing & setting a static variable.

- Order elements using depth (from front-to-back)
  when cycling multiple elements.
2022-03-16 20:09:55 +11:00
9df27e7f00 Fix object centers & geometry selecting meta-elements in edit-mode 2022-03-16 19:57:47 +11:00
4f37b548bd Cleanup: de-duplicate struct declaration
Also use boolean instead of int.
2022-03-16 15:55:10 +11:00
8cfdad99a0 Cleanup: incorrect comments, use C comments 2022-03-16 15:30:22 +11:00
24ada9c960 Cleanup: Remove volatile from RenderResult and related APIs
Volatile fields were introduced to the RenderResult struct years ago[1].

However, volatile is most likely not doing what it was intended to do
in this instance, and is problematic when moving files to c++ (see
discussion from D13962). There are complex rules around what happens to
these fields but none of them guarantee what the above commit alluded to.

This patch drops the volatile and cleans up the APIs surrounding it.

[1] rB7930c40051ef1b1a26140629cf1299aa89eed859

Passing on all platforms:
https://builder.blender.org/admin/#/builders/18/builds/338

Differential Revision: https://developer.blender.org/D14298
2022-03-15 21:12:49 -07:00
f1501ac060 Cleanup: rename variables in view3d_select_exec
- Rename 'location' to 'mval', typically used for region cursor coords.
- Rename 'retval' to 'changed', typically used for operators
  when their return value depends on a change being made.
2022-03-16 15:05:05 +11:00
5e5285baf6 View 3D: move picking arguments into a struct & minor refactor
- Add SelectPick_Params struct to make picking logic more
  straightforward and easier to extend.

- Use `eSelectOp` instead of booleans (extend, deselect, toggle)
  which were used to represent 4 states (which wasn't obvious).

- Handle deselect_all when pocking instead of view3d_select_exec,
  de-duplicate de-selection which was already needed in when replacing
  the selection in picking functions.

- Handle outliner update & notifiers in the picking functions
  instead of view3d_select_exec.

- Fix particle select deselect_all option which did nothing.
2022-03-16 14:48:25 +11:00
9a763d24f2 Fix missing update selecting 3D text-box 2022-03-16 13:40:16 +11:00
be7855591e Cleanup: rename cnt to count
Follow naming from T85728.
2022-03-16 11:58:22 +11:00
379bd6d50c Curves: Port count spline length output to new data-block
This fixes T96487 in a similar way to 5791835678,
and also removes the conversion to old curve type for the
"Point Count" output.
2022-03-15 16:22:36 -05:00
d8e3bcf770 Outliner: Display buttons to edit library override properties
As proposed in T95802, this adds buttons to a new column on the right to modify
the override in the Library Override display mode. Some further usability
improvements are planned. E.g. this does not yet expand collections (modifiers,
constraints, etc) nicely or group modified properties of a modifier together.
Vector properties with more than 3 items or matrices aren't displayed nicely
yet, they are just squeezed into the column. If this actually becomes a problem
there are some ideas to address this.

Differential Revision: https://developer.blender.org/D14268
2022-03-15 18:48:52 +01:00
7f77bd95d9 Fix T96381: Cycles GPU wrong render with camera inside multiple volumes 2022-03-15 18:42:08 +01:00
c2f9133b29 Fix Cycles kernel error on Metal after recent changes 2022-03-15 17:56:45 +01:00
630d2b6497 Cycles: allow Adaptive Sampling with Scrambling Distance
While the correlation may not work well with adaptive sampling, in practice
this appears to work ok in most cases

Automatic scrambling distance uses the minimum samples from adaptive sampling,
which provides a good default estimate to avoid artifacts.

Contributed by Alaska.

Differential Revision: https://developer.blender.org/D13325
2022-03-15 16:12:13 +01:00
f9d3632cde Cycles: change Scrambling Distance Multiplier to a soft limit
This allows users to type in values larger than 1, for use in conjunction
with automatic scrambling distance.

Contributed by Alaska.

Differential Revision: https://developer.blender.org/D13580
2022-03-15 16:12:13 +01:00
af51b0d8d8 Fix T96417: Cycles issue with multiscatter GGX and self intersection avoidance
When the light direction is not pointing away from the geometric normal and
there is a shadow terminator offset, self intersection is supposed to occur.
2022-03-15 16:12:13 +01:00
19bff8eb51 Fix T96263: command line rendering affected by current scene subframe 2022-03-15 16:12:13 +01:00
2613a2552d Fix some properties missing in the UI for new Curves object type
Missed some renames from HAIR to CURVES.
2022-03-15 16:12:13 +01:00
3bb4597b2d Disable GPU subdivision if the maximum number of SSBO binding is reached
Some old platforms and drivers have limited amount of SSBO binding per
compute shader. This disables GPU subdivision if we cannot possibly
bind all required buffers within this limit.

For now the maximum number of buffers used by the GPU code is hardcoded,
but will be programmatically detected when shader creation is automated.

Ref D14337
2022-03-15 16:07:32 +01:00
45b637e1e7 GPU capabilities: detect max SSBO bindings
This adds detection of the maximum number of shader storage buffer
bindings that is supported on the current platform. This can be
useful to turn off features that require compute shaders but use
more buffer bindings than available.

Differential Revision: https://developer.blender.org/D14337
2022-03-15 16:04:41 +01:00
e08180fdab Fix slow tracking of long sequences
The performance issue was noticeable when tracking a lot of tracks
which are using keyframe pattern matching. What was happening is that
at some cache gets filled in and the furthest away frame gets removed
from the cache: the frame at marker's keyframe gets removed and needs
to be re-read from disk on the next tracking step.

This change makes it so frames at markers' keyframes are not removed
from cache during tracking.

Steps to easily reproduce:
- Set cache size to 512 Mb.
- Open image sequence in clip editor
- Detect features
- Track all markers

Originally was reported by Rik, thanks!
2022-03-15 15:50:40 +01:00
2156841c8c Fix T96452: Armature corrupted after undoing 'Join' operation.
Modified source Armature ID in the join operation was not properly
tagged as such for the depsgraph (and therefore memfile undo)..

Issue caused/revealed by rBe648e388874a.

Should be backported to 3.1 should we make a corrective release.
2022-03-15 15:02:39 +01:00
256d36683b Cleanup: remove redundant 'extern StructRNA' declarations
After rB9b298cf3dbec, the `StructRNA` declarations can now be accessed via
`RNA prototypes.h`

Also, since all redundated declarations are now removed,
`_WM_MESSAGE_EXTERN_BEGIN` and `_WM_MESSAGE_EXTERN_END` are also no
longer needed.

Differential Revision: https://developer.blender.org/D14342
2022-03-15 09:14:38 -03:00
7ec2c5c10b Cleanup: Remove confusing double negation in RNA helper function
Much more readable that way.
2022-03-15 13:11:41 +01:00
46b35c6836 Cleanup: remove accidental shallow mesh copy 2022-03-15 12:32:18 +01:00
49fc4449e7 Fix T96357: Issue clicking on stem of arrow gizmos to scale on axis
Caused by 0cb5eae9d0 which restored
support for 3D depth when selecting gizmos - making it difficult
to select single lines drawn in front of other gizmos.
Previously the first hit was always used.

Resolve by using a margin around arrow stems when selecting
which was already done for 2D arrows.
2022-03-15 20:03:33 +11:00
a0a572ce8b Cleanup: correct unbalanced doxy sections 2022-03-15 17:29:54 +11:00
683c130b06 Docs: correct doc-string for BPY_driver_reset
Remove outdated reference to "pydrivers.py", also document BPY_DECREF.
2022-03-15 15:31:11 +11:00
8c60050d30 Cleanup: comments in bpy_driver.c, minor corrections 2022-03-15 15:20:38 +11:00
7c24804d62 Cleanup: de-duplicate Py_DECREF when evaluating PyDrivers 2022-03-15 15:06:25 +11:00
977c958242 Fix memory leak when there is an error evaluating a PyDriver
In practice users are unlikely to ever run into this error.
2022-03-15 15:03:27 +11:00
3cbf20228e Cleanup: use single back-ticks in regular comments
Double back-ticks are used for RST literals.
2022-03-15 14:53:49 +11:00
f410efbda0 UI: expose "Dolly View" in the menu
This is mainly to expose the shortcut to make Dolly discoverable.
2022-03-15 13:01:10 +11:00
Iyad Ahmed
fc259d4c30 Fix gpu.types.GPUTexture not passing data buffer to 3D textures
Missed in rB4430e8a00810ca8df2fa20029c4cb8078e8cdbe6

Reviewed By: mano-wii

Differential Revision: https://developer.blender.org/D14333
2022-03-14 16:06:32 -03:00
d4e46c13cc Geometry Nodes: Add named attribute nodes behind experimental flag
This commit adds three nodes:
- `Remove Attribute`: Removes an attribute with the given name
- `Named Attribute`: A field input node
- `Store Named Attribute`: Puts results of a field in a named attribute

They are added behind a new experimental feature flag, because further
development of attribute search and name dependency visualization will
happen as separate steps.

Ref T91742

Differential Revision: https://developer.blender.org/D12685
2022-03-14 11:48:11 -05:00
a5578351c3 Auto-generate RNA-structs declarations in RNA_prototypes.h
So far it was needed to declare a new RNA struct to `RNA_access.h` manually.
Since 9b298cf3db we generate a `RNA_prototypes.h` for RNA property
declarations. Now this also includes the RNA struct declarations, so they don't
have to be added manually anymore.

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

Reviewed by: brecht, campbellbarton
2022-03-14 17:08:46 +01:00
cc98b40f87 Cleanup: Clang tidy 2022-03-14 10:55:48 -05:00
9b298cf3db RNA: Generate property declerations header, solving msg-bus C++ incompatibility
Lets `makesrna` generate a `RNA_prototypes.h` header with declarations for all
RNA properties. This can be included in regular source files when needing to
reference RNA properties statically.

This solves an issue on MSVC with adding such declarations in functions, like
we used to do. See 800fc17367. Removes any such declarations and the related
FIXME comments.

Reviewed By: campbellbarton, LazyDodo, brecht

Differential Revision: https://developer.blender.org/D13837
2022-03-14 16:50:49 +01:00
cff6eb6580 Cleanup: Remove duplicate Bake modifier code
This patch remove all duplicate code for the same Bake modifier logic.

Still some modifiers need custom bake functions and cannot use this generic bake.
2022-03-14 16:13:59 +01:00
8c4ddd5dde Fix dead-lock in movie cache
Steps to reproduce:
- Add image sequence to movie clip editor.
- Set cache limit to a low value in the user preferences.
- Playback until old frames starts to be removed from cache.
- Jump to the beginning of the image sequence.

The reason of dead-lock comes from two factors:
- Due to global nature of the cache limiter calls needs to be
  guarded with locks.
- Image buffers stored in the cache can have their own cache
  (which is used for color management).

Didn't find a better solution than to use recursive lock.
Kind of makes sense since the thread-guardable resource is
recursive (moviecache can have nested moviecaches).

Differential Revision: https://developer.blender.org/D14331
2022-03-14 14:46:49 +01:00
e0241e0860 Convert moviecache to C++ 2022-03-14 14:46:22 +01:00
a5cd1799fc Cleanup: Deduplicate code in Multiply modifier 2022-03-14 11:35:26 +01:00
8eb189925e Cleanup: Make more obvious from the name that function is not public 2022-03-14 11:21:23 +01:00
7306417ae4 Revert "Animation: Sensible frame range for motion paths"
This reverts commit 1558b270e9.

An earlier commit (rB101fadcf6b93c) introduced some new functionality,
which was overlooked in reviewing this commit & got broken.

Will re-commit after the issue has been fixed.

Ref: D13687
2022-03-14 11:17:45 +01:00
Henrik Dick
4045b3d7b6 GPencil: Fix offset modifier negative scale thickness
If the scale in the offset modifier was set to a value lower than -1,
the object would get mirrored. The problem was, that the thickness
was set to 0 by that. This fix makes the thickness calculation only
use the absolute values.

Differential Revision: http://developer.blender.org/D14324
2022-03-14 11:11:22 +01:00
bf5e9ef2df Fix T96402: fix case when material output is contained in node group
For now just assume that a node group without output sockets is
an output node. Ideally, we would use run-time information stored
on the node group itself to determine if the group contains a
top-level output node (e.g. Material Output). That can be
implemented separately.

In the larger scheme of things, top-level outputs within node
groups seem to break the node group abstraction and reusability
a bit.
2022-03-14 10:49:35 +01:00
c6642f06ab Fix T96395: NDOF entries prevent loading of custom keymaps in 3.2
Even though the default key-map didn't use NDOF types some key-maps did.
2022-03-14 20:42:12 +11:00
82e7956f12 Fix T96396: cannot set active node group output with Python
This is essentially the same fix as in rB22a341d9d8d3d337f79df228ab2e4e0726f81430.
2022-03-14 10:21:47 +01:00
b3d0abd893 Fix T96378: B-Bone selection fails in pose-mode
Regression in 3267c91b4d.
2022-03-14 20:10:24 +11:00
d7dd7403a8 WM: avoid hard coded modifier key checks in object.hide_collection
These checks aren't always valid when there are multiple events
in the queue.
2022-03-14 15:50:06 +11:00
541ba68991 Cleanup: use size_t for BLF text API functions
Also minor cleanup to txt_sel_to_buf:

- Use memcpy instead of strncpy as the strings don't contain nil bytes.
- Replace while loops with for loops.
2022-03-14 14:25:33 +11:00
a5571fd0e8 Cleanup: spelling 2022-03-14 14:25:32 +11:00
6ea1455ce3 Fix mistake in 4c951bfa82
Removed WITH_SYSTEM_GLEW by mistake, thanks to @The_Orb for spotting.
2022-03-14 14:25:31 +11:00
b959f603da Fix T96267: Sidebar Tab Font Size Correction
Correction to the calculation of font size used for the tabs on the
Sidebar so that they are always the same size as other content on the
panel.

See D14322 for more details.

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

Reviewed by Brecht Van Lommel
2022-03-13 17:08:15 -07:00
4ec1c8bc9c Cleanup: Use helper variable, const argument 2022-03-13 16:53:48 -05:00
25b4e41875 Curve: Store NURBS basis cache as a single vector
Instead of allocating a vector of the basis weights cache for
each evaluated point, allocate a single vector for all of the
weights. This should reduce memory usage by avoiding the
overhead of storing many vectors. I noticed a small performance
improvement to evaluated position calculation with an order of 5,
which is larger than `Vector`'s default inline buffer capacity.

This change is possible because of previous commits that
made the basis cache for each evaluated point always have
the same "order" size.
2022-03-13 16:53:48 -05:00
3c8182409c Cleanup: Simplify NURBS basis cache arguments
Only pass a mutable span and a return argument to the calculation
function, so it's simpler and doesn't worry about where either are
stored.
2022-03-13 16:53:48 -05:00
29dc6fb1c1 Curve: Remove temporary buffer during NURBS evaluation
Currently a single buffer is used as working space for all evaluated
points. In order to make evaluations more independent, opening
options like multi-threading in the future, instead use a separate
array for each call. Using an inline buffer capacity higher than
the default allows a few percent performance improvement, and removes
allocations for every evaluated point.
2022-03-13 16:53:48 -05:00
34a61ceeaa Cleanup: Remove unnecessary NURBS optimization
The step after calculating the NURBS basis for a single evaluated
point trimmed extra zeroes from the weights. However, in practice
this rarely did anything, only for the first and last evaluated point
of certain knot configurations. Remove it in order to simplify code.

Also use a separate span for the result, to clarify its length.
2022-03-13 16:53:48 -05:00
Octave C
3b16530aa1 UI: Fix incoherent brush size in popover menu and brush settings
Previously, the popover menu in sculpt/texture paint mode did not
take into account the `UnifiedBrushSettings` for the unit.

To fix this,  the behavior of `class _draw_tool_settings_context_mode`  is matched
by checking the same conditions when setting up the UI of the right-click popover menu.

Fixes T81616

Reviewed By: #sculpt_paint_texture, pablodp606

Maniphest Tasks: T81616

Differential Revision: https://developer.blender.org/D9168
2022-03-13 17:45:35 -04:00
Yevgeny Makarov
301fac5ded UI: Fix Label alignment in top bar
Label alignment in top bar by using `ui_text_icon_width_ex` instead of `w_hint`

Old:

{F12733743}

New:

{F12733742}

Fixes T61558

Reviewed By: Severin

Maniphest Tasks: T61558

Differential Revision: https://developer.blender.org/D13552
2022-03-13 17:38:55 -04:00
Henrik Dick
a6b5d5bfe8 GPencil: Simplify modifier minimal vert count fix
Lower the minimal vert count for all simplify modes.

Differential Revision: http://developer.blender.org/D14319
2022-03-13 17:21:30 +01:00
Aras Pranckevicius
70720c42c2 Fix T96303: C++ OBJ exporter needs presets and skip modifiers.
This patch, D14303, from Aras Pranckevicius adds presets to the OBJ exporter,
and also adds a checkbox (default on) to apply modifiers before export.
2022-03-13 12:04:52 -04:00
91dbc28363 Cleanup: clang format 2022-03-13 00:49:41 -05:00
f6b7396610 Fix transform gizmo check for shift to constrain to a plane
The eventstate was checked instead of the current event being handled,
causing the check to be invalid in some cases.
2022-03-12 21:29:14 +11:00
a2bb3c4cad GPencil: Fix unreported select error in Normalize operator
The curve selection was wrongly checked.
2022-03-12 10:48:42 +01:00
8617ab153e Fix T96352: Gpencil crash using Normalize Thickness with Curves
The stroke curve data could be NULL.
2022-03-12 10:33:32 +01:00
Dilith Jayakody
39c070ed8f Fix T96229: GN Fillet Node unexpected limit radius behavior for 3 point splines
This commit fixes T96229.

The maximum possible radius was being used for 3 point
splines, regardless of the current radius.

Reviewed By: HooglyBoogly

Maniphest Tasks: T96229

Differential Revision: https://developer.blender.org/D14311
2022-03-12 10:19:26 +05:30
f19582ebf4 UI: Use property split in curves surface panel 2022-03-11 14:57:50 -06:00
db7c4d7a1c Cleanup: Use new enum for NURBS curve knots modes
Move the definition of the enum to `Curves` DNA, since the values
will be saved in files, and ongoing development needs to use this.
2022-03-11 14:55:42 -06:00
bd9f94e917 Fix T94692: Show Cached OneDrive Thumbnails
When OneDrive files are offline, show preexisting thumbnails.

See D13930 for details.

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

Reviewed by Julian Eisel
2022-03-11 10:05:16 -08:00
22807d2075 Curves: Move constructor/assignment
Add the ability to move `CurvesGeometry` without copying its attributes
and data. The benefit is more intuitive management of the data-block
copying, and less overhead for copying in some cases. The "moved-from"
source is left in an empty but valid state. A test file is added to test
the move constructor.
2022-03-11 11:34:03 -06:00
Ethan-Hall
3b28c785d4 Cycles: show viewport hair settings when using Cycles
Before this patch, users had to switch render engines just to change how the
hair should be displayed in solid and material preview viewport shading modes.

Differential Revision: https://developer.blender.org/D14290
2022-03-11 18:27:58 +01:00
Ethan-Hall
3902bebf18 Cycles: make smart interpolation fallback to cubic for GPU
Matching CPU and Eevee behavior.

Differential Revision: https://developer.blender.org/D14296
2022-03-11 18:27:58 +01:00
1842cef210 Fix wrong line width when using Show Lines in Histogram scope
By not resetting the line width, other scopes were using the
wrong line thickness.

Contributed by RedMser.

Differential Revision: https://developer.blender.org/D12030
2022-03-11 18:27:58 +01:00
Hallam Roberts
3da84d8b08 Cleanup: use M_PI_2 and M_PI_4 where possible
The constant M_PI_4 is added to GLSL to ensure it works there too.

Differential Revision: https://developer.blender.org/D14288
2022-03-11 18:27:58 +01:00
62a0984d72 Cleanup: fix source typos homogenous->homogeneous
Contributed by luzpaz.

Differential Revision: https://developer.blender.org/D14306
2022-03-11 18:27:58 +01:00
e1a1dc868b Cleanup: fix source comment typos
Contributed by luzpaz.

Differential Revision: https://developer.blender.org/D14307
2022-03-11 18:27:58 +01:00
dbd9472ef5 Fix: Assert in set spline type node after recent commit
My own error when committing 0602852860. It appears that
the "Endpoint" knots modes should be handled together, otherwise
out of bounds array access is possible.
2022-03-11 11:27:34 -06:00
ae3c8bc9f0 Fix T85689: Replace SHGetFileInfoW for Drive Name
Win32: Replace SHGetFileInfoW as means to get friendly display names
for volumes because it causes long pauses for disconnected remote
drives.

See D14305 for more details.

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

Reviewed by Brecht Van Lommel
2022-03-11 09:26:59 -08:00
5c86f0369c Fix: Deleting vertex group attribute can change original mesh
There was an error with the attribute API implementation for vertex
groups. If the vertex group layer referenced an original mesh, it wasn't
properly duplicated for writing.
2022-03-11 11:25:59 -06:00
28434dab0c Cleanup: Use helper variable
For a NURBS curve, the order is just the degree plus one.
So just pass around the degree instead of always subtracting one.
2022-03-11 10:46:48 -06:00
9097c97767 Fix T96243: Workbench Curvature not rendering in background.
When rendering using the command line the curvature wasn't rendered. The reason
was that the ui_scale wasn't initialized and therefore the same pixels where
sampled to detect the curvature. This is fixed by setting the ui_scale to 1 for any
image render.
2022-03-11 13:52:12 +01:00
9bee8e46a1 Event System: limit early evaluation of drag actions to mouse buttons
Change early drag evaluation added in
1f1dcf41d5 to only apply to drag events
from mouse buttons. Otherwise pressing two keyboard keys at one would
create a drag event for the first pressed key. While this didn't cause
any bugs as far as I know, this behavior makes most sense for drags
that come from cursor input.
2022-03-11 23:06:45 +11:00
c87c12b2a4 Event System: only set press values in win->eventstate
Only set press events in the windows eventstate, not the current event
since it's not useful for these to be set current events press values.
This makes it possible for a press event to access values for the
previous press.
2022-03-11 23:04:11 +11:00
789b1617f7 Fix out of order event handling when calling operators from gizmos
Activating a gizmo used the windows eventstate which may have values
newer than the event used to activate the gizmo.

This meant transforms check for the key that activated transform
could be incorrect.

Support passing an event when calling operators to avoid this problem.
2022-03-11 22:49:47 +11:00
e20fe18706 Correct error in 1032f111d0
Thanks to Jacques Lucke for spotting.
2022-03-11 22:37:16 +11:00
f4c8b4eb3e Fix threading conflict with movie cache line
It was possible that a render thread will be freeing cache while the
interface is iterating over cache items to build cache line.

Found while looking into T94738. It might be a fix, but I am unable
to reproduce the original issue, so can not know for sure whether
there is something else going or or not.
2022-03-11 12:34:37 +01:00
8f2c7b10cb temp-sculpt-colors: add typename keywords to make
gcc happy.
2022-03-11 01:22:26 -08:00
7701ae6792 temp-sculpt-colors: Remove various extraneous extern keywords 2022-03-11 01:12:08 -08:00
f6564df351 Cleanup: remove duplicate compiler attribute 2022-03-11 15:29:11 +11:00
cf58648409 Correct error in d2222d5b2c 2022-03-11 15:27:34 +11:00
d2222d5b2c RNA: use a function to access the nurbs error message
It makes more sense to use a function in this case as this
creates an error message which is not data associated with
the NURBS curve.
2022-03-11 15:21:30 +11:00
8cc5483331 Text: use simplified logic for txt_to_buf
This function was copied from txt_sel_to_buf, including unnecessary
complexity to support selection as well as checks for the cursor
which don't make sense when copying the whole buffer.

Use a simple loop to copy all text into the destination buffer.
2022-03-11 15:14:14 +11:00
231eac160e PyAPI: use C/RNA API for Text.from_string/to_string
Use faster C code for getting the buffer from text.
2022-03-11 14:44:02 +11:00
1032f111d0 RNA: support functions returning allocated strings
Now it's possible for a C/RNA function to return a dynamic string,
The PROP_NEVER_NULL flag is also supported so a NULL string returns
None in Python.
2022-03-11 14:42:39 +11:00
f527d6582b Cleanup: remove unused variable 2022-03-11 12:38:34 +11:00
d73726dbbe Cleanup: use doxy sections for the outliner 2022-03-11 12:00:08 +11:00
0327a464ba Fix dragging items in the outliner
Regression in b8960267dd,
it's important for box-select to use the drag start to check
if the cursor is over an icon.
2022-03-11 11:46:23 +11:00
Laurynas Duburas
0602852860 Curve: Improve NURBS knot generation modes
This patch enables all 8 combinations of Nurbs modes: Cyclic,
Bezier and Endpoint. Also removes restriction on Bezier Nurbs order.

The most significant changes are mode combinations bringing new
meaning. In D13891 is a scheme showing NURBS with same control
points in a modes, and also further description of each possible case.

Differential Revision: https://developer.blender.org/D13891
2022-03-10 18:34:27 -06:00
27fb63381e Fix T94121: PyAPI: ID property group returns wrong type with iter()
Regression in 265d97556a.
Where iterating directly on a property group failed, e.g.:
`iter(group)`, tests missed this since only `group.keys()`
was checked.
2022-03-11 10:26:27 +11:00
4a8bd31825 Cleanup: use doxy sections in image.cc
Also minor improvements & clarifications to comments.
2022-03-11 09:41:48 +11:00
d449deec21 Cleanup: use enum for local versioning enum 2022-03-11 09:27:37 +11:00
Germano Cavalcante
e3de755ae3 Transform/UI: individualize the option to use snap per editor type
`3DView`'s `use_snap` option has little or nothing to do with using
snapping in `UV`, `Nodes` or `Sequencer`.
So there are no real advantages to keeping these options in sync.

Therefore, individualize the option to use snap for each "spacetype".

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D13310
2022-03-10 18:47:38 -03:00
edcb2ad7b3 Fix: Handle handles reset when realizing with other curve types
The result handle attributes for non-bezier types are zeroed.
By mistake though, the entire array was zeroed, not just the
area corresponding to that curves source.
2022-03-10 15:42:30 -06:00
fe3a9fcce1 Fix incorrect meta strip background color
When viewing meta strip, it had orange color. This was caused by
overflow because of hard-coded offset. Theme got darker, and background
was also set again further in code, but redundant drawing was removed in
f4492629ea.
2022-03-10 20:26:21 +01:00
3f91e7d779 Curves: actually delete curves with Delete brush
Previously, the position was just set to zero as part of the prototype.

Differential Revision: https://developer.blender.org/D14291
2022-03-10 18:06:43 +01:00
22a341d9d8 Fix T96292: unable to set active material output using Python
Differential Revision: https://developer.blender.org/D14301
2022-03-10 18:04:07 +01:00
338fe9e2b5 Cleanup: Reduce duplication in realize instances code
Realizing and copying attributes of meshes, curves, and points are very
similar processes, but currently the logic is duplicated three times in
the realize instances code. This commit combines the implementation
for copying generic attributes and creating the result id attribute.

The functions for threaded copying and filling should ideally be in
some file elsewhere, since they're not just useful here. But it's not
clear where they would go yet.

Differential Revision: https://developer.blender.org/D14294
2022-03-10 09:37:56 -06:00
8cdee3a6d4 Fix T93710: Artifacts denoising hi-res images using OPtiX
Caused by an integer overflow in the tiling utilities of OptiX SDK.

Seems for now it's easier to copy and modify code to our sources so
that we don't need to bump SDK version requirement (which might lead
to an increased driver requirement as well).

There are still some fixes needed from a newer driver to have such
denoising to work properly: Windows requires 511.79, Linux 510.54.

Thanks Patrick for investigation!

Differential Revision: https://developer.blender.org/D14300
2022-03-10 16:17:59 +01:00
Ethan-Hall
34d8ef8fa4 Fix: closest image texture interpolation inconsistent in geometry nodes
The `-0.5f` offset is inconsistent with shader nodes.
See D14235 for an example file.

Differential Revision: https://developer.blender.org/D14235
2022-03-10 11:38:08 +01:00
7b62203fc7 IK: make Ik chain length non-animatable
Mark the chain length of regular and spline IK constraints
non-animatable. Changing the IK chain length requires a rebuild of
depsgraph relations. This makes it unsuitable for animation. It's better
to simply avoid having this property animatable than to allow animation
but produce unstable results.

Ref: T96203
2022-03-10 11:34:51 +01:00
1f1dcf41d5 Event System: key-press while dragging now activates drag first
When dragging with a large threshold (using a tablet for example),
it's possible to press another key before the drag threshold is reached.

So tweaking then pressing X would show the delete popup instead of
transforming along the X-axis.

Now key presses while dragging cause the drag event to be evaluated
before the key press.

Note that to properly base the mouse-move event on the previous
state the last handled event is now stored in the window.
Without this the inserted mouse-move event may contain invalid values
from the next event (it's modifier state or other `prev_*` values).

Requested by @JulienKaspar.
2022-03-10 21:26:15 +11:00
ef6d108b75 Fix T96279: 'Emulate 3 button mouse' fails to emulate MMB
Regression in 08d8eee006 caused
emulate-middle mouse to work once, clearing the modifier key.

Now the modifier key from emulated mouse events is never stored
in the windows event-state.
2022-03-10 20:50:58 +11:00
b33d38ebd9 Cleanup: de-duplicate event customdata freeing logic 2022-03-10 16:44:47 +11:00
8c3aee2faf Cleanup: use SPDX license header 2022-03-10 16:27:18 +11:00
36dd3f42bc Cleanup: use 'WM_file_' prefix for file operations 2022-03-10 16:27:18 +11:00
1829232598 Cleanup: spelling in comments & some minor clarifications 2022-03-10 16:27:18 +11:00
0ef8a6179d Cleanup: Move image.c to c++
Passing on all platforms:
https://builder.blender.org/admin/#/builders/18/builds/329

Differential Revision: https://developer.blender.org/D13962
2022-03-09 21:03:02 -08:00
f379943734 Cleanup: Simplify/deduplicate curves built-in attribute access
Separate two templated functions that deal with custom data so that
each built-in attribute accessor doesn't need the same boilerplace and
logic.
2022-03-09 22:59:39 -06:00
24c543d4af Fix: Add missing break 2022-03-09 10:27:08 -06:00
115ff08fdb Fix: Use "construct" instead of "assign" for uninitialized memory
The realize instances code used "assign", but the attribute buffers on
the result aren't necessarily initialized. This doesn't make a difference
for trivial types like `int`, but it would with more complex types.
2022-03-09 10:23:17 -06:00
6c6f591f90 Curves: Port realize instances node to the new data-block
This commit replaces the temporary conversion to `CurveEval` with
use of the new curves data-block. The end result is that the
process looks more like the other components-- somewhere in between
meshes and point clouds in terms of complexity.

The final result is that the logic between meshes and curves is
very similar. There are a few different strategies to reduce
duplication here, so I'll investigate that separately.

There is some special behavior for the radius and handle position
attributes. I used the attribute API to store spans of these
attributes temporarily. Using access methods on `CurvesGeometry`
would be reasonable to, storing spans separately feels a bit more
predictable for now though.

There should be significant performance improvements in some cases,
I haven't tested that specifically though.

Differential Revision: https://developer.blender.org/D14247
2022-03-09 09:58:02 -06:00
39c50d8f31 Outliner: Ensure compiler error when passing wrong tree-element to macro
Passing a `TreeElement *` instead of its `TreeStoreElement *` to
`TSELEM_OPEN()` would seem to work but cause a bug. Add a type check
that will cause a compiler error if it fails.
2022-03-09 15:28:16 +01:00
8e3a58578a Outliner: Correct check for element culling
I don't see a reason to use 2x the element height for the "in-view"
checks. That seems incorrect (although shouldn't cause issues). So
remove that, I don't expect behavior changes.
2022-03-09 15:23:51 +01:00
c4d3d10401 Cleanup: Deduplicate Outliner item culling logic
For whatever reason the "in-view" check was using 2x the element height.
From what I can see this isn't needed, so I'll remove it in a follow-up
commit.
2022-03-09 15:23:51 +01:00
beaf2baeff Cleanup: fix wrong spelling of texture and indentation
Contributed by luzpaz.

Ref D14271, D14270
2022-03-09 15:07:38 +01:00
Ethan-Hall
ef3d76fbaa Fix wrong detection of alpha for grayscale images, after recent changes
Differential Revision: https://developer.blender.org/D14286
2022-03-09 14:53:07 +01:00
6be665926c LibOverride/Outliner: Restrict further operations over liboverrides.
Restrict a lot deletion/moving around of liboverride objects and
collections in the Outliner.

While some of those operations may be valid in some specific cases, in
the vast majority of cases they would just end up breaking override
hierarchies/relationships.

Part of T95708/T95707.
2022-03-09 12:50:04 +01:00
6a7066c2c1 LibOverride: Add a 'is hierarchy root' macro check. 2022-03-09 12:50:04 +01:00
4da282a161 Curves: rename initial brushes
The brushes that are still called "Test" still need to be changed
until they can get their correct name.

Ref T96259.
2022-03-09 11:33:33 +01:00
010ea688f1 Fix T96233: Crash with gpencil data with vertex groups
Blender crashes when a multi-user grease pencil object has vertex
groups and is modified by modifiers, layer transform or parenting.

The fix makes sure that we copy the vertex group names list.

Reviewed By: antoniov

Maniphest Tasks: T96233

Differential Revision: https://developer.blender.org/D14275
2022-03-09 11:22:51 +01:00
04e89c5b06 Fix T96165: Incorrect render of barcelone scene with BVH2
Fix T95462: Partly transparent objects appear to glow in the dark

The issue was caused by incorrect check for exceeded number
of transparent bounces: the same maximum distance was used
for picking up N closest intersections and counting overall
intersections count.

Now made it so intersection count is using ray distance which
matches the way how Embree and OptiX implementation works.

Benchmark result:
{F12907888}

There is no big time difference in the pabellon scene. The
Victor scene timing doesn't seem to be very reliable as the
variance in time across different benchmark runs is quite
high.

Differential Revision: https://developer.blender.org/D14280
2022-03-09 10:37:19 +01:00
801d7b4921 Fix T95738: wrong "Bottom" selection for cone without base
Original patch by @lone_noel with changes by me.

Differential Revision: https://developer.blender.org/D14102
2022-03-09 10:34:59 +01:00
1f9d85f56a Fix cursor drag failing to use click-start
Error in b8960267dd,
the flag was cleared before use.
2022-03-09 17:18:31 +11:00
9416004092 Cleanup: use doxygen comments & sections for animation files 2022-03-09 16:29:22 +11:00
136f0910ff Fix T96250: Invalid default for uv_relax_method
Correct the default & version existing files.
2022-03-09 16:10:19 +11:00
20f53f6984 Correct assert in 399ac1ff11
Pass NULL instead of an empty string.
2022-03-09 13:43:39 +11:00
399ac1ff11 Fix subtype & default for keying set operator properties
Error in 1a12c9edab,
also correct descriptions.
2022-03-09 13:23:00 +11:00
e55f4657f7 Fix T89560: Keymap editor no longer shows keying set dropdown
Include built-in keying sets when ANIM_keying_sets_enum_itemf is called
without a context to allow binding keys to built-in keying sets.
2022-03-09 13:02:29 +11:00
2146256563 Cleanup: use ELEM macro 2022-03-09 10:13:43 +11:00
626c844105 Cleanup: rename wmEvent.prev_click_* to prev_press_*
At the time of naming these members only some event types generated
click events so it made some sense to differentiate a click.

Now all buttons support click & drag it's more logical to use the
prefix "prev_press_" as any press event will set these values.

Also update doc-strings.
2022-03-09 09:25:14 +11:00
353376c783 Fix T92331: Duplicated Window Should Not Be Modal
Operator area_dupli_invoke should not create modal windows.

See D14253 for details.

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

Reviewed by Brecht Van Lommel
2022-03-08 13:57:35 -08:00
Aleksi Juvani
eb326c7b40 Attributes: Implement CustomData interpolation for boolean data type
This commit fixes an issue, where for instance, when merging vertices
with the "Merge by Distance" geometry node, the resulting vertices had
their boolean attributes set unpredictably.

Boolean attributes are implemented as custom data, and when welding
vertices, the custom data for the resulting vertices comes from
interpolating the custom data of the source vertices.

This commit implements the missing interpolation function for the
boolean custom data type. This interpolation function is implemented in
terms of the logical or operation, that is to say, if any of the source
vertices (with a weight greater than zero) have the boolean set, the
boolean will also be set on the resulting vertex.

This logic matches 95981c9876.

In geometry nodes, attribute interpolation generally does not use the
CustomData API for performance reasons, but other areas of Blender
still do.

Differential Revision: https://developer.blender.org/D14172
2022-03-08 15:51:53 -06:00
521d4190a0 Fix T96146: Subdivide curve node uninitialized dangling handles
Handles of non-cyclic bezier curves were not initialized.
Now properly copy the dangling handle positions and types
from the source curve.
2022-03-08 15:45:37 -06:00
b8960267dd Event System: drag events no longer default to the drag start location
This avoids transform jumping which is a problem when tweaking values a
small amount. A fix for T40549 was made box-select used the location
when the key was pressed.

While it's important for box-select or any operator where it's expected
the drag-start location is used, this is only needed in some cases.
Since the event stores the click location and the current location,
no longer overwrite the events real location. Operators that depend on
using the drag-start can use this location if they need.

In some cases the region relative cursor location (Event.mval) now needs
to be calculated based on the click location.

- Added `WM_event_drag_start_mval` for convenient access to the region
  relative drag-start location (for drag events).
- Added `WM_event_drag_start_xy` for window relative coordinates.
- Added Python property Event.mouse_prev_click_x/y

Resolves T93599.

Reviewed By: Severin

Ref D14213
2022-03-09 08:38:42 +11:00
Hallam Roberts
156e07232e Geometry Nodes: Tiny optimization to UV Sphere primitive
Prevents a few unneeded calls to `std::sin`, with an observed
performance improvement of about 1 percent.

Differential Revision: https://developer.blender.org/D14279
2022-03-08 14:39:58 -06:00
d09695b4dd Cleanup: Clang tidy 2022-03-08 13:28:22 -06:00
90c3147e05 Cleanup: Correct comment
Normals aren't stored in custom data anymore, nor are they stored in
MVert for comparisons.
2022-03-08 12:31:21 -06:00
c7ff99b100 Merge branch 'blender-v3.1-release' 2022-03-08 12:19:50 -06:00
c77597cd0e Fix T95843: Invalid mesh runtime data after sculpt undo
When the geometry of the sculpt mesh was replaced when restoring from
a full undo step, the runtime data was not cleared (including any
normals, triangulation data, or any other cached derived data).
In the report, only the invalid normals were observed.

The fix is to simply clear these caches. Later they will be reallocated
and recalculated if necessary. Since the whole mesh replaced here
anyway, this should be a safe fix.

Differential Revision: https://developer.blender.org/D14282
2022-03-08 12:16:42 -06:00
ffea47530d Merge branch 'blender-v3.1-release' 2022-03-08 18:46:23 +01:00
7add8163e4 Blender 3.1 - version bump -> release 2022-03-08 18:36:00 +01:00
b154b8c6f8 Merge branch 'blender-v3.1-release' 2022-03-08 18:34:09 +01:00
b217eb73f5 Licenses: Attribution document for Blender 3.1 2022-03-08 18:27:04 +01:00
50bd8bb175 Cleanup: Remove extra . at the end of RNA string
The strings must not end with point.
2022-03-08 16:55:29 +01:00
c305b88aac Docs: 3.1 release description for Linux appdata 2022-03-08 16:55:19 +01:00
944122d49f Cleanup: Use ELEM macro 2022-03-08 16:44:03 +01:00
62885637fb Cleanup: Make format 2022-03-08 16:41:30 +01:00
Marc Chéhab
e74838d0d0 GPencil: New "Additive" mode for build modifier
The new mode only builds the new strokes in each frame. 

The code is assuming somebody uses "additive" drawing, so that each frame is different only in its NEW strokes. Already existing strokes are skipped. 

I used a simple solution: Count the number of strokes in the previous frame and ignore this many strokes in the current frame.

Differential Revision: https://developer.blender.org/D14252
2022-03-08 16:40:27 +01:00
5791835678 Geometry Nodes: fix spline length node after recent refactor
Differential Revision: https://developer.blender.org/D14276
2022-03-08 16:09:44 +01:00
7bd3762b7c UI: Minor tweaks to IDTemplate operations. 2022-03-08 14:57:47 +01:00
bea7d2e22d LibOverride: Do not assert when root ID is not object/collection.
While uncommon, this is still a valid case...
2022-03-08 14:57:47 +01:00
178f4fa71e Cleanup: fix compiler warning 2022-03-08 13:58:50 +01:00
6f8e65cd7a Merge remote-tracking branch 'origin/blender-v3.1-release' 2022-03-08 13:48:47 +01:00
d5e4cab76c Fix T96224: GPU subdiv crash with smooth normals and tangents
Tangents are computed from UVs on the CPU side when using GPU subdivision
and require that the normals are available there as well (at least for smooth
shading, flat normals can be computed on the fly). This simply adds the missing
normals update call for the `MeshRenderData` setup for the subdivision case.

Differential Revision: https://developer.blender.org/D14278
2022-03-08 13:47:14 +01:00
3a672fe6fb GPU: disable compute shader for problematic drivers
Some drivers for legacy platforms seem to have issues with compute
shaders, as revealed by T94936. This disables compute shader for the
known drivers where this issue is present. It is not clear if the issue
is Windows only or not, so this disable them for all operating systems.

See T94936 for a list of configurations where the issue is reproducible
or not.

Differential Revision: https://developer.blender.org/D14264
2022-03-08 13:39:18 +01:00
64a5fd7a1d Fix wrong edge crease validity check in the Cycles Alembic procedural 2022-03-08 13:38:21 +01:00
3cb3167278 Simplify sound property handling
Sound properties like volume, pitch and muting are handled in
`BKE_sound_add_scene_sound()`. This is unnecessary, because in
properties are then set to real values in `SEQ_edit_update_muting()` and
`seq_update_seq_cb()`.

Alternatively, it may be better to remove all other updates leave them
in `BKE_sound_add_scene_sound()`. But I want to add muting per channel,
whhich is easier and probably cleaner to do with function
`SEQ_edit_update_muting()`.

Reviewed By: sergey

Differential Revision: https://developer.blender.org/D14269
2022-03-08 13:16:36 +01:00
73dc8c24e4 PyAPI: optimize depsgraph use in PyDrivers
Avoid re-creating & freeing the depsgraph for every driver evaluation.

Now the depsgraph is kept in the name-space (matching self),
only re-created when the value changes.

In a contrived test-case with many drivers this gave ~15% overall
speedup for animation playback.
2022-03-08 22:15:12 +11:00
f76f48be23 Fix (unreported) liboverride rules from linked data disapearing.
Code cleaning up no-more-needed override data during diffing process
would systematically remove override data from linked IDs.

While this is not a critical issue in theory, it has bad consequences at
the very least on user UI/UX, and potentially can cause bugs in some
corner-cases scenarii.
2022-03-08 12:08:21 +01:00
0df8c22c8a LibOverrides: Tweak to ensure no overrides can be created on linked data.
Was already mostly the case, but from RNA API there was no proper check.
2022-03-08 11:02:22 +01:00
1c1efe3ac6 Fix memory leak evaluating PyDrivers
Missed decref in 686ab4c940 caused every
driver evaluation to create the BPy_StructRNA depsgraph without freeing
the previously allocated depsgraph.
2022-03-08 20:47:43 +11:00
10c11bb897 Curves: add initial comb, grow and shrink brush
The exact behavior of the brushes is still being iterated on, but it
helps having a base implementation that we can work upon.
All of that is still hidden behind an experimental feature flag anyway.

The brushes will get a name in the ui soon.

Differential Revision: https://developer.blender.org/D14241
2022-03-08 10:41:52 +01:00
Jeroen Bakker
1d902a6367 Fix T96213: Crash when texture painting across multiple materials.
Issue only happens in release builds on windows. That said it was an
actual error in the code. This class is compiled inline in release
builds. When updating multiple textures it would reuse the same memory
to collect the changes. When the previous loaded tilenumber was exactly the
same but from a different image the tile buffer wasn't loaded.

Reviewed By: sergey

Maniphest Tasks: T96213

Differential Revision: https://developer.blender.org/D14274
2022-03-08 10:38:38 +01:00
94d2470c41 Curves: increase default viewport resolution for curves object
This part has to be refactored soon anyway, because more types
curves have to be drawn for the new Curves object.

For now, 3 is a better default than 2, because that matches the
actual resolution of the curve currently.
2022-03-08 10:36:46 +01:00
4b598739c5 Curves: disable stroke spacing for curve sculpt brushes
This makes the brushes more smooth, because the brush has an
effect after every mouse move, instead of only every x pixels.

For this to work well, the brushes have to look at the stroke
segments instead of at the mouse positions separately.

A more fine grained check might be added in the future.
2022-03-08 10:33:51 +01:00
b588c09eee Fix: add missing case in switch statement for curves 2022-03-08 10:23:38 +01:00
3d71a05a1d Merge branch 'blender-v3.1-release' 2022-03-08 09:52:47 +01:00
Pratik Borhade
2ddb53de54 Fix T96228: TypeError on use of Copy from Active Track operation
Issue was introduced after the python 3.10 switch
Explicit conversion to int will fix the issue.
Same issue is likely to happen with `MovieTrackingSettings.default_search_size`
So I did the same change over there.

Differential Revision: https://developer.blender.org/D14273
2022-03-08 09:52:17 +01:00
63ac1660c0 Fix T92861: Transform fails for multiple pose object sharing ob-data
Support transforming two pose objects at once even when they share
object data as this is per-object.
2022-03-08 15:13:53 +11:00
3c889fe2b0 Cleanup: pass const scene argument to UV selection functions 2022-03-08 14:45:33 +11:00
06d9c2c223 Cleanup: spelling in comments 2022-03-08 14:32:34 +11:00
c0c840cc31 Cleanup: prefer UNUSED_VARS_NDEBUG for debug only variables
Otherwise it's possible to accidentally use these variables
in debug builds, breaking release builds.
2022-03-08 14:15:34 +11:00
59c972b40a Event System: remove unused NDOF buttons
GHOST always converts NDOF keyboard buttons into keyboard events
so there is no need to expose their values for Blender event types.
2022-03-08 14:01:49 +11:00
88b2bbc649 Event System: support changing NDOF button shortcuts 2022-03-08 13:56:04 +11:00
b58e660828 Event System: click/click-drag support for NDOF buttons
Support this for completeness, as it's simpler to support click-drag
for all events types that support press/release instead of having to
document which kinds buttons support click-drag.
2022-03-08 13:48:40 +11:00
f052fb5646 Event System: add ISKEYBOARD_OR_BUTTON macro
This simplifies checking for event types that support press & release.
2022-03-08 13:48:34 +11:00
08d8eee006 Event System: refactor click detection into function
Also simplify modifier & keymodifier assignment.
2022-03-08 13:48:33 +11:00
08f88bba69 Event System: exclude cursor & NDOF motion from ISHOTKEY() macro
In practice this didn't cause a bug since assigning hot-keys was also
checking for "press" events (which NDOF_MOTION doesn't generate).

Add ISNDOF_BUTTON macro which is now used by ISHOTKEY to avoid
problems in the future.
2022-03-08 13:48:32 +11:00
7b66397664 Cleanup: spelling in comments, use C++ comments for disabled code 2022-03-08 13:48:31 +11:00
901a03725e Curves: Port mesh to curve node to new data-block
The main improvement is a code simplification, because attributes don't
have to be transferred separately for each curve, and all attributes can
be handled generically. Performance improves significantly when the
output contains many curves. Basic testing with a 2 million curve output
shows an approximate 10x performance improvement.
2022-03-07 19:06:40 -06:00
c238728105 Fix: Curves cyclic access function duplicates attribute
This was an oversight in 6594e802ab. First it must check if the
attribute exists before adding it.
2022-03-07 18:58:04 -06:00
b8f1ae5c38 Cleanup: Rename geometry set "curve" to "curves"
Similar to 245722866d, just another function I missed before.
2022-03-07 16:26:55 -06:00
dfd7832a0e Merge branch 'blender-v3.1-release' 2022-03-07 13:58:14 -06:00
2b3367cdf8 Fix T93573: Curve evaluated mesh selected in edit mode
This fixes the second part of T93573 that 8506f3d9fe didn't
properly address. Specifically, outlines of instances still had the
selected color in edit mode in wireframe view. This change is the
same as that commit, just in a different place.

Differential Revision: https://developer.blender.org/D14229
2022-03-07 13:54:49 -06:00
0597902bde Fix memory leak when reading ffmpeg video frames.
We had forgotten to unref packets after reading them.
This lead to a memory leak inside of ffmpeg.
2022-03-07 19:04:51 +01:00
Leon Schittek
1cb303242f UI: align labels of number fields and value sliders
Previously the labels and values in number fields and value sliders
used different padding for the text. This looks weird when they are
placed underneath each other in a column and, as noted by a comment
in the code of `widget_numslider`, they are actually meant to be
aligned.

This patch fixes that by using the same padding that is used for the
number field for the value slider, as well. This also has the benefit,
that the labels of the value sliders don't shift anymore when adjusting
the corner roundness.

Differential Revision: https://developer.blender.org/D14091
2022-03-07 18:32:47 +01:00
21d633f83b GPencil: Temporary fix to avoid crashes on startup
This quick fix will populate the runtime orig pointers to avoid
crashes when a grease pencil object uses layer transforms, parenting
or modifiers.
This will have to be revisited and fixed with a better solution.
2022-03-07 17:48:36 +01:00
Ethan-Hall
15186f4259 Shader Nodes: added alpha mode selector to Image Texture node
Enables image user nodes to display the file alpha mode, similar to the
colorspace setting.

Also removes image_has_alpha in favor of using BKE_image_has_alpha, because it
did not check if the image actually had an alpha channel, just if the file format
was capable of supporting an alpha channel.

Differential Revision: https://developer.blender.org/D14153
2022-03-07 17:39:27 +01:00
Ethan-Hall
5b4ab89663 Shader Nodes: add Alpha output to Object Info node
An alpha component can be specified for an object's color. This adds an alpha
socket to the object info shader node allowing for the alpha component of the
object's color to be accessed in the shader editor.

Differential Revision: https://developer.blender.org/D14141
2022-03-07 17:35:48 +01:00
76f9d83a19 Merge branch 'blender-v3.1-release' 2022-03-07 17:31:32 +01:00
Ethan-Hall
60481e4d99 Fix T96195: f-curve factorized polynomial generator broken UI
The polynomial parameters were not shown correctly.

Differential Revision: https://developer.blender.org/D14254
2022-03-07 17:30:30 +01:00
f130d4f211 Cleanup: fix various typos
Contributed by luzpaz.

Differential Revision: https://developer.blender.org/D14203
2022-03-07 17:28:39 +01:00
5bb2b4236d Cleanup: move asssertion-test-only variable into #ifndef NDEBUG block
Move `ToolSettings *ts` into an `#ifdef NDEBUG` block, as it's only used
for a `BLI_assert` call.
2022-03-07 17:10:13 +01:00
2d06b97d29 Fix T95256: Crash when creating off-screen pose asset
Fix crash when creating a pose asset for which the file list entry in
the asset browser is scrolled off-screen. Because of the
off-screen-ness, it wasn't loaded into memory, which eventually caused
an unexpected NULL pointer.

The solution was to use a different function (`filelist_file_find_id`)
that can reliably find the file list entry, after which the cache entry
can be created.

Reviewed by: Severin

Differential Revision: https://developer.blender.org/D14265
2022-03-07 17:07:20 +01:00
Leon Schittek
6b8dde93b0 Fix T95531: Draw y axis values in Driver Editor
When drawing the driver editor, only skip drawing the "scrubbing area"
and not the Y-axis values or the scroll bars.

The issue was introduced in rBb3431a88465db2433b46e1f6426c801125d0047d
to avoid drawing the playhead in the Driver Editor but also prevented
the text on the y axis from being drawn.

Reviewed by: Severin, sybren

Maniphest Tasks: T95531

Differential Revision: https://developer.blender.org/D14022
2022-03-07 17:07:20 +01:00
5dca3ee6a2 Fix T95256: Crash when creating off-screen pose asset
Fix crash when creating a pose asset for which the file list entry in
the asset browser is scrolled off-screen. Because of the
off-screen-ness, it wasn't loaded into memory, which eventually caused
an unexpected NULL pointer.

The solution was to use a different function (`filelist_file_find_id`)
that can reliably find the file list entry, after which the cache entry
can be created.

Reviewed by: Severin

Differential Revision: https://developer.blender.org/D14265
2022-03-07 17:04:10 +01:00
5ae26e410a Fix T94360: Assert on dragging keyframes
Fix an assert by commenting out the assert.

In normal situations all keyframes are sorted. However, while keys are
transformed, they may change order and then this assertion no longer
holds. The effect is that the drawing isn't perfect during the
transform; the "constant value" bars aren't updated until the
transformation is confirmed. Apart from that, the code runs fine, so it
seems like a workable workaround.
2022-03-07 16:48:44 +01:00
Leon Schittek
ea3b2e8736 Fix T95531: Draw y axis values in Driver Editor
When drawing the driver editor, only skip drawing the "scrubbing area"
and not the Y-axis values or the scroll bars.

The issue was introduced in rBb3431a88465db2433b46e1f6426c801125d0047d
to avoid drawing the playhead in the Driver Editor but also prevented
the text on the y axis from being drawn.

Reviewed by: Severin, sybren

Maniphest Tasks: T95531

Differential Revision: https://developer.blender.org/D14022
2022-03-07 16:24:17 +01:00
5b2d9c0cbe Merge branch 'blender-v3.1-release' 2022-03-07 15:19:05 +01:00
e908ebc094 Fix T96207: wrong default value of Principled BSDF specular tint
Contributed by MysteryPancake.

Differential Revision: https://developer.blender.org/D14256
2022-03-07 14:53:59 +01:00
7f57899823 Merge branch 'blender-v3.1-release' 2022-03-07 12:37:54 +01:00
00f6e4c990 Fix T96180: driver in node tree not updating in real time
Differential Revision: https://developer.blender.org/D14260
2022-03-07 12:37:13 +01:00
4ffe2fec16 Python: Add new annotation_pre & annotation_post handlers
Annotation tool is used as a general mark tool for many add-ons. To be able to detect when an annotation is done is very handy to integrate the annotation tool in add-ons and other studio workflows.

The  new callback names are:  `annotation_pre`  and `annotation_post`

Both callbacks are exposed via the Python module `bpy.app.handlers`

Example use:

```
import bpy

def annotation_starts(gpd):
    print("Annotation starts")

def annotation_done(gpd):
    print("Annotation done")

bpy.app.handlers.annotation_pre.clear()
bpy.app.handlers.annotation_pre.append(annotation_starts)
bpy.app.handlers.annotation_post.clear()
bpy.app.handlers.annotation_post.append(annotation_done)
```

Note: The handlers are called for any annotation tool, including eraser.

Reviewed By: campbellbarton

Differential Revision: https://developer.blender.org/D14221
2022-03-07 12:36:47 +01:00
548eabbaa1 Revert "Revert "Fix Crash: Switching to wireframe mode.""
This reverts commit 25fc5876d3.

Committed this unintentionally, looking into an alternate fix.
2022-03-07 22:32:46 +11:00
638c0bd234 Merge branch 'blender-v3.1-release' 2022-03-07 21:52:24 +11:00
a61ee1dcae Cleanup: quiet warnings 2022-03-07 21:51:50 +11:00
0e51defcf4 Fix T95591: Crash on drawing with measure tool with tweak fallback tool
Using press to activate the Tweak tool doesn't work well when used a
fallback tool as the drag event is often used by the current tool -
making it impossible not to select when dragging (unless the fallback
tool is disabled entirely).
Resolve this by using CLICK events when the Tweak tool is used as a
fallback.

Even though this avoids the crash, check for null-pointer de-reference
since changes to the key-map shouldn't cause operators to crash.

Note that the ability for operators to access a gizmo before it's fully
initialized is a more general problem that should be addressed, but out
of scope for a bug-fix.

Reviewed By: zeddb, JulienKaspar, Severin

Maniphest Tasks: T95591

Ref D14231
2022-03-07 21:47:00 +11:00
Yann Lanthony
7ca13eef7c Improve multi-user gpencil data performance with modifiers
When a grease pencil data-block has multiple users and is subject
to modifiers, layer transforms or parenting, performance
(especially playback) is greatly affected.

This was caused by the grease pencil eval process which does per
instance full-copies of the original datablock in case those
kinds of transformations need to be applied.

This commit changes the behavior of the eval process to do shallow
copies (layers with empty frames) of the datablock instead
and duplicates only the visible strokes.

When we need to have a unique eval data
per instance, only copy the strokes of visible
frames to this copy.

Performance:
On a test file with 1350 frames 33k strokes and 480k points
in a single grease pencil object that was instanced 13 times:
 - master: 2.8 - 3.3 fps
 - patch: 42 - 52 fps

Co-authored by: @filedescriptor
This patch was contributed by The SPA Studios.

Reviewed By: #grease_pencil, pepeland

Differential Revision: https://developer.blender.org/D14238
2022-03-07 11:38:56 +01:00
57c5f2a503 Merge branch 'blender-v3.1-release' 2022-03-07 21:35:21 +11:00
72e20785e1 Fix T96205: Active shape key gets lost upon edit mode undo
Regression in d961adb866,
it's important that for the Mesh used for undo storage matches
the shape-key instead of using the coordinates of the Basis key.

Prior to bfdbc78466 a different method of
restoring the basis shape-key coordinates was used (restoring from the
input `Mesh.mvert` array). When undo wrote the edit-mesh into the mesh
this was always NULL so the basis shape keys coordinates were never
used.

Now a parameter has been added so undo can use the active shape for the
meshes vertex coordinates.

Reviewed By: sergey

Maniphest Tasks: T96205

Ref D14258
2022-03-07 21:31:48 +11:00
25fc5876d3 Revert "Fix Crash: Switching to wireframe mode."
This reverts commit cb986446e2.
2022-03-07 19:55:33 +11:00
781e212427 temp-sculpt-colors: Cleanup a few comments. 2022-03-07 00:28:18 -08:00
ba410bb416 Merge branch 'master' into temp-sculpt-colors 2022-03-07 00:17:59 -08:00
Jeroen Bakker
073d2390f0 Fix T96163: Image editor doesn't refresh when undo/redo.
Undo would invalidate image owned GPU textures only. Textures
that are owned by the editor were not refreshed. This patch would
invalidate all the GPU textures by marking the whole image dirty.

This can be improved later as we could add partial updates of GPU
textures.

Reviewed By: mont29

Maniphest Tasks: T96163

Differential Revision: https://developer.blender.org/D14259
2022-03-07 08:43:50 +01:00
ad2948face Merge branch 'blender-v3.1-release' 2022-03-07 07:49:52 +01:00
4681987d92 Fix T96156: Snap to 3D cursor can't be undone
Caused by oversight in 2bcf93bbbe. Operator returns `OPERATOR_CANCELLED`
when it should return `OPERATOR_FINISHED`.

Reviewed By: mano-wii, campbellbarton

Differential Revision: https://developer.blender.org/D14243
2022-03-07 07:46:24 +01:00
Red Mser
8ec35c05b2 Curve: sync active material with selection
Changing active spline updates active material index.

Reviewed By: campbellbarton

Ref D14250
2022-03-07 12:06:33 +11:00
fae45a43fa Cleanup: use doxy-sections for pipeline, text_drag & effects
Also improve on the doc-string for RE_RenderFrame & RE_RenderAnim.
2022-03-07 10:51:22 +11:00
a5f972c018 Cleanup: use loops for key-map entries that map values to number keys
Also add __all__ referencing the only two members of the modules
that should be accessed externally.
2022-03-06 21:16:21 +11:00
887ccb8537 Fix T96152: Crash realizing curve instances
The "curve_type" was transferred to instances because it isn't a
built-in curve attribute. Then it was interpolated as a point
domain attribute from the instance domain in the realize
instances node.

The fix was just missing from 9ec12c26f1.
`curve_type` needs to be marked as a built-in attribute.
2022-03-04 22:28:57 -05:00
295d5c6ef5 Fix T96164: Crash with curve domain attributes
When converting from the new type to the old, the curve domain
attributes weren't properly resized, so their data was not properly
allocated.
2022-03-04 11:11:56 -05:00
45079b169d Fix T96160: freezing when using multiple Handle Type Selection nodes
Differential Revision: https://developer.blender.org/D14245
2022-03-04 15:21:18 +01:00
1763ffa0be Cleanup: Unused variable warnings 2022-03-04 07:59:07 -05:00
5eaeb9bd0d GPencil: Fix wrong parameters in gpencil_check_same_material_color
The stroke and fill parameters were flipped.
2022-03-04 08:44:23 +01:00
0212c423bf Cleanup: remove outdated references to tweak 2022-03-04 13:31:16 +11:00
0a4fdcbb5f Cleanup: unused Python variables & imports 2022-03-04 11:07:37 +11:00
6bca614fd8 Cleanup: use doxy-sections in outliner_draw.cc
Also remove outdated comment.
2022-03-04 10:53:06 +11:00
bfd43222c3 Cleanup: use doxy-sections for interface_dropboxes.cc 2022-03-04 10:35:22 +11:00
0a2d61f45c Sequencer: de-duplicate new-scene enum, include in generated docs 2022-03-04 10:31:11 +11:00
65e6bcdd9f Sequencer: disallow assigning scenes to non-seuencer strips 2022-03-04 10:31:11 +11:00
ccefcf46bf Cleanup: use doxy-sections in scene_edit.c 2022-03-04 10:31:11 +11:00
4837ea3ab6 Cleanup: warning & spelling from recent scene/sequencer operator
- Avoid the abbreviation "VSE" as the convention is to use "sequencer".
- Remove dead-code (second return statement).
- Remove unused argument.
2022-03-04 10:31:11 +11:00
8b06c524d2 Cleanup: spelling in comments, function name 2022-03-04 10:31:11 +11:00
Azeem Bande-Ali
fd2519e0b6 UI: Drag & Drop to Properties Materials Panel
Support drag/drop of materials to Properties Material Slots.

See D13549 for more details.

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

Reviewed by Julian Eisel
2022-03-03 15:28:48 -08:00
471f27d66b Curves: Port endpoint selection node to new data-block
The node should be faster than in 3.1, for a few reasons:
- It doesn't need to calculate and allocate the curve offsets.
- It doesn't need to de-reference a pointer for each curve.
- The inputs are accessed from the virual arrays fewer times.

On top of that, I added two other performance improvements:
- The node is multi-threaded when there are many curves.
- There are generated special cases for single value and span inputs.

**Performance**
With a set position node affecting 1 million splines with a selection
based on this node, on an Intel i5 8250U (times are approximate):
| Before | After | Speedup |
| 760 ms | 60 ms | 13x     |

Differential Revision: https://developer.blender.org/D14233
2022-03-03 11:55:31 -05:00
908ac7dce2 Merge branch 'blender-v3.1-release' 2022-03-03 17:47:34 +01:00
769ae5c866 Fix T96139: Cycles doesn't warn if the render is paused
Caused by 6ec83afb1d.

Technically, a regression since 3.0.

Differential Revision: https://developer.blender.org/D14239
2022-03-03 17:21:11 +01:00
d793d18413 BLI: Add functions to IndexRange to mirror Span
Adds functions for special cases of slicing and an `is_empty` method.
2022-03-03 11:14:44 -05:00
e8dc82311d Fix T96145: GPencil eval data not updated correctly
When removing a modifier, changing the layer transform or updating
 the parent of a grease pencil object that has a multi-user datablock
 and animation data, the eval data is not updated properly (after a
 frame change). This can also cause memory leaks.

 The fix makes sure that we free and reset any runtime copy
 (`ob->runtime.gpd_eval`) in `BKE_gpencil_prepare_eval_data`.

 Note: As far as we can tell, `ob->runtime.gpd_orig` is unused and could
 be removed. The assignment in `BKE_gpencil_prepare_eval_data`
 seemed to be unnecessary.

Co-authored-by: @yann-lty

Reviewed By: antoniov

Maniphest Tasks: T96145

Differential Revision: https://developer.blender.org/D14236
2022-03-03 16:01:23 +01:00
6e487228a5 File Browser UI: Allow dragging anywhere in a file preview tile to drag
Previously you'd have to be careful to drag the image itself. Dragging
anywhere else on the tile (e.g. between the preview and the text, or the
text itself) would trigger border select. This often conflicts with user
expectations and causes frustration when trying to work quick, I've seen
many people complain about this.

Note that the "hitbox" for dragging is a bit smaller than the tile, to
not make border select by dragging from in-between the tiles too hard.

Differential Revision: https://developer.blender.org/D14228
2022-03-03 15:17:23 +01:00
544bd0c353 Cleanup: Remove redundant drag image size parameters
Just use the image-buffer size and the already provided scale to
determine the size, not the button size (which would always have to
match the scaled image-buffer size or it would give unexpected results).
2022-03-03 15:04:45 +01:00
1b863041c9 i18n: Fix more potential contextual issues with "Back" UI label.
Add 'ID_ACTION' context to some animation curve interpolation enums.

Related to T95506/T43295.
2022-03-03 14:52:45 +01:00
0f77933031 Merge branch 'blender-v3.1-release' 2022-03-03 13:49:08 +01:00
9c2e385509 Fix Cycles hang in classroom scene with upcomping AMD driver version 22.10
This is a workaround until there is a fix in the HIP compiler or driver.

Differential Revision: https://developer.blender.org/D14232
2022-03-03 13:42:58 +01:00
ffaaa0bcbf UV: Edge selection support
This patch adds edge selection support for UV editing (refer T76545).
Developed as a part of GSoC 2021 project - UV Editor Improvements.

Previously, selections in the UV editor always flushed down to vertices
and this caused multiple issues such as T76343, T78757 and T26676.
This patch fixes that by adding edge selection support for all UV
operators and adding support for flushing selections between vertices
and edges. Updating UV select modes is now done using a separate
operator, which also handles select mode flushing and undo for UV
select modes. Drawing edges (in UV edge mode) is also updated to match
the edit-mesh display in the 3D viewport.

Notes on technical changes made with this patch:
* MLOOPUV_EDGESEL flag is restored (was removed in rB9fa29fe7652a).
* Support for flushing selection between vertices and edges.
* Restored the BMLoopUV.select_edge boolean in the Python API.
* New operator to update UV select modes and flushing.
* UV select mode is now part of editmesh undo.

TODOs added with this patch:
* Edge support for shortest path operator (currently uses vertex path logic).
* Change default theme color instead of reducing contrast with edge-select.
* Proper UV element selections for Reveal Hidden operator.

Reviewed By: campbellbarton

Differential Revision: https://developer.blender.org/D12028
2022-03-03 17:59:09 +05:30
76879e3702 Outliner: Display respective data-block icon in library overrides mode
Just showing the library override icon for every item doesn't add much
information, it's just redundant. Displaying the data-block type icon on
the other hand can be useful.

Differential Revision: https://developer.blender.org/D14208
2022-03-03 13:18:23 +01:00
9b12889a1a Fix T96140: Crash on color button drag & drop
Use-after-free in context store, which wasn't cleared correctly after
setting and querying.
2022-03-03 12:51:44 +01:00
2d24ba0210 VSE: Allow to create scene in strip properties
This patch adds a button in the scene to add a new one, but this does not change to the new created scene because this breaks the storyboarding workflow.

This is a common request for Storyboarding artists.

Reviewed By: mendio, brecht, ISS

Differential Revision: https://developer.blender.org/D14148
2022-03-03 12:37:48 +01:00
ce0d4ea41c Merge branch 'blender-v3.1-release' 2022-03-03 20:47:07 +11:00
d961adb866 Fix T96135: Mesh coordinates are set to the last edited shape-key
When exiting edit-mode set the vertex coordinates to the basis-shape when editing non-basis keys.

Regression in bfdbc78466.

Reviewed By: sergey

Ref D14234
2022-03-03 20:42:30 +11:00
d66b047ca3 WM: use pass-through for cursor placement operator
This is needed since 4d0f846b93
however change in the operator instead of the event handler is correct,
as accepting a press event should suppress drag events unless
the pass-through flag is set.

This is how select & tweak already works.
2022-03-03 20:35:14 +11:00
ec09ded792 Fix missing i18n context variable in UI py script.
Mistake in own rBdb3f5ae48ac, thanks to Ethan-Hall (@Ethan1080) for the
heads up.
2022-03-03 08:57:06 +01:00
a8df292264 Cleanup: comments in wm_event_system.c 2022-03-03 16:45:40 +11:00
4d0f846b93 Event System: use more thoroughly tested logic for click-drag events
No functional changes, largely restoring old logic & removing the need
for workarounds.

Reverts:
- 13b6cec039.
- aa71414dfc (partially).
2022-03-03 16:07:18 +11:00
9d529407da UI: only wrap cursor motion horizontally when dragging markers
It's not useful to wrap vertical motion when dragging markers.
It was too easy to accidentally wrap the cursor to the top of a region,
as markers need to be dragged from the bottom edge of the region.
2022-03-03 15:48:41 +11:00
d764448f73 Cleanup: use doxygen sections for anim_markers.c 2022-03-03 15:46:26 +11:00
08da699faa Cleanup: rename misleading variable for marker selection cycling
"marker_selected" was the marker after the selected marker
and is used for cycling the selection.
2022-03-03 15:46:15 +11:00
61c288cee5 Fix timeline marker click-drag arbitrary deselection
The logic to cycle selected markers wasn't cycling back to the beginning
of the list.

The marker after the selected marker at the cursor frame was also used
to check if a selection existed, causing dragging to transform all
selected markers to de-select all when when dragging the last marker.
2022-03-03 15:25:02 +11:00
ef431a8705 Cleanup: remove references to key-map modifier values denoting order
This feature was never exposed to users.
2022-03-03 13:57:44 +11:00
3c175caaa3 Cleanup: Rename set handle type node internally to match UI
I've had trouble finding this node a few times now,
it's simpler if the file name matches the name in the UI.
2022-03-02 17:58:17 -05:00
ddf956fb58 Curves: Port set resolution node to the new data-block
The node unnecessarily converted to the old data structure to check if
there were any poly splines. Instead, that warning is just removed,
because the node now still sets resolution values in that case, they
just aren't used (before the values weren't set at all). Either way, it
wasn't clear that looping though all of the curve types was worth
the performance cost here.
2022-03-02 17:50:25 -05:00
2600806c2e Fix: BLI math clamp doesn't work
Return type was wrong, output of std::clamp wasn't used.
2022-03-02 17:09:17 -05:00
ecba8c1243 Fix mistake in seeking cleanup
In `ffmpeg_read_video_frame` fix assignment used as truth value.
In `ffmpeg_seek_recover_stream_position` loop while return value is
greater or equal to 0.
2022-03-02 22:25:43 +01:00
f531dff9b3 Cleanup: Use rectangle for file browser tile drawing
Passing around coordinates for drawing can be quite confusing, it's
often not clear what they represent and where they are currently.
Instead pass around the tile rectangle for drawing and let all code draw
based on that, it's way more clear that way.

Changes shouldn't be user visible.
2022-03-02 19:25:18 +01:00
Nikhil Shringarpurey
721b705499 UI: Comments Misspellings of Vertex/Vertices
Correct misspellings in code comments of "vertex" and "vertices".

See D13932 for more details.

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

Reviewed by Harley Acheson
2022-03-02 10:05:15 -08:00
ca0b728529 Fix T96101: "Remove" button failure on Grease Pencil layer's relation to bone
As the channel was not found, the relation data was not updated.

Now, if the bone is removed, the relation is set.
2022-03-02 17:48:35 +01:00
34267a868a Merge branch 'blender-v3.1-release'
and resolve merge error (version string).
2022-03-02 17:35:09 +01:00
9789a6c6d9 Search: take word order into account in string search
Differential Revision: https://developer.blender.org/D14223
2022-03-02 17:25:39 +01:00
8506f3d9fe Blender 3.1 bcon4 - change release cycle to release candidate
This is still a rolling release candidate with new builds every day
as a preparation to the final release.
2022-03-02 17:17:38 +01:00
ac45540a34 Curves: add brush to add curves on surface
This adds a prototype for the first brush that can add new curves by
painting on a surface. Note that this can only be used when the curves
object has a surface object set in the properties panel.

The brush can take minimum distance into account. This allows
distributing curves with a somewhat consistent density.

Differential Revision: https://developer.blender.org/D14207
2022-03-02 17:15:44 +01:00
037e1ad140 Merge branch 'blender-v3.1-release' 2022-03-02 17:13:57 +01:00
2fb31f34af Fix T95692: incorrect interpolated children particle hair
Differential Revision: https://developer.blender.org/D14227
2022-03-02 17:12:56 +01:00
d86f80f42a Merge branch 'blender-v3.1-release' 2022-03-02 10:55:21 -05:00
216a215ba5 Fix T93573: Remove outline from instances in edit mode
This commit removes the outline from instances generated from an object
when in edit mode. This takes the change in aa13c4b386 a bit further,
with the idea that instance outlines are more like regular outlines.

Because evaluated object data that doesn't match the original object
type is treated as an instance internally, this fixes the way evaluated
meshes for curves objects have an outline, for example.

See the differential revision for a visual comparison.

Differential Revision: https://developer.blender.org/D14226
2022-03-02 10:49:48 -05:00
7935d3668a Fix T95479: geometry nodes crash with cage display
Differential Revision: https://developer.blender.org/D14225
2022-03-02 16:10:42 +01:00
Ethan Hall
1e1d1f15e8 UI: Enable the outliner to use the correct icon for each curve subtype
This patch enables enables the outliner to use the correct icon for each
of the curve subtypes (Curve/Surface/Font).

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

Reviewed by: Julian Eisel
2022-03-02 15:52:17 +01:00
13b6cec039 Fix/Workaround T96120: Crash dropping from the file browser
Since removal of tweak events 4986f71848,
box-select is activating while dragging files.

As far as I can tell this used to work because of differences
int the order tweak / click-drag events are handled.

Apply a workaround since dragging files doesn't prevent other parts
of the UI from activated (it's possible to open menus for e.g),
this is something we will likely want to limit which would resolve
this bug too.
2022-03-03 01:36:14 +11:00
3a0df7d37b Merge remote-tracking branch 'origin/blender-v3.1-release' 2022-03-02 15:22:19 +01:00
6883c47bb5 Fix T94729: GPU subdivision does not support meshes without polygons
There are two issues revealed in the bug report:
- the GPU subdivision does not support meshes with only loose geometry
- the loose geometry is not subdivided

For the first case, checks are added to ensure we still fill the
buffers with loose geometry even if no polygons are present.

For the second case, this adds
`BKE_subdiv_mesh_interpolate_position_on_edge` which encapsulates the
loose vertex interpolation mechanism previously found in
`subdiv_mesh_vertex_of_loose_edge`.

The subdivided loose geometry is stored in a new specific data structure
`DRWSubdivLooseGeom` so as to not pollute `MeshExtractLooseGeom`. These
structures store the corresponding coarse element data, which will be
used for filling GPU buffers appropriately.

Differential Revision: https://developer.blender.org/D14171
2022-03-02 15:19:55 +01:00
47396ea81e Fix T96123: Crash when click-dragging across the visibility icons
Partially revert aa71414dfc

This attempted have the click-drag event compatible with old tweak
events, but needs to be re-thought since it caused events to be handled
in unexpected situations.
2022-03-03 01:11:17 +11:00
4a95c3466f Fix T96085: repeated evaluation of geometry nodes when nothing changed
Differential Revision: https://developer.blender.org/D14216
2022-03-02 14:12:08 +01:00
011fca7f76 temp-vertex-paint: Update a couple of comments 2022-02-25 14:36:20 -08:00
eceda09a3b temp-vertex-paint: finish C++ port of vertex paint
* Ported smudge and average brushes.
* The attribute domain is now passed via
  template argument instead of a "bool is_verts."
* VPaintData (which is internal to paint_vertex.cc)
  is now a template.
2022-02-25 14:10:32 -08:00
287358c269 temp-vertex-paint: Use sculpt undo for vertex paint 2022-02-24 23:23:10 -08:00
9a610c5197 temp-vertex-paint: Add support for vertex domain
for draw brush and port blur
		   brush to new system.
2022-02-24 22:45:20 -08:00
0903676871 temp-vertex-paint: Port paint_verteX_color_utils.c
to C++ templates.

* Ported all the color blending functions in
  paint_vertex_color_utils.c to c++ templates
  (I wrote a couple of internal type traits
  helper classes for this).
* Added missing color blending functions
* Replaced FloatColor and ByteColor with version from
  BLI_color.hh.

I thought about going with IMB_blend_color_float/byte;
unfortunately those are not interchangabe (the float
version assumes premultiplied alpha while the bytes
version does not)).  Meanwhile the bytes version is not
quite compatible with vertex paint's API, which uses a seperate
blending factor from the alpha.

I ended up simply porting vertex paint's existing blending
code to generic C++ templates.
2022-02-24 21:36:31 -08:00
246d547972 Merge branch 'temp-sculpt-colors' into temp-vertex-paint 2022-02-24 17:34:38 -08:00
488ebef44b Merge branch 'master' into temp-sculpt-colors 2022-02-24 17:34:17 -08:00
2e146df515 temp-vertex-paint: Vertex paint branch
I have successully ported vertex paint's
draw brush to C++ thanks to the magic
of templates.  It's amazing how easy
this is.
2022-02-22 23:01:08 -08:00
eddc806ab9 temp-sculpt-colors: compile fixes 2022-02-22 15:29:07 -08:00
08d04e4ed6 temp-sculpt-colors: Fix mask by color and
a few other minor bugs
2022-02-21 22:43:14 -08:00
ad99638844 temp-sculpt-colors: loop colors undo now works
* PBVHNode now has entries for the unique loops assigned
  to the node.  It works the same as for verts.  Note
  unlike verts loops are not assigned to nodes at pbvh
  build time to save RAM; code that wishes to use them
  must call BKE_pbvh_ensure_node_loops in the main
  thread.

* Sculpt color attribute wrangling now happens inside
  the PBVH api and in C++.  This saved an enourmous
  amount of duplicate (and thus highly error prone) code.

* SCULPT_vertex_color_get/set now forwards to
  new BKE_pbvh_vertex_color_get/set methods.
2022-02-21 22:21:17 -08:00
8c3be51118 temp-sculpt-colors: Store loop colors in undo
* Added BKE_pbvh_vertex_color_get/set methods,
  work same as SCULPT_vertex_color_get/set.
  SCULPT_vertex_color_get/set will forward to these
  (but not in this commit).
* PBVH stores active color attribute again.
2022-02-21 10:36:59 -08:00
5cbf05a637 Merge branch 'master' into temp-sculpt-colors 2022-02-21 07:48:43 -08:00
13f8444673 temp-sculpt-colors: Fix GPU memory leak where vertex
colors weren't always being released following switch
to PBVH drawing
2022-02-21 07:46:25 -08:00
c12313cfa8 temp-sculpt-colors: use new standard primary/secondary
ui layout
2022-02-16 07:23:32 -08:00
0704846250 temp-sculpt-colors: fix crash with color filter 2022-02-16 07:15:47 -08:00
0f96739b31 temp-sculpt-colors: fix color filter 2022-02-15 10:43:26 -08:00
47d222e4f3 temp-sculpt-colors: Fix bug in sculpt undo
SCULPT_undo_push_end was not being called, which
meant the active color attribute ref that's stored
at the end of each sculpt undo step wasn't set.

Added code to ensure this is always set, and also
added SCULPT_undo_push_end to the offending code.

Also renamed SculptUndoStep.active_attr_xxx to active_color_xxx.
2022-02-15 10:16:23 -08:00
664bf9fecb temp-sculpt-colors: Rename vertex colors panel to color attributes 2022-02-15 09:50:54 -08:00
626624ca79 Fix incomplete implementation of
fallback code for active/render color
attributes when the relevent
active flags do not exist.

Also bumped the subversion number.
2022-02-15 09:47:24 -08:00
69f483650c Merge branch 'master' into temp-sculpt-colors 2022-02-15 02:56:58 -08:00
6ca2f388e1 temp-sculpt-colors: more changes
Also, part of the wm_toolsystem bugfix was
missing, include it.
2022-02-14 15:54:48 -08:00
cceb8dd3ed Merge branch 'master' into temp-sculpt-colors 2022-02-14 15:21:40 -08:00
94ef9f09c9 temp-sculpt-colors: Requested patch changes 2022-02-14 15:20:20 -08:00
0bbdd6301a temp-sculpt-colors: run make format 2022-02-12 08:11:58 -08:00
61393ea09b temp-sculpt-colors: BKE_id_attribute_new no longer
takes a namespace mask argument.
2022-02-12 08:01:58 -08:00
0eb7bb98ec temp-sculpt-colors: fix bug in last commit
Got ordering of color attributes wrong
in one place.
2022-02-12 07:51:34 -08:00
17df30e8ea temp-sculpt-colors: make requested changes
* Active/render color references are now
  stored in customdata flags
* Everything seems to work except for gpu
  subsurf in editmode.  Need to track that
  one down still.
2022-02-12 07:27:54 -08:00
f09dbc54a5 Merge branch 'master' into temp-sculpt-colors 2022-02-12 02:32:00 -08:00
89662fa778 temp-sculpt-colors: don't include this particular bug
fix in the patch
2022-01-29 12:59:38 -08:00
80ee3c83d4 temp-sculpt-colors: pull in icon from master 2022-01-29 12:55:58 -08:00
e0c35f0ac0 Fix merge bugs 2022-01-29 12:54:21 -08:00
43bca12ec4 Merge branch 'master' into temp-sculpt-colors 2022-01-28 17:57:42 -08:00
6a8c9ec763 temp-sculpt-colors: Make requested changes 2022-01-28 17:47:00 -08:00
977031c9d0 temp-sculpt-colors: Make requested changes 2022-01-14 23:09:33 -08:00
f94295e46a Merge branch 'master' into temp-sculpt-colors 2022-01-14 22:13:14 -08:00
36b672cb63 temp-sculpt-colors: fix color of sculpt
paint smear icon
2022-01-12 08:47:59 -08:00
973c6a347b temp-sculpt-colors: update sculpt paint brushes
New icons for mask by color and color filter.
Provided by Julien Kaspar.
2022-01-12 08:44:05 -08:00
c1942c9b5e temp-sculpt-colors: make requested changes 2022-01-12 02:39:03 -08:00
fe24c6bb8b Cleanup: make format 2022-01-12 11:32:25 +01:00
f3fea47f6c Merge remote-tracking branch 'origin/master' into temp-sculpt-colors 2022-01-12 11:31:20 +01:00
9f9123e7c9 Merge branch 'master' into temp-sculpt-colors 2022-01-12 01:51:15 -08:00
e8f1ce29cd temp-sculpt-colors: fix bug in get_vcol_refs 2022-01-12 01:16:13 -08:00
def061207e Fix merge error 2022-01-07 10:12:12 -08:00
6437be3a1b Merge branch 'master' into temp-sculpt-colors 2022-01-07 07:57:34 -08:00
3067efe54e temp-sculpt-colors: Various fixes
* Fixed byte color layers not rendering in EEVEE
* Fixed byte color layers not showing up in ui list
  for vertex color shading node.
* Rewrote vcol extractor for non-BMesh case to be
  less messy.
2022-01-07 07:51:59 -08:00
9970263b66 temp-sculpt-colors: bring back color picker panel
for sculpt paint brush
2022-01-06 02:48:25 -08:00
8f256b68ce temp-sculpt-colors: fix another build error 2022-01-05 05:33:14 -08:00
32ccf68558 temp-sculpt-colors: fix build error 2022-01-05 05:30:22 -08:00
fa40124d2e temp-sculpt-colors: Automatically switch to vertex
shading mode when using paint
		    brushes.

Also fixed vcol layer auto-creation failing to
set active color reference properlty.
2022-01-05 04:45:46 -08:00
4a90199e22 Merge branch 'master' into temp-sculpt-colors 2022-01-04 04:12:28 -08:00
a4b55c207f Remove save/load to corners from py scripts 2021-12-20 10:43:38 -05:00
a1cc0d3af3 temp-sculpt-colors: fix buf in next_color_attr 2021-11-17 04:18:49 -08:00
6e069b7070 temp-sculpt-colors: fix icons and a couple of bugs 2021-11-17 02:32:47 -08:00
3c4b9a4bfb temp-sculpt-colors: Vertex color list now has active reference 2021-11-17 01:28:21 -08:00
f5a7262444 Merge branch 'master' into temp-sculpt-colors 2021-11-16 22:08:27 -08:00
6c0da7cc81 Merge branch 'master' into temp-sculpt-colors 2021-11-08 13:17:16 -08:00
86fe67d6ed Fix python error 2021-11-03 16:42:04 -07:00
923547add3 temp-sculpt-colors: fix out of bounds error 2021-11-03 16:19:06 -07:00
65ef507b8b tempt-sculpt-colors: editmode fix 2021-11-03 16:01:06 -07:00
a8fa8bf364 temp-sculpt-colors: implement patch review items 2021-11-03 15:06:27 -07:00
3efad90211 Merge branch 'master' into temp-sculpt-colors 2021-11-03 14:39:07 -07:00
6a84d61c8b Update icons 2021-11-03 14:37:49 -07:00
d42acadba5 temp-sculpt-colors: vcol extractor rewrite
Draw cache system now properly uploads all three
vcol types to the gpu.
2021-11-03 14:30:40 -07:00
1a5ea3c8b3 Merge branch 'master' into temp-sculpt-colors 2021-11-03 13:03:43 -07:00
1dcc741f43 temp-sculpt-colors: commit patch 2021-11-03 12:15:13 -07:00
1536 changed files with 53883 additions and 32697 deletions

View File

@@ -256,7 +256,7 @@ endif()
if(UNIX AND NOT APPLE)
option(WITH_SYSTEM_GLEW "Use GLEW OpenGL wrapper library provided by the operating system" OFF)
option(WITH_SYSTEM_GLEW "Use GLEW OpenGL wrapper library provided by the operating system" OFF)
option(WITH_SYSTEM_GLES "Use OpenGL ES library provided by the operating system" ON)
option(WITH_SYSTEM_FREETYPE "Use the freetype library provided by the operating system" OFF)
else()
# not an option for other OS's
@@ -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()
@@ -502,7 +505,7 @@ else()
set(WITH_EXPERIMENTAL_FEATURES OFF)
endif()
# Unit testsing
# Unit testing
option(WITH_GTESTS "Enable GTest unit testing" OFF)
option(WITH_OPENGL_RENDER_TESTS "Enable OpenGL render related unit testing (Experimental)" OFF)
option(WITH_OPENGL_DRAW_TESTS "Enable OpenGL UI drawing related unit testing (Experimental)" OFF)
@@ -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)
@@ -1668,6 +1695,8 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_DUPLICATE_ENUM -Wno-duplicate-enum)
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNDEF -Wno-undef)
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_MISSING_NORETURN -Wno-missing-noreturn)
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_BUT_SET_VARIABLE -Wno-unused-but-set-variable)
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_DEPRECATED_DECLARATIONS -Wno-deprecated-declarations)
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_PARAMETER -Wno-unused-parameter)
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_PRIVATE_FIELD -Wno-unused-private-field)
@@ -1882,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)
@@ -1946,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

@@ -32,7 +32,7 @@ Other Convenience Targets
* config: Run cmake configuration tool to set build options.
* deps: Build library dependencies (intended only for platform maintainers).
The existance of locally build dependencies overrides the pre-built dependencies from subversion.
The existence of locally build dependencies overrides the pre-built dependencies from subversion.
These must be manually removed from '../lib/' to go back to using the pre-compiled libraries.
Project Files

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

@@ -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
@@ -858,7 +866,7 @@ endif()
# If atomic operations are possible without libatomic then linker flags are left as-is.
function(CONFIGURE_ATOMIC_LIB_IF_NEEDED)
# Source which is used to enforce situation when software emulation of atomics is required.
# Assume that using 64bit integer gives a definitive asnwer (as in, if 64bit atomic operations
# Assume that using 64bit integer gives a definitive answer (as in, if 64bit atomic operations
# are possible using assembly/intrinsics 8, 16, and 32 bit operations will also be possible.
set(_source
"#include <atomic>

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)
windows_find_package(FFmpeg)
if(NOT FFMPEG_FOUND)
warn_hardcoded_paths(ffmpeg)
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)
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)
@@ -624,21 +635,23 @@ 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_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)
endif()
endif()
if(WITH_SDL)
@@ -659,12 +672,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()

View File

@@ -5,7 +5,7 @@ for %%X in (ctest.exe) do (set CTEST=%%~$PATH:X)
for %%X in (git.exe) do (set GIT=%%~$PATH:X)
REM For python, default on 39 but if that does not exist also check
REM the 310,311 and 312 folders to see if those are there, it checks
REM this far ahead to ensure good lib folder compatiblity in the future.
REM this far ahead to ensure good lib folder compatibility in the future.
set PYTHON=%BLENDER_DIR%\..\lib\win64_vc15\python\39\bin\python.exe
if EXIST %PYTHON% (
goto detect_python_done

View File

@@ -0,0 +1,502 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

View File

@@ -5,5 +5,6 @@ BSD-2-Clause BSD-2-Clause-license.txt https://spdx.org/licenses/BS
BSD-3-Clause BSD-3-Clause-license.txt https://spdx.org/licenses/BSD-3-Clause.html
GPL-2.0-or-later GPL-license.txt https://spdx.org/licenses/GPL-2.0-or-later.html
GPL-3.0-or-later GPL3-license.txt https://spdx.org/licenses/GPL-3.0-or-later.html
LGPL-2.1-or-later LGPL2.1-license.txt https://spdx.org/licenses/LGPL-2.1-or-later.html
MIT MIT-license.txt https://spdx.org/licenses/MIT.html
Zlib Zlib-license.txt https://spdx.org/licenses/Zlib.html

View File

@@ -16,7 +16,6 @@ and <output-filename> is where to write the generated man page.
import argparse
import os
import subprocess
import sys
import time
from typing import (

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

@@ -423,6 +423,7 @@ TEST(atomic, atomic_fetch_and_and_uint32)
/** \} */
/* -------------------------------------------------------------------- */
/** \name 32 bit signed int atomics
* \{ */
@@ -559,6 +560,7 @@ TEST(atomic, atomic_fetch_and_and_int32)
/** \} */
/* -------------------------------------------------------------------- */
/** \name 16 bit signed int atomics
* \{ */
@@ -592,6 +594,9 @@ TEST(atomic, atomic_fetch_and_and_int16)
}
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name 8 bit unsigned int atomics
* \{ */
@@ -638,6 +643,7 @@ TEST(atomic, atomic_fetch_and_and_int8)
/** \} */
/* -------------------------------------------------------------------- */
/** \name char aliases
* \{ */
@@ -661,6 +667,7 @@ TEST(atomic, atomic_fetch_and_and_char)
/** \} */
/* -------------------------------------------------------------------- */
/** \name size_t aliases
* \{ */
@@ -772,6 +779,7 @@ TEST(atomic, atomic_fetch_and_update_max_z)
/** \} */
/* -------------------------------------------------------------------- */
/** \name unsigned int aliases
* \{ */
@@ -867,6 +875,7 @@ TEST(atomic, atomic_cas_u)
/** \} */
/* -------------------------------------------------------------------- */
/** \name pointer aliases
* \{ */
@@ -885,6 +894,7 @@ TEST(atomic, atomic_cas_ptr)
/** \} */
/* -------------------------------------------------------------------- */
/** \name floating point atomics
* \{ */

View File

@@ -2,8 +2,12 @@
# Copyright 2011-2022 Blender Foundation
# Standalone or with Blender
if(NOT WITH_BLENDER AND WITH_CYCLES_STANDALONE)
set(CYCLES_INSTALL_PATH ${CMAKE_INSTALL_PREFIX})
if(NOT WITH_BLENDER)
if(WITH_CYCLES_STANDALONE OR NOT WITH_CYCLES_HYDRA_RENDER_DELEGATE)
set(CYCLES_INSTALL_PATH ${CMAKE_INSTALL_PREFIX})
else()
set(CYCLES_INSTALL_PATH ${CMAKE_INSTALL_PREFIX}/hdCycles/resources)
endif()
else()
set(WITH_CYCLES_BLENDER ON)
# WINDOWS_PYTHON_DEBUG needs to write into the user addons folder since it will
@@ -335,6 +339,11 @@ 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_CUDA_BINARIES AND (NOT WITH_CYCLES_CUBIN_COMPILER))
if(MSVC)
set(MAX_MSVC 1800)
@@ -395,6 +404,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

@@ -216,7 +216,6 @@ enum_direct_light_sampling_type = (
)
def update_render_passes(self, context):
scene = context.scene
view_layer = context.view_layer
view_layer.update_render_passes()
@@ -349,8 +348,8 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
scrambling_distance: FloatProperty(
name="Scrambling Distance",
default=1.0,
min=0.0, max=1.0,
description="Reduce randomization between pixels to improve GPU rendering performance, at the cost of possible rendering artifacts if set too low. Only works when not using adaptive sampling",
min=0.0, soft_max=1.0,
description="Reduce randomization between pixels to improve GPU rendering performance, at the cost of possible rendering artifacts if set too low",
)
preview_scrambling_distance: BoolProperty(
name="Scrambling Distance viewport",
@@ -361,7 +360,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
auto_scrambling_distance: BoolProperty(
name="Automatic Scrambling Distance",
default=False,
description="Automatically reduce the randomization between pixels to improve GPU rendering performance, at the cost of possible rendering artifacts. Only works when not using adaptive sampling",
description="Automatically reduce the randomization between pixels to improve GPU rendering performance, at the cost of possible rendering artifacts",
)
use_layer_samples: EnumProperty(
@@ -1353,7 +1352,7 @@ class CyclesPreferences(bpy.types.AddonPreferences):
items=CyclesPreferences.get_device_types,
)
devices: bpy.props.CollectionProperty(type=CyclesDeviceSettings)
devices: CollectionProperty(type=CyclesDeviceSettings)
peer_memory: BoolProperty(
name="Distribute memory across devices",
@@ -1481,7 +1480,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

@@ -11,6 +11,7 @@ from bl_ui.utils import PresetPanel
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
class CyclesPresetPanel(PresetPanel, Panel):
@@ -288,11 +289,8 @@ class CYCLES_RENDER_PT_sampling_advanced(CyclesButtonsPanel, Panel):
layout.separator()
heading = layout.column(align=True, heading="Scrambling Distance")
heading.active = not (cscene.use_adaptive_sampling and cscene.use_preview_adaptive_sampling)
heading.prop(cscene, "auto_scrambling_distance", text="Automatic")
sub = heading.row()
sub.active = not cscene.use_preview_adaptive_sampling
sub.prop(cscene, "preview_scrambling_distance", text="Viewport")
heading.prop(cscene, "preview_scrambling_distance", text="Viewport")
heading.prop(cscene, "scrambling_distance", text="Multiplier")
layout.separator()
@@ -355,6 +353,13 @@ class CYCLES_RENDER_PT_hair(CyclesButtonsPanel, Panel):
if ccscene.shape == 'RIBBONS':
col.prop(ccscene, "subdivisions", text="Curve Subdivisions")
class CYCLES_RENDER_PT_hair_viewport_display(CyclesButtonsPanel, Panel):
bl_label = "Viewport Display"
bl_parent_id = "CYCLES_RENDER_PT_hair"
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
draw_hair_settings(self, context)
class CYCLES_RENDER_PT_volumes(CyclesButtonsPanel, Panel):
bl_label = "Volumes"
@@ -1023,7 +1028,7 @@ class CYCLES_OBJECT_PT_motion_blur(CyclesButtonsPanel, Panel):
def poll(cls, context):
ob = context.object
if CyclesButtonsPanel.poll(context) and ob:
if ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META', 'CAMERA', 'HAIR', 'POINTCLOUD'}:
if ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META', 'CAMERA', 'CURVES', 'POINTCLOUD'}:
return True
if ob.instance_type == 'COLLECTION' and ob.instance_collection:
return True
@@ -1062,7 +1067,7 @@ class CYCLES_OBJECT_PT_motion_blur(CyclesButtonsPanel, Panel):
def has_geometry_visibility(ob):
return ob and ((ob.type in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'LIGHT', 'VOLUME', 'POINTCLOUD', 'HAIR'}) or
return ob and ((ob.type in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'LIGHT', 'VOLUME', 'POINTCLOUD', 'CURVES'}) or
(ob.instance_type == 'COLLECTION' and ob.instance_collection))
@@ -2153,6 +2158,7 @@ classes = (
CYCLES_RENDER_PT_volumes,
CYCLES_RENDER_PT_subdivision,
CYCLES_RENDER_PT_hair,
CYCLES_RENDER_PT_hair_viewport_display,
CYCLES_RENDER_PT_simplify,
CYCLES_RENDER_PT_simplify_viewport,
CYCLES_RENDER_PT_simplify_render,

View File

@@ -5,7 +5,6 @@
from __future__ import annotations
import bpy
import math
from bpy.app.handlers import persistent

View File

@@ -319,7 +319,9 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
(object->get_geometry() && object->get_geometry()->is_modified())) {
object->name = b_ob.name().c_str();
object->set_pass_id(b_ob.pass_index());
object->set_color(get_float3(b_ob.color()));
const BL::Array<float, 4> object_color = b_ob.color();
object->set_color(get_float3(object_color));
object->set_alpha(object_color[3]);
object->set_tfm(tfm);
/* dupli texture coordinates and random_id */
@@ -420,7 +422,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)

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)) {

View File

@@ -346,31 +346,48 @@ void BlenderSync::sync_integrator(BL::ViewLayer &b_view_layer, bool background)
cscene, "sampling_pattern", SAMPLING_NUM_PATTERNS, SAMPLING_PATTERN_SOBOL);
integrator->set_sampling_pattern(sampling_pattern);
int samples = 1;
bool use_adaptive_sampling = false;
if (preview) {
samples = get_int(cscene, "preview_samples");
use_adaptive_sampling = RNA_boolean_get(&cscene, "use_preview_adaptive_sampling");
integrator->set_use_adaptive_sampling(use_adaptive_sampling);
integrator->set_adaptive_threshold(get_float(cscene, "preview_adaptive_threshold"));
integrator->set_adaptive_min_samples(get_int(cscene, "preview_adaptive_min_samples"));
}
else {
samples = get_int(cscene, "samples");
use_adaptive_sampling = RNA_boolean_get(&cscene, "use_adaptive_sampling");
integrator->set_use_adaptive_sampling(use_adaptive_sampling);
integrator->set_adaptive_threshold(get_float(cscene, "adaptive_threshold"));
integrator->set_adaptive_min_samples(get_int(cscene, "adaptive_min_samples"));
}
int samples = get_int(cscene, "samples");
float scrambling_distance = get_float(cscene, "scrambling_distance");
bool auto_scrambling_distance = get_boolean(cscene, "auto_scrambling_distance");
if (auto_scrambling_distance) {
if (samples == 0) {
/* If samples is 0, then viewport rendering is set to render infinitely. In that case we
* override the samples value with 4096 so the Automatic Scrambling Distance algorithm
* picks a Scrambling Distance value with a good balance of performance and correlation
* artifacts when rendering to high sample counts. */
samples = 4096;
}
if (use_adaptive_sampling) {
/* If Adaptive Sampling is enabled, use "min_samples" in the Automatic Scrambling Distance
* algorithm to avoid artifacts common with Adaptive Sampling + Scrambling Distance. */
const AdaptiveSampling adaptive_sampling = integrator->get_adaptive_sampling();
samples = min(samples, adaptive_sampling.min_samples);
}
scrambling_distance *= 4.0f / sqrtf(samples);
}
/* only use scrambling distance in the viewport if user wants to and disable with AS */
/* Only use scrambling distance in the viewport if user wants to. */
bool preview_scrambling_distance = get_boolean(cscene, "preview_scrambling_distance");
if ((preview && !preview_scrambling_distance) || use_adaptive_sampling)
if (preview && !preview_scrambling_distance) {
scrambling_distance = 1.0f;
}
if (scrambling_distance != 1.0f) {
VLOG(3) << "Using scrambling distance: " << scrambling_distance;

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

@@ -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.

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

@@ -33,6 +33,191 @@
CCL_NAMESPACE_BEGIN
// A minimal copy of functionality `optix_denoiser_tiling.h` which allows to fix integer overflow
// issues without bumping SDK or driver requirement.
//
// The original code is Copyright NVIDIA Corporation, BSD-3-Clause.
namespace {
static OptixResult optixUtilDenoiserSplitImage(const OptixImage2D &input,
const OptixImage2D &output,
unsigned int overlapWindowSizeInPixels,
unsigned int tileWidth,
unsigned int tileHeight,
std::vector<OptixUtilDenoiserImageTile> &tiles)
{
if (tileWidth == 0 || tileHeight == 0)
return OPTIX_ERROR_INVALID_VALUE;
unsigned int inPixelStride = optixUtilGetPixelStride(input);
unsigned int outPixelStride = optixUtilGetPixelStride(output);
int inp_w = std::min(tileWidth + 2 * overlapWindowSizeInPixels, input.width);
int inp_h = std::min(tileHeight + 2 * overlapWindowSizeInPixels, input.height);
int inp_y = 0, copied_y = 0;
do {
int inputOffsetY = inp_y == 0 ? 0 :
std::max((int)overlapWindowSizeInPixels,
inp_h - ((int)input.height - inp_y));
int copy_y = inp_y == 0 ? std::min(input.height, tileHeight + overlapWindowSizeInPixels) :
std::min(tileHeight, input.height - copied_y);
int inp_x = 0, copied_x = 0;
do {
int inputOffsetX = inp_x == 0 ? 0 :
std::max((int)overlapWindowSizeInPixels,
inp_w - ((int)input.width - inp_x));
int copy_x = inp_x == 0 ? std::min(input.width, tileWidth + overlapWindowSizeInPixels) :
std::min(tileWidth, input.width - copied_x);
OptixUtilDenoiserImageTile tile;
tile.input.data = input.data + (size_t)(inp_y - inputOffsetY) * input.rowStrideInBytes +
+(size_t)(inp_x - inputOffsetX) * inPixelStride;
tile.input.width = inp_w;
tile.input.height = inp_h;
tile.input.rowStrideInBytes = input.rowStrideInBytes;
tile.input.pixelStrideInBytes = input.pixelStrideInBytes;
tile.input.format = input.format;
tile.output.data = output.data + (size_t)inp_y * output.rowStrideInBytes +
(size_t)inp_x * outPixelStride;
tile.output.width = copy_x;
tile.output.height = copy_y;
tile.output.rowStrideInBytes = output.rowStrideInBytes;
tile.output.pixelStrideInBytes = output.pixelStrideInBytes;
tile.output.format = output.format;
tile.inputOffsetX = inputOffsetX;
tile.inputOffsetY = inputOffsetY;
tiles.push_back(tile);
inp_x += inp_x == 0 ? tileWidth + overlapWindowSizeInPixels : tileWidth;
copied_x += copy_x;
} while (inp_x < static_cast<int>(input.width));
inp_y += inp_y == 0 ? tileHeight + overlapWindowSizeInPixels : tileHeight;
copied_y += copy_y;
} while (inp_y < static_cast<int>(input.height));
return OPTIX_SUCCESS;
}
static OptixResult optixUtilDenoiserInvokeTiled(OptixDenoiser denoiser,
CUstream stream,
const OptixDenoiserParams *params,
CUdeviceptr denoiserState,
size_t denoiserStateSizeInBytes,
const OptixDenoiserGuideLayer *guideLayer,
const OptixDenoiserLayer *layers,
unsigned int numLayers,
CUdeviceptr scratch,
size_t scratchSizeInBytes,
unsigned int overlapWindowSizeInPixels,
unsigned int tileWidth,
unsigned int tileHeight)
{
if (!guideLayer || !layers)
return OPTIX_ERROR_INVALID_VALUE;
std::vector<std::vector<OptixUtilDenoiserImageTile>> tiles(numLayers);
std::vector<std::vector<OptixUtilDenoiserImageTile>> prevTiles(numLayers);
for (unsigned int l = 0; l < numLayers; l++) {
if (const OptixResult res = ccl::optixUtilDenoiserSplitImage(layers[l].input,
layers[l].output,
overlapWindowSizeInPixels,
tileWidth,
tileHeight,
tiles[l]))
return res;
if (layers[l].previousOutput.data) {
OptixImage2D dummyOutput = layers[l].previousOutput;
if (const OptixResult res = ccl::optixUtilDenoiserSplitImage(layers[l].previousOutput,
dummyOutput,
overlapWindowSizeInPixels,
tileWidth,
tileHeight,
prevTiles[l]))
return res;
}
}
std::vector<OptixUtilDenoiserImageTile> albedoTiles;
if (guideLayer->albedo.data) {
OptixImage2D dummyOutput = guideLayer->albedo;
if (const OptixResult res = ccl::optixUtilDenoiserSplitImage(guideLayer->albedo,
dummyOutput,
overlapWindowSizeInPixels,
tileWidth,
tileHeight,
albedoTiles))
return res;
}
std::vector<OptixUtilDenoiserImageTile> normalTiles;
if (guideLayer->normal.data) {
OptixImage2D dummyOutput = guideLayer->normal;
if (const OptixResult res = ccl::optixUtilDenoiserSplitImage(guideLayer->normal,
dummyOutput,
overlapWindowSizeInPixels,
tileWidth,
tileHeight,
normalTiles))
return res;
}
std::vector<OptixUtilDenoiserImageTile> flowTiles;
if (guideLayer->flow.data) {
OptixImage2D dummyOutput = guideLayer->flow;
if (const OptixResult res = ccl::optixUtilDenoiserSplitImage(guideLayer->flow,
dummyOutput,
overlapWindowSizeInPixels,
tileWidth,
tileHeight,
flowTiles))
return res;
}
for (size_t t = 0; t < tiles[0].size(); t++) {
std::vector<OptixDenoiserLayer> tlayers;
for (unsigned int l = 0; l < numLayers; l++) {
OptixDenoiserLayer layer = {};
layer.input = (tiles[l])[t].input;
layer.output = (tiles[l])[t].output;
if (layers[l].previousOutput.data)
layer.previousOutput = (prevTiles[l])[t].input;
tlayers.push_back(layer);
}
OptixDenoiserGuideLayer gl = {};
if (guideLayer->albedo.data)
gl.albedo = albedoTiles[t].input;
if (guideLayer->normal.data)
gl.normal = normalTiles[t].input;
if (guideLayer->flow.data)
gl.flow = flowTiles[t].input;
if (const OptixResult res = optixDenoiserInvoke(denoiser,
stream,
params,
denoiserState,
denoiserStateSizeInBytes,
&gl,
&tlayers[0],
numLayers,
(tiles[0])[t].inputOffsetX,
(tiles[0])[t].inputOffsetY,
scratch,
scratchSizeInBytes))
return res;
}
return OPTIX_SUCCESS;
}
} // namespace
OptiXDevice::Denoiser::Denoiser(OptiXDevice *device)
: device(device), queue(device), state(device, "__denoiser_state", true)
{
@@ -1075,20 +1260,20 @@ bool OptiXDevice::denoise_run(DenoiseContext &context, const DenoisePass &pass)
/* Finally run denoising. */
OptixDenoiserParams params = {}; /* All parameters are disabled/zero. */
optix_assert(optixUtilDenoiserInvokeTiled(denoiser_.optix_denoiser,
denoiser_.queue.stream(),
&params,
denoiser_.state.device_pointer,
denoiser_.sizes.stateSizeInBytes,
&guide_layers,
&image_layers,
1,
denoiser_.state.device_pointer +
denoiser_.sizes.stateSizeInBytes,
denoiser_.sizes.withOverlapScratchSizeInBytes,
denoiser_.sizes.overlapWindowSizeInPixels,
denoiser_.configured_size.x,
denoiser_.configured_size.y));
optix_assert(ccl::optixUtilDenoiserInvokeTiled(denoiser_.optix_denoiser,
denoiser_.queue.stream(),
&params,
denoiser_.state.device_pointer,
denoiser_.sizes.stateSizeInBytes,
&guide_layers,
&image_layers,
1,
denoiser_.state.device_pointer +
denoiser_.sizes.stateSizeInBytes,
denoiser_.sizes.withOverlapScratchSizeInBytes,
denoiser_.sizes.overlapWindowSizeInPixels,
denoiser_.configured_size.x,
denoiser_.configured_size.y));
return true;
}

View File

@@ -100,7 +100,7 @@ class DeviceQueue {
* based on number of cores and/or available memory. */
virtual int num_concurrent_states(const size_t state_size) const = 0;
/* Number of states which keeps the device occupied with work without loosing performance.
/* Number of states which keeps the device occupied with work without losing performance.
* The renderer will add more work (when available) when number of active paths falls below this
* value. */
virtual int num_concurrent_busy_states() const = 0;

View File

@@ -0,0 +1,174 @@
# 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
PRIVATE
${USD_LIBRARY_DIR}/${PXR_LIB_PREFIX}hd${CMAKE_LINK_LIBRARY_SUFFIX}
${USD_LIBRARY_DIR}/${PXR_LIB_PREFIX}plug${CMAKE_LINK_LIBRARY_SUFFIX}
${USD_LIBRARY_DIR}/${PXR_LIB_PREFIX}tf${CMAKE_LINK_LIBRARY_SUFFIX}
${USD_LIBRARY_DIR}/${PXR_LIB_PREFIX}trace${CMAKE_LINK_LIBRARY_SUFFIX}
${USD_LIBRARY_DIR}/${PXR_LIB_PREFIX}vt${CMAKE_LINK_LIBRARY_SUFFIX}
${USD_LIBRARY_DIR}/${PXR_LIB_PREFIX}work${CMAKE_LINK_LIBRARY_SUFFIX}
${USD_LIBRARY_DIR}/${PXR_LIB_PREFIX}sdf${CMAKE_LINK_LIBRARY_SUFFIX}
${USD_LIBRARY_DIR}/${PXR_LIB_PREFIX}cameraUtil${CMAKE_LINK_LIBRARY_SUFFIX}
${USD_LIBRARY_DIR}/${PXR_LIB_PREFIX}hf${CMAKE_LINK_LIBRARY_SUFFIX}
${USD_LIBRARY_DIR}/${PXR_LIB_PREFIX}pxOsd${CMAKE_LINK_LIBRARY_SUFFIX}
${USD_LIBRARY_DIR}/${PXR_LIB_PREFIX}gf${CMAKE_LINK_LIBRARY_SUFFIX}
${USD_LIBRARY_DIR}/${PXR_LIB_PREFIX}arch${CMAKE_LINK_LIBRARY_SUFFIX}
${USD_LIBRARY_DIR}/${PXR_LIB_PREFIX}hgi${CMAKE_LINK_LIBRARY_SUFFIX}
${USD_LIBRARY_DIR}/${PXR_LIB_PREFIX}glf${CMAKE_LINK_LIBRARY_SUFFIX}
${USD_LIBRARY_DIR}/${PXR_LIB_PREFIX}hdx${CMAKE_LINK_LIBRARY_SUFFIX}
${USD_LIBRARY_DIR}/${PXR_LIB_PREFIX}usdGeom${CMAKE_LINK_LIBRARY_SUFFIX}
cycles_scene
cycles_session
cycles_graph
)
if(USD_PYTHON_LIBRARIES)
target_link_libraries(hdCyclesStatic
PRIVATE
${USD_PYTHON_LIBRARIES}
)
endif()
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
)
target_link_directories(${HdCyclesPluginName}
BEFORE
PRIVATE
${USD_LIBRARY_DIR}
)
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 "..")
set(PLUG_INFO_LIBRARY_PATH "../${HdCyclesPluginName}${CMAKE_SHARED_LIBRARY_SUFFIX}")
set(PLUG_INFO_RESOURCE_PATH "resources")
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,297 @@
/* 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);
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 (*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
}
}
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, UsdGeomTokens->projection);
if (!value.IsEmpty()) {
_data.SetProjection(value.Get<TfToken>() != UsdGeomTokens->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,44 @@
/* 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 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,88 @@
/* 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
// clang-format off
TF_DEFINE_PRIVATE_TOKENS(_tokens,
(fieldName)
);
// clang-format on
#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,589 @@
/* 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
namespace {
// 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);
}
};
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
struct HdCyclesMaterial::NodeDesc {
ShaderNode *node;
const UsdToCyclesMapping *mapping;
};
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,60 @@
/* 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;
}
struct NodeDesc;
private:
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<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

@@ -80,7 +80,8 @@ static bool is_single_supported_device(Device *device, DenoiserType type)
if (!device->info.multi_devices.empty()) {
/* Some configurations will use multi_devices, but keep the type of an individual device.
* This does simplify checks for homogenous setups, but here we really need a single device. */
* This does simplify checks for homogeneous setups, but here we really need a single device.
*/
return false;
}

View File

@@ -466,7 +466,7 @@ void PathTrace::set_denoiser_params(const DenoiseParams &params)
denoiser_ = Denoiser::create(device_, params);
/* Only take into account the "immediate" cancel to have interactive rendering responding to
* navigation as quickly as possible, but allow to run denoiser after user hit Esc button while
* navigation as quickly as possible, but allow to run denoiser after user hit Escape key while
* doing offline rendering. */
denoiser_->is_cancelled_cb = [this]() { return render_cancel_.is_requested; };
}

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

@@ -50,7 +50,6 @@ set(SRC_KERNEL_DEVICE_GPU_HEADERS
device/gpu/kernel.h
device/gpu/parallel_active_index.h
device/gpu/parallel_prefix_sum.h
device/gpu/parallel_reduce.h
device/gpu/parallel_sorted_index.h
device/gpu/work_stealing.h
)

View File

@@ -29,8 +29,8 @@ ccl_device_inline
IntegratorShadowState state,
const uint visibility,
const uint max_hits,
ccl_private uint *num_recorded_hits,
ccl_private float *throughput)
ccl_private uint *r_num_recorded_hits,
ccl_private float *r_throughput)
{
/* todo:
* - likely and unlikely for if() statements
@@ -60,15 +60,18 @@ ccl_device_inline
* recorded hits is exceeded and we no longer need to find hits beyond the max
* distance found. */
float t_max_world = ray->t;
/* Equal to t_max_world when traversing top level BVH, transformed into local
* space when entering instances. */
float t_max_current = t_max_world;
/* Current maximum distance to the intersection.
* Is calculated as a ray length, transformed to an object space when entering
* instance node. */
float t_max_current = ray->t;
/* Conversion from world to local space for the current instance if any, 1.0
* otherwise. */
float t_world_to_instance = 1.0f;
*num_recorded_hits = 0;
*throughput = 1.0f;
*r_num_recorded_hits = 0;
*r_throughput = 1.0f;
/* traversal loop */
do {
@@ -237,10 +240,10 @@ ccl_device_inline
/* Always use baked shadow transparency for curves. */
if (isect.type & PRIMITIVE_CURVE) {
*throughput *= intersection_curve_shadow_transparency(
*r_throughput *= intersection_curve_shadow_transparency(
kg, isect.object, isect.prim, isect.u);
if (*throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) {
if (*r_throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) {
return true;
}
else {
@@ -249,37 +252,39 @@ ccl_device_inline
}
if (record_intersection) {
/* Increase the number of hits, possibly beyond max_hits, we will
* simply not record those and only keep the max_hits closest. */
uint record_index = (*num_recorded_hits)++;
/* Test if we need to record this transparent intersection. */
const uint max_record_hits = min(max_hits, INTEGRATOR_SHADOW_ISECT_SIZE);
if (record_index >= max_record_hits - 1) {
/* If maximum number of hits reached, find the intersection with
* the largest distance to potentially replace when another hit
* is found. */
const int num_recorded_hits = min(max_record_hits, record_index);
float max_recorded_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, 0, t);
int max_recorded_hit = 0;
if (*r_num_recorded_hits < max_record_hits || isect.t < t_max_world) {
/* If maximum number of hits was reached, replace the intersection with the
* highest distance. We want to find the N closest intersections. */
const uint num_recorded_hits = min(*r_num_recorded_hits, max_record_hits);
uint isect_index = num_recorded_hits;
if (num_recorded_hits + 1 >= max_record_hits) {
float max_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, 0, t);
uint max_recorded_hit = 0;
for (int i = 1; i < num_recorded_hits; i++) {
const float isect_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, i, t);
if (isect_t > max_recorded_t) {
max_recorded_t = isect_t;
max_recorded_hit = i;
for (uint i = 1; i < num_recorded_hits; ++i) {
const float isect_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, i, t);
if (isect_t > max_t) {
max_recorded_hit = i;
max_t = isect_t;
}
}
if (num_recorded_hits >= max_record_hits) {
isect_index = max_recorded_hit;
}
/* Limit the ray distance and stop counting hits beyond this. */
t_max_world = max(isect.t, max_t);
}
if (record_index >= max_record_hits) {
record_index = max_recorded_hit;
}
/* Limit the ray distance and stop counting hits beyond this. */
t_max_world = max(max_recorded_t, isect.t);
t_max_current = t_max_world * t_world_to_instance;
integrator_state_write_shadow_isect(state, &isect, isect_index);
}
integrator_state_write_shadow_isect(state, &isect, record_index);
/* Always increase the number of recorded hits, even beyond the maximum,
* so that we can detect this and trace another ray if needed. */
++(*r_num_recorded_hits);
}
}
}
@@ -318,7 +323,7 @@ ccl_device_inline
#endif
/* Restore world space ray length. */
t_max_current = t_max_world;
t_max_current = ray->t;
object = OBJECT_NONE;
t_world_to_instance = 1.0f;

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

@@ -72,7 +72,6 @@ typedef unsigned long long uint64_t;
#define ccl_gpu_syncthreads() __syncthreads()
#define ccl_gpu_ballot(predicate) __ballot_sync(0xFFFFFFFF, predicate)
#define ccl_gpu_shfl_down_sync(mask, var, detla) __shfl_down_sync(mask, var, detla)
/* GPU texture objects */

View File

@@ -186,7 +186,7 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals kg, int id, float x, flo
const int texture_type = info.data_type;
if (texture_type == IMAGE_DATA_TYPE_FLOAT4 || texture_type == IMAGE_DATA_TYPE_BYTE4 ||
texture_type == IMAGE_DATA_TYPE_HALF4 || texture_type == IMAGE_DATA_TYPE_USHORT4) {
if (info.interpolation == INTERPOLATION_CUBIC) {
if (info.interpolation == INTERPOLATION_CUBIC || info.interpolation == INTERPOLATION_SMART) {
return kernel_tex_image_interp_bicubic<float4>(info, x, y);
}
else {
@@ -198,7 +198,7 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals kg, int id, float x, flo
else {
float f;
if (info.interpolation == INTERPOLATION_CUBIC) {
if (info.interpolation == INTERPOLATION_CUBIC || info.interpolation == INTERPOLATION_SMART) {
f = kernel_tex_image_interp_bicubic<float>(info, x, y);
}
else {
@@ -241,7 +241,7 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals kg,
#endif
if (texture_type == IMAGE_DATA_TYPE_FLOAT4 || texture_type == IMAGE_DATA_TYPE_BYTE4 ||
texture_type == IMAGE_DATA_TYPE_HALF4 || texture_type == IMAGE_DATA_TYPE_USHORT4) {
if (interpolation == INTERPOLATION_CUBIC) {
if (interpolation == INTERPOLATION_CUBIC || interpolation == INTERPOLATION_SMART) {
return kernel_tex_image_interp_tricubic<float4>(info, x, y, z);
}
else {
@@ -252,7 +252,7 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals kg,
else {
float f;
if (interpolation == INTERPOLATION_CUBIC) {
if (interpolation == INTERPOLATION_CUBIC || interpolation == INTERPOLATION_SMART) {
f = kernel_tex_image_interp_tricubic<float>(info, x, y, z);
}
else {

View File

@@ -1,74 +0,0 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2021-2022 Blender Foundation */
#pragma once
CCL_NAMESPACE_BEGIN
/* Parallel sum of array input_data with size n into output_sum.
*
* Adapted from "Optimizing Parallel Reduction in GPU", Mark Harris.
*
* This version adds multiple elements per thread sequentially. This reduces
* the overall cost of the algorithm while keeping the work complexity O(n) and
* the step complexity O(log n). (Brent's Theorem optimization) */
#ifdef __HIP__
# define GPU_PARALLEL_SUM_DEFAULT_BLOCK_SIZE 1024
#else
# define GPU_PARALLEL_SUM_DEFAULT_BLOCK_SIZE 512
#endif
template<uint blocksize, typename InputT, typename OutputT, typename ConvertOp>
__device__ void gpu_parallel_sum(
const InputT *input_data, const uint n, OutputT *output_sum, OutputT zero, ConvertOp convert)
{
extern ccl_gpu_shared OutputT shared_data[];
const uint tid = ccl_gpu_thread_idx_x;
const uint gridsize = blocksize * ccl_gpu_grid_dim_x();
OutputT sum = zero;
for (uint i = ccl_gpu_block_idx_x * blocksize + tid; i < n; i += gridsize) {
sum += convert(input_data[i]);
}
shared_data[tid] = sum;
ccl_gpu_syncthreads();
if (blocksize >= 512 && tid < 256) {
shared_data[tid] = sum = sum + shared_data[tid + 256];
}
ccl_gpu_syncthreads();
if (blocksize >= 256 && tid < 128) {
shared_data[tid] = sum = sum + shared_data[tid + 128];
}
ccl_gpu_syncthreads();
if (blocksize >= 128 && tid < 64) {
shared_data[tid] = sum = sum + shared_data[tid + 64];
}
ccl_gpu_syncthreads();
if (blocksize >= 64 && tid < 32) {
shared_data[tid] = sum = sum + shared_data[tid + 32];
}
ccl_gpu_syncthreads();
if (tid < 32) {
for (int offset = ccl_gpu_warp_size / 2; offset > 0; offset /= 2) {
sum += ccl_shfl_down_sync(0xFFFFFFFF, sum, offset);
}
}
if (tid == 0) {
output_sum[ccl_gpu_block_idx_x] = sum;
}
}
CCL_NAMESPACE_END

View File

@@ -62,7 +62,7 @@ typedef unsigned long long uint64_t;
#define ccl_gpu_block_idx_x (blockIdx.x)
#define ccl_gpu_grid_dim_x (gridDim.x)
#define ccl_gpu_warp_size (warpSize)
#define ccl_gpu_thread_mask(thread_warp) uint(0xFFFFFFFF >> (ccl_gpu_warp_size - thread_warp))
#define ccl_gpu_thread_mask(thread_warp) uint64_t(0xFFFFFFFFFFFFFFFF >> (64 - thread_warp))
#define ccl_gpu_global_id_x() (ccl_gpu_block_idx_x * ccl_gpu_block_dim_x + ccl_gpu_thread_idx_x)
#define ccl_gpu_global_size_x() (ccl_gpu_grid_dim_x * ccl_gpu_block_dim_x)
@@ -71,7 +71,6 @@ typedef unsigned long long uint64_t;
#define ccl_gpu_syncthreads() __syncthreads()
#define ccl_gpu_ballot(predicate) __ballot(predicate)
#define ccl_gpu_shfl_down_sync(mask, var, detla) __shfl_down(var, detla)
/* GPU texture objects */
typedef hipTextureObject_t ccl_gpu_tex_object;

View File

@@ -74,7 +74,6 @@ typedef unsigned long long uint64_t;
#define ccl_gpu_syncthreads() __syncthreads()
#define ccl_gpu_ballot(predicate) __ballot_sync(0xFFFFFFFF, predicate)
#define ccl_gpu_shfl_down_sync(mask, var, detla) __shfl_down_sync(mask, var, detla)
/* GPU texture objects */

View File

@@ -352,6 +352,12 @@ ccl_device_inline void kernel_accum_emission_or_background_pass(KernelGlobals kg
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 +443,12 @@ 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;
}
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
int pass_offset = PASS_UNUSED;

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

@@ -263,6 +263,16 @@ ccl_device_inline float3 object_color(KernelGlobals kg, int object)
return make_float3(kobject->color[0], kobject->color[1], kobject->color[2]);
}
/* Alpha of the object */
ccl_device_inline float object_alpha(KernelGlobals kg, int object)
{
if (object == OBJECT_NONE)
return 0.0f;
return kernel_tex_fetch(__objects, object).alpha;
}
/* Pass ID number of object */
ccl_device_inline float object_pass_id(KernelGlobals kg, int object)

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();
}
}

View File

@@ -135,10 +135,10 @@ ccl_device_forceinline float4 primitive_surface_attribute_float4(KernelGlobals k
#endif
else {
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);
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
*dy = zero_float4();
return zero_float4();
}
}
@@ -187,7 +187,7 @@ ccl_device_inline float4 primitive_volume_attribute_float4(KernelGlobals kg,
return volume_attribute_float4(kg, sd, desc);
}
else {
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
return zero_float4();
}
}
#endif

View File

@@ -566,9 +566,9 @@ ccl_device_noinline float4 subd_triangle_attribute_float4(KernelGlobals kg,
#endif /* __PATCH_EVAL__ */
if (desc.element == ATTR_ELEMENT_FACE) {
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();
return kernel_tex_fetch(__attributes_float4,
desc.offset + subd_triangle_patch_face(kg, patch));
@@ -648,19 +648,19 @@ ccl_device_noinline float4 subd_triangle_attribute_float4(KernelGlobals kg,
}
else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) {
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();
return kernel_tex_fetch(__attributes_float4, desc.offset);
}
else {
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();
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
return zero_float4();
}
}

View File

@@ -338,9 +338,9 @@ ccl_device float4 triangle_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_FACE | ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) {
@@ -349,7 +349,7 @@ ccl_device float4 triangle_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();
}
}
}

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