Compare commits

...

109 Commits

Author SHA1 Message Date
b5cb2d50f4 use multi-function 2021-11-14 14:29:29 +01:00
6ee633575f initial sound sampling 2021-11-14 12:57:00 +01:00
32663fc287 storage 2021-11-14 11:34:37 +01:00
8c40473286 initial nod 2021-11-14 11:29:00 +01:00
7e82c840b7 Fix text editor auto-close with quotes
Back-spacing a quote from the beginning of a line
would delete the quote in-front instead of doing nothing.
2021-11-14 11:26:06 +11:00
2549384baa Cleanup: minor tweaks to auto-close
Spelling and failure to reuse variable missed in review.
2021-11-14 11:11:20 +11:00
73047c69ea BLF: Use Floats for Font Point Sizes
Allow the use of floating-point values for font point sizes, which
allows greater precision and flexibility for text output.

See D8960 for more information, details, and justification.

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

Reviewed by Campbell Barton
2021-11-13 09:39:18 -08:00
e8a8bb67fc Cleanup: Correct order of guard and lock in moviecache_valfree
Fix own mistake in rB7061d1e39fe

In my attempt to quickly address T92838, along with the original bug, I
made a nonsensical choice to use the limiter lock to guard the check
against the cache item itself. While harmless, it is not necessary and
semantically wrong / potentially confusing to future readers of the code.

Differential Revision: https://developer.blender.org/D13122
2021-11-12 20:47:26 -08:00
ab9ec193c3 Fix splash screen showing on startup with files loaded by scripts
Suppressing the splash was only done when passing in an argument from
the command line.

Remove G.file_loaded, as it is misleading, only set once on startup,
replace with G.relbase_valid which is used everywhere else to check
if the file path should be used.
2021-11-13 14:05:27 +11:00
Matheus Santos
c4ea5cb1a3 Text Editor: Auto close relevant characters
Support the ability to close relevant characters like '(', '[' and '{'.

It will also delete the pair character if they're empty.

Ref D13119

Reviewed By: campbellbarton
2021-11-13 13:56:31 +11:00
1143bf281a Cleanup: spelling in comments, comment block formatting 2021-11-13 13:07:13 +11:00
acc800d24d Cleanup: clang-format 2021-11-13 12:47:18 +11:00
dc378bf1a4 Merge branch 'blender-v3.0-release' 2021-11-12 21:57:44 -03:00
0a6f428be7 Fix snapping not performing on selected bones or splines
This is an old issue but never reported as it is only visible in the measure tool snapping.
2021-11-12 21:56:42 -03:00
60b8eb30bb Merge branch 'blender-v3.0-release' 2021-11-12 21:36:35 -03:00
eed48a7322 Cleanup: reference some snap parameters in the snap context itself
This decreases the number of parameters in functions and makes important variables available in more places.
2021-11-12 21:34:19 -03:00
738f4fbc5e Revert "Fix T92636: Vector math node link disconnects when loading old file"
This reverts commit 6b4ca78108.

A simpler fix was used for 3.0, but rBd845ba481c6d2ef already contained
a more complete solution to the problem of inconsistent socket ids.
2021-11-12 17:14:27 -06:00
ebb4aba325 Merge branch 'blender-v3.0-release' 2021-11-12 17:12:39 -06:00
6b4ca78108 Fix T92636: Vector math node link disconnects when loading old file
Previously, unique identifiers for sockets were created automatically,
sometimes using .001 and sometimes _001. Now they are created
manually with the second format, but some files were saved with .001
format. I think this was only an issue in the vector math node.

rBd845ba481c6d fixed this problem in 3.1, but in a more general way.
After I merge this patch to 3.1, I will revert it, since the versioning
added in that commit will make this redundant.

Differential Revision: https://developer.blender.org/D13209
2021-11-12 17:07:38 -06:00
ec432ae998 Merge branch 'blender-v3.0-release' 2021-11-12 14:06:26 -06:00
8d3a771574 Fix: Node Class Type for Select by Handle Type
Change the node class type for Node Select by Handle Type to
NODE_CLASS_INPUT
2021-11-12 14:05:40 -06:00
55c69373e8 Cleanup: split 'initSnappingMode' into more specific functions
This helps to reuse small regions of a function's code elsewhere.

The logic had to be reorganized, theoretically it should behave the same way.
2021-11-12 16:30:01 -03:00
8b13cf5667 Cleanup: move 'imm_drawcircball' to 'gpu_immediate_util.c' 2021-11-12 16:30:01 -03:00
5941c39fbf Cleanup: fix some comments in the transform code 2021-11-12 16:30:01 -03:00
30f9034182 Cleanup: use 't->tsnap.mode' in transform code
This also prevents different snap modes from being used at the same time in the code.
2021-11-12 16:30:01 -03:00
e5a7dd8ab6 Cleanup: unify snap modes to geometry in a single flag
This combination was being repeated in some places.
2021-11-12 16:30:01 -03:00
5b787c24fb Merge branch 'blender-v3.0-release' 2021-11-12 13:26:26 -06:00
888b879f5f Fix: Incorrect transfer attribute error message with curves
The node does support curves, but only in index mode (see T88630)
So add a specific error message for the nearest mode, and let the
node support curves in the declaration.

Differential Revision: https://developer.blender.org/D13205
2021-11-12 13:25:22 -06:00
1b55b911f2 Merge branch 'blender-v3.0-release' 2021-11-12 20:04:05 +01:00
71131b4969 Tests: disable audio system for performance tests 2021-11-12 20:03:46 +01:00
b4d9b8b7f8 Fix T91893, T92455: wrong transmission pass with hair and multiscatter glass
We need to increase GPU memory usage a bit. Unfortunately we can't get away
with writing either reflection or transmission passes because these BSDFs may
scatter in either direction but still must be in a fixed reflection or
transmission category to match up with the color passes.
2021-11-12 20:03:46 +01:00
ef0b8d6306 Fix T92002: no Cycles combined baking support for filter settings 2021-11-12 20:03:46 +01:00
d845ba481c Fix T91826: Inconsistent node socket name identifier separator
Previously both `.` and `_` were used as separators when finding
a unique name for a socket. This removes the use of `.`, since `_`
was more common. It also does versioning for all of a file's node
trees to make sure that they all use the `_` convention.

Differential Revision: https://developer.blender.org/D13181
2021-11-12 12:22:43 -06:00
cbca71a7cf Cleanup: Move remaning node editor files to C++
Differential Revision: https://developer.blender.org/D13200
2021-11-12 12:12:27 -06:00
809ae823b7 Merge branch 'blender-v3.0-release' 2021-11-12 19:00:23 +01:00
9d0d4b8601 Fix T93029: OptiX denoising artifacts at high sample counts in specific scenes
Partially reverts commit rB440a3475b8f5410e5c41bfbed5ce82771b41356f because
"optixDenoiserComputeIntensity" does not currently support input images that are not packed (the
"pixelStrideInBytes" field is not zero). As a result the intensity calculation would take into account
data from other passes in the image, some of which was scaled by the number of samples still and
therefore produce widely incorrect results that then caused artifacts in the denoised image.

Maniphest Tasks: T93029
2021-11-12 18:59:50 +01:00
8a8bf99717 Merge remote-tracking branch 'origin/blender-v3.0-release' 2021-11-12 18:23:44 +01:00
2b394e1108 UI: (Performance) Avoid drawing buttons out of view
The UI was always drawing all buttons in a layout, no matter if they
were scrolled out of view (as in, outside of the visible part of the
region) or not. This means it's doing quite some work that can be
avoided.
UI drawing generally isn't a big bottleneck in Blender, so I don't
expect huge speedups from this. But while playing back animation, we do
redraw a fair bit of the UI, so in cases where there are many buttons
out of view, it may bring a little FPS boost. E.g. say in complex node
trees (the node editor is redrawn on animation playback in case there
are animated values that need updated UI feedback). This also mitigates
the issue in T92922 significantly.

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

Reviewed by: Brecht Van Lommel
2021-11-12 18:21:12 +01:00
Yevgeny Makarov
a89529d8db UI: Do not shade alpha when blending colors
UI_GetThemeColorBlendShade4fv incorrectly changing alpha by the amount
of the shading offset.

See D9944 for more details.

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

Reviewed by Hans Goudey
2021-11-12 08:55:20 -08:00
9f5290e3bc Fix T93007: Cycles not updating for animated Object properties like color 2021-11-12 08:55:20 -08:00
c671b5eee4 Fix Cycles ray visibility panel missing for volume objects 2021-11-12 08:55:20 -08:00
Yevgeny Makarov
896d3f1ce5 UI: Do not shade alpha when blending colors
UI_GetThemeColorBlendShade4fv incorrectly changing alpha by the amount
of the shading offset.

See D9944 for more details.

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

Reviewed by Hans Goudey
2021-11-12 08:51:31 -08:00
76105eb752 Fix T93007: Cycles not updating for animated Object properties like color 2021-11-12 17:09:21 +01:00
d48523cb4d Fix Cycles ray visibility panel missing for volume objects 2021-11-12 16:18:07 +01:00
ddf66cd060 Merge remote-tracking branch 'origin/blender-v3.0-release' 2021-11-12 14:36:55 +01:00
b4cfe80547 Assets: Store Action sub-type in asset metadata
Blender 3.0 will only support single-frame Actions in the pose library.
The goal of this patch is to lay the groundwork for making it possible
for the Asset Browser to reject/hide "animation snippet" Action assets.

Determining whether an Action has one or more frames (i.e. whether it
has a single pose or animation) requires inspecting the Action itself,
and thus loading the data-block itself. This would make it impossible to
quickly determine from the asset browser.

To solve this, the Action is inspected before saving, and a
`"is_single_frame"` boolean (well, 0/1 integer) IDProperty is added.

Reviewed by: Severin

Differential Revision: https://developer.blender.org/D13202
2021-11-12 14:36:22 +01:00
c7a88cf91a Merge branch 'blender-v3.0-release' 2021-11-13 00:31:03 +11:00
5f7d5c0809 Gizmo: adjust when gizmo protection flags are displayed
Restore behavior reverted in
0ea60cf6b8 but only for location
as it makes sense to use protection flags in global mode in that case.
2021-11-13 00:28:13 +11:00
a470e3c9d1 Merge branch 'blender-v3.0-release' 2021-11-13 00:20:07 +11:00
0ea60cf6b8 Fix gizmo protection flag use in object mode
Channel protection flags were only used in global mode,
this doesn't make any sense, especially for rotation and scale.

Follow pose-bones, only using protection flags for
local & gimbal orientation.
2021-11-13 00:19:36 +11:00
3fe735d371 Geometry Nodes: Add Outer Points Selection to Star
Adds a boolean field output containing a selection of the
points of the star that are controlled by the outer radius
of the star.

Differential Revision: https://developer.blender.org/D13097
2021-11-12 06:44:41 -06:00
a47359ff36 Merge branch 'blender-v3.0-release' 2021-11-12 11:52:49 +01:00
de8a46c6ad Fix T93008: Cycles: Huge memory spike when saving tile to disk
The root of the problem lies in bug in OIIO which we can work around
from our side (which does not affect pack memory usage).

Thanks Brecht for finding the root cause!

Differential Revision: https://developer.blender.org/D13186
2021-11-12 11:20:01 +01:00
26502f3d89 Merge remote-tracking branch 'origin/blender-v3.0-release' 2021-11-12 10:52:12 +01:00
2b633f12ad Fix crash in asset browser when switching from file browser
When the file browser is in asset browser mode, it sets the callback
`filelist->prepare_filter_fn` to an asset browser specific function. This
function will segfault if there is no current asset library. Switching back
from asset browser to file browser would not reset that callback to
`NULL`, causing it to be called and crash Blender. This is now fixed.
2021-11-12 10:51:09 +01:00
86ca206db8 Cleanup/document BKE_blender_copybuffer.
* Rename the 'copy' functions to make it clear they belong to the same
  'group' and are to be used together.
* Fix `flag` parameter of `BKE_copybuffer_paste` being a short instead
  of an int.
* Improve documentation.
2021-11-12 10:20:49 +01:00
William Leeson
456876208b Fix T92601: Disable profiling when the profiler is deemed not active.
Adds a method to profiler that can be used to check if it is active.
This is used to determine if stop_profiling and start_profiling
should be called.

| patch | Juans Scene UI 256 samples | Juans Scene bg 256 samples | junkshop UI | junkshop bg |
| No patch | 6:16.59 | 4:05.37 | 2:08.48 | 1:59.7 |
| D13187   | 4:12.15 | 3:57.36 | 2:07.25 | 1:58.16 |
| D13185   | 4.11.18 |3:54.74 | 2:07.44 | 1:58.03 |
| D13190   | 4:12.39 | 3:55.42 | 2:07.62 | 1:58.68 |

UI - means rendered from within Blender
bg - means rendered from the command line using ##blender -b scene.blend -f 1##

Reviewed By: sergey, brecht

Maniphest Tasks: T92601

Differential Revision: https://developer.blender.org/D13190
2021-11-12 10:16:01 +01:00
William Leeson
32c7687859 Fix T92601: Disable profiling when the profiler is deemed not active.
Adds a method to profiler that can be used to check if it is active.
This is used to determine if stop_profiling and start_profiling
should be called.

| patch | Juans Scene UI 256 samples | Juans Scene bg 256 samples | junkshop UI | junkshop bg |
| No patch | 6:16.59 | 4:05.37 | 2:08.48 | 1:59.7 |
| D13187   | 4:12.15 | 3:57.36 | 2:07.25 | 1:58.16 |
| D13185   | 4.11.18 |3:54.74 | 2:07.44 | 1:58.03 |
| D13190   | 4:12.39 | 3:55.42 | 2:07.62 | 1:58.68 |

UI - means rendered from within Blender
bg - means rendered from the command line using ##blender -b scene.blend -f 1##

Reviewed By: sergey, brecht

Maniphest Tasks: T92601

Differential Revision: https://developer.blender.org/D13190
2021-11-12 10:01:48 +01:00
a87253942d Cleanup: Remove GHOST_isUpsideDownContext.
GHOST API only has a header definition. No implementation or usage.
2021-11-12 09:38:25 +01:00
ae74ad191c Merge branch 'blender-v3.0-release' 2021-11-12 18:35:22 +11:00
aa1c44a113 Merge branch 'blender-v3.0-release' 2021-11-12 18:35:19 +11:00
5c0d4753cf Merge branch 'blender-v3.0-release' 2021-11-12 18:35:16 +11:00
02333544d1 Merge branch 'blender-v3.0-release' 2021-11-12 18:35:13 +11:00
1061f5a1ba Cleanup: remove redundant loop-index access
Use a counter for loop indices as they're being iterated in order.
2021-11-12 18:33:05 +11:00
1a7757b0bc Fix T91444: Edge Loop Preview fails with two Mirror Modifiers
The mirror modifiers merge option caused unnecessary re-ordering
to the vertex array with original vertices merging into their copies.

While this wasn't an error, it meant creating a 1:1 mapping from input
vertices to their final output wasn't reliable (when looping over
vertices first to last) as is done in
BKE_editmesh_vert_coords_when_deformed.

As merging in either direction is supported, keep the source meshes
vertices in-order since it allows the vertex coordinates to be extracted.
2021-11-12 18:27:47 +11:00
f133c6b094 Fix crash saving blend files in background mode
Reading the windows pixels was attempted in background mode.
2021-11-12 18:05:27 +11:00
d612d92630 Cleanup: use term sequence_strip instead of vse_strip 2021-11-12 17:38:58 +11:00
1e1c870001 Cleanup: Improve comment 2021-11-11 21:57:40 -06:00
0533f2851e Geometry Nodes: change selection output order in Cylinder node
This new order is a bit more intuitive.
2021-11-11 19:53:02 +01:00
d6e682a7b0 Merge branch 'blender-v3.0-release' 2021-11-11 19:50:24 +01:00
bd734cc441 Fix: Attribute Transfer node does not work with a single index
Differential Revision: https://developer.blender.org/D13194
2021-11-11 19:49:20 +01:00
e61da8e4fb Merge branch 'blender-v3.0-release' 2021-11-11 11:47:43 -06:00
f3bdabbe24 Fix: Incorrect modifier warning with non-geometry input first
The code assumed that any geometry input that wasn't the first input
was a second geometry input. Fix by separating the warning for the
first input and for the number of geometry inputs.
2021-11-11 11:47:19 -06:00
50f32025ac Merge branch 'blender-v3.0-release' 2021-11-11 18:27:31 +01:00
393879f30c Fix: wrong field inferencing with unavailable sockets 2021-11-11 18:26:40 +01:00
3d9c8397fc Fix T93005: Cycles shadow catcher not inherited by instances 2021-11-11 18:12:05 +01:00
c9c7658926 Geometry Nodes: Add Offset to Handle Position Node
Adds a vector offset field to the "Curve Handle Position Node".
This vector is added to the incoming position (which is the
implicit handle position if not connected) which will set the
position of the handle. Default is (0,0,0)

Differential Revision: https://developer.blender.org/D13035
2021-11-11 10:58:23 -06:00
3ca41b7312 Merge branch 'blender-v3.0-release' 2021-11-11 10:16:35 -06:00
Peter Sergay
4bc08b79aa UI: Updated Blender Light theme for Spreadsheet
This patch adds list colors to the light theme for the spreadsheet,
which are needed for the data set region. Addresses T92492.

Differential Revision: https://developer.blender.org/D13090
2021-11-11 10:10:28 -06:00
25e7365d0d Cleanup CUDA / HIP comments
Remove outdated CUDA comments for bindless textures and cleanup some HIP comments that still mentioned CUDA.

Differential Revision: https://developer.blender.org/D13189
2021-11-11 16:37:29 +01:00
52c617802f Merge branch 'blender-v3.0-release' 2021-11-11 09:27:42 -06:00
Martijn Versteegh
7aa39b40f4 Fix: Prevent use of uninitialized memory when creating Bezier spline
When Constructing bezier splines from dna, the positions of the
left/right handles were set directly in the internal vectors, by
requesting a reference to them. The problem is that
BezierSpline::handle_positions_left() calls ensure_auto_handles()
before returning the reference. That function does some calculations on
uninitialized memory if the positions array is not yet filled.

Differential Revision: https://developer.blender.org/D13107
2021-11-11 09:25:10 -06:00
ce395c84a3 Merge branch 'blender-v3.0-release' 2021-11-11 15:29:35 +01:00
d26d3cfe19 Fix T92868: Cycles catcher with transparency crashes
The issue was caused by splitting happening twice.

Fixed by checking for split flag which is assigned to the both states
during split.

The tricky part was to write catcher data at the moment of split: the
transparency and shadow catcher sample count is to be accumulated at
that point. Now it is happening in the `intersect_closest` kernel.
The downside is that render buffer is to be passed to the kernel, but
the benefit is that extra split bounce check is not needed now.

