1
1

Compare commits

..

293 Commits

Author SHA1 Message Date
e003c31ca0 cleanups 2020-03-08 12:39:19 +01:00
429e85c33a avoid some unnecessary changes 2020-03-08 12:29:24 +01:00
d2f2f732a5 add comment in ModifierTypeInfo 2020-03-08 12:24:51 +01:00
7502cdd86f improve naming 2020-03-08 12:16:33 +01:00
4e742352ec improve naming 2020-03-08 12:13:44 +01:00
f0b75491e9 avoid unnecesary changes in writefile 2020-03-08 12:09:49 +01:00
d7858eedbf improve naming 2020-03-08 12:06:31 +01:00
7a5da6a16c improve naming 2020-03-08 12:03:13 +01:00
5a90d35f79 use less nested preprocessing 2020-03-07 19:20:40 +01:00
fb29231e45 update armature modifier 2020-03-07 19:06:17 +01:00
ab673563e8 update subsurf modifier 2020-03-07 19:05:24 +01:00
bc317808d6 update explode modifier 2020-03-07 19:04:06 +01:00
5961d6565b update particle system modifier 2020-03-07 19:02:56 +01:00
acc05a1053 update surface modifier 2020-03-07 19:01:23 +01:00
dc3b6617bb update ocean modifier 2020-03-07 19:00:01 +01:00
d912bb9cce update mesh sequence cache modifier 2020-03-07 18:58:28 +01:00
23a071ee6c update dynamic paint 2020-03-07 18:56:28 +01:00
d807418a45 update warp modifier 2020-03-07 18:47:04 +01:00
9ad3a3754f update vertex weight edit modifier 2020-03-07 18:44:00 +01:00
b9a4a3ece5 improve parameter order 2020-03-07 18:37:37 +01:00
f563674d58 update laplacian deform modifier 2020-03-07 18:32:32 +01:00
0fa3a00f34 cleanup naming 2020-03-07 18:27:28 +01:00
7ed6e3a5ef simplify writing array 2020-03-07 18:23:46 +01:00
c6e61edb34 update corrective smooth modifier 2020-03-07 18:13:15 +01:00
a883e0a30e update bevel modifier 2020-03-07 18:03:50 +01:00
cfa101cf46 update surface deform modifier 2020-03-07 17:59:22 +01:00
520db97acf move meshdeform modifier writing/reading 2020-03-07 17:41:13 +01:00
6f77056dca move cloth modifier file writing/reading to MOD_cloth.c 2020-03-07 17:22:55 +01:00
0d444bd3ef simplify reading raw arrays of primitive types 2020-03-07 17:14:45 +01:00
0e52777cf0 add bloRead method to ModifierTypeInfo 2020-03-07 17:03:53 +01:00
f9e4086b04 write raw array utility 2020-03-07 16:53:35 +01:00
192091903e move hook modifier file writing into MOD_hook.c 2020-03-07 16:49:37 +01:00
681ff0c789 Add bloWrite callback to ModifierTypeInfo definitions of individual modifiers 2020-03-07 16:41:55 +01:00
081311d168 add blenloader write callback to ModifierTypeInfo 2020-03-07 16:38:00 +01:00
e41f2c1238 improve naming 2020-03-07 16:33:54 +01:00
ac7d45cc19 try different naming convention 2020-03-07 16:30:33 +01:00
eafb864bfe Merge branch 'master' into blenloader-api 2020-03-07 16:18:25 +01:00
fb13e40ce1 move curve profile writing/reading to blenkernel 2020-03-07 16:17:52 +01:00
ff86d46805 move point cache reading to blenkernel 2020-03-07 16:06:15 +01:00
ecb4c5d8a4 change parameter order 2020-03-07 13:20:33 +01:00
a0ec12a249 move pointcache file writing to blenkernel 2020-03-07 13:17:15 +01:00
c3c2ea39b2 move blenloader callback api to single file 2020-03-07 13:05:16 +01:00
ac8d26974e cleanup curve mapping reading 2020-03-07 12:58:45 +01:00
d7839734a0 utility for updating addresses 2020-03-07 12:58:32 +01:00
672372583e move curvemapping file handling to blenkernel 2020-03-07 12:52:00 +01:00
4c95dc5a1b fix api 2020-03-07 12:51:27 +01:00
946d39f688 UI: move Cycles adaptive sampling settings to own subpanel 2020-03-07 12:40:06 +01:00
7adcc0731e improve naming 2020-03-07 12:25:16 +01:00
7c08cd508a improve naming 2020-03-07 12:21:10 +01:00
8a5a306a83 Fix key release event activating click-drag
A handled release event could still trigger a click-drag afterwards.
2020-03-07 18:21:01 +11:00
2534dffaa5 WM: include repeat value in WM_event_print 2020-03-07 16:26:22 +11:00
ef5c6361a5 Cleanup: replace BLI_make_file_string with BLI_join_dirfile for the file-selector
In these cases the file selectors directory is already expanded.
2020-03-07 13:52:41 +11:00
0964865568 Cleanup: replace BLI_make_file_string with BLI_join_dirfile where possible
Use 'BLI_join_dirfile' for joining paths that don't need to expand '//'.
2020-03-07 13:26:23 +11:00
8fb1ea857f Include file system encoding in 'System Info' operator
Help troubleshooting file system encoding issues.
2020-03-07 11:53:14 +11:00
dcdcc23488 Fix T74504: Cycles wrong progress bar with CPU adaptive sampling 2020-03-06 23:46:58 +01:00
b31b44c223 Fix error in Cycles Optix adaptive sampling after recent cleanup 2020-03-06 23:46:58 +01:00
afe6df1487 Cleanup: VFont: Move to IDTypeInfo and remove unused BKE API
This was particularly strange because we had a _free_data() function.
But still the one I replaced was of course the _free() one.

And we should rename the _free_data_ function later to avoid confusions.
2020-03-06 20:07:02 +01:00
558f449f8c Cleanup: Text: Move to IDTypeInfo and remove unused BKE API. 2020-03-06 20:07:02 +01:00
7177862313 API Docs: Point to manual for Operator Cheat Sheet 2020-03-06 12:50:19 -05:00
13595c912c UI: Remove Windows 3D Object Folder Reference
Remove Windows special folder FOLDERID_Objects3D. Requires newer SDK.

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

Reviewed by Brecht Van Lommel
2020-03-06 09:33:13 -08:00
85424397b1 Cleanup: tweak Freestyle #includes in preparation for clang-format sorting 2020-03-06 17:26:32 +01:00
96e2bd8493 Cleanup: Fix forward declaration of headers 2020-03-06 17:26:32 +01:00
b2ee1770d4 Cleanup: Rename ARegion variables from ar to region
The old convention was easy to confuse with ScrArea.
Part of https://developer.blender.org/T74432.

This is mostly a batch rename with some manual fixing. Only single word
variable names are changed, no prefixed/suffixed names.

Brecht van Lommel and Campbell Barton both gave me a green light for
this convention change.

Also ran clan clang format on affected files.
2020-03-06 17:19:23 +01:00
b825a95ec3 Cleanup: Image: Move to IDTypeInfo and remove unused BKE API. 2020-03-06 17:13:27 +01:00
f4936de918 Cleanup: Texture: Move to IDTypeInfo and remove unused BKE API. 2020-03-06 17:13:27 +01:00
a7fb567c18 Cleanup: Material: Move to IDTypeInfo and remove unused BKE API. 2020-03-06 17:13:27 +01:00
ae6a5629a5 Fix build error on windows
```
Error	C4013	'_VA_ELEM1' undefined; assuming extern returning int
```
2020-03-06 12:49:24 -03:00
68b6d0302a Cleanup: Action: Move to IDTypeInfo, and remove unused BKE API. 2020-03-06 16:43:09 +01:00
57daecc2cf Cleanup: Armature: Move to IDTypeInfo, and remove unused BKE API. 2020-03-06 16:43:09 +01:00
14d03af7ae Bring back code accidentally removed by previous commit
Probably got lost when resolving merge conflicts.
2020-03-06 16:41:57 +01:00
d5572eacc5 Cleanup: Reduce context usage in UI functions
Part of https://developer.blender.org/T74429.

There's a chance that this causes some issues becaue in some cases we
change from getting the window from context to getting it from somewhere
else.
2020-03-06 16:27:13 +01:00
b242cc6792 Cleanup: Lattice: Move to IDTypeInfo and remove unused BKE API. 2020-03-06 16:23:23 +01:00
da7fcd3e52 Cleanup: MetaBall: Move to IDTypeInfo and remove unused BKE API. 2020-03-06 16:23:23 +01:00
8c21668ee1 Cleanup: Curve: Move to IDTypeInfo and remove unused BKE API. 2020-03-06 16:23:23 +01:00
bf6cf49133 Cleanup: Mesh: Move to IDTypeInfo and remove unused BKE API. 2020-03-06 16:23:23 +01:00
eb522af4fe Cleanup: move Alembic, AVI, Collada, and USD to source/blender/io
This moves the `alembic`, `avi`, `collada`, and `usd` modules into a common
`io` directory.

This also cleans up some `#include "../../{somedir}/{somefile}.h"` by
adding `../../io/{somedir}` to `CMakeLists.txt` and then just using
`#include "{somefile}.h"`.

No functional changes.
2020-03-06 16:19:45 +01:00
ff60dd8b18 Depsgraph: remove unused no-op nodes after building
This is the companion of D7031. That patch adds a new DIMENSIONS node to
the depsgraph for each object that has geometry. However, this node is
only necessary when there are drivers using an object's dimensions as
variable. Since this is rare, it's easiest to remove these nodes after
they turn out to be unnecessary. This is what (almost) happens in this
patch.

Removing nodes from the depsgraph is hard, and there are no functions to
do this yet. Instead, this patch recursively removes all the incoming
relations from unused no-op nodes (i.e. no-op operation nodes without
outgoing connections). Actually removing the nodes will be left as a
future improvement.

I've tested this on a Spring file [1]. Here are there results of blender
--debug-depsgraph-time spring_02_055_A.eevee.blend and letting it run
for a while to stabilise the reported FPS:

    master: 11.7 FPS
    Just D7031: 11.7 FPS
    Just D7033: 11.8 FPS
    Both D7031 + D7033: 12.3 FPS

[1] https://cloud.blender.org/p/spring/5d30a1076249366fa1939cf1

Differential Revision: https://developer.blender.org/D7033
2020-03-06 16:19:45 +01:00
f2f8c5b2bd Cleanup: Move Multiplane Scrape brush to its own file 2020-03-06 16:00:33 +01:00
40ac8250b2 Fix narrowing from int to short when removing material slot 2020-03-06 15:56:09 +01:00
926f52edf0 Sculpt: Cleanup, remove macro re-definition 2020-03-06 15:52:36 +01:00
a16e4652e3 Fix integer overflow in BLI_mempool_as_arrayN()
`(size_t)(int * int)` will actually cast overflown integer to size_t,
which isn't what was intended here. Correct thing would be to cast
in the following manner `(size_t)int * int`.

In this particular case can as well use function which is designed to
allocate an array of memory without overflow.
2020-03-06 15:35:52 +01:00
c60366c01f Cycles: cleanup warning 2020-03-06 15:27:50 +01:00
17f08cff6a Cleanup: Collection: Move to IDTypeInfo, and remove unused BKE API.
Note: we still need BKE_collection_free since we call it from scene.c.
2020-03-06 15:27:50 +01:00
69d4aec55f Cleanup: Use the SCULPT_ prefix in all sculpt_intern functions 2020-03-06 15:24:15 +01:00
b201a67faa Cleanup: bScreen: Move to IDTypeInfo and remove unused BKE API. 2020-03-06 15:20:04 +01:00
a5bbdd6998 Cleanup: use ELEM macro for path slash checks 2020-03-07 01:02:37 +11:00
b4f1edd98b Fluid: Revert bc2ce31d79 (changes to open boundaries)
Changes from that commit turned out to be unstable.
2020-03-06 15:01:30 +01:00
a9ac87be36 Fix T73842: UI: add cloth collision settings to Hair Dynamics panel
Since hair collisions were integrated with the cloth solver
(rBd42a7bbd6ea5), there are a couple of relevant settings which were not
exposed to the User:
- Collision Quality
- Minimum Distance (this was reported in T73842, default of 0.015m was
still limiting in certain scenarios - this can now be made smaller)
- Impulse clamping
- Collision collection

This will add a 'Collisions' panel to Hair Dynamics with those settings

Note: in contrast to 'real' cloth, self-collisions are not supported for
hair

Maniphest Tasks: T73842

Differential Revision: https://developer.blender.org/D7032
2020-03-06 14:59:02 +01:00
f9c7442479 Cleanup: bNodeTree: Move to IDTypeInfo and remove unused BKE API. 2020-03-06 14:58:23 +01:00
165daee7cb Improve modifier error message with sculpt mode
Make it obvious that this relates to being in sculpt mode.

ref T74489

Maniphest Tasks: T74489

Differential Revision: https://developer.blender.org/D7044
2020-03-06 14:52:25 +01:00
a9f39fa197 initial blenloader api 2020-03-06 14:50:39 +01:00
c8ac760c59 Cleanup: tweak Cycles #includes in preparation for clang-format sorting 2020-03-06 14:44:42 +01:00
4102d67d32 Cleanup: avoid use of BLI_cleanup_dir
Some cases don't need to add the trailing slash.
Use BLI_cleanup_path in this case.
2020-03-07 00:39:28 +11:00
2d5773d11a Documentation: added bpy.msgbus description and examples
The `bpy.msgbus` namespace was not included in the documentation generation.
I've added it, and ported Campbell's examples from P563.
2020-03-06 14:29:03 +01:00
07c5ca7f2c Cleanup: Message bus, removed incorrect return type from docstring
The docstring was likely copy-pasted, and the return type was not adjusted.
Since the `bpy.msgbus.subscribe_rna()` returns nothing, I just removed the
return type documentation.
2020-03-06 14:29:03 +01:00
b839a5d076 Cleanup: remove BLI_cleanup_file
In practice, references to files rarely have trailing slashes
(by accident). Remove this function in favor of BLI_cleanup_path.
2020-03-07 00:19:01 +11:00
0b16b63d87 Cleanup: spelling 2020-03-07 00:19:01 +11:00
8bb0ac27dc Fix using wrong property name for preserve face sets when remeshing
Spotted by Roel Koster in the initial face set commit.
2020-03-06 14:17:30 +01:00
50d5050e9c Nodes: fix writing socket default values to file
Previously, `writedata` was used to store `bNodeSocket->default_value`.
There are a couple of issues with that:
* Breaks if someone tries to load the file on a big endian system (afaik).
* There is a `/* do not use for structs */` comment on `writedata`.
* Depends on `MEM_allocN_len` which should be avoided in my opinion.
* Now it is more apparent, that this should be handled by callbacks as well.

The part in `readfile.c` should work just fine still. I could also do a case
distinction there, but the code would be the same for every case for now.
Just `sock->default_value = newdataadr(fd, sock->default_value);`.

This might change, if we want to store more complex socket type specific data
that does not fit into a single struct.

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

Reviewers: brecht
2020-03-06 13:31:15 +01:00
63bb2007d8 CodeCleanup: Added View3DShading enums
Added the core enums that workbench draw engine uses.
2020-03-06 13:00:06 +01:00
f0808b53ab Cleanup: Brush: Move to IDTypeInfo, and remove unused BKE API. 2020-03-06 12:54:04 +01:00
15c834ebbf Cleanup: ShapeKey: Move to IDTypeInfo and remove unused BKE API. 2020-03-06 12:52:52 +01:00
c08151c6fa Nodes: Support storing socket link limits in bNodeSocketType
Currently the link limit of sockets is stored in bNodeSocket->limit.
This allows for a lot of flexibility, but is also very redundant.
In every case I've had to deal with so far, it would have "more correct"
to set the link limit per socket type and not per socket. I did not enforce
this constraint yet, because the link limit is exposed in the Python API,
which I did not want to break here.

In the future it might even make sense to only support only three kinds of link limits:
a) no links, b) at most one link, c) an arbitrary number links links. The other link
limits usually don't work well with tools (e.g. which link should be removed when a new
one is connected?) and is not used in practice. However, that is for another day.

Eventually, I would like to get rid of bNodeSocket->limit completely and replace it
either with fixed link limits or a callback in bNodeSocketType.

This patch consists of three parts:

**1. Support defining link limit in socket type**
This introduces a new `nodeSocketLinkLimit` function that serves as an indirection to
hide where the link limit of a socket is defined.

**2. Define link limits for builtin sockets on socket type**
Data sockets: one input, many outputs
Virtual sockets: one input, one output
Undefined sockets: many inputs, many outputs (to avoid that links are removed when the type of the socket is not known)

**3. Remove `bNodeSocketTemplate->limit`**
This wasn't used anymore after the second commit. Removing it simplifies socket definitions
in hundreds of places and removes a lot of redundancy.

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

Reviewers: brecht
2020-03-06 12:33:04 +01:00
98d562af52 CodeCleanup: move include statements before extern "C"
Mistake on recent changes that would fail when used in CPP.
2020-03-06 12:32:53 +01:00
24a37b3c03 Fix memory leak in the colorio fallback implementation.
We would previously not store the transforms that were added to the
group transform node. This would lead to pointer to allocated memory
being lost and not freed.
2020-03-06 12:29:12 +01:00
e65f5c07b0 Fluid: Added missing UI options for effector objects
UI was missing some of the new functionality introduced in a5c4a44df6.
2020-03-06 12:26:47 +01:00
79558a581d CodeCleanup: Use eDrawType
This patch will make use of the eDrawType where it was used as a
variable or parameter name. The eObjectDrawType was renamed to eDrawType
as it is also used by `View3DShading.type`.
2020-03-06 12:23:46 +01:00
e96b103536 Cleanup: move camera, lights, world to IDTypeInfo 2020-03-06 12:19:11 +01:00
297261eb90 CodeCleanup: Added enums to opengl render functions
Motivation the functions get 3 different kind of flag parameters (ImBuf,
DrawType, OffscreenRendering) the naming of the flags were not clear,
leading to mistakes and unnecessary time spend debugging.
2020-03-06 12:11:55 +01:00
9fa29fe765 Cleanup: remove MLOOPUV_EDGESEL
This was not set anywhere, code relies on MLOOPUV_VERTSEL everywhere.

BMLoopUV.select_edge was never returning True and wasnt updating uv
select state when set manually.

Afaict, there were no official Addons using this from python.

Resolves T65836

Maniphest Tasks: T65836

Differential Revision: https://developer.blender.org/D6772
2020-03-06 11:59:28 +01:00
Julian Eisel
c72317943b Attempt to fix build errors on macOS
Mistake in 5be0e3430d
2020-03-06 11:43:13 +01:00
7d61132807 Animation: improved error handling when adding/deleting keyframes
There are two ways in which adding/deleting keyframes can fail, but only
one of those was handled. The other would be shown as a successful
add/delete of -2 keyframes.
2020-03-06 11:36:59 +01:00
d8491cb7c6 Cleanup: Animation, renamed and clarified 'success' variable
The `ANIM_apply_keyingset()` returns a value that indicates the number of
changed channels (if nonnegative) or an error state (negative). In the
places where the return value was actually used, this value was stored in
a badly named variable.
2020-03-06 11:36:59 +01:00
17e1fef85a Cleanup: Library: Move to IDTypeInfo, and remove unused BKE API. 2020-03-06 11:27:54 +01:00
c25f6e998b Cleanup: Object: remove unused BKE API. 2020-03-06 11:27:54 +01:00
af5d2e38f7 Cleanup: Scene: New IDTypeInfo, and remove unused API from BKE. 2020-03-06 11:27:54 +01:00
7d9a5b7b10 Fix T73254: Drivers with the object.dimension variable are not updated
This fixes an issue where drivers using `object.dimension` only add a dependency on `GEOMETRY` to the depsgraph, whereas they should also depend on `TRANSFORM`.

This patch adds a new no-op operation that depends on the geometry and transform components to the Parameters component.

An alternative implementation would be to have `RNANodeQuery::construct_node_identifier` return multiple node identifiers. However, this would spread throughout the depsgraph code and unnecessarily force many other functions to either return or handle multiple nodes where in 99.999% of the time a single node would suffice.

The new `DIMENSIONS` node is added for each object. An upcoming patch will go over all no-op operation nodes and remove them from the depsgraph. Since this is a more dangerous operation, it'll be reviewed separately.

Differential Revision: https://developer.blender.org/D7031
2020-03-06 11:05:22 +01:00
abd33a3c0c Fluid: Cleanup naming for emmission bounding box
Since the bounding boxes are now also being used for effector objects, there needs to be a better name for them. Instead of calling them EmissionMap, which caters only to emission objects, they will now be called FluidObjectBB.
2020-03-06 11:04:26 +01:00
2e7cfb86fe Keymap: ignore repeat events for transform actions
Resolves T54297
2020-03-06 21:02:11 +11:00
e6aa349c68 CodeCleanup: eevee_materials Use Struct Assignments 2020-03-06 10:28:02 +01:00
0b9c1c2b86 Cleanup: typo in function name
contect -> context
2020-03-06 09:47:27 +01:00
5be0e3430d GHOST/Keymap: support for detecting repeat events
- Keymap items now have 'repeat' boolean which can be set
  to make keymap items respond to key repeat events or not.
- Support for X11 & WIN32 (not macOS currently).

This allows for the possibility to perform actions while a key is held
and finish the action upon release.

Thanks to @Severin for review and WIN32 support.
2020-03-06 17:31:28 +11:00
73ef27f156 Cleanup: keyframing return arguments
- Use 'int' for counters instead of short.
- Use 'bool' instead of a counter when only a change is being detected.
- Use typed enum for keying set flags.
- Include in comments when a negate error code may be returned.
2020-03-06 17:05:18 +11:00
e97aed1e73 Cleanup: remove unused 'eInsertKeyFlags' from delete API call
There is no need for an insertion flag in a delete function.
2020-03-06 15:07:57 +11:00
b15c658801 Cleanup: keyframe API naming, high level keyframe API
- Split 'verify_fcurve' into two functions:

  ED_action_fcurve_ensure which adds the f-curve if needed.
  ED_action_fcurve_find which returns NULL when not found.

  Callers of ED_action_fcurve_find had unused 'group'
  argument which has been removed.

- Rename verify_adt_action to ED_id_action_ensure

  It had an argument to add data which was always true,
  remove this instead of splitting in into a separate function.
2020-03-06 14:16:38 +11:00
07d13be678 Cleanup: rename 'verify' to 'ensure' for BKE_image_viewer functions 2020-03-06 13:06:21 +11:00
54ab8c6abd Cleanup: rename 'verify' to 'ensure' for argument name 2020-03-06 13:00:01 +11:00
bba4a09b2f Cleanup: use 'BKE_' prefix for BKE_deform API calls
- Use 'BKE_object_defgroup' prefix for object functions.

- Rename 'defvert_verify_index' to 'defvert_ensure_index'
  since this adds the group if it isn't found.
2020-03-06 12:56:44 +11:00
1af83aa2dd Cleanup: use 'r_' prefix for return arguments
Also avoid a redundant strlen call.
2020-03-06 12:49:21 +11:00
088636bc38 Cleanup: use BLI_strnlen instead of strlen 2020-03-06 12:43:58 +11:00
5229448c43 Cleanup: clang-format 2020-03-06 12:39:00 +11:00
c19d2f2507 Cleanup: use MEM_recallocN_id 2020-03-06 12:00:37 +11:00
8574d68aa0 Cleanup: spelling 2020-03-06 11:52:32 +11:00
6c623b0e8c Cleanup: add decimal values for event types, order by value 2020-03-06 11:52:31 +11:00
da30e9a104 Cleanup: quiet switch warnings 2020-03-06 11:52:31 +11:00
310285b0c2 Cleanup: redundant-decls warning 2020-03-06 11:14:21 +11:00
eed1beff88 UI: Using Consistent Font Icon in File Browser
Use only one font icon in File Browser for all platforms. Correct mistake to allow this icon to be used.

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

Reviewed by Brecht Van Lommel
2020-03-05 13:23:28 -08:00
38d6533f21 Sculpt Face Sets
Face Sets are the new system to control the visibility state of the mesh in sculpt and paint modes. They are designed to work in modes where brushes are the primary way of interaction and they provide much more control when working with meshes with complex shapes and overlapping surfaces.

This initial commit includes:
- Sculpt Face Sets data structures and PBVH rendering.
- Face Set overlay and opacity controls.
- Sculpt Undo support.
- Remesher reprojection support. The visibility state of the mesh is also preserved when remeshing.
- Automasking and Mesh filter support.
- Mask expand operator mode to expand Face Sets (Shift + W) and flood fill areas by connectivity (press Ctrl while expanding).
- Sculpt Mode Face Sets and Visibility API.
- Sculpt Face Sets creation and visibility management operators.
- Operator to randomize the Face Sets colors.
- Draw Face Sets brush tool to create and edit the Face Sets. Drawing on the mesh creates a new Face Set. Pressing Ctrl before drawing modifies the Face Set under the brush at the beginning of the stroke.
- Updated keymap and menu to work with Face Sets from Sculpt Mode (H to toggle visibility, Alt + H to show all, Shit + H to hide).
- Pie menu on the W key with Face common Sets operations.

Know limitations:
- Multires support. The Face Sets and Visibility API needs to be implemented for Multires.

Reviewed By: jbakker, #user_interface, Severin

Differential Revision: https://developer.blender.org/D6070
2020-03-05 21:07:20 +01:00
e56471bcd3 UI: File Browser Favorites
Adding more Windows special folder locations, used when browsing or bookmarking.

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

Reviewed by Brecht Van Lommel
2020-03-05 11:49:56 -08:00
Yevgeny Makarov
84c9a99cca UI: Mac File Browser System List Changes
Nicer icons for File Browser System and Favorites lists on Mac.

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

Reviewed by Brecht Van Lommel
2020-03-05 10:40:02 -08:00
Julian Eisel
3b1ef223ba Ghost: Support drawing OpenGL framebuffers into a DirectX 11 buffer
Adds a minimal DirectX 11 Ghost context, plus some shared DirectX-OpenGL
resource interface using the NV_DX_interop2 WGL extension. From what I
know, this should be available on modern GPUs. If not, it should fail
gracefully.
There should be no user visible changes at this point.

Needed for DirectX-only OpenXR platforms (e.g. Windows Mixed Reality). I
heard there are other use-cases as well though.

It's known that this currently fails on some AMD systems, but that seems
to be fixable.

Most of this comes from the 2019 GSoC project, "Core Support of Virtual
Reality Headsets through OpenXR"
(https://wiki.blender.org/wiki/User:Severin/GSoC-2019/).

Reviewed by: Jeroen Bakker, Ray Molenkam, Brecht van Lommel

Differential Revision: https://developer.blender.org/D6190
2020-03-05 18:29:29 +01:00
4a3377fcf6 Fluid: Optimization in mesh generating loop
No need to have three separate loops for vertices, normals and speed vectors. Since all of them loop over the vertex count, a single loop can be used.
2020-03-05 17:51:21 +01:00
a874cfb858 Cleanup: Move std::deque to depsgraph_type.h
Since `std::deque` is used in a few areas of the Depsgraph, and an
upcoming patch adds one more, it's time it's considered as "commonly
used type".

No functional changes.
2020-03-05 17:32:01 +01:00
c43725e189 Add an session-wise uuid integer to IDs.
"session-wise" here mean while editing a same .blend file. So creating
or opening a new one will reset the uuid counter. This should avoid any
overflow in practice.

Only IDs added to Main database get an uuid, runtime-only ones are not
affected.

This is intended to provide undo with a way to find IDs across several
'memory realms' (undo speedup project).

No behavior change is expected from this commit itself.

Part of T60695.

Differential Revision: https://developer.blender.org/D7007
2020-03-05 16:30:12 +01:00
88db9a17ce Fix T74393: Cycles crashes when both OSL and Optix Denoising are enabled
Enabling viewport denoising causes Cycles to use a multi-device, which always returned NULL when
asked for OSL memory and would subsequently crash. This fixes that by returning the correct OSL
memory pointer from the CPU device in the special viewport denoising multi-device.
2020-03-05 16:28:31 +01:00
fe7528ee91 Fix T74332: selection sync replacing parent selection
Selecting certain child datablocks also selects the parent (e.g.
selecting a pose bone selects the armature). The base was selected, but
the outliner tree element was left unselected. The subsequent selection
sync would then deselect the parent base because it was not flagged as
selected in the outliner.

This led to issues like T74332 where selecting a pose bone in the
outliner did not show drivers in the driver editor unless the armature
was explicitly added to the selection afterwards.

The solution is to also flag the outliner elements as selected when
selecting parent bases.

Differential Revision: https://developer.blender.org/D7029
2020-03-05 07:40:29 -07:00
60c208e2d6 Fluid: Fix initial velocities for new static emission mode
For now, disabling static mode whenever initial velocities are being used.
2020-03-05 14:58:15 +01:00
950a35e353 Fluid: More optimizations in smoke / liquid scripts
Reduced extrapolation distances, no need to extrapolate that far.
2020-03-05 14:22:51 +01:00
cd0a6ff5c4 Fluid: Diffusion settings now optional
For optimization purposes these settings need to be enabled explicitly from now on.
2020-03-05 12:36:00 +01:00
4d3da4e1d0 EEVEE: Render Passes Blending
Changed the blending mode to full blending. I found the issue when
during development of a material pass containing alpha values.
2020-03-05 12:25:35 +01:00
Stefan Werner
51e898324d Adaptive Sampling for Cycles.
This feature takes some inspiration from
"RenderMan: An Advanced Path Tracing Architecture for Movie Rendering" and
"A Hierarchical Automatic Stopping Condition for Monte Carlo Global Illumination"

The basic principle is as follows:
While samples are being added to a pixel, the adaptive sampler writes half
of the samples to a separate buffer. This gives it two separate estimates
of the same pixel, and by comparing their difference it estimates convergence.
Once convergence drops below a given threshold, the pixel is considered done.

When a pixel has not converged yet and needs more samples than the minimum,
its immediate neighbors are also set to take more samples. This is done in order
to more reliably detect sharp features such as caustics. A 3x3 box filter that
is run periodically over the tile buffer is used for that purpose.

After a tile has finished rendering, the values of all passes are scaled as if
they were rendered with the full number of samples. This way, any code operating
on these buffers, for example the denoiser, does not need to be changed for
per-pixel sample counts.

Reviewed By: brecht, #cycles

Differential Revision: https://developer.blender.org/D4686
2020-03-05 12:21:38 +01:00
4ccbbd3080 Fix T74446: Liquid Inflow Does Not Work
Somehow this was forgotton in the optimization patch a5c4a44df6.
2020-03-05 11:41:09 +01:00
c328049535 Initial step for IDTypeInfo refactor 'cleanup' project.
Introduce new IDTypeInfo structure.

Each ID type will have its own, with some minimal basic common info,
and ID management callbacks.

This patch only does it for Object type, for demo/testing purpose.
Moving all existing IDs is a goal of next "cleanup Friday".

Note that BKE_idcode features should then be merged back into BKE_idtype -
but this will have to be done later, once all ID types have been properly
converted to the new system.

Another later TODO might be to try and add callbacks for file read/write,
and lib_query ID usages looper.

This is part of T73719.

Thanks to @brecht for initial idea, and reviewing the patch.

Differential Revision: https://developer.blender.org/D6966
2020-03-05 10:58:58 +01:00
6665ce8951 Cleanup: Clarified comment
No functional changes.
2020-03-05 10:46:52 +01:00
e5f98c79b0 Fix T74431: EEVEE AO Render Pass
Missing code-path in recent refactoring.
2020-03-05 08:58:00 +01:00
a0ea0153c2 Addons: Allow a user manual url prefix in doc_url
This was raised in T74017, the issue being that we point to `/dev` 
version of the manual for the addons when we want to point to a specific 
version instead.

Instead of manually updating the URL every release we can do this.

The `bl_info` for addons will need to be updated in the format of 
`'doc_url': 
{BLENDER_MANUAL_URL}/addons/import_export/scene_gltf2.html",`

Differential Revision: https://developer.blender.org/D6995
2020-03-04 23:24:13 -05:00
Aaron Carlisle
ae223ff52b Addons: deprecate 'wiki_url'
When running with debug enabled ('-d' argument),
warnings are printed for add-ons which are not yet updated.

Reminder to name things based on what they do,
not the technologies they use :)
2020-03-05 11:45:22 +11:00
3da2dc8213 Fix RNA runtime warning from recent commit 2020-03-04 17:43:17 -05:00
337e861486 UI: Fluid: Fix wrong uses of enabled 2020-03-04 17:41:42 -05:00
6ab14d971c UI: Fluid: Viewport Display
Cleanup the order of properties and hide sub setting as they were 
confusing before.
2020-03-04 17:41:42 -05:00
bd0f5fa71f UI: Fluid Group Liquid/Gas Panels
Part of T73617

Differential Revision: https://developer.blender.org/D6994
2020-03-04 17:41:42 -05:00
55b465f976 UI: Fluid: Use updated preset UI
Part of T73617
2020-03-04 17:41:41 -05:00
1d18a2a5ec Fix Unreported: Error adding fluid presets 2020-03-04 17:41:41 -05:00
1da8ed2a97 Cleanup: redundant casts 2020-03-05 08:38:41 +11:00
2fb4de1f8c Cleanup: material API naming
- Use 'BKE_object_material_*', 'BKE_id_material_*' prefix
  for functions that operate on Object and ID types.
- Use '_len' suffix for length (matching BLI naming).
- Use '_p' suffix for functions that return a pointer to values
  where the value would typically be returned.

Functions renamed:

- BKE_object_material_resize      was BKE_material_resize_object
- BKE_object_material_remap       was BKE_material_remap_object
- BKE_object_material_remap_calc  was BKE_material_remap_object_calc

- BKE_object_material_array_p     was BKE_object_material_array
- BKE_object_material_len_p       was BKE_object_material_num
- BKE_id_material_array_p         was BKE_id_material_array
- BKE_id_material_len_p           was BKE_id_material_num

- BKE_id_material_resize          was BKE_material_resize_id
- BKE_id_material_append          was BKE_material_append_id
- BKE_id_material_pop             was BKE_material_pop_id
- BKE_id_material_clear           was BKE_material_clear_id
2020-03-05 08:21:31 +11:00
5b0f1e7649 Cleanup: formatting, strip trailing space 2020-03-05 08:05:21 +11:00
a297a6c444 Cleanup: replace unnecessary MEM_callocN calls
Use MEM_mallocN when memory is immediately copied over.
2020-03-05 07:59:34 +11:00
a5c4a44df6 Fluid: Bounding boxes for effector objects
This commit adds bounding box support for emission objects - similarly to flow objects. Before, each effector object had to iterate over the entire domain. Bake times of scenes with multiple obstacles improved significantly with this optimization.

Other improvements that were implemented alongside the bbox feature:
- Option for subframe sampling for effector objects
- Option to enable / disable effectors (can be animated)
- Optimization for static objects. If a flow or effector object does not move and the adaptive domain is not in use, the bake time will be optimized further by reusing the flow / effector grids from the previous frame (no recalculation).
2020-03-04 18:46:48 +01:00
3c74d45c9e Fluid: Added sanity grid initializations in smoke / liquid scripts
Just a sanity check.
2020-03-04 18:46:48 +01:00
8f1876b4f0 Fluid: Fix issue with fire emission
Fixes weird behavior at inflow regions. Issue was introduced with d6d44ccc77.
2020-03-04 18:46:48 +01:00
bf8a73b4a7 Fluid: Naming cleanup for flags grid
Use flags instead of obstacle to avoid confusion with obstacle levelset grid.
2020-03-04 18:46:48 +01:00
6958ec3f7f Fluid: Added an option to delete fluid inside obstacles
Simple checkbox that - if enabled - will tell the solver to clear density or liquid particles in obstacle cells.
2020-03-04 18:46:48 +01:00
b32fd73b24 Fluid: Optimization for extrapolation functions in smoke / liquid scripts
Too much extrapolation can become expensive. Reducing it here since extrapolating levelsets into a couple of cells should be sufficient.
2020-03-04 18:46:48 +01:00
2a4f350940 Fix T74434: Video Sequencer: Alt+ clicking (assign to all selected) does
not work for unlocking

Special case for when we do this on "lock":
- locked sequences are not in "selected_editable_sequences"
- use "selected_sequences" in that case

Maniphest Tasks: T74434