Had to move the passes write to shadow catcher header, since include
of `film/passes.h` causes all the fun of requirement to have BSDF
data structures available.

Differential Revision: https://developer.blender.org/D13177
2021-11-11 15:21:35 +01:00
06a74e7816 LibLink/Append tests: Add basic testing of bpy.data.libraries.load code. 2021-11-11 14:54:26 +01:00
9f31b9b7d3 Merge branch 'blender-v3.0-release' 2021-11-11 14:33:28 +01:00
9be6880d02 Fix (unreported) bad handling of reports in libraries.load code.
rB60fee69682ac39 only partially fixed the issue, `BlendFileReadReport
bf_reports` was now properly stored in `BPy_Library` `self` for the
lifetime of the context, but its `reports` member was still referencing
local variable to `bpy_lib_enter` function.
2021-11-11 14:29:14 +01:00
4a98faf9f1 Merge branch 'blender-v3.0-release' 2021-11-11 21:34:05 +11:00
8c240f50b2 Merge branch 'blender-v3.0-release' 2021-11-11 21:34:02 +11:00
b7e2408ea4 Fix T92867: Gimbal rotation broken when used for multiple objects
Support gimbal orientation for objects & bones.
2021-11-11 21:33:09 +11:00
bb64155c63 Cleanup: split gimbal_axis into pose and object
Allow access to a single bones gimbal matrix.
2021-11-11 21:14:08 +11:00
Andrii
c63e735f6b Cycles: Add sample offset option
This patch exposes the sampling offset option to Blender. It is located in the "Sampling > Advanced" panel.
For example, this can be useful to parallelize rendering and distribute different chunks of samples for each computer to render.

---

I also had to add this option to `RenderWork` and `RenderScheduler` classes so that the sample count in the status string can be calculated correctly.

Reviewed By: leesonw

Differential Revision: https://developer.blender.org/D13086
2021-11-11 09:39:25 +01:00
b8d53b703a Merge branch 'blender-v3.0-release' 2021-11-11 15:00:23 +11:00
9787b46f09 Merge branch 'blender-v3.0-release' 2021-11-11 15:00:20 +11:00
03f0be35d6 Merge branch 'blender-v3.0-release' 2021-11-11 15:00:17 +11:00
d753ebd40a Cleanup: spelling in comments 2021-11-11 14:59:30 +11:00
ddf0bacaa9 Cleanup: typo in function name 2021-11-11 14:58:55 +11:00
3929db265f Fix T92954: Loop Cut Tool preview line visible during operation
Apply a local-workaround instead of adding support for this use-case
since pre-selection isn't the intended purpose of gizmos.

This also resolves a glitch where poly-build and loop cut would
briefly show loop-cut or poly-build pre-selection after transforming.

See gizmo_preselect_poll_for_draw note for more details.
2021-11-11 14:58:55 +11:00
e1bd4bbb66 UI: Introduce View pie in more editors
#### Motivation

The View pie menu is a convenient way to access operators such as `Frame Selected` and `Frame All` which are usually mapped to `PERIOD` or `HOME` keys on the right side of most keyboard, making it hard hard to reach with the left hand.

The motivation for this patch comes from working with a 75% keyboard (no numpad). Most laptops face a similar problem.

#### Implementation

The View pie menu has been added to the following editors and sub-modes where applicable:

* Node Editor
* Video Sequencer
* Dopesheet
* Graph
* NLA
* Image
* Clip
* Outliner

More options could definitely be added to this menu for convenience, as long as it maintains the common options in the same place (Frame Selected on the left, Frame All on the right).

For positioning I went with the following layout:
{F11791186, size=full}

I've added `Zoom 1:1`to the Image Editor and the VSE Preview since there is no way to reset the zoom on keyboards without numpad (unless Emulate Numpad is turned on).

The Outliner uses `Show Active` and `Show Hierarchy` which are the closest ones to the equivalent in other editors. Should `Show Active` be renamed to `Frame Selected`?

The shortcut assigned is the same as the 3D Viewport (`ACCENT_GRAVE`).

#### Screenshots

Node Editor
{F11778387, size=full}

Dopesheet
{F11778400, size=full}

Graph
{F11778403, size=full}

Image Editor (Paint and View)
{F11791113, size=full}

Image Editor (Mask)
{F11791114, size=full}

UV Editor
{F11791119, size=full}

Clip Editor (Tracking)
{F11791137, size=full}

Clip Editor (Mask)
{F11791140, size=full}

Clip Editor (Graph)
{F11791151, size=full}
View operators are not yet implemented in Clip Editor Dopesheet mode (left a note about this in the menu poll).

Reviewed By: #user_interface, campbellbarton

Differential Revision: https://developer.blender.org/D13169
2021-11-11 01:18:50 +01:00
f1a8644121 Cleanup: Move interface_region_search.c to C++
This will be helpful for solving a bug with search during animation
playback, T89313. I tested this on all platforms on the buildbot.
2021-11-10 15:49:49 -06:00
1ec7075ff2 Merge branch 'blender-v3.0-release' 2021-11-10 15:44:13 -06:00
22ffd69a91 Fix T89313: Attribute search crash with animation playback
rBc473b2ce8bdbf8fa42 improved the situation somewhat, but
attribute search still crashes during animation playback, because
the UI search data references stale memory. The proper solution
is to allow the search to own data rather than just referencing it,
but I would prefer not to do that for 3.0. In the meantime, just
disable attribute search when animation is playing.

Differential Revision: https://developer.blender.org/D13179
2021-11-10 15:43:18 -06:00
9ca8bf0b29 Merge branch 'blender-v3.0-release' 2021-11-10 22:28:03 +01:00
040630bb9a Fix wrong device check in HIP kernel compile.
Also cleanup some related code, that was falsely copied from CUDA.

Differential Revision: https://developer.blender.org/D13180
2021-11-10 22:24:53 +01:00
3fa86f4b28 Merge branch 'blender-v3.0-release' 2021-11-10 20:19:09 +01:00
7689f501e2 Cycles: enable HIP device and binaries on Windows
We've now done testing to confirm this works with RDNA and RDNA2 AMD GPUs
on Windows. The AMD driver needed for this will soon be released publicly.
2021-11-10 20:16:44 +01:00
Thomas Dinges
e507a789b3 Cycles: disable graphics interop for HIP devices
This is due to a driver bug, so disable it for now until it gets resolved
in a future driver release.

Ref T92972

Differential Revision: https://developer.blender.org/D13167
2021-11-10 20:16:44 +01:00
6b0008129e Fix T92972: Cycles HIP wrong render display after a recent refactor
It's unclear why this fails. Maybe the size of half4 is not the expected
8 bytes and adjacent pixels are overwritten. Or there is some bug in the
HIP compiler writing a struct into global memory, which we probably don't
do elsewhere in the kernel.

Thanks to Thomas, William and Jeroen for helping investigate this.
2021-11-10 20:03:07 +01:00
c8e93da0a7 Fix Cycles assert in denoising fallback to OIDN 2021-11-10 19:56:30 +01:00
208 changed files with 2493 additions and 1273 deletions

View File

@@ -440,7 +440,11 @@ mark_as_advanced(WITH_CYCLES_CUDA_BUILD_SERIAL)
mark_as_advanced(WITH_CUDA_DYNLOAD)
# AMD HIP
option(WITH_CYCLES_DEVICE_HIP "Enable Cycles AMD HIP support" OFF)
if(WIN32)
option(WITH_CYCLES_DEVICE_HIP "Enable Cycles AMD HIP support" ON)
else()
option(WITH_CYCLES_DEVICE_HIP "Enable Cycles AMD HIP support" OFF)
endif()
option(WITH_CYCLES_HIP_BINARIES "Build Cycles AMD HIP binaries" OFF)
set(CYCLES_HIP_BINARIES_ARCH gfx1010 gfx1011 gfx1012 gfx1030 gfx1031 gfx1032 gfx1034 CACHE STRING "AMD HIP architectures to build binaries for")
mark_as_advanced(WITH_CYCLES_DEVICE_HIP)

View File

@@ -81,4 +81,5 @@ if(NOT APPLE)
set(WITH_CYCLES_DEVICE_OPTIX ON CACHE BOOL "" FORCE)
set(WITH_CYCLES_CUDA_BINARIES ON CACHE BOOL "" FORCE)
set(WITH_CYCLES_CUBIN_COMPILER OFF CACHE BOOL "" FORCE)
set(WITH_CYCLES_HIP_BINARIES ON CACHE BOOL "" FORCE)
endif()

View File

@@ -325,6 +325,13 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
default=1024,
)
sample_offset: IntProperty(
name="Sample Offset",
description="Number of samples to skip when starting render",
min=0, max=(1 << 24),
default=0,
)
time_limit: FloatProperty(
name="Time Limit",
description="Limit the render time (excluding synchronization time)."

View File

@@ -290,6 +290,9 @@ class CYCLES_RENDER_PT_sampling_advanced(CyclesButtonsPanel, Panel):
col.active = not (cscene.use_adaptive_sampling and cscene.use_preview_adaptive_sampling)
col.prop(cscene, "sampling_pattern", text="Pattern")
col = layout.column(align=True)
col.prop(cscene, "sample_offset")
layout.separator()
col = layout.column(align=True)
@@ -1051,7 +1054,7 @@ class CYCLES_OBJECT_PT_motion_blur(CyclesButtonsPanel, Panel):
def has_geometry_visibility(ob):
return ob and ((ob.type in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'LIGHT'}) or
return ob and ((ob.type in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'LIGHT', 'VOLUME', 'POINTCLOUD', 'HAIR'}) or
(ob.instance_type == 'COLLECTION' and ob.instance_collection))

View File

@@ -294,7 +294,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
object->set_visibility(visibility);
object->set_is_shadow_catcher(b_ob.is_shadow_catcher());
object->set_is_shadow_catcher(b_ob.is_shadow_catcher() || b_parent.is_shadow_catcher());
float shadow_terminator_shading_offset = get_float(cobject, "shadow_terminator_offset");
object->set_shadow_terminator_shading_offset(shadow_terminator_shading_offset);

View File