Differential Revision: https://developer.blender.org/D7023
2020-03-04 17:35:39 +01:00
765f2a1bca Fix T71578: knife tool draws some points incorrectly
D6417 by @fbessou
2020-03-04 16:48:37 +01:00
Julian Eisel
a22573e243 Build System: Add OpenXR-SDK dependency and WITH_XR_OPENXR build option
The OpenXR-SDK contains utilities for using the OpenXR standard
(https://www.khronos.org/openxr/). Namely C-headers and a so called
"loader" to manage runtime linking to OpenXR platforms ("runtimes")
installed on the user's system.

The WITH_XR_OPENXR build option is disabled by default for now, as there
is no code using it yet. On macOS it will remain disabled for now, it's
untested and there's no OpenXR runtime in sight for it.

Some points on the OpenXR-SDK dependency:
* The repository is located at
  https://github.com/KhronosGroup/OpenXR-SDK (Apache 2).
* Notes on updating the dependency:
  https://wiki.blender.org/wiki/Source/OpenXR_SDK_Dependency
* It contains a bunch of generated files, for which the sources are in a
  separate repository
  (https://github.com/KhronosGroup/OpenXR-SDK-Source).
* We could use that other repo by default, but I'd rather go with the
  simpler solution and allow people to opt in if they want advanced dev
  features.
* We currently use the OpenXR loader lib from it and the headers.
* To use the injected OpenXR API-layers from the SDK (e.g. API
  validation layers), the SDK needs to be compiled from this other
  repository.

The extra "XR_" prefix in the build option is to avoid mix-ups of OpenXR
with OpenEXR.

Most of this comes from the 2019 GSoC project, "Core Support of Virtual
Reality Headsets through OpenXR"
(https://wiki.blender.org/wiki/User:Severin/GSoC-2019/).

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

Reviewed by: Campbell Barton, Sergey Sharybin, Bastien Montagne, Ray
Molenkamp
2020-03-04 16:45:07 +01:00
e7f1de5e11 Cleanup: use MEM_recallocN_id utility function 2020-03-04 23:51:32 +11:00
f4463cd865 RNA: ensure missing calls to RNA_enum_item_end crash in debug mode
Would have prevented T74227 from slipping through
since it didn't crash on some systems.
2020-03-04 23:48:45 +11:00
d83c0969f6 Fix T74426: Crash in the IK Pose Brush preview with null preview chain
After switching tools, the active vertex can be the same and the cursor
won't update the previews, so the pose_ik_chain_preview will be null.
This often happens in low poly meshes where chances of hovering the same
vertex are high.

Reviewed By: sergey

Maniphest Tasks: T74426

Differential Revision: https://developer.blender.org/D7021
2020-03-04 12:24:02 +01:00
6706ae5712 Cleanup: spelling 2020-03-04 21:46:16 +11:00
4bfa256ea4 Refactor ID make local to use a single flag parameter.
Instead of using anonymous booleans flags, also allows to keep the same
behavior in all cases, without needing special handling from calling
code for our beloved oddballs object proxies...
2020-03-04 11:43:31 +01:00
4e597a5cff Cleanup: ID make local: remove id_in_bmain argument.
This info is now stored in ID tags themselves, so no need to pass an
extra anonymous boolean parameter around, yay!
2020-03-04 11:43:30 +01:00
76d8e8693f Cleanup: Rename 'make local' functions to new scheme.
Also removed some only used locally from the header, `BKE_lib_id.h`
is already way too big, no need to overload it with unused things.
2020-03-04 11:43:30 +01:00
Asad-ullah Khan
e4eede8318 UI: rename View Selected" to "Frame Selected"
Addresses T74331
2020-03-04 21:38:23 +11:00
9c62a8c8e5 Fix T73797: Selection/Editing after Make Single User for Object Data
fails

Exposed by rB50d5c03e2d14.

This was only a problem when _only_ 'Object Data' was made local.
If also e.g. 'Object' or 'Materials' was checked, these were already
making sure realations were updated [DEG_relations_tag_update(bmain)].

Now also call DEG_relations_tag_update(bmain) for the 'Object Data'
case.

I assume the underlying issue is that there is some ID_NEW_REMAP
happening in 'single_obdata_users()' -- including that for 'me-
>texcomesh', which might be responsible for the glitches in selection/
editing? Also not entirely sure why this wasnt a problem prior to
rB50d5c03e2d14.(I assume this was somewhat hidden by the fact this was
always called with a default action being nothing, the user would always
need to access the redo panel. So this might have been hidden by an Undo
step involved?)

Maniphest Tasks: T73797

Differential Revision: https://developer.blender.org/D7020
2020-03-04 11:27:56 +01:00
a9dc1f6d00 Cleanup: avoid the term old when storing/restoring context variables 2020-03-04 21:13:32 +11:00
fb330dd110 Cleanup: remove unused BLI_strncat_utf8
Behaves differently to strncat,
BLI_strncpy_utf8_rlen can be used for a similar purpose.
2020-03-04 15:24:06 +11:00
8931c4b18d Fix possible buffer overflow from incorrect 'strncat' use
The size argument is the maximum number of bytes to copy,
not the destination buffer size.

Replace with utility function that joins strings.
2020-03-04 15:17:04 +11:00
0baae18375 BLI_string_utils: add BLI_string_join_array_by_sep_char
Utility to join strings into a fixed size buffer.
2020-03-04 15:14:02 +11:00
38ed95fe8d Cleanup: replace CLAMP macros with functions 2020-03-04 11:31:51 +11:00
89b10b8d42 BLI_math: inline clamp functions
These are used in some per-pixel operations such as image sampling and
color conversion, where replacing existing macro use could add overhead.
2020-03-04 11:23:00 +11:00
a37dceb139 Cleanup: replace commented code with define check
Avoids duplicated comments,
also quiet warning accessing non-existing variable.
2020-03-04 11:05:08 +11:00
a5c984a57d Cleanup: cmake indentation 2020-03-04 11:02:35 +11:00
d09c5bdc28 CMake: make OpenVDB depend on OpenEXR
OpenVDB uses 'half' type & fails to link without it.
2020-03-04 10:39:53 +11:00
Tiago Chaves
14c9f64def BLI_math: add clamp_v# and clamp_v#_v#v# utility functions 2020-03-04 10:25:44 +11:00
31aefdeec5 Fix T72028: Crash switching to vertex paint
This would happen when done from editmode, on a mesh with any modifier,
after adding/removing geometry in editmode.

Similar to rBba0870713b9b (which did this for weightpaint and sculpt
already), ensure an evaluated depsgraph, otherwise
'runtime.mesh_deform_eval' would not be up to date causing problems
later.

Maniphest Tasks: T72028

Differential Revision: https://developer.blender.org/D7011
2020-03-03 19:38:40 +01:00
059f3c1a7e Modifiers: Wave add invert vgroup option
Adds the invert vgroup option to the Wave modifier.

Differential Revision: https://developer.blender.org/D6893
2020-03-03 18:41:50 +01:00
Brecht Van Lommel
2841b2be39 IDs: change FILTER_ID_* to 64 bit to make space for new ID types
And change file browser to boolean from bitflag enum, which is only 32 bit.

Differential Revision: https://developer.blender.org/D7004
2020-03-03 17:34:21 +01:00
Brecht Van Lommel
19785b96c4 IDs: modify wm.previews_clear operator to make space for new ID types
Use a regular enum, to avoid running out of bits.

Differential Revision: https://developer.blender.org/D7003
2020-03-03 17:22:30 +01:00
Brecht Van Lommel
0c603cffd1 RNA: support 64 bit boolean bitflags in DNA
This does not affect the RNA access API, since how the boolean is read from
DNA abstracted away in the API.

Differential Revision: https://developer.blender.org/D7002
2020-03-03 17:21:47 +01:00
78383f7a9f Fix: USD Build error on windows
USD is being included before the blender headers.

USD includes TBB, which includes the windows headers
which define rad2 as a constant conflicting with a field
with that exact name in the MetaElem dna struct.

Added `-DWIN32_LEAN_AND_MEAN` to keep the windows headers
from defining rad2.
2020-03-03 09:04:31 -07:00
daca00f187 Fix Snake Hook rake on rotated objects
It was missing this local space conversion before calculating the rake
angle.

Reviewed By: jbakker

Differential Revision: https://developer.blender.org/D7008
2020-03-03 16:16:34 +01:00
b39273c071 Fix hardness not resetting when using reset brush
Just add it to the list or properties to reset from DNA_brush_defaults

Reviewed By: jbakker

Differential Revision: https://developer.blender.org/D6992
2020-03-03 16:12:25 +01:00
4b2b5fe4b8 USD: Added support for exporting metaballs
Metaballs are exported as evaluated polygonal mesh.

USDExporterContext::depsgraph was made non-const to allow calling
`BKE_mesh_new_from_object()`. The alternative was to make the depsgraph
parameter of that function const, but that would be too intrusive as
that would require even more functions to accept a const depsgraph
pointer.
2020-03-03 15:34:58 +01:00
453be9cc8a Cleanup: USD, marked overridden function with override
No functional changes.
2020-03-03 15:34:58 +01:00
c60e5211d7 Cleanup: USD, removed unused code
Removed an unused forward declaration.

No functional changes.
2020-03-03 15:34:58 +01:00
594945eb01 Fix T71871: Quadriflow remesh operator don't stack operations
Made an explicit call to the exec function be a blocking call and a call
from invoke (or otherwise) be nonblocking.

Reviewed By: Bastien

Differential Revision: http://developer.blender.org/D7006
2020-03-03 15:30:29 +01:00
1ba4aa37c9 Remove the "use mesh curvature" option from quadriflow
It sometimes caused the solver to get into an seemingly unrecoverable
state and crash. Therefore I will disable this feature for now.
2020-03-03 15:30:29 +01:00
ed29ff944a Fix delaunay triangulation, bad indices for output faces.
If there were merged vertices, sometimes the output faces
had wrong vertex indices. Added a test for this, and fixed.
2020-03-03 08:41:26 -05:00
40343a76c5 Revert "Fix T74110: EEVEE Shadow Pass"
This reverts commit 403bb357ae.
The old implementation matches cycles closer. See T74378
2020-03-03 12:35:50 +01:00
ce2dc6ef2b Cleanup: formatting, spelling 2020-03-03 22:23:10 +11:00
582205c134 Subdiv: Fix/Workaround for surface partial derivatives
Both partial derivatives were evaluated to 0 for a special vertex on
Suzanne model: this is happening on a vertex where two adjacent faces
with 2 common edges are connected (in the nose of Suzanne).

This was breaking multires in this point since tangent matrix is all
zeroes, and hence no displacement can be applied in that vertex.
2020-03-03 12:01:46 +01:00
b454a12233 Separate operators (mesh/curve/armature/gpencil): take user preferences
into account for duplicating actions

Previously actions remained linked after duplication, now this is based
on the User Preferences (PreferencesEdit.use_duplicate_action).

note: default is ON here, so this changes default behavior of separate
operators.

First intuition was to respect _all_ preferences here (e.g. also
duplicating materials if chosen in the User Preferences) but after
consideration this is probably not what the User would expect from such
'modeling' opertions (e.g. separate by loose parts resulting in possibly
many duplicate materials)

Fixes T71038

Maniphest Tasks: T71038

Differential Revision: https://developer.blender.org/D6120
2020-03-03 10:01:20 +01:00
ee7034949f Fix bone envelopes displaying wrong when armature is scaled
Object Scale was not taken into account.

This lead to reports like T74247 where the user scaled the envelope
distance and radii to the supposedly right values inthe viewport, but
these were actually 'wrong' under the hood. Assigning weights from bone
envelopes seemed like it would fail, but this code would actually take
the armature scaling into account when checking envelope distance and
weight.

ref T74247

Maniphest Tasks: T74247

Differential Revision: https://developer.blender.org/D6964
2020-03-03 09:48:04 +01:00
d6fd092495 Fix T74375: grid levels theme preference reset to default 2020-03-03 09:29:19 +01:00
73bd0ef12d Fix dope sheet (Mask mode) keyframe editing not image/clip views
Every key-frame edit was updating all grease pencil & mask data-blocks.

Change the logic to only update edited data-blocks.
2020-03-03 16:53:32 +11:00
8447f45f09 Fix T74292: Dope sheet (Mask mode) keyframe editing misses update 2020-03-03 15:50:11 +11:00
7a875922e7 Cleanup: Use a utility function to obtain the bvh_cache 2020-03-03 00:40:15 -03:00
29716abcd1 Missed in the last commit 2020-03-03 00:20:25 -03:00
3e1aa6cbf3 Transform Snap: Clear 'SnapObjectData' after changes in the geometry
Differential Revision: https://developer.blender.org/D6927
2020-03-03 00:08:16 -03:00
a976fe42ef Revert "Transform Snap: Clear 'SnapObjectData' after changes in the geometry"
This reverts commit fe7c4fb4a2.

It does not work because `mesh_eval_cage` and `mesh_eval_final` always is `NULL` in this case.
2020-03-02 22:12:46 -03:00
c549a9dd46 Fix error parsing XDG path values
Own error in recent changes to parsing.
2020-03-03 11:14:39 +11:00
fe7c4fb4a2 Transform Snap: Clear 'SnapObjectData' after changes in the geometry
Differential Revision: https://developer.blender.org/D6927
2020-03-02 20:59:11 -03:00
5a77748e47 Fix T74377: Weld Modifier destroys vertex groups
Differential Revision: https://developer.blender.org/D6997
2020-03-02 18:44:58 -03:00
98c74c6a6e Fix: Excessive (re)builds of subprojects
Recent refactor external dependencies handling (D6642)
improperly linked all library dependencies with public
linkage rather than interface linkage. Causing excessive
(re)builds of subprojects when not needed.

This patch restores the interface linkage.

Reviewed By: brecht sergey

Differential Revision: https://developer.blender.org/D6983
2020-03-02 12:42:01 -07:00
Stefan Werner
409074aae5 Cycles: add Progressive Multi-Jitter sampling pattern
This sampling pattern is particularly suited to adaptive sampling, and will
be used for that upcoming feature.

Based on "Progressive Multi-Jittered Sample Sequences" by Per Christensen,
Andrew Kensler and Charlie Kilpatrick.

Ref D4686
2020-03-02 16:35:52 +01:00
Valentin
7b8db971d4 Cleanup: Use generics properties for arrow keys navigation (walk-select)
This patch refactors arrow keys navigation to move properties and enum
to generic ED_select_utils.h and property to
WM_operator_properties_select_walk_direction()

No functional change

Reviewed By: Julian Eisel

Differential Revision: https://developer.blender.org/D4771
2020-03-02 16:07:34 +01:00
51bce18b6f Cleanup: make blf header work in C++ 2020-03-02 15:34:17 +01:00
f48b46860b Cleanup: make remaining gpu headers work in C++ 2020-03-02 15:29:09 +01:00
360443a483 Fix T74278: Light, Image Object, and Compositor Backdrop Viewer Node
gizmos are too big

Caused by rB9cac5fa681c5 which fixed the handles for the camera border
gizmo (being much too small)-- which in turn was broken by
rB98e4fbc7cc9e.

Camera border gizmo sets up its matrix_space a bit differently [this is
why we are getting very small values in gizmo_calc_rect_view_scale --
needs more investigation], but instead of breaking it for Light, Image
and Compositor Backdrop, lets just compensate by scaling the Camera
Border Gizmo for now.

Maniphest Tasks: T74278

Differential Revision: https://developer.blender.org/D6991
2020-03-02 15:21:07 +01:00
d8198b27df Cleanup: make remaining imbuf headers work in C++ 2020-03-02 15:20:13 +01:00
680b70f093 Cleanup: make remaining editor include headers work in C++ 2020-03-02 15:09:10 +01:00
5de56f9596 Cleanup: make remaining blenkernel headers work in C++ 2020-03-02 15:07:49 +01:00
cf93b65a65 Cleanup: make remaining blenlib headers work in C++
Differential Revision: https://developer.blender.org/D6988

Reviewers: brecht
2020-03-02 15:05:15 +01:00
Ish Bosamiya
5afa4b1dc8 Fix T65568: sewing and self collision issue
As explained in T65568 by @LucaRood, the self collision system should exclude triangles that are connected by sewing springs.

Differential Revision: https://developer.blender.org/D6911
2020-03-02 11:02:26 -03:00
1648a79036 Fix T74295: Cloth + Internal springs crashes on a non-polygonal geometry
Added check to see if the mesh has any polygons at all.
If there are no polygons, the bvh tree data will consist of null
pointers, so skip internal springs if this is the case.
2020-03-02 15:02:24 +01:00
9c4523b1fd Fix crash when compiling renderpass shader on some AMD drivers
Differential Revision: https://developer.blender.org/D6959
2020-03-02 10:33:45 -03:00
847c091ae8 Shading: Add invert option to Vector Rotate Node
Checkbox to invert rotation angle, suggested by @simonthommes

Differential Revision: https://developer.blender.org/D6932
2020-03-02 12:49:19 +00:00
493c99078a Fix T74362: Material Preview Assert
When using Material Previews not all uniform blocks were filled. This
patch will add the renderpass_block when drawing the background.

Note that I wasn't able to reproduce the issue on my system, but
according the the backtrace it most likely solves the issue. I let the
reporter test.
2020-03-02 13:47:52 +01:00
6fa4581d92 Fix T74334: VSE can't import multiple movie files
Add `directory` RNA property to add operators.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D6986
2020-03-02 13:16:01 +01:00
bd25df3d68 Fix T74335: Text.use_module "Online Manual" leads to TextCurve pages. 2020-03-02 12:05:07 +01:00
c930cd7450 Clay Thumb: Remove hardcoded hardness value
Clay Thumb was using a custom hardness implementation and value to make
it functional. Hardness is now a property of brushes and it is
implemented for all brushes, so this is no longer needed.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D6981
2020-03-02 11:54:54 +01:00
94937984b0 Cleanup: Correct forward declaration 2020-03-02 10:17:38 +01:00
e0ffb911a2 Fix T74299: PyGPUOffscreen Color Management
Color management currently happens after the python handlers. This means
that all common drawing operations needs to happen in SRS. The
PyGPUOffscreen requested that the color management was applied, that
resulted into applying colormanagement twice.

This patch makes sure that PyGPUOffscreen.draw_view3d renders in SRS.
There are more code paths that needs to be checked that the correct
space is being requested.
2020-03-02 09:24:06 +01:00
f78ca97cfc Bevel: Z-Up Custom Profile Orientation
When beveling architectural objects like baseboards or crown mouldings that
may consist of multiple	islands, it's useful if	the orientation	is at least
conistent.

This changes the arbitrary decision of how the orientation should start	at a
chain beginning to use the highest side of the profile in the Z direction.

Reviewed By: howardt

Differential Revision: https://developer.blender.org/D6946
2020-03-01 22:21:51 -06:00
e9e4f6af9e Fix T74320: Sound strip waveforms drawing allows negative volume values
While animating sound strips volume within the graph editor, it is possible to set keyframes to negative values.
The drawing code of waveforms wasn't clamping these values to zero and was instead drawing an "inverted" curve

Author: a.monti

Reviewed By: iss

Differential Revision: https://developer.blender.org/D6971
2020-03-02 02:49:35 +01:00
eaf0528749 Fix .arcconfig not working with latest arcanist version 2020-03-01 22:35:31 +01:00
3db948cffe Fix: Build error on windows.
Use of undefined GSQueue type was causing build errors.
2020-03-01 13:59:51 -07:00
Pablo Dobarro
ff0124418f Sculpt: Hardness brush property
The hardness property moves the brush falloff towards the edges, making
the brush sharper.

This should be the intended way to control the brush falloff instead of
tweaking the falloff curve manually, as it can be mapped to pressure to
make the falloff variable during the stroke.
It is also a good idea to show in the UI that the custom curves is an
advance features and it should almost never be modified when sculpting/
painting unless you want to create some advanced effects. By modifying
the curves freely it is really easy to break the brushes and make them
produce artifacts. This needs to be done in a later after merging the
pending projects to reorganize all the brush properties accordingly.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D6902
2020-03-01 20:05:58 +01:00
fc7fdc5c4e Cleanup: Move pose brush to its own file
Reviewed By: brecht

Differential Revision: https://developer.blender.org/D6973
2020-03-01 19:54:31 +01:00
Pablo Dobarro
233158b555 Fix T74307: Add missing brushes to versioning_defaults
At least a brush under each tool needs to exist by default in the blend
file to reset its properties. If it does not exist, the user needs to
reset it manually.

Reviewed By: brecht

Maniphest Tasks: T74307

Differential Revision: https://developer.blender.org/D6972
2020-03-01 19:37:49 +01:00
Pablo Dobarro
3c9956a3ac Fix T73707: Missing mesh normals update on sculpt undo
When sculpting on multi user data normals needs to be recalculated to
avoid artifacts. I refactored that line to make it more readable.

Reviewed By: brecht

Maniphest Tasks: T73707

Differential Revision: https://developer.blender.org/D6957
2020-03-01 19:35:50 +01:00
Pablo Dobarro
a489d77c5b Fix T74074: Strokes with timer events don't get pressure values
When processing a timer event WM_event_tablet_data returns 0 instead of
the last valid pressure value from the tablet. This always stores the
last pressure value and uses it in case a timer event is being
processed.

Reviewed By: brecht

Maniphest Tasks: T74074

Differential Revision: https://developer.blender.org/D6950
2020-03-01 19:32:01 +01:00
Pablo Dobarro
c04c5ac4f6 Fix T73947: Support radial symmetry in Multiplane Scrape
This includes the following changes:
- Use always the angle stored in the StrokeCache when deforming
- Interpolate between the previous and the new sampled angles
- Calculate the cursor matrix only on the 0 radial symmetry iteration

Reviewed By: brecht

Maniphest Tasks: T73947

Differential Revision: https://developer.blender.org/D6901
2020-03-01 19:29:10 +01:00
f2557d137a Fix problem with Delaunay triangulalation re output mapping.
The array giving original vertex indices should not contain
entries for newly created vertices. Added a test to check this.
2020-03-01 12:25:44 -05:00
Peter Fog
38058833f1 UI: harmonize strip colors in video sequencer
Now only the hue is different between different strip types, with the
saturation the same for all.

Differential Revision: https://developer.blender.org/D6775
2020-03-01 16:20:44 +01:00
Phillip Thomas
6a6ccb26ec Build: show draco library under extern folder in Visual Studio
And other code tweaks to make this library more consistent with others.

Differential Revision: https://developer.blender.org/D6864
2020-03-01 16:19:37 +01:00
24ef1cf07e Fix show large cursor preference not being fully removed and causing warnings 2020-03-01 16:15:25 +01:00
Yevgeny Makarov
821ecbe805 UI: make Save Custom Studio Light pop-ups less wide
Differential Revision: https://developer.blender.org/D6977
2020-03-01 16:09:57 +01:00
Yevgeny Makarov
0373e300ea UI: use dedicated icons for topbar and statusbar in theme preferences
Differential Revision: https://developer.blender.org/D6978
2020-03-01 16:09:26 +01:00
22a8a3b214 Apply patch D6620, Adde tests for Deform modifiers.
This test is authored by Himanshi Kalra (calra).
It requires a new modifers.blend in the svn tests.
2020-02-29 14:07:14 -05:00
cb8b424c6b Made BLI_delaunay_2d_cdt_calc better at tiny feature elimination.
The 'random' unit tests and some examples from the new boolean code
triggered asserts and crashes. This fixes those.
There is a new flag in the input that optionally disables a pass
over input to snap segment edges to other segments.
2020-02-29 13:26:27 -05:00
a52eb7489f Cleanup: Move transform_constraints declarations to its own header 2020-02-28 21:25:47 -03:00
85f980c517 UI: Remove Support for Large Cursors
Removing the 'Large Cursors' option as it is no longer applicable or useful on any platform.

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

Reviewed by Brecht Van Lommel
2020-02-28 08:45:17 -08:00
4a373afa5f Sculpt: Cloth brush
This brush has a simple physics solver that helps when sculpting cloth.

- The mass and the damping properties of the simulation are properties of the brush.
- It has two additional radius control to limit the influence and falloff of the simulation.
- Masked vertices are pinned in the simulation, and it applies the sculpt gravity directly in the solver.
- The Cloth Brush has 7 deformation modes with 2 falloff types (radial and plane).

The brush can create the constraints only on the required PBVH nodes, so the simulation is isolated on high poly meshes. As long
as the brush size is not too big it should be possible to keep it real time.

Known issues:
- The way constraints are created is extremely basic and it creates repeated constraints. Maybe there is another way to create fewer constraints while keeping the simulation quality decent. This part can also be multithreaded. (As it is it works ok, but it could be better)

Reviewed By: jbakker

Differential Revision: https://developer.blender.org/D6715
2020-02-28 17:03:20 +01:00
793135e190 Fix wrong coordinates being read when using the sculpt API
The coordinates should be read from the PBVH when using deform modifiers.
This is needed for the cloth brush to work with subdivisions, as it reads the
vertex coordinates using this function when building and updating the
constraints.

Reviewed By: jbakker

Differential Revision: https://developer.blender.org/D6967
2020-02-28 16:53:34 +01:00
bc2ce31d79 Fluid: Improved behavior at open boundaries
Use greater boundary width for smoke simulations
2020-02-28 16:20:13 +01:00
21bdeb5cc0 Fluid: Updated Manta pp files
Updates include:
- std::move() cleanup in rcmatrix.h
- Enabled parallelization for fluid guiding (fairly noticeable speed improvement).
- More flexible flags setter function with control over boundary width.
2020-02-28 16:20:13 +01:00
af54bbd61c Cycles: Rework tile scheduling for denoising
This fixes denoising being delayed until after all rendering has finished. Instead, tile-based
denoising is now part of the "RENDER" task again, so that it is all in one task and does not
cause issues with dedicated task pools where tasks are serialized.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D6940
2020-02-28 16:12:29 +01:00
03e04d4db7 Cleanup: clang-format 2020-02-28 16:04:15 +01:00
Yevgeny Makarov
fe3ce61528 Fix T65351: visual glitches when scrolling in popovers 2020-02-28 16:03:53 +01:00
0cea9353fd Fix CUDA out of memory error with OptiX viewport denoising on small GPUs
This makes the memory allocation for the denoiser state use the memory allocator in Cycles, which
will evict textures to host memory when there is not enough space on the device. This means the
allocation for the denoiser state won't just fail if there is no more space and instead more space is
made for it to work. Also simplifies code somewhat.
2020-02-28 15:58:17 +01:00
Yevgeny Makarov
27fa33c143 Fix T72404: particle brush size radial control mismatch on high DPI display 2020-02-28 15:55:51 +01:00
498397f7bd Fix (unreported) Separate bones creates empty armature
Fix for fix (rB8bf7ca9fe31c).
The fix was not actually working [neither for multi-armature-editing as
intended nor for single armatures] and it broke single-armature bone
separation completely.

More or less indentation issue, move relevant code out of bone loop, do
after all bones have been checked, guess this was intended anyways.

Differential Revision: https://developer.blender.org/D6949
2020-02-28 15:26:57 +01:00
4c83e6bac0 Fix T71611: Outliner - Show only Visible/Hidden Objects not working when hiding Collections
Use BASE_VISIBLE_VIEWLAYER (rather than BASE_VISIBLE_DEPSGRAPH -- which
is not including the 'Hide in Viewport')

Note: the is one case where this still 'fails':
- 'Show only Hidden' plus excluding the parent collection (would be nice
to show those -- but contents of excluded excluded collections dont get
show in any case... this would be more work and for another report...)

Maniphest Tasks: T71611

Differential Revision: https://developer.blender.org/D6953
2020-02-28 15:20:59 +01:00
94dcfe7a77 Preview Render: Disable Unneeded Render Passes 2020-02-28 14:46:40 +01:00
e8ab0137f8 File Browser: Add Ctrl+F shortcut to activate filter textbox
Reviewers: Severin, brecht

Differential Revision: https://developer.blender.org/D6941
2020-02-28 14:34:56 +01:00
e0f41d32c9 Code Cleanup: UNDEF not existing define 2020-02-28 14:31:46 +01:00
bcac081ad5 OpenSubdiv: Allow less topology callbacks assigned
Useful for cases when topology does not need to have any
crease or UV layers. Now instead of assigning callbacks
which returns zero data is possible to simply assign the
callback itself to NULL.
2020-02-28 14:30:49 +01:00
95d0e04ed1 BLI: fix utf8 character counting when there is an incomplete utf8 char
D6923 by Kim Geonwoo
2020-02-28 14:26:07 +01:00
Pawel Franitza
2269759fdf UI: add theme option for grid levels to display in node editor background
Differential Revision: https://developer.blender.org/D6916
2020-02-28 14:11:48 +01:00
Yevgeny Makarov
e287122af6 UI: improve label text colors in save and security popups
This adds a utility functions to draw a label highlighted or in red.

Differential Revision: https://developer.blender.org/D6934
2020-02-28 13:57:32 +01:00
Brecht Van Lommel
318112379d Objects: make evaluated data runtime storage usable for types other than mesh
This is in preparation of new object types. This only changes mesh_eval, we
may do the same for mesh_deform_eval and other areas in the future if there is
a need for it.

This previously caused a bug in T74283, that should be fixed now.

Differential Revision: https://developer.blender.org/D6695
2020-02-28 13:49:35 +01:00
c60be37f3e Nodes: Use destructor callbacks for bNodeSocketType and bNodeType
Reviewers: brecht

Differential Revision: https://developer.blender.org/D6963
2020-02-28 13:28:16 +01:00
da1140f75e Revert "Objects: make evaluated data runtime storage usable for types other than mesh"
This reverts commit f2b95b9eae.

Fix T74283: modifier display lost when moving object in edit mode.

The cause is not immediately obvious so better to revert and look at this
carefully.
2020-02-28 13:01:02 +01:00
7a8a074a30 Multires: Move current reshaping/propagation logic to legacy file
It will eventually rewritten.
This commit prepares some clean space to start this process.

So far no functional changes.
2020-02-28 12:42:27 +01:00
Tobias Langen
8e8b4ec3a3 Fix T73587: Wrong sub-panel animation on double-click
Under the special circumstance of double clicking and then opening a
panel with sub-panels again, the parent panel's offset in y-direction
was added twice to the child panels: once inside "get_panel_real_ofsy"
and once within "align_sub_panels".
This introduced a visible glitch.

Reviewed by: Julian Eisel

Differential Revision: https://developer.blender.org/D6942
2020-02-28 12:39:11 +01:00
1eb73d1596 Multires: Fix CCG->MDISPS conversion happens twice
Was happening when leaving sculpt mode, introducing unnecessary lag
to the operation.
2020-02-28 12:24:26 +01:00
944da82eaf Multires: Cleanup, use early return 2020-02-28 12:24:26 +01:00
feead324fd Multires: Cleanup, naming 2020-02-28 12:24:26 +01:00
Julian Eisel
d9c25f0192 UI: Move menu shadow theme options next to each other
For some reason they were separated, even though they are closely
related.
2020-02-28 11:36:25 +01:00
9a855f94fc Cleanup: Spelling 2020-02-28 10:12:08 +01:00
4c4d36c25e Subdiv: Correct corner passed to foreach_loop callback
Was affecting quad faces. where 0 was always passed for inner
loops and a wrong one for boundary ones.

In the current code this change shouldn't cause any difference
since the corner index is ignored in the actual callback, but
it is required to have his fixed for an upcoming changes.
2020-02-28 10:12:08 +01:00
1679 changed files with 44193 additions and 63531 deletions

View File

@@ -1,6 +1,7 @@
{
"project_id" : "Blender",
"conduit_uri" : "https://developer.blender.org/",
"phabricator.uri" : "https://developer.blender.org/",
"git.default-relative-commit" : "origin/master",
"arc.land.update.default" : "rebase",
"arc.land.onto.default" : "master"

View File

@@ -180,6 +180,15 @@ option(WITH_BULLET "Enable Bullet (Physics Engine)" ON)
option(WITH_SYSTEM_BULLET "Use the systems bullet library (currently unsupported due to missing features in upstream!)" )
mark_as_advanced(WITH_SYSTEM_BULLET)
option(WITH_OPENCOLORIO "Enable OpenColorIO color management" ON)
if(APPLE)
# There's no OpenXR runtime in sight for macOS, neither is code well
# tested there -> disable it by default.
option(WITH_XR_OPENXR "Enable VR features through the OpenXR specification" OFF)
mark_as_advanced(WITH_XR_OPENXR)
else()
# Disabled until there's more than just the build system stuff. Should be enabled soon.
option(WITH_XR_OPENXR "Enable VR features through the OpenXR specification" OFF)
endif()
# Compositor
option(WITH_COMPOSITOR "Enable the tile based nodal compositor" ON)
@@ -633,6 +642,9 @@ set_and_warn_dependency(WITH_TBB WITH_OPENIMAGEDENOISE OFF)
set_and_warn_dependency(WITH_TBB WITH_OPENVDB OFF)
set_and_warn_dependency(WITH_TBB WITH_MOD_FLUID OFF)
# OpenVDB uses 'half' type from OpenEXR & fails to link without OpenEXR enabled.
set_and_warn_dependency(WITH_IMAGE_OPENEXR WITH_OPENVDB OFF)
# auto enable openimageio for cycles
if(WITH_CYCLES)
set(WITH_OPENIMAGEIO ON)
@@ -1695,6 +1707,7 @@ if(FIRST_RUN)
info_cfg_option(WITH_CYCLES)
info_cfg_option(WITH_FREESTYLE)
info_cfg_option(WITH_OPENCOLORIO)
info_cfg_option(WITH_XR_OPENXR)
info_cfg_option(WITH_OPENIMAGEDENOISE)
info_cfg_option(WITH_OPENVDB)
info_cfg_option(WITH_ALEMBIC)

View File

@@ -99,6 +99,7 @@ else()
endif()
include(cmake/openimagedenoise.cmake)
include(cmake/embree.cmake)
include(cmake/xr_openxr.cmake)
if(WITH_WEBP)
include(cmake/webp.cmake)

View File

@@ -161,6 +161,8 @@ harvest(opensubdiv/include opensubdiv/include "*.h")
harvest(opensubdiv/lib opensubdiv/lib "*.a")
harvest(openvdb/include/openvdb openvdb/include/openvdb "*.h")
harvest(openvdb/lib openvdb/lib "*.a")
harvest(xr_openxr_sdk/include/openxr xr_openxr_sdk/include/openxr "*.h")
harvest(xr_openxr_sdk/lib xr_openxr_sdk/src/loader "*.a")
harvest(osl/bin osl/bin "oslc")
harvest(osl/include osl/include "*.h")
harvest(osl/lib osl/lib "*.a")

View File

@@ -318,3 +318,7 @@ set(LIBGLU_HASH 151aef599b8259efe9acd599c96ea2a3)
set(MESA_VERSION 18.3.1)
set(MESA_URI ftp://ftp.freedesktop.org/pub/mesa//mesa-${MESA_VERSION}.tar.xz)
set(MESA_HASH d60828056d77bfdbae0970f9b15fb1be)
set(XR_OPENXR_SDK_VERSION 1.0.6)
set(XR_OPENXR_SDK_URI https://github.com/KhronosGroup/OpenXR-SDK/archive/release-${XR_OPENXR_SDK_VERSION}.tar.gz)
set(XR_OPENXR_SDK_HASH 21daea7c3bfec365298d779a0e19caa1)

View File

@@ -0,0 +1,58 @@
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ***** END GPL LICENSE BLOCK *****
# Keep flags in sync with install_deps.sh ones in compile_XR_OpenXR_SDK()
set(XR_OPENXR_SDK_EXTRA_ARGS
-DBUILD_FORCE_GENERATION=OFF
-DBUILD_LOADER=ON
-DDYNAMIC_LOADER=OFF
)
if(UNIX AND NOT APPLE)
list(APPEND XR_OPENXR_SDK_EXTRA_ARGS
-DBUILD_WITH_WAYLAND_HEADERS=OFF
-DBUILD_WITH_XCB_HEADERS=OFF
-DBUILD_WITH_XLIB_HEADERS=ON
)
endif()
ExternalProject_Add(external_xr_openxr_sdk
URL ${XR_OPENXR_SDK_URI}
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH MD5=${XR_OPENXR_SDK_HASH}
PREFIX ${BUILD_DIR}/xr_openxr_sdk
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/xr_openxr_sdk ${DEFAULT_CMAKE_FLAGS} ${XR_OPENXR_SDK_EXTRA_ARGS}
INSTALL_DIR ${LIBDIR}/xr_openxr_sdk
)
if(WIN32)
if(BUILD_MODE STREQUAL Release)
ExternalProject_Add_Step(external_xr_openxr_sdk after_install
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/xr_openxr_sdk/include/openxr ${HARVEST_TARGET}/xr_openxr_sdk/include/openxr
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/xr_openxr_sdk/lib ${HARVEST_TARGET}/xr_openxr_sdk/lib
DEPENDEES install
)
endif()
if(BUILD_MODE STREQUAL Debug)
ExternalProject_Add_Step(external_xr_openxr_sdk after_install
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/xr_openxr_sdk/lib/openxr_loader.lib ${HARVEST_TARGET}/xr_openxr_sdk/lib/openxr_loader_d.lib
DEPENDEES install
)
endif()
endif()

View File

@@ -52,16 +52,19 @@ getopt \
-o s:i:t:h \
--long source:,install:,tmp:,info:,threads:,help,show-deps,no-sudo,no-build,no-confirm,\
with-all,with-opencollada,with-jack,with-embree,with-oidn,\
ver-ocio:,ver-oiio:,ver-llvm:,ver-osl:,ver-osd:,ver-openvdb:,\
ver-ocio:,ver-oiio:,ver-llvm:,ver-osl:,ver-osd:,ver-openvdb:,ver-xr-openxr:,\
force-all,force-python,force-numpy,force-boost,\
force-ocio,force-openexr,force-oiio,force-llvm,force-osl,force-osd,force-openvdb,\
force-ffmpeg,force-opencollada,force-alembic,force-embree,force-oidn,force-usd,\
force-xr-openxr,\
build-all,build-python,build-numpy,build-boost,\
build-ocio,build-openexr,build-oiio,build-llvm,build-osl,build-osd,build-openvdb,\
build-ffmpeg,build-opencollada,build-alembic,build-embree,build-oidn,build-usd,\
build-xr-openxr,\
skip-python,skip-numpy,skip-boost,\
skip-ocio,skip-openexr,skip-oiio,skip-llvm,skip-osl,skip-osd,skip-openvdb,\
skip-ffmpeg,skip-opencollada,skip-alembic,skip-embree,skip-oidn,skip-usd \
skip-ffmpeg,skip-opencollada,skip-alembic,skip-embree,skip-oidn,skip-usd, \
skip-xr-openxr\
-- "$@" \
)
@@ -169,6 +172,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
--ver-openvdb=<ver>
Force version of OpenVDB library.
--ver-xr-openxr=<ver>
Force version of OpenXR-SDK.
Note about the --ver-foo options:
It may not always work as expected (some libs are actually checked out from a git rev...), yet it might help
to fix some build issues (like LLVM mismatch with the version used by your graphic system).
@@ -224,6 +230,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
--build-usd
Force the build of Universal Scene Description.
--build-xr-openxr
Force the build of OpenXR-SDK.
Note about the --build-foo options:
* They force the script to prefer building dependencies rather than using available packages.
This may make things simpler and allow working around some distribution bugs, but on the other hand it will
@@ -285,6 +294,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
--force-usd
Force the rebuild of Universal Scene Description.
--force-xr-openxr
Force the rebuild of OpenXR-SDK.
Note about the --force-foo options:
* They obviously only have an effect if those libraries are built by this script
(i.e. if there is no available and satisfactory package)!
@@ -337,7 +349,10 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
Unconditionally skip FFMpeg installation/building.
--skip-usd
Unconditionally skip Universal Scene Description installation/building.\""
Unconditionally skip Universal Scene Description installation/building.
--skip-xr-openxr
Unconditionally skip OpenXR-SDK installation/building.\""
# ----------------------------------------------------------------------------
# Main Vars
@@ -454,6 +469,11 @@ FFMPEG_FORCE_REBUILD=false
FFMPEG_SKIP=false
_ffmpeg_list_sep=";"
XR_OPENXR_VERSION="1.0.6"
XR_OPENXR_FORCE_BUILD=false
XR_OPENXR_FORCE_REBUILD=false
XR_OPENXR_SKIP=false
# FFMPEG optional libs.
VORBIS_USE=false
VORBIS_DEV=""
@@ -624,6 +644,11 @@ while true; do
OPENVDB_VERSION_MIN=$OPENVDB_VERSION
shift; shift; continue
;;
--ver-xr-openxr)
XR_OPENXR_VERSION="$2"
XR_OPENXR_VERSION_MIN=$XR_OPENXR_VERSION
shift; shift; continue
;;
--build-all)
PYTHON_FORCE_BUILD=true
NUMPY_FORCE_BUILD=true
@@ -641,6 +666,7 @@ while true; do
FFMPEG_FORCE_BUILD=true
ALEMBIC_FORCE_BUILD=true
USD_FORCE_BUILD=true
XR_OPENXR_FORCE_BUILD=true
shift; continue
;;
--build-python)
@@ -695,6 +721,9 @@ while true; do
--build-usd)
USD_FORCE_BUILD=true; shift; continue
;;
--build-xr-openxr)
XR_OPENXR_FORCE_BUILD=true; shift; continue
;;
--force-all)
PYTHON_FORCE_REBUILD=true
NUMPY_FORCE_REBUILD=true
@@ -712,6 +741,7 @@ while true; do
FFMPEG_FORCE_REBUILD=true
ALEMBIC_FORCE_REBUILD=true
USD_FORCE_REBUILD=true
XR_OPENXR_FORCE_REBUILD=true
shift; continue
;;
--force-python)
@@ -764,6 +794,9 @@ while true; do
--force-usd)
USD_FORCE_REBUILD=true; shift; continue
;;
--force-xr-openxr)
XR_OPENXR_FORCE_REBUILD=true; shift; continue
;;
--skip-python)
PYTHON_SKIP=true; shift; continue
;;
@@ -812,6 +845,9 @@ while true; do
--skip-usd)
USD_SKIP=true; shift; continue
;;
--skip-xr-openxr)
XR_OPENXR_SKIP=true; shift; continue
;;
--)
# no more arguments to parse
break
@@ -940,6 +976,12 @@ OIDN_SOURCE=( "https://github.com/OpenImageDenoise/oidn/releases/download/v${OID
FFMPEG_SOURCE=( "http://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2" )
XR_OPENXR_USE_REPO=false
XR_OPENXR_SOURCE=("https://github.com/KhronosGroup/OpenXR-SDK/archive/release-${XR_OPENXR_VERSION}.tar.gz")
#~ XR_OPENXR_SOURCE_REPO=("https://github.com/KhronosGroup/OpenXR-SDK-Source.git")
#~ XR_OPENXR_REPO_UID="5292e57fda47561e672fba0a4b6e545c0f25dd8d"
#~ XR_OPENXR_REPO_BRANCH="master"
# C++11 is required now
CXXFLAGS_BACK=$CXXFLAGS
CXXFLAGS="$CXXFLAGS -std=c++11"
@@ -982,7 +1024,8 @@ You may also want to build them yourself (optional ones are [between brackets]):
* [Embree $EMBREE_VERSION] (from $EMBREE_SOURCE).
* [OpenImageDenoise $OIDN_VERSION] (from $OIDN_SOURCE).
* [Alembic $ALEMBIC_VERSION] (from $ALEMBIC_SOURCE).
* [Universal Scene Description $USD_VERSION] (from $USD_SOURCE).\""
* [Universal Scene Description $USD_VERSION] (from $USD_SOURCE).
* [OpenXR-SDK $XR_OPENXR_VERSION] (from $XR_OPENXR_SOURCE).\""
if [ "$DO_SHOW_DEPS" = true ]; then
PRINT ""
@@ -3058,6 +3101,116 @@ compile_FFmpeg() {
fi
}
# ----------------------------------------------------------------------------
# Build OpenXR SDK
_init_xr_openxr_sdk() {
_src=$SRC/XR-OpenXR-SDK-$XR_OPENXR_VERSION
_git=true
_inst=$INST/xr-openxr-sdk-$XR_OPENXR_VERSION
_inst_shortcut=$INST/xr-openxr-sdk
}
_update_deps_xr_openxr_sdk() {
:
}
clean_XR_OpenXR_SDK() {
_init_xr_openxr_sdk
_clean
_update_deps_xr_openxr_sdk
}
compile_XR_OpenXR_SDK() {
if [ "$NO_BUILD" = true ]; then
WARNING "--no-build enabled, OpenXR will not be compiled!"
return
fi
# To be changed each time we make edits that would modify the compiled result!
xr_openxr_magic=0
_init_xr_openxr_sdk
# Clean install if needed!
magic_compile_check xr-openxr-$OPENXR_VERSION $xr_openxr_magic
if [ $? -eq 1 -o "$XR_OPENXR_FORCE_REBUILD" = true ]; then
clean_XR_OpenXR_SDK
fi
if [ ! -d $_inst ]; then
INFO "Building XR-OpenXR-SDK-$XR_OPENXR_VERSION"
_is_building=true
# Rebuild dependencies as well!
_update_deps_xr_openxr_sdk
prepare_opt
if [ ! -d $_src ]; then
mkdir -p $SRC
if [ "$XR_OPENXR_USE_REPO" = true ]; then
git clone $XR_OPENXR_SOURCE_REPO $_src
else
download XR_OPENXR_SOURCE[@] "$_src.tar.gz"
INFO "Unpacking XR-OpenXR-SDK-$XR_OPENXR_VERSION"
tar -C $SRC --transform "s,(.*/?)OpenXR-SDK-[^/]*(.*),\1XR-OpenXR-SDK-$XR_OPENXR_VERSION\2,x" \
-xf $_src.tar.gz
fi
fi
cd $_src
if [ "$XR_OPENXR_USE_REPO" = true ]; then
git pull origin $XR_OPENXR_REPO_BRANCH
# Stick to same rev as windows' libs...
git checkout $XR_OPENXR_REPO_UID
git reset --hard
fi
# Always refresh the whole build!
if [ -d build ]; then
rm -rf build
fi
mkdir build
cd build
# Keep flags in sync with XR_OPENXR_SDK_EXTRA_ARGS in xr_openxr.cmake!
cmake_d="-D CMAKE_BUILD_TYPE=Release"
cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst"
cmake_d="$cmake_d -D BUILD_FORCE_GENERATION=OFF"
cmake_d="$cmake_d -D BUILD_LOADER=ON"
cmake_d="$cmake_d -D DYNAMIC_LOADER=OFF"
cmake_d="$cmake_d -D BUILD_WITH_WAYLAND_HEADERS=OFF"
cmake_d="$cmake_d -D BUILD_WITH_XCB_HEADERS=OFF"
cmake_d="$cmake_d -D BUILD_WITH_XLIB_HEADERS=ON"
cmake $cmake_d ..
make -j$THREADS && make install
make clean
if [ -d $_inst ]; then
_create_inst_shortcut
else
ERROR "XR-OpenXR-SDK-$XR_OPENXR_VERSION failed to compile, exiting"
exit 1
fi
magic_compile_set xr-openxr-$XR_OPENXR_VERSION $xr_openxr_magic
cd $CWD
INFO "Done compiling XR-OpenXR-SDK-$XR_OPENXR_VERSION!"
_is_building=false
else
INFO "Own XR-OpenXR-SDK-$XR_OPENXR_VERSION is up to date, nothing to do!"
INFO "If you want to force rebuild of this lib, use the --force-xr-openxr option."
fi
run_ldconfig "xr-openxr-sdk"
}
# ----------------------------------------------------------------------------
# Install on DEB-like
@@ -3602,6 +3755,18 @@ install_DEB() {
compile_FFmpeg
fi
fi
PRINT ""
if [ "$XR_OPENXR_SKIP" = true ]; then
WARNING "Skipping OpenXR-SDK installation, as requested..."
elif [ "$XR_OPENXR_FORCE_BUILD" = true ]; then
INFO "Forced OpenXR-SDK building, as requested..."
compile_XR_OpenXR_SDK
else
# No package currently!
PRINT ""
compile_XR_OpenXR_SDK
fi
}
@@ -4208,6 +4373,17 @@ install_RPM() {
compile_FFmpeg
fi
fi
PRINT ""
if [ "$XR_OPENXR_SKIP" = true ]; then
WARNING "Skipping OpenXR-SDK installation, as requested..."
elif [ "$XR_OPENXR_FORCE_BUILD" = true ]; then
INFO "Forced OpenXR-SDK building, as requested..."
compile_XR_OpenXR_SDK
else
# No package currently!
compile_XR_OpenXR_SDK
fi
}
@@ -4709,6 +4885,17 @@ install_ARCH() {
compile_FFmpeg
fi
fi
PRINT ""
if [ "$XR_OPENXR_SKIP" = true ]; then
WARNING "Skipping OpenXR-SDK installation, as requested..."
elif [ "$XR_OPENXR_FORCE_BUILD" = true ]; then
INFO "Forced OpenXR-SDK building, as requested..."
compile_XR_OpenXR_SDK
else
# No package currently!
compile_XR_OpenXR_SDK
fi
}
@@ -4906,6 +5093,17 @@ install_OTHER() {
INFO "Forced FFMpeg building, as requested..."
compile_FFmpeg
fi
PRINT ""
if [ "$XR_OPENXR_SKIP" = true ]; then
WARNING "Skipping OpenXR-SDK installation, as requested..."
elif [ "$XR_OPENXR_FORCE_BUILD" = true ]; then
INFO "Forced OpenXR-SDK building, as requested..."
compile_XR_OpenXR_SDK
else
# No package currently!
compile_XR_OpenXR_SDK
fi
}
# ----------------------------------------------------------------------------
@@ -5174,6 +5372,17 @@ print_info() {
fi
fi
if [ "$XR_OPENXR_SKIP" = false ]; then
_1="-D WITH_XR_OPENXR=ON"
PRINT " $_1"
_buildargs="$_buildargs $_1"
if [ -d $INST/xr-openxr-sdk ]; then
_1="-D XR_OPENXR_ROOT_DIR=$INST/xr-openxr-sdk"
PRINT " $_1"
_buildargs="$_buildargs $_1"
fi
fi
PRINT ""
PRINT "Or even simpler, just run (in your blender-source dir):"
PRINT " make -j$THREADS BUILD_CMAKE_ARGS=\"$_buildargs\""

View File

@@ -49,7 +49,6 @@ if(NOT LLVM_ROOT_DIR)
OUTPUT_VARIABLE LLVM_ROOT_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE)
set(LLVM_ROOT_DIR ${LLVM_ROOT_DIR} CACHE PATH "Path to the LLVM installation")
set(LLVM_INCLUDE_DIRS ${LLVM_ROOT_DIR}/include CACHE PATH "Path to the LLVM include directory")
endif()
if(NOT LLVM_LIBPATH)
execute_process(COMMAND ${LLVM_CONFIG} --libdir

View File

@@ -0,0 +1,73 @@
# - Find OpenXR-SDK libraries
# Find the native OpenXR-SDK includes and libraries
#
# Note that there is a distinction between the OpenXR standard and the SDK. The
# latter provides utilities to use the standard but is not part of it. Most
# importantly, it contains C headers and a loader library, which manages
# dynamic linking to OpenXR runtimes like Monado, Windows Mixed Reality or
# Oculus. See the repository for more details:
# https://github.com/KhronosGroup/OpenXR-SDK
#
# This module defines
# XR_OPENXR_SDK_INCLUDE_DIRS, where to find OpenXR-SDK headers, Set when
# XR_OPENXR_SDK_INCLUDE_DIR is found.
# XR_OPENXR_SDK_LIBRARIES, libraries to link against to use OpenXR.
# XR_OPENXR_SDK_ROOT_DIR, the base directory to search for OpenXR-SDK.
# This can also be an environment variable.
# XR_OPENXR_SDK_FOUND, if false, do not try to use OpenXR-SDK.
#
# also defined, but not for general use are
# XR_OPENXR_SDK_LOADER_LIBRARY, where to find the OpenXR-SDK loader library.
#=============================================================================
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# If XR_OPENXR_SDK_ROOT_DIR was defined in the environment, use it.
IF(NOT XR_OPENXR_SDK_ROOT_DIR AND NOT $ENV{XR_OPENXR_SDK_ROOT_DIR} STREQUAL "")
SET(XR_OPENXR_SDK_ROOT_DIR $ENV{XR_OPENXR_SDK_ROOT_DIR})
ENDIF()
SET(_xr_openxr_sdk_SEARCH_DIRS
${XR_OPENXR_SDK_ROOT_DIR}
/opt/lib/xr-openxr-sdk
)
FIND_PATH(XR_OPENXR_SDK_INCLUDE_DIR
NAMES
openxr/openxr.h
HINTS
${_xr_openxr_sdk_SEARCH_DIRS}
PATH_SUFFIXES
include
)
FIND_LIBRARY(XR_OPENXR_SDK_LOADER_LIBRARY
NAMES
openxr_loader
HINTS
${_xr_openxr_sdk_SEARCH_DIRS}
PATH_SUFFIXES
lib64 lib
)
# handle the QUIETLY and REQUIRED arguments and set XR_OPENXR_SDK_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(XR_OPENXR_SDK DEFAULT_MSG
XR_OPENXR_SDK_LOADER_LIBRARY XR_OPENXR_SDK_INCLUDE_DIR)
IF(XR_OPENXR_SDK_FOUND)
SET(XR_OPENXR_SDK_LIBRARIES ${XR_OPENXR_SDK_LOADER_LIBRARY})
SET(XR_OPENXR_SDK_INCLUDE_DIRS ${XR_OPENXR_SDK_INCLUDE_DIR})
ENDIF(XR_OPENXR_SDK_FOUND)
MARK_AS_ADVANCED(
XR_OPENXR_SDK_INCLUDE_DIR
XR_OPENXR_SDK_LOADER_LIBRARY
)

View File

@@ -61,3 +61,6 @@ if(UNIX AND NOT APPLE)
set(WITH_X11_XINPUT ON CACHE BOOL "" FORCE)
set(WITH_X11_XF86VMODE ON CACHE BOOL "" FORCE)
endif()
if(NOT APPLE)
set(WITH_XR_OPENXR ON CACHE BOOL "" FORCE)
endif()

View File

@@ -44,6 +44,7 @@ set(WITH_OPENAL OFF CACHE BOOL "" FORCE)
set(WITH_OPENCOLLADA OFF CACHE BOOL "" FORCE)
set(WITH_OPENCOLORIO OFF CACHE BOOL "" FORCE)
set(WITH_OPENIMAGEDENOISE OFF CACHE BOOL "" FORCE)
set(WITH_XR_OPENXR OFF CACHE BOOL "" FORCE)
set(WITH_OPENIMAGEIO OFF CACHE BOOL "" FORCE)
set(WITH_OPENMP OFF CACHE BOOL "" FORCE)
set(WITH_OPENSUBDIV OFF CACHE BOOL "" FORCE)

View File

@@ -65,3 +65,6 @@ if(UNIX AND NOT APPLE)
set(WITH_X11_XINPUT ON CACHE BOOL "" FORCE)
set(WITH_X11_XF86VMODE ON CACHE BOOL "" FORCE)
endif()
if(NOT APPLE)
set(WITH_XR_OPENXR ON CACHE BOOL "" FORCE)
endif()

View File

@@ -122,7 +122,7 @@ function(target_link_libraries_optimized
)
foreach(_LIB ${LIBS})
target_link_libraries(${TARGET} optimized "${_LIB}")
target_link_libraries(${TARGET} INTERFACE optimized "${_LIB}")
endforeach()
endfunction()
@@ -132,7 +132,7 @@ function(target_link_libraries_debug
)
foreach(_LIB ${LIBS})
target_link_libraries(${TARGET} debug "${_LIB}")
target_link_libraries(${TARGET} INTERFACE debug "${_LIB}")
endforeach()
endfunction()
@@ -170,6 +170,7 @@ function(blender_include_dirs_sys
endfunction()
function(blender_source_group
name
sources
)
@@ -205,6 +206,13 @@ function(blender_source_group
source_group("${GROUP_ID}" FILES ${_SRC})
endforeach()
endif()
# if enabled, set the FOLDER property for visual studio projects
if(WINDOWS_USE_VISUAL_STUDIO_PROJECT_FOLDERS)
get_filename_component(FolderDir ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY)
string(REPLACE ${CMAKE_SOURCE_DIR} "" FolderDir ${FolderDir})
set_target_properties(${name} PROPERTIES FOLDER ${FolderDir})
endif()
endfunction()
@@ -295,11 +303,11 @@ function(blender_add_lib__impl
set(next_library_mode "${library_lower}")
else()
if("${next_library_mode}" STREQUAL "optimized")
target_link_libraries(${name} optimized ${library})
target_link_libraries(${name} INTERFACE optimized ${library})
elseif("${next_library_mode}" STREQUAL "debug")
target_link_libraries(${name} debug ${library})
target_link_libraries(${name} INTERFACE debug ${library})
else()
target_link_libraries(${name} ${library})
target_link_libraries(${name} INTERFACE ${library})
endif()
set(next_library_mode "")
endif()
@@ -308,14 +316,7 @@ function(blender_add_lib__impl
# works fine without having the includes
# listed is helpful for IDE's (QtCreator/MSVC)
blender_source_group("${sources}")
# if enabled, set the FOLDER property for visual studio projects
if(WINDOWS_USE_VISUAL_STUDIO_PROJECT_FOLDERS)
get_filename_component(FolderDir ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY)
string(REPLACE ${CMAKE_SOURCE_DIR} "" FolderDir ${FolderDir})
set_target_properties(${name} PROPERTIES FOLDER ${FolderDir})
endif()
blender_source_group("${name}" "${sources}")
list_assert_duplicates("${sources}")
list_assert_duplicates("${includes}")
@@ -946,7 +947,7 @@ function(data_to_c_simple
set_source_files_properties(${_file_to} PROPERTIES GENERATED TRUE)
endfunction()
# macro for converting pixmap directory to a png and then a c file
# Function for converting pixmap directory to a '.png' and then a '.c' file.
function(data_to_c_simple_icons
path_from icon_prefix icon_names
list_to_add
@@ -1159,12 +1160,12 @@ macro(blender_precompile_headers target cpp header)
endmacro()
macro(set_and_warn_dependency
_dependency _setting _val)
# when $_dependency is disabled, forces $_setting = $_val
if(NOT ${${_dependency}} AND ${${_setting}})
message(STATUS "'${_dependency}' is disabled: forcing 'set(${_setting} ${_val})'")
set(${_setting} ${_val})
endif()
_dependency _setting _val)
# when $_dependency is disabled, forces $_setting = $_val
if(NOT ${${_dependency}} AND ${${_setting}})
message(STATUS "'${_dependency}' is disabled: forcing 'set(${_setting} ${_val})'")
set(${_setting} ${_val})
endif()
endmacro()
macro(without_system_libs_begin)

View File

@@ -411,11 +411,21 @@ if(WITH_OPENMP)
# Copy libomp.dylib to allow executables like datatoc and tests to work.
execute_process(
COMMAND mkdir -p ${CMAKE_BINARY_DIR}/Resources/lib
COMMAND cp -p ${LIBDIR}/openmp/lib/libomp.dylib ${CMAKE_BINARY_DIR}/Resources/lib/libomp.dylib)
COMMAND mkdir -p ${CMAKE_BINARY_DIR}/Resources/lib
COMMAND cp -p ${LIBDIR}/openmp/lib/libomp.dylib ${CMAKE_BINARY_DIR}/Resources/lib/libomp.dylib
)
execute_process(
COMMAND mkdir -p ${CMAKE_BINARY_DIR}/bin/Resources/lib
COMMAND cp -p ${LIBDIR}/openmp/lib/libomp.dylib ${CMAKE_BINARY_DIR}/bin/Resources/lib/libomp.dylib)
COMMAND mkdir -p ${CMAKE_BINARY_DIR}/bin/Resources/lib
COMMAND cp -p ${LIBDIR}/openmp/lib/libomp.dylib ${CMAKE_BINARY_DIR}/bin/Resources/lib/libomp.dylib
)
endif()
endif()
if(WITH_XR_OPENXR)
find_package(OpenXR-SDK)
if(NOT OPENXR_SDK_FOUND)
message(WARNING "OpenXR-SDK was not found, disabling WITH_XR_OPENXR")
set(WITH_XR_OPENXR OFF)
endif()
endif()

View File

@@ -428,6 +428,14 @@ if(WITH_TBB)
find_package_wrapper(TBB)
endif()
if(WITH_XR_OPENXR)
find_package(XR-OpenXR-SDK)
if(NOT XR_OPENXR_SDK_FOUND)
message(WARNING "OpenXR-SDK not found, disabling WITH_XR_OPENXR")
set(WITH_XR_OPENXR OFF)
endif()
endif()
if(EXISTS ${LIBDIR})
without_system_libs_end()
endif()

View File

@@ -671,8 +671,8 @@ if(WITH_USD)
set(USD_DEBUG_LIB ${LIBDIR}/usd/lib/libusd_m_d.lib)
set(USD_LIBRARY_DIR ${LIBDIR}/usd/lib/usd)
set(USD_LIBRARIES
debug ${USD_DEBUG_LIB}
optimized ${USD_RELEASE_LIB}
debug ${USD_DEBUG_LIB}
optimized ${USD_RELEASE_LIB}
)
endif()
endif()
@@ -713,3 +713,15 @@ if(WINDOWS_PYTHON_DEBUG)
</Project>")
endif()
endif()
if(WITH_XR_OPENXR)
if(EXISTS ${LIBDIR}/xr_openxr_sdk)
set(XR_OPENXR_SDK ${LIBDIR}/xr_openxr_sdk)
set(XR_OPENXR_SDK_LIBPATH ${LIBDIR}/xr_openxr_sdk/lib)
set(XR_OPENXR_SDK_INCLUDE_DIR ${XR_OPENXR_SDK}/include)
set(XR_OPENXR_SDK_LIBRARIES optimized ${XR_OPENXR_SDK_LIBPATH}/openxr_loader.lib debug ${XR_OPENXR_SDK_LIBPATH}/openxr_loader_d.lib)
else()
message(WARNING "OpenXR-SDK was not found, disabling WITH_XR_OPENXR")
set(WITH_XR_OPENXR OFF)
endif()
endif()

View File

@@ -0,0 +1,44 @@
"""
The message bus system can be used to receive notifications when properties of
Blender datablocks are changed via the data API.
Limitations
-----------
The message bus system is triggered by updates via the RNA system. This means
that the following updates will result in a notification on the message bus:
- Changes via the Python API, for example ``some_object.location.x += 3``.
- Changes via the sliders, fields, and buttons in the user interface.
The following updates do **not** trigger message bus notifications:
- Moving objects in the 3D Viewport.
- Changes performed by the animation system.
Example Use
-----------
Below is an example of subscription to changes in the active object's location.
"""
import bpy
# Any Python object can act as the subscription's owner.
owner = object()
subscribe_to = bpy.context.object.location
def msgbus_callback(*args):
# This will print:
# Something changed! (1, 2, 3)
print("Something changed!", args)
bpy.msgbus.subscribe_rna(
key=subscribe_to,
owner=owner,
args=(1, 2, 3),
notify=msgbus_callback,
)

View File

@@ -0,0 +1,6 @@
"""
Some properties are converted to Python objects when you retrieve them. This
needs to be avoided in order to create the subscription, by using
``datablock.path_resolve("property_name", False)``:
"""
subscribe_to = bpy.context.object.path_resolve("name", False)

View File

@@ -0,0 +1,5 @@
"""
It is also possible to create subscriptions on a property of all instances of a
certain type:
"""
subscribe_to = (bpy.types.Object, "location")

View File

@@ -6,7 +6,7 @@ bl_info = {
"location": "SpaceBar Search -> Add-on Preferences Example",
"description": "Example Add-on",
"warning": "",
"wiki_url": "",
"doc_url": "",
"tracker_url": "",
"category": "Object",
}

View File

@@ -255,9 +255,9 @@ Examples:
>>> bpy.ops.object.scale_apply()
{'FINISHED'}
.. note::
.. tip::
The menu item: :menuselection:`Help --> Operator Cheat Sheet`
The :ref:`Operator Cheat Sheet <blender_manual:bpy.ops.wm.operator_cheat_sheet>`.
gives a list of all operators and their default values in Python syntax, along with the generated docs.
This is a good way to get an overview of all Blender's operators.

View File

@@ -1756,6 +1756,7 @@ def write_rst_contents(basepath):
app_modules = (
"bpy.context", # note: not actually a module
"bpy.data", # note: not actually a module
"bpy.msgbus", # note: not actually a module
"bpy.ops",
"bpy.types",
@@ -1846,6 +1847,29 @@ def write_rst_ops_index(basepath):
file.close()
def write_rst_msgbus(basepath):
"""
Write the rst files of bpy.msgbus module
"""
if 'bpy.msgbus' in EXCLUDE_MODULES:
return
# Write the index.
filepath = os.path.join(basepath, "bpy.msgbus.rst")
file = open(filepath, "w", encoding="utf-8")
fw = file.write
fw(title_string("Message Bus (bpy.msgbus)", "="))
write_example_ref("", fw, "bpy.msgbus")
fw(".. toctree::\n")
fw(" :glob:\n\n")
fw(" bpy.msgbus.*\n\n")
file.close()
# Write the contents.
pymodule2sphinx(basepath, 'bpy.msgbus', bpy.msgbus, 'Message Bus')
EXAMPLE_SET_USED.add("bpy.msgbus")
def write_rst_data(basepath):
'''
Write the rst file of bpy.data module
@@ -2000,6 +2024,7 @@ def rna2sphinx(basepath):
write_rst_bpy(basepath) # bpy, disabled by default
write_rst_types_index(basepath) # bpy.types
write_rst_ops_index(basepath) # bpy.ops
write_rst_msgbus(basepath) # bpy.msgbus
pyrna2sphinx(basepath) # bpy.types.* and bpy.ops.*
write_rst_data(basepath) # bpy.data
write_rst_importable_modules(basepath)

View File

@@ -24,6 +24,21 @@ set(CMAKE_CXX_STANDARD 14)
add_subdirectory(dracoenc)
# Build blender-draco-exporter module.
add_library(extern_draco SHARED src/draco-compressor.cpp src/draco-compressor.h)
target_include_directories(extern_draco PUBLIC dracoenc/src)
target_link_libraries(extern_draco PUBLIC dracoenc)
set(SRC
src/draco-compressor.cpp
src/draco-compressor.h
)
set(INC
dracoenc/src
)
set(LIB
dracoenc
)
add_library(extern_draco SHARED "${SRC}")
target_include_directories(extern_draco PUBLIC "${INC}")
target_link_libraries(extern_draco PUBLIC "${LIB}")
blender_source_group(extern_draco "${SRC}")

View File

@@ -17,16 +17,13 @@
// link to omp & tbb for now
#if OPENMP == 1 || TBB == 1
# define MANTA_ENABLE_PARALLEL 0
# define MANTA_ENABLE_PARALLEL 1
// allow the preconditioner to be computed in parallel? (can lead to slightly non-deterministic
// results)
# define MANTA_ENABLE_PARALLEL_PC 0
// use c++11 code?
# define MANTA_USE_CPP11 1
#else
# define MANTA_ENABLE_PARALLEL 0
# define MANTA_ENABLE_PARALLEL_PC 0
# define MANTA_USE_CPP11 0
#endif
#if MANTA_ENABLE_PARALLEL == 1
@@ -503,11 +500,7 @@ template<class N, class T> struct RCMatrix {
for (Iterator it = row_begin(i); it; ++it)
result.fix_element(it.index(), i, it.value());
}
#if MANTA_USE_CPP11 == 1
return std::move(result);
#else
return result;
#endif
}
RCMatrix getKtK() const
@@ -532,12 +525,7 @@ template<class N, class T> struct RCMatrix {
}
}
}
parallel_end
#if MANTA_USE_CPP11 == 1
return std::move(result);
#else
return result;
#endif
parallel_end return result;
}
RCMatrix operator*(const RCMatrix &m) const
@@ -561,12 +549,7 @@ template<class N, class T> struct RCMatrix {
}
}
}
parallel_end
#if MANTA_USE_CPP11 == 1
return std::move(result);
#else
return result;
#endif
parallel_end return result;
}
RCMatrix sqrt() const
@@ -581,12 +564,7 @@ template<class N, class T> struct RCMatrix {
result.set_element(i, j, std::sqrt(it_A.value()));
}
}
parallel_end
#if MANTA_USE_CPP11 == 1
return std::move(result);
#else
return result;
#endif
parallel_end return result;
}
RCMatrix operator*(const double k) const
@@ -601,12 +579,7 @@ template<class N, class T> struct RCMatrix {
result.add_to_element(i, j, it_A.value() * k);
}
}
parallel_end
#if MANTA_USE_CPP11 == 1
return std::move(result);
#else
return result;
#endif
parallel_end return result;
}
RCMatrix applyKernel(const RCMatrix &kernel, const int nx, const int ny) const
@@ -640,12 +613,7 @@ template<class N, class T> struct RCMatrix {
}
}
}
parallel_end
#if MANTA_USE_CPP11 == 1
return std::move(result);
#else
return result;
#endif
parallel_end return result;
}
RCMatrix applyHorizontalKernel(const RCMatrix &kernel, const int nx, const int ny) const
@@ -679,12 +647,7 @@ template<class N, class T> struct RCMatrix {
}
}
}
parallel_end
#if MANTA_USE_CPP11 == 1
return std::move(result);
#else
return result;
#endif
parallel_end return result;
}
RCMatrix applyVerticalKernel(const RCMatrix &kernel, const int nx, const int ny) const
@@ -718,12 +681,7 @@ template<class N, class T> struct RCMatrix {
}
}
}
parallel_end
#if MANTA_USE_CPP11 == 1
return std::move(result);
#else
return result;
#endif
parallel_end return result;
}
RCMatrix applySeparableKernel(const RCMatrix &kernelH,
@@ -747,11 +705,7 @@ template<class N, class T> struct RCMatrix {
{
std::vector<T> result(n, 0.0);
multiply(rhs, result);
#if MANTA_USE_CPP11 == 1
return std::move(result);
#else
return result;
#endif
}
void multiply(const std::vector<T> &rhs, std::vector<T> &result) const
{
@@ -832,11 +786,7 @@ template<class N, class T> struct RCMatrix {
for (N i = 0; i < result.size(); i++) {
result[i] = std::abs(result[i] - rhs[i]);
}
#if MANTA_USE_CPP11 == 1
return std::move(result);
#else
return result;
#endif
}
T norm() const
{
@@ -1024,11 +974,7 @@ template<class N, class T> struct RCFixedMatrix {
{
std::vector<T> result(n, 0.0);
multiply(rhs, result);
#if MANTA_USE_CPP11 == 1
return std::move(result);
#else
return result;
#endif
}
void multiply(const std::vector<T> &rhs, std::vector<T> &result) const
{
@@ -1064,12 +1010,7 @@ template<class N, class T> struct RCFixedMatrix {
}
}
}
parallel_end
#if MANTA_USE_CPP11 == 1
return std::move(result);
#else
return result;
#endif
parallel_end return result;
}
RCMatrix<N, T> toRCMatrix() const
@@ -1087,12 +1028,7 @@ template<class N, class T> struct RCFixedMatrix {
result.matrix[i]->value[j] = value[rowstart[i] + j];
}
}
parallel_end
#if MANTA_USE_CPP11 == 1
return std::move(result);
#else
return result;
#endif
parallel_end return result;
}
};

View File

@@ -1,3 +1,3 @@
#define MANTA_GIT_VERSION "commit ce000bcbd7004e6549ac2f118755fcdc1f679bc3"
#define MANTA_GIT_VERSION "commit 1d52e96ad602f1974dfee75bef293bc397e4b41b"

View File

@@ -1829,13 +1829,15 @@ struct KnUpdateFlagsObs : public KernelBase {
const MACGrid *fractions,
const Grid<Real> &phiObs,
const Grid<Real> *phiOut,
const Grid<Real> *phiIn)
: KernelBase(&flags, 1),
const Grid<Real> *phiIn,
int boundaryWidth)
: KernelBase(&flags, boundaryWidth),
flags(flags),
fractions(fractions),
phiObs(phiObs),
phiOut(phiOut),
phiIn(phiIn)
phiIn(phiIn),
boundaryWidth(boundaryWidth)
{
runMessage();
run();
@@ -1847,7 +1849,8 @@ struct KnUpdateFlagsObs : public KernelBase {
const MACGrid *fractions,
const Grid<Real> &phiObs,
const Grid<Real> *phiOut,
const Grid<Real> *phiIn) const
const Grid<Real> *phiIn,
int boundaryWidth) const
{
bool isObs = false;
@@ -1910,6 +1913,11 @@ struct KnUpdateFlagsObs : public KernelBase {
return phiIn;
}
typedef Grid<Real> type4;
inline int &getArg5()
{
return boundaryWidth;
}
typedef int type5;
void runMessage()
{
debMsg("Executing kernel KnUpdateFlagsObs ", 3);
@@ -1923,15 +1931,15 @@ struct KnUpdateFlagsObs : public KernelBase {
const int _maxY = maxY;
if (maxZ > 1) {
for (int k = __r.begin(); k != (int)__r.end(); k++)
for (int j = 1; j < _maxY; j++)
for (int i = 1; i < _maxX; i++)
op(i, j, k, flags, fractions, phiObs, phiOut, phiIn);
for (int j = boundaryWidth; j < _maxY; j++)
for (int i = boundaryWidth; i < _maxX; i++)
op(i, j, k, flags, fractions, phiObs, phiOut, phiIn, boundaryWidth);
}
else {
const int k = 0;
for (int j = __r.begin(); j != (int)__r.end(); j++)
for (int i = 1; i < _maxX; i++)
op(i, j, k, flags, fractions, phiObs, phiOut, phiIn);
for (int i = boundaryWidth; i < _maxX; i++)
op(i, j, k, flags, fractions, phiObs, phiOut, phiIn, boundaryWidth);
}
}
void run()
@@ -1939,13 +1947,14 @@ struct KnUpdateFlagsObs : public KernelBase {
if (maxZ > 1)
tbb::parallel_for(tbb::blocked_range<IndexInt>(minZ, maxZ), *this);
else
tbb::parallel_for(tbb::blocked_range<IndexInt>(1, maxY), *this);
tbb::parallel_for(tbb::blocked_range<IndexInt>(boundaryWidth, maxY), *this);
}
FlagGrid &flags;
const MACGrid *fractions;
const Grid<Real> &phiObs;
const Grid<Real> *phiOut;
const Grid<Real> *phiIn;
int boundaryWidth;
};
//! update obstacle and outflow flags from levelsets
@@ -1954,9 +1963,10 @@ void setObstacleFlags(FlagGrid &flags,
const Grid<Real> &phiObs,
const MACGrid *fractions = NULL,
const Grid<Real> *phiOut = NULL,
const Grid<Real> *phiIn = NULL)
const Grid<Real> *phiIn = NULL,
int boundaryWidth = 1)
{
KnUpdateFlagsObs(flags, fractions, phiObs, phiOut, phiIn);
KnUpdateFlagsObs(flags, fractions, phiObs, phiOut, phiIn, boundaryWidth);
}
static PyObject *_W_18(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
@@ -1973,8 +1983,9 @@ static PyObject *_W_18(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
const MACGrid *fractions = _args.getPtrOpt<MACGrid>("fractions", 2, NULL, &_lock);
const Grid<Real> *phiOut = _args.getPtrOpt<Grid<Real>>("phiOut", 3, NULL, &_lock);
const Grid<Real> *phiIn = _args.getPtrOpt<Grid<Real>>("phiIn", 4, NULL, &_lock);
int boundaryWidth = _args.getOpt<int>("boundaryWidth", 5, 1, &_lock);
_retval = getPyNone();
setObstacleFlags(flags, phiObs, fractions, phiOut, phiIn);
setObstacleFlags(flags, phiObs, fractions, phiOut, phiIn, boundaryWidth);
_args.check();
}
pbFinalizePlugin(parent, "setObstacleFlags", !noTiming);

View File

@@ -51,14 +51,16 @@ endif()
# Common configuration.
link_directories(${OPENIMAGEIO_LIBPATH}
${BOOST_LIBPATH}
${PNG_LIBPATH}
${JPEG_LIBPATH}
${ZLIB_LIBPATH}
${TIFF_LIBPATH}
${OPENEXR_LIBPATH}
${OPENJPEG_LIBPATH})
link_directories(
${OPENIMAGEIO_LIBPATH}
${BOOST_LIBPATH}
${PNG_LIBPATH}
${JPEG_LIBPATH}
${ZLIB_LIBPATH}
${TIFF_LIBPATH}
${OPENEXR_LIBPATH}
${OPENJPEG_LIBPATH}
)
if(WITH_OPENCOLORIO)
link_directories(${OPENCOLORIO_LIBPATH})

View File

@@ -22,7 +22,7 @@ bl_info = {
"blender": (2, 80, 0),
"description": "Cycles renderer integration",
"warning": "",
"wiki_url": "https://docs.blender.org/manual/en/latest/render/cycles/",
"doc_url": "https://docs.blender.org/manual/en/latest/render/cycles/",
"tracker_url": "",
"support": 'OFFICIAL',
"category": "Render"}

View File

@@ -255,6 +255,7 @@ def list_render_passes(srl):
if crl.pass_debug_bvh_traversed_instances: yield ("Debug BVH Traversed Instances", "X", 'VALUE')
if crl.pass_debug_bvh_intersections: yield ("Debug BVH Intersections", "X", 'VALUE')
if crl.pass_debug_ray_bounces: yield ("Debug Ray Bounces", "X", 'VALUE')
if crl.pass_debug_sample_count: yield ("Debug Sample Count", "X", 'VALUE')
if crl.use_pass_volume_direct: yield ("VolumeDir", "RGB", 'COLOR')
if crl.use_pass_volume_indirect: yield ("VolumeInd", "RGB", 'COLOR')

View File

@@ -112,6 +112,7 @@ enum_use_layer_samples = (
enum_sampling_pattern = (
('SOBOL', "Sobol", "Use Sobol random sampling pattern"),
('CORRELATED_MUTI_JITTER', "Correlated Multi-Jitter", "Use Correlated Multi-Jitter random sampling pattern"),
('PROGRESSIVE_MUTI_JITTER', "Progressive Multi-Jitter", "Use Progressive Multi-Jitter random sampling pattern"),
)
enum_integrator = (
@@ -349,6 +350,25 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
default=0.01,
)
use_adaptive_sampling: BoolProperty(
name="Use Adaptive Sampling",
description="Automatically reduce the number of samples per pixel based on estimated noise level",
default=False,
)
adaptive_threshold: FloatProperty(
name="Adaptive Sampling Threshold",
description="Noise level step to stop sampling at, lower values reduce noise the cost of render time. Zero for automatic setting based on number of AA samples",
min=0.0, max=1.0,
default=0.0,
)
adaptive_min_samples: IntProperty(
name="Adaptive Min Samples",
description="Minimum AA samples for adaptive sampling, to discover noisy features before stopping sampling. Zero for automatic setting based on number of AA samples",
min=0, max=4096,
default=0,
)
min_light_bounces: IntProperty(
name="Min Light Bounces",
description="Minimum number of light bounces. Setting this higher reduces noise in the first bounces, "
@@ -1297,7 +1317,12 @@ class CyclesRenderLayerSettings(bpy.types.PropertyGroup):
default=False,
update=update_render_passes,
)
pass_debug_sample_count: BoolProperty(
name="Debug Sample Count",
description="Number of samples/camera rays per pixel",
default=False,
update=update_render_passes,
)
use_pass_volume_direct: BoolProperty(
name="Volume Direct",
description="Deliver direct volumetric scattering pass",

View File

@@ -230,6 +230,32 @@ class CYCLES_RENDER_PT_sampling_sub_samples(CyclesButtonsPanel, Panel):
draw_samples_info(layout, context)
class CYCLES_RENDER_PT_sampling_adaptive(CyclesButtonsPanel, Panel):
bl_label = "Adaptive Sampling"
bl_parent_id = "CYCLES_RENDER_PT_sampling"
bl_options = {'DEFAULT_CLOSED'}
def draw_header(self, context):
layout = self.layout
scene = context.scene
cscene = scene.cycles
layout.prop(cscene, "use_adaptive_sampling", text="")
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
scene = context.scene
cscene = scene.cycles
layout.active = cscene.use_adaptive_sampling
col = layout.column(align=True)
col.prop(cscene, "adaptive_min_samples", text="Min Samples")
col.prop(cscene, "adaptive_threshold", text="Noise Threshold")
class CYCLES_RENDER_PT_sampling_advanced(CyclesButtonsPanel, Panel):
bl_label = "Advanced"
bl_parent_id = "CYCLES_RENDER_PT_sampling"
@@ -247,7 +273,9 @@ class CYCLES_RENDER_PT_sampling_advanced(CyclesButtonsPanel, Panel):
row.prop(cscene, "seed")
row.prop(cscene, "use_animated_seed", text="", icon='TIME')
layout.prop(cscene, "sampling_pattern", text="Pattern")
col = layout.column(align=True)
col.active = not(cscene.use_adaptive_sampling)
col.prop(cscene, "sampling_pattern", text="Pattern")
layout.prop(cscene, "use_square_samples")
@@ -813,6 +841,8 @@ class CYCLES_RENDER_PT_passes_data(CyclesButtonsPanel, Panel):
col.prop(cycles_view_layer, "denoising_store_passes", text="Denoising Data")
col = flow.column()
col.prop(cycles_view_layer, "pass_debug_render_time", text="Render Time")
col = flow.column()
col.prop(cycles_view_layer, "pass_debug_sample_count", text="Sample Count")
layout.separator()
@@ -2238,6 +2268,7 @@ classes = (
CYCLES_PT_integrator_presets,
CYCLES_RENDER_PT_sampling,
CYCLES_RENDER_PT_sampling_sub_samples,
CYCLES_RENDER_PT_sampling_adaptive,
CYCLES_RENDER_PT_sampling_advanced,
CYCLES_RENDER_PT_light_paths,
CYCLES_RENDER_PT_light_paths_max_bounces,

View File

@@ -470,7 +470,8 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_)
b_rlay_name = b_view_layer.name();
/* add passes */
vector<Pass> passes = sync->sync_render_passes(b_rlay, b_view_layer);
vector<Pass> passes = sync->sync_render_passes(
b_rlay, b_view_layer, session_params.adaptive_sampling);
buffer_params.passes = passes;
PointerRNA crl = RNA_pointer_get(&b_view_layer.ptr, "cycles");

View File

@@ -17,15 +17,19 @@
#ifndef __BLENDER_SESSION_H__
#define __BLENDER_SESSION_H__
#include "RNA_blender_cpp.h"
#include "device/device.h"
#include "render/bake.h"
#include "render/scene.h"
#include "render/session.h"
#include "render/bake.h"
#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
class BlenderSync;
class ImageMetaData;
class Scene;
class Session;

View File

@@ -327,6 +327,7 @@ static ShaderNode *add_node(Scene *scene,
BL::ShaderNodeVectorRotate b_vector_rotate_node(b_node);
VectorRotateNode *vector_rotate_node = new VectorRotateNode();
vector_rotate_node->type = (NodeVectorRotateType)b_vector_rotate_node.rotation_type();
vector_rotate_node->invert = b_vector_rotate_node.invert();
node = vector_rotate_node;
}
else if (b_node.is_a(&RNA_ShaderNodeVectorTransform)) {

View File

@@ -296,6 +296,16 @@ void BlenderSync::sync_integrator()
integrator->sample_all_lights_indirect = get_boolean(cscene, "sample_all_lights_indirect");
integrator->light_sampling_threshold = get_float(cscene, "light_sampling_threshold");
if (RNA_boolean_get(&cscene, "use_adaptive_sampling")) {
integrator->sampling_pattern = SAMPLING_PATTERN_PMJ;
integrator->adaptive_min_samples = get_int(cscene, "adaptive_min_samples");
integrator->adaptive_threshold = get_float(cscene, "adaptive_threshold");
}
else {
integrator->adaptive_min_samples = INT_MAX;
integrator->adaptive_threshold = 0.0f;
}
int diffuse_samples = get_int(cscene, "diffuse_samples");
int glossy_samples = get_int(cscene, "glossy_samples");
int transmission_samples = get_int(cscene, "transmission_samples");
@@ -312,6 +322,8 @@ void BlenderSync::sync_integrator()
integrator->mesh_light_samples = mesh_light_samples * mesh_light_samples;
integrator->subsurface_samples = subsurface_samples * subsurface_samples;
integrator->volume_samples = volume_samples * volume_samples;
integrator->adaptive_min_samples = min(
integrator->adaptive_min_samples * integrator->adaptive_min_samples, INT_MAX);
}
else {
integrator->diffuse_samples = diffuse_samples;
@@ -484,6 +496,8 @@ PassType BlenderSync::get_pass_type(BL::RenderPass &b_pass)
MAP_PASS("Debug Ray Bounces", PASS_RAY_BOUNCES);
#endif
MAP_PASS("Debug Render Time", PASS_RENDER_TIME);
MAP_PASS("AdaptiveAuxBuffer", PASS_ADAPTIVE_AUX_BUFFER);
MAP_PASS("Debug Sample Count", PASS_SAMPLE_COUNT);
if (string_startswith(name, cryptomatte_prefix)) {
return PASS_CRYPTOMATTE;
}
@@ -519,7 +533,9 @@ int BlenderSync::get_denoising_pass(BL::RenderPass &b_pass)
return -1;
}
vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_view_layer)
vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay,
BL::ViewLayer &b_view_layer,
bool adaptive_sampling)
{
vector<Pass> passes;
@@ -595,6 +611,10 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLa
b_engine.add_pass("Debug Render Time", 1, "X", b_view_layer.name().c_str());
Pass::add(PASS_RENDER_TIME, passes, "Debug Render Time");
}
if (get_boolean(crp, "pass_debug_sample_count")) {
b_engine.add_pass("Debug Sample Count", 1, "X", b_view_layer.name().c_str());
Pass::add(PASS_SAMPLE_COUNT, passes, "Debug Sample Count");
}
if (get_boolean(crp, "use_pass_volume_direct")) {
b_engine.add_pass("VolumeDir", 3, "RGB", b_view_layer.name().c_str());
Pass::add(PASS_VOLUME_DIRECT, passes, "VolumeDir");
@@ -641,6 +661,13 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLa
CRYPT_ACCURATE);
}
if (adaptive_sampling) {
Pass::add(PASS_ADAPTIVE_AUX_BUFFER, passes);
if (!get_boolean(crp, "pass_debug_sample_count")) {
Pass::add(PASS_SAMPLE_COUNT, passes);
}
}
RNA_BEGIN (&crp, b_aov, "aovs") {
bool is_color = (get_enum(b_aov, "type") == 1);
string name = get_string(b_aov, "name");
@@ -880,6 +907,8 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine &b_engine,
params.use_profiling = params.device.has_profiling && !b_engine.is_preview() && background &&
BlenderSession::print_render_stats;
params.adaptive_sampling = RNA_boolean_get(&cscene, "use_adaptive_sampling");
return params;
}

View File

@@ -71,7 +71,9 @@ class BlenderSync {
int height,
void **python_thread_state);
void sync_view_layer(BL::SpaceView3D &b_v3d, BL::ViewLayer &b_view_layer);
vector<Pass> sync_render_passes(BL::RenderLayer &b_render_layer, BL::ViewLayer &b_view_layer);
vector<Pass> sync_render_passes(BL::RenderLayer &b_render_layer,
BL::ViewLayer &b_view_layer,
bool adaptive_sampling);
void sync_integrator();
void sync_camera(BL::RenderSettings &b_render,
BL::Object &b_override,

View File

@@ -82,6 +82,17 @@ class CUDADevice : public Device {
device_vector<TextureInfo> texture_info;
bool need_texture_info;
/* Kernels */
struct {
bool loaded;
CUfunction adaptive_stopping;
CUfunction adaptive_filter_x;
CUfunction adaptive_filter_y;
CUfunction adaptive_scale_samples;
int adaptive_num_threads_per_block;
} functions;
static bool have_precompiled_kernels();
virtual bool show_samples() const;
@@ -114,6 +125,8 @@ class CUDADevice : public Device {
virtual bool load_kernels(const DeviceRequestedFeatures &requested_features);
void load_functions();
void reserve_local_memory(const DeviceRequestedFeatures &requested_features);
void init_host_memory();
@@ -197,6 +210,15 @@ class CUDADevice : public Device {
void denoise(RenderTile &rtile, DenoisingTask &denoising);
void adaptive_sampling_filter(uint filter_sample,
WorkTile *wtile,
CUdeviceptr d_wtile,
CUstream stream = 0);
void adaptive_sampling_post(RenderTile &rtile,
WorkTile *wtile,
CUdeviceptr d_wtile,
CUstream stream = 0);
void path_trace(DeviceTask &task, RenderTile &rtile, device_vector<WorkTile> &work_tiles);
void film_convert(DeviceTask &task,

View File

@@ -208,6 +208,8 @@ CUDADevice::CUDADevice(DeviceInfo &info, Stats &stats, Profiler &profiler, bool
map_host_used = 0;
can_map_host = 0;
functions.loaded = false;
/* Intialize CUDA. */
if (cuda_error(cuInit(0)))
return;
@@ -531,9 +533,42 @@ bool CUDADevice::load_kernels(const DeviceRequestedFeatures &requested_features)
reserve_local_memory(requested_features);
}
load_functions();
return (result == CUDA_SUCCESS);
}
void CUDADevice::load_functions()
{
/* TODO: load all functions here. */
if (functions.loaded) {
return;
}
functions.loaded = true;
cuda_assert(cuModuleGetFunction(
&functions.adaptive_stopping, cuModule, "kernel_cuda_adaptive_stopping"));
cuda_assert(cuModuleGetFunction(
&functions.adaptive_filter_x, cuModule, "kernel_cuda_adaptive_filter_x"));
cuda_assert(cuModuleGetFunction(
&functions.adaptive_filter_y, cuModule, "kernel_cuda_adaptive_filter_y"));
cuda_assert(cuModuleGetFunction(
&functions.adaptive_scale_samples, cuModule, "kernel_cuda_adaptive_scale_samples"));
cuda_assert(cuFuncSetCacheConfig(functions.adaptive_stopping, CU_FUNC_CACHE_PREFER_L1));
cuda_assert(cuFuncSetCacheConfig(functions.adaptive_filter_x, CU_FUNC_CACHE_PREFER_L1));
cuda_assert(cuFuncSetCacheConfig(functions.adaptive_filter_y, CU_FUNC_CACHE_PREFER_L1));
cuda_assert(cuFuncSetCacheConfig(functions.adaptive_scale_samples, CU_FUNC_CACHE_PREFER_L1));
int unused_min_blocks;
cuda_assert(cuOccupancyMaxPotentialBlockSize(&unused_min_blocks,
&functions.adaptive_num_threads_per_block,
functions.adaptive_scale_samples,
NULL,
0,
0));
}
void CUDADevice::reserve_local_memory(const DeviceRequestedFeatures &requested_features)
{
if (use_split_kernel()) {
@@ -1666,6 +1701,80 @@ void CUDADevice::denoise(RenderTile &rtile, DenoisingTask &denoising)
denoising.run_denoising(&rtile);
}
void CUDADevice::adaptive_sampling_filter(uint filter_sample,
WorkTile *wtile,
CUdeviceptr d_wtile,
CUstream stream)
{
const int num_threads_per_block = functions.adaptive_num_threads_per_block;
/* These are a series of tiny kernels because there is no grid synchronization
* from within a kernel, so multiple kernel launches it is. */
uint total_work_size = wtile->h * wtile->w;
void *args2[] = {&d_wtile, &filter_sample, &total_work_size};
uint num_blocks = divide_up(total_work_size, num_threads_per_block);
cuda_assert(cuLaunchKernel(functions.adaptive_stopping,
num_blocks,
1,
1,
num_threads_per_block,
1,
1,
0,
stream,
args2,
0));
total_work_size = wtile->h;
num_blocks = divide_up(total_work_size, num_threads_per_block);
cuda_assert(cuLaunchKernel(functions.adaptive_filter_x,
num_blocks,
1,
1,
num_threads_per_block,
1,
1,
0,
stream,
args2,
0));
total_work_size = wtile->w;
num_blocks = divide_up(total_work_size, num_threads_per_block);
cuda_assert(cuLaunchKernel(functions.adaptive_filter_y,
num_blocks,
1,
1,
num_threads_per_block,
1,
1,
0,
stream,
args2,
0));
}
void CUDADevice::adaptive_sampling_post(RenderTile &rtile,
WorkTile *wtile,
CUdeviceptr d_wtile,
CUstream stream)
{
const int num_threads_per_block = functions.adaptive_num_threads_per_block;
uint total_work_size = wtile->h * wtile->w;
void *args[] = {&d_wtile, &rtile.start_sample, &rtile.sample, &total_work_size};
uint num_blocks = divide_up(total_work_size, num_threads_per_block);
cuda_assert(cuLaunchKernel(functions.adaptive_scale_samples,
num_blocks,
1,
1,
num_threads_per_block,
1,
1,
0,
stream,
args,
0));
}
void CUDADevice::path_trace(DeviceTask &task,
RenderTile &rtile,
device_vector<WorkTile> &work_tiles)
@@ -1715,6 +1824,9 @@ void CUDADevice::path_trace(DeviceTask &task,
}
uint step_samples = divide_up(min_blocks * num_threads_per_block, wtile->w * wtile->h);
if (task.adaptive_sampling.use) {
step_samples = task.adaptive_sampling.align_static_samples(step_samples);
}
/* Render all samples. */
int start_sample = rtile.start_sample;
@@ -1736,6 +1848,12 @@ void CUDADevice::path_trace(DeviceTask &task,
cuda_assert(
cuLaunchKernel(cuPathTrace, num_blocks, 1, 1, num_threads_per_block, 1, 1, 0, 0, args, 0));
/* Run the adaptive sampling kernels at selected samples aligned to step samples. */
uint filter_sample = sample + wtile->num_samples - 1;
if (task.adaptive_sampling.use && task.adaptive_sampling.need_filter(filter_sample)) {
adaptive_sampling_filter(filter_sample, wtile, d_work_tiles);
}
cuda_assert(cuCtxSynchronize());
/* Update progress. */
@@ -1747,6 +1865,14 @@ void CUDADevice::path_trace(DeviceTask &task,
break;
}
}
/* Finalize adaptive sampling. */
if (task.adaptive_sampling.use) {
CUdeviceptr d_work_tiles = (CUdeviceptr)work_tiles.device_pointer;
adaptive_sampling_post(rtile, wtile, d_work_tiles);
cuda_assert(cuCtxSynchronize());
task.update_progress(&rtile, rtile.w * rtile.h * wtile->num_samples);
}
}
void CUDADevice::film_convert(DeviceTask &task,
@@ -2144,7 +2270,7 @@ void CUDADevice::thread_run(DeviceTask *task)
{
CUDAContextScope scope(this);
if (task->type == DeviceTask::RENDER || task->type == DeviceTask::DENOISE) {
if (task->type == DeviceTask::RENDER) {
DeviceRequestedFeatures requested_features;
if (use_split_kernel()) {
if (split_kernel == NULL) {
@@ -2159,7 +2285,7 @@ void CUDADevice::thread_run(DeviceTask *task)
RenderTile tile;
DenoisingTask denoising(this, *task);
while (task->acquire_tile(this, tile)) {
while (task->acquire_tile(this, tile, task->tile_types)) {
if (tile.task == RenderTile::PATH_TRACE) {
if (use_split_kernel()) {
device_only_memory<uchar> void_buffer(this, "void_buffer");

View File

@@ -29,16 +29,19 @@
#include "device/device_intern.h"
#include "device/device_split_kernel.h"
// clang-format off
#include "kernel/kernel.h"
#include "kernel/kernel_compat_cpu.h"
#include "kernel/kernel_types.h"
#include "kernel/split/kernel_split_data.h"
#include "kernel/kernel_globals.h"
#include "kernel/kernel_adaptive_sampling.h"
#include "kernel/filter/filter.h"
#include "kernel/osl/osl_shader.h"
#include "kernel/osl/osl_globals.h"
// clang-format on
#include "render/buffers.h"
#include "render/coverage.h"
@@ -317,6 +320,10 @@ class CPUDevice : public Device {
REGISTER_SPLIT_KERNEL(next_iteration_setup);
REGISTER_SPLIT_KERNEL(indirect_subsurface);
REGISTER_SPLIT_KERNEL(buffer_update);
REGISTER_SPLIT_KERNEL(adaptive_stopping);
REGISTER_SPLIT_KERNEL(adaptive_filter_x);
REGISTER_SPLIT_KERNEL(adaptive_filter_y);
REGISTER_SPLIT_KERNEL(adaptive_adjust_samples);
#undef REGISTER_SPLIT_KERNEL
#undef KERNEL_FUNCTIONS
}
@@ -511,7 +518,7 @@ class CPUDevice : public Device {
void thread_run(DeviceTask *task)
{
if (task->type == DeviceTask::RENDER || task->type == DeviceTask::DENOISE)
if (task->type == DeviceTask::RENDER)
thread_render(*task);
else if (task->type == DeviceTask::SHADER)
thread_shader(*task);
@@ -823,6 +830,49 @@ class CPUDevice : public Device {
return true;
}
bool adaptive_sampling_filter(KernelGlobals *kg, RenderTile &tile)
{
WorkTile wtile;
wtile.x = tile.x;
wtile.y = tile.y;
wtile.w = tile.w;
wtile.h = tile.h;
wtile.offset = tile.offset;
wtile.stride = tile.stride;
wtile.buffer = (float *)tile.buffer;
bool any = false;
for (int y = tile.y; y < tile.y + tile.h; ++y) {
any |= kernel_do_adaptive_filter_x(kg, y, &wtile);
}
for (int x = tile.x; x < tile.x + tile.w; ++x) {
any |= kernel_do_adaptive_filter_y(kg, x, &wtile);
}
return (!any);
}
void adaptive_sampling_post(const RenderTile &tile, KernelGlobals *kg)
{
float *render_buffer = (float *)tile.buffer;
for (int y = tile.y; y < tile.y + tile.h; y++) {
for (int x = tile.x; x < tile.x + tile.w; x++) {
int index = tile.offset + x + y * tile.stride;
ccl_global float *buffer = render_buffer + index * kernel_data.film.pass_stride;
if (buffer[kernel_data.film.pass_sample_count] < 0.0f) {
buffer[kernel_data.film.pass_sample_count] = -buffer[kernel_data.film.pass_sample_count];
float sample_multiplier = tile.sample / max((float)tile.start_sample + 1.0f,
buffer[kernel_data.film.pass_sample_count]);
if (sample_multiplier != 1.0f) {
kernel_adaptive_post_adjust(kg, buffer, sample_multiplier);
}
}
else {
kernel_adaptive_post_adjust(kg, buffer, tile.sample / (tile.sample - 1.0f));
}
}
}
}
void path_trace(DeviceTask &task, RenderTile &tile, KernelGlobals *kg)
{
const bool use_coverage = kernel_data.film.cryptomatte_passes & CRYPT_ACCURATE;
@@ -855,14 +905,27 @@ class CPUDevice : public Device {
path_trace_kernel()(kg, render_buffer, sample, x, y, tile.offset, tile.stride);
}
}
tile.sample = sample + 1;
if (task.adaptive_sampling.use && task.adaptive_sampling.need_filter(sample)) {
const bool stop = adaptive_sampling_filter(kg, tile);
if (stop) {
const int num_progress_samples = end_sample - sample;
tile.sample = end_sample;
task.update_progress(&tile, tile.w * tile.h * num_progress_samples);
break;
}
}
task.update_progress(&tile, tile.w * tile.h);
}
if (use_coverage) {
coverage.finalize();
}
if (task.adaptive_sampling.use) {
adaptive_sampling_post(tile, kg);
}
}
void denoise(DenoisingTask &denoising, RenderTile &tile)
@@ -927,7 +990,7 @@ class CPUDevice : public Device {
DenoisingTask denoising(this, task);
denoising.profiler = &kg->profiler;
while (task.acquire_tile(this, tile)) {
while (task.acquire_tile(this, tile, task.tile_types)) {
if (tile.task == RenderTile::PATH_TRACE) {
if (use_split_kernel) {
device_only_memory<uchar> void_buffer(this, "void_buffer");

View File

@@ -17,9 +17,15 @@
#ifndef __DEVICE_INTERN_H__
#define __DEVICE_INTERN_H__
#include "util/util_string.h"
#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
class Device;
class DeviceInfo;
class Profiler;
class Stats;
Device *device_cpu_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background);
bool device_opencl_init();

View File

@@ -183,6 +183,14 @@ class MultiDevice : public Device {
return true;
}
virtual void *osl_memory()
{
if (devices.size() > 1) {
return NULL;
}
return devices.front().device->osl_memory();
}
void mem_alloc(device_memory &mem)
{
device_ptr key = unique_key++;
@@ -482,11 +490,24 @@ class MultiDevice : public Device {
void task_add(DeviceTask &task)
{
list<SubDevice> &task_devices = denoising_devices.empty() ||
(task.type != DeviceTask::DENOISE &&
task.type != DeviceTask::DENOISE_BUFFER) ?
devices :
denoising_devices;
list<SubDevice> task_devices = devices;
if (!denoising_devices.empty()) {
if (task.type == DeviceTask::DENOISE_BUFFER) {
/* Denoising tasks should be redirected to the denoising devices entirely. */
task_devices = denoising_devices;
}
else if (task.type == DeviceTask::RENDER && (task.tile_types & RenderTile::DENOISE)) {
const uint tile_types = task.tile_types;
/* For normal rendering tasks only redirect the denoising part to the denoising devices.
* Do not need to split the task here, since they all run through 'acquire_tile'. */
task.tile_types = RenderTile::DENOISE;
foreach (SubDevice &sub, denoising_devices) {
sub.device->task_add(task);
}
/* Rendering itself should still be executed on the rendering devices. */
task.tile_types = tile_types ^ RenderTile::DENOISE;
}
}
list<DeviceTask> tasks;
task.split(tasks, task_devices.size());

View File

@@ -186,14 +186,15 @@ class OptiXDevice : public CUDADevice {
OptixTraversableHandle tlas_handle = 0;
OptixDenoiser denoiser = NULL;
pair<int2, CUdeviceptr> denoiser_state = {};
device_only_memory<unsigned char> denoiser_state;
int denoiser_input_passes = 0;
public:
OptiXDevice(DeviceInfo &info_, Stats &stats_, Profiler &profiler_, bool background_)
: CUDADevice(info_, stats_, profiler_, background_),
sbt_data(this, "__sbt", MEM_READ_ONLY),
launch_params(this, "__params")
launch_params(this, "__params"),
denoiser_state(this, "__denoiser_state")
{
// Store number of CUDA streams in device info
info.cpu_threads = DebugFlags().optix.cuda_streams;
@@ -255,13 +256,10 @@ class OptiXDevice : public CUDADevice {
cuMemFree(mem);
}
if (denoiser_state.second) {
cuMemFree(denoiser_state.second);
}
sbt_data.free();
texture_info.free();
launch_params.free();
denoiser_state.free();
// Unload modules
if (optix_module != NULL)
@@ -571,9 +569,14 @@ class OptiXDevice : public CUDADevice {
if (have_error())
return; // Abort early if there was an error previously
if (task.type == DeviceTask::RENDER || task.type == DeviceTask::DENOISE) {
if (task.type == DeviceTask::RENDER) {
if (thread_index != 0) {
// Only execute denoising in a single thread (see also 'task_add')
task.tile_types &= ~RenderTile::DENOISE;
}
RenderTile tile;
while (task.acquire_tile(this, tile)) {
while (task.acquire_tile(this, tile, task.tile_types)) {
if (tile.task == RenderTile::PATH_TRACE)
launch_render(task, tile, thread_index);
else if (tile.task == RenderTile::DENOISE)
@@ -624,7 +627,11 @@ class OptiXDevice : public CUDADevice {
const int end_sample = rtile.start_sample + rtile.num_samples;
// Keep this number reasonable to avoid running into TDRs
const int step_samples = (info.display_device ? 8 : 32);
int step_samples = (info.display_device ? 8 : 32);
if (task.adaptive_sampling.use) {
step_samples = task.adaptive_sampling.align_static_samples(step_samples);
}
// Offset into launch params buffer so that streams use separate data
device_ptr launch_params_ptr = launch_params.device_pointer +
thread_index * launch_params.data_elements;
@@ -635,10 +642,9 @@ class OptiXDevice : public CUDADevice {
// Copy work tile information to device
wtile.num_samples = min(step_samples, end_sample - sample);
wtile.start_sample = sample;
check_result_cuda(cuMemcpyHtoDAsync(launch_params_ptr + offsetof(KernelParams, tile),
&wtile,
sizeof(wtile),
cuda_stream[thread_index]));
device_ptr d_wtile_ptr = launch_params_ptr + offsetof(KernelParams, tile);
check_result_cuda(
cuMemcpyHtoDAsync(d_wtile_ptr, &wtile, sizeof(wtile), cuda_stream[thread_index]));
OptixShaderBindingTable sbt_params = {};
sbt_params.raygenRecord = sbt_data.device_pointer + PG_RGEN * sizeof(SbtRecord);
@@ -663,6 +669,12 @@ class OptiXDevice : public CUDADevice {
wtile.h,
1));
// Run the adaptive sampling kernels at selected samples aligned to step samples.
uint filter_sample = wtile.start_sample + wtile.num_samples - 1;
if (task.adaptive_sampling.use && task.adaptive_sampling.need_filter(filter_sample)) {
adaptive_sampling_filter(filter_sample, &wtile, d_wtile_ptr, cuda_stream[thread_index]);
}
// Wait for launch to finish
check_result_cuda(cuStreamSynchronize(cuda_stream[thread_index]));
@@ -674,6 +686,14 @@ class OptiXDevice : public CUDADevice {
if (task.get_cancel() && !task.need_finish_queue)
return; // Cancel rendering
}
// Finalize adaptive sampling
if (task.adaptive_sampling.use) {
device_ptr d_wtile_ptr = launch_params_ptr + offsetof(KernelParams, tile);
adaptive_sampling_post(rtile, &wtile, d_wtile_ptr, cuda_stream[thread_index]);
check_result_cuda(cuStreamSynchronize(cuda_stream[thread_index]));
task.update_progress(&rtile, rtile.w * rtile.h * wtile.num_samples);
}
}
bool launch_denoise(DeviceTask &task, RenderTile &rtile)
@@ -813,32 +833,26 @@ class OptiXDevice : public CUDADevice {
check_result_optix_ret(
optixDenoiserComputeMemoryResources(denoiser, rect_size.x, rect_size.y, &sizes));
auto &state = denoiser_state.second;
auto &state_size = denoiser_state.first;
const size_t scratch_size = sizes.recommendedScratchSizeInBytes;
const size_t scratch_offset = sizes.stateSizeInBytes;
// Allocate denoiser state if tile size has changed since last setup
if (state_size.x != rect_size.x || state_size.y != rect_size.y || recreate_denoiser) {
// Free existing state before allocating new one
if (state) {
cuMemFree(state);
state = 0;
}
check_result_cuda_ret(cuMemAlloc(&state, scratch_offset + scratch_size));
if (recreate_denoiser || (denoiser_state.data_width != rect_size.x ||
denoiser_state.data_height != rect_size.y)) {
denoiser_state.alloc_to_device(scratch_offset + scratch_size);
// Initialize denoiser state for the current tile size
check_result_optix_ret(optixDenoiserSetup(denoiser,
0,
rect_size.x,
rect_size.y,
state,
denoiser_state.device_pointer,
scratch_offset,
state + scratch_offset,
denoiser_state.device_pointer + scratch_offset,
scratch_size));
state_size = rect_size;
denoiser_state.data_width = rect_size.x;
denoiser_state.data_height = rect_size.y;
}
// Set up input and output layer information
@@ -880,14 +894,14 @@ class OptiXDevice : public CUDADevice {
check_result_optix_ret(optixDenoiserInvoke(denoiser,
0,
&params,
state,
denoiser_state.device_pointer,
scratch_offset,
input_layers,
task.denoising.optix_input_passes,
overlap_offset.x,
overlap_offset.y,
output_layers,
state + scratch_offset,
denoiser_state.device_pointer + scratch_offset,
scratch_size));
# if OPTIX_DENOISER_NO_PIXEL_STRIDE
@@ -1459,7 +1473,7 @@ class OptiXDevice : public CUDADevice {
return;
}
if (task.type == DeviceTask::DENOISE || task.type == DeviceTask::DENOISE_BUFFER) {
if (task.type == DeviceTask::DENOISE_BUFFER) {
// Execute denoising in a single thread (e.g. to avoid race conditions during creation)
task_pool.push(new OptiXDeviceTask(this, task, 0));
return;

View File

@@ -55,6 +55,10 @@ DeviceSplitKernel::DeviceSplitKernel(Device *device)
kernel_next_iteration_setup = NULL;
kernel_indirect_subsurface = NULL;
kernel_buffer_update = NULL;
kernel_adaptive_stopping = NULL;
kernel_adaptive_filter_x = NULL;
kernel_adaptive_filter_y = NULL;
kernel_adaptive_adjust_samples = NULL;
}
DeviceSplitKernel::~DeviceSplitKernel()
@@ -83,6 +87,10 @@ DeviceSplitKernel::~DeviceSplitKernel()
delete kernel_next_iteration_setup;
delete kernel_indirect_subsurface;
delete kernel_buffer_update;
delete kernel_adaptive_stopping;
delete kernel_adaptive_filter_x;
delete kernel_adaptive_filter_y;
delete kernel_adaptive_adjust_samples;
}
bool DeviceSplitKernel::load_kernels(const DeviceRequestedFeatures &requested_features)
@@ -114,6 +122,10 @@ bool DeviceSplitKernel::load_kernels(const DeviceRequestedFeatures &requested_fe
LOAD_KERNEL(next_iteration_setup);
LOAD_KERNEL(indirect_subsurface);
LOAD_KERNEL(buffer_update);
LOAD_KERNEL(adaptive_stopping);
LOAD_KERNEL(adaptive_filter_x);
LOAD_KERNEL(adaptive_filter_y);
LOAD_KERNEL(adaptive_adjust_samples);
#undef LOAD_KERNEL
@@ -202,13 +214,21 @@ bool DeviceSplitKernel::path_trace(DeviceTask *task,
/* initial guess to start rolling average */
const int initial_num_samples = 1;
/* approx number of samples per second */
int samples_per_second = (avg_time_per_sample > 0.0) ?
int(double(time_multiplier) / avg_time_per_sample) + 1 :
initial_num_samples;
const int samples_per_second = (avg_time_per_sample > 0.0) ?
int(double(time_multiplier) / avg_time_per_sample) + 1 :
initial_num_samples;
RenderTile subtile = tile;
subtile.start_sample = tile.sample;
subtile.num_samples = min(samples_per_second,
subtile.num_samples = samples_per_second;
if (task->adaptive_sampling.use) {
subtile.num_samples = task->adaptive_sampling.align_dynamic_samples(subtile.start_sample,
subtile.num_samples);
}
/* Don't go beyond requested number of samples. */
subtile.num_samples = min(subtile.num_samples,
tile.start_sample + tile.num_samples - tile.sample);
if (device->have_error()) {
@@ -302,6 +322,23 @@ bool DeviceSplitKernel::path_trace(DeviceTask *task,
}
}
int filter_sample = tile.sample + subtile.num_samples - 1;
if (task->adaptive_sampling.use && task->adaptive_sampling.need_filter(filter_sample)) {
size_t buffer_size[2];
buffer_size[0] = round_up(tile.w, local_size[0]);
buffer_size[1] = round_up(tile.h, local_size[1]);
kernel_adaptive_stopping->enqueue(
KernelDimensions(buffer_size, local_size), kgbuffer, kernel_data);
buffer_size[0] = round_up(tile.h, local_size[0]);
buffer_size[1] = round_up(1, local_size[1]);
kernel_adaptive_filter_x->enqueue(
KernelDimensions(buffer_size, local_size), kgbuffer, kernel_data);
buffer_size[0] = round_up(tile.w, local_size[0]);
buffer_size[1] = round_up(1, local_size[1]);
kernel_adaptive_filter_y->enqueue(
KernelDimensions(buffer_size, local_size), kgbuffer, kernel_data);
}
double time_per_sample = ((time_dt() - start_time) / subtile.num_samples);
if (avg_time_per_sample == 0.0) {
@@ -324,6 +361,28 @@ bool DeviceSplitKernel::path_trace(DeviceTask *task,
}
}
if (task->adaptive_sampling.use) {
/* Reset the start samples. */
RenderTile subtile = tile;
subtile.start_sample = tile.start_sample;
subtile.num_samples = tile.sample - tile.start_sample;
enqueue_split_kernel_data_init(KernelDimensions(global_size, local_size),
subtile,
num_global_elements,
kgbuffer,
kernel_data,
split_data,
ray_state,
queue_index,
use_queues_flag,
work_pool_wgs);
size_t buffer_size[2];
buffer_size[0] = round_up(tile.w, local_size[0]);
buffer_size[1] = round_up(tile.h, local_size[1]);
kernel_adaptive_adjust_samples->enqueue(
KernelDimensions(buffer_size, local_size), kgbuffer, kernel_data);
}
return true;
}

View File

@@ -75,6 +75,10 @@ class DeviceSplitKernel {
SplitKernelFunction *kernel_next_iteration_setup;
SplitKernelFunction *kernel_indirect_subsurface;
SplitKernelFunction *kernel_buffer_update;
SplitKernelFunction *kernel_adaptive_stopping;
SplitKernelFunction *kernel_adaptive_filter_x;
SplitKernelFunction *kernel_adaptive_filter_y;
SplitKernelFunction *kernel_adaptive_adjust_samples;
/* Global memory variables [porting]; These memory is used for
* co-operation between different kernels; Data written by one

View File

@@ -68,7 +68,7 @@ int DeviceTask::get_subtask_count(int num, int max_size)
if (type == SHADER) {
num = min(shader_w, num);
}
else if (type == RENDER || type == DENOISE) {
else if (type == RENDER) {
}
else {
num = min(h, num);
@@ -94,7 +94,7 @@ void DeviceTask::split(list<DeviceTask> &tasks, int num, int max_size)
tasks.push_back(task);
}
}
else if (type == RENDER || type == DENOISE) {
else if (type == RENDER) {
for (int i = 0; i < num; i++)
tasks.push_back(*this);
}
@@ -136,4 +136,59 @@ void DeviceTask::update_progress(RenderTile *rtile, int pixel_samples)
}
}
/* Adaptive Sampling */
AdaptiveSampling::AdaptiveSampling()
: use(true), adaptive_step(ADAPTIVE_SAMPLE_STEP), min_samples(0)
{
}
/* Render samples in steps that align with the adaptive filtering. */
int AdaptiveSampling::align_static_samples(int samples) const
{
if (samples > adaptive_step) {
/* Make multiple of adaptive_step. */
while (samples % adaptive_step != 0) {
samples--;
}
}
else if (samples < adaptive_step) {
/* Make divisor of adaptive_step. */
while (adaptive_step % samples != 0) {
samples--;
}
}
return max(samples, 1);
}
/* Render samples in steps that align with the adaptive filtering, with the
* suggested number of samples dynamically changing. */
int AdaptiveSampling::align_dynamic_samples(int offset, int samples) const
{
/* Round so that we end up on multiples of adaptive_samples. */
samples += offset;
if (samples > adaptive_step) {
/* Make multiple of adaptive_step. */
while (samples % adaptive_step != 0) {
samples--;
}
}
samples -= offset;
return max(samples, 1);
}
bool AdaptiveSampling::need_filter(int sample) const
{
if (sample > min_samples) {
return (sample & (adaptive_step - 1)) == (adaptive_step - 1);
}
else {
return false;
}
}
CCL_NAMESPACE_END

View File

@@ -62,9 +62,22 @@ class DenoiseParams {
}
};
class AdaptiveSampling {
public:
AdaptiveSampling();
int align_static_samples(int samples) const;
int align_dynamic_samples(int offset, int samples) const;
bool need_filter(int sample) const;
bool use;
int adaptive_step;
int min_samples;
};
class DeviceTask : public Task {
public:
typedef enum { RENDER, DENOISE, DENOISE_BUFFER, FILM_CONVERT, SHADER } Type;
typedef enum { RENDER, FILM_CONVERT, SHADER, DENOISE_BUFFER } Type;
Type type;
int x, y, w, h;
@@ -90,7 +103,7 @@ class DeviceTask : public Task {
void update_progress(RenderTile *rtile, int pixel_samples = -1);
function<bool(Device *device, RenderTile &)> acquire_tile;
function<bool(Device *device, RenderTile &, uint)> acquire_tile;
function<void(long, int)> update_progress_sample;
function<void(RenderTile &)> update_tile_sample;
function<void(RenderTile &)> release_tile;
@@ -98,6 +111,7 @@ class DeviceTask : public Task {
function<void(RenderTile *, Device *)> map_neighbor_tiles;
function<void(RenderTile *, Device *)> unmap_neighbor_tiles;
uint tile_types;
DenoiseParams denoising;
bool denoising_from_render;
vector<int> denoising_frames;
@@ -114,6 +128,7 @@ class DeviceTask : public Task {
bool need_finish_queue;
bool integrator_branched;
AdaptiveSampling adaptive_sampling;
protected:
double last_update_time;

View File

@@ -445,6 +445,7 @@ class OpenCLDevice : public Device {
device_ptr rgba_byte,
device_ptr rgba_half);
void shader(DeviceTask &task);
void update_adaptive(DeviceTask &task, RenderTile &tile, int sample);
void denoise(RenderTile &tile, DenoisingTask &denoising);

View File

@@ -56,7 +56,11 @@ static const string SPLIT_BUNDLE_KERNELS =
"enqueue_inactive "
"next_iteration_setup "
"indirect_subsurface "
"buffer_update";
"buffer_update "
"adaptive_stopping "
"adaptive_filter_x "
"adaptive_filter_y "
"adaptive_adjust_samples";
const string OpenCLDevice::get_opencl_program_name(const string &kernel_name)
{
@@ -283,6 +287,10 @@ void OpenCLDevice::OpenCLSplitPrograms::load_kernels(
ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(next_iteration_setup);
ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(indirect_subsurface);
ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(buffer_update);
ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(adaptive_stopping);
ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(adaptive_filter_x);
ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(adaptive_filter_y);
ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(adaptive_adjust_samples);
programs.push_back(&program_split);
# undef ADD_SPLIT_KERNEL_PROGRAM
@@ -1308,7 +1316,7 @@ void OpenCLDevice::thread_run(DeviceTask *task)
{
flush_texture_buffers();
if (task->type == DeviceTask::RENDER || task->type == DeviceTask::DENOISE) {
if (task->type == DeviceTask::RENDER) {
RenderTile tile;
DenoisingTask denoising(this, *task);
@@ -1317,7 +1325,7 @@ void OpenCLDevice::thread_run(DeviceTask *task)
kgbuffer.alloc_to_device(1);
/* Keep rendering tiles until done. */
while (task->acquire_tile(this, tile)) {
while (task->acquire_tile(this, tile, task->tile_types)) {
if (tile.task == RenderTile::PATH_TRACE) {
assert(tile.task == RenderTile::PATH_TRACE);
scoped_timer timer(&tile.buffers->render_time);

View File

@@ -36,6 +36,10 @@ set(SRC_CUDA_KERNELS
)
set(SRC_OPENCL_KERNELS
kernels/opencl/kernel_adaptive_stopping.cl
kernels/opencl/kernel_adaptive_filter_x.cl
kernels/opencl/kernel_adaptive_filter_y.cl
kernels/opencl/kernel_adaptive_adjust_samples.cl
kernels/opencl/kernel_bake.cl
kernels/opencl/kernel_base.cl
kernels/opencl/kernel_displace.cl
@@ -94,6 +98,7 @@ set(SRC_BVH_HEADERS
set(SRC_HEADERS
kernel_accumulate.h
kernel_adaptive_sampling.h
kernel_bake.h
kernel_camera.h
kernel_color.h
@@ -324,6 +329,10 @@ set(SRC_UTIL_HEADERS
)
set(SRC_SPLIT_HEADERS
split/kernel_adaptive_adjust_samples.h
split/kernel_adaptive_filter_x.h
split/kernel_adaptive_filter_y.h
split/kernel_adaptive_stopping.h
split/kernel_branched.h
split/kernel_buffer_update.h
split/kernel_data_init.h

View File

@@ -17,9 +17,12 @@
#include <embree3/rtcore_ray.h>
#include <embree3/rtcore_scene.h>
// clang-format off
#include "kernel/kernel_compat_cpu.h"
#include "kernel/split/kernel_split_data_types.h"
#include "kernel/kernel_globals.h"
// clang-format on
#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN

View File

@@ -14,6 +14,7 @@
* limitations under the License.
*/
// clang-format off
#include "kernel/closure/bsdf_ashikhmin_velvet.h"
#include "kernel/closure/bsdf_diffuse.h"
#include "kernel/closure/bsdf_oren_nayar.h"
@@ -32,6 +33,7 @@
#include "kernel/closure/bsdf_principled_sheen.h"
#include "kernel/closure/bssrdf.h"
#include "kernel/closure/volume.h"
// clang-format on
CCL_NAMESPACE_BEGIN

View File

@@ -14,6 +14,7 @@
* limitations under the License.
*/
// clang-format off
#include "kernel/geom/geom_attribute.h"
#include "kernel/geom/geom_object.h"
#ifdef __PATCH_EVAL__
@@ -30,3 +31,4 @@
#include "kernel/geom/geom_curve_intersect.h"
#include "kernel/geom/geom_volume.h"
#include "kernel/geom/geom_primitive.h"
// clang-format on

View File

@@ -0,0 +1,231 @@
/*
* Copyright 2019 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __KERNEL_ADAPTIVE_SAMPLING_H__
#define __KERNEL_ADAPTIVE_SAMPLING_H__
CCL_NAMESPACE_BEGIN
/* Determines whether to continue sampling a given pixel or if it has sufficiently converged. */
ccl_device void kernel_do_adaptive_stopping(KernelGlobals *kg,
ccl_global float *buffer,
int sample)
{
/* TODO Stefan: Is this better in linear, sRGB or something else? */
float4 I = *((ccl_global float4 *)buffer);
float4 A = *(ccl_global float4 *)(buffer + kernel_data.film.pass_adaptive_aux_buffer);
/* The per pixel error as seen in section 2.1 of
* "A hierarchical automatic stopping condition for Monte Carlo global illumination"
* A small epsilon is added to the divisor to prevent division by zero. */
float error = (fabsf(I.x - A.x) + fabsf(I.y - A.y) + fabsf(I.z - A.z)) /
(sample * 0.0001f + sqrtf(I.x + I.y + I.z));
if (error < kernel_data.integrator.adaptive_threshold * (float)sample) {
/* Set the fourth component to non-zero value to indicate that this pixel has converged. */
buffer[kernel_data.film.pass_adaptive_aux_buffer + 3] += 1.0f;
}
}
/* Adjust the values of an adaptively sampled pixel. */
ccl_device void kernel_adaptive_post_adjust(KernelGlobals *kg,
ccl_global float *buffer,
float sample_multiplier)
{
*(ccl_global float4 *)(buffer) *= sample_multiplier;
/* Scale the aux pass too, this is necessary for progressive rendering to work properly. */
kernel_assert(kernel_data.film.pass_adaptive_aux_buffer);
*(ccl_global float4 *)(buffer + kernel_data.film.pass_adaptive_aux_buffer) *= sample_multiplier;
#ifdef __PASSES__
int flag = kernel_data.film.pass_flag;
if (flag & PASSMASK(SHADOW))
*(ccl_global float3 *)(buffer + kernel_data.film.pass_shadow) *= sample_multiplier;
if (flag & PASSMASK(MIST))
*(ccl_global float *)(buffer + kernel_data.film.pass_mist) *= sample_multiplier;
if (flag & PASSMASK(NORMAL))
*(ccl_global float3 *)(buffer + kernel_data.film.pass_normal) *= sample_multiplier;
if (flag & PASSMASK(UV))
*(ccl_global float3 *)(buffer + kernel_data.film.pass_uv) *= sample_multiplier;
if (flag & PASSMASK(MOTION)) {
*(ccl_global float4 *)(buffer + kernel_data.film.pass_motion) *= sample_multiplier;
*(ccl_global float *)(buffer + kernel_data.film.pass_motion_weight) *= sample_multiplier;
}
if (kernel_data.film.use_light_pass) {
int light_flag = kernel_data.film.light_pass_flag;
if (light_flag & PASSMASK(DIFFUSE_INDIRECT))
*(ccl_global float3 *)(buffer + kernel_data.film.pass_diffuse_indirect) *= sample_multiplier;
if (light_flag & PASSMASK(GLOSSY_INDIRECT))
*(ccl_global float3 *)(buffer + kernel_data.film.pass_glossy_indirect) *= sample_multiplier;
if (light_flag & PASSMASK(TRANSMISSION_INDIRECT))
*(ccl_global float3 *)(buffer +
kernel_data.film.pass_transmission_indirect) *= sample_multiplier;
if (light_flag & PASSMASK(VOLUME_INDIRECT))
*(ccl_global float3 *)(buffer + kernel_data.film.pass_volume_indirect) *= sample_multiplier;
if (light_flag & PASSMASK(DIFFUSE_DIRECT))
*(ccl_global float3 *)(buffer + kernel_data.film.pass_diffuse_direct) *= sample_multiplier;
if (light_flag & PASSMASK(GLOSSY_DIRECT))
*(ccl_global float3 *)(buffer + kernel_data.film.pass_glossy_direct) *= sample_multiplier;
if (light_flag & PASSMASK(TRANSMISSION_DIRECT))
*(ccl_global float3 *)(buffer +
kernel_data.film.pass_transmission_direct) *= sample_multiplier;
if (light_flag & PASSMASK(VOLUME_DIRECT))
*(ccl_global float3 *)(buffer + kernel_data.film.pass_volume_direct) *= sample_multiplier;
if (light_flag & PASSMASK(EMISSION))
*(ccl_global float3 *)(buffer + kernel_data.film.pass_emission) *= sample_multiplier;
if (light_flag & PASSMASK(BACKGROUND))
*(ccl_global float3 *)(buffer + kernel_data.film.pass_background) *= sample_multiplier;
if (light_flag & PASSMASK(AO))
*(ccl_global float3 *)(buffer + kernel_data.film.pass_ao) *= sample_multiplier;
if (light_flag & PASSMASK(DIFFUSE_COLOR))
*(ccl_global float3 *)(buffer + kernel_data.film.pass_diffuse_color) *= sample_multiplier;
if (light_flag & PASSMASK(GLOSSY_COLOR))
*(ccl_global float3 *)(buffer + kernel_data.film.pass_glossy_color) *= sample_multiplier;
if (light_flag & PASSMASK(TRANSMISSION_COLOR))
*(ccl_global float3 *)(buffer +
kernel_data.film.pass_transmission_color) *= sample_multiplier;
}
#endif
#ifdef __DENOISING_FEATURES__
# define scale_float3_variance(buffer, offset, scale) \
*(buffer + offset) *= scale; \
*(buffer + offset + 1) *= scale; \
*(buffer + offset + 2) *= scale; \
*(buffer + offset + 3) *= scale * scale; \
*(buffer + offset + 4) *= scale * scale; \
*(buffer + offset + 5) *= scale * scale;
# define scale_shadow_variance(buffer, offset, scale) \
*(buffer + offset) *= scale; \
*(buffer + offset + 1) *= scale; \
*(buffer + offset + 2) *= scale * scale;
if (kernel_data.film.pass_denoising_data) {
scale_shadow_variance(
buffer, kernel_data.film.pass_denoising_data + DENOISING_PASS_SHADOW_A, sample_multiplier);
scale_shadow_variance(
buffer, kernel_data.film.pass_denoising_data + DENOISING_PASS_SHADOW_B, sample_multiplier);
if (kernel_data.film.pass_denoising_clean) {
scale_float3_variance(
buffer, kernel_data.film.pass_denoising_data + DENOISING_PASS_COLOR, sample_multiplier);
*(buffer + kernel_data.film.pass_denoising_clean) *= sample_multiplier;
*(buffer + kernel_data.film.pass_denoising_clean + 1) *= sample_multiplier;
*(buffer + kernel_data.film.pass_denoising_clean + 2) *= sample_multiplier;
}
else {
scale_float3_variance(
buffer, kernel_data.film.pass_denoising_data + DENOISING_PASS_COLOR, sample_multiplier);
}
scale_float3_variance(
buffer, kernel_data.film.pass_denoising_data + DENOISING_PASS_NORMAL, sample_multiplier);
scale_float3_variance(
buffer, kernel_data.film.pass_denoising_data + DENOISING_PASS_ALBEDO, sample_multiplier);
*(buffer + kernel_data.film.pass_denoising_data + DENOISING_PASS_DEPTH) *= sample_multiplier;
*(buffer + kernel_data.film.pass_denoising_data + DENOISING_PASS_DEPTH +
1) *= sample_multiplier * sample_multiplier;
}
#endif /* __DENOISING_FEATURES__ */
if (kernel_data.film.cryptomatte_passes) {
int num_slots = 0;
num_slots += (kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) ? 1 : 0;
num_slots += (kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) ? 1 : 0;
num_slots += (kernel_data.film.cryptomatte_passes & CRYPT_ASSET) ? 1 : 0;
num_slots = num_slots * 2 * kernel_data.film.cryptomatte_depth;
ccl_global float2 *id_buffer = (ccl_global float2 *)(buffer +
kernel_data.film.pass_cryptomatte);
for (int slot = 0; slot < num_slots; slot++) {
id_buffer[slot].y *= sample_multiplier;
}
}
}
/* This is a simple box filter in two passes.
* When a pixel demands more adaptive samples, let its neighboring pixels draw more samples too. */
ccl_device bool kernel_do_adaptive_filter_x(KernelGlobals *kg, int y, ccl_global WorkTile *tile)
{
bool any = false;
bool prev = false;
for (int x = tile->x; x < tile->x + tile->w; ++x) {
int index = tile->offset + x + y * tile->stride;
ccl_global float *buffer = tile->buffer + index * kernel_data.film.pass_stride;
ccl_global float4 *aux = (ccl_global float4 *)(buffer +
kernel_data.film.pass_adaptive_aux_buffer);
if (aux->w == 0.0f) {
any = true;
if (x > tile->x && !prev) {
index = index - 1;
buffer = tile->buffer + index * kernel_data.film.pass_stride;
aux = (ccl_global float4 *)(buffer + kernel_data.film.pass_adaptive_aux_buffer);
aux->w = 0.0f;
}
prev = true;
}
else {
if (prev) {
aux->w = 0.0f;
}
prev = false;
}
}
return any;
}
ccl_device bool kernel_do_adaptive_filter_y(KernelGlobals *kg, int x, ccl_global WorkTile *tile)
{
bool prev = false;
bool any = false;
for (int y = tile->y; y < tile->y + tile->h; ++y) {
int index = tile->offset + x + y * tile->stride;
ccl_global float *buffer = tile->buffer + index * kernel_data.film.pass_stride;
ccl_global float4 *aux = (ccl_global float4 *)(buffer +
kernel_data.film.pass_adaptive_aux_buffer);
if (aux->w == 0.0f) {
any = true;
if (y > tile->y && !prev) {
index = index - tile->stride;
buffer = tile->buffer + index * kernel_data.film.pass_stride;
aux = (ccl_global float4 *)(buffer + kernel_data.film.pass_adaptive_aux_buffer);
aux->w = 0.0f;
}
prev = true;
}
else {
if (prev) {
aux->w = 0.0f;
}
prev = false;
}
}
return any;
}
CCL_NAMESPACE_END
#endif /* __KERNEL_ADAPTIVE_SAMPLING_H__ */

View File

@@ -195,4 +195,35 @@ ccl_device void cmj_sample_2D(int s, int N, int p, float *fx, float *fy)
}
#endif
ccl_device float pmj_sample_1D(KernelGlobals *kg, int sample, int rng_hash, int dimension)
{
/* Fallback to random */
if (sample > NUM_PMJ_SAMPLES) {
int p = rng_hash + dimension;
return cmj_randfloat(sample, p);
}
uint tmp_rng = cmj_hash_simple(dimension, rng_hash);
int index = ((dimension % NUM_PMJ_PATTERNS) * NUM_PMJ_SAMPLES + sample) * 2;
return __uint_as_float(kernel_tex_fetch(__sample_pattern_lut, index) ^ (tmp_rng & 0x007fffff)) -
1.0f;
}
ccl_device void pmj_sample_2D(
KernelGlobals *kg, int sample, int rng_hash, int dimension, float *fx, float *fy)
{
if (sample > NUM_PMJ_SAMPLES) {
int p = rng_hash + dimension;
*fx = cmj_randfloat(sample, p);
*fy = cmj_randfloat(sample, p + 1);
}
uint tmp_rng = cmj_hash_simple(dimension, rng_hash);
int index = ((dimension % NUM_PMJ_PATTERNS) * NUM_PMJ_SAMPLES + sample) * 2;
*fx = __uint_as_float(kernel_tex_fetch(__sample_pattern_lut, index) ^ (tmp_rng & 0x007fffff)) -
1.0f;
tmp_rng = cmj_hash_simple(dimension + 1, rng_hash);
*fy = __uint_as_float(kernel_tex_fetch(__sample_pattern_lut, index + 1) ^
(tmp_rng & 0x007fffff)) -
1.0f;
}
CCL_NAMESPACE_END

View File

@@ -29,7 +29,9 @@ ccl_device_inline void kernel_write_denoising_shadow(KernelGlobals *kg,
if (kernel_data.film.pass_denoising_data == 0)
return;
buffer += (sample & 1) ? DENOISING_PASS_SHADOW_B : DENOISING_PASS_SHADOW_A;
buffer += sample_is_even(kernel_data.integrator.sampling_pattern, sample) ?
DENOISING_PASS_SHADOW_B :
DENOISING_PASS_SHADOW_A;
path_total = ensure_finite(path_total);
path_total_shaded = ensure_finite(path_total_shaded);
@@ -386,6 +388,41 @@ ccl_device_inline void kernel_write_result(KernelGlobals *kg,
#ifdef __KERNEL_DEBUG__
kernel_write_debug_passes(kg, buffer, L);
#endif
/* Adaptive Sampling. Fill the additional buffer with the odd samples and calculate our stopping
criteria. This is the heuristic from "A hierarchical automatic stopping condition for Monte
Carlo global illumination" except that here it is applied per pixel and not in hierarchical
tiles. */
if (kernel_data.film.pass_adaptive_aux_buffer &&
kernel_data.integrator.adaptive_threshold > 0.0f) {
if (sample_is_even(kernel_data.integrator.sampling_pattern, sample)) {
kernel_write_pass_float4(buffer + kernel_data.film.pass_adaptive_aux_buffer,
make_float4(L_sum.x * 2.0f, L_sum.y * 2.0f, L_sum.z * 2.0f, 0.0f));
}
#ifdef __KERNEL_CPU__
if (sample > kernel_data.integrator.adaptive_min_samples &&
(sample & (ADAPTIVE_SAMPLE_STEP - 1)) == (ADAPTIVE_SAMPLE_STEP - 1)) {
kernel_do_adaptive_stopping(kg, buffer, sample);
}
#endif
}
/* Write the sample count as negative numbers initially to mark the samples as in progress.
* Once the tile has finished rendering, the sign gets flipped and all the pixel values
* are scaled as if they were taken at a uniform sample count. */
if (kernel_data.film.pass_sample_count) {
/* Make sure it's a negative number. In progressive refine mode, this bit gets flipped between
* passes. */
#ifdef __ATOMIC_PASS_WRITE__
atomic_fetch_and_or_uint32((ccl_global uint *)(buffer + kernel_data.film.pass_sample_count),
0x80000000);
#else
if (buffer[kernel_data.film.pass_sample_count] > 0) {
buffer[kernel_data.film.pass_sample_count] *= -1.0f;
}
#endif
kernel_write_pass_float(buffer + kernel_data.film.pass_sample_count, -1.0f);
}
}
CCL_NAMESPACE_END

View File

@@ -18,6 +18,7 @@
# include "kernel/osl/osl_shader.h"
#endif
// clang-format off
#include "kernel/kernel_random.h"
#include "kernel/kernel_projection.h"
#include "kernel/kernel_montecarlo.h"
@@ -31,6 +32,7 @@
#include "kernel/kernel_accumulate.h"
#include "kernel/kernel_shader.h"
#include "kernel/kernel_light.h"
#include "kernel/kernel_adaptive_sampling.h"
#include "kernel/kernel_passes.h"
#if defined(__VOLUME__) || defined(__SUBSURFACE__)
@@ -48,6 +50,7 @@
#include "kernel/kernel_path_surface.h"
#include "kernel/kernel_path_volume.h"
#include "kernel/kernel_path_subsurface.h"
// clang-format on
CCL_NAMESPACE_BEGIN
@@ -656,6 +659,14 @@ ccl_device void kernel_path_trace(
buffer += index * pass_stride;
if (kernel_data.film.pass_adaptive_aux_buffer) {
ccl_global float4 *aux = (ccl_global float4 *)(buffer +
kernel_data.film.pass_adaptive_aux_buffer);
if (aux->w > 0.0f) {
return;
}
}
/* Initialize random numbers and sample ray. */
uint rng_hash;
Ray ray;

View File

@@ -523,6 +523,14 @@ ccl_device void kernel_branched_path_trace(
buffer += index * pass_stride;
if (kernel_data.film.pass_adaptive_aux_buffer) {
ccl_global float4 *aux = (ccl_global float4 *)(buffer +
kernel_data.film.pass_adaptive_aux_buffer);
if (aux->w > 0.0f) {
return;
}
}
/* initialize random numbers and ray */
uint rng_hash;
Ray ray;

View File

@@ -43,7 +43,7 @@ ccl_device uint sobol_dimension(KernelGlobals *kg, int index, int dimension)
uint i = index + SOBOL_SKIP;
for (int j = 0, x; (x = find_first_set(i)); i >>= x) {
j += x;
result ^= kernel_tex_fetch(__sobol_directions, 32 * dimension + j - 1);
result ^= kernel_tex_fetch(__sample_pattern_lut, 32 * dimension + j - 1);
}
return result;
}
@@ -56,7 +56,9 @@ ccl_device_forceinline float path_rng_1D(
#ifdef __DEBUG_CORRELATION__
return (float)drand48();
#endif
if (kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_PMJ) {
return pmj_sample_1D(kg, sample, rng_hash, dimension);
}
#ifdef __CMJ__
# ifdef __SOBOL__
if (kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_CMJ)
@@ -99,7 +101,10 @@ ccl_device_forceinline void path_rng_2D(KernelGlobals *kg,
*fy = (float)drand48();
return;
#endif
if (kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_PMJ) {
pmj_sample_2D(kg, sample, rng_hash, dimension, fx, fy);
return;
}
#ifdef __CMJ__
# ifdef __SOBOL__
if (kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_CMJ)
@@ -284,4 +289,28 @@ ccl_device float lcg_step_float_addrspace(ccl_addr_space uint *rng)
return (float)*rng * (1.0f / (float)0xFFFFFFFF);
}
ccl_device_inline bool sample_is_even(int pattern, int sample)
{
if (pattern == SAMPLING_PATTERN_PMJ) {
/* See Section 10.2.1, "Progressive Multi-Jittered Sample Sequences", Christensen et al.
* We can use this to get divide sample sequence into two classes for easier variance
* estimation. There must be a more elegant way of writing this? */
#if defined(__GNUC__) && !defined(__KERNEL_GPU__)
return __builtin_popcount(sample & 0xaaaaaaaa) & 1;
#elif defined(__NVCC__)
return __popc(sample & 0xaaaaaaaa) & 1;
#else
int i = sample & 0xaaaaaaaa;
i = i - ((i >> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
i = (((i + (i >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
return i & 1;
#endif
}
else {
/* TODO(Stefan): Are there reliable ways of dividing CMJ and Sobol into two classes? */
return sample & 0x1;
}
}
CCL_NAMESPACE_END

View File

@@ -23,10 +23,12 @@
* Release.
*/
// clang-format off
#include "kernel/closure/alloc.h"
#include "kernel/closure/bsdf_util.h"
#include "kernel/closure/bsdf.h"
#include "kernel/closure/emissive.h"
// clang-format on
#include "kernel/svm/svm.h"

View File

@@ -77,7 +77,7 @@ KERNEL_TEX(KernelShader, __shaders)
KERNEL_TEX(float, __lookup_table)
/* sobol */
KERNEL_TEX(uint, __sobol_directions)
KERNEL_TEX(uint, __sample_pattern_lut)
/* image textures */
KERNEL_TEX(TextureInfo, __texture_info)

View File

@@ -63,6 +63,11 @@ CCL_NAMESPACE_BEGIN
#define VOLUME_STACK_SIZE 32
/* Adaptive sampling constants */
#define ADAPTIVE_SAMPLE_STEP 4
static_assert((ADAPTIVE_SAMPLE_STEP & (ADAPTIVE_SAMPLE_STEP - 1)) == 0,
"ADAPTIVE_SAMPLE_STEP must be power of two for bitwise operations to work");
/* Split kernel constants */
#define WORK_POOL_SIZE_GPU 64
#define WORK_POOL_SIZE_CPU 1
@@ -267,6 +272,7 @@ enum PathTraceDimension {
enum SamplingPattern {
SAMPLING_PATTERN_SOBOL = 0,
SAMPLING_PATTERN_CMJ = 1,
SAMPLING_PATTERN_PMJ = 2,
SAMPLING_NUM_PATTERNS,
};
@@ -373,6 +379,8 @@ typedef enum PassType {
PASS_CRYPTOMATTE,
PASS_AOV_COLOR,
PASS_AOV_VALUE,
PASS_ADAPTIVE_AUX_BUFFER,
PASS_SAMPLE_COUNT,
PASS_CATEGORY_MAIN_END = 31,
PASS_MIST = 32,
@@ -1222,6 +1230,9 @@ typedef struct KernelFilm {
int cryptomatte_depth;
int pass_cryptomatte;
int pass_adaptive_aux_buffer;
int pass_sample_count;
int pass_mist;
float mist_start;
float mist_inv_depth;
@@ -1255,6 +1266,8 @@ typedef struct KernelFilm {
int display_divide_pass_stride;
int use_display_exposure;
int use_display_pass_alpha;
int pad3, pad4, pad5;
} KernelFilm;
static_assert_align(KernelFilm, 16);
@@ -1336,6 +1349,8 @@ typedef struct KernelIntegrator {
/* sampler */
int sampling_pattern;
int aa_samples;
int adaptive_min_samples;
float adaptive_threshold;
/* volume render */
int use_volumes;
@@ -1347,7 +1362,7 @@ typedef struct KernelIntegrator {
int max_closures;
int pad1;
int pad1, pad2, pad3;
} KernelIntegrator;
static_assert_align(KernelIntegrator, 16);
@@ -1661,12 +1676,16 @@ typedef struct WorkTile {
uint start_sample;
uint num_samples;
uint offset;
int offset;
uint stride;
ccl_global float *buffer;
} WorkTile;
/* Precoumputed sample table sizes for PMJ02 sampler. */
#define NUM_PMJ_SAMPLES 64 * 64
#define NUM_PMJ_PATTERNS 48
CCL_NAMESPACE_END
#endif /* __KERNEL_TYPES_H__ */

View File

@@ -23,41 +23,6 @@ CCL_NAMESPACE_BEGIN
* Utility functions for work stealing
*/
#ifdef __KERNEL_OPENCL__
# pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
#endif
#ifdef __SPLIT_KERNEL__
/* Returns true if there is work */
ccl_device bool get_next_work(KernelGlobals *kg,
ccl_global uint *work_pools,
uint total_work_size,
uint ray_index,
ccl_private uint *global_work_index)
{
/* With a small amount of work there may be more threads than work due to
* rounding up of global size, stop such threads immediately. */
if (ray_index >= total_work_size) {
return false;
}
/* Increase atomic work index counter in pool. */
uint pool = ray_index / WORK_POOL_SIZE;
uint work_index = atomic_fetch_and_inc_uint32(&work_pools[pool]);
/* Map per-pool work index to a global work index. */
uint global_size = ccl_global_size(0) * ccl_global_size(1);
kernel_assert(global_size % WORK_POOL_SIZE == 0);
kernel_assert(ray_index < global_size);
*global_work_index = (work_index / WORK_POOL_SIZE) * global_size + (pool * WORK_POOL_SIZE) +
(work_index % WORK_POOL_SIZE);
/* Test if all work for this pool is done. */
return (*global_work_index < total_work_size);
}
#endif
/* Map global work index to tile, pixel X/Y and sample. */
ccl_device_inline void get_work_pixel(ccl_global const WorkTile *tile,
uint global_work_index,
@@ -82,6 +47,71 @@ ccl_device_inline void get_work_pixel(ccl_global const WorkTile *tile,
*sample = tile->start_sample + sample_offset;
}
#ifdef __KERNEL_OPENCL__
# pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
#endif
#ifdef __SPLIT_KERNEL__
/* Returns true if there is work */
ccl_device bool get_next_work_item(KernelGlobals *kg,
ccl_global uint *work_pools,
uint total_work_size,
uint ray_index,
ccl_private uint *global_work_index)
{
/* With a small amount of work there may be more threads than work due to
* rounding up of global size, stop such threads immediately. */
if (ray_index >= total_work_size) {
return false;
}
/* Increase atomic work index counter in pool. */
uint pool = ray_index / WORK_POOL_SIZE;
uint work_index = atomic_fetch_and_inc_uint32(&work_pools[pool]);
/* Map per-pool work index to a global work index. */
uint global_size = ccl_global_size(0) * ccl_global_size(1);
kernel_assert(global_size % WORK_POOL_SIZE == 0);
kernel_assert(ray_index < global_size);
*global_work_index = (work_index / WORK_POOL_SIZE) * global_size + (pool * WORK_POOL_SIZE) +
(work_index % WORK_POOL_SIZE);
/* Test if all work for this pool is done. */
return (*global_work_index < total_work_size);
}
ccl_device bool get_next_work(KernelGlobals *kg,
ccl_global uint *work_pools,
uint total_work_size,
uint ray_index,
ccl_private uint *global_work_index)
{
bool got_work = false;
if (kernel_data.film.pass_adaptive_aux_buffer) {
do {
got_work = get_next_work_item(kg, work_pools, total_work_size, ray_index, global_work_index);
if (got_work) {
ccl_global WorkTile *tile = &kernel_split_params.tile;
uint x, y, sample;
get_work_pixel(tile, *global_work_index, &x, &y, &sample);
uint buffer_offset = (tile->offset + x + y * tile->stride) * kernel_data.film.pass_stride;
ccl_global float *buffer = kernel_split_params.tile.buffer + buffer_offset;
ccl_global float4 *aux = (ccl_global float4 *)(buffer +
kernel_data.film.pass_adaptive_aux_buffer);
if (aux->w == 0.0f) {
break;
}
}
} while (got_work);
}
else {
got_work = get_next_work_item(kg, work_pools, total_work_size, ray_index, global_work_index);
}
return got_work;
}
#endif
CCL_NAMESPACE_END
#endif /* __KERNEL_WORK_STEALING_H__ */

View File

@@ -89,5 +89,9 @@ DECLARE_SPLIT_KERNEL_FUNCTION(enqueue_inactive)
DECLARE_SPLIT_KERNEL_FUNCTION(next_iteration_setup)
DECLARE_SPLIT_KERNEL_FUNCTION(indirect_subsurface)
DECLARE_SPLIT_KERNEL_FUNCTION(buffer_update)
DECLARE_SPLIT_KERNEL_FUNCTION(adaptive_stopping)
DECLARE_SPLIT_KERNEL_FUNCTION(adaptive_filter_x)
DECLARE_SPLIT_KERNEL_FUNCTION(adaptive_filter_y)
DECLARE_SPLIT_KERNEL_FUNCTION(adaptive_adjust_samples)
#undef KERNEL_ARCH

View File

@@ -20,6 +20,7 @@
* simply includes this file without worry of copying actual implementation over.
*/
// clang-format off
#include "kernel/kernel_compat_cpu.h"
#ifndef KERNEL_STUB
@@ -58,6 +59,10 @@
# include "kernel/split/kernel_next_iteration_setup.h"
# include "kernel/split/kernel_indirect_subsurface.h"
# include "kernel/split/kernel_buffer_update.h"
# include "kernel/split/kernel_adaptive_stopping.h"
# include "kernel/split/kernel_adaptive_filter_x.h"
# include "kernel/split/kernel_adaptive_filter_y.h"
# include "kernel/split/kernel_adaptive_adjust_samples.h"
# endif /* __SPLIT_KERNEL__ */
#else
# define STUB_ASSERT(arch, name) \
@@ -67,6 +72,7 @@
# include "kernel/split/kernel_data_init.h"
# endif /* __SPLIT_KERNEL__ */
#endif /* KERNEL_STUB */
// clang-format on
CCL_NAMESPACE_BEGIN
@@ -204,6 +210,10 @@ DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(enqueue_inactive, uint)
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(next_iteration_setup, uint)
DEFINE_SPLIT_KERNEL_FUNCTION(indirect_subsurface)
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(buffer_update, uint)
DEFINE_SPLIT_KERNEL_FUNCTION(adaptive_stopping)
DEFINE_SPLIT_KERNEL_FUNCTION(adaptive_filter_x)
DEFINE_SPLIT_KERNEL_FUNCTION(adaptive_filter_y)
DEFINE_SPLIT_KERNEL_FUNCTION(adaptive_adjust_samples)
#endif /* __SPLIT_KERNEL__ */
#undef KERNEL_STUB

View File

@@ -33,6 +33,7 @@
#include "kernel/kernel_path_branched.h"
#include "kernel/kernel_bake.h"
#include "kernel/kernel_work_stealing.h"
#include "kernel/kernel_adaptive_sampling.h"
/* kernels */
extern "C" __global__ void
@@ -81,6 +82,75 @@ kernel_cuda_branched_path_trace(WorkTile *tile, uint total_work_size)
}
#endif
extern "C" __global__ void
CUDA_LAUNCH_BOUNDS(CUDA_THREADS_BLOCK_WIDTH, CUDA_KERNEL_MAX_REGISTERS)
kernel_cuda_adaptive_stopping(WorkTile *tile, int sample, uint total_work_size)
{
int work_index = ccl_global_id(0);
bool thread_is_active = work_index < total_work_size;
KernelGlobals kg;
if(thread_is_active && kernel_data.film.pass_adaptive_aux_buffer) {
uint x = tile->x + work_index % tile->w;
uint y = tile->y + work_index / tile->w;
int index = tile->offset + x + y * tile->stride;
ccl_global float *buffer = tile->buffer + index * kernel_data.film.pass_stride;
kernel_do_adaptive_stopping(&kg, buffer, sample);
}
}
extern "C" __global__ void
CUDA_LAUNCH_BOUNDS(CUDA_THREADS_BLOCK_WIDTH, CUDA_KERNEL_MAX_REGISTERS)
kernel_cuda_adaptive_filter_x(WorkTile *tile, int sample, uint)
{
KernelGlobals kg;
if(kernel_data.film.pass_adaptive_aux_buffer && sample > kernel_data.integrator.adaptive_min_samples) {
if(ccl_global_id(0) < tile->h) {
int y = tile->y + ccl_global_id(0);
kernel_do_adaptive_filter_x(&kg, y, tile);
}
}
}
extern "C" __global__ void
CUDA_LAUNCH_BOUNDS(CUDA_THREADS_BLOCK_WIDTH, CUDA_KERNEL_MAX_REGISTERS)
kernel_cuda_adaptive_filter_y(WorkTile *tile, int sample, uint)
{
KernelGlobals kg;
if(kernel_data.film.pass_adaptive_aux_buffer && sample > kernel_data.integrator.adaptive_min_samples) {
if(ccl_global_id(0) < tile->w) {
int x = tile->x + ccl_global_id(0);
kernel_do_adaptive_filter_y(&kg, x, tile);
}
}
}
extern "C" __global__ void
CUDA_LAUNCH_BOUNDS(CUDA_THREADS_BLOCK_WIDTH, CUDA_KERNEL_MAX_REGISTERS)
kernel_cuda_adaptive_scale_samples(WorkTile *tile, int start_sample, int sample, uint total_work_size)
{
if(kernel_data.film.pass_adaptive_aux_buffer) {
int work_index = ccl_global_id(0);
bool thread_is_active = work_index < total_work_size;
KernelGlobals kg;
if(thread_is_active) {
uint x = tile->x + work_index % tile->w;
uint y = tile->y + work_index / tile->w;
int index = tile->offset + x + y * tile->stride;
ccl_global float *buffer = tile->buffer + index * kernel_data.film.pass_stride;
if(buffer[kernel_data.film.pass_sample_count] < 0.0f) {
buffer[kernel_data.film.pass_sample_count] = -buffer[kernel_data.film.pass_sample_count];
float sample_multiplier = sample / max((float)start_sample + 1.0f, buffer[kernel_data.film.pass_sample_count]);
if(sample_multiplier != 1.0f) {
kernel_adaptive_post_adjust(&kg, buffer, sample_multiplier);
}
}
else {
kernel_adaptive_post_adjust(&kg, buffer, sample / (sample - 1.0f));
}
}
}
}
extern "C" __global__ void
CUDA_LAUNCH_BOUNDS(CUDA_THREADS_BLOCK_WIDTH, CUDA_KERNEL_MAX_REGISTERS)
kernel_cuda_convert_to_byte(uchar4 *rgba, float *buffer, float sample_scale, int sx, int sy, int sw, int sh, int offset, int stride)

View File

@@ -43,6 +43,10 @@
#include "kernel/split/kernel_next_iteration_setup.h"
#include "kernel/split/kernel_indirect_subsurface.h"
#include "kernel/split/kernel_buffer_update.h"
#include "kernel/split/kernel_adaptive_stopping.h"
#include "kernel/split/kernel_adaptive_filter_x.h"
#include "kernel/split/kernel_adaptive_filter_y.h"
#include "kernel/split/kernel_adaptive_adjust_samples.h"
#include "kernel/kernel_film.h"
@@ -121,6 +125,10 @@ DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(enqueue_inactive, uint)
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(next_iteration_setup, uint)
DEFINE_SPLIT_KERNEL_FUNCTION(indirect_subsurface)
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(buffer_update, uint)
DEFINE_SPLIT_KERNEL_FUNCTION(adaptive_stopping)
DEFINE_SPLIT_KERNEL_FUNCTION(adaptive_filter_x)
DEFINE_SPLIT_KERNEL_FUNCTION(adaptive_filter_y)
DEFINE_SPLIT_KERNEL_FUNCTION(adaptive_adjust_samples)
extern "C" __global__ void
CUDA_LAUNCH_BOUNDS(CUDA_THREADS_BLOCK_WIDTH, CUDA_KERNEL_MAX_REGISTERS)

View File

@@ -0,0 +1,23 @@
/*
* Copyright 2019 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "kernel/kernel_compat_opencl.h"
#include "kernel/split/kernel_split_common.h"
#include "kernel/split/kernel_adaptive_adjust_samples.h"
#define KERNEL_NAME adaptive_adjust_samples
#include "kernel/kernels/opencl/kernel_split_function.h"
#undef KERNEL_NAME

View File

@@ -0,0 +1,23 @@
/*
* Copyright 2019 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "kernel/kernel_compat_opencl.h"
#include "kernel/split/kernel_split_common.h"
#include "kernel/split/kernel_adaptive_filter_x.h"
#define KERNEL_NAME adaptive_filter_x
#include "kernel/kernels/opencl/kernel_split_function.h"
#undef KERNEL_NAME

View File

@@ -0,0 +1,23 @@
/*
* Copyright 2019 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "kernel/kernel_compat_opencl.h"
#include "kernel/split/kernel_split_common.h"
#include "kernel/split/kernel_adaptive_filter_y.h"
#define KERNEL_NAME adaptive_filter_y
#include "kernel/kernels/opencl/kernel_split_function.h"
#undef KERNEL_NAME

View File

@@ -0,0 +1,23 @@
/*
* Copyright 2019 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "kernel/kernel_compat_opencl.h"
#include "kernel/split/kernel_split_common.h"
#include "kernel/split/kernel_adaptive_stopping.h"
#define KERNEL_NAME adaptive_stopping
#include "kernel/kernels/opencl/kernel_split_function.h"
#undef KERNEL_NAME

View File

@@ -28,3 +28,7 @@
#include "kernel/kernels/opencl/kernel_next_iteration_setup.cl"
#include "kernel/kernels/opencl/kernel_indirect_subsurface.cl"
#include "kernel/kernels/opencl/kernel_buffer_update.cl"
#include "kernel/kernels/opencl/kernel_adaptive_stopping.cl"
#include "kernel/kernels/opencl/kernel_adaptive_filter_x.cl"
#include "kernel/kernels/opencl/kernel_adaptive_filter_y.cl"
#include "kernel/kernels/opencl/kernel_adaptive_adjust_samples.cl"

View File

@@ -36,9 +36,11 @@
#include "kernel/osl/osl_closures.h"
// clang-format off
#include "kernel/kernel_compat_cpu.h"
#include "kernel/closure/alloc.h"
#include "kernel/closure/emissive.h"
// clang-format on
CCL_NAMESPACE_BEGIN

View File

@@ -37,10 +37,12 @@
#include "kernel/kernel_compat_cpu.h"
#include "kernel/osl/osl_closures.h"
// clang-format off
#include "kernel/kernel_types.h"
#include "kernel/kernel_montecarlo.h"
#include "kernel/closure/alloc.h"
#include "kernel/closure/bsdf_diffuse_ramp.h"
// clang-format on
CCL_NAMESPACE_BEGIN

View File

@@ -37,9 +37,11 @@
#include "kernel/kernel_compat_cpu.h"
#include "kernel/osl/osl_closures.h"
// clang-format off
#include "kernel/kernel_types.h"
#include "kernel/closure/alloc.h"
#include "kernel/closure/bsdf_phong_ramp.h"
// clang-format on
CCL_NAMESPACE_BEGIN

View File

@@ -36,10 +36,12 @@
#include "kernel/osl/osl_closures.h"
// clang-format off
#include "kernel/kernel_compat_cpu.h"
#include "kernel/kernel_types.h"
#include "kernel/closure/alloc.h"
#include "kernel/closure/emissive.h"
// clang-format on
CCL_NAMESPACE_BEGIN

View File

@@ -35,6 +35,7 @@
#include "kernel/kernel_compat_cpu.h"
#include "kernel/osl/osl_closures.h"
// clang-format off
#include "kernel/kernel_types.h"
#include "kernel/kernel_montecarlo.h"
@@ -43,6 +44,7 @@
#include "kernel/closure/bsdf_diffuse.h"
#include "kernel/closure/bsdf_principled_diffuse.h"
#include "kernel/closure/bssrdf.h"
// clang-format on
CCL_NAMESPACE_BEGIN

View File

@@ -39,6 +39,7 @@
#include "util/util_math.h"
#include "util/util_param.h"
// clang-format off
#include "kernel/kernel_types.h"
#include "kernel/kernel_compat_cpu.h"
#include "kernel/split/kernel_split_data_types.h"
@@ -63,6 +64,7 @@
#include "kernel/closure/bsdf_principled_diffuse.h"
#include "kernel/closure/bsdf_principled_sheen.h"
#include "kernel/closure/volume.h"
// clang-format on
CCL_NAMESPACE_BEGIN

View File

@@ -39,6 +39,7 @@
#include "util/util_logging.h"
#include "util/util_string.h"
// clang-format off
#include "kernel/kernel_compat_cpu.h"
#include "kernel/split/kernel_split_data_types.h"
#include "kernel/kernel_globals.h"
@@ -56,6 +57,7 @@
#include "kernel/kernel_projection.h"
#include "kernel/kernel_accumulate.h"
#include "kernel/kernel_shader.h"
// clang-format on
CCL_NAMESPACE_BEGIN

View File

@@ -16,6 +16,7 @@
#include <OSL/oslexec.h>
// clang-format off
#include "kernel/kernel_compat_cpu.h"
#include "kernel/kernel_montecarlo.h"
#include "kernel/kernel_types.h"
@@ -28,6 +29,7 @@
#include "kernel/osl/osl_globals.h"
#include "kernel/osl/osl_services.h"
#include "kernel/osl/osl_shader.h"
// clang-format on
#include "util/util_foreach.h"

View File

@@ -17,7 +17,8 @@
#include "stdcycles.h"
#include "node_math.h"
shader node_vector_rotate(string type = "axis",
shader node_vector_rotate(int invert = 0,
string type = "axis",
vector VectorIn = vector(0.0, 0.0, 0.0),
point Center = point(0.0, 0.0, 0.0),
point Rotation = point(0.0, 0.0, 0.0),
@@ -26,20 +27,23 @@ shader node_vector_rotate(string type = "axis",
output vector VectorOut = vector(0.0, 0.0, 0.0))
{
if (type == "euler_xyz") {
VectorOut = transform(euler_to_mat(Rotation), VectorIn - Center) + Center;
matrix rmat = (invert) ? transpose(euler_to_mat(Rotation)) : euler_to_mat(Rotation);
VectorOut = transform(rmat, VectorIn - Center) + Center;
}
else if (type == "x_axis") {
VectorOut = rotate(VectorIn - Center, Angle, point(0.0), vector(1.0, 0.0, 0.0)) + Center;
}
else if (type == "y_axis") {
VectorOut = rotate(VectorIn - Center, Angle, point(0.0), vector(0.0, 1.0, 0.0)) + Center;
}
else if (type == "z_axis") {
VectorOut = rotate(VectorIn - Center, Angle, point(0.0), vector(0.0, 0.0, 1.0)) + Center;
}
else { // axis
VectorOut = (length(Axis) != 0.0) ?
rotate(VectorIn - Center, Angle, point(0.0), Axis) + Center :
VectorIn;
else {
float a = (invert) ? -Angle : Angle;
if (type == "x_axis") {
VectorOut = rotate(VectorIn - Center, a, point(0.0), vector(1.0, 0.0, 0.0)) + Center;
}
else if (type == "y_axis") {
VectorOut = rotate(VectorIn - Center, a, point(0.0), vector(0.0, 1.0, 0.0)) + Center;
}
else if (type == "z_axis") {
VectorOut = rotate(VectorIn - Center, a, point(0.0), vector(0.0, 0.0, 1.0)) + Center;
}
else { // axis
VectorOut = (length(Axis) != 0.0) ? rotate(VectorIn - Center, a, point(0.0), Axis) + Center :
VectorIn;
}
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2019 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
CCL_NAMESPACE_BEGIN
ccl_device void kernel_adaptive_adjust_samples(KernelGlobals *kg)
{
int pixel_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
if (pixel_index < kernel_split_params.tile.w * kernel_split_params.tile.h) {
int x = kernel_split_params.tile.x + pixel_index % kernel_split_params.tile.w;
int y = kernel_split_params.tile.y + pixel_index / kernel_split_params.tile.w;
int buffer_offset = (kernel_split_params.tile.offset + x +
y * kernel_split_params.tile.stride) *
kernel_data.film.pass_stride;
ccl_global float *buffer = kernel_split_params.tile.buffer + buffer_offset;
int sample = kernel_split_params.tile.start_sample + kernel_split_params.tile.num_samples;
if (buffer[kernel_data.film.pass_sample_count] < 0.0f) {
buffer[kernel_data.film.pass_sample_count] = -buffer[kernel_data.film.pass_sample_count];
float sample_multiplier = sample / max((float)kernel_split_params.tile.start_sample + 1.0f,
buffer[kernel_data.film.pass_sample_count]);
if (sample_multiplier != 1.0f) {
kernel_adaptive_post_adjust(kg, buffer, sample_multiplier);
}
}
else {
kernel_adaptive_post_adjust(kg, buffer, sample / (sample - 1.0f));
}
}
}
CCL_NAMESPACE_END

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2019 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
CCL_NAMESPACE_BEGIN
ccl_device void kernel_adaptive_filter_x(KernelGlobals *kg)
{
int pixel_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
if (pixel_index < kernel_split_params.tile.h &&
kernel_split_params.tile.start_sample + kernel_split_params.tile.num_samples >=
kernel_data.integrator.adaptive_min_samples) {
int y = kernel_split_params.tile.y + pixel_index;
kernel_do_adaptive_filter_x(kg, y, &kernel_split_params.tile);
}
}
CCL_NAMESPACE_END

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2019 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
CCL_NAMESPACE_BEGIN
ccl_device void kernel_adaptive_filter_y(KernelGlobals *kg)
{
int pixel_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
if (pixel_index < kernel_split_params.tile.w &&
kernel_split_params.tile.start_sample + kernel_split_params.tile.num_samples >=
kernel_data.integrator.adaptive_min_samples) {
int x = kernel_split_params.tile.x + pixel_index;
kernel_do_adaptive_filter_y(kg, x, &kernel_split_params.tile);
}
}
CCL_NAMESPACE_END

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2019 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
CCL_NAMESPACE_BEGIN
ccl_device void kernel_adaptive_stopping(KernelGlobals *kg)
{
int pixel_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
if (pixel_index < kernel_split_params.tile.w * kernel_split_params.tile.h &&
kernel_split_params.tile.start_sample + kernel_split_params.tile.num_samples >=
kernel_data.integrator.adaptive_min_samples) {
int x = kernel_split_params.tile.x + pixel_index % kernel_split_params.tile.w;
int y = kernel_split_params.tile.y + pixel_index / kernel_split_params.tile.w;
int buffer_offset = (kernel_split_params.tile.offset + x +
y * kernel_split_params.tile.stride) *
kernel_data.film.pass_stride;
ccl_global float *buffer = kernel_split_params.tile.buffer + buffer_offset;
kernel_do_adaptive_stopping(kg,
buffer,
kernel_split_params.tile.start_sample +
kernel_split_params.tile.num_samples - 1);
}
}
CCL_NAMESPACE_END

View File

@@ -17,6 +17,7 @@
#ifndef __KERNEL_SPLIT_H__
#define __KERNEL_SPLIT_H__
// clang-format off
#include "kernel/kernel_math.h"
#include "kernel/kernel_types.h"
@@ -52,6 +53,7 @@
#ifdef __BRANCHED_PATH__
# include "kernel/split/kernel_branched.h"
#endif
// clang-format on
CCL_NAMESPACE_BEGIN

View File

@@ -18,6 +18,7 @@
#define __KERNEL_SPLIT_DATA_H__
#include "kernel/split/kernel_split_data_types.h"
#include "kernel/kernel_globals.h"
CCL_NAMESPACE_BEGIN

View File

@@ -25,45 +25,52 @@ ccl_device void svm_node_vector_rotate(ShaderData *sd,
uint result_stack_offset)
{
uint type, vector_stack_offset, rotation_stack_offset, center_stack_offset, axis_stack_offset,
angle_stack_offset;
angle_stack_offset, invert;
svm_unpack_node_uchar3(input_stack_offsets, &type, &vector_stack_offset, &rotation_stack_offset);
svm_unpack_node_uchar4(
input_stack_offsets, &type, &vector_stack_offset, &rotation_stack_offset, &invert);
svm_unpack_node_uchar3(
axis_stack_offsets, &center_stack_offset, &axis_stack_offset, &angle_stack_offset);
float3 vector = stack_load_float3(stack, vector_stack_offset);
float3 center = stack_load_float3(stack, center_stack_offset);
float3 result = make_float3(0.0f, 0.0f, 0.0f);
if (type == NODE_VECTOR_ROTATE_TYPE_EULER_XYZ) {
float3 rotation = stack_load_float3(stack, rotation_stack_offset); // Default XYZ.
Transform rotationTransform = euler_to_transform(rotation);
result = transform_direction(&rotationTransform, vector - center) + center;
}
else {
float3 axis;
switch (type) {
case NODE_VECTOR_ROTATE_TYPE_AXIS_X:
axis = make_float3(1.0f, 0.0f, 0.0f);
break;
case NODE_VECTOR_ROTATE_TYPE_AXIS_Y:
axis = make_float3(0.0f, 1.0f, 0.0f);
break;
case NODE_VECTOR_ROTATE_TYPE_AXIS_Z:
axis = make_float3(0.0f, 0.0f, 1.0f);
break;
default:
axis = normalize(stack_load_float3(stack, axis_stack_offset));
break;
}
float angle = stack_load_float(stack, angle_stack_offset);
result = (len_squared(axis) != 0.0f) ?
rotate_around_axis(vector - center, axis, angle) + center :
vector;
}
/* Output */
if (stack_valid(result_stack_offset)) {
float3 vector = stack_load_float3(stack, vector_stack_offset);
float3 center = stack_load_float3(stack, center_stack_offset);
float3 result = make_float3(0.0f, 0.0f, 0.0f);
if (type == NODE_VECTOR_ROTATE_TYPE_EULER_XYZ) {
float3 rotation = stack_load_float3(stack, rotation_stack_offset); // Default XYZ.
Transform rotationTransform = euler_to_transform(rotation);
if (invert) {
result = transform_direction_transposed(&rotationTransform, vector - center) + center;
}
else {
result = transform_direction(&rotationTransform, vector - center) + center;
}
}
else {
float3 axis;
switch (type) {
case NODE_VECTOR_ROTATE_TYPE_AXIS_X:
axis = make_float3(1.0f, 0.0f, 0.0f);
break;
case NODE_VECTOR_ROTATE_TYPE_AXIS_Y:
axis = make_float3(0.0f, 1.0f, 0.0f);
break;
case NODE_VECTOR_ROTATE_TYPE_AXIS_Z:
axis = make_float3(0.0f, 0.0f, 1.0f);
break;
default:
axis = normalize(stack_load_float3(stack, axis_stack_offset));
break;
}
float angle = stack_load_float(stack, angle_stack_offset);
angle = invert ? -angle : angle;
result = (len_squared(axis) != 0.0f) ?
rotate_around_axis(vector - center, axis, angle) + center :
vector;
}
stack_store_float3(stack, result_stack_offset, result);
}
}

View File

@@ -24,6 +24,7 @@ set(SRC
hair.cpp
image.cpp
integrator.cpp
jitter.cpp
light.cpp
merge.cpp
mesh.cpp
@@ -62,6 +63,7 @@ set(SRC_HEADERS
image.h
integrator.h
light.h
jitter.h
merge.h
mesh.h
nodes.h

View File

@@ -260,6 +260,22 @@ bool RenderBuffers::get_pass_rect(
return false;
}
float *sample_count = NULL;
if (name == "Combined") {
int sample_offset = 0;
for (size_t j = 0; j < params.passes.size(); j++) {
Pass &pass = params.passes[j];
if (pass.type != PASS_SAMPLE_COUNT) {
sample_offset += pass.components;
continue;
}
else {
sample_count = buffer.data() + sample_offset;
break;
}
}
}
int pass_offset = 0;
for (size_t j = 0; j < params.passes.size(); j++) {
@@ -420,6 +436,11 @@ bool RenderBuffers::get_pass_rect(
}
else {
for (int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
if (sample_count && sample_count[i * pass_stride] < 0.0f) {
scale = (pass.filter) ? -1.0f / (sample_count[i * pass_stride]) : 1.0f;
scale_exposure = (pass.exposure) ? scale * exposure : scale;
}
float4 f = make_float4(in[0], in[1], in[2], in[3]);
pixels[0] = f.x * scale_exposure;

View File

@@ -130,7 +130,7 @@ class DisplayBuffer {
class RenderTile {
public:
typedef enum { PATH_TRACE, DENOISE } Task;
typedef enum { PATH_TRACE = (1 << 0), DENOISE = (1 << 1) } Task;
Task task;
int x, y, w, h;

View File

@@ -29,6 +29,7 @@
#include "util/util_vector.h"
/* needed for calculating differentials */
// clang-format off
#include "kernel/kernel_compat_cpu.h"
#include "kernel/split/kernel_split_data.h"
#include "kernel/kernel_globals.h"
@@ -36,6 +37,7 @@
#include "kernel/kernel_differential.h"
#include "kernel/kernel_montecarlo.h"
#include "kernel/kernel_camera.h"
// clang-format on
CCL_NAMESPACE_BEGIN

View File

@@ -15,13 +15,16 @@
*/
#include "render/coverage.h"
#include "render/buffers.h"
#include "kernel/kernel_compat_cpu.h"
#include "kernel/kernel_types.h"
#include "kernel/split/kernel_split_data.h"
#include "kernel/kernel_globals.h"
#include "kernel/kernel_id_passes.h"
#include "kernel/kernel_types.h"
#include "util/util_map.h"
#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN

View File

@@ -14,18 +14,19 @@
* limitations under the License.
*/
#include "render/buffers.h"
#include "kernel/kernel_compat_cpu.h"
#include "kernel/split/kernel_split_data.h"
#include "kernel/kernel_globals.h"
#ifndef __COVERAGE_H__
#define __COVERAGE_H__
#include "util/util_map.h"
#include "util/util_vector.h"
#ifndef __COVERAGE_H__
# define __COVERAGE_H__
CCL_NAMESPACE_BEGIN
struct KernelGlobals;
class RenderTile;
typedef unordered_map<float, float> CoverageMap;
class Coverage {
public:
Coverage(KernelGlobals *kg_, RenderTile &tile_) : kg(kg_), tile(tile_)

View File

@@ -183,6 +183,13 @@ void Pass::add(PassType type, vector<Pass> &passes, const char *name)
case PASS_CRYPTOMATTE:
pass.components = 4;
break;
case PASS_ADAPTIVE_AUX_BUFFER:
pass.components = 4;
break;
case PASS_SAMPLE_COUNT:
pass.components = 1;
pass.exposure = false;
break;
case PASS_AOV_COLOR:
pass.components = 4;
break;
@@ -311,6 +318,7 @@ NODE_DEFINE(Film)
SOCKET_BOOLEAN(denoising_clean_pass, "Generate Denoising Clean Pass", false);
SOCKET_BOOLEAN(denoising_prefiltered_pass, "Generate Denoising Prefiltered Pass", false);
SOCKET_INT(denoising_flags, "Denoising Flags", 0);
SOCKET_BOOLEAN(use_adaptive_sampling, "Use Adaptive Sampling", false);
return type;
}
@@ -482,6 +490,12 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
kfilm->pass_stride;
have_cryptomatte = true;
break;
case PASS_ADAPTIVE_AUX_BUFFER:
kfilm->pass_adaptive_aux_buffer = kfilm->pass_stride;
break;
case PASS_SAMPLE_COUNT:
kfilm->pass_sample_count = kfilm->pass_stride;
break;
case PASS_AOV_COLOR:
if (!have_aov_color) {
kfilm->pass_aov_color = kfilm->pass_stride;

View File

@@ -81,6 +81,8 @@ class Film : public Node {
CryptomatteType cryptomatte_passes;
int cryptomatte_depth;
bool use_adaptive_sampling;
bool need_update;
Film();

View File

@@ -18,12 +18,16 @@
#include "render/background.h"
#include "render/integrator.h"
#include "render/film.h"
#include "render/jitter.h"
#include "render/light.h"
#include "render/scene.h"
#include "render/shader.h"
#include "render/sobol.h"
#include "kernel/kernel_types.h"
#include "util/util_foreach.h"
#include "util/util_logging.h"
#include "util/util_hash.h"
CCL_NAMESPACE_BEGIN
@@ -66,6 +70,9 @@ NODE_DEFINE(Integrator)
SOCKET_INT(volume_samples, "Volume Samples", 1);
SOCKET_INT(start_sample, "Start Sample", 0);
SOCKET_FLOAT(adaptive_threshold, "Adaptive Threshold", 0.0f);
SOCKET_INT(adaptive_min_samples, "Adaptive Min Samples", 0);
SOCKET_BOOLEAN(sample_all_lights_direct, "Sample All Lights Direct", true);
SOCKET_BOOLEAN(sample_all_lights_indirect, "Sample All Lights Indirect", true);
SOCKET_FLOAT(light_sampling_threshold, "Light Sampling Threshold", 0.05f);
@@ -78,6 +85,7 @@ NODE_DEFINE(Integrator)
static NodeEnum sampling_pattern_enum;
sampling_pattern_enum.insert("sobol", SAMPLING_PATTERN_SOBOL);
sampling_pattern_enum.insert("cmj", SAMPLING_PATTERN_CMJ);
sampling_pattern_enum.insert("pmj", SAMPLING_PATTERN_PMJ);
SOCKET_ENUM(sampling_pattern, "Sampling Pattern", sampling_pattern_enum, SAMPLING_PATTERN_SOBOL);
return type;
@@ -174,6 +182,22 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
kintegrator->sampling_pattern = sampling_pattern;
kintegrator->aa_samples = aa_samples;
if (aa_samples > 0 && adaptive_min_samples == 0) {
kintegrator->adaptive_min_samples = max(4, (int)sqrtf(aa_samples));
VLOG(1) << "Cycles adaptive sampling: automatic min samples = "
<< kintegrator->adaptive_min_samples;
}
else {
kintegrator->adaptive_min_samples = max(4, adaptive_min_samples);
}
if (aa_samples > 0 && adaptive_threshold == 0.0f) {
kintegrator->adaptive_threshold = max(0.001f, 1.0f / (float)aa_samples);
VLOG(1) << "Cycles adaptive sampling: automatic threshold = "
<< kintegrator->adaptive_threshold;
}
else {
kintegrator->adaptive_threshold = adaptive_threshold;
}
if (light_sampling_threshold > 0.0f) {
kintegrator->light_inv_rr_threshold = 1.0f / light_sampling_threshold;
@@ -203,18 +227,34 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
int dimensions = PRNG_BASE_NUM + max_samples * PRNG_BOUNCE_NUM;
dimensions = min(dimensions, SOBOL_MAX_DIMENSIONS);
uint *directions = dscene->sobol_directions.alloc(SOBOL_BITS * dimensions);
if (sampling_pattern == SAMPLING_PATTERN_SOBOL) {
uint *directions = dscene->sample_pattern_lut.alloc(SOBOL_BITS * dimensions);
sobol_generate_direction_vectors((uint(*)[SOBOL_BITS])directions, dimensions);
sobol_generate_direction_vectors((uint(*)[SOBOL_BITS])directions, dimensions);
dscene->sobol_directions.copy_to_device();
dscene->sample_pattern_lut.copy_to_device();
}
else {
constexpr int sequence_size = NUM_PMJ_SAMPLES;
constexpr int num_sequences = NUM_PMJ_PATTERNS;
float2 *directions = (float2 *)dscene->sample_pattern_lut.alloc(sequence_size * num_sequences *
2);
TaskPool pool;
for (int j = 0; j < num_sequences; ++j) {
float2 *sequence = directions + j * sequence_size;
pool.push(
function_bind(&progressive_multi_jitter_02_generate_2D, sequence, sequence_size, j));
}
pool.wait_work();
dscene->sample_pattern_lut.copy_to_device();
}
need_update = false;
}
void Integrator::device_free(Device *, DeviceScene *dscene)
{
dscene->sobol_directions.free();
dscene->sample_pattern_lut.free();
}
bool Integrator::modified(const Integrator &integrator)

View File

@@ -75,6 +75,9 @@ class Integrator : public Node {
bool sample_all_lights_indirect;
float light_sampling_threshold;
int adaptive_min_samples;
float adaptive_threshold;
enum Method {
BRANCHED_PATH = 0,
PATH = 1,

View File

@@ -0,0 +1,287 @@
/*
* Copyright 2019 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* This file is based on "Progressive Multi-Jittered Sample Sequences"
* by Per Christensen, Andrew Kensler and Charlie Kilpatrick.
* http://graphics.pixar.com/library/ProgressiveMultiJitteredSampling/paper.pdf
*
* Performance can be improved in the future by implementing the new
* algorithm from Matt Pharr in http://jcgt.org/published/0008/01/04/
* "Efficient Generation of Points that Satisfy Two-Dimensional Elementary Intervals"
*/
#include "render/jitter.h"
#include <math.h>
#include <vector>
CCL_NAMESPACE_BEGIN
static uint cmj_hash(uint i, uint p)
{
i ^= p;
i ^= i >> 17;
i ^= i >> 10;
i *= 0xb36534e5;
i ^= i >> 12;
i ^= i >> 21;
i *= 0x93fc4795;
i ^= 0xdf6e307f;
i ^= i >> 17;
i *= 1 | p >> 18;
return i;
}
static float cmj_randfloat(uint i, uint p)
{
return cmj_hash(i, p) * (1.0f / 4294967808.0f);
}
class PMJ_Generator {
public:
static void generate_2D(float2 points[], int size, int rng_seed_in)
{
PMJ_Generator g(rng_seed_in);
points[0].x = g.rnd();
points[0].y = g.rnd();
int N = 1;
while (N < size) {
g.extend_sequence_even(points, N);
g.extend_sequence_odd(points, 2 * N);
N = 4 * N;
}
}
protected:
PMJ_Generator(int rnd_seed_in) : num_samples(1), rnd_index(2), rnd_seed(rnd_seed_in)
{
}
float rnd()
{
return cmj_randfloat(++rnd_index, rnd_seed);
}
virtual void mark_occupied_strata(float2 points[], int N)
{
int NN = 2 * N;
for (int s = 0; s < NN; ++s) {
occupied1Dx[s] = occupied1Dy[s] = false;
}
for (int s = 0; s < N; ++s) {
int xstratum = (int)(NN * points[s].x);
int ystratum = (int)(NN * points[s].y);
occupied1Dx[xstratum] = true;
occupied1Dy[ystratum] = true;
}
}
virtual void generate_sample_point(
float2 points[], float i, float j, float xhalf, float yhalf, int n, int N)
{
int NN = 2 * N;
float2 pt;
int xstratum, ystratum;
do {
pt.x = (i + 0.5f * (xhalf + rnd())) / n;
xstratum = (int)(NN * pt.x);
} while (occupied1Dx[xstratum]);
do {
pt.y = (j + 0.5f * (yhalf + rnd())) / n;
ystratum = (int)(NN * pt.y);
} while (occupied1Dy[ystratum]);
occupied1Dx[xstratum] = true;
occupied1Dy[ystratum] = true;
points[num_samples] = pt;
++num_samples;
}
void extend_sequence_even(float2 points[], int N)
{
int n = (int)sqrtf(N);
occupied1Dx.resize(2 * N);
occupied1Dy.resize(2 * N);
mark_occupied_strata(points, N);
for (int s = 0; s < N; ++s) {
float2 oldpt = points[s];
float i = floorf(n * oldpt.x);
float j = floorf(n * oldpt.y);
float xhalf = floorf(2.0f * (n * oldpt.x - i));
float yhalf = floorf(2.0f * (n * oldpt.y - j));
xhalf = 1.0f - xhalf;
yhalf = 1.0f - yhalf;
generate_sample_point(points, i, j, xhalf, yhalf, n, N);
}
}
void extend_sequence_odd(float2 points[], int N)
{
int n = (int)sqrtf(N / 2);
occupied1Dx.resize(2 * N);
occupied1Dy.resize(2 * N);
mark_occupied_strata(points, N);
std::vector<float> xhalves(N / 2);
std::vector<float> yhalves(N / 2);
for (int s = 0; s < N / 2; ++s) {
float2 oldpt = points[s];
float i = floorf(n * oldpt.x);
float j = floorf(n * oldpt.y);
float xhalf = floorf(2.0f * (n * oldpt.x - i));
float yhalf = floorf(2.0f * (n * oldpt.y - j));
if (rnd() > 0.5f) {
xhalf = 1.0f - xhalf;
}
else {
yhalf = 1.0f - yhalf;
}
xhalves[s] = xhalf;
yhalves[s] = yhalf;
generate_sample_point(points, i, j, xhalf, yhalf, n, N);
}
for (int s = 0; s < N / 2; ++s) {
float2 oldpt = points[s];
float i = floorf(n * oldpt.x);
float j = floorf(n * oldpt.y);
float xhalf = 1.0f - xhalves[s];
float yhalf = 1.0f - yhalves[s];
generate_sample_point(points, i, j, xhalf, yhalf, n, N);
}
}
std::vector<bool> occupied1Dx, occupied1Dy;
int num_samples;
int rnd_index, rnd_seed;
};
class PMJ02_Generator : public PMJ_Generator {
protected:
void generate_sample_point(
float2 points[], float i, float j, float xhalf, float yhalf, int n, int N) override
{
int NN = 2 * N;
float2 pt;
do {
pt.x = (i + 0.5f * (xhalf + rnd())) / n;
pt.y = (j + 0.5f * (yhalf + rnd())) / n;
} while (is_occupied(pt, NN));
mark_occupied_strata1(pt, NN);
points[num_samples] = pt;
++num_samples;
}
void mark_occupied_strata(float2 points[], int N) override
{
int NN = 2 * N;
int num_shapes = (int)log2f(NN) + 1;
occupiedStrata.resize(num_shapes);
for (int shape = 0; shape < num_shapes; ++shape) {
occupiedStrata[shape].resize(NN);
for (int n = 0; n < NN; ++n) {
occupiedStrata[shape][n] = false;
}
}
for (int s = 0; s < N; ++s) {
mark_occupied_strata1(points[s], NN);
}
}
void mark_occupied_strata1(float2 pt, int NN)
{
int shape = 0;
int xdivs = NN;
int ydivs = 1;
do {
int xstratum = (int)(xdivs * pt.x);
int ystratum = (int)(ydivs * pt.y);
size_t index = ystratum * xdivs + xstratum;
assert(index < NN);
occupiedStrata[shape][index] = true;
shape = shape + 1;
xdivs = xdivs / 2;
ydivs = ydivs * 2;
} while (xdivs > 0);
}
bool is_occupied(float2 pt, int NN)
{
int shape = 0;
int xdivs = NN;
int ydivs = 1;
do {
int xstratum = (int)(xdivs * pt.x);
int ystratum = (int)(ydivs * pt.y);
size_t index = ystratum * xdivs + xstratum;
assert(index < NN);
if (occupiedStrata[shape][index]) {
return true;
}
shape = shape + 1;
xdivs = xdivs / 2;
ydivs = ydivs * 2;
} while (xdivs > 0);
return false;
}
private:
std::vector<std::vector<bool>> occupiedStrata;
};
static void shuffle(float2 points[], int size, int rng_seed)
{
/* Offset samples by 1.0 for faster scrambling in kernel_random.h */
for (int i = 0; i < size; ++i) {
points[i].x += 1.0f;
points[i].y += 1.0f;
}
if (rng_seed == 0) {
return;
}
constexpr int odd[8] = {0, 1, 4, 5, 10, 11, 14, 15};
constexpr int even[8] = {2, 3, 6, 7, 8, 9, 12, 13};
int rng_index = 0;
for (int yy = 0; yy < size / 16; ++yy) {
for (int xx = 0; xx < 8; ++xx) {
int other = (int)(cmj_randfloat(++rng_index, rng_seed) * (8.0f - xx) + xx);
float2 tmp = points[odd[other] + yy * 16];
points[odd[other] + yy * 16] = points[odd[xx] + yy * 16];
points[odd[xx] + yy * 16] = tmp;
}
for (int xx = 0; xx < 8; ++xx) {
int other = (int)(cmj_randfloat(++rng_index, rng_seed) * (8.0f - xx) + xx);
float2 tmp = points[even[other] + yy * 16];
points[even[other] + yy * 16] = points[even[xx] + yy * 16];
points[even[xx] + yy * 16] = tmp;
}
}
}
void progressive_multi_jitter_generate_2D(float2 points[], int size, int rng_seed)
{
PMJ_Generator::generate_2D(points, size, rng_seed);
shuffle(points, size, rng_seed);
}
void progressive_multi_jitter_02_generate_2D(float2 points[], int size, int rng_seed)
{
PMJ02_Generator::generate_2D(points, size, rng_seed);
shuffle(points, size, rng_seed);
}
CCL_NAMESPACE_END

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2019 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __JITTER_H__
#define __JITTER_H__
#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
void progressive_multi_jitter_generate_2D(float2 points[], int size, int rng_seed);
void progressive_multi_jitter_02_generate_2D(float2 points[], int size, int rng_seed);
CCL_NAMESPACE_END
#endif /* __JITTER_H__ */

View File

@@ -23,18 +23,19 @@
#include "render/nodes.h"
#include "render/scene.h"
#include "render/svm.h"
#include "kernel/svm/svm_color_util.h"
#include "kernel/svm/svm_ramp_util.h"
#include "kernel/svm/svm_math_util.h"
#include "kernel/svm/svm_mapping_util.h"
#include "render/osl.h"
#include "render/constant_fold.h"
#include "util/util_sky_model.h"
#include "util/util_foreach.h"
#include "util/util_logging.h"
#include "util/util_sky_model.h"
#include "util/util_transform.h"
#include "kernel/svm/svm_color_util.h"
#include "kernel/svm/svm_mapping_util.h"
#include "kernel/svm/svm_math_util.h"
#include "kernel/svm/svm_ramp_util.h"
CCL_NAMESPACE_BEGIN
/* Texture Mapping */
@@ -6157,6 +6158,8 @@ NODE_DEFINE(VectorRotateNode)
type_enum.insert("euler_xyz", NODE_VECTOR_ROTATE_TYPE_EULER_XYZ);
SOCKET_ENUM(type, "Type", type_enum, NODE_VECTOR_ROTATE_TYPE_AXIS);
SOCKET_BOOLEAN(invert, "Invert", false);
SOCKET_IN_VECTOR(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f));
SOCKET_IN_POINT(rotation, "Rotation", make_float3(0.0f, 0.0f, 0.0f));
SOCKET_IN_POINT(center, "Center", make_float3(0.0f, 0.0f, 0.0f));
@@ -6180,19 +6183,20 @@ void VectorRotateNode::compile(SVMCompiler &compiler)
ShaderInput *angle_in = input("Angle");
ShaderOutput *vector_out = output("Vector");
compiler.add_node(NODE_VECTOR_ROTATE,
compiler.encode_uchar4(type,
compiler.stack_assign(vector_in),
compiler.stack_assign(rotation_in)),
compiler.encode_uchar4(compiler.stack_assign(center_in),
compiler.stack_assign(axis_in),
compiler.stack_assign(angle_in)),
compiler.stack_assign(vector_out));
compiler.add_node(
NODE_VECTOR_ROTATE,
compiler.encode_uchar4(
type, compiler.stack_assign(vector_in), compiler.stack_assign(rotation_in), invert),
compiler.encode_uchar4(compiler.stack_assign(center_in),
compiler.stack_assign(axis_in),
compiler.stack_assign(angle_in)),
compiler.stack_assign(vector_out));
}
void VectorRotateNode::compile(OSLCompiler &compiler)
{
compiler.parameter(this, "type");
compiler.parameter(this, "invert");
compiler.add(this, "node_vector_rotate");
}

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