@@ -606,6 +606,19 @@ void BlenderSession::bake(BL::Depsgraph &b_depsgraph_,
pass->set_type(bake_type_to_pass(bake_type, bake_filter));
pass->set_include_albedo((bake_filter & BL::BakeSettings::pass_filter_COLOR));
if (pass->get_type() == PASS_COMBINED) {
/* Filtering settings for combined pass. */
Integrator *integrator = scene->integrator;
integrator->set_use_direct_light((bake_filter & BL::BakeSettings::pass_filter_DIRECT) != 0);
integrator->set_use_indirect_light((bake_filter & BL::BakeSettings::pass_filter_INDIRECT) !=
0);
integrator->set_use_diffuse((bake_filter & BL::BakeSettings::pass_filter_DIFFUSE) != 0);
integrator->set_use_glossy((bake_filter & BL::BakeSettings::pass_filter_GLOSSY) != 0);
integrator->set_use_transmission((bake_filter & BL::BakeSettings::pass_filter_TRANSMISSION) !=
0);
integrator->set_use_emission((bake_filter & BL::BakeSettings::pass_filter_EMIT) != 0);
}
session->set_display_driver(nullptr);
session->set_output_driver(make_unique<BlenderOutputDriver>(b_engine));

View File

@@ -835,18 +835,25 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine &b_engine,
/* samples */
int samples = get_int(cscene, "samples");
int preview_samples = get_int(cscene, "preview_samples");
int sample_offset = get_int(cscene, "sample_offset");
if (background) {
params.samples = samples;
params.sample_offset = sample_offset;
}
else {
params.samples = preview_samples;
if (params.samples == 0)
if (params.samples == 0) {
params.samples = INT_MAX;
}
params.sample_offset = 0;
}
/* Clamp sample offset. */
params.sample_offset = clamp(params.sample_offset, 0, Integrator::MAX_SAMPLES);
/* Clamp samples. */
params.samples = min(params.samples, Integrator::MAX_SAMPLES);
params.samples = clamp(params.samples, 0, Integrator::MAX_SAMPLES - params.sample_offset);
/* Viewport Performance */
params.pixel_size = b_engine.get_preview_pixel_size(b_scene);

View File

@@ -42,7 +42,7 @@ class CPUKernels {
IntegratorInitFunction integrator_init_from_camera;
IntegratorInitFunction integrator_init_from_bake;
IntegratorFunction integrator_intersect_closest;
IntegratorShadeFunction integrator_intersect_closest;
IntegratorFunction integrator_intersect_shadow;
IntegratorFunction integrator_intersect_subsurface;
IntegratorFunction integrator_intersect_volume_stack;

View File

@@ -931,7 +931,6 @@ void CUDADevice::tex_alloc(device_texture &mem)
{
CUDAContextScope scope(this);
/* General variables for both architectures */
string bind_name = mem.name;
size_t dsize = datatype_size(mem.data_type);
size_t size = mem.memory_size();
@@ -1094,7 +1093,6 @@ void CUDADevice::tex_alloc(device_texture &mem)
if (mem.info.data_type != IMAGE_DATA_TYPE_NANOVDB_FLOAT &&
mem.info.data_type != IMAGE_DATA_TYPE_NANOVDB_FLOAT3) {
/* Kepler+, bindless textures. */
CUDA_RESOURCE_DESC resDesc;
memset(&resDesc, 0, sizeof(resDesc));

View File

@@ -222,7 +222,6 @@ string HIPDevice::compile_kernel_get_common_cflags(const uint kernel_features)
const string include_path = source_path;
string cflags = string_printf(
"-m%d "
"--ptxas-options=\"-v\" "
"--use_fast_math "
"-DHIPCC "
"-I\"%s\"",
@@ -234,10 +233,7 @@ string HIPDevice::compile_kernel_get_common_cflags(const uint kernel_features)
return cflags;
}
string HIPDevice::compile_kernel(const uint kernel_features,
const char *name,
const char *base,
bool force_ptx)
string HIPDevice::compile_kernel(const uint kernel_features, const char *name, const char *base)
{
/* Compute kernel name. */
int major, minor;
@@ -247,7 +243,7 @@ string HIPDevice::compile_kernel(const uint kernel_features,
hipGetDeviceProperties(&props, hipDevId);
/* gcnArchName can contain tokens after the arch name with features, ie.
"gfx1010:sramecc-:xnack-" so we tokenize it to get the first part. */
* `gfx1010:sramecc-:xnack-` so we tokenize it to get the first part. */
char *arch = strtok(props.gcnArchName, ":");
if (arch == NULL) {
arch = props.gcnArchName;
@@ -255,13 +251,11 @@ string HIPDevice::compile_kernel(const uint kernel_features,
/* Attempt to use kernel provided with Blender. */
if (!use_adaptive_compilation()) {
if (!force_ptx) {
const string fatbin = path_get(string_printf("lib/%s_%s.fatbin", name, arch));
VLOG(1) << "Testing for pre-compiled kernel " << fatbin << ".";
if (path_exists(fatbin)) {
VLOG(1) << "Using precompiled kernel.";
return fatbin;
}
const string fatbin = path_get(string_printf("lib/%s_%s.fatbin", name, arch));
VLOG(1) << "Testing for pre-compiled kernel " << fatbin << ".";
if (path_exists(fatbin)) {
VLOG(1) << "Using precompiled kernel.";
return fatbin;
}
}
@@ -298,9 +292,9 @@ string HIPDevice::compile_kernel(const uint kernel_features,
# ifdef _WIN32
if (!use_adaptive_compilation() && have_precompiled_kernels()) {
if (major < 3) {
if (!hipSupportsDevice(hipDevId)) {
set_error(
string_printf("HIP backend requires compute capability 3.0 or up, but found %d.%d. "
string_printf("HIP backend requires compute capability 10.1 or up, but found %d.%d. "
"Your GPU is not supported.",
major,
minor));
@@ -380,10 +374,9 @@ string HIPDevice::compile_kernel(const uint kernel_features,
bool HIPDevice::load_kernels(const uint kernel_features)
{
/* TODO(sergey): Support kernels re-load for CUDA devices adaptive compile.
/* TODO(sergey): Support kernels re-load for HIP devices adaptive compile.
*
* Currently re-loading kernel will invalidate memory pointers,
* causing problems in cuCtxSynchronize.
* Currently re-loading kernels will invalidate memory pointers.
*/
if (hipModule) {
if (use_adaptive_compilation()) {
@@ -904,7 +897,6 @@ void HIPDevice::tex_alloc(device_texture &mem)
{
HIPContextScope scope(this);
/* General variables for both architectures */
string bind_name = mem.name;
size_t dsize = datatype_size(mem.data_type);
size_t size = mem.memory_size();
@@ -1069,7 +1061,6 @@ void HIPDevice::tex_alloc(device_texture &mem)
if (mem.info.data_type != IMAGE_DATA_TYPE_NANOVDB_FLOAT &&
mem.info.data_type != IMAGE_DATA_TYPE_NANOVDB_FLOAT3) {
/* Kepler+, bindless textures. */
hipResourceDesc resDesc;
memset(&resDesc, 0, sizeof(resDesc));
@@ -1160,6 +1151,8 @@ bool HIPDevice::should_use_graphics_interop()
* possible, but from the empiric measurements it can be considerably slower than using naive
* pixels copy. */
/* Disable graphics interop for now, because of driver bug in 21.40. See T92972 */
# if 0
HIPContextScope scope(this);
int num_all_devices = 0;
@@ -1178,6 +1171,7 @@ bool HIPDevice::should_use_graphics_interop()
return true;
}
}
# endif
return false;
}

View File

@@ -93,10 +93,7 @@ class HIPDevice : public Device {
virtual string compile_kernel_get_common_cflags(const uint kernel_features);
string compile_kernel(const uint kernel_features,
const char *name,
const char *base = "hip",
bool force_ptx = false);
string compile_kernel(const uint kernel_features, const char *name, const char *base = "hip");
virtual bool load_kernels(const uint kernel_features) override;
void reserve_local_memory(const uint kernel_features);

View File

@@ -48,7 +48,7 @@ class HIPDeviceGraphicsInterop : public DeviceGraphicsInterop {
HIPDeviceQueue *queue_ = nullptr;
HIPDevice *device_ = nullptr;
/* OpenGL PBO which is currently registered as the destination for the CUDA buffer. */
/* OpenGL PBO which is currently registered as the destination for the HIP buffer. */
uint opengl_pbo_id_ = 0;
/* Buffer area in pixels of the corresponding PBO. */
int64_t buffer_area_ = 0;

View File

@@ -886,8 +886,7 @@ bool OptiXDevice::denoise_configure_if_needed(DenoiseContext &context)
denoiser_.scratch_offset = sizes.stateSizeInBytes;
/* Allocate denoiser state if tile size has changed since last setup. */
denoiser_.state.alloc_to_device(denoiser_.scratch_offset + denoiser_.scratch_size +
sizeof(float));
denoiser_.state.alloc_to_device(denoiser_.scratch_offset + denoiser_.scratch_size);
/* Initialize denoiser state for the current tile size. */
const OptixResult result = optixDenoiserSetup(
@@ -971,16 +970,6 @@ bool OptiXDevice::denoise_run(DenoiseContext &context, const DenoisePass &pass)
/* Finally run denoising. */
OptixDenoiserParams params = {}; /* All parameters are disabled/zero. */
params.hdrIntensity = denoiser_.state.device_pointer + denoiser_.scratch_offset +
denoiser_.scratch_size;
optix_assert(
optixDenoiserComputeIntensity(denoiser_.optix_denoiser,
denoiser_.queue.stream(),
&color_layer,
params.hdrIntensity,
denoiser_.state.device_pointer + denoiser_.scratch_offset,
denoiser_.scratch_size));
OptixDenoiserLayer image_layers = {};
image_layers.input = color_layer;

View File

@@ -73,7 +73,8 @@ bool OptiXDeviceQueue::enqueue(DeviceKernel kernel, const int work_size, void *a
sizeof(device_ptr),
cuda_stream_));
if (kernel == DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE) {
if (kernel == DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST ||
kernel == DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE) {
cuda_device_assert(
cuda_device_,
cuMemcpyHtoDAsync(launch_params_ptr + offsetof(KernelParamsOptiX, render_buffer),

View File

@@ -33,7 +33,10 @@ unique_ptr<Denoiser> Denoiser::create(Device *path_trace_device, const DenoisePa
return make_unique<OptiXDenoiser>(path_trace_device, params);
}
return make_unique<OIDNDenoiser>(path_trace_device, params);
/* Always fallback to OIDN. */
DenoiseParams oidn_params = params;
oidn_params.type = DENOISER_OPENIMAGEDENOISE;
return make_unique<OIDNDenoiser>(path_trace_device, oidn_params);
}
Denoiser::Denoiser(Device *path_trace_device, const DenoiseParams &params)

View File

@@ -380,7 +380,10 @@ void PathTrace::path_trace(RenderWork &render_work)
PathTraceWork *path_trace_work = path_trace_works_[i].get();
PathTraceWork::RenderStatistics statistics;
path_trace_work->render_samples(statistics, render_work.path_trace.start_sample, num_samples);
path_trace_work->render_samples(statistics,
render_work.path_trace.start_sample,
num_samples,
render_work.path_trace.sample_offset);
const double work_time = time_dt() - work_start_time;
work_balance_infos_[i].time_spent += work_time;
@@ -849,7 +852,8 @@ void PathTrace::progress_update_if_needed(const RenderWork &render_work)
const int2 tile_size = get_render_tile_size();
const int num_samples_added = tile_size.x * tile_size.y * render_work.path_trace.num_samples;
const int current_sample = render_work.path_trace.start_sample +
render_work.path_trace.num_samples;
render_work.path_trace.num_samples -
render_work.path_trace.sample_offset;
progress_->add_samples(num_samples_added, current_sample);
}

View File

@@ -75,7 +75,10 @@ class PathTraceWork {
/* Render given number of samples as a synchronous blocking call.
* The samples are added to the render buffer associated with this work. */
virtual void render_samples(RenderStatistics &statistics, int start_sample, int samples_num) = 0;
virtual void render_samples(RenderStatistics &statistics,
int start_sample,
int samples_num,
int sample_offset) = 0;
/* Copy render result from this work to the corresponding place of the GPU display.
*

View File

@@ -71,14 +71,17 @@ void PathTraceWorkCPU::init_execution()
void PathTraceWorkCPU::render_samples(RenderStatistics &statistics,
int start_sample,
int samples_num)
int samples_num,
int sample_offset)
{
const int64_t image_width = effective_buffer_params_.width;
const int64_t image_height = effective_buffer_params_.height;
const int64_t total_pixels_num = image_width * image_height;
for (CPUKernelThreadGlobals &kernel_globals : kernel_thread_globals_) {
kernel_globals.start_profiling();
if (device_->profiler.active()) {
for (CPUKernelThreadGlobals &kernel_globals : kernel_thread_globals_) {
kernel_globals.start_profiling();
}
}
tbb::task_arena local_arena = local_tbb_arena_create(device_);
@@ -97,6 +100,7 @@ void PathTraceWorkCPU::render_samples(RenderStatistics &statistics,
work_tile.w = 1;
work_tile.h = 1;
work_tile.start_sample = start_sample;
work_tile.sample_offset = sample_offset;
work_tile.num_samples = 1;
work_tile.offset = effective_buffer_params_.offset;
work_tile.stride = effective_buffer_params_.stride;
@@ -106,9 +110,10 @@ void PathTraceWorkCPU::render_samples(RenderStatistics &statistics,
render_samples_full_pipeline(kernel_globals, work_tile, samples_num);
});
});
for (CPUKernelThreadGlobals &kernel_globals : kernel_thread_globals_) {
kernel_globals.stop_profiling();
if (device_->profiler.active()) {
for (CPUKernelThreadGlobals &kernel_globals : kernel_thread_globals_) {
kernel_globals.stop_profiling();
}
}
statistics.occupancy = 1.0f;

View File

@@ -48,7 +48,8 @@ class PathTraceWorkCPU : public PathTraceWork {
virtual void render_samples(RenderStatistics &statistics,
int start_sample,
int samples_num) override;
int samples_num,
int sample_offset) override;
virtual void copy_to_display(PathTraceDisplay *display,
PassMode pass_mode,

View File

@@ -250,7 +250,8 @@ void PathTraceWorkGPU::init_execution()
void PathTraceWorkGPU::render_samples(RenderStatistics &statistics,
int start_sample,
int samples_num)
int samples_num,
int sample_offset)
{
/* Limit number of states for the tile and rely on a greedy scheduling of tiles. This allows to
* add more work (because tiles are smaller, so there is higher chance that more paths will
@@ -261,6 +262,7 @@ void PathTraceWorkGPU::render_samples(RenderStatistics &statistics,
work_tile_scheduler_.reset(effective_buffer_params_,
start_sample,
samples_num,
sample_offset,
device_scene_->data.integrator.scrambling_distance);
enqueue_reset();
@@ -437,7 +439,15 @@ void PathTraceWorkGPU::enqueue_path_iteration(DeviceKernel kernel, const int num
DCHECK_LE(work_size, max_num_paths_);
switch (kernel) {
case DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST:
case DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST: {
/* Closest ray intersection kernels with integrator state and render buffer. */
void *d_render_buffer = (void *)buffers_->buffer.device_pointer;
void *args[] = {&d_path_index, &d_render_buffer, const_cast<int *>(&work_size)};
queue_->enqueue(kernel, work_size, args);
break;
}
case DEVICE_KERNEL_INTEGRATOR_INTERSECT_SHADOW:
case DEVICE_KERNEL_INTEGRATOR_INTERSECT_SUBSURFACE:
case DEVICE_KERNEL_INTEGRATOR_INTERSECT_VOLUME_STACK: {

View File

@@ -46,7 +46,8 @@ class PathTraceWorkGPU : public PathTraceWork {
virtual void render_samples(RenderStatistics &statistics,
int start_sample,
int samples_num) override;
int samples_num,
int sample_offset) override;
virtual void copy_to_display(PathTraceDisplay *display,
PassMode pass_mode,

View File

@@ -88,6 +88,16 @@ int RenderScheduler::get_num_samples() const
return num_samples_;
}
void RenderScheduler::set_sample_offset(int sample_offset)
{
sample_offset_ = sample_offset;
}
int RenderScheduler::get_sample_offset() const
{
return sample_offset_;
}
void RenderScheduler::set_time_limit(double time_limit)
{
time_limit_ = time_limit;
@@ -110,13 +120,15 @@ int RenderScheduler::get_num_rendered_samples() const
return state_.num_rendered_samples;
}
void RenderScheduler::reset(const BufferParams &buffer_params, int num_samples)
void RenderScheduler::reset(const BufferParams &buffer_params, int num_samples, int sample_offset)
{
buffer_params_ = buffer_params;
update_start_resolution_divider();
set_num_samples(num_samples);
set_start_sample(sample_offset);
set_sample_offset(sample_offset);
/* In background mode never do lower resolution render preview, as it is not really supported
* by the software. */
@@ -171,7 +183,7 @@ void RenderScheduler::reset(const BufferParams &buffer_params, int num_samples)
void RenderScheduler::reset_for_next_tile()
{
reset(buffer_params_, num_samples_);
reset(buffer_params_, num_samples_, sample_offset_);
}
bool RenderScheduler::render_work_reschedule_on_converge(RenderWork &render_work)
@@ -317,6 +329,7 @@ RenderWork RenderScheduler::get_render_work()
render_work.path_trace.start_sample = get_start_sample_to_path_trace();
render_work.path_trace.num_samples = get_num_samples_to_path_trace();
render_work.path_trace.sample_offset = get_sample_offset();
render_work.init_render_buffers = (render_work.path_trace.start_sample == get_start_sample());

View File

@@ -39,6 +39,7 @@ class RenderWork {
struct {
int start_sample = 0;
int num_samples = 0;
int sample_offset = 0;
} path_trace;
struct {
@@ -125,6 +126,9 @@ class RenderScheduler {
void set_num_samples(int num_samples);
int get_num_samples() const;
void set_sample_offset(int sample_offset);
int get_sample_offset() const;
/* Time limit for the path tracing tasks, in minutes.
* Zero disables the limit. */
void set_time_limit(double time_limit);
@@ -150,7 +154,7 @@ class RenderScheduler {
/* Reset scheduler, indicating that rendering will happen from scratch.
* Resets current rendered state, as well as scheduling information. */
void reset(const BufferParams &buffer_params, int num_samples);
void reset(const BufferParams &buffer_params, int num_samples, int sample_offset);
/* Reset scheduler upon switching to a next tile.
* Will keep the same number of samples and full-frame render parameters, but will reset progress
@@ -419,6 +423,8 @@ class RenderScheduler {
int start_sample_ = 0;
int num_samples_ = 0;
int sample_offset_ = 0;
/* Limit in seconds for how long path tracing is allowed to happen.
* Zero means no limit is applied. */
double time_limit_ = 0.0;

View File

@@ -36,6 +36,7 @@ void WorkTileScheduler::set_max_num_path_states(int max_num_path_states)
void WorkTileScheduler::reset(const BufferParams &buffer_params,
int sample_start,
int samples_num,
int sample_offset,
float scrambling_distance)
{
/* Image buffer parameters. */
@@ -51,6 +52,7 @@ void WorkTileScheduler::reset(const BufferParams &buffer_params,
/* Samples parameters. */
sample_start_ = sample_start;
samples_num_ = samples_num;
sample_offset_ = sample_offset;
/* Initialize new scheduling. */
reset_scheduler_state();
@@ -111,6 +113,7 @@ bool WorkTileScheduler::get_work(KernelWorkTile *work_tile_, const int max_work_
work_tile.h = tile_size_.height;
work_tile.start_sample = sample_start_ + start_sample;
work_tile.num_samples = min(tile_size_.num_samples, samples_num_ - start_sample);
work_tile.sample_offset = sample_offset_;
work_tile.offset = offset_;
work_tile.stride = stride_;

View File

@@ -41,6 +41,7 @@ class WorkTileScheduler {
void reset(const BufferParams &buffer_params,
int sample_start,
int samples_num,
int sample_offset,
float scrambling_distance);
/* Get work for a device.
@@ -79,6 +80,7 @@ class WorkTileScheduler {
* (splitting into a smaller work tiles). */
int sample_start_ = 0;
int samples_num_ = 0;
int sample_offset_ = 0;
/* Tile size which be scheduled for rendering. */
TileSize tile_size_;

View File

@@ -37,7 +37,7 @@
KERNEL_INTEGRATOR_INIT_FUNCTION(init_from_camera);
KERNEL_INTEGRATOR_INIT_FUNCTION(init_from_bake);
KERNEL_INTEGRATOR_FUNCTION(intersect_closest);
KERNEL_INTEGRATOR_SHADE_FUNCTION(intersect_closest);
KERNEL_INTEGRATOR_FUNCTION(intersect_shadow);
KERNEL_INTEGRATOR_FUNCTION(intersect_subsurface);
KERNEL_INTEGRATOR_FUNCTION(intersect_volume_stack);

View File

@@ -112,7 +112,7 @@ CCL_NAMESPACE_BEGIN
DEFINE_INTEGRATOR_INIT_KERNEL(init_from_camera)
DEFINE_INTEGRATOR_INIT_KERNEL(init_from_bake)
DEFINE_INTEGRATOR_KERNEL(intersect_closest)
DEFINE_INTEGRATOR_SHADE_KERNEL(intersect_closest)
DEFINE_INTEGRATOR_KERNEL(intersect_subsurface)
DEFINE_INTEGRATOR_KERNEL(intersect_volume_stack)
DEFINE_INTEGRATOR_SHADE_KERNEL(shade_background)

View File

@@ -131,13 +131,14 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(integrator_intersect_closest,
ccl_global const int *path_index_array,
ccl_global float *render_buffer,
const int work_size)
{
const int global_index = ccl_gpu_global_id_x();
if (global_index < work_size) {
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
ccl_gpu_kernel_call(integrator_intersect_closest(NULL, state));
ccl_gpu_kernel_call(integrator_intersect_closest(NULL, state, render_buffer));
}
}
@@ -523,6 +524,26 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
* Film.
*/
ccl_device_inline void kernel_gpu_film_convert_half_write(ccl_global uchar4 *rgba,
const int rgba_offset,
const int rgba_stride,
const int x,
const int y,
const half4 half_pixel)
{
/* Work around HIP issue with half float display, see T92972. */
#ifdef __KERNEL_HIP__
ccl_global half *out = ((ccl_global half *)rgba) + (rgba_offset + y * rgba_stride + x) * 4;
out[0] = half_pixel.x;
out[1] = half_pixel.y;
out[2] = half_pixel.z;
out[3] = half_pixel.w;
#else
ccl_global half4 *out = ((ccl_global half4 *)rgba) + rgba_offset + y * rgba_stride + x;
*out = half_pixel;
#endif
}
#define KERNEL_FILM_CONVERT_VARIANT(variant, input_channel_count) \
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) \
ccl_gpu_kernel_signature(film_convert_##variant, \
@@ -588,8 +609,9 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
\
film_apply_pass_pixel_overlays_rgba(&kfilm_convert, buffer, pixel); \
\
ccl_global half4 *out = ((ccl_global half4 *)rgba) + rgba_offset + y * rgba_stride + x; \
*out = float4_to_half4_display(make_float4(pixel[0], pixel[1], pixel[2], pixel[3])); \
const half4 half_pixel = float4_to_half4_display( \
make_float4(pixel[0], pixel[1], pixel[2], pixel[3])); \
kernel_gpu_film_convert_half_write(rgba, rgba_offset, rgba_stride, x, y, half_pixel); \
}
/* 1 channel inputs */

View File

@@ -73,7 +73,8 @@ using namespace metal;
#define ccl_gpu_kernel(block_num_threads, thread_num_registers)
#define ccl_gpu_kernel_threads(block_num_threads)
/* convert a comma-separated list into a semicolon-separated list (so that we can generate a struct based on kernel entrypoint parameters) */
/* Convert a comma-separated list into a semicolon-separated list
* (so that we can generate a struct based on kernel entry-point parameters). */
#define FN0()
#define FN1(p1) p1;
#define FN2(p1, p2) p1; p2;
@@ -94,7 +95,8 @@ using namespace metal;
#define GET_LAST_ARG(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, ...) p16
#define PARAMS_MAKER(...) GET_LAST_ARG(__VA_ARGS__, FN16, FN15, FN14, FN13, FN12, FN11, FN10, FN9, FN8, FN7, FN6, FN5, FN4, FN3, FN2, FN1, FN0)
/* generate a struct containing the entrypoint parameters and a "run" method which can access them implicitly via this-> */
/* Generate a struct containing the entry-point parameters and a "run"
* method which can access them implicitly via this-> */
#define ccl_gpu_kernel_signature(name, ...) \
struct kernel_gpu_##name \
{ \

View File

@@ -76,4 +76,4 @@ class MetalKernelContext {
}
# include "kernel/device/gpu/image.h"
// clang-format on
// clang-format on

View File

@@ -17,7 +17,7 @@
; /* end of MetalKernelContext class definition */
/* Silently redirect into the MetalKernelContext instance */
/* NOTE: These macros will need maintaining as entrypoints change */
/* NOTE: These macros will need maintaining as entry-points change. */
#undef kernel_integrator_state
#define kernel_integrator_state context.launch_params_metal.__integrator_state

View File

@@ -57,7 +57,7 @@ extern "C" __global__ void __raygen__kernel_optix_integrator_intersect_closest()
const int global_index = optixGetLaunchIndex().x;
const int path_index = (__params.path_index_array) ? __params.path_index_array[global_index] :
global_index;
integrator_intersect_closest(nullptr, path_index);
integrator_intersect_closest(nullptr, path_index, __params.render_buffer);
}
extern "C" __global__ void __raygen__kernel_optix_integrator_intersect_shadow()

View File

@@ -33,62 +33,72 @@ CCL_NAMESPACE_BEGIN
* them separately. */
ccl_device_inline void bsdf_eval_init(ccl_private BsdfEval *eval,
const bool is_diffuse,
const ClosureType closure_type,
float3 value)
{
eval->diffuse = zero_float3();
eval->glossy = zero_float3();
if (is_diffuse) {
if (CLOSURE_IS_BSDF_DIFFUSE(closure_type)) {
eval->diffuse = value;
}
else {
else if (CLOSURE_IS_BSDF_GLOSSY(closure_type)) {
eval->glossy = value;
}
eval->sum = value;
}
ccl_device_inline void bsdf_eval_accum(ccl_private BsdfEval *eval,
const bool is_diffuse,
float3 value,
float mis_weight)
const ClosureType closure_type,
float3 value)
{
value *= mis_weight;
if (is_diffuse) {
if (CLOSURE_IS_BSDF_DIFFUSE(closure_type)) {
eval->diffuse += value;
}
else {
else if (CLOSURE_IS_BSDF_GLOSSY(closure_type)) {
eval->glossy += value;
}
eval->sum += value;
}
ccl_device_inline bool bsdf_eval_is_zero(ccl_private BsdfEval *eval)
{
return is_zero(eval->diffuse) && is_zero(eval->glossy);
return is_zero(eval->sum);
}
ccl_device_inline void bsdf_eval_mul(ccl_private BsdfEval *eval, float value)
{
eval->diffuse *= value;
eval->glossy *= value;
eval->sum *= value;
}
ccl_device_inline void bsdf_eval_mul3(ccl_private BsdfEval *eval, float3 value)
{
eval->diffuse *= value;
eval->glossy *= value;
eval->sum *= value;
}
ccl_device_inline float3 bsdf_eval_sum(ccl_private const BsdfEval *eval)
{
return eval->diffuse + eval->glossy;
return eval->sum;
}
ccl_device_inline float3 bsdf_eval_diffuse_glossy_ratio(ccl_private const BsdfEval *eval)
ccl_device_inline float3 bsdf_eval_pass_diffuse_weight(ccl_private const BsdfEval *eval)
{
/* Ratio of diffuse and glossy to recover proportions for writing to render pass.
/* Ratio of diffuse weight to recover proportions for writing to render pass.
* We assume reflection, transmission and volume scatter to be exclusive. */
return safe_divide_float3_float3(eval->diffuse, eval->diffuse + eval->glossy);
return safe_divide_float3_float3(eval->diffuse, eval->sum);
}
ccl_device_inline float3 bsdf_eval_pass_glossy_weight(ccl_private const BsdfEval *eval)
{
/* Ratio of glossy weight to recover proportions for writing to render pass.
* We assume reflection, transmission and volume scatter to be exclusive. */
return safe_divide_float3_float3(eval->glossy, eval->sum);
}
/* --------------------------------------------------------------------
@@ -141,7 +151,8 @@ ccl_device_forceinline ccl_global float *kernel_accum_pixel_render_buffer(
ccl_device_inline int kernel_accum_sample(KernelGlobals kg,
ConstIntegratorState state,
ccl_global float *ccl_restrict render_buffer,
int sample)
int sample,
int sample_offset)
{
if (kernel_data.film.pass_sample_count == PASS_UNUSED) {
return sample;
@@ -149,7 +160,8 @@ ccl_device_inline int kernel_accum_sample(KernelGlobals kg,
ccl_global float *buffer = kernel_accum_pixel_render_buffer(kg, state, render_buffer);
return atomic_fetch_and_add_uint32((uint *)(buffer) + kernel_data.film.pass_sample_count, 1);
return atomic_fetch_and_add_uint32((uint *)(buffer) + kernel_data.film.pass_sample_count, 1) +
sample_offset;
}
ccl_device void kernel_accum_adaptive_buffer(KernelGlobals kg,
@@ -351,37 +363,47 @@ ccl_device_inline void kernel_accum_emission_or_background_pass(KernelGlobals kg
/* Directly visible, write to emission or background pass. */
pass_offset = pass;
}
else if (path_flag & (PATH_RAY_REFLECT_PASS | PATH_RAY_TRANSMISSION_PASS)) {
/* Indirectly visible through reflection. */
const int glossy_pass_offset = (path_flag & PATH_RAY_REFLECT_PASS) ?
((INTEGRATOR_STATE(state, path, bounce) == 1) ?
kernel_data.film.pass_glossy_direct :
kernel_data.film.pass_glossy_indirect) :
((INTEGRATOR_STATE(state, path, bounce) == 1) ?
kernel_data.film.pass_transmission_direct :
kernel_data.film.pass_transmission_indirect);
else if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
if (path_flag & PATH_RAY_SURFACE_PASS) {
/* Indirectly visible through reflection. */
const float3 diffuse_weight = INTEGRATOR_STATE(state, path, pass_diffuse_weight);
const float3 glossy_weight = INTEGRATOR_STATE(state, path, pass_glossy_weight);
if (glossy_pass_offset != PASS_UNUSED) {
/* Glossy is a subset of the throughput, reconstruct it here using the
* diffuse-glossy ratio. */
const float3 ratio = INTEGRATOR_STATE(state, path, diffuse_glossy_ratio);
const float3 glossy_contribution = (one_float3() - ratio) * contribution;
kernel_write_pass_float3(buffer + glossy_pass_offset, glossy_contribution);
}
/* Glossy */
const int glossy_pass_offset = ((INTEGRATOR_STATE(state, path, bounce) == 1) ?
kernel_data.film.pass_glossy_direct :
kernel_data.film.pass_glossy_indirect);
if (glossy_pass_offset != PASS_UNUSED) {
kernel_write_pass_float3(buffer + glossy_pass_offset, glossy_weight * contribution);
}
/* Reconstruct diffuse subset of throughput. */
pass_offset = (INTEGRATOR_STATE(state, path, bounce) == 1) ?
kernel_data.film.pass_diffuse_direct :
kernel_data.film.pass_diffuse_indirect;
if (pass_offset != PASS_UNUSED) {
contribution *= INTEGRATOR_STATE(state, path, diffuse_glossy_ratio);
/* Transmission */
const int transmission_pass_offset = ((INTEGRATOR_STATE(state, path, bounce) == 1) ?
kernel_data.film.pass_transmission_direct :
kernel_data.film.pass_transmission_indirect);
if (transmission_pass_offset != PASS_UNUSED) {
/* Transmission is what remains if not diffuse and glossy, not stored explicitly to save
* GPU memory. */
const float3 transmission_weight = one_float3() - diffuse_weight - glossy_weight;
kernel_write_pass_float3(buffer + transmission_pass_offset,
transmission_weight * contribution);
}
/* Reconstruct diffuse subset of throughput. */
pass_offset = (INTEGRATOR_STATE(state, path, bounce) == 1) ?
kernel_data.film.pass_diffuse_direct :
kernel_data.film.pass_diffuse_indirect;
if (pass_offset != PASS_UNUSED) {
contribution *= diffuse_weight;
}
}
else if (path_flag & PATH_RAY_VOLUME_PASS) {
/* Indirectly visible through volume. */
pass_offset = (INTEGRATOR_STATE(state, path, bounce) == 1) ?
kernel_data.film.pass_volume_direct :
kernel_data.film.pass_volume_indirect;
}
}
else if (path_flag & PATH_RAY_VOLUME_PASS) {
/* Indirectly visible through volume. */
pass_offset = (INTEGRATOR_STATE(state, path, bounce) == 1) ?
kernel_data.film.pass_volume_direct :
kernel_data.film.pass_volume_indirect;
}
/* Single write call for GPU coherence. */
@@ -426,45 +448,56 @@ ccl_device_inline void kernel_accum_light(KernelGlobals kg,
#ifdef __PASSES__
if (kernel_data.film.light_pass_flag & PASS_ANY) {
const uint32_t path_flag = INTEGRATOR_STATE(state, shadow_path, flag);
int pass_offset = PASS_UNUSED;
if (path_flag & (PATH_RAY_REFLECT_PASS | PATH_RAY_TRANSMISSION_PASS)) {
/* Indirectly visible through reflection. */
const int glossy_pass_offset = (path_flag & PATH_RAY_REFLECT_PASS) ?
((INTEGRATOR_STATE(state, shadow_path, bounce) == 0) ?
kernel_data.film.pass_glossy_direct :
kernel_data.film.pass_glossy_indirect) :
((INTEGRATOR_STATE(state, shadow_path, bounce) == 0) ?
kernel_data.film.pass_transmission_direct :
kernel_data.film.pass_transmission_indirect);
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
int pass_offset = PASS_UNUSED;
if (glossy_pass_offset != PASS_UNUSED) {
/* Glossy is a subset of the throughput, reconstruct it here using the
* diffuse-glossy ratio. */
const float3 ratio = INTEGRATOR_STATE(state, shadow_path, diffuse_glossy_ratio);
const float3 glossy_contribution = (one_float3() - ratio) * contribution;
kernel_write_pass_float3(buffer + glossy_pass_offset, glossy_contribution);
if (path_flag & PATH_RAY_SURFACE_PASS) {
/* Indirectly visible through reflection. */
const float3 diffuse_weight = INTEGRATOR_STATE(state, shadow_path, pass_diffuse_weight);
const float3 glossy_weight = INTEGRATOR_STATE(state, shadow_path, pass_glossy_weight);
/* Glossy */
const int glossy_pass_offset = ((INTEGRATOR_STATE(state, shadow_path, bounce) == 0) ?
kernel_data.film.pass_glossy_direct :
kernel_data.film.pass_glossy_indirect);
if (glossy_pass_offset != PASS_UNUSED) {
kernel_write_pass_float3(buffer + glossy_pass_offset, glossy_weight * contribution);
}
/* Transmission */
const int transmission_pass_offset = ((INTEGRATOR_STATE(state, shadow_path, bounce) == 0) ?
kernel_data.film.pass_transmission_direct :
kernel_data.film.pass_transmission_indirect);
if (transmission_pass_offset != PASS_UNUSED) {
/* Transmission is what remains if not diffuse and glossy, not stored explicitly to save
* GPU memory. */
const float3 transmission_weight = one_float3() - diffuse_weight - glossy_weight;
kernel_write_pass_float3(buffer + transmission_pass_offset,
transmission_weight * contribution);
}
/* Reconstruct diffuse subset of throughput. */
pass_offset = (INTEGRATOR_STATE(state, shadow_path, bounce) == 0) ?
kernel_data.film.pass_diffuse_direct :
kernel_data.film.pass_diffuse_indirect;
if (pass_offset != PASS_UNUSED) {
contribution *= diffuse_weight;
}
}
else if (path_flag & PATH_RAY_VOLUME_PASS) {
/* Indirectly visible through volume. */
pass_offset = (INTEGRATOR_STATE(state, shadow_path, bounce) == 0) ?
kernel_data.film.pass_volume_direct :
kernel_data.film.pass_volume_indirect;
}
/* Reconstruct diffuse subset of throughput. */
pass_offset = (INTEGRATOR_STATE(state, shadow_path, bounce) == 0) ?
kernel_data.film.pass_diffuse_direct :
kernel_data.film.pass_diffuse_indirect;
/* Single write call for GPU coherence. */
if (pass_offset != PASS_UNUSED) {
contribution *= INTEGRATOR_STATE(state, shadow_path, diffuse_glossy_ratio);
kernel_write_pass_float3(buffer + pass_offset, contribution);
}
}
else if (path_flag & PATH_RAY_VOLUME_PASS) {
/* Indirectly visible through volume. */
pass_offset = (INTEGRATOR_STATE(state, shadow_path, bounce) == 0) ?
kernel_data.film.pass_volume_direct :
kernel_data.film.pass_volume_indirect;
}
/* Single write call for GPU coherence. */
if (pass_offset != PASS_UNUSED) {
kernel_write_pass_float3(buffer + pass_offset, contribution);
}
/* Write shadow pass. */
if (kernel_data.film.pass_shadow != PASS_UNUSED && (path_flag & PATH_RAY_SHADOW_FOR_LIGHT) &&

View File

@@ -160,40 +160,6 @@ ccl_device_forceinline void kernel_write_denoising_features_volume(KernelGlobals
}
#endif /* __DENOISING_FEATURES__ */
#ifdef __SHADOW_CATCHER__
/* Write shadow catcher passes on a bounce from the shadow catcher object. */
ccl_device_forceinline void kernel_write_shadow_catcher_bounce_data(
KernelGlobals kg,
IntegratorState state,
ccl_private const ShaderData *sd,
ccl_global float *ccl_restrict render_buffer)
{
if (!kernel_data.integrator.has_shadow_catcher) {
return;
}
kernel_assert(kernel_data.film.pass_shadow_catcher_sample_count != PASS_UNUSED);
kernel_assert(kernel_data.film.pass_shadow_catcher_matte != PASS_UNUSED);
if (!kernel_shadow_catcher_is_path_split_bounce(kg, state, sd->object_flag)) {
return;
}
ccl_global float *buffer = kernel_pass_pixel_render_buffer(kg, state, render_buffer);
/* Count sample for the shadow catcher object. */
kernel_write_pass_float(buffer + kernel_data.film.pass_shadow_catcher_sample_count, 1.0f);
/* Since the split is done, the sample does not contribute to the matte, so accumulate it as
* transparency to the matte. */
const float3 throughput = INTEGRATOR_STATE(state, path, throughput);
kernel_write_pass_float(buffer + kernel_data.film.pass_shadow_catcher_matte + 3,
average(throughput));
}
#endif /* __SHADOW_CATCHER__ */
ccl_device_inline size_t kernel_write_id_pass(ccl_global float *ccl_restrict buffer,
size_t depth,
float id,

View File

@@ -65,7 +65,8 @@ ccl_device bool integrator_init_from_bake(KernelGlobals kg,
}
/* Always count the sample, even if the camera sample will reject the ray. */
const int sample = kernel_accum_sample(kg, state, render_buffer, scheduled_sample);
const int sample = kernel_accum_sample(
kg, state, render_buffer, scheduled_sample, tile->sample_offset);
/* Setup render buffers. */
const int index = INTEGRATOR_STATE(state, path, render_pixel_index);

View File

@@ -89,7 +89,8 @@ ccl_device bool integrator_init_from_camera(KernelGlobals kg,
* This logic allows to both count actual number of samples per pixel, and to add samples to this
* pixel after it was converged and samples were added somewhere else (in which case the
* `scheduled_sample` will be different from actual number of samples in this pixel). */
const int sample = kernel_accum_sample(kg, state, render_buffer, scheduled_sample);
const int sample = kernel_accum_sample(
kg, state, render_buffer, scheduled_sample, tile->sample_offset);
/* Initialize random number seed for path. */
const uint rng_hash = path_rng_hash_init(kg, sample, x, y);

View File

@@ -88,7 +88,10 @@ ccl_device_forceinline bool integrator_intersect_terminate(KernelGlobals kg,
#ifdef __SHADOW_CATCHER__
/* Split path if a shadow catcher was hit. */
ccl_device_forceinline void integrator_split_shadow_catcher(
KernelGlobals kg, IntegratorState state, ccl_private const Intersection *ccl_restrict isect)
KernelGlobals kg,
IntegratorState state,
ccl_private const Intersection *ccl_restrict isect,
ccl_global float *ccl_restrict render_buffer)
{
/* Test if we hit a shadow catcher object, and potentially split the path to continue tracing two
* paths from here. */
@@ -97,6 +100,8 @@ ccl_device_forceinline void integrator_split_shadow_catcher(
return;
}
kernel_write_shadow_catcher_bounce_data(kg, state, render_buffer);
/* Mark state as having done a shadow catcher split so that it stops contributing to
* the shadow catcher matte pass, but keeps contributing to the combined pass. */
INTEGRATOR_STATE_WRITE(state, path, flag) |= PATH_RAY_SHADOW_CATCHER_HIT;
@@ -191,6 +196,7 @@ ccl_device_forceinline void integrator_intersect_next_kernel(
KernelGlobals kg,
IntegratorState state,
ccl_private const Intersection *ccl_restrict isect,
ccl_global float *ccl_restrict render_buffer,
const bool hit)
{
/* Continue with volume kernel if we are inside a volume, regardless if we hit anything. */
@@ -233,7 +239,7 @@ ccl_device_forceinline void integrator_intersect_next_kernel(
#ifdef __SHADOW_CATCHER__
/* Handle shadow catcher. */
integrator_split_shadow_catcher(kg, state, isect);
integrator_split_shadow_catcher(kg, state, isect, render_buffer);
#endif
}
else {
@@ -253,7 +259,10 @@ ccl_device_forceinline void integrator_intersect_next_kernel(
* volume shading and termination testing have already been done. */
template<uint32_t current_kernel>
ccl_device_forceinline void integrator_intersect_next_kernel_after_volume(
KernelGlobals kg, IntegratorState state, ccl_private const Intersection *ccl_restrict isect)
KernelGlobals kg,
IntegratorState state,
ccl_private const Intersection *ccl_restrict isect,
ccl_global float *ccl_restrict render_buffer)
{
if (isect->prim != PRIM_NONE) {
/* Hit a surface, continue with light or surface kernel. */
@@ -278,7 +287,7 @@ ccl_device_forceinline void integrator_intersect_next_kernel_after_volume(
#ifdef __SHADOW_CATCHER__
/* Handle shadow catcher. */
integrator_split_shadow_catcher(kg, state, isect);
integrator_split_shadow_catcher(kg, state, isect, render_buffer);
#endif
return;
}
@@ -290,7 +299,9 @@ ccl_device_forceinline void integrator_intersect_next_kernel_after_volume(
}
}
ccl_device void integrator_intersect_closest(KernelGlobals kg, IntegratorState state)
ccl_device void integrator_intersect_closest(KernelGlobals kg,
IntegratorState state,
ccl_global float *ccl_restrict render_buffer)
{
PROFILING_INIT(kg, PROFILING_INTERSECT_CLOSEST);
@@ -341,7 +352,7 @@ ccl_device void integrator_intersect_closest(KernelGlobals kg, IntegratorState s
/* Setup up next kernel to be executed. */
integrator_intersect_next_kernel<DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST>(
kg, state, &isect, hit);
kg, state, &isect, render_buffer, hit);
}
CCL_NAMESPACE_END

View File

@@ -76,7 +76,7 @@ ccl_device void integrator_megakernel(KernelGlobals kg,
if (queued_kernel) {
switch (queued_kernel) {
case DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST:
integrator_intersect_closest(kg, state);
integrator_intersect_closest(kg, state, render_buffer);
break;
case DEVICE_KERNEL_INTEGRATOR_SHADE_BACKGROUND:
integrator_shade_background(kg, state, render_buffer);

View File

@@ -185,7 +185,7 @@ ccl_device_inline void path_state_next(KernelGlobals kg, IntegratorState state,
/* Render pass categories. */
if (bounce == 1) {
flag |= (label & LABEL_TRANSMIT) ? PATH_RAY_TRANSMISSION_PASS : PATH_RAY_REFLECT_PASS;
flag |= PATH_RAY_SURFACE_PASS;
}
}

View File

@@ -191,14 +191,18 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
const uint16_t transparent_bounce = INTEGRATOR_STATE(state, path, transparent_bounce);
uint32_t shadow_flag = INTEGRATOR_STATE(state, path, flag);
shadow_flag |= (is_light) ? PATH_RAY_SHADOW_FOR_LIGHT : 0;
shadow_flag |= (is_transmission) ? PATH_RAY_TRANSMISSION_PASS : PATH_RAY_REFLECT_PASS;
shadow_flag |= PATH_RAY_SURFACE_PASS;
const float3 throughput = INTEGRATOR_STATE(state, path, throughput) * bsdf_eval_sum(&bsdf_eval);
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
const float3 diffuse_glossy_ratio = (bounce == 0) ?
bsdf_eval_diffuse_glossy_ratio(&bsdf_eval) :
INTEGRATOR_STATE(state, path, diffuse_glossy_ratio);
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, diffuse_glossy_ratio) = diffuse_glossy_ratio;
const float3 pass_diffuse_weight = (bounce == 0) ?
bsdf_eval_pass_diffuse_weight(&bsdf_eval) :
INTEGRATOR_STATE(state, path, pass_diffuse_weight);
const float3 pass_glossy_weight = (bounce == 0) ?
bsdf_eval_pass_glossy_weight(&bsdf_eval) :
INTEGRATOR_STATE(state, path, pass_glossy_weight);
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, pass_diffuse_weight) = pass_diffuse_weight;
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, pass_glossy_weight) = pass_glossy_weight;
}
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, render_pixel_index) = INTEGRATOR_STATE(
@@ -283,7 +287,9 @@ ccl_device_forceinline int integrate_surface_bsdf_bssrdf_bounce(
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
if (INTEGRATOR_STATE(state, path, bounce) == 0) {
INTEGRATOR_STATE_WRITE(state, path, diffuse_glossy_ratio) = bsdf_eval_diffuse_glossy_ratio(
INTEGRATOR_STATE_WRITE(state, path, pass_diffuse_weight) = bsdf_eval_pass_diffuse_weight(
&bsdf_eval);
INTEGRATOR_STATE_WRITE(state, path, pass_glossy_weight) = bsdf_eval_pass_glossy_weight(
&bsdf_eval);
}
}
@@ -445,7 +451,7 @@ ccl_device bool integrate_surface(KernelGlobals kg,
}
#endif
shader_prepare_surface_closures(kg, state, &sd);
shader_prepare_surface_closures(kg, state, &sd, path_flag);
#ifdef __HOLDOUT__
/* Evaluate holdout. */
@@ -492,10 +498,6 @@ ccl_device bool integrate_surface(KernelGlobals kg,
kernel_write_denoising_features_surface(kg, state, &sd, render_buffer);
#endif
#ifdef __SHADOW_CATCHER__
kernel_write_shadow_catcher_bounce_data(kg, state, &sd, render_buffer);
#endif
/* Direct light. */
PROFILING_EVENT(PROFILING_SHADE_SURFACE_DIRECT_LIGHT);
integrate_surface_direct_light(kg, state, &sd, &rng_state);

View File

@@ -794,10 +794,11 @@ ccl_device_forceinline void integrate_volume_direct_light(
const float3 throughput_phase = throughput * bsdf_eval_sum(&phase_eval);
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
const float3 diffuse_glossy_ratio = (bounce == 0) ?
one_float3() :
INTEGRATOR_STATE(state, path, diffuse_glossy_ratio);
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, diffuse_glossy_ratio) = diffuse_glossy_ratio;
const float3 pass_diffuse_weight = (bounce == 0) ?
one_float3() :
INTEGRATOR_STATE(state, path, pass_diffuse_weight);
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, pass_diffuse_weight) = pass_diffuse_weight;
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, pass_glossy_weight) = zero_float3();
}
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, render_pixel_index) = INTEGRATOR_STATE(
@@ -876,7 +877,8 @@ ccl_device_forceinline bool integrate_volume_phase_scatter(
INTEGRATOR_STATE_WRITE(state, path, throughput) = throughput_phase;
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
INTEGRATOR_STATE_WRITE(state, path, diffuse_glossy_ratio) = one_float3();
INTEGRATOR_STATE_WRITE(state, path, pass_diffuse_weight) = one_float3();
INTEGRATOR_STATE_WRITE(state, path, pass_glossy_weight) = zero_float3();
}
/* Update path state */
@@ -1024,7 +1026,7 @@ ccl_device void integrator_shade_volume(KernelGlobals kg,
else {
/* Continue to background, light or surface. */
integrator_intersect_next_kernel_after_volume<DEVICE_KERNEL_INTEGRATOR_SHADE_VOLUME>(
kg, state, &isect);
kg, state, &isect, render_buffer);
return;
}
#endif /* __VOLUME__ */

View File

@@ -105,8 +105,45 @@ ccl_device_inline void shader_copy_volume_phases(ccl_private ShaderVolumePhases
ccl_device_inline void shader_prepare_surface_closures(KernelGlobals kg,
ConstIntegratorState state,
ccl_private ShaderData *sd)
ccl_private ShaderData *sd,
const uint32_t path_flag)
{
/* Filter out closures. */
if (kernel_data.integrator.filter_closures) {
if (kernel_data.integrator.filter_closures & FILTER_CLOSURE_EMISSION) {
sd->closure_emission_background = zero_float3();
}
if (kernel_data.integrator.filter_closures & FILTER_CLOSURE_DIRECT_LIGHT) {
sd->flag &= ~SD_BSDF_HAS_EVAL;
}
if (path_flag & PATH_RAY_CAMERA) {
for (int i = 0; i < sd->num_closure; i++) {
ccl_private ShaderClosure *sc = &sd->closure[i];
if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
if (kernel_data.integrator.filter_closures & FILTER_CLOSURE_DIFFUSE) {
sc->type = CLOSURE_NONE_ID;
sc->sample_weight = 0.0f;
}
}
else if (CLOSURE_IS_BSDF_GLOSSY(sc->type)) {
if (kernel_data.integrator.filter_closures & FILTER_CLOSURE_GLOSSY) {
sc->type = CLOSURE_NONE_ID;
sc->sample_weight = 0.0f;
}
}
else if (CLOSURE_IS_BSDF_TRANSMISSION(sc->type)) {
if (kernel_data.integrator.filter_closures & FILTER_CLOSURE_TRANSMISSION) {
sc->type = CLOSURE_NONE_ID;
sc->sample_weight = 0.0f;
}
}
}
}
}
/* Defensive sampling.
*
* We can likely also do defensive sampling at deeper bounces, particularly
@@ -209,8 +246,7 @@ ccl_device_inline float _shader_bsdf_multi_eval(KernelGlobals kg,
float3 eval = bsdf_eval(kg, sd, sc, omega_in, is_transmission, &bsdf_pdf);
if (bsdf_pdf != 0.0f) {
const bool is_diffuse = CLOSURE_IS_BSDF_DIFFUSE(sc->type);
bsdf_eval_accum(result_eval, is_diffuse, eval * sc->weight, 1.0f);
bsdf_eval_accum(result_eval, sc->type, eval * sc->weight);
sum_pdf += bsdf_pdf * sc->sample_weight;
}
}
@@ -235,7 +271,7 @@ ccl_device_inline
ccl_private BsdfEval *bsdf_eval,
const uint light_shader_flags)
{
bsdf_eval_init(bsdf_eval, false, zero_float3());
bsdf_eval_init(bsdf_eval, CLOSURE_NONE_ID, zero_float3());
return _shader_bsdf_multi_eval(
kg, sd, omega_in, is_transmission, NULL, bsdf_eval, 0.0f, 0.0f, light_shader_flags);
@@ -328,8 +364,7 @@ ccl_device int shader_bsdf_sample_closure(KernelGlobals kg,
label = bsdf_sample(kg, sd, sc, randu, randv, &eval, omega_in, domega_in, pdf);
if (*pdf != 0.0f) {
const bool is_diffuse = CLOSURE_IS_BSDF_DIFFUSE(sc->type);
bsdf_eval_init(bsdf_eval, is_diffuse, eval * sc->weight);
bsdf_eval_init(bsdf_eval, sc->type, eval * sc->weight);
if (sd->num_closure > 1) {
const bool is_transmission = shader_bsdf_is_transmission(sd, *omega_in);
@@ -655,7 +690,7 @@ ccl_device_inline float _shader_volume_phase_multi_eval(
float3 eval = volume_phase_eval(sd, svc, omega_in, &phase_pdf);
if (phase_pdf != 0.0f) {
bsdf_eval_accum(result_eval, false, eval, 1.0f);
bsdf_eval_accum(result_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, eval);
sum_pdf += phase_pdf * svc->sample_weight;
}
@@ -671,7 +706,7 @@ ccl_device float shader_volume_phase_eval(KernelGlobals kg,
const float3 omega_in,
ccl_private BsdfEval *phase_eval)
{
bsdf_eval_init(phase_eval, false, zero_float3());
bsdf_eval_init(phase_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, zero_float3());
return _shader_volume_phase_multi_eval(sd, phases, omega_in, -1, phase_eval, 0.0f, 0.0f);
}
@@ -729,7 +764,7 @@ ccl_device int shader_volume_phase_sample(KernelGlobals kg,
label = volume_phase_sample(sd, svc, randu, randv, &eval, omega_in, domega_in, pdf);
if (*pdf != 0.0f) {
bsdf_eval_init(phase_eval, false, eval);
bsdf_eval_init(phase_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, eval);
}
return label;
@@ -752,7 +787,7 @@ ccl_device int shader_phase_sample_closure(KernelGlobals kg,
label = volume_phase_sample(sd, sc, randu, randv, &eval, omega_in, domega_in, pdf);
if (*pdf != 0.0f)
bsdf_eval_init(phase_eval, false, eval);
bsdf_eval_init(phase_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, eval);
return label;
}

View File

@@ -16,6 +16,7 @@
#pragma once
#include "kernel/film/write_passes.h"
#include "kernel/integrator/path_state.h"
#include "kernel/integrator/state_util.h"
@@ -47,7 +48,7 @@ ccl_device_inline bool kernel_shadow_catcher_is_path_split_bounce(KernelGlobals
return false;
}
if (path_flag & PATH_RAY_SHADOW_CATCHER_PASS) {
if (path_flag & PATH_RAY_SHADOW_CATCHER_HIT) {
return false;
}
@@ -88,6 +89,28 @@ ccl_device_forceinline bool kernel_shadow_catcher_is_object_pass(const uint32_t
return path_flag & PATH_RAY_SHADOW_CATCHER_PASS;
}
/* Write shadow catcher passes on a bounce from the shadow catcher object. */
ccl_device_forceinline void kernel_write_shadow_catcher_bounce_data(
KernelGlobals kg, IntegratorState state, ccl_global float *ccl_restrict render_buffer)
{
kernel_assert(kernel_data.film.pass_shadow_catcher_sample_count != PASS_UNUSED);
kernel_assert(kernel_data.film.pass_shadow_catcher_matte != PASS_UNUSED);
const uint32_t render_pixel_index = INTEGRATOR_STATE(state, path, render_pixel_index);
const uint64_t render_buffer_offset = (uint64_t)render_pixel_index *
kernel_data.film.pass_stride;
ccl_global float *buffer = render_buffer + render_buffer_offset;
/* Count sample for the shadow catcher object. */
kernel_write_pass_float(buffer + kernel_data.film.pass_shadow_catcher_sample_count, 1.0f);
/* Since the split is done, the sample does not contribute to the matte, so accumulate it as
* transparency to the matte. */
const float3 throughput = INTEGRATOR_STATE(state, path, throughput);
kernel_write_pass_float(buffer + kernel_data.film.pass_shadow_catcher_matte + 3,
average(throughput));
}
#endif /* __SHADOW_CATCHER__ */
CCL_NAMESPACE_END

View File

@@ -46,8 +46,9 @@ KERNEL_STRUCT_MEMBER(shadow_path,
float3,
unshadowed_throughput,
KERNEL_FEATURE_SHADOW_PASS | KERNEL_FEATURE_AO_ADDITIVE)
/* Ratio of throughput to distinguish diffuse and glossy render passes. */
KERNEL_STRUCT_MEMBER(shadow_path, float3, diffuse_glossy_ratio, KERNEL_FEATURE_LIGHT_PASSES)
/* Ratio of throughput to distinguish diffuse / glossy / transmission render passes. */
KERNEL_STRUCT_MEMBER(shadow_path, float3, pass_diffuse_weight, KERNEL_FEATURE_LIGHT_PASSES)
KERNEL_STRUCT_MEMBER(shadow_path, float3, pass_glossy_weight, KERNEL_FEATURE_LIGHT_PASSES)
/* Number of intersections found by ray-tracing. */
KERNEL_STRUCT_MEMBER(shadow_path, uint16_t, num_hits, KERNEL_FEATURE_PATH_TRACING)
KERNEL_STRUCT_END(shadow_path)

View File

@@ -60,8 +60,9 @@ KERNEL_STRUCT_MEMBER(path, float, min_ray_pdf, KERNEL_FEATURE_PATH_TRACING)
KERNEL_STRUCT_MEMBER(path, float, continuation_probability, KERNEL_FEATURE_PATH_TRACING)
/* Throughput. */
KERNEL_STRUCT_MEMBER(path, float3, throughput, KERNEL_FEATURE_PATH_TRACING)
/* Ratio of throughput to distinguish diffuse and glossy render passes. */
KERNEL_STRUCT_MEMBER(path, float3, diffuse_glossy_ratio, KERNEL_FEATURE_LIGHT_PASSES)
/* Ratio of throughput to distinguish diffuse / glossy / transmission render passes. */
KERNEL_STRUCT_MEMBER(path, float3, pass_diffuse_weight, KERNEL_FEATURE_LIGHT_PASSES)
KERNEL_STRUCT_MEMBER(path, float3, pass_glossy_weight, KERNEL_FEATURE_LIGHT_PASSES)
/* Denoising. */
KERNEL_STRUCT_MEMBER(path, float3, denoising_feature_throughput, KERNEL_FEATURE_DENOISING)
/* Shader sorting. */

View File

@@ -79,7 +79,8 @@ ccl_device int subsurface_bounce(KernelGlobals kg,
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
if (INTEGRATOR_STATE(state, path, bounce) == 0) {
INTEGRATOR_STATE_WRITE(state, path, diffuse_glossy_ratio) = one_float3();
INTEGRATOR_STATE_WRITE(state, path, pass_diffuse_weight) = one_float3();
INTEGRATOR_STATE_WRITE(state, path, pass_glossy_weight) = zero_float3();
}
}

View File

@@ -286,27 +286,26 @@ enum PathRayFlag {
PATH_RAY_DENOISING_FEATURES = (1U << 23U),
/* Render pass categories. */
PATH_RAY_REFLECT_PASS = (1U << 24U),
PATH_RAY_TRANSMISSION_PASS = (1U << 25U),
PATH_RAY_VOLUME_PASS = (1U << 26U),
PATH_RAY_ANY_PASS = (PATH_RAY_REFLECT_PASS | PATH_RAY_TRANSMISSION_PASS | PATH_RAY_VOLUME_PASS),
PATH_RAY_SURFACE_PASS = (1U << 24U),
PATH_RAY_VOLUME_PASS = (1U << 25U),
PATH_RAY_ANY_PASS = (PATH_RAY_SURFACE_PASS | PATH_RAY_VOLUME_PASS),
/* Shadow ray is for a light or surface, or AO. */
PATH_RAY_SHADOW_FOR_LIGHT = (1U << 27U),
PATH_RAY_SHADOW_FOR_AO = (1U << 28U),
PATH_RAY_SHADOW_FOR_LIGHT = (1U << 26U),
PATH_RAY_SHADOW_FOR_AO = (1U << 27U),
/* A shadow catcher object was hit and the path was split into two. */
PATH_RAY_SHADOW_CATCHER_HIT = (1U << 29U),
PATH_RAY_SHADOW_CATCHER_HIT = (1U << 28U),
/* A shadow catcher object was hit and this path traces only shadow catchers, writing them into
* their dedicated pass for later division.
*
* NOTE: Is not covered with `PATH_RAY_ANY_PASS` because shadow catcher does special handling
* which is separate from the light passes. */
PATH_RAY_SHADOW_CATCHER_PASS = (1U << 30U),
PATH_RAY_SHADOW_CATCHER_PASS = (1U << 29U),
/* Path is evaluating background for an approximate shadow catcher with non-transparent film. */
PATH_RAY_SHADOW_CATCHER_BACKGROUND = (1U << 31U),
PATH_RAY_SHADOW_CATCHER_BACKGROUND = (1U << 30U),
};
/* Configure ray visibility bits for rays and objects respectively,
@@ -428,8 +427,19 @@ typedef enum CryptomatteType {
typedef struct BsdfEval {
float3 diffuse;
float3 glossy;
float3 sum;
} BsdfEval;
/* Closure Filter */
typedef enum FilterClosures {
FILTER_CLOSURE_EMISSION = (1 << 0),
FILTER_CLOSURE_DIFFUSE = (1 << 1),
FILTER_CLOSURE_GLOSSY = (1 << 2),
FILTER_CLOSURE_TRANSMISSION = (1 << 3),
FILTER_CLOSURE_DIRECT_LIGHT = (1 << 4),
} FilterClosures;
/* Shader Flag */
typedef enum ShaderFlag {
@@ -1186,7 +1196,11 @@ typedef struct KernelIntegrator {
int has_shadow_catcher;
float scrambling_distance;
/* Closure filter. */
int filter_closures;
/* padding */
int pad1, pad2, pad3;
} KernelIntegrator;
static_assert_align(KernelIntegrator, 16);
@@ -1410,6 +1424,7 @@ typedef struct KernelWorkTile {
uint start_sample;
uint num_samples;
uint sample_offset;
int offset;
uint stride;

View File

@@ -187,8 +187,6 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
kfilm->pass_transmission_indirect = PASS_UNUSED;
kfilm->pass_volume_direct = PASS_UNUSED;
kfilm->pass_volume_indirect = PASS_UNUSED;
kfilm->pass_volume_direct = PASS_UNUSED;
kfilm->pass_volume_indirect = PASS_UNUSED;
kfilm->pass_shadow = PASS_UNUSED;
/* Mark passes as unused so that the kernel knows the pass is inaccessible. */
@@ -673,13 +671,12 @@ uint Film::get_kernel_features(const Scene *scene) const
kernel_features |= KERNEL_FEATURE_DENOISING;
}
if (pass_type != PASS_NONE && pass_type != PASS_COMBINED &&
pass_type <= PASS_CATEGORY_LIGHT_END) {
if (pass_type >= PASS_DIFFUSE && pass_type <= PASS_VOLUME_INDIRECT) {
kernel_features |= KERNEL_FEATURE_LIGHT_PASSES;
}
if (pass_type == PASS_SHADOW) {
kernel_features |= KERNEL_FEATURE_SHADOW_PASS;
}
if (pass_type == PASS_SHADOW) {
kernel_features |= KERNEL_FEATURE_SHADOW_PASS;
}
if (pass_type == PASS_AO) {

View File

@@ -63,6 +63,14 @@ NODE_DEFINE(Integrator)
SOCKET_BOOLEAN(caustics_reflective, "Reflective Caustics", true);
SOCKET_BOOLEAN(caustics_refractive, "Refractive Caustics", true);
SOCKET_FLOAT(filter_glossy, "Filter Glossy", 0.0f);
SOCKET_BOOLEAN(use_direct_light, "Use Direct Light", true);
SOCKET_BOOLEAN(use_indirect_light, "Use Indirect Light", true);
SOCKET_BOOLEAN(use_diffuse, "Use Diffuse", true);
SOCKET_BOOLEAN(use_glossy, "Use Glossy", true);
SOCKET_BOOLEAN(use_transmission, "Use Transmission", true);
SOCKET_BOOLEAN(use_emission, "Use Emission", true);
SOCKET_INT(seed, "Seed", 0);
SOCKET_FLOAT(sample_clamp_direct, "Sample Clamp Direct", 0.0f);
SOCKET_FLOAT(sample_clamp_indirect, "Sample Clamp Indirect", 0.0f);
@@ -184,6 +192,27 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
kintegrator->caustics_refractive = caustics_refractive;
kintegrator->filter_glossy = (filter_glossy == 0.0f) ? FLT_MAX : 1.0f / filter_glossy;
kintegrator->filter_closures = 0;
if (!use_direct_light) {
kintegrator->filter_closures |= FILTER_CLOSURE_DIRECT_LIGHT;
}
if (!use_indirect_light) {
kintegrator->min_bounce = 1;
kintegrator->max_bounce = 1;
}
if (!use_diffuse) {
kintegrator->filter_closures |= FILTER_CLOSURE_DIFFUSE;
}
if (!use_glossy) {
kintegrator->filter_closures |= FILTER_CLOSURE_GLOSSY;
}
if (!use_transmission) {
kintegrator->filter_closures |= FILTER_CLOSURE_TRANSMISSION;
}
if (!use_emission) {
kintegrator->filter_closures |= FILTER_CLOSURE_EMISSION;
}
kintegrator->seed = seed;
kintegrator->sample_clamp_direct = (sample_clamp_direct == 0.0f) ? FLT_MAX :

View File

@@ -56,6 +56,13 @@ class Integrator : public Node {
NODE_SOCKET_API(bool, caustics_refractive)
NODE_SOCKET_API(float, filter_glossy)
NODE_SOCKET_API(bool, use_direct_light);
NODE_SOCKET_API(bool, use_indirect_light);
NODE_SOCKET_API(bool, use_diffuse);
NODE_SOCKET_API(bool, use_glossy);
NODE_SOCKET_API(bool, use_transmission);
NODE_SOCKET_API(bool, use_emission);
NODE_SOCKET_API(int, seed)
NODE_SOCKET_API(float, sample_clamp_direct)

View File

@@ -274,19 +274,26 @@ void OSLShaderManager::shading_system_init()
"diffuse_ancestor", /* PATH_RAY_DIFFUSE_ANCESTOR */
"__unused__", /* PATH_RAY_SINGLE_PASS_DONE */
"__unused__", /* PATH_RAY_TRANSPARENT_BACKGROUND */
"__unused__", /* PATH_RAY_TERMINATE_IMMEDIATE */
"__unused__", /* PATH_RAY_TERMINATE_AFTER_TRANSPARENT */
"__unused__", /* PATH_RAY_EMISSION */
"__unused__", /* PATH_RAY_SUBSURFACE */
"__unused__", /* PATH_RAY_DENOISING_FEATURES */
"__unused__", /* PATH_RAY_REFLECT_PASS */
"__unused__", /* PATH_RAY_TRANSMISSION_PASS */
"__unused__", /* PATH_RAY_VOLUME_PASS */
"__unused__", /* PATH_RAY_SHADOW_FOR_LIGHT */
"__unused__", /* PATH_RAY_SHADOW_CATCHER_HIT */
"__unused__", /* PATH_RAY_SHADOW_CATCHER_PASS */
/* Remaining irrelevant bits up to 32. */
"__unused__",
"__unused__",
"__unused__",
"__unused__",
"__unused__",
"__unused__",
"__unused__",
"__unused__",
"__unused__",
"__unused__",
"__unused__",
"__unused__",
"__unused__",
"__unused__",
"__unused__",
"__unused__",
"__unused__",
"__unused__",
"__unused__",
};
const int nraytypes = sizeof(raytypes) / sizeof(raytypes[0]);

View File

@@ -262,6 +262,7 @@ RenderWork Session::run_update_for_next_iteration()
}
render_scheduler_.set_num_samples(params.samples);
render_scheduler_.set_start_sample(params.sample_offset);
render_scheduler_.set_time_limit(params.time_limit);
while (have_tiles) {
@@ -397,7 +398,7 @@ void Session::do_delayed_reset()
/* Tile and work scheduling. */
tile_manager_.reset_scheduling(buffer_params_, get_effective_tile_size());
render_scheduler_.reset(buffer_params_, params.samples);
render_scheduler_.reset(buffer_params_, params.samples, params.sample_offset);
/* Passes. */
/* When multiple tiles are used SAMPLE_COUNT pass is used to keep track of possible partial

View File

@@ -54,6 +54,7 @@ class SessionParams {
bool experimental;
int samples;
int sample_offset;
int pixel_size;
int threads;
@@ -75,6 +76,7 @@ class SessionParams {
experimental = false;
samples = 1024;
sample_offset = 0;
pixel_size = 1;
threads = 0;
time_limit = 0.0;

View File

@@ -29,6 +29,7 @@
#include "util/path.h"
#include "util/string.h"
#include "util/system.h"
#include "util/time.h"
#include "util/types.h"
CCL_NAMESPACE_BEGIN
@@ -503,9 +504,9 @@ bool TileManager::write_tile(const RenderBuffers &tile_buffers)
}
}
DCHECK_EQ(tile_buffers.params.pass_stride, buffer_params_.pass_stride);
const double time_start = time_dt();
vector<float> pixel_storage;
DCHECK_EQ(tile_buffers.params.pass_stride, buffer_params_.pass_stride);
const BufferParams &tile_params = tile_buffers.params;
@@ -515,13 +516,32 @@ bool TileManager::write_tile(const RenderBuffers &tile_buffers)
const int64_t pass_stride = tile_params.pass_stride;
const int64_t tile_row_stride = tile_params.width * pass_stride;
const int64_t xstride = pass_stride * sizeof(float);
const int64_t ystride = xstride * tile_params.width;
const int64_t zstride = ystride * tile_params.height;
vector<float> pixel_storage;
const float *pixels = tile_buffers.buffer.data() + tile_params.window_x * pass_stride +
tile_params.window_y * tile_row_stride;
/* If there is an overscan used for the tile copy pixels into single continuous block of memory
* without any "gaps".
* This is a workaround for bug in OIIO (https://github.com/OpenImageIO/oiio/pull/3176).
* Our task reference: T93008. */
if (tile_params.window_x || tile_params.window_y ||
tile_params.window_width != tile_params.width ||
tile_params.window_height != tile_params.height) {
pixel_storage.resize(pass_stride * tile_params.window_width * tile_params.window_height);
float *pixels_continuous = pixel_storage.data();
const int64_t pixels_row_stride = pass_stride * tile_params.width;
const int64_t pixels_continuous_row_stride = pass_stride * tile_params.window_width;
for (int i = 0; i < tile_params.window_height; ++i) {
memcpy(pixels_continuous, pixels, sizeof(float) * pixels_continuous_row_stride);
pixels += pixels_row_stride;
pixels_continuous += pixels_continuous_row_stride;
}
pixels = pixel_storage.data();
}
VLOG(3) << "Write tile at " << tile_x << ", " << tile_y;
/* The image tile sizes in the OpenEXR file are different from the size of our big tiles. The
@@ -531,6 +551,11 @@ bool TileManager::write_tile(const RenderBuffers &tile_buffers)
*
* The only thing we have to ensure is that the tile_x and tile_y are a multiple of the
* image tile size, which happens in compute_render_tile_size. */
const int64_t xstride = pass_stride * sizeof(float);
const int64_t ystride = xstride * tile_params.window_width;
const int64_t zstride = ystride * tile_params.window_height;
if (!write_state_.tile_out->write_tiles(tile_x,
tile_x + tile_params.window_width,
tile_y,
@@ -548,6 +573,8 @@ bool TileManager::write_tile(const RenderBuffers &tile_buffers)
++write_state_.num_tiles_written;
VLOG(3) << "Tile written in " << time_dt() - time_start << " seconds.";
return true;
}
@@ -589,6 +616,9 @@ void TileManager::finish_write_tiles()
full_buffer_written_cb(write_state_.filename);
}
VLOG(3) << "Tile file size is "
<< string_human_readable_number(path_file_size(write_state_.filename)) << " bytes.";
/* Advance the counter upon explicit finish of the file.
* Makes it possible to re-use tile manager for another scene, and avoids unnecessary increments
* of the tile-file-within-session index. */

View File

@@ -171,4 +171,9 @@ bool Profiler::get_object(int object, uint64_t &samples, uint64_t &hits)
return true;
}
bool Profiler::active() const
{
return (worker != nullptr);
}
CCL_NAMESPACE_END

View File

@@ -96,6 +96,8 @@ class Profiler {
bool get_shader(int shader, uint64_t &samples, uint64_t &hits);
bool get_object(int object, uint64_t &samples, uint64_t &hits);
bool active() const;
protected:
void run();

View File

@@ -728,13 +728,6 @@ extern GHOST_TSuccess GHOST_ReleaseOpenGLContext(GHOST_ContextHandle contexthand
*/
extern unsigned int GHOST_GetContextDefaultOpenGLFramebuffer(GHOST_ContextHandle contexthandle);
/**
* Returns whether a context is rendered upside down compared to OpenGL. This only needs to be
* called if there's a non-OpenGL context, which is really the exception.
* So generally, this does not need to be called.
*/
extern int GHOST_isUpsideDownContext(GHOST_ContextHandle contexthandle);
/**
* Get the OpenGL frame-buffer handle that serves as a default frame-buffer.
*/

View File

@@ -654,8 +654,8 @@ enum {
GHOST_kXrContextDebug = (1 << 0),
GHOST_kXrContextDebugTime = (1 << 1),
# ifdef WIN32
/* Needed to avoid issues with the SteamVR OpenGL graphics binding (use DirectX fallback
instead). */
/* Needed to avoid issues with the SteamVR OpenGL graphics binding
* (use DirectX fallback instead). */
GHOST_kXrContextGpuNVIDIA = (1 << 2),
# endif
};

View File

@@ -1245,7 +1245,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
/* Convert the image in a RGBA 32bit format */
/* As Core Graphics does not support contexts with non premutliplied alpha,
we need to get alpha key values in a separate batch */
* we need to get alpha key values in a separate batch */
/* First get RGB values w/o Alpha to avoid pre-multiplication,
* 32bit but last byte is unused */
@@ -1479,8 +1479,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
CocoaWindow *cocoawindow;
/* [event window] returns other windows if mouse-over, that's OSX input standard
however, if mouse exits window(s), the windows become inactive, until you click.
We then fall back to the active window from ghost */
* however, if mouse exits window(s), the windows become inactive, until you click.
* We then fall back to the active window from ghost. */
window = (GHOST_WindowCocoa *)m_windowManager->getWindowAssociatedWithOSWindow(
(void *)[event window]);
if (!window) {

View File

@@ -216,8 +216,9 @@ GHOST_XrAction::GHOST_XrAction(XrInstance instance,
XrActionCreateInfo action_info{XR_TYPE_ACTION_CREATE_INFO};
strcpy(action_info.actionName, info.name);
strcpy(action_info.localizedActionName, info.name); /* Just use same name for localized. This can
be changed in the future if necessary. */
/* Just use same name for localized. This can be changed in the future if necessary. */
strcpy(action_info.localizedActionName, info.name);
switch (info.type) {
case GHOST_kXrActionTypeBooleanInput:

View File

@@ -97,8 +97,8 @@ static void read_vertices(const tinygltf::Accessor &accessor,
validate_accessor(accessor, buffer_view, buffer, stride, packed_size);
/* Resize the vertices vector, if necessary, to include room for the attribute data.
If there are multiple attributes for a primitive, the first one will resize, and the
subsequent will not need to. */
* If there are multiple attributes for a primitive, the first one will resize, and the
* subsequent will not need to. */
primitive.vertices.resize(accessor.count);
/* Copy the attribute value over from the glTF buffer into the appropriate vertex field. */
@@ -147,9 +147,9 @@ static void read_indices(const tinygltf::Accessor &accessor,
const tinygltf::Buffer &buffer,
GHOST_XrPrimitive &primitive)
{
if (buffer_view.target != TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER &&
buffer_view.target != 0) { /* Allow 0 (not specified) even though spec doesn't seem to allow
this (BoomBox GLB fails). */
/* Allow 0 (not specified) even though spec doesn't seem to allow this (BoomBox GLB fails). */
if (buffer_view.target != TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER && buffer_view.target != 0) {
throw GHOST_XrException(
"glTF: Accessor for indices uses bufferview with invalid 'target' type.");
}
@@ -164,8 +164,8 @@ static void read_indices(const tinygltf::Accessor &accessor,
validate_accessor(accessor, buffer_view, buffer, component_size_bytes, component_size_bytes);
if ((accessor.count % 3) != 0) { /* Since only triangles are supported, enforce that the number
of indices is divisible by 3. */
/* Since only triangles are supported, enforce that the number of indices is divisible by 3. */
if ((accessor.count % 3) != 0) {
throw GHOST_XrException("glTF: Unexpected number of indices for triangle primitive");
}

View File

@@ -1056,17 +1056,17 @@
<ThemeInfo
info_selected="#6080ff"
info_selected_text="#000000"
info_error="#FF0038ff"
info_error="#ff0038ff"
info_error_text="#000000"
info_warning="#FFE900ff"
info_warning="#ffe900ff"
info_warning_text="#000000"
info_info="#0068B3ff"
info_info="#0068b3ff"
info_info_text="#000000"
info_debug="#B30095ff"
info_debug="#b30095ff"
info_debug_text="#000000"
info_property="#44B300ff"
info_property="#44b300ff"
info_property_text="#000000"
info_operator="#44B300ff"
info_operator="#44b300ff"
info_operator_text="#000000"
>
<space>
@@ -1352,6 +1352,15 @@
</panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
<ThemeSpaceListGeneric
list="#adadad"
list_title="#c3c3c3"
list_text="#c3c3c3"
list_text_hi="#00ffff"
>
</ThemeSpaceListGeneric>
</space_list>
</ThemeSpreadsheet>
</spreadsheet>
<bone_color_sets>
@@ -1530,6 +1539,44 @@
>
</ThemeCollectionColor>
</collection_color>
<strip_color>
<ThemeStripColor
color="#e2605b"
>
</ThemeStripColor>
<ThemeStripColor
color="#f1a355"
>
</ThemeStripColor>
<ThemeStripColor
color="#f1dc55"
>
</ThemeStripColor>
<ThemeStripColor
color="#7bcc7b"
>
</ThemeStripColor>
<ThemeStripColor
color="#5db6ea"
>
</ThemeStripColor>
<ThemeStripColor
color="#8d59da"
>
</ThemeStripColor>
<ThemeStripColor
color="#c673b8"
>
</ThemeStripColor>
<ThemeStripColor
color="#7a5441"
>
</ThemeStripColor>
<ThemeStripColor
color="#5f5f5f"
>
</ThemeStripColor>
</strip_color>
</Theme>
<ThemeStyle>
<panel_title>

View File

@@ -1097,6 +1097,7 @@ def km_outliner(params):
# Fall through to generic context menu if the item(s) selected have no type specific actions.
("outliner.operation", {"type": 'RIGHTMOUSE', "value": 'PRESS'}, None),
op_menu("OUTLINER_MT_context_menu", {"type": 'RIGHTMOUSE', "value": 'PRESS'}),
op_menu_pie("OUTLINER_MT_view_pie", {"type": 'ACCENT_GRAVE', "value": 'PRESS'}),
("outliner.item_drag_drop", {"type": 'EVT_TWEAK_L', "value": 'ANY'}, None),
("outliner.item_drag_drop", {"type": 'EVT_TWEAK_L', "value": 'ANY', "shift": True}, None),
("outliner.show_hierarchy", {"type": 'HOME', "value": 'PRESS'}, None),
@@ -1748,6 +1749,7 @@ def km_graph_editor(params):
("graph.view_all", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'}, None),
("graph.view_selected", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None),
("graph.view_frame", {"type": 'NUMPAD_0', "value": 'PRESS'}, None),
op_menu_pie("GRAPH_MT_view_pie", {"type": 'ACCENT_GRAVE', "value": 'PRESS'}),
("graph.fmodifier_add", {"type": 'M', "value": 'PRESS', "shift": True, "ctrl": True},
{"properties": [("only_active", False)]}),
("anim.channels_editable_toggle", {"type": 'TAB', "value": 'PRESS'}, None),
@@ -1815,6 +1817,7 @@ def km_image_generic(params):
("image.cycle_render_slot", {"type": 'J', "value": 'PRESS', "repeat": True}, None),
("image.cycle_render_slot", {"type": 'J', "value": 'PRESS', "alt": True, "repeat": True},
{"properties": [("reverse", True)]}),
op_menu_pie("IMAGE_MT_view_pie", {"type": 'ACCENT_GRAVE', "value": 'PRESS'}),
])
if not params.legacy:
@@ -2027,6 +2030,7 @@ def km_node_editor(params):
("node.view_all", {"type": 'HOME', "value": 'PRESS'}, None),
("node.view_all", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'}, None),
("node.view_selected", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None),
op_menu_pie("NODE_MT_view_pie", {"type": 'ACCENT_GRAVE', "value": 'PRESS'}),
("node.delete", {"type": 'X', "value": 'PRESS'}, None),
("node.delete", {"type": 'DEL', "value": 'PRESS'}, None),
("node.delete_reconnect", {"type": 'X', "value": 'PRESS', "ctrl": True}, None),
@@ -2389,6 +2393,7 @@ def km_dopesheet(params):
("action.view_all", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'}, None),
("action.view_selected", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None),
("action.view_frame", {"type": 'NUMPAD_0', "value": 'PRESS'}, None),
op_menu_pie("DOPESHEET_MT_view_pie", {"type": 'ACCENT_GRAVE', "value": 'PRESS'}),
("anim.channels_editable_toggle", {"type": 'TAB', "value": 'PRESS'}, None),
("anim.channels_select_filter", {"type": 'F', "value": 'PRESS', "ctrl": True}, None),
("transform.transform", {"type": 'G', "value": 'PRESS'},
@@ -2503,6 +2508,7 @@ def km_nla_editor(params):
("nla.view_all", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'}, None),
("nla.view_selected", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None),
("nla.view_frame", {"type": 'NUMPAD_0', "value": 'PRESS'}, None),
op_menu_pie("NLA_MT_view_pie", {"type": 'ACCENT_GRAVE', "value": 'PRESS'}),
("nla.actionclip_add", {"type": 'A', "value": 'PRESS', "shift": True}, None),
("nla.transition_add", {"type": 'T', "value": 'PRESS', "shift": True}, None),
("nla.soundclip_add", {"type": 'K', "value": 'PRESS', "shift": True}, None),
@@ -2835,6 +2841,7 @@ def km_sequencer(params):
("sequencer.select_grouped", {"type": 'G', "value": 'PRESS', "shift": True}, None),
op_menu("SEQUENCER_MT_add", {"type": 'A', "value": 'PRESS', "shift": True}),
op_menu("SEQUENCER_MT_change", {"type": 'C', "value": 'PRESS'}),
op_menu_pie("SEQUENCER_MT_view_pie", {"type": 'ACCENT_GRAVE', "value": 'PRESS'}),
("sequencer.slip", {"type": 'S', "value": 'PRESS'}, None),
("wm.context_set_int", {"type": 'O', "value": 'PRESS'},
{"properties": [("data_path", 'scene.sequence_editor.overlay_frame'), ("value", 0)]}),
@@ -2892,6 +2899,7 @@ def km_sequencerpreview(params):
{"properties": [("ratio", 0.25)]}),
("sequencer.view_zoom_ratio", {"type": 'NUMPAD_8', "value": 'PRESS'},
{"properties": [("ratio", 0.125)]}),
op_menu_pie("SEQUENCER_MT_preview_view_pie", {"type": 'ACCENT_GRAVE', "value": 'PRESS'}),
# Edit.
("transform.translate", {"type": params.select_tweak, "value": 'ANY'}, None),
@@ -3042,6 +3050,7 @@ def km_clip(_params):
op_menu_pie("CLIP_MT_solving_pie", {"type": 'S', "value": 'PRESS', "shift": True}),
op_menu_pie("CLIP_MT_marker_pie", {"type": 'E', "value": 'PRESS', "shift": True}),
op_menu_pie("CLIP_MT_reconstruction_pie", {"type": 'W', "value": 'PRESS', "shift": True}),
op_menu_pie("CLIP_MT_view_pie", {"type": 'ACCENT_GRAVE', "value": 'PRESS'}),
])
return keymap

View File

@@ -1858,6 +1858,43 @@ class CLIP_MT_reconstruction_pie(Menu):
pie.operator("clip.apply_solution_scale", icon='ARROW_LEFTRIGHT')
class CLIP_MT_view_pie(Menu):
bl_label = "View"
@classmethod
def poll(cls, context):
space = context.space_data
# View operators are not yet implemented in Dopesheet mode.
return space.view != 'DOPESHEET'
def draw(self, context):
layout = self.layout
sc = context.space_data
pie = layout.menu_pie()
if sc.view == 'CLIP':
pie.operator("clip.view_all")
pie.operator("clip.view_selected", icon='ZOOM_SELECTED')
if sc.mode == 'MASK':
pie.operator("clip.view_center_cursor")
pie.separator()
else:
# Add spaces so items stay in the same position through all modes.
pie.separator()
pie.separator()
pie.operator("clip.view_all", text="Frame All Fit").fit_view = True
if sc.view == 'GRAPH':
pie.operator_context = 'INVOKE_REGION_PREVIEW'
pie.operator("clip.graph_view_all")
pie.separator()
pie.operator("clip.graph_center_current_frame")
classes = (
CLIP_UL_tracking_objects,
CLIP_HT_header,
@@ -1925,6 +1962,7 @@ classes = (
CLIP_MT_tracking_pie,
CLIP_MT_reconstruction_pie,
CLIP_MT_solving_pie,
CLIP_MT_view_pie,
)
if __name__ == "__main__": # only for live edit.

View File

@@ -379,6 +379,18 @@ class DOPESHEET_MT_view(Menu):
layout.menu("INFO_MT_area")
class DOPESHEET_MT_view_pie(Menu):
bl_label = "View"
def draw(self, context):
layout = self.layout
pie = layout.menu_pie()
pie.operator("action.view_all")
pie.operator("action.view_selected", icon='ZOOM_SELECTED')
pie.operator("action.view_frame")
class DOPESHEET_MT_select(Menu):
bl_label = "Select"
@@ -778,6 +790,7 @@ classes = (
DOPESHEET_MT_context_menu,
DOPESHEET_MT_channel_context_menu,
DOPESHEET_MT_snap_pie,
DOPESHEET_MT_view_pie,
DOPESHEET_PT_filters,
DOPESHEET_PT_gpencil_mode,
DOPESHEET_PT_gpencil_layer_masks,

View File

@@ -338,6 +338,18 @@ class GRAPH_MT_key_snap(Menu):
layout.operator("graph.snap_cursor_value", text="Cursor Value to Selection")
class GRAPH_MT_view_pie(Menu):
bl_label = "View"
def draw(self, context):
layout = self.layout
pie = layout.menu_pie()
pie.operator("graph.view_all")
pie.operator("graph.view_selected", icon='ZOOM_SELECTED')
pie.operator("graph.view_frame")
class GRAPH_MT_delete(Menu):
bl_label = "Delete"
@@ -468,6 +480,7 @@ classes = (
GRAPH_MT_channel_context_menu,
GRAPH_MT_pivot_pie,
GRAPH_MT_snap_pie,
GRAPH_MT_view_pie,
GRAPH_PT_filters,
)

View File

@@ -591,6 +591,31 @@ class IMAGE_MT_uvs_snap_pie(Menu):
).target = 'ADJACENT_UNSELECTED'
class IMAGE_MT_view_pie(Menu):
bl_label = "View"
def draw(self, context):
layout = self.layout
sima = context.space_data
show_uvedit = sima.show_uvedit
show_maskedit = sima.show_maskedit
pie = layout.menu_pie()
pie.operator("image.view_all")
if show_uvedit or show_maskedit:
pie.operator("image.view_selected", text="Frame Selected", icon='ZOOM_SELECTED')
pie.operator("image.view_center_cursor", text="Center View to Cursor")
else:
# Add spaces so items stay in the same position through all modes.
pie.separator()
pie.separator()
pie.operator("image.view_zoom_ratio", text="Zoom 1:1").ratio = 1
pie.operator("image.view_all", text="Frame All Fit").fit_view = True
class IMAGE_HT_tool_header(Header):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'TOOL_HEADER'
@@ -1633,6 +1658,7 @@ classes = (
IMAGE_MT_mask_context_menu,
IMAGE_MT_pivot_pie,
IMAGE_MT_uvs_snap_pie,
IMAGE_MT_view_pie,
IMAGE_HT_tool_header,
IMAGE_HT_header,
IMAGE_MT_editor_menus,

View File

@@ -247,6 +247,18 @@ class NLA_MT_snap_pie(Menu):
pie.operator("nla.snap", text="Selection to Nearest Marker").type = 'NEAREST_MARKER'
class NLA_MT_view_pie(Menu):
bl_label = "View"
def draw(self, context):
layout = self.layout
pie = layout.menu_pie()
pie.operator("nla.view_all")
pie.operator("nla.view_selected", icon='ZOOM_SELECTED')
pie.operator("nla.view_frame")
class NLA_MT_context_menu(Menu):
bl_label = "NLA Context Menu"
@@ -300,6 +312,7 @@ classes = (
NLA_MT_add,
NLA_MT_edit_transform,
NLA_MT_snap_pie,
NLA_MT_view_pie,
NLA_MT_context_menu,
NLA_MT_channel_context_menu,
NLA_PT_filters,

View File

@@ -367,6 +367,17 @@ class NODE_MT_node(Menu):
layout.operator("node.read_viewlayers")
class NODE_MT_view_pie(Menu):
bl_label = "View"
def draw(self, context):
layout = self.layout
pie = layout.menu_pie()
pie.operator("node.view_all")
pie.operator("node.view_selected", icon='ZOOM_SELECTED')
class NODE_PT_active_tool(ToolActivePanelHelper, Panel):
bl_space_type = 'NODE_EDITOR'
bl_region_type = 'UI'
@@ -877,6 +888,7 @@ classes = (
NODE_MT_node,
NODE_MT_node_color_context_menu,
NODE_MT_context_menu,
NODE_MT_view_pie,
NODE_PT_material_slots,
NODE_PT_node_color_presets,
NODE_PT_active_node_generic,

View File

@@ -142,6 +142,17 @@ class OUTLINER_MT_context_menu_view(Menu):
layout.operator("outliner.show_one_level", text="Hide One Level").open = False
class OUTLINER_MT_view_pie(Menu):
bl_label = "View"
def draw(self, context):
layout = self.layout
pie = layout.menu_pie()
pie.operator("outliner.show_hierarchy")
pie.operator("outliner.show_active", icon='ZOOM_SELECTED')
class OUTLINER_MT_edit_datablocks(Menu):
bl_label = "Edit"
@@ -471,6 +482,7 @@ classes = (
OUTLINER_MT_asset,
OUTLINER_MT_context_menu,
OUTLINER_MT_context_menu_view,
OUTLINER_MT_view_pie,
OUTLINER_PT_filter,
)

View File

@@ -1173,6 +1173,31 @@ class SEQUENCER_MT_pivot_pie(Menu):
pie.prop_enum(sequencer_tool_settings, "pivot_point", value='MEDIAN')
class SEQUENCER_MT_view_pie(Menu):
bl_label = "View"
def draw(self, context):
layout = self.layout
pie = layout.menu_pie()
pie.operator("sequencer.view_all")
pie.operator("sequencer.view_selected", text="Frame Selected", icon='ZOOM_SELECTED')
class SEQUENCER_MT_preview_view_pie(Menu):
bl_label = "View"
def draw(self, context):
layout = self.layout
pie = layout.menu_pie()
pie.operator_context = 'INVOKE_REGION_PREVIEW'
pie.operator("sequencer.view_all_preview")
pie.operator("sequencer.view_selected", text="Frame Selected", icon='ZOOM_SELECTED')
pie.separator()
pie.operator("sequencer.view_zoom_ratio", text="Zoom 1:1").ratio = 1
class SequencerButtonsPanel:
bl_space_type = 'SEQUENCE_EDITOR'
bl_region_type = 'UI'
@@ -2615,6 +2640,8 @@ classes = (
SEQUENCER_MT_context_menu,
SEQUENCER_MT_preview_context_menu,
SEQUENCER_MT_pivot_pie,
SEQUENCER_MT_view_pie,
SEQUENCER_MT_preview_view_pie,
SEQUENCER_PT_color_tag_picker,

View File

@@ -477,6 +477,16 @@ class USERPREF_PT_edit_weight_paint(EditingPanel, CenterAlignMixIn, Panel):
col.active = view.use_weight_color_range
col.template_color_ramp(view, "weight_color_range", expand=True)
class USERPREF_PT_edit_text_editor(EditingPanel, CenterAlignMixIn, Panel):
bl_label = "Text Editor"
bl_options = {'DEFAULT_CLOSED'}
def draw_centered(self, context, layout):
prefs = context.preferences
edit = prefs.edit
layout.prop(edit, "use_text_edit_auto_close")
class USERPREF_PT_edit_misc(EditingPanel, CenterAlignMixIn, Panel):
bl_label = "Miscellaneous"
@@ -2357,6 +2367,7 @@ classes = (
USERPREF_PT_edit_annotations,
USERPREF_PT_edit_weight_paint,
USERPREF_PT_edit_gpencil,
USERPREF_PT_edit_text_editor,
USERPREF_PT_edit_misc,
USERPREF_PT_animation_timeline,

View File

@@ -754,6 +754,7 @@ geometry_node_categories = [
NodeItem("GeometryNodeSwitch"),
NodeItem("FunctionNodeRandomValue"),
NodeItem("FunctionNodeAlignEulerToVector"),
NodeItem("GeometryNodeSampleSound"),
]),
GeometryNodeCategory("GEO_VECTOR", "Vector", items=[
NodeItem("ShaderNodeVectorCurve"),

View File

@@ -65,7 +65,7 @@ void BLF_metrics_attach(int fontid, unsigned char *mem, int mem_size);
void BLF_aspect(int fontid, float x, float y, float z);
void BLF_position(int fontid, float x, float y, float z);
void BLF_size(int fontid, int size, int dpi);
void BLF_size(int fontid, float size, int dpi);
/* goal: small but useful color API */
void BLF_color4ubv(int fontid, const unsigned char rgba[4]);

View File

@@ -363,7 +363,7 @@ void BLF_position(int fontid, float x, float y, float z)
}
}
void BLF_size(int fontid, int size, int dpi)
void BLF_size(int fontid, float size, int dpi)
{
FontBLF *font = blf_get(fontid);
@@ -910,7 +910,7 @@ void BLF_state_print(int fontid)
if (font) {
printf("fontid %d %p\n", fontid, (void *)font);
printf(" name: '%s'\n", font->name);
printf(" size: %u\n", font->size);
printf(" size: %f\n", font->size);
printf(" dpi: %u\n", font->dpi);
printf(" pos: %.6f %.6f %.6f\n", UNPACK3(font->pos));
printf(" aspect: (%d) %.6f %.6f %.6f\n",

View File

@@ -1350,19 +1350,24 @@ void blf_font_free(FontBLF *font)
/** \name Font Configure
* \{ */
void blf_font_size(FontBLF *font, unsigned int size, unsigned int dpi)
void blf_font_size(FontBLF *font, float size, unsigned int dpi)
{
blf_glyph_cache_acquire(font);
/* FreeType uses fixed-point integers in 64ths. */
FT_F26Dot6 ft_size = lroundf(size * 64.0f);
/* Adjust our size to be on even 64ths. */
size = (float)ft_size / 64.0f;
GlyphCacheBLF *gc = blf_glyph_cache_find(font, size, dpi);
if (gc && (font->size == size && font->dpi == dpi)) {
/* Optimization: do not call FT_Set_Char_Size if size did not change. */
}
else {
const FT_Error err = FT_Set_Char_Size(font->face, 0, ((FT_F26Dot6)(size)) * 64, dpi, dpi);
const FT_Error err = FT_Set_Char_Size(font->face, 0, ft_size, dpi, dpi);
if (err) {
/* FIXME: here we can go through the fixed size and choice a close one */
printf("The current font don't support the size, %u and dpi, %u\n", size, dpi);
printf("The current font don't support the size, %f and dpi, %u\n", size, dpi);
}
else {
font->size = size;

View File

@@ -76,7 +76,7 @@ static FT_Fixed to_16dot16(double val)
/**
* Find a glyph cache that matches a size, DPI & styles.
*/
GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font, unsigned int size, unsigned int dpi)
GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font, float size, unsigned int dpi)
{
GlyphCacheBLF *gc = (GlyphCacheBLF *)font->cache.first;
while (gc) {

View File

@@ -52,7 +52,7 @@ struct FontBLF *blf_font_new(const char *name, const char *filename);
struct FontBLF *blf_font_new_from_mem(const char *name, const unsigned char *mem, int mem_size);
void blf_font_attach_from_mem(struct FontBLF *font, const unsigned char *mem, int mem_size);
void blf_font_size(struct FontBLF *font, unsigned int size, unsigned int dpi);
void blf_font_size(struct FontBLF *font, float size, unsigned int dpi);
void blf_font_draw(struct FontBLF *font,
const char *str,
size_t str_len,
@@ -130,9 +130,7 @@ int blf_font_count_missing_chars(struct FontBLF *font,
void blf_font_free(struct FontBLF *font);
struct GlyphCacheBLF *blf_glyph_cache_find(struct FontBLF *font,
unsigned int size,
unsigned int dpi);
struct GlyphCacheBLF *blf_glyph_cache_find(struct FontBLF *font, float size, unsigned int dpi);
struct GlyphCacheBLF *blf_glyph_cache_new(struct FontBLF *font);
struct GlyphCacheBLF *blf_glyph_cache_acquire(struct FontBLF *font);
void blf_glyph_cache_release(struct FontBLF *font);

View File

@@ -65,7 +65,7 @@ typedef struct GlyphCacheBLF {
struct GlyphCacheBLF *prev;
/* font size. */
unsigned int size;
float size;
/* and dpi. */
unsigned int dpi;
@@ -205,7 +205,7 @@ typedef struct FontBLF {
unsigned int dpi;
/* font size. */
unsigned int size;
float size;
/* Column width when printing monospaced. */
int fixed_width;

View File

@@ -95,7 +95,7 @@ void BLF_thumb_preview(const char *filename,
const size_t draw_str_i18n_len = strlen(draw_str_i18n);
int draw_str_i18n_nbr = 0;
blf_font_size(font, (unsigned int)MAX2(font_size_min, font_size_curr), dpi);
blf_font_size(font, (float)MAX2(font_size_min, font_size_curr), dpi);
gc = blf_glyph_cache_find(font, font->size, font->dpi);
/* There will be no matching glyph cache if blf_font_size() failed to set font size. */
if (!gc) {

View File

@@ -125,6 +125,17 @@ struct bActionGroup *BKE_action_group_find_name(struct bAction *act, const char
/* Clear all 'temp' flags on all groups */
void action_groups_clear_tempflags(struct bAction *act);
/**
* Return whether the action has one unique point in time keyed.
*
* This is mostly for the pose library, which will have different behavior depending on whether an
* Action corresponds to a "pose" (one keyframe) or "animation snippet" (multiple keyframes).
*
* \return `false` when there is no keyframe at all or keys on different points in time, `true`
* when exactly one point in time is keyed.
*/
bool BKE_action_has_single_frame(const struct bAction *act);
/* Pose API ----------------- */
void BKE_pose_channel_free(struct bPoseChannel *pchan);

View File

@@ -31,16 +31,18 @@ struct ReportList;
struct bContext;
/* copybuffer (wrapper for BKE_blendfile_write_partial) */
void BKE_copybuffer_begin(struct Main *bmain_src);
void BKE_copybuffer_tag_ID(struct ID *id);
bool BKE_copybuffer_save(struct Main *bmain_src, const char *filename, struct ReportList *reports);
void BKE_copybuffer_copy_begin(struct Main *bmain_src);
void BKE_copybuffer_copy_tag_ID(struct ID *id);
bool BKE_copybuffer_copy_end(struct Main *bmain_src,
const char *filename,
struct ReportList *reports);
bool BKE_copybuffer_read(struct Main *bmain_dst,
const char *libname,
struct ReportList *reports,
const uint64_t id_types_mask);
int BKE_copybuffer_paste(struct bContext *C,
const char *libname,
const short flag,
const int flag,
struct ReportList *reports,
const uint64_t id_types_mask);

View File

@@ -45,7 +45,6 @@ typedef struct Global {
/** When set: `G_MAIN->name` contains valid relative base path. */
bool relbase_valid;
bool file_loaded;
bool save_over;
/** Strings of recent opened files. */

View File

@@ -134,8 +134,10 @@ enum {
LIB_ID_COPY_SHAPEKEY = 1 << 26,
/** EXCEPTION! Specific deep-copy of node trees used e.g. for rendering purposes. */
LIB_ID_COPY_NODETREE_LOCALIZE = 1 << 27,
/** EXCEPTION! Specific handling of RB objects regarding collections differs depending whether we
duplicate scene/collections, or objects. */
/**
* EXCEPTION! Specific handling of RB objects regarding collections differs depending whether we
* duplicate scene/collections, or objects.
*/
LIB_ID_COPY_RIGID_BODY_NO_COLLECTION_HANDLING = 1 << 28,
/* *** Helper 'defines' gathering most common flag sets. *** */

View File

@@ -1553,6 +1553,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
#define GEO_NODE_VOLUME_TO_MESH 1133
#define GEO_NODE_INPUT_ID 1134
#define GEO_NODE_SET_ID 1135
#define GEO_NODE_SAMPLE_SOUND 1136
/** \} */

View File

@@ -306,11 +306,23 @@ class BezierSpline final : public Spline {
blender::Span<HandleType> handle_types_left() const;
blender::MutableSpan<HandleType> handle_types_left();
blender::Span<blender::float3> handle_positions_left() const;
blender::MutableSpan<blender::float3> handle_positions_left();
/**
* Get writable access to the handle position.
*
* \param write_only: pass true for an uninitialized spline, this prevents accessing
* uninitialized memory while auto-generating handles.
*/
blender::MutableSpan<blender::float3> handle_positions_left(bool write_only = false);
blender::Span<HandleType> handle_types_right() const;
blender::MutableSpan<HandleType> handle_types_right();
blender::Span<blender::float3> handle_positions_right() const;
blender::MutableSpan<blender::float3> handle_positions_right();
/**
* Get writable access to the handle position.
*
* \param write_only: pass true for an uninitialized spline, this prevents accessing
* uninitialized memory while auto-generating handles.
*/
blender::MutableSpan<blender::float3> handle_positions_right(bool write_only = false);
void ensure_auto_handles() const;
void translate(const blender::float3 &translation) override;

View File

@@ -51,6 +51,7 @@
#include "BKE_anim_visualization.h"
#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_asset.h"
#include "BKE_constraint.h"
#include "BKE_deform.h"
#include "BKE_fcurve.h"
@@ -286,6 +287,30 @@ static void action_blend_read_expand(BlendExpander *expander, ID *id)
}
}
static IDProperty *action_asset_type_property(const bAction *action)
{
const bool is_single_frame = !BKE_action_has_single_frame(action);
IDPropertyTemplate idprop = {0};
idprop.i = is_single_frame;
IDProperty *property = IDP_New(IDP_INT, &idprop, "is_single_frame");
return property;
}
static void action_asset_pre_save(void *asset_ptr, struct AssetMetaData *asset_data)
{
bAction *action = (bAction *)asset_ptr;
BLI_assert(GS(action->id.name) == ID_AC);
IDProperty *action_type = action_asset_type_property(action);
BKE_asset_metadata_idprop_ensure(asset_data, action_type);
}
AssetTypeInfo AssetType_AC = {
/* pre_save_fn */ action_asset_pre_save,
};
IDTypeInfo IDType_ID_AC = {
.id_code = ID_AC,
.id_filter = FILTER_ID_AC,
@@ -312,6 +337,8 @@ IDTypeInfo IDType_ID_AC = {
.blend_read_undo_preserve = NULL,
.lib_override_apply_post = NULL,
.asset_type_info = &AssetType_AC,
};
/* ***************** Library data level operations on action ************** */
@@ -1418,6 +1445,47 @@ bool action_has_motion(const bAction *act)
return false;
}
bool BKE_action_has_single_frame(const struct bAction *act)
{
if (act == NULL || BLI_listbase_is_empty(&act->curves)) {
return false;
}
bool found_key = false;
float found_key_frame = 0.0f;
LISTBASE_FOREACH (FCurve *, fcu, &act->curves) {
switch (fcu->totvert) {
case 0:
/* No keys, so impossible to come to a conclusion on this curve alone. */
continue;
case 1:
/* Single key, which is the complex case, so handle below. */
break;
default:
/* Multiple keys, so there is animation. */
return false;
}
const float this_key_frame = fcu->bezt != NULL ? fcu->bezt[0].vec[1][0] : fcu->fpt[0].vec[0];
if (!found_key) {
found_key = true;
found_key_frame = this_key_frame;
continue;
}
/* The graph editor rounds to 1/1000th of a frame, so it's not necessary to be really precise
* with these comparisons. */
if (!compare_ff(found_key_frame, this_key_frame, 0.001f)) {
/* This key differs from the already-found key, so this Action represents animation. */
return false;
}
}
/* There is only a single frame if we found at least one key. */
return found_key;
}
/* Calculate the extents of given action */
void calc_action_range(const bAction *act, float *start, float *end, short incl_modifiers)
{

View File

@@ -24,6 +24,8 @@
#include "BLI_listbase.h"
#include "MEM_guardedalloc.h"
#include "testing/testing.h"
namespace blender::bke::tests {
@@ -141,4 +143,97 @@ TEST(action_groups, ReconstructGroupsWithReordering)
EXPECT_EQ(groupDcurve2.next, nullptr);
}
namespace {
/* Allocate fcu->bezt, and also return a unique_ptr to it for easily freeing the memory. */
std::unique_ptr<BezTriple[]> allocate_keyframes(FCurve *fcu, const size_t num_keyframes)
{
auto bezt_uptr = std::make_unique<BezTriple[]>(num_keyframes);
fcu->bezt = bezt_uptr.get();
return bezt_uptr;
}
/* Append keyframe, assumes that fcu->bezt is allocated and has enough space. */
void add_keyframe(FCurve *fcu, float x, float y)
{
/* The insert_keyframe functions are in the editors, so we cannot link to those here. */
BezTriple the_keyframe;
memset(&the_keyframe, 0, sizeof(the_keyframe));
/* Copied from insert_vert_fcurve() in keyframing.c. */
the_keyframe.vec[0][0] = x - 1.0f;
the_keyframe.vec[0][1] = y;
the_keyframe.vec[1][0] = x;
the_keyframe.vec[1][1] = y;
the_keyframe.vec[2][0] = x + 1.0f;
the_keyframe.vec[2][1] = y;
memcpy(&fcu->bezt[fcu->totvert], &the_keyframe, sizeof(the_keyframe));
fcu->totvert++;
}
} // namespace
TEST(action_assets, BKE_action_has_single_frame)
{
/* NULL action. */
EXPECT_FALSE(BKE_action_has_single_frame(nullptr)) << "NULL Action cannot have a single frame.";
/* No FCurves. */
{
const bAction empty = {nullptr};
EXPECT_FALSE(BKE_action_has_single_frame(&empty))
<< "Action without FCurves cannot have a single frame.";
}
/* One curve with one key. */
{
FCurve fcu = {nullptr};
std::unique_ptr<BezTriple[]> bezt = allocate_keyframes(&fcu, 1);
add_keyframe(&fcu, 1.0f, 2.0f);
bAction action = {nullptr};
BLI_addtail(&action.curves, &fcu);
EXPECT_TRUE(BKE_action_has_single_frame(&action))
<< "Action with one FCurve and one key should have single frame.";
}
/* Two curves with one key each. */
{
FCurve fcu1 = {nullptr};
FCurve fcu2 = {nullptr};
std::unique_ptr<BezTriple[]> bezt1 = allocate_keyframes(&fcu1, 1);
std::unique_ptr<BezTriple[]> bezt2 = allocate_keyframes(&fcu2, 1);
add_keyframe(&fcu1, 1.0f, 327.0f);
add_keyframe(&fcu2, 1.0f, 47.0f); /* Same X-coordinate as the other one. */
bAction action = {nullptr};
BLI_addtail(&action.curves, &fcu1);
BLI_addtail(&action.curves, &fcu2);
EXPECT_TRUE(BKE_action_has_single_frame(&action))
<< "Two FCurves with keys on the same frame should have single frame.";
/* Modify the 2nd curve so it's keyed on a different frame. */
fcu2.bezt[0].vec[1][0] = 2.0f;
EXPECT_FALSE(BKE_action_has_single_frame(&action))
<< "Two FCurves with keys on different frames should have animation.";
}
/* One curve with two keys. */
{
FCurve fcu = {nullptr};
std::unique_ptr<BezTriple[]> bezt = allocate_keyframes(&fcu, 2);
add_keyframe(&fcu, 1.0f, 2.0f);
add_keyframe(&fcu, 2.0f, 2.5f);
bAction action = {nullptr};
BLI_addtail(&action.curves, &fcu);
EXPECT_FALSE(BKE_action_has_single_frame(&action))
<< "Action with one FCurve and two keys must have animation.";
}
}
} // namespace blender::bke::tests

View File

@@ -57,20 +57,26 @@
/** \name Copy/Paste `.blend`, partial saves.
* \{ */
void BKE_copybuffer_begin(Main *bmain_src)
/** Initialize a copy operation. */
void BKE_copybuffer_copy_begin(Main *bmain_src)
{
BKE_blendfile_write_partial_begin(bmain_src);
}
void BKE_copybuffer_tag_ID(ID *id)
/** Mark an ID to be copied. Should only be called after a call to #BKE_copybuffer_copy_begin. */
void BKE_copybuffer_copy_tag_ID(ID *id)
{
BKE_blendfile_write_partial_tag_ID(id, true);
}
/**
* \return Success.
* Finalize a copy operation into given .blend file 'buffer'.
*
* \param filename: Full path to the .blend file used as copy/paste buffer.
*
* \return true on success, false otherwise.
*/
bool BKE_copybuffer_save(Main *bmain_src, const char *filename, ReportList *reports)
bool BKE_copybuffer_copy_end(Main *bmain_src, const char *filename, ReportList *reports)
{
const int write_flags = 0;
const eBLO_WritePathRemap remap_mode = BLO_WRITE_PATH_REMAP_RELATIVE;
@@ -82,6 +88,16 @@ bool BKE_copybuffer_save(Main *bmain_src, const char *filename, ReportList *repo
return retval;
}
/**
* Paste datablocks from the given .blend file 'buffer' (i.e. append them).
*
* Unlike #BKE_copybuffer_paste, it does not perform any instantiation of collections/objects/etc.
*
* \param libname: Full path to the .blend file used as copy/paste buffer.
* \param id_types_mask: Only directly link IDs of those types from the given .blend file buffer.
*
* \return true on success, false otherwise.
*/
bool BKE_copybuffer_read(Main *bmain_dst,
const char *libname,
ReportList *reports,
@@ -116,12 +132,22 @@ bool BKE_copybuffer_read(Main *bmain_dst,
}
/**
* \return Number of IDs directly pasted from the buffer
* (does not includes indirectly pulled out ones).
* Paste datablocks from the given .blend file 'buffer' (i.e. append them).
*
* Similar to #BKE_copybuffer_read, but also handles instantiation of collections/objects/etc.
*
* \param libname: Full path to the .blend file used as copy/paste buffer.
* \param flag: A combination of #eBLOLibLinkFlags and ##eFileSel_Params_Flag to control
* link/append behavior.
* \note: Ignores #FILE_LINK flag, since it always appends IDs.
* \param id_types_mask: Only directly link IDs of those types from the given .blend file buffer.
*
* \return Number of IDs directly pasted from the buffer (does not includes indirectly linked
* ones).
*/
int BKE_copybuffer_paste(bContext *C,
const char *libname,
const short flag,
const int flag,
ReportList *reports,
const uint64_t id_types_mask)
{

View File

@@ -225,8 +225,8 @@ static SplinePtr spline_from_dna_bezier(const Nurb &nurb)
Span<const BezTriple> src_points{nurb.bezt, nurb.pntsu};
spline->resize(src_points.size());
MutableSpan<float3> positions = spline->positions();
MutableSpan<float3> handle_positions_left = spline->handle_positions_left();
MutableSpan<float3> handle_positions_right = spline->handle_positions_right();
MutableSpan<float3> handle_positions_left = spline->handle_positions_left(true);
MutableSpan<float3> handle_positions_right = spline->handle_positions_right(true);
MutableSpan<BezierSpline::HandleType> handle_types_left = spline->handle_types_left();
MutableSpan<BezierSpline::HandleType> handle_types_right = spline->handle_types_right();
MutableSpan<float> radii = spline->radii();

View File

@@ -422,7 +422,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
}
}
else {
/* Convert to worldspace. */
/* Convert to world-space. */
copy_v3_v3(tmp_loc, pchan->pose_head);
mul_m4_v3(ob->obmat, tmp_loc);
}

View File

@@ -369,7 +369,7 @@ static void checker_board_text(
char text[3] = {'A', '1', '\0'};
const int mono = blf_mono_font_render;
BLF_size(mono, 54, 72); /* hard coded size! */
BLF_size(mono, 54.0f, 72); /* hard coded size! */
/* OCIO_TODO: using NULL as display will assume using sRGB display
* this is correct since currently generated images are assumed to be in sRGB space,

View File

@@ -260,10 +260,16 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
mul_m4_v3(mtx, mv->co);
if (do_vtargetmap) {
/* compare location of the original and mirrored vertex, to see if they
* should be mapped for merging */
/* Compare location of the original and mirrored vertex,
* to see if they should be mapped for merging.
*
* Always merge from the copied into the original vertices so it's possible to
* generate a 1:1 mapping by scanning vertices from the beginning of the array
* as is done in #BKE_editmesh_vert_coords_when_deformed. Without this,
* the coordinates returned will sometimes point to the copied vertex locations, see: T91444.
*/
if (UNLIKELY(len_squared_v3v3(mv_prev->co, mv->co) < tolerance_sq)) {
*vtmap_a = maxVerts + i;
*vtmap_b = i;
tot_vtargetmap++;
/* average location */
@@ -271,10 +277,11 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
copy_v3_v3(mv_prev->co, mv->co);
}
else {
*vtmap_a = -1;
*vtmap_b = -1;
}
*vtmap_b = -1; /* fill here to avoid 2x loops */
/* Fill here to avoid 2x loops. */
*vtmap_a = -1;
vtmap_a++;
vtmap_b++;

View File

@@ -113,7 +113,7 @@ void BKE_mesh_runtime_reset_on_copy(Mesh *mesh, const int UNUSED(flag))
/**
* \brief This function clears runtime cache of the given mesh.
*
*
* Call this function to recalculate runtime data when used.
*/
void BKE_mesh_runtime_clear_cache(Mesh *mesh)

View File

@@ -1542,7 +1542,7 @@ static bNodeSocket *make_socket(bNodeTree *ntree,
}
/* make the identifier unique */
BLI_uniquename_cb(
unique_identifier_check, lb, "socket", '.', auto_identifier, sizeof(auto_identifier));
unique_identifier_check, lb, "socket", '_', auto_identifier, sizeof(auto_identifier));
bNodeSocket *sock = (bNodeSocket *)MEM_callocN(sizeof(bNodeSocket), "sock");
sock->in_out = in_out;
@@ -4778,6 +4778,9 @@ static OutputFieldDependency find_group_output_dependencies(
/* Propagate search further to the left. */
for (const InputSocketRef *origin_input_socket :
gather_input_socket_dependencies(field_dependency, origin_node)) {
if (!origin_input_socket->is_available()) {
continue;
}
if (!field_state_by_socket_id[origin_input_socket->id()].is_single) {
if (handled_sockets.add(origin_input_socket)) {
sockets_to_check.push(origin_input_socket);
@@ -4826,6 +4829,9 @@ static void propagate_data_requirements_from_right_to_left(
const Vector<const InputSocketRef *> connected_inputs = gather_input_socket_dependencies(
field_dependency, *node);
for (const InputSocketRef *input_socket : connected_inputs) {
if (!input_socket->is_available()) {
continue;
}
if (inferencing_interface.inputs[input_socket->index()] ==
InputSocketFieldType::Implicit) {
if (!input_socket->is_logically_linked()) {
@@ -5923,6 +5929,7 @@ static void registerGeometryNodes()
register_node_type_geo_raycast();
register_node_type_geo_realize_instances();
register_node_type_geo_rotate_instances();
register_node_type_geo_sample_sound();
register_node_type_geo_sample_texture();
register_node_type_geo_scale_instances();
register_node_type_geo_separate_components();

View File

@@ -1071,7 +1071,7 @@ static void link_recurs_seq(BlendDataReader *reader, ListBase *lb)
/* Sanity check. */
if (!SEQ_valid_strip_channel(seq)) {
BLI_freelinkN(lb, seq);
BLO_read_data_reports(reader)->count.vse_strips_skipped++;
BLO_read_data_reports(reader)->count.sequence_strips_skipped++;
}
else if (seq->seqbase.first) {
link_recurs_seq(reader, &seq->seqbase);

View File

@@ -86,6 +86,8 @@ static void sound_copy_data(Main *UNUSED(bmain),
sound_dst->playback_handle = NULL;
sound_dst->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock");
BLI_spin_init(sound_dst->spinlock);
sound_dst->tot_samples = 0;
sound_dst->samples = NULL;
/* Just to be sure, should not have any value actually after reading time. */
sound_dst->ipo = NULL;
@@ -117,6 +119,9 @@ static void sound_free_data(ID *id)
MEM_freeN(sound->spinlock);
sound->spinlock = NULL;
}
if (sound->samples) {
AUD_Sound_freeData(sound->samples);
}
}
static void sound_foreach_cache(ID *id,
@@ -162,6 +167,8 @@ static void sound_blend_read_data(BlendDataReader *reader, ID *id)
sound->tags = 0;
sound->handle = NULL;
sound->playback_handle = NULL;
sound->samples = NULL;
sound->tot_samples = 0;
/* versioning stuff, if there was a cache, then we enable caching: */
if (sound->cache) {

View File

@@ -142,11 +142,14 @@ Span<float3> BezierSpline::handle_positions_left() const
this->ensure_auto_handles();
return handle_positions_left_;
}
MutableSpan<float3> BezierSpline::handle_positions_left()
MutableSpan<float3> BezierSpline::handle_positions_left(const bool write_only)
{
this->ensure_auto_handles();
if (!write_only) {
this->ensure_auto_handles();
}
return handle_positions_left_;
}
Span<BezierSpline::HandleType> BezierSpline::handle_types_right() const
{
return handle_types_right_;
@@ -160,9 +163,11 @@ Span<float3> BezierSpline::handle_positions_right() const
this->ensure_auto_handles();
return handle_positions_right_;
}
MutableSpan<float3> BezierSpline::handle_positions_right()
MutableSpan<float3> BezierSpline::handle_positions_right(const bool write_only)
{
this->ensure_auto_handles();
if (!write_only) {
this->ensure_auto_handles();
}
return handle_positions_right_;
}

View File

@@ -1346,9 +1346,8 @@ void BLI_str_format_byte_unit(char dst[15], long long int bytes, const bool base
}
/**
* Format a attribute domain to a up to 6 places (plus '\0' terminator) string using long number
* names abbreviations. This function is designed to produce a compact representation of large
* numbers.
* Format a count to up to 6 places (plus '\0' terminator) string using long number
* names abbreviations. Used to produce a compact representation of large numbers.
*
* 1 -> 1
* 15 -> 15
@@ -1362,8 +1361,7 @@ void BLI_str_format_byte_unit(char dst[15], long long int bytes, const bool base
* 1000000000 -> 1B
* ...
*
* Dimension of 7 is the maximum length of the resulting string
* A combination with 7 places would be -15.5K\0
* Length of 7 is the maximum of the resulting string, for example, `-15.5K\0`.
*/
void BLI_str_format_attribute_domain_size(char dst[7], int number_to_format)
{

View File

@@ -124,7 +124,7 @@ typedef struct BlendFileReadReport {
/* Number of proxies that failed to convert to library overrides. */
int proxies_to_lib_overrides_failures;
/* Number of sequencer strips that were not read because were in non-supported channels. */
int vse_strips_skipped;
int sequence_strips_skipped;
} count;
/* Number of libraries which had overrides that needed to be resynced, and a single linked list

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