Compare commits

..

281 Commits

Author SHA1 Message Date
b3d15c05a9 typo 2022-01-13 16:43:08 +01:00
4c6916402d move to c++ 2022-01-13 16:42:51 +01:00
79e985ea54 Cleanup: fix building all geometry nodes in one translation unit
There were a couple of function name collisions which were caused
by sharing code with the mask modifier. I just removed the dependence
on the mask modifier now. The code that I duplicated for that purpose
is only in a legacy node, so it can be expected to be removed soonish.
2022-01-13 12:39:48 +01:00
19a6220308 Fix link errors after recent FFMPEG / link_directories changes 2022-01-13 11:12:56 +01:00
d53738396f Tests: skip some compositor tests when WITH_LIBMV=OFF 2022-01-13 10:41:34 +01:00
7bb572f208 Fix T94737: Cycles wrong normal map normal with OSL
Ensure valid reflection was moved elsewhere, should not be done in the node
anymore.
2022-01-13 10:40:41 +01:00
0cf2fafd81 Fix T94050, T94570, T94527: Cycles Bevel and AO nodes not working with Metal
Workaround what may be a compiler bug, solution found by Michael Jones.
2022-01-13 10:40:41 +01:00
a3deef6fff Fix Cycles CPU + GPU render not using CPU after recent changes
In some places the task scheduler was not initialized in time.
2022-01-13 10:40:41 +01:00
eaa4cdaa42 Fix T94758: wrong denoising albedo with BSSRDF retro reflection 2022-01-13 10:40:40 +01:00
Brecht Van Lommel
29450a2af3 Build: remove usage of link_directories
We are now always using absolute paths for libraries, as recommended by the
CMake docs.

Followup to D9177.
2022-01-13 10:40:38 +01:00
Brecht Van Lommel
75a1a578bd CMake: use FFmpeg find module on Linux
And change install_deps.sh to build shared (instead of static) FFMPEG
libraries, for consistency with other library dependencies and to simplify
the logic. This may require users of install_deps.sh to rebuild FFMPEG.

This is the last step that lets us get rid of LIBPATH variables and
link_directories() entirely, as recommended by the CMake docs.

Some fixes were needed in the find FFMPEG module to make it actually work,
this code was unused up to now.

Followup to D8855.

Differential Revision: https://developer.blender.org/D9177
2022-01-13 10:27:11 +01:00
f1a488d0f2 Fix T92953: Tool Settings: Drag on Tweak fails with LMB select 2022-01-13 14:30:12 +11:00
a7c9fb59ca Cleanup: follow code-style for float suffix 2022-01-13 12:34:28 +11:00
227f0f3582 Cleanup: quiet missing braces warning 2022-01-13 12:33:34 +11:00
97c2c39916 Fix T94624: Object as font instances don't work
The fundamental limitation is that we can only have one instance
("dupli") generator at a time. Because the mesh output of a curve
object is output as an instances, the geometry set instances existed,
replacing the object as font instances. The "fix" is to reverse the
order. The behavior won't be perfect still, but at least the old
behavior will be preserved, which is really what matters for a
feature like this.

One way to take this change further would be completely disabling
regular geometry evaluation while this option is active. However,
it doesn't seem like that would actually improve the state of the code.

Differential Revision: https://developer.blender.org/D13768
2022-01-12 13:46:13 -06:00
a311fa96aa Fix T85706: wm_window_make_drawable update DPI
When drawing windows on monitors that differ in DPI, we can sometimes
have UI elements draw at an incorrect scale. This patch just ensures
that `wm_window_make_drawable` always updates DPI.

See D10483 for more details.

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

Reviewed by Brecht Van Lommel
2022-01-12 10:37:52 -08:00
e594f23a27 Revert "CMake: use FFmpeg find module on Linux"
This reverts commit 62a0de1673. Linux buildbot
is giving link errors.
2022-01-12 19:07:40 +01:00
fa8c2c7885 Fix T94071: Area Split Improvements
Allow area Split to be initiated in any area and give better feedback
when not allowed.

See D13599 for more details and usage examples.

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

Reviewed by Campbell Barton
2022-01-12 09:45:19 -08:00
a0dcd0bf2c Fix warnings after bab47b60cb
It's not really clear how this part of the defaults code should be used,
I think this is fine now and solves the warnings.
2022-01-12 18:37:53 +01:00
a72a9e099c Cleanup: Correct indentation 2022-01-12 18:37:53 +01:00
Brecht Van Lommel
62a0de1673 CMake: use FFmpeg find module on Linux
And change install_deps.sh to build shared (instead of static) FFMPEG
libraries, for consistency with other library dependencies and to simplify
the logic. This may require users of install_deps.sh to rebuild FFMPEG.

This is the last step that lets us get rid of LIBPATH variables and
link_directories() entirely, as recommended by the CMake docs.

Some fixes were needed in the find FFMPEG module to make it actually work,
this code was unused up to now.

Followup to D8855.

Differential Revision: https://developer.blender.org/D9177
2022-01-12 18:25:24 +01:00
Simon Lenz
bab47b60cb DNA: Add space clip editor defaults
This is my attempt of adding defaults for the space clip editor struct
(in line with https://developer.blender.org/T80164).

It adds the default allocation for `SpaceClip` and
`node_composite_movieclip.cc`. This also solves the error below (for
C++ files using the DNA_default_alloc), which was put forward by
Sergey Sharybin.

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

Reviewed by: Julian Eisel
2022-01-12 18:04:48 +01:00
Bastien Montagne
a909ab984c Outliner: Add way to display warning icon for items.
While theorically fairly generic, current code is only enabled for
bledfile and liboverride views, and only used to display messages from
library IDs.

Reviewed By: Severin

Differential Revision: https://developer.blender.org/D13766
2022-01-12 18:01:50 +01:00
5f7ad4baaa BLI_math: Fix building when WITH_GMP is off 2022-01-12 17:24:57 +01:00
Nikhil Shringarpurey
e5858a3ad0 Icons: Remove absolute pathnames and deprecated gradients from SVG files
SVG files contained specific detailed pathnames on developers'
computers. These included full local user profile and path and should
not be in the release.

This patches corrects those lines. It also removes unused gradients from
the private icons SVG.

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

Reviewed by: Yevgeny Makarov, Julian Eisel
2022-01-12 15:03:05 +01:00
ec5560db73 DRW: Add DRW_gpu_wrapper.hh
This adds wrapper classes that make it easier to use GPU objects in C++.

####Motivations:####

 - Easier handling of GPU objects.
 - EEVEE rewrite already makes use of similar wrappers.
 - There is the ongoing effort to use more C++ in the codebase
 and lans to port more engines to it.
 - The shader code refactor will make use of many UBOs with shared
 struct declaration. This helps managing them.
 - Safer handling of `TextureFromPool` which can't be bound as normal
 texture (only texture ref) and can be better tracked in the future.

####Considerations:####

 - I chose the `blender::draw` namespace because `blender::gpu` already has private classes (i.e: `gpu::Texture`).
 - Theses are wrappers that manage a GPU object internally. They might be confused with actual `Texture`. However, the name `TextureWrapper` is a bit too much verbose in my opinion. I'm open to suggestion about better name.

Reviewed By: jbakker

Differential Revision: http://developer.blender.org/D13805
2022-01-12 13:05:18 +01:00
0882069095 Cleanup: codestyle obj_exporter_tests.cc. 2022-01-12 13:02:28 +01:00
1552b86b55 Cleanup: Not needed if statement around delete. 2022-01-12 13:02:28 +01:00
d43b5791e0 BLI: Refactor vector types & functions to use templates
This patch implements the vector types (i.e:`float2`) by making heavy
usage of templating. All vector functions are now outside of the vector
classes (inside the `blender::math` namespace) and are not vector size
dependent for the most part.

In the ongoing effort to make shaders less GL centric, we are aiming
to share more code between GLSL and C++ to avoid code duplication.

####Motivations:
- We are aiming to share UBO and SSBO structures between GLSL and C++.
This means we will use many of the existing vector types and others
we currently don't have (uintX, intX). All these variations were
asking for many more code duplication.
- Deduplicate existing code which is duplicated for each vector size.
- We also want to share small functions. Which means that vector
functions should be static and not in the class namespace.
- Reduce friction to use these types in new projects due to their
incompleteness.
- The current state of the `BLI_(float|double|mpq)(2|3|4).hh` is a
bit of a let down. Most clases are incomplete, out of sync with each
others with different codestyles, and some functions that should be
static are not (i.e: `float3::reflect()`).

####Upsides:
- Still support `.x, .y, .z, .w` for readability.
- Compact, readable and easilly extendable.
- All of the vector functions are available for all the vectors types
and can be restricted to certain types. Also template specialization
let us define exception for special class (like mpq).
- With optimization ON, the compiler unroll the loops and performance
is the same.

####Downsides:
- Might impact debugability. Though I would arge that the bugs are
rarelly caused by the vector class itself (since the operations are
quite trivial) but by the type conversions.
- Might impact compile time. I did not saw a significant impact since
the usage is not really widespread.
- Functions needs to be rewritten to support arbitrary vector length.
For instance, one can't call `len_squared_v3v3` in
`math::length_squared()` and call it a day.
- Type cast does not work with the template version of the `math::`
vector functions. Meaning you need to manually cast `float *` and
`(float *)[3]` to `float3` for the function calls.
i.e: `math::distance_squared(float3(nearest.co), positions[i]);`
- Some parts might loose in readability:
`float3::dot(v1.normalized(), v2.normalized())`
becoming
`math::dot(math::normalize(v1), math::normalize(v2))`
But I propose, when appropriate, to use
`using namespace blender::math;` on function local or file scope to
increase readability.
`dot(normalize(v1), normalize(v2))`

####Consideration:
- Include back `.length()` method. It is quite handy and is more C++
oriented.
- I considered the GLM library as a candidate for replacement. It felt
like too much for what we need and would be difficult to extend / modify
to our needs.
- I used Macros to reduce code in operators declaration and potential
copy paste bugs. This could reduce debugability and could be reverted.
- This touches `delaunay_2d.cc` and the intersection code. I would like
to know @howardt opinion on the matter.
- The `noexcept` on the copy constructor of `mpq(2|3)` is being removed.
But according to @JacquesLucke it is not a real problem for now.

I would like to give a huge thanks to @JacquesLucke who helped during this
and pushed me to reduce the duplication further.

Reviewed By: brecht, sergey, JacquesLucke

Differential Revision: https://developer.blender.org/D13791
2022-01-12 12:57:07 +01:00
fb6bd88644 Revert "BLI: Refactor vector types & functions to use templates"
Includes unwanted changes

This reverts commit 46e049d0ce.
2022-01-12 12:50:02 +01:00
Clment Foucault
46e049d0ce BLI: Refactor vector types & functions to use templates
This patch implements the vector types (i.e:`float2`) by making heavy
usage of templating. All vector functions are now outside of the vector
classes (inside the `blender::math` namespace) and are not vector size
dependent for the most part.

In the ongoing effort to make shaders less GL centric, we are aiming
to share more code between GLSL and C++ to avoid code duplication.

####Motivations:
 - We are aiming to share UBO and SSBO structures between GLSL and C++.
 This means we will use many of the existing vector types and others
 we currently don't have (uintX, intX). All these variations were
 asking for many more code duplication.
 - Deduplicate existing code which is duplicated for each vector size.
 - We also want to share small functions. Which means that vector
 functions should be static and not in the class namespace.
 - Reduce friction to use these types in new projects due to their
 incompleteness.
 - The current state of the `BLI_(float|double|mpq)(2|3|4).hh` is a
 bit of a let down. Most clases are incomplete, out of sync with each
 others with different codestyles, and some functions that should be
 static are not (i.e: `float3::reflect()`).

####Upsides:
 - Still support `.x, .y, .z, .w` for readability.
 - Compact, readable and easilly extendable.
 - All of the vector functions are available for all the vectors types
 and can be restricted to certain types. Also template specialization
 let us define exception for special class (like mpq).
 - With optimization ON, the compiler unroll the loops and performance
 is the same.

####Downsides:
 - Might impact debugability. Though I would arge that the bugs are
 rarelly caused by the vector class itself (since the operations are
 quite trivial) but by the type conversions.
 - Might impact compile time. I did not saw a significant impact since
 the usage is not really widespread.
 - Functions needs to be rewritten to support arbitrary vector length.
 For instance, one can't call `len_squared_v3v3` in
 `math::length_squared()` and call it a day.
 - Type cast does not work with the template version of the `math::`
 vector functions. Meaning you need to manually cast `float *` and
 `(float *)[3]` to `float3` for the function calls.
 i.e: `math::distance_squared(float3(nearest.co), positions[i]);`
 - Some parts might loose in readability:
 `float3::dot(v1.normalized(), v2.normalized())`
 becoming
 `math::dot(math::normalize(v1), math::normalize(v2))`
 But I propose, when appropriate, to use
 `using namespace blender::math;` on function local or file scope to
 increase readability.
 `dot(normalize(v1), normalize(v2))`

####Consideration:
 - Include back `.length()` method. It is quite handy and is more C++
 oriented.
 - I considered the GLM library as a candidate for replacement. It felt
 like too much for what we need and would be difficult to extend / modify
 to our needs.
 - I used Macros to reduce code in operators declaration and potential
 copy paste bugs. This could reduce debugability and could be reverted.
 - This touches `delaunay_2d.cc` and the intersection code. I would like
 to know @howardt opinion on the matter.
 - The `noexcept` on the copy constructor of `mpq(2|3)` is being removed.
 But according to @JacquesLucke it is not a real problem for now.

I would like to give a huge thanks to @JacquesLucke who helped during this
and pushed me to reduce the duplication further.

Reviewed By: brecht, sergey, JacquesLucke

Differential Revision: https://developer.blender.org/D13791
2022-01-12 12:47:43 +01:00
e5766752d0 Revert "BLI: Refactor vector types & functions to use templates"
Reverted because the commit removes a lot of commits.

This reverts commit a2c1c368af.
2022-01-12 12:44:26 +01:00
Nathan Rozendaal
b2ccd8546c Compositor: Add Scene Time Node, Rename Time node
Fixes issue T94603
It adds a new compositor node called Scene Time which is already present as a geo node, having the same basic nodes available in all node trees is a nice thing to have.
Renames "Time" node to "Time Curve", this is done to avoid confusion between the Time node and the Scene Time node.

Reviewed By: jbakker

Maniphest Tasks: T94603

Differential Revision: https://developer.blender.org/D13762
2022-01-12 12:29:44 +01:00
a2c1c368af BLI: Refactor vector types & functions to use templates
This patch implements the vector types (i.e:float2) by making heavy
usage of templating. All vector functions are now outside of the vector
classes (inside the blender::math namespace) and are not vector size
dependent for the most part.

In the ongoing effort to make shaders less GL centric, we are aiming
to share more code between GLSL and C++ to avoid code duplication.

Motivations:
- We are aiming to share UBO and SSBO structures between GLSL and C++.
  This means we will use many of the existing vector types and others we
  currently don't have (uintX, intX). All these variations were asking
  for many more code duplication.
- Deduplicate existing code which is duplicated for each vector size.
- We also want to share small functions. Which means that vector functions
  should be static and not in the class namespace.
- Reduce friction to use these types in new projects due to their
  incompleteness.
- The current state of the BLI_(float|double|mpq)(2|3|4).hh is a bit of a
  let down. Most clases are incomplete, out of sync with each others with
  different codestyles, and some functions that should be static are not
  (i.e: float3::reflect()).

Upsides:
- Still support .x, .y, .z, .w for readability.
- Compact, readable and easilly extendable.
- All of the vector functions are available for all the vectors types and
  can be restricted to certain types. Also template specialization let us
  define exception for special class (like mpq).
- With optimization ON, the compiler unroll the loops and performance is
  the same.

Downsides:
- Might impact debugability. Though I would arge that the bugs are rarelly
  caused by the vector class itself (since the operations are quite trivial)
  but by the type conversions.
- Might impact compile time. I did not saw a significant impact since the
  usage is not really widespread.
- Functions needs to be rewritten to support arbitrary vector length. For
  instance, one can't call len_squared_v3v3 in math::length_squared() and
  call it a day.
- Type cast does not work with the template version of the math:: vector
  functions. Meaning you need to manually cast float * and (float *)[3] to
  float3 for the function calls.
  i.e: math::distance_squared(float3(nearest.co), positions[i]);
- Some parts might loose in readability:
  float3::dot(v1.normalized(), v2.normalized())
  becoming
  math::dot(math::normalize(v1), math::normalize(v2))
  But I propose, when appropriate, to use
  using namespace blender::math; on function local or file scope to
  increase readability. dot(normalize(v1), normalize(v2))

Consideration:
- Include back .length() method. It is quite handy and is more C++
  oriented.
- I considered the GLM library as a candidate for replacement.
  It felt like too much for what we need and would be difficult to
  extend / modify to our needs.
- I used Macros to reduce code in operators declaration and potential
  copy paste bugs. This could reduce debugability and could be reverted.
- This touches delaunay_2d.cc and the intersection code. I would like to
  know @Howard Trickey (howardt) opinion on the matter.
- The noexcept on the copy constructor of mpq(2|3) is being removed.
  But according to @Jacques Lucke (JacquesLucke) it is not a real problem
  for now.

I would like to give a huge thanks to @Jacques Lucke (JacquesLucke) who
helped during this and pushed me to reduce the duplication further.

Reviewed By: brecht, sergey, JacquesLucke

Differential Revision: http://developer.blender.org/D13791
2022-01-12 12:19:39 +01:00
d320f3677e Cleanup: make format 2022-01-12 11:29:18 +01:00
1e61b759c7 Fix T94797: crash when playing animation in eevee rendered view
The issue was caused by rBd09b1d2759861aa012ab2e7e4ce2ffa2.
Since this commit, the image users in gpu materials were updated
during depsgraph evaluation as well. However, there was a race
condition when one thread is deleting gpu materials in `BKE_material_eval`
while another thread is updating the image users at the same time.

The solution is to make sure that deleting gpu materials is done before
iterating over all gpu materials, by adding a new depsgraph relation.
2022-01-12 11:15:22 +01:00
145f1d1e0a Fix T94812: render layer sockets are missing after file load
The main issue was the use of `G_MAIN` during file load.
This patch refactors the code so that iterating over `G_MAIN`
is not necessary anymore. See D13800 for more details.

Differential Revision: https://developer.blender.org/D13800
2022-01-12 11:07:31 +01:00
7a2b181591 Fix T94041: Loading a new file gives crash while rendering in viewport
The issue was caused by Cycles display driver not being able to restore
window's OpenGL context after disposing Cycles-side OpenGL context.

This is due to the window OpenGL re-activation needing to access window
manager which gets cleared out form global main during file reading.

Defer clearing window manager from the global main to until after all
screens are "exited". This allows Cycles to properly stop rendering,
dispose its OpenGL context, and restore window's drawable context.

It is unclear why it was required to clear window manager list early
on. Guess is that it comes from an original code in a1c8543f2a where
there was an early return which then got replaced with an actual logic
without changing the order of de-initialization and window manager list
clear.

Differential Revision: https://developer.blender.org/D13799
2022-01-12 10:01:33 +01:00
ebad1d8d33 CMake: exclude linker options for APPLE and non-UNIX
These are only used for non-apple unix systems.
2022-01-12 18:55:13 +11:00
795cea2cce Revert "Cleanup GPencil strength previous commit"
This reverts commit e339946515.

This broken the tablet pressure and it was impossible to set a proper strength.
2022-01-12 08:45:57 +01:00
7f28084e2a Cleanup: use utility functions 2022-01-12 06:46:12 +01:00
77616082f4 Fix T89542: Crash when loading certain .hdr files
The direct cause of the bug in question was passing in the raw memory
buffer to sscanf. It should be called with a null-terminated buffer;
which isn't guaranteed when blindly trusting the file data.

When attempting to fuzz this code path, a variety of other crashes were
discovered and fixed.

Differential Revision: https://developer.blender.org/D11952
2022-01-11 20:48:32 -08:00
0dc309bef6 Cleanup: remove redundant const qualifiers for POD types 2022-01-12 12:51:11 +11:00
f4492629ea Cleanup: VSE channel drawing
Remove code that very slightly darkened line on bottom of timeline, when
backdrop is enabled. Purpose of the code wasn't dodumented, and 2.79
doesn't seem to produce this darkened line.
Rename drawing functions to appropriate names.
2022-01-12 01:46:27 +01:00
ef5d01d98f deps_builder: GMP 6.2.1
Pretty straightforward update, nothing noteworthy to report.

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

Reviewed by: brecht, sybren
2022-01-11 16:26:30 -07:00
89145341e5 BLF: UI_fontstyle_draw Usage
Add maximum string length argument to UI_fontstyle_draw to reduce usage
of BLF_DRAW_STR_DUMMY_MAX. Reorders arguments to UI_fontstyle_draw_ex

See D13794 for more details.

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

Reviewed by Campbell Barton
2022-01-11 14:52:39 -08:00
bbe59c6014 BLF: Reduction of use of BLF_DRAW_STR_DUMMY_MAX
Reduction of the number of uses of the define BLF_DRAW_STR_DUMMY_MAX
by using actual sizes of static character arrays.

See D13793 for more details.

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

Reviewed by Campbell Barton
2022-01-11 14:08:38 -08:00
ab125f466c Fix T94751: ground created by Setup Tracking Scene not marked as Shadow Catcher
Change that was missing in {rBca64bd0aacda}.
2022-01-11 19:02:04 -03:00
947dc21979 Cleanup: Fix build warning with MSVC
comparing a bool > 0 make MSVC emit
warning C4804: '>': unsafe use of type 'bool' in operation.

int does the job nicely.
2022-01-11 14:57:54 -07:00
5a6ec0f003 Build: Enable unity build for bf_compositor
Blender's compositor code already makes extensive use of
namespace which makes it very simple to enable unity build.
There was one duplicated function that has since to be moved
to a common header.

I saw roughly a 3x speedup of bf_compositor using ninja on
linux using i5 8250u (1:34 down to 0:34).

Reviewed By: LazyDodo

Differential Revision: https://developer.blender.org/D13792
2022-01-11 16:55:45 -05:00
48ff9b57f8 Build: Add precompiled headers for bf_compositor
With this change, compilation saw a 2.4x improvement.

This can be combined with unity build to give an overall 4x improvement

Depends on D13797

Reviewed By: LazyDodo

Differential Revision: https://developer.blender.org/D13798
2022-01-11 16:50:35 -05:00
bdf99a5119 cleanup: hipew remove unused variables
caused 4 warnings, nothing even conditionally
uses them, can be safely removed.
2022-01-11 14:49:29 -07:00
e339946515 Cleanup previous commit
Don't need check minimum constant value, brush value is enough.
2022-01-11 22:48:26 +01:00
ac3d07ad17 Fix T94799: GPencil Strokes drawn at 0.0 Strength still visible
There was a clamp with a value greater than 0.
2022-01-11 22:45:50 +01:00
376e425c02 Fix T93588: some videos loaded flipped over Y axis on macOS Arm
Was not actually flipping in the need_aligned_ffmpeg_buffer case.
2022-01-11 21:43:32 +01:00
45bb6b836a IME Cleanup: Unused GHOST_TEventImeData Member
Removal of unused tmp member of GHOST_TEventImeData. Not used now,
nor was it used by the commit that added it to begin with.

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

Reviewed by Ray Molenkamp
2022-01-11 12:35:11 -08:00
e95b4dc2dd Cleanup: Fix build warnings with MSVC
our UNUSED macro is essentially a no-op for MSVC, which lead to
the situation  where this well meant macro was emitting the
following warning:

C4189: 'UNUSED_i': local variable is initialized but not referenced

However since we have been on c++17 for a while now the UNUSED
macro can be replaced with the standard [[maybe_unused]] attribute
in cpp files.

This changes cleans up the use of the UNUSED macro in the
bf_nodes_geometry project.

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

Reviewed by: JacquesLucke, Severin, Sergey, HooglyBoogly
2022-01-11 12:54:18 -07:00
259a71cd3c Build: use precompiled headers on all platforms
Since CMake 3.16, CMake has native precompiled header (PCH) support.

This change swaps Blender's own PCH implementation with the native implementation.
Previously, PCH was only enabled on Windows however,
this new implementation works on all platforms.

For more information see https://cmake.org/cmake/help/latest/command/target_precompile_headers.html

On my system, Linux with ninja running on an i5 8250U
I saw a 60% reduction in compile times for `bf_freestyle` + linking time.

Reviewed By: LazyDodo, brecht

Differential Revision: https://developer.blender.org/D13797
2022-01-11 14:18:58 -05:00
8cff1ecf9f Fix T94804: GPencil Simplify when strokes are Automerged in Draw Mode
The problem was the points were selected in edit mode and then sampled. Now, in draw mode, the points are always unselected to avoid this effect in the auto merge process.
2022-01-11 19:20:27 +01:00
Henrik Dick
631067e559 Add support for a longest diagonal quad triangulation mode
The new triangulation mode for quads is the opposite of the current default
shortest diagonal mode. It is optimal for cloth simulations using quad meshes.

Differential Revision: http://developer.blender.org/D13777
2022-01-11 18:51:25 +01:00
41ce7807a6 Fix T94299: Object asset set as visible but doesn't show
Differential Revision: https://developer.blender.org/D13738

Reviewed by: Bastien Montagne, Sergey Sharybin
2022-01-11 18:38:05 +01:00
ccac22fec5 Cleanup compiler warning in Windows
`bool` used instead of `int`
2022-01-11 16:48:16 +01:00
6774cae3f2 Fix T94728: Auto Depth problem with Cliping Region
Issue introduced in rB1d49293b80446b89b5b12fa0eeefaf14e5051e48

`drw_manager_init` must be called after `drw_context_state_init` as
`DST.draw_ctx.sh_cfg` (indicating when the view is clipped) must be set
first.

Differential Revision: https://developer.blender.org/D13795
2022-01-11 10:39:39 -03:00
fc0f315106 Cleanup: remove unnecessary 'use_opengl_context' parameter
The argument passed is always false.
2022-01-11 10:28:32 -03:00
Aleksi Juvani
0c94e5d166 Fix PSYS_GLOBAL_HAIR stripped even if connecting the hair fails
After disconnecting hair on an object, if you then hide the particle system, and try connecting the hair again, the operator is cancelled due to `remap_hair_emitter` returning `false` because `target_psmd->mesh_final` is NULL, but `connect_hair` will still strip the `PSYS_GLOBAL_HAIR` flag, which will cause the hair in the hidden particle system to be positioned incorrectly. The correct behavior is to strip the flag only if `remap_hair_emitter` succeeds.

Differential Revision: https://developer.blender.org/D13703
2022-01-11 13:08:13 +01:00
9dc9692b09 Select Similar: hide 'threshold' from UI when not used
When the 'threshold' is not used in the type we are comparing, just hide
it. This was obvious for some types (e.g. Materials), but maybe not so
on others (e.g. Polygon Sides) and potentionally confusing.

Reported by @hitrpr in chat.

Differential Revision: https://developer.blender.org/D13760
2022-01-11 11:47:57 +01:00
255727b752 GPU: Utility function to bind UBO to batches. 2022-01-11 09:57:22 +01:00
Evan Wilson
1949aece21 Explicit Color OCIO role comment fix.
This is an update to the correct OCIO role.

It changes `SceneReference` to `scene_linear`

See https://opencolorio.readthedocs.io/en/latest/guides/authoring/overview.html#config-roles

>     - reference - the color space against which the other color spaces are defined
>NOTE: The reference role has sometimes been misinterpreted as being the space in which “reference art” is stored in.
>
>    - scene_linear - the scene-referred linear-to-light color space, often the same as the reference space

The current OCIO UX working group doc says:

>reference: This role has had multiple interpreted meanings over the years and is a common point of confusion. It is kept in OCIO for backwards compatibility, but the recommendation is that it is not used by apps.

Reviewed By: jbakker

Differential Revision: https://developer.blender.org/D11398
2022-01-11 09:55:22 +01:00
4e8a883bcc Cleanup: use unity build for composite nodes
GIves about a 2.1x improvement in compilation times.
2022-01-11 02:57:14 -05:00
bc02ede98b Cleanup: Deduplicate finv_test function 2022-01-11 02:16:47 -05:00
d608b98145 Cleanup: quite missing-variable-declarations warnings 2022-01-11 18:16:00 +11:00
9af81c2b74 Cleanup: correct exception message 2022-01-11 18:16:00 +11:00
c77f837598 Revert "Cleanup: remove declaration for removed function"
This reverts commit aa363ec2ae.

The function still exists, this commit caused a warning with Clang
So keep MEM_printmemlist_pydict.
2022-01-11 18:16:00 +11:00
fd922f5940 Cleanup: Composite nodes: add namespace for every file
This puts all static functions in composite node files into a new
namespace. This allows using unity build which can improve
compile times significantly.

This is a follow up on rB1df8abff257030ba79bc23dc321f35494f4d91c5
but for compositor nodes.

The namespace name is derived from the file name.
That makes it possible to write some tooling that checks the names later on.
The filename extension (`cc`) is added to the namespace name as well.
his also possibly simplifies tooling but also makes it more obvious that this namespace is specific to a file.

Reviewed By: JacquesLucke, HooglyBoogly, jbakker

Differential Revision: https://developer.blender.org/D13466
2022-01-11 02:11:14 -05:00
f2fb9a0c59 Fix T94768: Crash in VSE prefetching
If timeline contains scene strip outside of edited meta strip, this will
cause crash. This is because prefetchin ignored meta strips being edited
when rendering, but did check for scene strips only inside edited meta
strip.

Change active seqbase pointer when entering meta strip. This makes it
possible to prefetch only content that is being presented to user.
2022-01-11 06:12:15 +01:00
f134341e03 Fix T94671: performance regression with subsurf modifier
rBeed45d2a239a introduced a GPU backend for OpenSubDiv which lets us do
the subdivision at render time. However, some tools might still need to
have the subdivision data available on the CPU side. For this a
subdivision mesh wrapper was also introduced, and is computed whenever a
CPU side mesh is needed. The subdivision settings for this wrapper are
stored during modifier evaluation if GPU subdivision can be done.

The performance regression is due to the fact that although the
subdivision mesh was already computed on the CPU, and no subdivision
wrapper is generated, some checks for creating subdivision data in
`BKE_mesh_wrapper_ensure_subdivision` where still run, one of which is
very expensive.

To fix this we first check the runtime settings of the mesh to see if
subdivision is needed at all.
2022-01-11 03:34:16 +01:00
922ae55a16 Spreadsheet: Add mesh topology information with a debug value
This commit adds topology information from mesh data structs to the
spreadsheet when the debug value `4001` is set. Eventually we could
expose these. For now it can be a useful tool for developers when
working on mesh algorithms.

Differential Revision: https://developer.blender.org/D13735
2022-01-10 16:45:53 -06:00
37b336a8af Cleanup: Remove unused "active ID" node flag
The value of this flag was only retrieved in `nodeGetActiveID`, which
wasn't used anywhere. Other than that, the `NODE_ACTIVE_ID` and
related functions seem to come from the Blender internal renderer.

Differential Revision: https://developer.blender.org/D13770
2022-01-10 16:42:50 -06:00
f4af21038d Geometry Nodes: Move normal field input to be usable elsewhere
This commit moves the normal field input to `BKE_geometry_set.hh`
from the node file so that normals can be used as an implicit input to
other nodes.

Differential Revision: https://developer.blender.org/D13779
2022-01-10 16:41:05 -06:00
fe82b8d1e8 Docs: correct doc-string for bl_run_operators_event_simulate
The event() action swapped type/value arguments.
2022-01-11 09:13:25 +11:00
4b8cf11fa5 macOS: fix xcrun sdk detection for minimal CLT
Differential Revision: https://developer.blender.org/D13783
2022-01-11 01:07:31 +05:30
a4a95c8d36 Docs: Add comments to node socket struct header 2022-01-10 12:29:09 -06:00
ccf06fffbc UI: Allow AltGr Key + C,V,X Text Input
Slight change to our processing of Ctrl-C, Ctrl-V, and Ctrl-X so that
they will not be triggered if Alt is also pressed. This allows entry
of AltGr-C, -V, -X when using International keyboard layouts.

See D13781 for more details

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

Reviewed by Brecht Van Lommel
2022-01-10 09:52:19 -08:00
Takahiro Shizuki
57bea57f5e Fix T94434: Windows IME Pinyin Forward Slash
Treat "/" as a key that should be evaluated by the Win IME system when
the input language is Chinese. This fixes a duplication of the input
character and results in the expected output of a Chinese wide comma.

See D13771 for more details.

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

Reviewed by Brecht Van Lommel
2022-01-10 09:09:13 -08:00
1a27d20df3 Tests: disable all but one simple test for the Cycles Metal device
Until all tests are passing, this lets us run a basic test on the buildbot.

Ref T92212
2022-01-10 17:35:07 +01:00
39ba82f25d Fix T94111: nurb normal calculation does not work
The normals were computed with an uninitialized tilt.
2022-01-10 17:25:42 +01:00
af6a30ebf1 Fix compilation error after recent fix
For some reason GCC accepted C++-style of unused variable marking.
2022-01-10 17:17:31 +01:00
b0a83a6ed4 Fix compile error with msvc 2022-01-10 17:10:07 +01:00
292c2cefe3 Fix T93727: Tiled render error in Cycles after changing temp directory
Consider temporary directory to be variant part of session configuration
which gets communicated to the tile manager on render reset.

This allows to be able to render with one temp directory, change the
directory, render again and have proper render result even with enabled
persistent data.

For the ease of access to the temp directory expose it via the render
engine API (engine.temp_directory).

Differential Revision: https://developer.blender.org/D13790
2022-01-10 16:54:12 +01:00
20cb2c72a5 Fix second render failure with Cycles persistent data
The issue was caused by the recent changes in the way how the
render result is drawn: the display driver now could hold an
OpenGL resources. Those resources are not shared across contexts
so whenever OpenGL context is destroyed those resources are to
be destroyed as well (and not attempted to be re-used for a next
render).

Do such destruction and entire driver re-creation since it does
simplifies things from API usage point of view without causing
measurable slowdown.

Steps to reproduce the issue:
- Set the render resolution to 2x of Full HD
- Enable persistent data
- Render (F12)
- Render again

Observe OpenGL state being corrupted. Easy to see in debug mode
where IMM abstraction level reports issues about the buffer size
not being the proper size. This was caused by the display driver
trying to use VAO from the previous OpenGL context.

Differential Revision: https://developer.blender.org/D13789
2022-01-10 16:53:44 +01:00
d9dd8c287f Fix T94661: Out-of-bounds memory access due to malformed DDS image file
Harden bounds check in the stream reader avoiding integer overflow.
2022-01-10 14:27:54 +01:00
76d69bbb08 Fix Cycles compilation with Optix on Windows.
Since Optix 7.3 is required, update the default path accordingly.
2022-01-10 13:39:53 +01:00
8dd163160e Fix T94766: texture coordinates from other object do not refresh
The core issue is that flushing dependencies are created from an object
to a node tree when it contains e.g. a Texture Coordinate node.
That is an issue because the evaluation of the node tree itself does not
depend on the object (node tree evaluation is essentially a no-op).

Only other systems that parse and evaluate the node tree in a specific
context actually depend on e.g. the position of the referenced object.
It can even be the case that the node tree depends on objects that
the actual evaluator (geometry nodes modifier/material) does not depend
on, because a node is not connected to the output.

Geometry nodes makes the distinction between dependencies to the
node tree and to the evaluator already. Shader nodes do not.
Therefore, shader nodes need a flushing relation from node groups
to their parent node groups.

This brings back some unnecessary updates from rB7e712b2d6a0d
(e.g. when creating a node group from nodes that are not connected
to the output). This is a bit unfortunate, but refactoring how
dependencies work with shader nodes is a out of scope for this fix.
2022-01-10 13:02:57 +01:00
Demeter Dzadik
3ec88ae21d Fix error when keyframing with Custom Properties
Since rBf9ccd26b037d, calling `data.path_resolve()` on custom properties
with `None` value do not cause a `ValueError` exception any more. This
is now taken into account in the keying sets targeting custom
properties.

Reviewed By: sybren

Differential Revision: https://developer.blender.org/D13787
2022-01-10 13:01:01 +01:00
f5e90a943f Remove GPU_SHADER_2D_POINT_FIXED_SIZE_UNIFORM_COLOR.
Shader isn't used and not accessible via py-api.
2022-01-10 12:51:21 +01:00
8a772645e2 Remove GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR.
Shader isn't used and not accessible via py-api.
2022-01-10 12:51:21 +01:00
1b57dcf320 Remove GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA.
Shader isn't used and not accessible via py-api.
2022-01-10 12:51:21 +01:00
6669431846 Remove GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR.
Shader isn't used and not accessible via py-api.
2022-01-10 12:51:21 +01:00
e12a707692 Remove GPU_SHADER_3D_POINT_VARYING_SIZE_UNIFORM_COLOR.
Shader isn't used and not accessible via the py-api.
2022-01-10 12:51:21 +01:00
f813aab787 Remove GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA.
Shader isn't used and isn't accessible via py-api.
2022-01-10 12:51:21 +01:00
cfb3f5062d Cleanup: Remove unused source files. 2022-01-10 12:51:21 +01:00
3488339475 Cleanup: Consistent naming GPU_SHADER_2D_AREA_BORDERS. 2022-01-10 12:51:21 +01:00
227fd753df GPU: Remove unused UV shaders.
The UV shaders have been migrated to the overlay engine and aren't
accessible via the python API.
2022-01-10 12:51:21 +01:00
bd8fa07a3d Cleanup: add utility macro to simplify using std::enable_if 2022-01-10 12:28:33 +01:00
934db6a820 Fix T94409: GPencil smooth stroke thickness operator weird result
The smooth was not working "smoothly" and any change in the factor produced a weird result.
2022-01-10 12:23:52 +01:00
5aac794b11 Fix compile error in gpu test. 2022-01-10 12:16:25 +01:00
1b1e947162 Fix T94600: Apply single shrinkwrap constraint fails
rBd6891d9bee2b introduced a way to apply a single constraint from the
constraint stack. For this we want to work in the evaluated domain, in
particular the constraint target should be evaluated (the shrinkwrap
constraint needs to have access to the target's evaluated mesh).

Thx a lot to @sergey for handholding here!

Maniphest Tasks: T94600

Differential Revision: https://developer.blender.org/D13765
2022-01-10 11:57:54 +01:00
101fadcf6b Motion Path: Tweak the User Interface
This moves the clear paths button ("X") to the same line of "Update All Paths",
and make it visible at all times.

1. The clear button affects all objects (by default). However the
Calculate/Update Paths only works on the selected objects/objects.
Better to not have them both on the same line.

2. The operator to clear object and pose paths can run even if the active
object/bone has no motion path. However the UI was not showing the button in
those cases.

Before:
{F12757500, size=full}

After:
{F12757502, size=full}

Differential Revision: https://developer.blender.org/D13609
2022-01-10 11:40:37 +01:00
62e8d80a61 Fix out of bounds memory access displaying the compositor crop gizmo
Regression from typo in cbca71a7cf.
2022-01-10 21:09:30 +11:00
6beaa29791 Compositing Convert color space node
Compositor node to convert between color spaces.

Conversion is skipped when converting between the same color spaces or to or from data spaces.
Implementation done for tiled and full frame compositor.

Reviewed By: Blendify, jbakker

Differential Revision: https://developer.blender.org/D12481
2022-01-10 08:59:00 +01:00
eb7333e772 Cleanup: Wintab input processing.
Switched populating GHOST_WintabInfoWin32 vector from resizing and
assigning to reserving and pushing.

Removed unnecessary state tracking for multiple button presses in a
single packet.

Paired initialization with definition, and added default initialization
for GHOST_WintabInfoWin32.
2022-01-09 19:38:11 -08:00
1705587e21 Cleanup: note that compositor vector blur shares logic with zbuf.c
Note that some functions have been copied between these files.
De-duplication isn't trivial as there are differences in some functions.
2022-01-10 13:47:13 +11:00
74c896c081 Cleanup: typos in comments, remove libnumaapi reference 2022-01-10 13:47:12 +11:00
c04d36e922 Cleanup: Missing internationization for socket description 2022-01-09 18:39:34 -05:00
37d6ae16be Fix mistake in previous commit 2022-01-09 18:32:26 -05:00
17c7bac405 Cleanup: redundent semicolons after function braces 2022-01-09 18:24:48 -05:00
6110f3aa1f Cleanup: Use new socket builder API 2022-01-09 17:44:36 -05:00
ca0c69eaeb UI: Make uiTemplateNodeLink work for all socket types
Currently the node link ui template only works with a few socket types.
This commit addes support for the rest of the socket type declarations.

As pointed out in D13776 currently after recent refactors
Shader nodes no longer display in the menu.

In the future more socket types will be used in the shader nodes
and makes the UI template work better for other node trees.

Differential Revision: https://developer.blender.org/D13778
2022-01-09 11:49:08 -05:00
5519a6a520 Fix T94243: weightpaint gradient panel shown in other places
Weightpaint gradient tool panel showed in other modes (and as a separate
panel).

Fix for fix, see
- rBf8a0e102cf5e
- rBe549d6c1bd2d

So now, check mode again and restrict to topbar (prevents an additional
panel since this is already included in the brush settings).

ref rB0837926740b3 in sculpt-dev branch, so thx @joeedh as well!

Maniphest Tasks: T94243

Differential Revision: https://developer.blender.org/D13630
2022-01-09 11:31:57 +01:00
c5ee3ac7e0 Cleanup: Remove no op socket templates 2022-01-09 01:03:39 -05:00
e17ac8dc58 Cleanup: Nodes: Begin splitting shader node buttons into individual files
Currently, most node buttons are defined in `drawnode.cc` however,
this is inconvenient because it requires editing many files when adding new nodes.
The goal is to minimize the number of files needed to add or update a node.

This commit moves most of the node layout functions for shader nodes into their respected
source/blender/nodes/shader/nodes file.

In the future, these functions will be simplified to node_layout.

Some nodes were left in `drawnode.cc` as this would require duplicating code
while this is likely fine it is best to leave that to a seperate commit.
2022-01-09 00:59:34 -05:00
ed1ced2484 Cleanup: Use new socket builder API 2022-01-08 23:16:55 -05:00
9620fdc986 Cleanup: Remove no op socket templates 2022-01-08 22:15:47 -05:00
45bc4e3209 Fix T94713: Alembic crash with empty frames and velocities
Some software or processing tools (videogrammetry in this case) may
export malformed files with velocity data even when the frame is empty
for some reason. We need to explicity compare the data size with the
vertex size, and refuse to load the attribute if there is a data size
mismatch.
2022-01-08 20:46:28 +01:00
d5e73fa13d Fix T94534: dangling pointer in internal link after removing socket
The dangling pointer caused errors further down the line.
The solution is to simply delete an internal link when one
of the corresponding sockets is removed (just like normal
links are removed as well).
2022-01-08 17:36:59 +01:00
937aa8e114 Cleanup: Use new socket builder API 2022-01-07 23:53:57 -05:00
90e5ce6ab5 Cleanup: Loop through socket listbase instead of array
The socket arrays will be removed when using the new socket builder.
So instead we have to loop through the node outputs list.
2022-01-07 23:53:45 -05:00
741ed5fcd2 Fix Cycles compile error after last own commit
We can't include `BLI_utildefines.h` in `RNA_types.h` since Cycles includes
that, but duplicates some of the util defines. So you'd have duplicated
definitions.
2022-01-08 00:28:19 +01:00
34e84d0ee8 Cleanup: Remove unused code from BKE_node.h
Remove a variety of unused functions, declarations without definitions,
incorrect comments, and defines that have been commented for years
2022-01-07 16:16:56 -06:00
09d6846839 Fix Adjust Last Operation panel showing session UUID number button
This is implementation specific data that should never be exposed to regular
users. Also make sure this data is not saved to presets.
2022-01-07 23:06:29 +01:00
3e11c7016e RNA: Support bitwise operators for property flags in C++
Needed for the following commit.
2022-01-07 22:50:55 +01:00
5ba5678e00 Cleanup: Use forward declaration of struct in header
This meant that BKE_mesh.h couldn't be used without
the DNA headers first.
2022-01-07 12:42:04 -06:00
Aleksi Juvani
1152caad32 Fix: connecting hair fails on meshes with no generative modifiers
Fixes a bug introduced in rB5dedb39d447b. `mesh_original` is not set if the
mesh has no generative modifiers, in which case we can use `mesh_final`, which
would seem to be consistent with the rest of the particle code. An alternative
approach would be to make sure that `mesh_original` is always set in
`deformVerts`.

Differential Revision: https://developer.blender.org/D13754
2022-01-07 18:05:03 +01:00
Olivier Maury
34d553671d Fix wrong shadow terminator geometry offset with deformation motion blur
Differential Revision: https://developer.blender.org/D13759
2022-01-07 17:20:04 +01:00
Olivier Maury
ee0928d4be Fix wrong shadow terminator geometry offset for instances
Must take into account SD_OBJECT_TRANSFORM_APPLIED to determine if the normal
was already in world space.

Differential Revision: https://developer.blender.org/D13639
2022-01-07 17:20:04 +01:00
ae28d90578 Fix T93350: Cycles renders shows black during rendering huge resolutions
The root of the issue is caused by Cycles ignoring OpenGL limitation on
the maximum resolution of textures: Cycles was allocating texture of the
final render resolution. It was exceeding limitation on certain GPUs and
driver.

The idea is simple: use multiple textures for the display, each of which
will fit into OpenGL limitations.

There is some code which allows the display driver to know when to start
the new tile. Also added some code to allow force graphics interop to be
re-created. The latter one ended up not used in the final version of the
patch, but it might be helpful for other drivers implementation.

The tile size is limited to 8K now as it is the safest size for textures
on many GPUs and OpenGL drivers.

This is an updated fix with a workaround for freezing with the NVIDIA
driver on Linux.

Differential Revision: https://developer.blender.org/D13385
2022-01-07 17:20:04 +01:00
Michael Jones
efe3d60a2c Cycles: Fix Metal build
This patch fixes a couple of new Metal kernel compilation errors: 1) a kernel parameter count overflow, and 2) missing address space qualifiers.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D13763
2022-01-07 16:19:31 +00:00
b7ea6e9d0e LibOverrides: small refactor of resync main public function.
Simplify signature of `BKE_lib_override_library_resync` and make it a
shallow wrapper around new internal `lib_override_library_resync` that
can then be easily extended for other internal needs.

Not functional changes expected here.
2022-01-07 15:25:25 +01:00
Germano Cavalcante
5560f32447 Fix T94078: Wrong Bound Box calculated for curves
`DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN` creates temporary objects that
correspond to duplicates or instances.

These temporary objects can share same pointers with the original object
as in the case of Bounding Box.

Bound Box of temporary objects is marked dirty in
`BKE_object_replace_data_on_shallow_copy` since `ob->data` is different.

This causes the original Bounding Box, calculated for the evaluated
geometry, to be lost.

The solution in this commit is to change the boundbox reference of the
temporary objects, so the boundbox of the non-temporary object (with
the data curve) is not marked dirty.

Differential Revision: https://developer.blender.org/D13581
2022-01-07 10:42:13 -03:00
5085c622ea Cleanup: Remove unused numapi library 2022-01-07 12:19:02 +01:00
312aa67cc7 Remove dead numaapi code in blenlib
It it rather an old experiment now which didn't pay off.
The initial idea was to have main and jobs threads on fast
nodes of TR2 processors. This didn't really work reliably
because in Blender we need to be able to create nested
threads without their affinity set. This is not how some of
OS are creating nested threads, and we don't always have
access to child threads to reset their affinity.

So overall complexity of the initial idea implementation
became too much compared to the performance gain.
2022-01-07 12:19:02 +01:00
ed52de948c LibOverride: Add tag to libraries that had to be recursively resynced.
Request from studio, to help identify quickly libs that need update.

NOTE: Currently only outputing INFO log in console, display of this info
in the outliner will come in a separate commit.
2022-01-07 12:09:50 +01:00
2cc6b249c3 Cycles: Remove usage of libnumaapi
No need for it now since all the threading queries and
scheduling is done via TBB.

Should be no functional changes as all the removed code
is supposed to be unused.
2022-01-07 11:47:37 +01:00
Jagannadhan Ravi
361702f239 Fix T94310: Blender doesn't support with 128 threads well in Win11
Query TBB for the maximum allowed concurrency, which is free from a bug
in own concurrency detection code. One thing to keep in mind is that now
Cycles is limited by the number of threads in the TBB areana from which
Session is created. This isn't a problem for Blender since we do not limit
arena on Blender side. Could be something to watch out for in other Cycles
integrations.

Differential Revision: https://developer.blender.org/D13658
2022-01-07 11:37:30 +01:00
bef2412ca2 Fix T86952: Buffer overflow reading specific DDS images
Add a data boundary check in the flipping code.

This code now also communicates the number of mipmap levels
it processed with an intent to avoid GPU texture from using
more levels than there are in the DDS data.

Differential Revision: https://developer.blender.org/D13755
2022-01-07 11:15:17 +01:00
29e33cfff5 Fix T94659: crash when deleting instances (part 2)
This was missing from rB3e92b4ed2408eacd126c0.
Before only the Separate Geometry node was fixed, because that
node was used in the file from the bug report. The same issue
existed in the Delete Geometry node as well though.
2022-01-07 08:21:34 +01:00
6c906b7c21 Fix T94707: inverted output of separate geometry node incorrect
This was an oversight in rB3e92b4ed2408eacd126c0.
2022-01-07 08:11:25 +01:00
7c04bc9a01 Cleanup: exclude uiFont from DNA, rename filename -> filepath
This isn't saved to the preferences,
so there is no need to store in DNA.

Also remove unused `r_to_l` member.
2022-01-07 18:05:36 +11:00
f24854005d Fix T94708: negative reference count error with Python API callbacks
Regression in 7972785d7b that caused
Python callback arguments to be de-referenced twice - potentially
accessing freed memory. Making a new-file with a circle-select
tool active triggered this (for example).

Now arguments aren't de-referenced when Blender it's self has already
removed the callback handle.
2022-01-07 17:48:54 +11:00
1642028310 Cleanup: use the ELEM macro 2022-01-07 17:48:25 +11:00
82858ca3f4 Fix T94629: The IMB_flip API would fail with large images
Fix IMB_flip[xy] to handle cases where integer overflow might occur when
given sufficiently large image dimensions.

All of these fixes were of a similar class where the intermediate
sub-expression would overflow silently. Widen the types as necessary.

Differential Revision: https://developer.blender.org/D13744
2022-01-06 21:35:04 -08:00
b3dc1a17a0 Fix BKE_image_ensure_tile_token being called with a full path
Assert that only the file name component is passed in
since special handling for UDIM should only be applied to the file name.

Also remove an unnecessary NULL check on the filename argument.
2022-01-07 15:15:08 +11:00
2cd8238ce3 Cleanup: use static sets for comparison, quiet unused arg warnings 2022-01-07 14:47:27 +11:00
f48164b5ea Cleanup: rename sculpt_brushes.c -> sculpt_brush_types.c
This better differentiates sculpt brush types with brush data-blocks,
since the same sculpt brush type may be used for many brushes.
2022-01-07 14:28:49 +11:00
3d3bc74884 Cleanup: remove redundant const qualifiers for POD types
MSVC used to warn about const mismatch for arguments passed by value.
Remove these as newer versions of MSVC no longer show this warning.
2022-01-07 14:16:26 +11:00
bb69c19f08 Cleanup: Fix spelling in filename 2022-01-06 20:51:23 -05:00
e6ca0b33e9 Cleanup: Add bf_nodes_texture library
For sake of consistencey with other node tree types, create its own cmake module.
This change helps keep `bf_nodes` focused on  generic nodes files.

Texture nodes are end of life and hopefully for Blender 4.0 they can be removed.
It is not expected that these will see the updates that the other nodes are getting.
This change also helps isolate the end of life files, we may move some texture
specific node tree execution code out of `node_exec` and into a `node_texture_exec` files.

Differential Revision: https://developer.blender.org/D13743
2022-01-06 18:21:01 -05:00
ed9b21098d Cleanup: Use new socket builder API
This commit converts most shader or bsdf nodes.
2022-01-06 17:57:30 -05:00
3ae664363d Fix T94635: Sculpt Smooth in Surface mode with Anchored Stroke crash
Sculpt Smooth in Surface mode (as opposed to Laplacian) needs a cache
initialized on first time. In anchored stroke mode with spherical falloff
this was skipped though (because this starts of with no PBVH nodes and
an early return checks for this) and `first_time` was set to false before
cache initialization.

Now move the cache initalization to happen earlier (same as the cache
initialization for automasking).

Maniphest Tasks: T94635

Differential Revision: https://developer.blender.org/D13746
2022-01-06 20:55:43 +01:00
3a4952e7c2 Fix Cycles updating display unnecessarily when stopping 3D viewport
Debug code accidentally committed in 466b50d. This was found while
investigating issues with D13385.
2022-01-06 19:10:50 +01:00
0c6b29ee43 Fix T94672: incorrect Workbench shadows with GPU subdivision
The `lines_adjacency` IBO build in the GPU subdivision case was missing
edges at the boundaries of open meshes. As it is used for the shadow
pass, the shadows were then not clipped properly.

This would also make X-Ray mode render differently in those cases.

To fix this, we can simply reuse the buffer finalization routine from the
non-subdivision case, as such edges are handled there.
2022-01-06 16:25:09 +01:00
c2089ae53c GPU subdiv: fix wrong data sizes used for lines adjacency IBO
Function parameters were mismatched, causing an assertion failure in
debug builds.
2022-01-06 16:24:52 +01:00
ddae2d88fa Depsgraph: only link 'IK Constraint -> Init IK Tree' if animated.
This relation is intended to ensure that the properties of the IK
constraint are ready by the time the IK solver tree is built. This
however can cause spurious dependency cycles, because there is only
one init tree node for the whole armature, and the relation actually
implies dependency on all properties of the bone.

This patch reduces spurious dependencies by only creating the relation
if any properties of the IK constraint specifically are animated.

Differential Revision: https://developer.blender.org/D13714
2022-01-06 16:43:18 +03:00
1785286ecc Bone Overlay: support changing bone wireframe opacity.
When weight painting the bone overlay is extremely intrusive,
effectively requiring either extensive use of hiding individual
bones, or disabling the whole bone overlay between selections.

This addresses the issue by adding a bone opacity slider that
is used for the 'wireframe' armature drawing mode. It directly
controls the uniform opacity as a straightforward option.

Differential Revision: https://developer.blender.org/D11804
2022-01-06 16:43:18 +03:00
7bcf21e66e Depsgraph: fix spurious cycles with identically named idprops on bones.
If multiple bones have a custom property with the same name,
depsgraph didn't distinguish between them, potentially leading
to spurious cycles.

This patch moves ID_PROPERTY operation nodes for bone custom
properties from the parameters component to individual bone
components, thus decoupling them.

Differential Revision: https://developer.blender.org/D13729
2022-01-06 16:43:18 +03:00
08aa7861d6 Fix T94685: python error adding Space handlers for Spreadsheet
Oversight in {rB9cb5f0a2282a}.

Above commit made an entry in `rna_Space_refine()`, but the entry in
`rna_Space_refine_reverse()` was missing (and this is what python uses
for the Space callbacks).

Maniphest Tasks: T94685

Differential Revision: https://developer.blender.org/D13751
2022-01-06 13:47:35 +01:00
45277d804e Cleanup: use correct file namespace name 2022-01-06 13:25:42 +01:00
d31b8c316f Cleanup: typos in code. 2022-01-06 11:48:44 +01:00
88e15ff1e6 Fix T94674: crash reading ORCOs from an Alembic animation
The crash is caused as the data is only for the first frame, but the mesh
changes topology, so reading the data in subsequent frames causes a
buffer overflow. To fix this, we check that the data size matches the
mesh's vertex count.
2022-01-06 11:48:44 +01:00
ed3fecae8e Cleanup: USD/ABC, remove const from pass-by-value params
Remove `const` from pass-by-value parameters in function declarations.
The variables passed as parameters can never be modified by the function
anyway, so declaring them as `const` is meaningless. Having the
declaration there could confuse, especially as it suggests it does have
a meaning, training people to write meaningless code.
2022-01-06 11:41:03 +01:00
f9aa6376f1 Cleanup: anim, remove const declarations from pass-by-value params
Remove `const` from pass-by-value parameters in function declarations.
The variables passed as parameters can never be modified by the function
anyway, so declaring them as `const` is meaningless. Having the
declaration there could confuse, especially as it suggests it does have
a meaning, training people to write meaningless code.
2022-01-06 11:41:03 +01:00
1484fe260b Cleanup: Replace FINISHED with CANCELLED
As the operator does nothing, better use cancelled.
2022-01-06 10:22:32 +01:00
e766dc9189 Fix (unreported) crash in liboverride after yesterday's commit.
Own mistake in rBbfb760e16acb.
2022-01-06 10:01:07 +01:00
6f389f1bb8 Cleanup: move public doc-strings into headers
Some recent changes re-introduced public-style doc-strings
in the source file.
2022-01-06 19:25:24 +11:00
c12607baa3 Cleanup: quiet GCC stringop-overflow in bmesh_beautify.c
Also elaborate on the doc-string.
2022-01-06 13:54:56 +11:00
66a4da87f4 Cleanup: sort cmake file lists 2022-01-06 13:54:55 +11:00
ed68e18c1c Cleanup: remove unnecessary slashes and quotes from paths in CMake 2022-01-06 13:54:54 +11:00
2ee37e9031 Cleanup: remove redundant/unused assignment
SRC was being assigned invalid values then overwritten.
2022-01-06 13:54:53 +11:00
499fec6f79 Cleanup: spelling in comments 2022-01-06 13:54:52 +11:00
aa363ec2ae Cleanup: remove declaration for removed function 2022-01-06 13:54:51 +11:00
61e2384b7a Cleanup: compiler warnings 2022-01-06 13:54:49 +11:00
60757f010a CMake: add missing headers 2022-01-06 13:54:48 +11:00
0e53ea4cb5 Correct error when moving doc-strings into header
Error in ffc4c126f5,
which moved doc-strings from implementation into headers.

Some changes in BKE_animsys.h needed to done manually as there
were already doc-strings in both the header and implementation
(with overlapping information).
When making these changes some doc-strings were removed unintentionally.

Thanks for @sybren for the heads up.
2022-01-06 13:54:46 +11:00
4067367b6c Cleanup: Clang-tidy: modernize-redundant-void-arg 2022-01-05 21:44:22 -05:00
c0fb8ea8f3 Cleanup: Spelling/grammar in comments 2022-01-05 19:03:05 -06:00
1d9bac7d92 Cleanup: Use snake case for file names
This is so that we can have "proper" file namespace names in D13466
2022-01-05 17:15:13 -05:00
0e1da8dd12 In obj exporter test, fix a strncpy length and a stray test file left behind. 2022-01-05 17:05:53 -05:00
e55a6bf82b Cleanup: Remove empty node socket template array 2022-01-05 16:45:41 -05:00
c240ab70ae Cleanup: Use new socket builder API
Instead of looping through the old socket template array
looper through the node output listbase.
2022-01-05 16:27:29 -05:00
7c013f1154 Fix: MSVC build error
MSVC2017 and early 2019 versions are under
the impression struct OGLRender is non trivial
type due to the ThreadCondition field, not
entirely sure why, but it is what it is.

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

Reviewed by: JacquesLucke
2022-01-05 14:02:07 -07:00
611da3b7d6 Cleanup: Use new socket builder API 2022-01-05 15:47:15 -05:00
50f694c7de Cleanup: Use new socket builder API
Also enables translation of socket names
2022-01-05 15:47:15 -05:00
a5b4373f95 Fix/workaround macOS Rosetta crash running Cycles AVX tests
Just disable these tests on macOS for now as fixing seems hard, and we want to
be able to cross-compile and test x86_64 on Arm machines on the buildbot.
2022-01-05 21:21:13 +01:00
cdd61bb6d7 Fix Cycles AVX test failure with x86_64 build running on Arm
Don't create const avx vectors before validating if CPU supports AVX.
2022-01-05 20:05:16 +01:00
f7a0f6a0e4 Fix T94563: Cycles standalone build error on with strict float/double casting
Thanks to John David for finding this.
2022-01-05 20:05:16 +01:00
1dc0bf86bb Fix T93695: Discontinuous cutting with the knife tool
An important check to reject edge linehits when a vertex of that edge
was already hit was accidentally removed in
rB6e77afe6ec7b6a73f218f1fef264758abcbc778a
2022-01-05 18:32:23 +00:00
a0edee712a Cleanup: Remove unused node_type_exec for shader node
From what I can tell these are left over from Blender Internal render.

Test still pass locally, also tested a couple eevee scenes.

Reviewed By: JacquesLucke, brecht

Differential Revision: https://developer.blender.org/D13732
2022-01-05 11:52:57 -05:00
8cd6d0fe68 Fix T94169: Missing grease pencil render with tiled rendering
Delay grease pencil for until after the render result is written
to the Blender side.

Differential Revision: https://developer.blender.org/D13740
2022-01-05 17:47:10 +01:00
3c04b44913 Fix Cycles allocating result too early
When tiled rendering was used the render result was
allocated at the end of every view layer render as
opposite of an intended end of all rendering.

Modify the render_result_end so that it only ensures
pixels are allocated if pixels are actually copied
over.
2022-01-05 17:47:10 +01:00
5e7e571b0d Fix Cycles using Cancel semantic on final result write
Seems like a copy-paste bug from another place.
2022-01-05 17:47:10 +01:00
bfb760e16a Fix T94650: LibOverride: Bad handling of (auto)resync in case of single override.
Overrides that are not created as part of an override hierarchy should
not be handled through (auto)resync at all. users are responsible to
hanlde those updates if they need it.

This is achieved by flagging overrides created outside of a hierarchical
process accordingly, and skipping them during resync process.
2022-01-05 17:30:22 +01:00
1403f034ff LibOverride: Cleanup some code.
No functional change.
2022-01-05 17:30:22 +01:00
b63f375775 Assets: disable automatic preview generation for node groups
The current preview generation is more confusing than useful.
Therefore it is better to disable it until better preview generation
methods are found.

Differential Revision: https://developer.blender.org/D13728
2022-01-05 17:01:52 +01:00
3e92b4ed24 Fix T94659: crash when deleting instances
The crash was caused by using `modify_geometry_sets` to modify
instances, which does not generally work unfortunately.
The intended behavior was wrong anyway. In instances mode,
only top level instances should be deleted.

Also removed the old error handling because it doesn't look like it
ever worked. all_is_error remained false all the time.
Furthermore, updating it was not thread safe.

Differential Revision: https://developer.blender.org/D13736
2022-01-05 16:55:09 +01:00
Aleksi Juvani
5dedb39d44 Fix T54488: hair disconnect/reconnect not working with modifiers
Take the Use Modifier Stack setting into account when connecting hair, and
fix wrong results results when using deforming modifiers also.

Differential Revision: https://developer.blender.org/D13704
2022-01-05 16:53:54 +01:00
1031638c51 Cleanup: rename mesh -> geom in some places that now handle multiple geom types 2022-01-05 16:06:34 +01:00
f64d7bfa4a Cleanup: compiler warnings about unused code 2022-01-05 16:06:23 +01:00
8393ccd076 Cycles: Add OptiX temporal denoising support
Enables the `bpy.ops.cycles.denoise_animation()` operator again and modifies it to support
temporal denoising with OptiX. This requires renders that were done with both the "Vector"
and "Denoising Data" passes.

Differential Revision: https://developer.blender.org/D11442
2022-01-05 15:58:36 +01:00
86141a75eb Cleanup: fix typos in source code in intern/
Contributed by luzpaz.

Differential Revision: https://developer.blender.org/D13532
2022-01-05 15:35:30 +01:00
29ab711efa Cleanup: Remove unused code (USE_COLOR_U32) 2022-01-05 15:00:07 +01:00
4c3f52e7dc Cycles: support rendering PointCloud motion blur from attribute
This adds support to render PointCloud motion blur from a standard
"velocity" attribute.

This implementation is similar to that of the Mesh geometry, and
perhaps some code could be deduplicated through a more generic API.
`mesh_need_motion_attribute` was renamed `object_need_motion_attribute`
as it does not really require a mesh and moved to `util.h` so that
it can be shared.

This fixes T94622.

Reviewed By: brecht

Maniphest Tasks: T94622

Differential Revision: https://developer.blender.org/D13719
2022-01-05 14:17:57 +01:00
b1bd0f8ffd Enable OpenEXR DWAB compresstion
The DWAB compression was disabled in the d59721c2c3 due to
a bug in the OpenEXR library which is now resolved.

Re-enable the DWAB compression for OpenEXR output. It is a
simple change, and DWAB often behaves better than DWAA.

Differential Revision: https://developer.blender.org/D13713
2022-01-05 14:07:21 +01:00
13e7065dd2 Fix T94564: Mirror clipping is not properly placed in sculpt mode
If a mirror object is used in a mirror modifier, sculptmode did not take
this into account (and instead always clipped on the sculpt objects
local axis).

Now take this into account by storing a matrix in the preparation
function `sculpt_init_mirror_clipping` and use that later in
`SCULPT_clip`.

Maniphest Tasks: T94564

Differential Revision: https://developer.blender.org/D13711
2022-01-05 13:23:37 +01:00
924d2b8df6 Fix T94506: Crash in Compositing 2022-01-05 12:31:37 +01:00
d960c78693 Fix T94545: support realizing instanced collections
This case wasn't handled in rBf5ce243a56a22d718 correctly.
Now `object_get_evaluated_geometry_set` just returns a geometry
set that contains the collection instance for collection instance objects.
2022-01-05 11:47:09 +01:00
33400ffcc9 IDManagement: Add assert against no-main IDs passed to BKE_id_delete.
This high-level function can only deal with IDs in main, trying to use
it to delete/free a no-main ID does nothing.
2022-01-05 10:39:09 +01:00
5df916f23f Fix T94366: Grease Pencil Automerge no immediate UI update
Just an oversight in rBe9607f45d85d.
Now add notifier that toolsettings changed.

Maniphest Tasks: T94366

Differential Revision: https://developer.blender.org/D13723
2022-01-05 09:13:52 +01:00
b7073fa797 Cleanup: Use new socket builder API 2022-01-05 00:59:18 -05:00
458be2ecc4 Nodes: Consistent link drag search for math and vector math nodes
Previously operations for the math node when connecting to
outputs weren't added. It also used a different method to
check whether the link would be valid.
2022-01-04 23:19:12 -06:00
5336fdc6e3 Cleanup: Make shade node util header CPP only
Now that all shader nodes are converted to CPP
this header can now be made into a CPP header.
2022-01-04 23:25:27 -05:00
713d59bcaf Fix T89587: Don't Change Line Width For Previews
Do not temporarily change U.pixelsize while creating object previews
in object_preview_render. It does nothing to the render, but the change
in line width can affect other UI drawing since it is done in a thread.

see D13717 for for details.

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

Reviewed by Julian Eisel
2022-01-04 15:51:18 -08:00
e3748d7fa5 Fix T94145: Knife tool fails in orthographic mode
Calculating min and max orthographic extent forgot to convert to
worldspace coordinates.
2022-01-04 20:26:09 +00:00
07de17ded6 Cleanup: Dont use relative include
Instead let cmake determine the path for file includes
2022-01-04 11:58:21 -05:00
Aaron Carlisle
25018dc061 Cleanup: Nodes: Convert generic shader node files to c++
Along with the general changes to CPP this commit does the following

- Use static casts where possible
- Use new CPP MEM library functions instead of cast
- Use listbase macros where possible
- Declare variables where initialized

Reviewed By: HooglyBoogly, JacquesLucke

Differential Revision: https://developer.blender.org/D13718
2022-01-04 11:42:40 -05:00
f7c0287278 Fix: Link drag search error with random value node from color socket
Dragging from a color socket would hit an assert in a debug build.
The node does not have a color mode currently, so use the vector mode
instead when connecting to a color socket.
2022-01-04 10:32:32 -06:00
55842b4244 Fix T94620: GPencil AutoMerge does not work when Draw On Back is enabled
The problem was the stroke was added to head and the `prev` pointer was NULL. Now check if there is the list is empty`next`.
2022-01-04 17:08:05 +01:00
ad8e2d6661 Fix T94308: Window Manager console error 2022-01-04 17:00:05 +01:00
bbd0c4118b Fix: Build issue with MSVC
std::min was used without including the algorithm
header. Seems to be implicitly included by
something in newer MSVC versions and GCC, however
vs16.4 needed a little help here.
2022-01-04 07:15:51 -07:00
54e2f851a4 Cleanup: Code formatting. 2022-01-04 14:07:27 +01:00
070948b5f1 Fix T94546: Remove soft limit for the Clamp Node value socket. 2022-01-04 12:26:16 +01:00
f7018f7b06 Fix T94544: crash removing image used as camera background via python
Since 2.8, background images are tied to cameras (in 2.79 these were
tied to a View3D I think).
Code in `BKE_library_id_can_use_idtype` wasnt taking this relation
between `Camera` and `Image` into account, thus leading to ID deletion/
unlinking not working properly -- in particular `libblock_remap_data`
not doing its thing (and leaving the camera as a user of the image),
then things went downhill from there...

Now make the "Camera-can-use-an-Image" relation clear in
`BKE_library_id_can_use_idtype`.

Maniphest Tasks: T94544

Differential Revision: https://developer.blender.org/D13722
2022-01-04 12:13:05 +01:00
b2867d4365 Fix T94599: Assert on usercount when deleting image created via operator.
`IMAGE_OT_new` operator would not properly clear the by-default one user
generated by 'new id' code, in case it could not tie the image to
anything.
2022-01-04 10:03:31 +01:00
Manuel Castilla
a2a02e3994 Fix T90830: Crop node cropping is one pixel short
Currently the crop higher limits are inclusive too which contradicts
the documentation as it says that if Left and Right are both 50, it
will result in a zero-sized image. And the result is one pixel out of
the crop gizmo, which is another hint that this is not intended.

In "Full Frame" experimental mode it's two pixels short because of
a misuse of `BLI_rcti_isect_pt` as it considers max limits inclusive.

Reviewed By: jbakker

Maniphest Tasks: T90830

Differential Revision: https://developer.blender.org/D12786
2022-01-04 08:22:37 +01:00
Aidan Davey
325beef7af Fix T91160 - Movie Clip Editor - frame indicator/controller is not displayed
The frame indicator/controller is not displayed when in the Graph or Dopesheet view of the Movie Clip Editor

To solve this we could call the function ED_time_scrub_draw_current_frame in clip_draw_dopesheet_main and graph_region_draw in space_clip.c

Reviewed By: jbakker

Maniphest Tasks: T91160

Differential Revision: https://developer.blender.org/D12659
2022-01-04 08:21:13 +01:00
Aaron Carlisle
7af01de802 Shader Nodes: Unity Build
Enable unity builds for  `bf_nodes_shader`, gives about a 2.7x speedup
of total compile times when just building `bf_nodes_shader`.
On my machine, this equates to saving about 30 seconds.

Differential Revision: https://developer.blender.org/D13720
2022-01-03 23:10:36 -05:00
a9e0caa92d Cleanup: Move node storage macro inside file namespace
Must have been a mistake in previous commits,
this fix is needed to enable unity builds.
2022-01-03 21:52:20 -05:00
d2cc672b0c Fix soft light blend mode math
Function `blend_color_softlight_float` used math different to compositor and
produced result that had abrupt value changes.

Use math based on modified screen blend mode as compositor does.
2022-01-04 02:11:38 +01:00
9c85acf61d Fix out of range color in blend modes
Result of Exclusion and Pin Light blend modes could be greater than 255
which caused artifacts. Limit color value to 0-255 range.
2022-01-04 02:11:38 +01:00
Aaron Carlisle
d3ad04172d Cleanup: Remove bNodeType flag from base registration functions
This flag is only used a few small cases, so instead
of setting the flag for every node only set the
required flag for the nodes that require it.

Mostly the flag is used to set `ntype.flag = NODE_PREVIEW`
For nodes that should have previews by default which
is only some compositor nodes and some texture nodes.

The frame node also sets the `NODE_BACKGROUND` flag.

All other nodes were setting a flag of 0 which has no purpose.

Reviewed By: JacquesLucke

Differential Revision: https://developer.blender.org/D13699
2022-01-03 19:33:14 -05:00
9793bc30ce BLI: Add slice method to MutableSpan
Span had a slice method with an IndexRange argument, but MutableSpan
did not, yet. This commit makes the two types consistent.
2022-01-03 16:27:13 -06:00
675d3cdd69 Cleanup: Clang tidy 2022-01-03 13:52:55 -06:00
4e44cfa3d9 Add a new C++ version of an exporter for the Wavefront .obj format.
This was originally written by Ankit Meel as a GSoC 2020 project.
Howard Trickey added some tests and made some corrections/modifications.
See D13046 for more details.

This commit inserts a new menu item into the export menu called
"Wavefront OBJ (.obj) - New".
For now the old Python exporter remains in the menu, along with
the Python importer, but we plan to remove it soon (leaving the
old addon bundled with Blender but not enabled by default).
2022-01-03 14:49:31 -05:00
c6069c439c Fix T94581: Incorrect geometry delete behavior with instances
Compare the start of the range to zero to figure out whether the
indices for the instances to keep starts at zero. Also rename the
selection argument, since it made it seem like the selected indices
should be removed rather than kept.
2022-01-03 13:19:04 -06:00
a42e972e1b Fix T94316: Asset catalog tree scrolls away when renaming a catalog
The activation of the text button is a bit special, since it happens during
drawing, the layout isn't computed yet then. Comparable cases where the button
is added on top don't use the layout system, so this didn't become an issue
until now. Trigger a delayed call to `UI_but_ensure_in_view()`.
2022-01-03 19:55:49 +01:00
1b9e103a30 Fix T94594: Incorrect spreadsheet data set region type in old files
This completes 1a721c5dbe by versioning old files to correct the
region type. The "tools" region type is relatively standard for this type
of region and doesn't require any changes to the theme, unlike
the "nav bar" type, which would have been a reasonable choice.
2022-01-03 12:54:40 -06:00
b7ad58b945 Geometry Nodes: Edge Angle Node
Calculates the angle in radians between two faces that meet at an edge.
0 to PI in either direction with flat being 0 and folded over on itself PI.
If there are not 2 faces on the edge, the angle will be 0.

For valid edges, the angle is the same as the 'edge angle' overlay.

For the Face and Point domain, the node uses simple interpolation to calculate a value.

Differential Revision: https://developer.blender.org/D13366
2022-01-03 11:16:50 -06:00
ca143fafa6 Cleanup: Silence "integer conversion resulted in a change of sign" warning in Cycles kernel code
Occured because "PATH_RAY_SHADOW_CATCHER_BACKGROUND" is expressed as an unsigned
integer, because too large for a signed integer, but the "PathRayFlag" enum type defaulted to a
signed integer still.
2022-01-03 16:28:44 +01:00
8f9f65bc29 Allow overrides for cloth, collision and force field properties.
Allow overriding simple properties of cloth simulations, colliders
and force fields. Vertex group and shape key selectors in cloth are
still not overridable since they are tied to mesh data.

Force fields have a number of physical fields shared between multiple
RNA fields. Until they are decoupled, they will produce redundant
overrides, and cannot have different hard range limits.

Differential Revision: https://developer.blender.org/D13710
2022-01-03 18:06:13 +03:00
8189471912 Fix T94392: 3D Cursor surface projection onto hidden geometry
Regression introduced in rB098008f42d8127d9b60717c7059d3c55a3bfada7

Previously the selected geometry was ignored along with the hidden one.

The mentioned commit caused neither the hidden nor the selected one to be ignored.

But hidden geometry needs to be ignored.
2022-01-03 11:52:02 -03:00
a230445cae Depsgraph: Remove object-level visibility from geometry builders
Continuation of the D13404 which finished the design of not having
geometry-level nodes dependent on object-level.

Differential Revision: https://developer.blender.org/D13405
2022-01-03 15:30:14 +01:00
a3e634d4d7 Cleanup: Unused variable in Cycles code 2022-01-03 14:46:10 +01:00
6a4ee3fd56 Fix (unreported) i18n utils failing to create MO files in trunk.
Not really important anymore, since those are not used by Blender, but
better be consistent.
2022-01-03 11:48:24 +01:00
e51864a357 Add Georgian to our list of languages.
CC @Tamuna who started the translation for this language.
2022-01-03 11:13:15 +01:00
0a4bd32e59 Blender font: Add georgian script.
Weirdly enough, our 'mono' font already had it, but not the main one.

Copied from DeJaVu sans font.

CC @Tamuna who started the translation for that language.
2022-01-03 11:12:55 +01:00
add4aa7d25 Install_deps: Also cleanup CLANG CMAKE variables
Needed together with LLVM cleanup, otherwise things fail when LLVM gets
updated.
2022-01-03 10:39:37 +01:00
2e00d90938 Cleanup: Renamed to_object_value to to_dictionary_value. 2022-01-03 10:25:16 +01:00
e2fdc6226a Cleanup: rename ValueType.Object to ValueType.Dictionary. 2022-01-03 10:23:09 +01:00
ea8d749587 Cleanup: Rename ObjectValue to DictionaryValue (Serialization).
ObjectValue was to confusing as it is the term from JSON.
2022-01-03 08:10:21 +01:00
180b66ae8a UDIM: Support virtual filenames
This implements the design detailed in T92696 to support virtual
filenames for UDIM textures. Currently, the following 2 substitution
tokens are supported:

| Token | Meaning |
| ----- | ---- |
| <UDIM>   | 1001 + u-tile + v-tile * 10 |
| <UVTILE> | Equivalent to u<u-tile + 1>_v<v-tile + 1> |

Example for u-tile of 3 and v-tile of 1:
filename.<UDIM>_ver0023.png   --> filename.1014_ver0023.png
filename.<UVTILE>_ver0023.png --> filename.u4_v2_ver0023.png

For image loading, the existing workflow is unchanged. A user can select
one or more image files, belonging to one or more UDIM tile sets, and
have Blender load them all as it does today. Now the <UVTILE> format is
"guessed" just as the <UDIM> format was guessed before.

If guessing fails, the user can simply go into the Image Editor and type
the proper substitution in the filename. Once typing is complete,
Blender will reload the files and correctly fill the tiles. This
workflow is new as attempting to fix the guessing in current versions
did not really work, and the user was often stuck with a confusing
situation.

For image saving, the existing workflow is changed slightly. Currently,
when saving, a user has to be sure to type the filename of the first
tile (e.g. filename.1001.png) to save the entire UDIM set. The number
could differ if they start at a different tile etc. This is confusing.
Now, the user should type a filename containing the appropriate
substitution token. By default Blender will fill in a default name using
the <UDIM> token but the user is free to save out images using <UVTILE>
if they wish.

Differential Revision: https://developer.blender.org/D13057
2022-01-02 20:48:59 -08:00
Aaron Carlisle
367fc69dc1 Nodes: Convert several shader nodes to c++
Also add file namespace

This is needed to use new node APIs

Differential Revision: https://developer.blender.org/D13690
2022-01-02 23:35:20 -05:00
8be217ada5 Geometry Nodes: add field node type for constants
It is common to have fields that contain a constant value. Before this
commit, such constants were represented by operation nodes which
don't have inputs. Having a special node type for constants makes
working with them a bit cheaper.

It also allows skipping some unnecessary processing when evaluating
fields, because constant fields can be detected more easily.

This commit also generalizes the concept of field node types a bit.
2022-01-02 14:27:16 +01:00
4c46203cb5 Geometry Nodes: small refactor towards supporting partially lazy nodes
Currently, a node either supports lazyness during execution (like the Switch
node), or it doesn't. If it does support lazyness, then every input is computed
lazily. However, usually not all inputs actually have to be computed lazily.
E.g. the boolean switch input is always required, while the other inputs
should be computed lazily.

Better support for such sockets  can avoid unnecessary round trips through
the node execution function.
2022-01-01 12:50:48 +01:00
Charlie Jolly
6844304dda Nodes: Add Compare node operations to link drag search menu
Exposes compare operations via rna emums.
This uses the rna enum to build the search list using
named operations linked to socket A.
This also weights the Math Node comparison operations lower
for geometry node trees.

Differential Revision: https://developer.blender.org/D13695
2021-12-31 20:32:42 +00:00
e79b4523b4 LineArt: Correct collection intersection mask logic.
The logic used to be:

"if collection doesn't have child collection, check if ob is from this one"

The correct logic should be:

"if collection child does not have this ob, then check this collection".
2021-12-31 21:54:07 +08:00
97ae08c9fc LineArt: Correct clamping of out of bound isect index
Handles rare cases where line doesn't intersect the triangle correctly.
2021-12-31 21:26:39 +08:00
d09b1d2759 Fix T94464: video texture is not refreshing
In the past that worked because the `GPUMaterial` referenced the
`ImageUser` from the image node. However, that design was incompatible
with the recent node tree update refactor (rB7e712b2d6a0d257d272e).
Also, in general it is a bad idea to have references between data that is
owned by two different data blocks.

This incompatibility was resolved by copying the image user from the node
to the `GPUMaterial` (rB28df0107d4a8). Unfortunately, eevee depended
on this reference, because the image user on the node was update when the
frame changed. Because the image user was copied, the image user in the
`GPUMaterial` did not receive the frame update anymore.

This frame update is added back by this commit. The main change is that
the image user iterator now also iterates over image users in `GPUMaterial`s
on material and world data blocks. An issue is that these materials don't
exist on the original data blocks and that caused the check in
`build_animation_images` in the depsgraph to give the wrong answer.
Therefore the check is extended.

Right now the check is not optimal, because it results in more depsgraph
nodes than are necessary. This can be improved when it becomes cheaper
to check if a node tree contains any references to a video texture.
The node tree update refactor mentioned before makes it much easier
to construct this kind of run-time data from the bottom up, instead of
scanning the entire node tree recursively every time some information
is needed.
2021-12-31 14:24:11 +01:00
56344fb30f Cleanup: Silence warning for wrong const char comparison
Incorrectly used comparison for empty string.

Reported in chat by @jacqueslucke.
2021-12-31 13:05:58 +00:00
018272ee5b Fix T94416: incorrect handling when nodes are linked in a loop
This just skips the entire algorithm when there are cycles.
In the future, cycles could be handled more gracefully in the
algorithm, but for now that's not worth it and is not necessary
to fix the bug.
2021-12-31 11:33:47 +01:00
Charlie Jolly
71468f475b Nodes: Weight drag link search for Math nodes
As @hooglyboogly suggested in D13680, this patch adds weighting
to the search results. Dragging from a vector/rgba socket weights
the Vector Math node higher than a float Math node, and vice versa.

Reviewed By: HooglyBoogly

Differential Revision: https://developer.blender.org/D13691
2021-12-31 02:34:23 +00:00
0aa7315608 Fix (unreported): remove menu separators from drag link search
Search was picking up the menu separator entries.
Add check for these which are defined by empty identifier strings.
2021-12-31 01:15:00 +00:00
bf4358ed0c Cleanup: Use switch to get gpu shader name
Rather than using the array syntax that doesnt work in C++,
use a switch state which is also much easier to read.
2021-12-30 17:39:23 -05:00
ee2b72fd29 Nodes: Convert several shader nodes to c++
Also add file namespace

This is needed to use new node APIs

Differential Revision: https://developer.blender.org/D13690
2021-12-30 12:42:12 -05:00
e0d1e66732 Fix T93868: GPencil material filter does not work with instances
When the material is used in several objects, the filter by material is not working as expected because the internal pointers are different due eval version.

Now, the original version of the material is compared to keep same address.
2021-12-30 12:48:51 +01:00
Shen Ciao
52da1afbf6 Fix T93134: Set origin broken for curve edit mode
Bug: Set Origin causes unexpected offset on Grease Pencil strokes when Curve Editing is enabled.
Fix: Add transformation of editcurve points in `object_origin_set_exec`.

Reviewed By: #grease_pencil, antoniov

Maniphest Tasks: T93134

Differential Revision: https://developer.blender.org/D13273
2021-12-30 11:29:09 +01:00
49a18cc91e Fix T93163: GPencil scale thickness fails in negative scales
Before the negative scales produced a thickness invalid. Now, the value is used in absolute value to avoid this situation.
2021-12-30 11:18:05 +01:00
0b73b2c6cf Nodes: Improve link drag search for Math and Vector Math nodes
Exposes math operations via rna emums.

This uses the rna enum to build the search list.

Differential Revision: https://developer.blender.org/D13680
2021-12-30 01:22:10 +00:00
6d7dbdbb44 Point Cloud: Optimize bounding box calculation
This is analagous to 6a71b2af66 which did the same
thing for mesh data. Two differences are that here the coordinates
are simply `float3`, and we account for the radius if it's available.
Here I observed a similar performance increase, from 50ms
average to 10ms average, with 16 million points, a 5x speedup.

The calculation is about 1.4 times faster when no radius is used, down
 to 7.3ms average. Before, the calculation was only 1.2 times faster.
2021-12-29 18:39:41 -06:00
9d3264b4fd Cleanup: clang-tidy modernize-redundant-void-arg 2021-12-29 18:51:10 -05:00
d3a31311b9 Nodes: Convert shader, texture category nodes to c++
Also add/correct file namespace

This is needed to use new node APIs

Differential Revision: https://developer.blender.org/D13688
2021-12-29 18:36:15 -05:00
c0fdf16561 Fix T94454: Python API curve to mesh use after free without depsgraph
This was caused by a mistake in eb0eb54d96, which removed
the clearing of the curve edit mode pointers that are set when creating
the temporary data for the conversion. If they are not cleared, the
generic ID free function will also free the edit mode data, which is
wrong when the source curve is in edit mode.
2021-12-29 16:53:02 -06:00
04ead39dae Modifiers: decrease maximum allocation size for Weld vertices
At the time of allocating the buffer with vertices in context, we don't
know exactly how many vertices are affected, but we do know that it is
less than or equal to twice the number of vertices killed.
2021-12-29 17:45:56 -03:00
1350 changed files with 19928 additions and 32727 deletions

View File

@@ -559,12 +559,14 @@ if(WIN32)
set(CPACK_INSTALL_PREFIX ${CMAKE_GENERIC_PROGRAM_FILES}/${})
endif()
# Compiler toolchain
if(CMAKE_COMPILER_IS_GNUCC)
option(WITH_LINKER_GOLD "Use ld.gold linker which is usually faster than ld.bfd" ON)
mark_as_advanced(WITH_LINKER_GOLD)
option(WITH_LINKER_LLD "Use ld.lld linker which is usually faster than ld.gold" OFF)
mark_as_advanced(WITH_LINKER_LLD)
# Compiler tool-chain.
if(UNIX AND NOT APPLE)
if(CMAKE_COMPILER_IS_GNUCC)
option(WITH_LINKER_GOLD "Use ld.gold linker which is usually faster than ld.bfd" ON)
mark_as_advanced(WITH_LINKER_GOLD)
option(WITH_LINKER_LLD "Use ld.lld linker which is usually faster than ld.gold" OFF)
mark_as_advanced(WITH_LINKER_LLD)
endif()
endif()
option(WITH_COMPILER_ASAN "Build and link against address sanitizer (only for Debug & RelWithDebInfo targets)." OFF)

View File

@@ -38,13 +38,6 @@ elseif(UNIX AND NOT APPLE)
)
endif()
if(BLENDER_PLATFORM_ARM)
set(GMP_OPTIONS
${GMP_OPTIONS}
--disable-assembly
)
endif()
ExternalProject_Add(external_gmp
URL file://${PACKAGE_DIR}/${GMP_FILE}
DOWNLOAD_DIR ${DOWNLOAD_DIR}

View File

@@ -474,9 +474,9 @@ set(ISPC_HASH 2e3abedbc0ea9aaec17d6562c632454d)
set(ISPC_HASH_TYPE MD5)
set(ISPC_FILE ispc-${ISPC_VERSION}.tar.gz)
set(GMP_VERSION 6.2.0)
set(GMP_VERSION 6.2.1)
set(GMP_URI https://gmplib.org/download/gmp/gmp-${GMP_VERSION}.tar.xz)
set(GMP_HASH a325e3f09e6d91e62101e59f9bda3ec1)
set(GMP_HASH 0b82665c4a92fd2ade7440c13fcaa42b)
set(GMP_HASH_TYPE MD5)
set(GMP_FILE gmp-${GMP_VERSION}.tar.xz)

View File

@@ -3620,8 +3620,8 @@ compile_FFmpeg() {
fi
./configure --cc="gcc -Wl,--as-needed" \
--extra-ldflags="-pthread -static-libgcc" \
--prefix=$_inst --enable-static \
--extra-ldflags="-pthread" \
--prefix=$_inst --enable-shared \
--disable-ffplay --disable-doc \
--enable-gray \
--enable-avfilter --disable-vdpau \
@@ -5721,76 +5721,6 @@ install_OTHER() {
# ----------------------------------------------------------------------------
# Printing User Info
print_info_ffmpeglink_DEB() {
dpkg -L $_packages | grep -e ".*\/lib[^\/]\+\.so" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", gensub(/.*lib([^\/]+)\.so/, "\\1", "g", $0)); nlines++ }'
}
print_info_ffmpeglink_RPM() {
rpm -ql $_packages | grep -e ".*\/lib[^\/]\+\.so" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", gensub(/.*lib([^\/]+)\.so/, "\\1", "g", $0)); nlines++ }'
}
print_info_ffmpeglink_ARCH() {
pacman -Ql $_packages | grep -e ".*\/lib[^\/]\+\.so$" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", gensub(/.*lib([^\/]+)\.so/, "\\1", "g", $0)); nlines++ }'
}
print_info_ffmpeglink() {
# This func must only print a ';'-separated list of libs...
if [ -z "$DISTRO" ]; then
ERROR "Failed to detect distribution type"
exit 1
fi
# Create list of packages from which to get libs names...
_packages=""
if [ "$THEORA_USE" = true ]; then
_packages="$_packages $THEORA_DEV"
fi
if [ "$VORBIS_USE" = true ]; then
_packages="$_packages $VORBIS_DEV"
fi
if [ "$OGG_USE" = true ]; then
_packages="$_packages $OGG_DEV"
fi
if [ "$XVID_USE" = true ]; then
_packages="$_packages $XVID_DEV"
fi
if [ "$VPX_USE" = true ]; then
_packages="$_packages $VPX_DEV"
fi
if [ "$OPUS_USE" = true ]; then
_packages="$_packages $OPUS_DEV"
fi
if [ "$MP3LAME_USE" = true ]; then
_packages="$_packages $MP3LAME_DEV"
fi
if [ "$X264_USE" = true ]; then
_packages="$_packages $X264_DEV"
fi
if [ "$OPENJPEG_USE" = true ]; then
_packages="$_packages $OPENJPEG_DEV"
fi
if [ "$DISTRO" = "DEB" ]; then
print_info_ffmpeglink_DEB
elif [ "$DISTRO" = "RPM" ]; then
print_info_ffmpeglink_RPM
elif [ "$DISTRO" = "ARCH" ]; then
print_info_ffmpeglink_ARCH
# XXX TODO!
else
PRINT "<Could not determine additional link libraries needed for ffmpeg, replace this by valid list of libs...>"
fi
}
print_info() {
PRINT ""
PRINT ""
@@ -5801,7 +5731,7 @@ print_info() {
PRINT "If you're using CMake add this to your configuration flags:"
_buildargs="-U *SNDFILE* -U PYTHON* -U *BOOST* -U *Boost* -U *TBB*"
_buildargs="$_buildargs -U *OPENCOLORIO* -U *OPENEXR* -U *OPENIMAGEIO* -U *LLVM* -U *CYCLES*"
_buildargs="$_buildargs -U *OPENCOLORIO* -U *OPENEXR* -U *OPENIMAGEIO* -U *LLVM* -U *CLANG* -U *CYCLES*"
_buildargs="$_buildargs -U *OPENSUBDIV* -U *OPENVDB* -U *BLOSC* -U *COLLADA* -U *FFMPEG* -U *ALEMBIC* -U *USD*"
_buildargs="$_buildargs -U *EMBREE* -U *OPENIMAGEDENOISE* -U *OPENXR*"
@@ -6002,12 +5932,10 @@ print_info() {
if [ "$FFMPEG_SKIP" = false ]; then
_1="-D WITH_CODEC_FFMPEG=ON"
_2="-D FFMPEG_LIBRARIES='avformat;avcodec;avutil;avdevice;swscale;swresample;lzma;rt;`print_info_ffmpeglink`'"
PRINT " $_1"
PRINT " $_2"
_buildargs="$_buildargs $_1 $_2"
_buildargs="$_buildargs $_1"
if [ -d $INST/ffmpeg ]; then
_1="-D FFMPEG=$INST/ffmpeg"
_1="-D FFMPEG_ROOT_DIR=$INST/ffmpeg"
PRINT " $_1"
_buildargs="$_buildargs $_1"
fi

View File

@@ -33,6 +33,8 @@ if(NOT FFMPEG_FIND_COMPONENTS)
avfilter
avformat
avutil
swscale
swresample
)
endif()
@@ -50,9 +52,9 @@ foreach(_component ${FFMPEG_FIND_COMPONENTS})
string(TOUPPER ${_component} _upper_COMPONENT)
find_library(FFMPEG_${_upper_COMPONENT}_LIBRARY
NAMES
${_upper_COMPONENT}
${_component}
HINTS
${LIBDIR}/ffmpeg
${_ffmpeg_SEARCH_DIRS}
PATH_SUFFIXES
lib64 lib
)

View File

@@ -21,7 +21,7 @@ ENDIF()
SET(_optix_SEARCH_DIRS
${OPTIX_ROOT_DIR}
"$ENV{PROGRAMDATA}/NVIDIA Corporation/OptiX SDK 7.0.0"
"$ENV{PROGRAMDATA}/NVIDIA Corporation/OptiX SDK 7.3.0"
)
FIND_PATH(OPTIX_INCLUDE_DIR

View File

@@ -114,7 +114,7 @@ def is_c_header(filename: str) -> bool:
def is_c(filename: str) -> bool:
ext = splitext(filename)[1]
return (ext in {".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl"})
return (ext in {".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl", ".metal"})
def is_c_any(filename: str) -> bool:

View File

@@ -488,7 +488,6 @@ function(blender_add_test_executable
include_directories(${includes})
include_directories(${includes_sys})
setup_libdirs()
BLENDER_SRC_GTEST_EX(
NAME ${name}
@@ -525,83 +524,6 @@ function(setup_heavy_lib_pool)
endif()
endfunction()
function(SETUP_LIBDIRS)
# NOTE: For all new libraries, use absolute library paths.
# This should eventually be phased out.
# APPLE platform uses full paths for linking libraries, and avoids link_directories.
if(NOT MSVC AND NOT APPLE)
link_directories(${JPEG_LIBPATH} ${PNG_LIBPATH} ${ZLIB_LIBPATH} ${FREETYPE_LIBPATH})
if(WITH_PYTHON) # AND NOT WITH_PYTHON_MODULE # WIN32 needs
link_directories(${PYTHON_LIBPATH})
endif()
if(WITH_SDL AND NOT WITH_SDL_DYNLOAD)
link_directories(${SDL_LIBPATH})
endif()
if(WITH_CODEC_FFMPEG)
link_directories(${FFMPEG_LIBPATH})
endif()
if(WITH_IMAGE_OPENEXR)
link_directories(${OPENEXR_LIBPATH})
endif()
if(WITH_IMAGE_TIFF)
link_directories(${TIFF_LIBPATH})
endif()
if(WITH_BOOST)
link_directories(${BOOST_LIBPATH})
endif()
if(WITH_OPENIMAGEIO)
link_directories(${OPENIMAGEIO_LIBPATH})
endif()
if(WITH_OPENIMAGEDENOISE)
link_directories(${OPENIMAGEDENOISE_LIBPATH})
endif()
if(WITH_OPENCOLORIO)
link_directories(${OPENCOLORIO_LIBPATH})
endif()
if(WITH_OPENVDB)
link_directories(${OPENVDB_LIBPATH})
endif()
if(WITH_OPENAL)
link_directories(${OPENAL_LIBPATH})
endif()
if(WITH_JACK AND NOT WITH_JACK_DYNLOAD)
link_directories(${JACK_LIBPATH})
endif()
if(WITH_PULSEAUDIO AND NOT WITH_PULSEAUDIO_DYNLOAD)
link_directories(${LIBPULSE_LIBPATH})
endif()
if(WITH_CODEC_SNDFILE)
link_directories(${LIBSNDFILE_LIBPATH})
endif()
if(WITH_FFTW3)
link_directories(${FFTW3_LIBPATH})
endif()
if(WITH_OPENCOLLADA)
link_directories(${OPENCOLLADA_LIBPATH})
# # Never set
# link_directories(${PCRE_LIBPATH})
# link_directories(${EXPAT_LIBPATH})
endif()
if(WITH_LLVM)
link_directories(${LLVM_LIBPATH})
endif()
if(WITH_ALEMBIC)
link_directories(${ALEMBIC_LIBPATH})
endif()
if(WITH_GMP)
link_directories(${GMP_LIBPATH})
endif()
if(WIN32 AND NOT UNIX)
link_directories(${PTHREADS_LIBPATH})
endif()
endif()
endfunction()
# Platform specific linker flags for targets.
function(setup_platform_linker_flags
target)
@@ -1292,29 +1214,6 @@ macro(openmp_delayload
endif()
endmacro()
macro(blender_precompile_headers target cpp header)
if(MSVC)
# get the name for the pch output file
get_filename_component(pchbase ${cpp} NAME_WE)
set(pchfinal "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${pchbase}.pch")
# mark the cpp as the one outputting the pch
set_property(SOURCE ${cpp} APPEND PROPERTY OBJECT_OUTPUTS "${pchfinal}")
# get all sources for the target
get_target_property(sources ${target} SOURCES)
# make all sources depend on the pch to enforce the build order
foreach(src ${sources})
set_property(SOURCE ${src} APPEND PROPERTY OBJECT_DEPENDS "${pchfinal}")
endforeach()
target_sources(${target} PRIVATE ${cpp} ${header})
set_target_properties(${target} PROPERTIES COMPILE_FLAGS "/Yu${header} /Fp${pchfinal} /FI${header}")
set_source_files_properties(${cpp} PROPERTIES COMPILE_FLAGS "/Yc${header} /Fp${pchfinal}")
endif()
endmacro()
macro(set_and_warn_dependency
_dependency _setting _val)
# when $_dependency is disabled, forces $_setting = $_val

View File

@@ -173,6 +173,7 @@ if(WITH_IMAGE_OPENEXR)
endif()
if(WITH_CODEC_FFMPEG)
set(FFMPEG_ROOT_DIR ${LIBDIR}/ffmpeg)
set(FFMPEG_FIND_COMPONENTS
avcodec avdevice avformat avutil
mp3lame ogg opus swresample swscale

View File

@@ -96,7 +96,7 @@ else()
# Detect SDK version to use.
if(NOT DEFINED OSX_SYSTEM)
execute_process(
COMMAND xcrun --show-sdk-version
COMMAND xcrun --sdk macosx --show-sdk-version
OUTPUT_VARIABLE OSX_SYSTEM
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()

View File

@@ -18,7 +18,7 @@
# All rights reserved.
# ***** END GPL LICENSE BLOCK *****
# Libraries configuration for any *nix system including Linux and Unix.
# Libraries configuration for any *nix system including Linux and Unix (excluding APPLE).
# Detect precompiled library directory
if(NOT DEFINED LIBDIR)
@@ -178,26 +178,30 @@ endif()
if(WITH_CODEC_FFMPEG)
if(EXISTS ${LIBDIR})
# For precompiled lib directory, all ffmpeg dependencies are in the same folder
file(GLOB ffmpeg_libs ${LIBDIR}/ffmpeg/lib/*.a ${LIBDIR}/sndfile/lib/*.a)
set(FFMPEG ${LIBDIR}/ffmpeg CACHE PATH "FFMPEG Directory")
set(FFMPEG_LIBRARIES ${ffmpeg_libs} ${ffmpeg_libs} CACHE STRING "FFMPEG Libraries")
else()
set(FFMPEG /usr CACHE PATH "FFMPEG Directory")
set(FFMPEG_LIBRARIES avformat avcodec avutil avdevice swscale CACHE STRING "FFMPEG Libraries")
set(FFMPEG_ROOT_DIR ${LIBDIR}/ffmpeg)
# Override FFMPEG components to also include static library dependencies
# included with precompiled libraries, and to ensure correct link order.
set(FFMPEG_FIND_COMPONENTS
avformat avcodec avdevice avutil swresample swscale
sndfile
FLAC
mp3lame
opus
theora theoradec theoraenc
vorbis vorbisenc vorbisfile ogg
vpx
x264
xvidcore)
elseif(FFMPEG)
# Old cache variable used for root dir, convert to new standard.
set(FFMPEG_ROOT_DIR ${FFMPEG})
endif()
find_package(FFmpeg)
mark_as_advanced(FFMPEG)
# lame, but until we have proper find module for ffmpeg
set(FFMPEG_INCLUDE_DIRS ${FFMPEG}/include)
if(EXISTS "${FFMPEG}/include/ffmpeg/")
list(APPEND FFMPEG_INCLUDE_DIRS "${FFMPEG}/include/ffmpeg")
if(NOT FFMPEG_FOUND)
set(WITH_CODEC_FFMPEG OFF)
message(STATUS "FFmpeg not found, disabling it")
endif()
# end lameness
mark_as_advanced(FFMPEG_LIBRARIES)
set(FFMPEG_LIBPATH ${FFMPEG}/lib)
endif()
if(WITH_FFTW3)

View File

@@ -51,9 +51,6 @@
/** \defgroup intern_mikktspace MikktSpace
* \ingroup intern */
/** \defgroup intern_numaapi NUMA (Non Uniform Memory Architecture)
* \ingroup intern */
/** \defgroup intern_rigidbody Rigid-Body C-API
* \ingroup intern */

View File

@@ -257,7 +257,7 @@ static int hipewHipInit(void) {
#endif
static int initialized = 0;
static int result = 0;
int error, driver_version;
int error;
if (initialized) {
return result;
@@ -565,8 +565,6 @@ int hipewCompilerVersion(void) {
const char *path = hipewCompilerPath();
const char *marker = "Hip compilation tools, release ";
FILE *pipe;
int major, minor;
char *versionstr;
char buf[128];
char output[65536] = "\0";
char command[65536] = "\0";

View File

@@ -25,7 +25,6 @@ add_subdirectory(ghost)
add_subdirectory(guardedalloc)
add_subdirectory(libmv)
add_subdirectory(memutil)
add_subdirectory(numaapi)
add_subdirectory(opencolorio)
add_subdirectory(opensubdiv)
add_subdirectory(mikktspace)

View File

@@ -51,8 +51,6 @@ list(APPEND LIBRARIES ${CYCLES_GL_LIBRARIES})
# Common configuration.
cycles_link_directories()
add_definitions(${GL_DEFINITIONS})
include_directories(${INC})

View File

@@ -82,7 +82,7 @@ static void session_print_status()
string status, substatus;
/* get status */
float progress = options.session->progress.get_progress();
double progress = options.session->progress.get_progress();
options.session->progress.get_status(status, substatus);
if (substatus != "")
@@ -183,7 +183,7 @@ static void display_info(Progress &progress)
progress.get_time(total_time, sample_time);
progress.get_status(status, substatus);
float progress_val = progress.get_progress();
double progress_val = progress.get_progress();
if (substatus != "")
status += ": " + substatus;

View File

@@ -60,9 +60,8 @@ def init():
path = os.path.dirname(__file__)
user_path = os.path.dirname(os.path.abspath(bpy.utils.user_resource('CONFIG', path='')))
temp_path = bpy.app.tempdir
_cycles.init(path, user_path, temp_path, bpy.app.background)
_cycles.init(path, user_path, bpy.app.background)
_parse_command_line()

View File

@@ -802,7 +802,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
name="Tile Size",
default=2048,
description="",
min=8, max=16384,
min=8, max=8192,
)
# Various fine-tuning debug flags

View File

@@ -272,12 +272,300 @@ uint BlenderDisplaySpaceShader::get_shader_program()
return shader_program_;
}
/* --------------------------------------------------------------------
* DrawTile.
*/
/* Higher level representation of a texture from the graphics library. */
class GLTexture {
public:
/* Global counter for all allocated OpenGL textures used by instances of this class. */
static inline std::atomic<int> num_used = 0;
GLTexture() = default;
~GLTexture()
{
assert(gl_id == 0);
}
GLTexture(const GLTexture &other) = delete;
GLTexture &operator=(GLTexture &other) = delete;
GLTexture(GLTexture &&other) noexcept
: gl_id(other.gl_id), width(other.width), height(other.height)
{
other.reset();
}
GLTexture &operator=(GLTexture &&other)
{
if (this == &other) {
return *this;
}
gl_id = other.gl_id;
width = other.width;
height = other.height;
other.reset();
return *this;
}
bool gl_resources_ensure()
{
if (gl_id) {
return true;
}
/* Create texture. */
glGenTextures(1, &gl_id);
if (!gl_id) {
LOG(ERROR) << "Error creating texture.";
return false;
}
/* Configure the texture. */
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, gl_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
/* Clamp to edge so that precision issues when zoomed out (which forces linear interpolation)
* does not cause unwanted repetition. */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_2D, 0);
++num_used;
return true;
}
void gl_resources_destroy()
{
if (!gl_id) {
return;
}
glDeleteTextures(1, &gl_id);
reset();
--num_used;
}
/* OpenGL resource IDs of the texture.
*
* NOTE: Allocated on the render engine's context. */
uint gl_id = 0;
/* Dimensions of the texture in pixels. */
int width = 0;
int height = 0;
protected:
void reset()
{
gl_id = 0;
width = 0;
height = 0;
}
};
/* Higher level representation of a Pixel Buffer Object (PBO) from the graphics library. */
class GLPixelBufferObject {
public:
/* Global counter for all allocated OpenGL PBOs used by instances of this class. */
static inline std::atomic<int> num_used = 0;
GLPixelBufferObject() = default;
~GLPixelBufferObject()
{
assert(gl_id == 0);
}
GLPixelBufferObject(const GLPixelBufferObject &other) = delete;
GLPixelBufferObject &operator=(GLPixelBufferObject &other) = delete;
GLPixelBufferObject(GLPixelBufferObject &&other) noexcept
: gl_id(other.gl_id), width(other.width), height(other.height)
{
other.reset();
}
GLPixelBufferObject &operator=(GLPixelBufferObject &&other)
{
if (this == &other) {
return *this;
}
gl_id = other.gl_id;
width = other.width;
height = other.height;
other.reset();
return *this;
}
bool gl_resources_ensure()
{
if (gl_id) {
return true;
}
glGenBuffers(1, &gl_id);
if (!gl_id) {
LOG(ERROR) << "Error creating texture pixel buffer object.";
return false;
}
++num_used;
return true;
}
void gl_resources_destroy()
{
if (!gl_id) {
return;
}
glDeleteBuffers(1, &gl_id);
reset();
--num_used;
}
/* OpenGL resource IDs of the PBO.
*
* NOTE: Allocated on the render engine's context. */
uint gl_id = 0;
/* Dimensions of the PBO. */
int width = 0;
int height = 0;
protected:
void reset()
{
gl_id = 0;
width = 0;
height = 0;
}
};
class DrawTile {
public:
DrawTile() = default;
~DrawTile() = default;
DrawTile(const DrawTile &other) = delete;
DrawTile &operator=(const DrawTile &other) = delete;
DrawTile(DrawTile &&other) noexcept = default;
DrawTile &operator=(DrawTile &&other) = default;
bool gl_resources_ensure()
{
if (!texture.gl_resources_ensure()) {
gl_resources_destroy();
return false;
}
if (!gl_vertex_buffer) {
glGenBuffers(1, &gl_vertex_buffer);
if (!gl_vertex_buffer) {
LOG(ERROR) << "Error allocating tile VBO.";
gl_resources_destroy();
return false;
}
}
return true;
}
void gl_resources_destroy()
{
texture.gl_resources_destroy();
if (gl_vertex_buffer) {
glDeleteBuffers(1, &gl_vertex_buffer);
gl_vertex_buffer = 0;
}
}
inline bool ready_to_draw() const
{
return texture.gl_id != 0;
}
/* Texture which contains pixels of the tile. */
GLTexture texture;
/* Display parameters the texture of this tile has been updated for. */
BlenderDisplayDriver::Params params;
/* OpenGL resources needed for drawing. */
uint gl_vertex_buffer = 0;
};
class DrawTileAndPBO {
public:
bool gl_resources_ensure()
{
if (!tile.gl_resources_ensure() || !buffer_object.gl_resources_ensure()) {
gl_resources_destroy();
return false;
}
return true;
}
void gl_resources_destroy()
{
tile.gl_resources_destroy();
buffer_object.gl_resources_destroy();
}
DrawTile tile;
GLPixelBufferObject buffer_object;
};
/* --------------------------------------------------------------------
* BlenderDisplayDriver.
*/
struct BlenderDisplayDriver::Tiles {
/* Resources of a tile which is being currently rendered. */
DrawTileAndPBO current_tile;
/* All tiles which rendering is finished and which content will not be changed. */
struct {
vector<DrawTile> tiles;
void gl_resources_destroy_and_clear()
{
for (DrawTile &tile : tiles) {
tile.gl_resources_destroy();
}
tiles.clear();
}
} finished_tiles;
};
BlenderDisplayDriver::BlenderDisplayDriver(BL::RenderEngine &b_engine, BL::Scene &b_scene)
: b_engine_(b_engine), display_shader_(BlenderDisplayShader::create(b_engine, b_scene))
: b_engine_(b_engine),
display_shader_(BlenderDisplayShader::create(b_engine, b_scene)),
tiles_(make_unique<Tiles>())
{
/* Create context while on the main thread. */
gl_context_create();
@@ -292,6 +580,21 @@ BlenderDisplayDriver::~BlenderDisplayDriver()
* Update procedure.
*/
void BlenderDisplayDriver::next_tile_begin()
{
if (!tiles_->current_tile.tile.ready_to_draw()) {
LOG(ERROR)
<< "Unexpectedly moving to the next tile without any data provided for current tile.";
return;
}
/* Moving to the next tile without giving render data for the current tile is not an expected
* situation. */
DCHECK(!need_clear_);
tiles_->finished_tiles.tiles.emplace_back(std::move(tiles_->current_tile.tile));
}
bool BlenderDisplayDriver::update_begin(const Params &params,
int texture_width,
int texture_height)
@@ -312,24 +615,33 @@ bool BlenderDisplayDriver::update_begin(const Params &params,
glWaitSync((GLsync)gl_render_sync_, 0, GL_TIMEOUT_IGNORED);
}
if (!gl_texture_resources_ensure()) {
DrawTile &current_tile = tiles_->current_tile.tile;
GLPixelBufferObject &current_tile_buffer_object = tiles_->current_tile.buffer_object;
/* Clear storage of all finished tiles when display clear is requested.
* Do it when new tile data is provided to handle the display clear flag in a single place.
* It also makes the logic reliable from the whether drawing did happen or not point of view. */
if (need_clear_) {
tiles_->finished_tiles.gl_resources_destroy_and_clear();
need_clear_ = false;
}
if (!tiles_->current_tile.gl_resources_ensure()) {
tiles_->current_tile.gl_resources_destroy();
gl_context_disable();
return false;
}
/* Update texture dimensions if needed. */
if (texture_.width != texture_width || texture_.height != texture_height) {
if (current_tile.texture.width != texture_width ||
current_tile.texture.height != texture_height) {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture_.gl_id);
glBindTexture(GL_TEXTURE_2D, current_tile.texture.gl_id);
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGBA16F, texture_width, texture_height, 0, GL_RGBA, GL_HALF_FLOAT, 0);
texture_.width = texture_width;
texture_.height = texture_height;
current_tile.texture.width = texture_width;
current_tile.texture.height = texture_height;
glBindTexture(GL_TEXTURE_2D, 0);
/* Texture did change, and no pixel storage was provided. Tag for an explicit zeroing out to
* avoid undefined content. */
texture_.need_clear = true;
}
/* Update PBO dimensions if needed.
@@ -341,29 +653,58 @@ bool BlenderDisplayDriver::update_begin(const Params &params,
* sending too much data to GPU when resolution divider is not 1. */
/* TODO(sergey): Investigate whether keeping the PBO exact size of the texture makes non-interop
* mode faster. */
const int buffer_width = params.full_size.x;
const int buffer_height = params.full_size.y;
if (texture_.buffer_width != buffer_width || texture_.buffer_height != buffer_height) {
const int buffer_width = params.size.x;
const int buffer_height = params.size.y;
if (current_tile_buffer_object.width != buffer_width ||
current_tile_buffer_object.height != buffer_height) {
const size_t size_in_bytes = sizeof(half4) * buffer_width * buffer_height;
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture_.gl_pbo_id);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, current_tile_buffer_object.gl_id);
glBufferData(GL_PIXEL_UNPACK_BUFFER, size_in_bytes, 0, GL_DYNAMIC_DRAW);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
texture_.buffer_width = buffer_width;
texture_.buffer_height = buffer_height;
current_tile_buffer_object.width = buffer_width;
current_tile_buffer_object.height = buffer_height;
}
/* New content will be provided to the texture in one way or another, so mark this in a
* centralized place. */
texture_.need_update = true;
texture_.params = params;
/* Store an updated parameters of the current tile.
* In theory it is only needed once per update of the tile, but doing it on every update is
* the easiest and is not expensive. */
tiles_->current_tile.tile.params = params;
return true;
}
static void update_tile_texture_pixels(const DrawTileAndPBO &tile)
{
const GLTexture &texture = tile.tile.texture;
DCHECK_NE(tile.buffer_object.gl_id, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture.gl_id);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, tile.buffer_object.gl_id);
glTexSubImage2D(
GL_TEXTURE_2D, 0, 0, 0, texture.width, texture.height, GL_RGBA, GL_HALF_FLOAT, 0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
}
void BlenderDisplayDriver::update_end()
{
/* Unpack the PBO into the texture as soon as the new content is provided.
*
* This allows to ensure that the unpacking happens while resources like graphics interop (which
* lifetime is outside of control of the display driver) are still valid, as well as allows to
* move the tile from being current to finished immediately after this call.
*
* One concern with this approach is that if the update happens more often than drawing then
* doing the unpack here occupies GPU transfer for no good reason. However, the render scheduler
* takes care of ensuring updates don't happen that often. In regular applications redraw will
* happen much more often than this update. */
update_tile_texture_pixels(tiles_->current_tile);
gl_upload_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
glFlush();
@@ -376,7 +717,11 @@ void BlenderDisplayDriver::update_end()
half4 *BlenderDisplayDriver::map_texture_buffer()
{
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture_.gl_pbo_id);
const uint pbo_gl_id = tiles_->current_tile.buffer_object.gl_id;
DCHECK_NE(pbo_gl_id, 0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo_gl_id);
half4 *mapped_rgba_pixels = reinterpret_cast<half4 *>(
glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY));
@@ -384,15 +729,6 @@ half4 *BlenderDisplayDriver::map_texture_buffer()
LOG(ERROR) << "Error mapping BlenderDisplayDriver pixel buffer object.";
}
if (texture_.need_clear) {
const int64_t texture_width = texture_.width;
const int64_t texture_height = texture_.height;
memset(reinterpret_cast<void *>(mapped_rgba_pixels),
0,
texture_width * texture_height * sizeof(half4));
texture_.need_clear = false;
}
return mapped_rgba_pixels;
}
@@ -411,12 +747,9 @@ BlenderDisplayDriver::GraphicsInterop BlenderDisplayDriver::graphics_interop_get
{
GraphicsInterop interop_dst;
interop_dst.buffer_width = texture_.buffer_width;
interop_dst.buffer_height = texture_.buffer_height;
interop_dst.opengl_pbo_id = texture_.gl_pbo_id;
interop_dst.need_clear = texture_.need_clear;
texture_.need_clear = false;
interop_dst.buffer_width = tiles_->current_tile.buffer_object.width;
interop_dst.buffer_height = tiles_->current_tile.buffer_object.height;
interop_dst.opengl_pbo_id = tiles_->current_tile.buffer_object.gl_id;
return interop_dst;
}
@@ -437,7 +770,7 @@ void BlenderDisplayDriver::graphics_interop_deactivate()
void BlenderDisplayDriver::clear()
{
texture_.need_clear = true;
need_clear_ = true;
}
void BlenderDisplayDriver::set_zoom(float zoom_x, float zoom_y)
@@ -445,26 +778,155 @@ void BlenderDisplayDriver::set_zoom(float zoom_x, float zoom_y)
zoom_ = make_float2(zoom_x, zoom_y);
}
/* Update vertex buffer with new coordinates of vertex positions and texture coordinates.
* This buffer is used to render texture in the viewport.
*
* NOTE: The buffer needs to be bound. */
static void vertex_buffer_update(const DisplayDriver::Params &params)
{
const int x = params.full_offset.x;
const int y = params.full_offset.y;
const int width = params.size.x;
const int height = params.size.y;
/* Invalidate old contents - avoids stalling if the buffer is still waiting in queue to be
* rendered. */
glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), NULL, GL_STREAM_DRAW);
float *vpointer = reinterpret_cast<float *>(glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY));
if (!vpointer) {
return;
}
vpointer[0] = 0.0f;
vpointer[1] = 0.0f;
vpointer[2] = x;
vpointer[3] = y;
vpointer[4] = 1.0f;
vpointer[5] = 0.0f;
vpointer[6] = x + width;
vpointer[7] = y;
vpointer[8] = 1.0f;
vpointer[9] = 1.0f;
vpointer[10] = x + width;
vpointer[11] = y + height;
vpointer[12] = 0.0f;
vpointer[13] = 1.0f;
vpointer[14] = x;
vpointer[15] = y + height;
glUnmapBuffer(GL_ARRAY_BUFFER);
}
static void draw_tile(const float2 &zoom,
const int texcoord_attribute,
const int position_attribute,
const DrawTile &draw_tile)
{
if (!draw_tile.ready_to_draw()) {
return;
}
const GLTexture &texture = draw_tile.texture;
DCHECK_NE(texture.gl_id, 0);
DCHECK_NE(draw_tile.gl_vertex_buffer, 0);
glBindBuffer(GL_ARRAY_BUFFER, draw_tile.gl_vertex_buffer);
/* Draw at the parameters for which the texture has been updated for. This allows to always draw
* texture during bordered-rendered camera view without flickering. The validness of the display
* parameters for a texture is guaranteed by the initial "clear" state which makes drawing to
* have an early output.
*
* Such approach can cause some extra "jelly" effect during panning, but it is not more jelly
* than overlay of selected objects. Also, it's possible to redraw texture at an intersection of
* the texture draw parameters and the latest updated draw parameters (although, complexity of
* doing it might not worth it. */
vertex_buffer_update(draw_tile.params);
glBindTexture(GL_TEXTURE_2D, texture.gl_id);
/* Trick to keep sharp rendering without jagged edges on all GPUs.
*
* The idea here is to enforce driver to use linear interpolation when the image is not zoomed
* in.
* For the render result with a resolution divider in effect we always use nearest interpolation.
*
* Use explicit MIN assignment to make sure the driver does not have an undefined behavior at
* the zoom level 1. The MAG filter is always NEAREST. */
const float zoomed_width = draw_tile.params.size.x * zoom.x;
const float zoomed_height = draw_tile.params.size.y * zoom.y;
if (texture.width != draw_tile.params.size.x || texture.height != draw_tile.params.size.y) {
/* Resolution divider is different from 1, force nearest interpolation. */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
else if (zoomed_width - draw_tile.params.size.x > 0.5f ||
zoomed_height - draw_tile.params.size.y > 0.5f) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
glVertexAttribPointer(
texcoord_attribute, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (const GLvoid *)0);
glVertexAttribPointer(position_attribute,
2,
GL_FLOAT,
GL_FALSE,
4 * sizeof(float),
(const GLvoid *)(sizeof(float) * 2));
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
void BlenderDisplayDriver::flush()
{
/* This is called from the render thread that also calls update_begin/end, right before ending
* the render loop. We wait for any queued PBO and render commands to be done, before destroying
* the render thread and activating the context in the main thread to destroy resources.
*
* If we don't do this, the NVIDIA driver hangs for a few seconds for when ending 3D viewport
* rendering, for unknown reasons. This was found with NVIDIA driver version 470.73 and a Quadro
* RTX 6000 on Linux. */
if (!gl_context_enable()) {
return;
}
if (gl_upload_sync_) {
glWaitSync((GLsync)gl_upload_sync_, 0, GL_TIMEOUT_IGNORED);
}
if (gl_render_sync_) {
glWaitSync((GLsync)gl_render_sync_, 0, GL_TIMEOUT_IGNORED);
}
gl_context_disable();
}
void BlenderDisplayDriver::draw(const Params &params)
{
/* See do_update_begin() for why no locking is required here. */
const bool transparent = true; // TODO(sergey): Derive this from Film.
if (!gl_draw_resources_ensure()) {
return;
}
if (use_gl_context_) {
gl_context_mutex_.lock();
}
if (texture_.need_clear) {
if (need_clear_) {
/* Texture is requested to be cleared and was not yet cleared.
*
* Do early return which should be equivalent of drawing all-zero texture.
* Watch out for the lock though so that the clear happening during update is properly
* synchronized here. */
gl_context_mutex_.unlock();
if (use_gl_context_) {
gl_context_mutex_.unlock();
}
return;
}
@@ -477,66 +939,37 @@ void BlenderDisplayDriver::draw(const Params &params)
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
display_shader_->bind(params.full_size.x, params.full_size.y);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture_.gl_id);
/* Trick to keep sharp rendering without jagged edges on all GPUs.
*
* The idea here is to enforce driver to use linear interpolation when the image is not zoomed
* in.
* For the render result with a resolution divider in effect we always use nearest interpolation.
*
* Use explicit MIN assignment to make sure the driver does not have an undefined behavior at
* the zoom level 1. The MAG filter is always NEAREST. */
const float zoomed_width = params.size.x * zoom_.x;
const float zoomed_height = params.size.y * zoom_.y;
if (texture_.width != params.size.x || texture_.height != params.size.y) {
/* Resolution divider is different from 1, force nearest interpolation. */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
else if (zoomed_width - params.size.x > 0.5f || zoomed_height - params.size.y > 0.5f) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
texture_update_if_needed();
vertex_buffer_update(params);
/* TODO(sergey): Does it make sense/possible to cache/reuse the VAO? */
/* NOTE: The VAO is to be allocated on the drawing context as it is not shared across contexts.
* Simplest is to allocate it on every redraw so that it is possible to destroy it from a
* correct context. */
GLuint vertex_array_object;
glGenVertexArrays(1, &vertex_array_object);
glBindVertexArray(vertex_array_object);
display_shader_->bind(params.full_size.x, params.full_size.y);
const int texcoord_attribute = display_shader_->get_tex_coord_attrib_location();
const int position_attribute = display_shader_->get_position_attrib_location();
glEnableVertexAttribArray(texcoord_attribute);
glEnableVertexAttribArray(position_attribute);
glVertexAttribPointer(
texcoord_attribute, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (const GLvoid *)0);
glVertexAttribPointer(position_attribute,
2,
GL_FLOAT,
GL_FALSE,
4 * sizeof(float),
(const GLvoid *)(sizeof(float) * 2));
draw_tile(zoom_, texcoord_attribute, position_attribute, tiles_->current_tile.tile);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glDeleteVertexArrays(1, &vertex_array_object);
for (const DrawTile &tile : tiles_->finished_tiles.tiles) {
draw_tile(zoom_, texcoord_attribute, position_attribute, tile);
}
display_shader_->unbind();
glBindTexture(GL_TEXTURE_2D, 0);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDeleteVertexArrays(1, &vertex_array_object);
if (transparent) {
glDisable(GL_BLEND);
}
@@ -544,6 +977,11 @@ void BlenderDisplayDriver::draw(const Params &params)
gl_render_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
glFlush();
if (VLOG_IS_ON(5)) {
VLOG(5) << "Number of textures: " << GLTexture::num_used;
VLOG(5) << "Number of PBOs: " << GLPixelBufferObject::num_used;
}
if (use_gl_context_) {
gl_context_mutex_.unlock();
}
@@ -618,154 +1056,16 @@ void BlenderDisplayDriver::gl_context_dispose()
}
}
bool BlenderDisplayDriver::gl_draw_resources_ensure()
{
if (!texture_.gl_id) {
/* If there is no texture allocated, there is nothing to draw. Inform the draw call that it can
* can not continue. Note that this is not an unrecoverable error, so once the texture is known
* we will come back here and create all the GPU resources needed for draw. */
return false;
}
if (gl_draw_resource_creation_attempted_) {
return gl_draw_resources_created_;
}
gl_draw_resource_creation_attempted_ = true;
if (!vertex_buffer_) {
glGenBuffers(1, &vertex_buffer_);
if (!vertex_buffer_) {
LOG(ERROR) << "Error creating vertex buffer.";
return false;
}
}
gl_draw_resources_created_ = true;
return true;
}
void BlenderDisplayDriver::gl_resources_destroy()
{
gl_context_enable();
if (vertex_buffer_ != 0) {
glDeleteBuffers(1, &vertex_buffer_);
}
if (texture_.gl_pbo_id) {
glDeleteBuffers(1, &texture_.gl_pbo_id);
texture_.gl_pbo_id = 0;
}
if (texture_.gl_id) {
glDeleteTextures(1, &texture_.gl_id);
texture_.gl_id = 0;
}
tiles_->current_tile.gl_resources_destroy();
tiles_->finished_tiles.gl_resources_destroy_and_clear();
gl_context_disable();
gl_context_dispose();
}
bool BlenderDisplayDriver::gl_texture_resources_ensure()
{
if (texture_.creation_attempted) {
return texture_.is_created;
}
texture_.creation_attempted = true;
DCHECK(!texture_.gl_id);
DCHECK(!texture_.gl_pbo_id);
/* Create texture. */
glGenTextures(1, &texture_.gl_id);
if (!texture_.gl_id) {
LOG(ERROR) << "Error creating texture.";
return false;
}
/* Configure the texture. */
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture_.gl_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
/* Create PBO for the texture. */
glGenBuffers(1, &texture_.gl_pbo_id);
if (!texture_.gl_pbo_id) {
LOG(ERROR) << "Error creating texture pixel buffer object.";
return false;
}
/* Creation finished with a success. */
texture_.is_created = true;
return true;
}
void BlenderDisplayDriver::texture_update_if_needed()
{
if (!texture_.need_update) {
return;
}
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture_.gl_pbo_id);
glTexSubImage2D(
GL_TEXTURE_2D, 0, 0, 0, texture_.width, texture_.height, GL_RGBA, GL_HALF_FLOAT, 0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
texture_.need_update = false;
}
void BlenderDisplayDriver::vertex_buffer_update(const Params & /*params*/)
{
/* Draw at the parameters for which the texture has been updated for. This allows to always draw
* texture during bordered-rendered camera view without flickering. The validness of the display
* parameters for a texture is guaranteed by the initial "clear" state which makes drawing to
* have an early output.
*
* Such approach can cause some extra "jelly" effect during panning, but it is not more jelly
* than overlay of selected objects. Also, it's possible to redraw texture at an intersection of
* the texture draw parameters and the latest updated draw parameters (although, complexity of
* doing it might not worth it. */
const int x = texture_.params.full_offset.x;
const int y = texture_.params.full_offset.y;
const int width = texture_.params.size.x;
const int height = texture_.params.size.y;
/* Invalidate old contents - avoids stalling if the buffer is still waiting in queue to be
* rendered. */
glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), NULL, GL_STREAM_DRAW);
float *vpointer = reinterpret_cast<float *>(glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY));
if (!vpointer) {
return;
}
vpointer[0] = 0.0f;
vpointer[1] = 0.0f;
vpointer[2] = x;
vpointer[3] = y;
vpointer[4] = 1.0f;
vpointer[5] = 0.0f;
vpointer[6] = x + width;
vpointer[7] = y;
vpointer[8] = 1.0f;
vpointer[9] = 1.0f;
vpointer[10] = x + width;
vpointer[11] = y + height;
vpointer[12] = 0.0f;
vpointer[13] = 1.0f;
vpointer[14] = x;
vpointer[15] = y + height;
glUnmapBuffer(GL_ARRAY_BUFFER);
}
CCL_NAMESPACE_END

View File

@@ -26,6 +26,7 @@
#include "util/thread.h"
#include "util/unique_ptr.h"
#include "util/vector.h"
CCL_NAMESPACE_BEGIN
@@ -112,6 +113,8 @@ class BlenderDisplayDriver : public DisplayDriver {
void set_zoom(float zoom_x, float zoom_y);
protected:
virtual void next_tile_begin() override;
virtual bool update_begin(const Params &params, int texture_width, int texture_height) override;
virtual void update_end() override;
@@ -122,33 +125,17 @@ class BlenderDisplayDriver : public DisplayDriver {
virtual void draw(const Params &params) override;
virtual void flush() override;
/* Helper function which allocates new GPU context. */
void gl_context_create();
bool gl_context_enable();
void gl_context_disable();
void gl_context_dispose();
/* Make sure texture is allocated and its initial configuration is performed. */
bool gl_texture_resources_ensure();
/* Ensure all runtime GPU resources needed for drawing are allocated.
* Returns true if all resources needed for drawing are available. */
bool gl_draw_resources_ensure();
/* Destroy all GPU resources which are being used by this object. */
void gl_resources_destroy();
/* Update GPU texture dimensions and content if needed (new pixel data was provided).
*
* NOTE: The texture needs to be bound. */
void texture_update_if_needed();
/* Update vertex buffer with new coordinates of vertex positions and texture coordinates.
* This buffer is used to render texture in the viewport.
*
* NOTE: The buffer needs to be bound. */
void vertex_buffer_update(const Params &params);
BL::RenderEngine b_engine_;
/* OpenGL context which is used the render engine doesn't have its own. */
@@ -159,50 +146,14 @@ class BlenderDisplayDriver : public DisplayDriver {
/* Mutex used to guard the `gl_context_`. */
thread_mutex gl_context_mutex_;
/* Texture which contains pixels of the render result. */
struct {
/* Indicates whether texture creation was attempted and succeeded.
* Used to avoid multiple attempts of texture creation on GPU issues or GPU context
* misconfiguration. */
bool creation_attempted = false;
bool is_created = false;
/* OpenGL resource IDs of the texture itself and Pixel Buffer Object (PBO) used to write
* pixels to it.
*
* NOTE: Allocated on the engine's context. */
uint gl_id = 0;
uint gl_pbo_id = 0;
/* Is true when new data was written to the PBO, meaning, the texture might need to be resized
* and new data is to be uploaded to the GPU. */
bool need_update = false;
/* Content of the texture is to be filled with zeroes. */
std::atomic<bool> need_clear = true;
/* Dimensions of the texture in pixels. */
int width = 0;
int height = 0;
/* Dimensions of the underlying PBO. */
int buffer_width = 0;
int buffer_height = 0;
/* Display parameters the texture has been updated for. */
Params params;
} texture_;
/* Content of the display is to be filled with zeroes. */
std::atomic<bool> need_clear_ = true;
unique_ptr<BlenderDisplayShader> display_shader_;
/* Special track of whether GPU resources were attempted to be created, to avoid attempts of
* their re-creation on failure on every redraw. */
bool gl_draw_resource_creation_attempted_ = false;
bool gl_draw_resources_created_ = false;
/* Vertex buffer which hold vertices of a triangle fan which is textures with the texture
* holding the render result. */
uint vertex_buffer_ = 0;
/* Opaque storage for an internal state and data for tiles. */
struct Tiles;
unique_ptr<Tiles> tiles_;
void *gl_render_sync_ = nullptr;
void *gl_upload_sync_ = nullptr;

View File

@@ -1086,40 +1086,6 @@ static void create_subd_mesh(Scene *scene,
/* Sync */
/* Check whether some of "built-in" motion-related attributes are needed to be exported (includes
* things like velocity from cache modifier, fluid simulation).
*
* NOTE: This code is run prior to object motion blur initialization. so can not access properties
* set by `sync_object_motion_init()`. */
static bool mesh_need_motion_attribute(BObjectInfo &b_ob_info, Scene *scene)
{
const Scene::MotionType need_motion = scene->need_motion();
if (need_motion == Scene::MOTION_NONE) {
/* Simple case: neither motion pass nor motion blur is needed, no need in the motion related
* attributes. */
return false;
}
if (need_motion == Scene::MOTION_BLUR) {
/* A bit tricky and implicit case:
* - Motion blur is enabled in the scene, which implies specific number of time steps for
* objects.
* - If the object has motion blur disabled on it, it will have 0 time steps.
* - Motion attribute expects non-zero time steps.
*
* Avoid adding motion attributes if the motion blur will enforce 0 motion steps. */
PointerRNA cobject = RNA_pointer_get(&b_ob_info.real_object.ptr, "cycles");
const bool use_motion = get_boolean(cobject, "use_motion_blur");
if (!use_motion) {
return false;
}
}
/* Motion pass which implies 3 motion steps, or motion blur which is not disabled on object
* level. */
return true;
}
void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, Mesh *mesh)
{
/* make a copy of the shaders as the caller in the main thread still need them for syncing the
@@ -1144,7 +1110,7 @@ void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, M
if (b_mesh) {
/* Motion blur attribute is relative to seconds, we need it relative to frames. */
const bool need_motion = mesh_need_motion_attribute(b_ob_info, scene);
const bool need_motion = object_need_motion_attribute(b_ob_info, scene);
const float motion_scale = (need_motion) ?
scene->motion_shutter_time() /
(b_scene.render().fps() / b_scene.render().fps_base()) :

View File

@@ -120,7 +120,7 @@ void BlenderOutputDriver::write_render_tile(const Tile &tile)
b_pass.rect(&pixels[0]);
}
b_engine_.end_result(b_rr, true, false, true);
b_engine_.end_result(b_rr, false, false, true);
}
CCL_NAMESPACE_END

View File

@@ -37,12 +37,52 @@ static void fill_generic_attribute(BL::PointCloud &b_pointcloud,
}
}
static void copy_attributes(PointCloud *pointcloud, BL::PointCloud b_pointcloud)
static void attr_create_motion(PointCloud *pointcloud,
BL::Attribute &b_attribute,
const float motion_scale)
{
if (!(b_attribute.domain() == BL::Attribute::domain_POINT) &&
(b_attribute.data_type() == BL::Attribute::data_type_FLOAT_VECTOR)) {
return;
}
BL::FloatVectorAttribute b_vector_attribute(b_attribute);
const int num_points = pointcloud->get_points().size();
/* Find or add attribute */
float3 *P = &pointcloud->get_points()[0];
Attribute *attr_mP = pointcloud->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
if (!attr_mP) {
attr_mP = pointcloud->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
}
/* Only export previous and next frame, we don't have any in between data. */
float motion_times[2] = {-1.0f, 1.0f};
for (int step = 0; step < 2; step++) {
const float relative_time = motion_times[step] * 0.5f * motion_scale;
float3 *mP = attr_mP->data_float3() + step * num_points;
for (int i = 0; i < num_points; i++) {
mP[i] = P[i] + get_float3(b_vector_attribute.data[i].vector()) * relative_time;
}
}
}
static void copy_attributes(PointCloud *pointcloud,
BL::PointCloud b_pointcloud,
const bool need_motion,
const float motion_scale)
{
AttributeSet &attributes = pointcloud->attributes;
static const ustring u_velocity("velocity");
for (BL::Attribute &b_attribute : b_pointcloud.attributes) {
const ustring name{b_attribute.name().c_str()};
if (need_motion && name == u_velocity) {
attr_create_motion(pointcloud, b_attribute, motion_scale);
}
if (attributes.find(name)) {
continue;
}
@@ -111,7 +151,11 @@ static void copy_attributes(PointCloud *pointcloud, BL::PointCloud b_pointcloud)
}
}
static void export_pointcloud(Scene *scene, PointCloud *pointcloud, BL::PointCloud b_pointcloud)
static void export_pointcloud(Scene *scene,
PointCloud *pointcloud,
BL::PointCloud b_pointcloud,
const bool need_motion,
const float motion_scale)
{
/* TODO: optimize so we can straight memcpy arrays from Blender? */
@@ -141,7 +185,7 @@ static void export_pointcloud(Scene *scene, PointCloud *pointcloud, BL::PointClo
}
/* Export attributes */
copy_attributes(pointcloud, b_pointcloud);
copy_attributes(pointcloud, b_pointcloud, need_motion, motion_scale);
}
static void export_pointcloud_motion(PointCloud *pointcloud,
@@ -193,7 +237,7 @@ static void export_pointcloud_motion(PointCloud *pointcloud,
}
/* Export attributes */
copy_attributes(pointcloud, b_pointcloud);
copy_attributes(pointcloud, b_pointcloud, false, 0.0f);
}
void BlenderSync::sync_pointcloud(PointCloud *pointcloud, BObjectInfo &b_ob_info)
@@ -207,7 +251,13 @@ void BlenderSync::sync_pointcloud(PointCloud *pointcloud, BObjectInfo &b_ob_info
/* TODO: add option to filter out points in the view layer. */
BL::PointCloud b_pointcloud(b_ob_info.object_data);
export_pointcloud(scene, &new_pointcloud, b_pointcloud);
/* Motion blur attribute is relative to seconds, we need it relative to frames. */
const bool need_motion = object_need_motion_attribute(b_ob_info, scene);
const float motion_scale = (need_motion) ?
scene->motion_shutter_time() /
(b_scene.render().fps() / b_scene.render().fps_base()) :
0.0f;
export_pointcloud(scene, &new_pointcloud, b_pointcloud, need_motion, motion_scale);
/* update original sockets */
for (const SocketType &socket : new_pointcloud.type->inputs) {

View File

@@ -138,20 +138,18 @@ static const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce)
static PyObject *init_func(PyObject * /*self*/, PyObject *args)
{
PyObject *path, *user_path, *temp_path;
PyObject *path, *user_path;
int headless;
if (!PyArg_ParseTuple(args, "OOOi", &path, &user_path, &temp_path, &headless)) {
if (!PyArg_ParseTuple(args, "OOi", &path, &user_path, &headless)) {
return nullptr;
}
PyObject *path_coerce = nullptr, *user_path_coerce = nullptr, *temp_path_coerce = nullptr;
PyObject *path_coerce = nullptr, *user_path_coerce = nullptr;
path_init(PyC_UnicodeAsByte(path, &path_coerce),
PyC_UnicodeAsByte(user_path, &user_path_coerce),
PyC_UnicodeAsByte(temp_path, &temp_path_coerce));
PyC_UnicodeAsByte(user_path, &user_path_coerce));
Py_XDECREF(path_coerce);
Py_XDECREF(user_path_coerce);
Py_XDECREF(temp_path_coerce);
BlenderSession::headless = headless;
@@ -735,27 +733,20 @@ static bool image_parse_filepaths(PyObject *pyfilepaths, vector<string> &filepat
static PyObject *denoise_func(PyObject * /*self*/, PyObject *args, PyObject *keywords)
{
#if 1
(void)args;
(void)keywords;
#else
static const char *keyword_list[] = {
"preferences", "scene", "view_layer", "input", "output", "tile_size", "samples", NULL};
"preferences", "scene", "view_layer", "input", "output", NULL};
PyObject *pypreferences, *pyscene, *pyviewlayer;
PyObject *pyinput, *pyoutput = NULL;
int tile_size = 0, samples = 0;
if (!PyArg_ParseTupleAndKeywords(args,
keywords,
"OOOO|Oii",
"OOOO|O",
(char **)keyword_list,
&pypreferences,
&pyscene,
&pyviewlayer,
&pyinput,
&pyoutput,
&tile_size,
&samples)) {
&pyoutput)) {
return NULL;
}
@@ -777,14 +768,10 @@ static PyObject *denoise_func(PyObject * /*self*/, PyObject *args, PyObject *key
&RNA_ViewLayer,
PyLong_AsVoidPtr(pyviewlayer),
&viewlayerptr);
PointerRNA cviewlayer = RNA_pointer_get(&viewlayerptr, "cycles");
BL::ViewLayer b_view_layer(viewlayerptr);
DenoiseParams params;
params.radius = get_int(cviewlayer, "denoising_radius");
params.strength = get_float(cviewlayer, "denoising_strength");
params.feature_strength = get_float(cviewlayer, "denoising_feature_strength");
params.relative_pca = get_boolean(cviewlayer, "denoising_relative_pca");
params.neighbor_frames = get_int(cviewlayer, "denoising_neighbor_frames");
DenoiseParams params = BlenderSync::get_denoise_params(b_scene, b_view_layer, true);
params.use = true;
/* Parse file paths list. */
vector<string> input, output;
@@ -812,24 +799,15 @@ static PyObject *denoise_func(PyObject * /*self*/, PyObject *args, PyObject *key
}
/* Create denoiser. */
DenoiserPipeline denoiser(device);
denoiser.params = params;
DenoiserPipeline denoiser(device, params);
denoiser.input = input;
denoiser.output = output;
if (tile_size > 0) {
denoiser.tile_size = make_int2(tile_size, tile_size);
}
if (samples > 0) {
denoiser.samples_override = samples;
}
/* Run denoiser. */
if (!denoiser.run()) {
PyErr_SetString(PyExc_ValueError, denoiser.error.c_str());
return NULL;
}
#endif
Py_RETURN_NONE;
}

View File

@@ -502,10 +502,15 @@ void BlenderSession::render_frame_finish()
path_remove(filename);
}
/* Clear driver. */
/* Clear output driver. */
session->set_output_driver(nullptr);
session->full_buffer_written_cb = function_null;
/* The display driver holds OpenGL resources which belong to an OpenGL context held by the render
* engine on Blender side. Force destruction of those resources. */
display_driver_ = nullptr;
session->set_display_driver(nullptr);
/* All the files are handled.
* Clear the list so that this session can be re-used by Persistent Data. */
full_buffer_files_.clear();

View File

@@ -776,7 +776,7 @@ static ShaderNode *add_node(Scene *scene,
}
else {
ustring filename = ustring(
image_user_file_path(b_image_user, b_image, b_scene.frame_current(), true));
image_user_file_path(b_image_user, b_image, b_scene.frame_current()));
image->set_filename(filename);
}
}
@@ -813,7 +813,7 @@ static ShaderNode *add_node(Scene *scene,
}
else {
env->set_filename(
ustring(image_user_file_path(b_image_user, b_image, b_scene.frame_current(), false)));
ustring(image_user_file_path(b_image_user, b_image, b_scene.frame_current())));
}
}
node = env;

View File

@@ -832,6 +832,14 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine &b_engine,
SessionParams params;
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
if (background && !b_engine.is_preview()) {
/* Viewport and preview renders do not require temp directory and do request session
* parameters more often than the background render.
* Optimize RNA-C++ usage and memory allocation a bit by saving string access which we know is
* not needed for viewport render. */
params.temp_dir = b_engine.temporary_directory();
}
/* feature set */
params.experimental = (get_enum(cscene, "feature_set") != 0);

View File

@@ -105,11 +105,11 @@ class BlenderSync {
static BufferParams get_buffer_params(
BL::SpaceView3D &b_v3d, BL::RegionView3D &b_rv3d, Camera *cam, int width, int height);
private:
static DenoiseParams get_denoise_params(BL::Scene &b_scene,
BL::ViewLayer &b_view_layer,
bool background);
private:
/* sync */
void sync_lights(BL::Depsgraph &b_depsgraph, bool update_all);
void sync_materials(BL::Depsgraph &b_depsgraph, bool update_all);

View File

@@ -18,6 +18,7 @@
#define __BLENDER_UTIL_H__
#include "scene/mesh.h"
#include "scene/scene.h"
#include "util/algorithm.h"
#include "util/array.h"
@@ -33,7 +34,7 @@
extern "C" {
void BKE_image_user_frame_calc(void *ima, void *iuser, int cfra);
void BKE_image_user_file_path(void *iuser, void *ima, char *path);
void BKE_image_user_file_path_ex(void *iuser, void *ima, char *path, bool resolve_udim);
unsigned char *BKE_image_get_pixels_for_frame(void *image, int frame, int tile);
float *BKE_image_get_float_pixels_for_frame(void *image, int frame, int tile);
}
@@ -290,25 +291,14 @@ static inline int render_resolution_y(BL::RenderSettings &b_render)
return b_render.resolution_y() * b_render.resolution_percentage() / 100;
}
static inline string image_user_file_path(BL::ImageUser &iuser,
BL::Image &ima,
int cfra,
bool load_tiled)
static inline string image_user_file_path(BL::ImageUser &iuser, BL::Image &ima, int cfra)
{
char filepath[1024];
iuser.tile(0);
BKE_image_user_frame_calc(ima.ptr.data, iuser.ptr.data, cfra);
BKE_image_user_file_path(iuser.ptr.data, ima.ptr.data, filepath);
BKE_image_user_file_path_ex(iuser.ptr.data, ima.ptr.data, filepath, false);
string filepath_str = string(filepath);
if (load_tiled && ima.source() == BL::Image::source_TILED) {
string udim;
if (!ima.tiles.empty()) {
udim = to_string(ima.tiles[0].number());
}
string_replace(filepath_str, udim, "<UDIM>");
}
return filepath_str;
return string(filepath);
}
static inline int image_user_frame_number(BL::ImageUser &iuser, BL::Image &ima, int cfra)
@@ -681,6 +671,40 @@ static inline uint object_ray_visibility(BL::Object &b_ob)
return flag;
}
/* Check whether some of "built-in" motion-related attributes are needed to be exported (includes
* things like velocity from cache modifier, fluid simulation).
*
* NOTE: This code is run prior to object motion blur initialization. so can not access properties
* set by `sync_object_motion_init()`. */
static inline bool object_need_motion_attribute(BObjectInfo &b_ob_info, Scene *scene)
{
const Scene::MotionType need_motion = scene->need_motion();
if (need_motion == Scene::MOTION_NONE) {
/* Simple case: neither motion pass nor motion blur is needed, no need in the motion related
* attributes. */
return false;
}
if (need_motion == Scene::MOTION_BLUR) {
/* A bit tricky and implicit case:
* - Motion blur is enabled in the scene, which implies specific number of time steps for
* objects.
* - If the object has motion blur disabled on it, it will have 0 time steps.
* - Motion attribute expects non-zero time steps.
*
* Avoid adding motion attributes if the motion blur will enforce 0 motion steps. */
PointerRNA cobject = RNA_pointer_get(&b_ob_info.real_object.ptr, "cycles");
const bool use_motion = get_boolean(cobject, "use_motion_blur");
if (!use_motion) {
return false;
}
}
/* Motion pass which implies 3 motion steps, or motion blur which is not disabled on object
* level. */
return true;
}
class EdgeMap {
public:
EdgeMap()

View File

@@ -84,39 +84,6 @@ macro(cycles_add_library target library_deps)
cycles_set_solution_folder(${target})
endmacro()
# Cycles library dependencies common to all executables
function(cycles_link_directories)
if(APPLE)
# APPLE platform uses full paths for linking libraries, and avoids link_directories.
return()
endif()
if(WITH_OPENCOLORIO)
link_directories(${OPENCOLORIO_LIBPATH})
endif()
if(WITH_OPENVDB)
link_directories(${OPENVDB_LIBPATH} ${BLOSC_LIBPATH})
endif()
if(WITH_OPENSUBDIV)
link_directories(${OPENSUBDIV_LIBPATH})
endif()
if(WITH_OPENIMAGEDENOISE)
link_directories(${OPENIMAGEDENOISE_LIBPATH})
endif()
link_directories(
${OPENIMAGEIO_LIBPATH}
${BOOST_LIBPATH}
${PNG_LIBPATH}
${JPEG_LIBPATH}
${ZLIB_LIBPATH}
${TIFF_LIBPATH}
${OPENEXR_LIBPATH}
${OPENJPEG_LIBPATH}
)
endfunction()
macro(cycles_target_link_libraries target)
if(WITH_CYCLES_LOGGING)
target_link_libraries(${target} ${GLOG_LIBRARIES} ${GFLAGS_LIBRARIES})
@@ -168,12 +135,6 @@ macro(cycles_target_link_libraries target)
target_link_libraries(${target} extern_hipew)
endif()
if(CYCLES_STANDALONE_REPOSITORY)
target_link_libraries(${target} extern_numaapi)
else()
target_link_libraries(${target} bf_intern_numaapi)
endif()
if(UNIX AND NOT APPLE)
if(CYCLES_STANDALONE_REPOSITORY)
target_link_libraries(${target} extern_libc_compat)

View File

@@ -72,7 +72,7 @@ CPUDevice::CPUDevice(const DeviceInfo &info_, Stats &stats_, Profiler &profiler_
<< " CPU kernels.";
if (info.cpu_threads == 0) {
info.cpu_threads = TaskScheduler::num_threads();
info.cpu_threads = TaskScheduler::max_concurrency();
}
#ifdef WITH_OSL

View File

@@ -45,8 +45,10 @@ void CUDADeviceGraphicsInterop::set_display_interop(
need_clear_ = display_interop.need_clear;
if (opengl_pbo_id_ == display_interop.opengl_pbo_id && buffer_area_ == new_buffer_area) {
return;
if (!display_interop.need_recreate) {
if (opengl_pbo_id_ == display_interop.opengl_pbo_id && buffer_area_ == new_buffer_area) {
return;
}
}
CUDAContextScope scope(device_);

View File

@@ -76,6 +76,8 @@ NODE_DEFINE(DenoiseParams)
SOCKET_BOOLEAN(use_pass_albedo, "Use Pass Albedo", true);
SOCKET_BOOLEAN(use_pass_normal, "Use Pass Normal", false);
SOCKET_BOOLEAN(temporally_stable, "Temporally Stable", false);
SOCKET_ENUM(prefilter, "Prefilter", *prefilter_enum, DENOISER_PREFILTER_FAST);
return type;

View File

@@ -72,6 +72,9 @@ class DenoiseParams : public Node {
bool use_pass_albedo = true;
bool use_pass_normal = true;
/* Configure the denoiser to use motion vectors, previous image and a temporally stable model. */
bool temporally_stable = false;
DenoiserPrefilter prefilter = DENOISER_PREFILTER_FAST;
static const NodeEnum *get_type_enum();
@@ -83,7 +86,8 @@ class DenoiseParams : public Node {
{
return !(use == other.use && type == other.type && start_sample == other.start_sample &&
use_pass_albedo == other.use_pass_albedo &&
use_pass_normal == other.use_pass_normal && prefilter == other.prefilter);
use_pass_normal == other.use_pass_normal &&
temporally_stable == other.temporally_stable && prefilter == other.prefilter);
}
};

View File

@@ -37,6 +37,7 @@
#include "util/math.h"
#include "util/string.h"
#include "util/system.h"
#include "util/task.h"
#include "util/time.h"
#include "util/types.h"
#include "util/vector.h"
@@ -333,7 +334,7 @@ DeviceInfo Device::get_multi_device(const vector<DeviceInfo> &subdevices,
/* Ensure CPU device does not slow down GPU. */
if (device.type == DEVICE_CPU && subdevices.size() > 1) {
if (background) {
int orig_cpu_threads = (threads) ? threads : system_cpu_thread_count();
int orig_cpu_threads = (threads) ? threads : TaskScheduler::max_concurrency();
int cpu_threads = max(orig_cpu_threads - (subdevices.size() - 1), 0);
VLOG(1) << "CPU render threads reduced from " << orig_cpu_threads << " to " << cpu_threads

View File

@@ -566,6 +566,19 @@ class OptiXDevice::DenoiseContext {
}
}
if (denoise_params.temporally_stable) {
prev_output.device_pointer = render_buffers->buffer.device_pointer;
prev_output.offset = buffer_params.get_pass_offset(PASS_DENOISING_PREVIOUS);
prev_output.stride = buffer_params.stride;
prev_output.pass_stride = buffer_params.pass_stride;
num_input_passes += 1;
use_pass_flow = true;
pass_motion = buffer_params.get_pass_offset(PASS_MOTION);
}
use_guiding_passes = (num_input_passes - 1) > 0;
if (use_guiding_passes) {
@@ -574,6 +587,7 @@ class OptiXDevice::DenoiseContext {
guiding_params.pass_albedo = pass_denoising_albedo;
guiding_params.pass_normal = pass_denoising_normal;
guiding_params.pass_flow = pass_motion;
guiding_params.stride = buffer_params.stride;
guiding_params.pass_stride = buffer_params.pass_stride;
@@ -588,6 +602,10 @@ class OptiXDevice::DenoiseContext {
guiding_params.pass_normal = guiding_params.pass_stride;
guiding_params.pass_stride += 3;
}
if (use_pass_flow) {
guiding_params.pass_flow = guiding_params.pass_stride;
guiding_params.pass_stride += 2;
}
guiding_params.stride = buffer_params.width;
@@ -605,6 +623,16 @@ class OptiXDevice::DenoiseContext {
RenderBuffers *render_buffers = nullptr;
const BufferParams &buffer_params;
/* Previous output. */
struct {
device_ptr device_pointer = 0;
int offset = PASS_UNUSED;
int stride = -1;
int pass_stride = -1;
} prev_output;
/* Device-side storage of the guiding passes. */
device_only_memory<float> guiding_buffer;
@@ -614,6 +642,7 @@ class OptiXDevice::DenoiseContext {
/* NOTE: Are only initialized when the corresponding guiding pass is enabled. */
int pass_albedo = PASS_UNUSED;
int pass_normal = PASS_UNUSED;
int pass_flow = PASS_UNUSED;
int stride = -1;
int pass_stride = -1;
@@ -624,6 +653,7 @@ class OptiXDevice::DenoiseContext {
bool use_guiding_passes = false;
bool use_pass_albedo = false;
bool use_pass_normal = false;
bool use_pass_flow = false;
int num_samples = 0;
@@ -632,6 +662,7 @@ class OptiXDevice::DenoiseContext {
/* NOTE: Are only initialized when the corresponding guiding pass is enabled. */
int pass_denoising_albedo = PASS_UNUSED;
int pass_denoising_normal = PASS_UNUSED;
int pass_motion = PASS_UNUSED;
/* For passes which don't need albedo channel for denoising we replace the actual albedo with
* the (0.5, 0.5, 0.5). This flag indicates that the real albedo pass has been replaced with
@@ -702,6 +733,7 @@ bool OptiXDevice::denoise_filter_guiding_preprocess(DenoiseContext &context)
&context.guiding_params.pass_stride,
&context.guiding_params.pass_albedo,
&context.guiding_params.pass_normal,
&context.guiding_params.pass_flow,
&context.render_buffers->buffer.device_pointer,
&buffer_params.offset,
&buffer_params.stride,
@@ -709,6 +741,7 @@ bool OptiXDevice::denoise_filter_guiding_preprocess(DenoiseContext &context)
&context.pass_sample_count,
&context.pass_denoising_albedo,
&context.pass_denoising_normal,
&context.pass_motion,
&buffer_params.full_x,
&buffer_params.full_y,
&buffer_params.width,
@@ -881,7 +914,8 @@ bool OptiXDevice::denoise_create_if_needed(DenoiseContext &context)
{
const bool recreate_denoiser = (denoiser_.optix_denoiser == nullptr) ||
(denoiser_.use_pass_albedo != context.use_pass_albedo) ||
(denoiser_.use_pass_normal != context.use_pass_normal);
(denoiser_.use_pass_normal != context.use_pass_normal) ||
(denoiser_.use_pass_flow != context.use_pass_flow);
if (!recreate_denoiser) {
return true;
}
@@ -895,8 +929,14 @@ bool OptiXDevice::denoise_create_if_needed(DenoiseContext &context)
OptixDenoiserOptions denoiser_options = {};
denoiser_options.guideAlbedo = context.use_pass_albedo;
denoiser_options.guideNormal = context.use_pass_normal;
OptixDenoiserModelKind model = OPTIX_DENOISER_MODEL_KIND_HDR;
if (context.use_pass_flow) {
model = OPTIX_DENOISER_MODEL_KIND_TEMPORAL;
}
const OptixResult result = optixDenoiserCreate(
this->context, OPTIX_DENOISER_MODEL_KIND_HDR, &denoiser_options, &denoiser_.optix_denoiser);
this->context, model, &denoiser_options, &denoiser_.optix_denoiser);
if (result != OPTIX_SUCCESS) {
set_error("Failed to create OptiX denoiser");
@@ -906,6 +946,7 @@ bool OptiXDevice::denoise_create_if_needed(DenoiseContext &context)
/* OptiX denoiser handle was created with the requested number of input passes. */
denoiser_.use_pass_albedo = context.use_pass_albedo;
denoiser_.use_pass_normal = context.use_pass_normal;
denoiser_.use_pass_flow = context.use_pass_flow;
/* OptiX denoiser has been created, but it needs configuration. */
denoiser_.is_configured = false;
@@ -965,8 +1006,10 @@ bool OptiXDevice::denoise_run(DenoiseContext &context, const DenoisePass &pass)
OptixImage2D color_layer = {0};
OptixImage2D albedo_layer = {0};
OptixImage2D normal_layer = {0};
OptixImage2D flow_layer = {0};
OptixImage2D output_layer = {0};
OptixImage2D prev_output_layer = {0};
/* Color pass. */
{
@@ -982,6 +1025,19 @@ bool OptiXDevice::denoise_run(DenoiseContext &context, const DenoisePass &pass)
color_layer.format = OPTIX_PIXEL_FORMAT_FLOAT3;
}
/* Previous output. */
if (context.prev_output.offset != PASS_UNUSED) {
const int64_t pass_stride_in_bytes = context.prev_output.pass_stride * sizeof(float);
prev_output_layer.data = context.prev_output.device_pointer +
context.prev_output.offset * sizeof(float);
prev_output_layer.width = width;
prev_output_layer.height = height;
prev_output_layer.rowStrideInBytes = pass_stride_in_bytes * context.prev_output.stride;
prev_output_layer.pixelStrideInBytes = pass_stride_in_bytes;
prev_output_layer.format = OPTIX_PIXEL_FORMAT_FLOAT3;
}
/* Optional albedo and color passes. */
if (context.num_input_passes > 1) {
const device_ptr d_guiding_buffer = context.guiding_params.device_pointer;
@@ -1005,21 +1061,32 @@ bool OptiXDevice::denoise_run(DenoiseContext &context, const DenoisePass &pass)
normal_layer.pixelStrideInBytes = pixel_stride_in_bytes;
normal_layer.format = OPTIX_PIXEL_FORMAT_FLOAT3;
}
if (context.use_pass_flow) {
flow_layer.data = d_guiding_buffer + context.guiding_params.pass_flow * sizeof(float);
flow_layer.width = width;
flow_layer.height = height;
flow_layer.rowStrideInBytes = row_stride_in_bytes;
flow_layer.pixelStrideInBytes = pixel_stride_in_bytes;
flow_layer.format = OPTIX_PIXEL_FORMAT_FLOAT2;
}
}
/* Denoise in-place of the noisy input in the render buffers. */
output_layer = color_layer;
/* Finally run denoising. */
OptixDenoiserParams params = {}; /* All parameters are disabled/zero. */
OptixDenoiserLayer image_layers = {};
image_layers.input = color_layer;
image_layers.output = output_layer;
OptixDenoiserGuideLayer guide_layers = {};
guide_layers.albedo = albedo_layer;
guide_layers.normal = normal_layer;
guide_layers.flow = flow_layer;
OptixDenoiserLayer image_layers = {};
image_layers.input = color_layer;
image_layers.previousOutput = prev_output_layer;
image_layers.output = output_layer;
/* Finally run denoising. */
OptixDenoiserParams params = {}; /* All parameters are disabled/zero. */
optix_assert(optixUtilDenoiserInvokeTiled(denoiser_.optix_denoiser,
denoiser_.queue.stream(),

View File

@@ -104,6 +104,7 @@ class OptiXDevice : public CUDADevice {
bool use_pass_albedo = false;
bool use_pass_normal = false;
bool use_pass_flow = false;
};
Denoiser denoiser_;

View File

@@ -19,6 +19,7 @@
#include "device/kernel.h"
#include "device/graphics_interop.h"
#include "util/debug.h"
#include "util/log.h"
#include "util/map.h"
#include "util/string.h"
@@ -42,7 +43,7 @@ struct DeviceKernelArguments {
KERNEL_FILM_CONVERT,
};
static const int MAX_ARGS = 16;
static const int MAX_ARGS = 18;
Type types[MAX_ARGS];
void *values[MAX_ARGS];
size_t sizes[MAX_ARGS];
@@ -85,6 +86,8 @@ struct DeviceKernelArguments {
}
void add(const Type type, const void *value, size_t size)
{
assert(count < MAX_ARGS);
types[count] = type;
values[count] = (void *)value;
sizes[count] = size;

View File

@@ -115,7 +115,9 @@ bool PathTrace::ready_to_reset()
return false;
}
void PathTrace::reset(const BufferParams &full_params, const BufferParams &big_tile_params)
void PathTrace::reset(const BufferParams &full_params,
const BufferParams &big_tile_params,
const bool reset_rendering)
{
if (big_tile_params_.modified(big_tile_params)) {
big_tile_params_ = big_tile_params;
@@ -128,7 +130,7 @@ void PathTrace::reset(const BufferParams &full_params, const BufferParams &big_t
* It is requires to inform about reset whenever it happens, so that the redraw state tracking is
* properly updated. */
if (display_) {
display_->reset(full_params);
display_->reset(big_tile_params, reset_rendering);
}
render_state_.has_denoised_result = false;
@@ -594,6 +596,15 @@ void PathTrace::draw()
did_draw_after_reset_ |= display_->draw();
}
void PathTrace::flush_display()
{
if (!display_) {
return;
}
display_->flush();
}
void PathTrace::update_display(const RenderWork &render_work)
{
if (!render_work.display.update) {
@@ -622,9 +633,8 @@ void PathTrace::update_display(const RenderWork &render_work)
if (display_) {
VLOG(3) << "Perform copy to GPUDisplay work.";
const int resolution_divider = render_work.resolution_divider;
const int texture_width = max(1, full_params_.width / resolution_divider);
const int texture_height = max(1, full_params_.height / resolution_divider);
const int texture_width = render_state_.effective_big_tile_params.window_width;
const int texture_height = render_state_.effective_big_tile_params.window_height;
if (!display_->update_begin(texture_width, texture_height)) {
LOG(ERROR) << "Error beginning GPUDisplay update.";
return;

View File

@@ -72,7 +72,9 @@ class PathTrace {
* render result. */
bool ready_to_reset();
void reset(const BufferParams &full_params, const BufferParams &big_tile_params);
void reset(const BufferParams &full_params,
const BufferParams &big_tile_params,
bool reset_rendering);
void device_free();
@@ -112,6 +114,9 @@ class PathTrace {
/* Perform drawing of the current state of the DisplayDriver. */
void draw();
/* Flush outstanding display commands before ending the render loop. */
void flush_display();
/* Cancel rendering process as soon as possible, without waiting for full tile to be sampled.
* Used in cases like reset of render session.
*

View File

@@ -26,15 +26,20 @@ PathTraceDisplay::PathTraceDisplay(unique_ptr<DisplayDriver> driver) : driver_(m
{
}
void PathTraceDisplay::reset(const BufferParams &buffer_params)
void PathTraceDisplay::reset(const BufferParams &buffer_params, const bool reset_rendering)
{
thread_scoped_lock lock(mutex_);
params_.full_offset = make_int2(buffer_params.full_x, buffer_params.full_y);
params_.full_offset = make_int2(buffer_params.full_x + buffer_params.window_x,
buffer_params.full_y + buffer_params.window_y);
params_.full_size = make_int2(buffer_params.full_width, buffer_params.full_height);
params_.size = make_int2(buffer_params.width, buffer_params.height);
params_.size = make_int2(buffer_params.window_width, buffer_params.window_height);
texture_state_.is_outdated = true;
if (!reset_rendering) {
driver_->next_tile_begin();
}
}
void PathTraceDisplay::mark_texture_updated()
@@ -248,4 +253,9 @@ bool PathTraceDisplay::draw()
return !is_outdated;
}
void PathTraceDisplay::flush()
{
driver_->flush();
}
CCL_NAMESPACE_END

View File

@@ -38,14 +38,17 @@ class BufferParams;
class PathTraceDisplay {
public:
PathTraceDisplay(unique_ptr<DisplayDriver> driver);
explicit PathTraceDisplay(unique_ptr<DisplayDriver> driver);
virtual ~PathTraceDisplay() = default;
/* Reset the display for the new state of render session. Is called whenever session is reset,
* which happens on changes like viewport navigation or viewport dimension change.
*
* This call will configure parameters for a changed buffer and reset the texture state. */
void reset(const BufferParams &buffer_params);
* This call will configure parameters for a changed buffer and reset the texture state.
*
* When the `reset_rendering` a complete display reset happens. When it is false reset happens
* for a new state of the buffer parameters which is assumed to correspond to the next tile. */
void reset(const BufferParams &buffer_params, bool reset_rendering);
/* --------------------------------------------------------------------
* Update procedure.
@@ -151,6 +154,9 @@ class PathTraceDisplay {
* Returns true if this call did draw an updated state of the texture. */
bool draw();
/* Flush outstanding display commands before ending the render loop. */
void flush();
private:
/* Display driver implemented by the host application. */
unique_ptr<DisplayDriver> driver_;

View File

@@ -194,10 +194,10 @@ PassAccessor::Destination PathTraceWork::get_display_destination_template(
PassAccessor::Destination destination(film_->get_display_pass());
const int2 display_texture_size = display->get_texture_size();
const int texture_x = effective_buffer_params_.full_x - effective_full_params_.full_x +
effective_buffer_params_.window_x;
const int texture_y = effective_buffer_params_.full_y - effective_full_params_.full_y +
effective_buffer_params_.window_y;
const int texture_x = effective_buffer_params_.full_x - effective_big_tile_params_.full_x +
effective_buffer_params_.window_x - effective_big_tile_params_.window_x;
const int texture_y = effective_buffer_params_.full_y - effective_big_tile_params_.full_y +
effective_buffer_params_.window_y - effective_big_tile_params_.window_y;
destination.offset = texture_y * display_texture_size.x + texture_x;
destination.stride = display_texture_size.x;

View File

@@ -875,8 +875,10 @@ void PathTraceWorkGPU::copy_to_display_naive(PathTraceDisplay *display,
const int final_width = buffers_->params.window_width;
const int final_height = buffers_->params.window_height;
const int texture_x = full_x - effective_full_params_.full_x + effective_buffer_params_.window_x;
const int texture_y = full_y - effective_full_params_.full_y + effective_buffer_params_.window_y;
const int texture_x = full_x - effective_big_tile_params_.full_x +
effective_buffer_params_.window_x - effective_big_tile_params_.window_x;
const int texture_y = full_y - effective_big_tile_params_.full_y +
effective_buffer_params_.window_y - effective_big_tile_params_.window_y;
/* Re-allocate display memory if needed, and make sure the device pointer is allocated.
*

View File

@@ -406,9 +406,6 @@ bool RenderScheduler::set_postprocess_render_work(RenderWork *render_work)
any_scheduled = true;
}
/* Force update. */
any_scheduled = true;
if (any_scheduled) {
render_work->display.update = true;
}

View File

@@ -283,7 +283,7 @@ class RenderScheduler {
/* Check whether timing report about the given work need to reset accumulated average time. */
bool work_report_reset_average(const RenderWork &render_work);
/* CHeck whether render time limit has been reached (or exceeded), and if so store related
/* Check whether render time limit has been reached (or exceeded), and if so store related
* information in the state so that rendering is considered finished, and is possible to report
* average render time information. */
void check_time_limit_reached();

View File

@@ -243,6 +243,10 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
}
}
#ifdef __KERNEL_METAL__
constant int __dummy_constant [[function_constant(0)]];
#endif
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(integrator_shade_surface_raytrace,
ccl_global const int *path_index_array,
@@ -253,7 +257,16 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
if (global_index < work_size) {
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
#ifdef __KERNEL_METAL__
KernelGlobals kg = NULL;
/* Workaround Ambient Occlusion and Bevel nodes not working with Metal.
* Dummy offset should not affect result, but somehow fixes bug! */
kg += __dummy_constant;
ccl_gpu_kernel_call(integrator_shade_surface_raytrace(kg, state, render_buffer));
#else
ccl_gpu_kernel_call(integrator_shade_surface_raytrace(NULL, state, render_buffer));
#endif
}
}
@@ -756,6 +769,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
int guiding_pass_stride,
int guiding_pass_albedo,
int guiding_pass_normal,
int guiding_pass_flow,
ccl_global const float *render_buffer,
int render_offset,
int render_stride,
@@ -763,6 +777,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
int render_pass_sample_count,
int render_pass_denoising_albedo,
int render_pass_denoising_normal,
int render_pass_motion,
int full_x,
int full_y,
int width,
@@ -814,6 +829,17 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
normal_out[1] = normal_in[1] * pixel_scale;
normal_out[2] = normal_in[2] * pixel_scale;
}
/* Flow pass. */
if (guiding_pass_flow != PASS_UNUSED) {
kernel_assert(render_pass_motion != PASS_UNUSED);
ccl_global const float *motion_in = buffer + render_pass_motion;
ccl_global float *flow_out = guiding_pixel + guiding_pass_flow;
flow_out[0] = -motion_in[0] * pixel_scale;
flow_out[1] = -motion_in[1] * pixel_scale;
}
}
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
@@ -899,7 +925,6 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
else {
/* Assigning to zero since this is a default alpha value for 3-component passes, and it
* is an opaque pixel for 4 component passes. */
denoised_pixel[3] = 0;
}
}

View File

@@ -98,8 +98,12 @@ using namespace metal::raytracing;
#define FN14(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14) p1; p2; p3; p4; p5; p6; p7; p8; p9; p10; p11; p12; p13; p14;
#define FN15(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15) p1; p2; p3; p4; p5; p6; p7; p8; p9; p10; p11; p12; p13; p14; p15;
#define FN16(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16) p1; p2; p3; p4; p5; p6; p7; p8; p9; p10; p11; p12; p13; p14; p15; p16;
#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)
#define FN17(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17) p1; p2; p3; p4; p5; p6; p7; p8; p9; p10; p11; p12; p13; p14; p15; p16; p17;
#define FN18(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18) p1; p2; p3; p4; p5; p6; p7; p8; p9; p10; p11; p12; p13; p14; p15; p16; p17; p18;
#define FN19(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19) p1; p2; p3; p4; p5; p6; p7; p8; p9; p10; p11; p12; p13; p14; p15; p16; p17; p18; p19;
#define FN20(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20) p1; p2; p3; p4; p5; p6; p7; p8; p9; p10; p11; p12; p13; p14; p15; p16; p17; p18; p19; p20;
#define GET_LAST_ARG(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, ...) p20
#define PARAMS_MAKER(...) GET_LAST_ARG(__VA_ARGS__, FN20, FN19, FN18, FN17, FN16, FN15, FN14, FN13, FN12, FN11, FN10, FN9, FN8, FN7, FN6, FN5, FN4, FN3, FN2, FN1, FN0)
/* Generate a struct containing the entry-point parameters and a "run"
* method which can access them implicitly via this-> */

View File

@@ -92,6 +92,14 @@ ccl_device_forceinline void kernel_write_denoising_features_surface(
else if (sc->type == CLOSURE_BSDF_HAIR_PRINCIPLED_ID) {
closure_albedo *= bsdf_principled_hair_albedo(sc);
}
else if (sc->type == CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID) {
/* BSSRDF already accounts for weight, retro-reflection would double up. */
ccl_private const PrincipledDiffuseBsdf *bsdf = (ccl_private const PrincipledDiffuseBsdf *)
sc;
if (bsdf->components == PRINCIPLED_DIFFUSE_RETRO_REFLECTION) {
continue;
}
}
if (bsdf_get_specular_roughness_squared(sc) > sqr(0.075f)) {
diffuse_albedo += closure_albedo;

View File

@@ -116,6 +116,52 @@ ccl_device_inline void motion_triangle_vertices(
verts[2] = (1.0f - t) * verts[2] + t * next_verts[2];
}
ccl_device_inline void motion_triangle_vertices_and_normals(
KernelGlobals kg, int object, int prim, float time, float3 verts[3], float3 normals[3])
{
/* get motion info */
int numsteps, numverts;
object_motion_info(kg, object, &numsteps, &numverts, NULL);
/* Figure out which steps we need to fetch and their interpolation factor. */
int maxstep = numsteps * 2;
int step = min((int)(time * maxstep), maxstep - 1);
float t = time * maxstep - step;
/* Find attribute. */
int offset = intersection_find_attribute(kg, object, ATTR_STD_MOTION_VERTEX_POSITION);
kernel_assert(offset != ATTR_STD_NOT_FOUND);
/* Fetch vertex coordinates. */
float3 next_verts[3];
uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step, verts);
motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step + 1, next_verts);
/* Interpolate between steps. */
verts[0] = (1.0f - t) * verts[0] + t * next_verts[0];
verts[1] = (1.0f - t) * verts[1] + t * next_verts[1];
verts[2] = (1.0f - t) * verts[2] + t * next_verts[2];
/* Compute smooth normal. */
/* Find attribute. */
offset = intersection_find_attribute(kg, object, ATTR_STD_MOTION_VERTEX_NORMAL);
kernel_assert(offset != ATTR_STD_NOT_FOUND);
/* Fetch vertex coordinates. */
float3 next_normals[3];
motion_triangle_normals_for_step(kg, tri_vindex, offset, numverts, numsteps, step, normals);
motion_triangle_normals_for_step(
kg, tri_vindex, offset, numverts, numsteps, step + 1, next_normals);
/* Interpolate between steps. */
normals[0] = (1.0f - t) * normals[0] + t * next_normals[0];
normals[1] = (1.0f - t) * normals[1] + t * next_normals[1];
normals[2] = (1.0f - t) * normals[2] + t * next_normals[2];
}
ccl_device_inline float3 motion_triangle_smooth_normal(
KernelGlobals kg, float3 Ng, int object, int prim, float u, float v, float time)
{

View File

@@ -141,14 +141,23 @@ ccl_device_inline float3 shadow_ray_smooth_surface_offset(
KernelGlobals kg, ccl_private const ShaderData *ccl_restrict sd, float3 Ng)
{
float3 V[3], N[3];
triangle_vertices_and_normals(kg, sd->prim, V, N);
if (sd->type == PRIMITIVE_MOTION_TRIANGLE) {
motion_triangle_vertices_and_normals(kg, sd->object, sd->prim, sd->time, V, N);
}
else {
kernel_assert(sd->type == PRIMITIVE_TRIANGLE);
triangle_vertices_and_normals(kg, sd->prim, V, N);
}
const float u = sd->u, v = sd->v;
const float w = 1 - u - v;
float3 P = V[0] * u + V[1] * v + V[2] * w; /* Local space */
float3 n = N[0] * u + N[1] * v + N[2] * w; /* We get away without normalization */
object_normal_transform(kg, sd, &n); /* Normal x scale, world space */
if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
object_normal_transform(kg, sd, &n); /* Normal x scale, world space */
}
/* Parabolic approximation */
float a = dot(N[2] - N[0], V[0] - V[2]);

View File

@@ -85,6 +85,4 @@ shader node_normal_map(normal NormalIn = N,
if (Strength != 1.0)
Normal = normalize(NormalIn + (Normal - NormalIn) * max(Strength, 0.0));
Normal = ensure_valid_reflection(Ng, I, Normal);
}

View File

@@ -25,7 +25,7 @@ ccl_device_noinline_cpu float3 svm_magic(float3 p, float scale, int n, float dis
/*
* Prevent NaNs due to input p
* Sin and Cosine are periodic about [0 2*PI) so the following
* will yeild a more accurate result. As it stops the input values
* will yield a more accurate result. As it stops the input values
* going out of range for floats which caused a NaN. The
* calculation of (px + py + pz)*5 can cause an Inf when one or more
* values are very large the cos or sin of this results in a NaN

View File

@@ -124,7 +124,7 @@ typedef enum ShaderNodeType {
NODE_AOV_VALUE,
NODE_FLOAT_CURVE,
/* NOTE: for best OpenCL performance, item definition in the enum must
* match the switch case order in svm.h. */
* match the switch case order in `svm.h`. */
} ShaderNodeType;
typedef enum NodeAttributeOutputType {

View File

@@ -202,7 +202,7 @@ enum SamplingPattern {
/* These flags values correspond to `raytypes` in `osl.cpp`, so keep them in sync! */
enum PathRayFlag {
enum PathRayFlag : uint32_t {
/* --------------------------------------------------------------------
* Ray visibility.
*
@@ -388,6 +388,7 @@ typedef enum PassType {
PASS_DENOISING_NORMAL,
PASS_DENOISING_ALBEDO,
PASS_DENOISING_DEPTH,
PASS_DENOISING_PREVIOUS,
/* PASS_SHADOW_CATCHER accumulates contribution of shadow catcher object which is not affected by
* any other object. The pass accessor will divide the combined pass by the shadow catcher. The
@@ -1559,7 +1560,7 @@ enum {
/* Kernel Features */
enum KernelFeatureFlag : unsigned int {
enum KernelFeatureFlag : uint32_t {
/* Shader nodes. */
KERNEL_FEATURE_NODE_BSDF = (1U << 0U),
KERNEL_FEATURE_NODE_EMISSION = (1U << 1U),

View File

@@ -1002,10 +1002,10 @@ void GeometryManager::device_update_attributes(Device *device,
/* After mesh attributes and patch tables have been copied to device memory,
* we need to update offsets in the objects. */
scene->object_manager->device_update_mesh_offsets(device, dscene, scene);
scene->object_manager->device_update_geom_offsets(device, dscene, scene);
}
void GeometryManager::mesh_calc_offset(Scene *scene, BVHLayout bvh_layout)
void GeometryManager::geom_calc_offset(Scene *scene, BVHLayout bvh_layout)
{
size_t vert_size = 0;
size_t tri_size = 0;
@@ -1922,7 +1922,7 @@ void GeometryManager::device_update(Device *device,
const BVHLayout bvh_layout = BVHParams::best_bvh_layout(scene->params.bvh_layout,
device->get_bvh_layout_mask());
mesh_calc_offset(scene, bvh_layout);
geom_calc_offset(scene, bvh_layout);
if (true_displacement_used || curve_shadow_transparency_used) {
scoped_callback_timer timer([scene](double time) {
if (scene->update_stats) {

View File

@@ -242,7 +242,7 @@ class GeometryManager {
vector<AttributeRequestSet> &object_attributes);
/* Compute verts/triangles/curves offsets in global arrays. */
void mesh_calc_offset(Scene *scene, BVHLayout bvh_layout);
void geom_calc_offset(Scene *scene, BVHLayout bvh_layout);
void device_update_object(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);

View File

@@ -381,8 +381,15 @@ ImageHandle ImageManager::add_image(const string &filename,
foreach (int tile, tiles) {
string tile_filename = filename;
/* Since we don't have information about the exact tile format used in this code location,
* just attempt all replacement patterns that Blender supports. */
if (tile != 0) {
string_replace(tile_filename, "<UDIM>", string_printf("%04d", tile));
int u = ((tile - 1001) % 10);
int v = ((tile - 1001) / 10);
string_replace(tile_filename, "<UVTILE>", string_printf("u%d_v%d", u + 1, v + 1));
}
const int slot = add_image_slot(new OIIOImageLoader(tile_filename), params, false);
handle.tile_slots.push_back(slot);

View File

@@ -821,7 +821,7 @@ void ObjectManager::device_update_flags(
dscene->object_volume_step.clear_modified();
}
void ObjectManager::device_update_mesh_offsets(Device *, DeviceScene *dscene, Scene *scene)
void ObjectManager::device_update_geom_offsets(Device *, DeviceScene *dscene, Scene *scene)
{
if (dscene->objects.size() == 0) {
return;

View File

@@ -162,7 +162,7 @@ class ObjectManager {
Scene *scene,
Progress &progress,
bool bounds_valid = true);
void device_update_mesh_offsets(Device *device, DeviceScene *dscene, Scene *scene);
void device_update_geom_offsets(Device *device, DeviceScene *dscene, Scene *scene);
void device_free(Device *device, DeviceScene *dscene, bool force_free);

View File

@@ -101,6 +101,7 @@ const NodeEnum *Pass::get_type_enum()
pass_type_enum.insert("denoising_normal", PASS_DENOISING_NORMAL);
pass_type_enum.insert("denoising_albedo", PASS_DENOISING_ALBEDO);
pass_type_enum.insert("denoising_depth", PASS_DENOISING_DEPTH);
pass_type_enum.insert("denoising_previous", PASS_DENOISING_PREVIOUS);
pass_type_enum.insert("shadow_catcher", PASS_SHADOW_CATCHER);
pass_type_enum.insert("shadow_catcher_sample_count", PASS_SHADOW_CATCHER_SAMPLE_COUNT);
@@ -299,6 +300,10 @@ PassInfo Pass::get_info(const PassType type, const bool include_albedo)
case PASS_DENOISING_DEPTH:
pass_info.num_components = 1;
break;
case PASS_DENOISING_PREVIOUS:
pass_info.num_components = 3;
pass_info.use_exposure = true;
break;
case PASS_SHADOW_CATCHER:
pass_info.num_components = 3;

View File

@@ -5901,7 +5901,7 @@ VectorMapRangeNode::VectorMapRangeNode() : ShaderNode(get_node_type())
{
}
void VectorMapRangeNode::expand(ShaderGraph *graph)
void VectorMapRangeNode::expand(ShaderGraph * /*graph*/)
{
}

View File

@@ -16,62 +16,17 @@
#include "session/denoising.h"
#if 0
#include "util/map.h"
#include "util/system.h"
#include "util/task.h"
#include "util/time.h"
# include "kernel/filter/filter_defines.h"
# include "util/util_foreach.h"
# include "util/util_map.h"
# include "util/util_system.h"
# include "util/util_task.h"
# include "util/util_time.h"
# include <OpenImageIO/filesystem.h>
#include <OpenImageIO/filesystem.h>
CCL_NAMESPACE_BEGIN
/* Utility Functions */
static void print_progress(int num, int total, int frame, int num_frames)
{
const char *label = "Denoise Frame ";
int cols = system_console_width();
cols -= strlen(label);
int len = 1;
for (int x = total; x > 9; x /= 10) {
len++;
}
int bars = cols - 2 * len - 6;
printf("\r%s", label);
if (num_frames > 1) {
int frame_len = 1;
for (int x = num_frames - 1; x > 9; x /= 10) {
frame_len++;
}
bars -= frame_len + 2;
printf("%*d ", frame_len, frame);
}
int v = int(float(num) * bars / total);
printf("[");
for (int i = 0; i < v; i++) {
printf("=");
}
if (v < bars) {
printf(">");
}
for (int i = v + 1; i < bars; i++) {
printf(" ");
}
printf(string_printf("] %%%dd / %d", len, total).c_str(), num);
fflush(stdout);
}
/* Splits in at its last dot, setting suffix to the part after the dot and in to the part before
* it. Returns whether a dot was found. */
static bool split_last_dot(string &in, string &suffix)
@@ -125,24 +80,18 @@ static void fill_mapping(vector<ChannelMapping> &map, int pos, string name, stri
}
}
static const int INPUT_NUM_CHANNELS = 15;
static const int INPUT_DENOISING_DEPTH = 0;
static const int INPUT_DENOISING_NORMAL = 1;
static const int INPUT_DENOISING_SHADOWING = 4;
static const int INPUT_DENOISING_ALBEDO = 5;
static const int INPUT_NOISY_IMAGE = 8;
static const int INPUT_DENOISING_VARIANCE = 11;
static const int INPUT_DENOISING_INTENSITY = 14;
static const int INPUT_NUM_CHANNELS = 13;
static const int INPUT_NOISY_IMAGE = 0;
static const int INPUT_DENOISING_NORMAL = 3;
static const int INPUT_DENOISING_ALBEDO = 6;
static const int INPUT_MOTION = 9;
static vector<ChannelMapping> input_channels()
{
vector<ChannelMapping> map;
fill_mapping(map, INPUT_DENOISING_DEPTH, "Denoising Depth", "Z");
fill_mapping(map, INPUT_NOISY_IMAGE, "Combined", "RGB");
fill_mapping(map, INPUT_DENOISING_NORMAL, "Denoising Normal", "XYZ");
fill_mapping(map, INPUT_DENOISING_SHADOWING, "Denoising Shadowing", "X");
fill_mapping(map, INPUT_DENOISING_ALBEDO, "Denoising Albedo", "RGB");
fill_mapping(map, INPUT_NOISY_IMAGE, "Noisy Image", "RGB");
fill_mapping(map, INPUT_DENOISING_VARIANCE, "Denoising Variance", "RGB");
fill_mapping(map, INPUT_DENOISING_INTENSITY, "Denoising Intensity", "X");
fill_mapping(map, INPUT_MOTION, "Vector", "XYZW");
return map;
}
@@ -162,7 +111,7 @@ bool DenoiseImageLayer::detect_denoising_channels()
input_to_image_channel.clear();
input_to_image_channel.resize(INPUT_NUM_CHANNELS, -1);
foreach (const ChannelMapping &mapping, input_channels()) {
for (const ChannelMapping &mapping : input_channels()) {
vector<string>::iterator i = find(channels.begin(), channels.end(), mapping.name);
if (i == channels.end()) {
return false;
@@ -177,7 +126,7 @@ bool DenoiseImageLayer::detect_denoising_channels()
output_to_image_channel.clear();
output_to_image_channel.resize(OUTPUT_NUM_CHANNELS, -1);
foreach (const ChannelMapping &mapping, output_channels()) {
for (const ChannelMapping &mapping : output_channels()) {
vector<string>::iterator i = find(channels.begin(), channels.end(), mapping.name);
if (i == channels.end()) {
return false;
@@ -199,18 +148,16 @@ bool DenoiseImageLayer::detect_denoising_channels()
return true;
}
bool DenoiseImageLayer::match_channels(int neighbor,
const std::vector<string> &channelnames,
bool DenoiseImageLayer::match_channels(const std::vector<string> &channelnames,
const std::vector<string> &neighbor_channelnames)
{
neighbor_input_to_image_channel.resize(neighbor + 1);
vector<int> &mapping = neighbor_input_to_image_channel[neighbor];
vector<int> &mapping = previous_output_to_image_channel;
assert(mapping.size() == 0);
mapping.resize(input_to_image_channel.size(), -1);
mapping.resize(output_to_image_channel.size(), -1);
for (int i = 0; i < input_to_image_channel.size(); i++) {
const string &channel = channelnames[input_to_image_channel[i]];
for (int i = 0; i < output_to_image_channel.size(); i++) {
const string &channel = channelnames[output_to_image_channel[i]];
std::vector<string>::const_iterator frame_channel = find(
neighbor_channelnames.begin(), neighbor_channelnames.end(), channel);
@@ -226,19 +173,9 @@ bool DenoiseImageLayer::match_channels(int neighbor,
/* Denoise Task */
DenoiseTask::DenoiseTask(Device *device,
DenoiserPipeline *denoiser,
int frame,
const vector<int> &neighbor_frames)
: denoiser(denoiser),
device(device),
frame(frame),
neighbor_frames(neighbor_frames),
current_layer(0),
input_pixels(device, "filter input buffer", MEM_READ_ONLY),
num_tiles(0)
DenoiseTask::DenoiseTask(Device *device, DenoiserPipeline *denoiser, int frame)
: denoiser(denoiser), device(device), frame(frame), current_layer(0), buffers(device)
{
image.samples = denoiser->samples_override;
}
DenoiseTask::~DenoiseTask()
@@ -246,284 +183,39 @@ DenoiseTask::~DenoiseTask()
free();
}
/* Device callbacks */
bool DenoiseTask::acquire_tile(Device *device, Device *tile_device, RenderTile &tile)
{
thread_scoped_lock tile_lock(tiles_mutex);
if (tiles.empty()) {
return false;
}
tile = tiles.front();
tiles.pop_front();
device->map_tile(tile_device, tile);
print_progress(num_tiles - tiles.size(), num_tiles, frame, denoiser->num_frames);
return true;
}
/* Mapping tiles is required for regular rendering since each tile has its separate memory
* which may be allocated on a different device.
* For standalone denoising, there is a single memory that is present on all devices, so the only
* thing that needs to be done here is to specify the surrounding tile geometry.
*
* However, since there is only one large memory, the denoised result has to be written to
* a different buffer to avoid having to copy an entire horizontal slice of the image. */
void DenoiseTask::map_neighboring_tiles(RenderTileNeighbors &neighbors, Device *tile_device)
{
RenderTile &center_tile = neighbors.tiles[RenderTileNeighbors::CENTER];
RenderTile &target_tile = neighbors.target;
/* Fill tile information. */
for (int i = 0; i < RenderTileNeighbors::SIZE; i++) {
if (i == RenderTileNeighbors::CENTER) {
continue;
}
RenderTile &tile = neighbors.tiles[i];
int dx = (i % 3) - 1;
int dy = (i / 3) - 1;
tile.x = clamp(center_tile.x + dx * denoiser->tile_size.x, 0, image.width);
tile.w = clamp(center_tile.x + (dx + 1) * denoiser->tile_size.x, 0, image.width) - tile.x;
tile.y = clamp(center_tile.y + dy * denoiser->tile_size.y, 0, image.height);
tile.h = clamp(center_tile.y + (dy + 1) * denoiser->tile_size.y, 0, image.height) - tile.y;
tile.buffer = center_tile.buffer;
tile.offset = center_tile.offset;
tile.stride = image.width;
}
/* Allocate output buffer. */
device_vector<float> *output_mem = new device_vector<float>(
tile_device, "denoising_output", MEM_READ_WRITE);
output_mem->alloc(OUTPUT_NUM_CHANNELS * center_tile.w * center_tile.h);
/* Fill output buffer with noisy image, assumed by kernel_filter_finalize
* when skipping denoising of some pixels. */
float *result = output_mem->data();
float *in = &image.pixels[image.num_channels * (center_tile.y * image.width + center_tile.x)];
const DenoiseImageLayer &layer = image.layers[current_layer];
const int *input_to_image_channel = layer.input_to_image_channel.data();
for (int y = 0; y < center_tile.h; y++) {
for (int x = 0; x < center_tile.w; x++, result += OUTPUT_NUM_CHANNELS) {
for (int i = 0; i < OUTPUT_NUM_CHANNELS; i++) {
result[i] = in[image.num_channels * x + input_to_image_channel[INPUT_NOISY_IMAGE + i]];
}
}
in += image.num_channels * image.width;
}
output_mem->copy_to_device();
/* Fill output tile info. */
target_tile = center_tile;
target_tile.buffer = output_mem->device_pointer;
target_tile.stride = target_tile.w;
target_tile.offset -= target_tile.x + target_tile.y * target_tile.stride;
thread_scoped_lock output_lock(output_mutex);
assert(output_pixels.count(center_tile.tile_index) == 0);
output_pixels[target_tile.tile_index] = output_mem;
}
void DenoiseTask::unmap_neighboring_tiles(RenderTileNeighbors &neighbors)
{
RenderTile &center_tile = neighbors.tiles[RenderTileNeighbors::CENTER];
RenderTile &target_tile = neighbors.target;
thread_scoped_lock output_lock(output_mutex);
assert(output_pixels.count(center_tile.tile_index) == 1);
device_vector<float> *output_mem = output_pixels[target_tile.tile_index];
output_pixels.erase(center_tile.tile_index);
output_lock.unlock();
/* Copy denoised pixels from device. */
output_mem->copy_from_device(0, OUTPUT_NUM_CHANNELS * target_tile.w, target_tile.h);
float *result = output_mem->data();
float *out = &image.pixels[image.num_channels * (target_tile.y * image.width + target_tile.x)];
const DenoiseImageLayer &layer = image.layers[current_layer];
const int *output_to_image_channel = layer.output_to_image_channel.data();
for (int y = 0; y < target_tile.h; y++) {
for (int x = 0; x < target_tile.w; x++, result += OUTPUT_NUM_CHANNELS) {
for (int i = 0; i < OUTPUT_NUM_CHANNELS; i++) {
out[image.num_channels * x + output_to_image_channel[i]] = result[i];
}
}
out += image.num_channels * image.width;
}
/* Free device buffer. */
output_mem->free();
delete output_mem;
}
void DenoiseTask::release_tile()
{
}
bool DenoiseTask::get_cancel()
{
return false;
}
void DenoiseTask::create_task(DeviceTask &task)
{
/* Callback functions. */
task.acquire_tile = function_bind(&DenoiseTask::acquire_tile, this, device, _1, _2);
task.map_neighbor_tiles = function_bind(&DenoiseTask::map_neighboring_tiles, this, _1, _2);
task.unmap_neighbor_tiles = function_bind(&DenoiseTask::unmap_neighboring_tiles, this, _1);
task.release_tile = function_bind(&DenoiseTask::release_tile, this);
task.get_cancel = function_bind(&DenoiseTask::get_cancel, this);
/* Denoising parameters. */
task.denoising = denoiser->params;
task.denoising.type = DENOISER_NLM;
task.denoising.use = true;
task.denoising_from_render = false;
task.denoising_frames.resize(neighbor_frames.size());
for (int i = 0; i < neighbor_frames.size(); i++) {
task.denoising_frames[i] = neighbor_frames[i] - frame;
}
/* Buffer parameters. */
task.pass_stride = INPUT_NUM_CHANNELS;
task.target_pass_stride = OUTPUT_NUM_CHANNELS;
task.pass_denoising_data = 0;
task.pass_denoising_clean = -1;
task.frame_stride = image.width * image.height * INPUT_NUM_CHANNELS;
/* Create tiles. */
thread_scoped_lock tile_lock(tiles_mutex);
thread_scoped_lock output_lock(output_mutex);
tiles.clear();
assert(output_pixels.empty());
output_pixels.clear();
int tiles_x = divide_up(image.width, denoiser->tile_size.x);
int tiles_y = divide_up(image.height, denoiser->tile_size.y);
for (int ty = 0; ty < tiles_y; ty++) {
for (int tx = 0; tx < tiles_x; tx++) {
RenderTile tile;
tile.x = tx * denoiser->tile_size.x;
tile.y = ty * denoiser->tile_size.y;
tile.w = min(image.width - tile.x, denoiser->tile_size.x);
tile.h = min(image.height - tile.y, denoiser->tile_size.y);
tile.start_sample = 0;
tile.num_samples = image.layers[current_layer].samples;
tile.sample = 0;
tile.offset = 0;
tile.stride = image.width;
tile.tile_index = ty * tiles_x + tx;
tile.task = RenderTile::DENOISE;
tile.buffers = NULL;
tile.buffer = input_pixels.device_pointer;
tiles.push_back(tile);
}
}
num_tiles = tiles.size();
}
/* Denoiser Operations */
bool DenoiseTask::load_input_pixels(int layer)
{
int w = image.width;
int h = image.height;
int num_pixels = image.width * image.height;
int frame_stride = num_pixels * INPUT_NUM_CHANNELS;
/* Load center image */
DenoiseImageLayer &image_layer = image.layers[layer];
float *buffer_data = input_pixels.data();
image.read_pixels(image_layer, buffer_data);
buffer_data += frame_stride;
float *buffer_data = buffers.buffer.data();
image.read_pixels(image_layer, buffers.params, buffer_data);
/* Load neighbor images */
for (int i = 0; i < image.in_neighbors.size(); i++) {
if (!image.read_neighbor_pixels(i, image_layer, buffer_data)) {
error = "Failed to read neighbor frame pixels";
return false;
}
buffer_data += frame_stride;
}
/* Preprocess */
buffer_data = input_pixels.data();
for (int neighbor = 0; neighbor < image.in_neighbors.size() + 1; neighbor++) {
/* Clamp */
if (denoiser->params.clamp_input) {
for (int i = 0; i < num_pixels * INPUT_NUM_CHANNELS; i++) {
buffer_data[i] = clamp(buffer_data[i], -1e8f, 1e8f);
}
}
/* Box blur */
int r = 5 * denoiser->params.radius;
float *data = buffer_data + 14;
array<float> temp(num_pixels);
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int n = 0;
float sum = 0.0f;
for (int dx = max(x - r, 0); dx < min(x + r + 1, w); dx++, n++) {
sum += data[INPUT_NUM_CHANNELS * (y * w + dx)];
}
temp[y * w + x] = sum / n;
}
}
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int n = 0;
float sum = 0.0f;
for (int dy = max(y - r, 0); dy < min(y + r + 1, h); dy++, n++) {
sum += temp[dy * w + x];
}
data[INPUT_NUM_CHANNELS * (y * w + x)] = sum / n;
}
}
/* Highlight compression */
data = buffer_data + 8;
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int idx = INPUT_NUM_CHANNELS * (y * w + x);
float3 color = make_float3(data[idx], data[idx + 1], data[idx + 2]);
color = color_highlight_compress(color, NULL);
data[idx] = color.x;
data[idx + 1] = color.y;
data[idx + 2] = color.z;
}
}
buffer_data += frame_stride;
/* Load previous image */
if (frame > 0 && !image.read_previous_pixels(image_layer, buffers.params, buffer_data)) {
error = "Failed to read neighbor frame pixels";
return false;
}
/* Copy to device */
input_pixels.copy_to_device();
buffers.buffer.copy_to_device();
return true;
}
/* Task stages */
static void add_pass(vector<Pass *> &passes, PassType type, PassMode mode = PassMode::NOISY)
{
Pass *pass = new Pass();
pass->set_type(type);
pass->set_mode(mode);
passes.push_back(pass);
}
bool DenoiseTask::load()
{
string center_filepath = denoiser->input[frame];
@@ -531,7 +223,8 @@ bool DenoiseTask::load()
return false;
}
if (!image.load_neighbors(denoiser->input, neighbor_frames, error)) {
/* Use previous frame output as input for subsequent frames. */
if (frame > 0 && !image.load_previous(denoiser->output[frame - 1], error)) {
return false;
}
@@ -540,10 +233,35 @@ bool DenoiseTask::load()
return false;
}
/* Enable temporal denoising for frames after the first (which will use the output from the
* previous frames). */
DenoiseParams params = denoiser->denoiser->get_params();
params.temporally_stable = frame > 0;
denoiser->denoiser->set_params(params);
/* Allocate device buffer. */
int num_frames = image.in_neighbors.size() + 1;
input_pixels.alloc(image.width * INPUT_NUM_CHANNELS, image.height * num_frames);
input_pixels.zero_to_device();
vector<Pass *> passes;
add_pass(passes, PassType::PASS_COMBINED);
add_pass(passes, PassType::PASS_DENOISING_ALBEDO);
add_pass(passes, PassType::PASS_DENOISING_NORMAL);
add_pass(passes, PassType::PASS_MOTION);
add_pass(passes, PassType::PASS_DENOISING_PREVIOUS);
add_pass(passes, PassType::PASS_COMBINED, PassMode::DENOISED);
BufferParams buffer_params;
buffer_params.width = image.width;
buffer_params.height = image.height;
buffer_params.full_x = 0;
buffer_params.full_y = 0;
buffer_params.full_width = image.width;
buffer_params.full_height = image.height;
buffer_params.update_passes(passes);
for (Pass *pass : passes) {
delete pass;
}
buffers.reset(buffer_params);
/* Read pixels for first layer. */
current_layer = 0;
@@ -565,10 +283,26 @@ bool DenoiseTask::exec()
}
/* Run task on device. */
DeviceTask task(DeviceTask::RENDER);
create_task(task);
device->task_add(task);
device->task_wait();
denoiser->denoiser->denoise_buffer(buffers.params, &buffers, 1, true);
/* Copy denoised pixels from device. */
buffers.buffer.copy_from_device();
float *result = buffers.buffer.data(), *out = image.pixels.data();
const DenoiseImageLayer &layer = image.layers[current_layer];
const int *output_to_image_channel = layer.output_to_image_channel.data();
for (int y = 0; y < image.height; y++) {
for (int x = 0; x < image.width; x++, result += buffers.params.pass_stride) {
for (int j = 0; j < OUTPUT_NUM_CHANNELS; j++) {
int offset = buffers.params.get_pass_offset(PASS_COMBINED, PassMode::DENOISED);
int image_channel = output_to_image_channel[j];
out[image.num_channels * x + image_channel] = result[offset + j];
}
}
out += image.num_channels * image.width;
}
printf("\n");
}
@@ -586,8 +320,7 @@ bool DenoiseTask::save()
void DenoiseTask::free()
{
image.free();
input_pixels.free();
assert(output_pixels.empty());
buffers.buffer.free();
}
/* Denoise Image Storage */
@@ -607,7 +340,7 @@ DenoiseImage::~DenoiseImage()
void DenoiseImage::close_input()
{
in_neighbors.clear();
in_previous.reset();
}
void DenoiseImage::free()
@@ -677,39 +410,61 @@ bool DenoiseImage::parse_channels(const ImageSpec &in_spec, string &error)
return true;
}
void DenoiseImage::read_pixels(const DenoiseImageLayer &layer, float *input_pixels)
void DenoiseImage::read_pixels(const DenoiseImageLayer &layer,
const BufferParams &params,
float *input_pixels)
{
/* Pixels from center file have already been loaded into pixels.
* We copy a subset into the device input buffer with channels reshuffled. */
const int *input_to_image_channel = layer.input_to_image_channel.data();
for (int i = 0; i < width * height; i++) {
for (int j = 0; j < INPUT_NUM_CHANNELS; j++) {
int image_channel = input_to_image_channel[j];
input_pixels[i * INPUT_NUM_CHANNELS + j] =
for (int j = 0; j < 3; ++j) {
int offset = params.get_pass_offset(PASS_COMBINED);
int image_channel = input_to_image_channel[INPUT_NOISY_IMAGE + j];
input_pixels[i * params.pass_stride + offset + j] =
pixels[((size_t)i) * num_channels + image_channel];
}
for (int j = 0; j < 3; ++j) {
int offset = params.get_pass_offset(PASS_DENOISING_NORMAL);
int image_channel = input_to_image_channel[INPUT_DENOISING_NORMAL + j];
input_pixels[i * params.pass_stride + offset + j] =
pixels[((size_t)i) * num_channels + image_channel];
}
for (int j = 0; j < 3; ++j) {
int offset = params.get_pass_offset(PASS_DENOISING_ALBEDO);
int image_channel = input_to_image_channel[INPUT_DENOISING_ALBEDO + j];
input_pixels[i * params.pass_stride + offset + j] =
pixels[((size_t)i) * num_channels + image_channel];
}
for (int j = 0; j < 4; ++j) {
int offset = params.get_pass_offset(PASS_MOTION);
int image_channel = input_to_image_channel[INPUT_MOTION + j];
input_pixels[i * params.pass_stride + offset + j] =
pixels[((size_t)i) * num_channels + image_channel];
}
}
}
bool DenoiseImage::read_neighbor_pixels(int neighbor,
const DenoiseImageLayer &layer,
bool DenoiseImage::read_previous_pixels(const DenoiseImageLayer &layer,
const BufferParams &params,
float *input_pixels)
{
/* Load pixels from neighboring frames, and copy them into device buffer
* with channels reshuffled. */
size_t num_pixels = (size_t)width * (size_t)height;
array<float> neighbor_pixels(num_pixels * num_channels);
if (!in_neighbors[neighbor]->read_image(TypeDesc::FLOAT, neighbor_pixels.data())) {
if (!in_previous->read_image(TypeDesc::FLOAT, neighbor_pixels.data())) {
return false;
}
const int *input_to_image_channel = layer.neighbor_input_to_image_channel[neighbor].data();
const int *output_to_image_channel = layer.previous_output_to_image_channel.data();
for (int i = 0; i < width * height; i++) {
for (int j = 0; j < INPUT_NUM_CHANNELS; j++) {
int image_channel = input_to_image_channel[j];
input_pixels[i * INPUT_NUM_CHANNELS + j] =
for (int j = 0; j < 3; ++j) {
int offset = params.get_pass_offset(PASS_DENOISING_PREVIOUS);
int image_channel = output_to_image_channel[j];
input_pixels[i * params.pass_stride + offset + j] =
neighbor_pixels[((size_t)i) * num_channels + image_channel];
}
}
@@ -739,8 +494,8 @@ bool DenoiseImage::load(const string &in_filepath, string &error)
return false;
}
if (layers.size() == 0) {
error = "Could not find a render layer containing denoising info";
if (layers.empty()) {
error = "Could not find a render layer containing denoising data and motion vector passes";
return false;
}
@@ -757,46 +512,34 @@ bool DenoiseImage::load(const string &in_filepath, string &error)
return true;
}
bool DenoiseImage::load_neighbors(const vector<string> &filepaths,
const vector<int> &frames,
string &error)
bool DenoiseImage::load_previous(const string &filepath, string &error)
{
if (frames.size() > DENOISE_MAX_FRAMES - 1) {
error = string_printf("Maximum number of neighbors (%d) exceeded\n", DENOISE_MAX_FRAMES - 1);
if (!Filesystem::is_regular(filepath)) {
error = "Couldn't find neighbor frame: " + filepath;
return false;
}
for (int neighbor = 0; neighbor < frames.size(); neighbor++) {
int frame = frames[neighbor];
const string &filepath = filepaths[frame];
if (!Filesystem::is_regular(filepath)) {
error = "Couldn't find neighbor frame: " + filepath;
return false;
}
unique_ptr<ImageInput> in_neighbor(ImageInput::open(filepath));
if (!in_neighbor) {
error = "Couldn't open neighbor frame: " + filepath;
return false;
}
const ImageSpec &neighbor_spec = in_neighbor->spec();
if (neighbor_spec.width != width || neighbor_spec.height != height) {
error = "Neighbor frame has different dimensions: " + filepath;
return false;
}
foreach (DenoiseImageLayer &layer, layers) {
if (!layer.match_channels(neighbor, in_spec.channelnames, neighbor_spec.channelnames)) {
error = "Neighbor frame misses denoising data passes: " + filepath;
return false;
}
}
in_neighbors.push_back(std::move(in_neighbor));
unique_ptr<ImageInput> in_neighbor(ImageInput::open(filepath));
if (!in_neighbor) {
error = "Couldn't open neighbor frame: " + filepath;
return false;
}
const ImageSpec &neighbor_spec = in_neighbor->spec();
if (neighbor_spec.width != width || neighbor_spec.height != height) {
error = "Neighbor frame has different dimensions: " + filepath;
return false;
}
for (DenoiseImageLayer &layer : layers) {
if (!layer.match_channels(in_spec.channelnames, neighbor_spec.channelnames)) {
error = "Neighbor frame misses denoising data passes: " + filepath;
return false;
}
}
in_previous = std::move(in_neighbor);
return true;
}
@@ -864,24 +607,22 @@ bool DenoiseImage::save_output(const string &out_filepath, string &error)
/* File pattern handling and outer loop over frames */
DenoiserPipeline::DenoiserPipeline(DeviceInfo &device_info)
DenoiserPipeline::DenoiserPipeline(DeviceInfo &device_info, const DenoiseParams &params)
{
samples_override = 0;
tile_size = make_int2(64, 64);
num_frames = 0;
/* Initialize task scheduler. */
TaskScheduler::init();
/* Initialize device. */
device = Device::create(device_info, stats, profiler, true);
device = Device::create(device_info, stats, profiler);
device->load_kernels(KERNEL_FEATURE_DENOISING);
denoiser = Denoiser::create(device, params);
denoiser->load_kernels(nullptr);
}
DenoiserPipeline::~DenoiserPipeline()
{
denoiser.reset();
delete device;
TaskScheduler::exit();
}
@@ -890,7 +631,7 @@ bool DenoiserPipeline::run()
{
assert(input.size() == output.size());
num_frames = output.size();
int num_frames = output.size();
for (int frame = 0; frame < num_frames; frame++) {
/* Skip empty output paths. */
@@ -898,16 +639,8 @@ bool DenoiserPipeline::run()
continue;
}
/* Determine neighbor frame numbers that should be used for filtering. */
vector<int> neighbor_frames;
for (int f = frame - params.neighbor_frames; f <= frame + params.neighbor_frames; f++) {
if (f >= 0 && f < num_frames && f != frame) {
neighbor_frames.push_back(f);
}
}
/* Execute task. */
DenoiseTask task(device, this, frame, neighbor_frames);
DenoiseTask task(device, this, frame);
if (!task.load()) {
error = task.error;
return false;
@@ -930,5 +663,3 @@ bool DenoiserPipeline::run()
}
CCL_NAMESPACE_END
#endif

View File

@@ -17,20 +17,17 @@
#ifndef __DENOISING_H__
#define __DENOISING_H__
#if 0
/* TODO(sergey): Make it explicit and clear when something is a denoiser, its pipeline or
* parameters. Currently it is an annoying mixture of terms used interchangeably. */
# include "device/device.h"
#include "device/device.h"
#include "integrator/denoiser.h"
# include "render/buffers.h"
#include "util/string.h"
#include "util/unique_ptr.h"
#include "util/vector.h"
# include "util/util_string.h"
# include "util/util_unique_ptr.h"
# include "util/util_vector.h"
# include <OpenImageIO/imageio.h>
#include <OpenImageIO/imageio.h>
OIIO_NAMESPACE_USING
@@ -40,7 +37,7 @@ CCL_NAMESPACE_BEGIN
class DenoiserPipeline {
public:
DenoiserPipeline(DeviceInfo &device_info);
DenoiserPipeline(DeviceInfo &device_info, const DenoiseParams &params);
~DenoiserPipeline();
bool run();
@@ -55,22 +52,13 @@ class DenoiserPipeline {
* taking into account all input frames. */
vector<string> output;
/* Sample number override, takes precedence over values from input frames. */
int samples_override;
/* Tile size for processing on device. */
int2 tile_size;
/* Equivalent to the settings in the regular denoiser. */
DenoiseParams params;
protected:
friend class DenoiseTask;
Stats stats;
Profiler profiler;
Device *device;
int num_frames;
std::unique_ptr<Denoiser> denoiser;
};
/* Denoise Image Layer */
@@ -88,13 +76,13 @@ struct DenoiseImageLayer {
/* Device input channel will be copied from image channel input_to_image_channel[i]. */
vector<int> input_to_image_channel;
/* input_to_image_channel of the secondary frames, if any are used. */
vector<vector<int>> neighbor_input_to_image_channel;
/* Write i-th channel of the processing output to output_to_image_channel[i]-th channel of the
* file. */
vector<int> output_to_image_channel;
/* output_to_image_channel of the previous frame, if used. */
vector<int> previous_output_to_image_channel;
/* Detect whether this layer contains a full set of channels and set up the offsets accordingly.
*/
bool detect_denoising_channels();
@@ -102,8 +90,7 @@ struct DenoiseImageLayer {
/* Map the channels of a secondary frame to the channels that are required for processing,
* fill neighbor_input_to_image_channel if all are present or return false if a channel are
* missing. */
bool match_channels(int neighbor,
const std::vector<string> &channelnames,
bool match_channels(const std::vector<string> &channelnames,
const std::vector<string> &neighbor_channelnames);
};
@@ -125,7 +112,7 @@ class DenoiseImage {
/* Image file handles */
ImageSpec in_spec;
vector<unique_ptr<ImageInput>> in_neighbors;
unique_ptr<ImageInput> in_previous;
/* Render layers */
vector<DenoiseImageLayer> layers;
@@ -137,12 +124,16 @@ class DenoiseImage {
bool load(const string &in_filepath, string &error);
/* Load neighboring frames. */
bool load_neighbors(const vector<string> &filepaths, const vector<int> &frames, string &error);
bool load_previous(const string &in_filepath, string &error);
/* Load subset of pixels from file buffer into input buffer, as needed for denoising
* on the device. Channels are reshuffled following the provided mapping. */
void read_pixels(const DenoiseImageLayer &layer, float *input_pixels);
bool read_neighbor_pixels(int neighbor, const DenoiseImageLayer &layer, float *input_pixels);
void read_pixels(const DenoiseImageLayer &layer,
const BufferParams &params,
float *input_pixels);
bool read_previous_pixels(const DenoiseImageLayer &layer,
const BufferParams &params,
float *input_pixels);
bool save_output(const string &out_filepath, string &error);
@@ -159,10 +150,7 @@ class DenoiseImage {
class DenoiseTask {
public:
DenoiseTask(Device *device,
DenoiserPipeline *denoiser,
int frame,
const vector<int> &neighbor_frames);
DenoiseTask(Device *device, DenoiserPipeline *denoiser, int frame);
~DenoiseTask();
/* Task stages */
@@ -180,37 +168,17 @@ class DenoiseTask {
/* Frame number to be denoised */
int frame;
vector<int> neighbor_frames;
/* Image file data */
DenoiseImage image;
int current_layer;
/* Device input buffer */
device_vector<float> input_pixels;
/* Tiles */
thread_mutex tiles_mutex;
list<RenderTile> tiles;
int num_tiles;
thread_mutex output_mutex;
map<int, device_vector<float> *> output_pixels;
RenderBuffers buffers;
/* Task handling */
bool load_input_pixels(int layer);
void create_task(DeviceTask &task);
/* Device task callbacks */
bool acquire_tile(Device *device, Device *tile_device, RenderTile &tile);
void map_neighboring_tiles(RenderTileNeighbors &neighbors, Device *tile_device);
void unmap_neighboring_tiles(RenderTileNeighbors &neighbors);
void release_tile();
bool get_cancel();
};
CCL_NAMESPACE_END
#endif
#endif /* __DENOISING_H__ */

View File

@@ -54,6 +54,8 @@ class DisplayDriver {
}
};
virtual void next_tile_begin() = 0;
/* Update the render from the rendering thread.
*
* Cycles periodically updates the render to be displayed. For multithreaded updates with
@@ -80,6 +82,9 @@ class DisplayDriver {
virtual bool update_begin(const Params &params, int width, int height) = 0;
virtual void update_end() = 0;
/* Optionally flush outstanding display commands before ending the render loop. */
virtual void flush(){};
virtual half4 *map_texture_buffer() = 0;
virtual void unmap_texture_buffer() = 0;
@@ -97,6 +102,17 @@ class DisplayDriver {
/* Clear the entire buffer before doing partial write to it. */
bool need_clear = false;
/* Enforce re-creation of the graphics interop object.
*
* When this field is true then the graphics interop will be re-created no matter what the
* rest of the configuration is.
* When this field is false the graphics interop will be re-created if the PBO or buffer size
* did change.
*
* This allows to ensure graphics interop is re-created when there is a possibility that an
* underlying PBO was re-allocated but did not change its ID. */
bool need_recreate = false;
};
virtual GraphicsInterop graphics_interop_get()

View File

@@ -192,6 +192,8 @@ void Session::run_main_render_loop()
break;
}
}
path_trace_->flush_display();
}
void Session::run()
@@ -303,7 +305,7 @@ RenderWork Session::run_update_for_next_iteration()
tile_params.update_offset_stride();
path_trace_->reset(buffer_params_, tile_params);
path_trace_->reset(buffer_params_, tile_params, did_reset);
}
const int resolution = render_work.resolution_divider;
@@ -384,7 +386,8 @@ int2 Session::get_effective_tile_size() const
const int tile_size = tile_manager_.compute_render_tile_size(params.tile_size);
const int64_t actual_tile_area = static_cast<int64_t>(tile_size) * tile_size;
if (actual_tile_area >= image_area) {
if (actual_tile_area >= image_area && image_width <= TileManager::MAX_TILE_SIZE &&
image_height <= TileManager::MAX_TILE_SIZE) {
return make_int2(image_width, image_height);
}
@@ -423,6 +426,11 @@ void Session::do_delayed_reset()
buffer_params_.update_passes(scene->passes);
tile_manager_.update(buffer_params_, scene);
/* Update temp directory on reset.
* This potentially allows to finish the existing rendering with a previously configure temporary
* direcotry in the host software and switch to a new temp directory when new render starts. */
tile_manager_.set_temp_dir(params.temp_dir);
/* Progress. */
progress.reset_sample();
progress.set_total_pixel_samples(static_cast<uint64_t>(buffer_params_.width) *

View File

@@ -69,6 +69,9 @@ class SessionParams {
ShadingSystem shadingsystem;
/* Session-specific temporary directory to store in-progress EXR files in. */
string temp_dir;
SessionParams()
{
headless = false;

View File

@@ -23,6 +23,7 @@
#include "scene/film.h"
#include "scene/integrator.h"
#include "scene/scene.h"
#include "session/session.h"
#include "util/algorithm.h"
#include "util/foreach.h"
#include "util/log.h"
@@ -341,8 +342,10 @@ int TileManager::compute_render_tile_size(const int suggested_tile_size) const
/* Must be a multiple of IMAGE_TILE_SIZE so that we can write render tiles into the image file
* aligned on image tile boundaries. We can't set IMAGE_TILE_SIZE equal to the render tile size
* because too big tile size leads to integer overflow inside OpenEXR. */
return (suggested_tile_size <= IMAGE_TILE_SIZE) ? suggested_tile_size :
align_up(suggested_tile_size, IMAGE_TILE_SIZE);
const int computed_tile_size = (suggested_tile_size <= IMAGE_TILE_SIZE) ?
suggested_tile_size :
align_up(suggested_tile_size, IMAGE_TILE_SIZE);
return min(computed_tile_size, MAX_TILE_SIZE);
}
void TileManager::reset_scheduling(const BufferParams &params, int2 tile_size)
@@ -392,6 +395,11 @@ void TileManager::update(const BufferParams &params, const Scene *scene)
}
}
void TileManager::set_temp_dir(const string &temp_dir)
{
temp_dir_ = temp_dir;
}
bool TileManager::done()
{
return tile_state_.next_tile_index == tile_state_.num_tiles;
@@ -450,7 +458,8 @@ const int2 TileManager::get_size() const
bool TileManager::open_tile_output()
{
write_state_.filename = path_temp_get("cycles-tile-buffer-" + tile_file_unique_part_ + "-" +
write_state_.filename = path_join(temp_dir_,
"cycles-tile-buffer-" + tile_file_unique_part_ + "-" +
to_string(write_state_.tile_file_index) + ".exr");
write_state_.tile_out = ImageOutput::create(write_state_.filename);

View File

@@ -71,6 +71,8 @@ class TileManager {
* Will store all parameters needed for buffers access outside of the scene graph. */
void update(const BufferParams &params, const Scene *scene);
void set_temp_dir(const string &temp_dir);
inline int get_num_tiles() const
{
return tile_state_.num_tiles;
@@ -122,6 +124,12 @@ class TileManager {
/* Tile size in the image file. */
static const int IMAGE_TILE_SIZE = 128;
/* Maximum supported tile size.
* Needs to be safe from allocation on a GPU point of view: the display driver needs to be able
* to allocate texture with the side size of this value.
* Use conservative value which is safe for most of OpenGL drivers and GPUs. */
static const int MAX_TILE_SIZE = 8192;
protected:
/* Get tile configuration for its index.
* The tile index must be within [0, state_.tile_state_). */
@@ -130,6 +138,8 @@ class TileManager {
bool open_tile_output();
bool close_tile_output();
string temp_dir_;
/* Part of an on-disk tile file name which avoids conflicts between several Cycles instances or
* several sessions. */
string tile_file_unique_part_;

View File

@@ -38,8 +38,6 @@ set(ALL_CYCLES_LIBRARIES
)
include_directories(${INC})
cycles_link_directories()
set(SRC
integrator_adaptive_sampling_test.cpp
integrator_render_scheduler_test.cpp
@@ -54,17 +52,21 @@ set(SRC
util_transform_test.cpp
)
if(CXX_HAS_AVX)
list(APPEND SRC
util_avxf_avx_test.cpp
)
set_source_files_properties(util_avxf_avx_test.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX_KERNEL_FLAGS}")
endif()
if(CXX_HAS_AVX2)
list(APPEND SRC
util_avxf_avx2_test.cpp
)
set_source_files_properties(util_avxf_avx2_test.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX2_KERNEL_FLAGS}")
# Disable AVX tests on macOS. Rosetta has problems running them, and other
# platforms should be enough to verify AVX operations are implemented correctly.
if(NOT APPLE)
if(CXX_HAS_AVX)
list(APPEND SRC
util_avxf_avx_test.cpp
)
set_source_files_properties(util_avxf_avx_test.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX_KERNEL_FLAGS}")
endif()
if(CXX_HAS_AVX2)
list(APPEND SRC
util_avxf_avx2_test.cpp
)
set_source_files_properties(util_avxf_avx2_test.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX2_KERNEL_FLAGS}")
endif()
endif()
if(WITH_GTESTS)

View File

@@ -32,9 +32,13 @@ static bool validate_cpu_capabilities()
#endif
}
#define VALIDATECPU \
#define INIT_AVX_TEST \
if (!validate_cpu_capabilities()) \
return;
return; \
\
const avxf avxf_a(0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f); \
const avxf avxf_b(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f); \
const avxf avxf_c(1.1f, 2.2f, 3.3f, 4.4f, 5.5f, 6.6f, 7.7f, 8.8f);
#define compare_vector_scalar(a, b) \
for (size_t index = 0; index < a.size; index++) \
@@ -49,21 +53,18 @@ static bool validate_cpu_capabilities()
EXPECT_NEAR(a[index], b[index], abserror);
#define basic_test_vv(a, b, op) \
VALIDATECPU \
INIT_AVX_TEST \
avxf c = a op b; \
for (size_t i = 0; i < a.size; i++) \
EXPECT_FLOAT_EQ(c[i], a[i] op b[i]);
/* vector op float tests */
#define basic_test_vf(a, b, op) \
VALIDATECPU \
INIT_AVX_TEST \
avxf c = a op b; \
for (size_t i = 0; i < a.size; i++) \
EXPECT_FLOAT_EQ(c[i], a[i] op b);
static const avxf avxf_a(0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f);
static const avxf avxf_b(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f);
static const avxf avxf_c(1.1f, 2.2f, 3.3f, 4.4f, 5.5f, 6.6f, 7.7f, 8.8f);
static const float float_b = 1.5f;
TEST(TEST_CATEGORY_NAME, avxf_add_vv){basic_test_vv(avxf_a, avxf_b, +)} TEST(TEST_CATEGORY_NAME,
@@ -78,7 +79,7 @@ TEST(TEST_CATEGORY_NAME, avxf_add_vv){basic_test_vv(avxf_a, avxf_b, +)} TEST(TES
TEST(TEST_CATEGORY_NAME, avxf_ctor)
{
VALIDATECPU
INIT_AVX_TEST
compare_vector_scalar(avxf(7.0f, 6.0f, 5.0f, 4.0f, 3.0f, 2.0f, 1.0f, 0.0f),
static_cast<float>(index));
compare_vector_scalar(avxf(1.0f), 1.0f);
@@ -91,28 +92,28 @@ TEST(TEST_CATEGORY_NAME, avxf_ctor)
TEST(TEST_CATEGORY_NAME, avxf_sqrt)
{
VALIDATECPU
INIT_AVX_TEST
compare_vector_vector(mm256_sqrt(avxf(1.0f, 4.0f, 9.0f, 16.0f, 25.0f, 36.0f, 49.0f, 64.0f)),
avxf(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f));
}
TEST(TEST_CATEGORY_NAME, avxf_min_max)
{
VALIDATECPU
INIT_AVX_TEST
compare_vector_vector(min(avxf_a, avxf_b), avxf_a);
compare_vector_vector(max(avxf_a, avxf_b), avxf_b);
}
TEST(TEST_CATEGORY_NAME, avxf_set_sign)
{
VALIDATECPU
INIT_AVX_TEST
avxf res = set_sign_bit<1, 0, 0, 0, 0, 0, 0, 0>(avxf_a);
compare_vector_vector(res, avxf(0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, -0.8f));
}
TEST(TEST_CATEGORY_NAME, avxf_msub)
{
VALIDATECPU
INIT_AVX_TEST
avxf res = msub(avxf_a, avxf_b, avxf_c);
avxf exp = avxf((avxf_a[7] * avxf_b[7]) - avxf_c[7],
(avxf_a[6] * avxf_b[6]) - avxf_c[6],
@@ -127,7 +128,7 @@ TEST(TEST_CATEGORY_NAME, avxf_msub)
TEST(TEST_CATEGORY_NAME, avxf_madd)
{
VALIDATECPU
INIT_AVX_TEST
avxf res = madd(avxf_a, avxf_b, avxf_c);
avxf exp = avxf((avxf_a[7] * avxf_b[7]) + avxf_c[7],
(avxf_a[6] * avxf_b[6]) + avxf_c[6],
@@ -142,7 +143,7 @@ TEST(TEST_CATEGORY_NAME, avxf_madd)
TEST(TEST_CATEGORY_NAME, avxf_nmadd)
{
VALIDATECPU
INIT_AVX_TEST
avxf res = nmadd(avxf_a, avxf_b, avxf_c);
avxf exp = avxf(avxf_c[7] - (avxf_a[7] * avxf_b[7]),
avxf_c[6] - (avxf_a[6] * avxf_b[6]),
@@ -157,7 +158,7 @@ TEST(TEST_CATEGORY_NAME, avxf_nmadd)
TEST(TEST_CATEGORY_NAME, avxf_compare)
{
VALIDATECPU
INIT_AVX_TEST
avxf a(0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f);
avxf b(7.0f, 6.0f, 5.0f, 4.0f, 3.0f, 2.0f, 1.0f, 0.0f);
avxb res = a <= b;
@@ -176,28 +177,28 @@ TEST(TEST_CATEGORY_NAME, avxf_compare)
TEST(TEST_CATEGORY_NAME, avxf_permute)
{
VALIDATECPU
INIT_AVX_TEST
avxf res = permute<3, 0, 1, 7, 6, 5, 2, 4>(avxf_b);
compare_vector_vector(res, avxf(4.0f, 6.0f, 3.0f, 2.0f, 1.0f, 7.0f, 8.0f, 5.0f));
}
TEST(TEST_CATEGORY_NAME, avxf_blend)
{
VALIDATECPU
INIT_AVX_TEST
avxf res = blend<0, 0, 1, 0, 1, 0, 1, 0>(avxf_a, avxf_b);
compare_vector_vector(res, avxf(0.1f, 0.2f, 3.0f, 0.4f, 5.0f, 0.6f, 7.0f, 0.8f));
}
TEST(TEST_CATEGORY_NAME, avxf_shuffle)
{
VALIDATECPU
INIT_AVX_TEST
avxf res = shuffle<0, 1, 2, 3, 1, 3, 2, 0>(avxf_a);
compare_vector_vector(res, avxf(0.4f, 0.2f, 0.1f, 0.3f, 0.5f, 0.6f, 0.7f, 0.8f));
}
TEST(TEST_CATEGORY_NAME, avxf_cross)
{
VALIDATECPU
INIT_AVX_TEST
avxf res = cross(avxf_b, avxf_c);
compare_vector_vector_near(res,
avxf(0.0f,
@@ -213,7 +214,7 @@ TEST(TEST_CATEGORY_NAME, avxf_cross)
TEST(TEST_CATEGORY_NAME, avxf_dot3)
{
VALIDATECPU
INIT_AVX_TEST
float den, den2;
dot3(avxf_a, avxf_b, den, den2);
EXPECT_FLOAT_EQ(den, 14.9f);

View File

@@ -53,16 +53,6 @@ if(WITH_CYCLES_STANDALONE)
endif()
endif()
if(CYCLES_STANDALONE_REPOSITORY)
list(APPEND INC_SYS
../../third_party/numaapi/include
)
else()
list(APPEND INC_SYS
../../numaapi/include
)
endif()
set(SRC_HEADERS
algorithm.h
aligned_malloc.h

View File

@@ -66,7 +66,6 @@ typedef struct stat path_stat_t;
static string cached_path = "";
static string cached_user_path = "";
static string cached_temp_path = "";
static string cached_xdg_cache_path = "";
namespace {
@@ -336,11 +335,10 @@ static string path_xdg_cache_get()
}
#endif
void path_init(const string &path, const string &user_path, const string &temp_path)
void path_init(const string &path, const string &user_path)
{
cached_path = path;
cached_user_path = user_path;
cached_temp_path = temp_path;
#ifdef _MSC_VER
// workaround for https://svn.boost.org/trac/boost/ticket/6320
@@ -384,15 +382,6 @@ string path_cache_get(const string &sub)
#endif
}
string path_temp_get(const string &sub)
{
if (cached_temp_path == "") {
cached_temp_path = Filesystem::temp_directory_path();
}
return path_join(cached_temp_path, sub);
}
#if defined(__linux__) || defined(__APPLE__)
string path_xdg_home_get(const string &sub = "");
#endif

View File

@@ -32,10 +32,9 @@
CCL_NAMESPACE_BEGIN
/* program paths */
void path_init(const string &path = "", const string &user_path = "", const string &tmp_path = "");
void path_init(const string &path = "", const string &user_path = "");
string path_get(const string &sub = "");
string path_user_get(const string &sub = "");
string path_temp_get(const string &sub = "");
string path_cache_get(const string &sub = "");
/* path string manipulation */

View File

@@ -20,9 +20,8 @@
#include "util/string.h"
#include "util/types.h"
#include <numaapi.h>
#include <OpenImageIO/sysutil.h>
OIIO_NAMESPACE_USING
#ifdef _WIN32
@@ -41,83 +40,6 @@ OIIO_NAMESPACE_USING
CCL_NAMESPACE_BEGIN
bool system_cpu_ensure_initialized()
{
static bool is_initialized = false;
static bool result = false;
if (is_initialized) {
return result;
}
is_initialized = true;
const NUMAAPI_Result numa_result = numaAPI_Initialize();
result = (numa_result == NUMAAPI_SUCCESS);
return result;
}
/* Fallback solution, which doesn't use NUMA/CPU groups. */
static int system_cpu_thread_count_fallback()
{
#ifdef _WIN32
SYSTEM_INFO info;
GetSystemInfo(&info);
return info.dwNumberOfProcessors;
#elif defined(__APPLE__)
int count;
size_t len = sizeof(count);
int mib[2] = {CTL_HW, HW_NCPU};
sysctl(mib, 2, &count, &len, NULL, 0);
return count;
#else
return sysconf(_SC_NPROCESSORS_ONLN);
#endif
}
int system_cpu_thread_count()
{
const int num_nodes = system_cpu_num_numa_nodes();
int num_threads = 0;
for (int node = 0; node < num_nodes; ++node) {
if (!system_cpu_is_numa_node_available(node)) {
continue;
}
num_threads += system_cpu_num_numa_node_processors(node);
}
return num_threads;
}
int system_cpu_num_numa_nodes()
{
if (!system_cpu_ensure_initialized()) {
/* Fallback to a single node with all the threads. */
return 1;
}
return numaAPI_GetNumNodes();
}
bool system_cpu_is_numa_node_available(int node)
{
if (!system_cpu_ensure_initialized()) {
return true;
}
return numaAPI_IsNodeAvailable(node);
}
int system_cpu_num_numa_node_processors(int node)
{
if (!system_cpu_ensure_initialized()) {
return system_cpu_thread_count_fallback();
}
return numaAPI_GetNumNodeProcessors(node);
}
bool system_cpu_run_thread_on_node(int node)
{
if (!system_cpu_ensure_initialized()) {
return true;
}
return numaAPI_RunThreadOnNode(node);
}
int system_console_width()
{
int columns = 0;
@@ -137,14 +59,6 @@ int system_console_width()
return (columns > 0) ? columns : 80;
}
int system_cpu_num_active_group_processors()
{
if (!system_cpu_ensure_initialized()) {
return system_cpu_thread_count_fallback();
}
return numaAPI_GetNumCurrentNodesProcessors();
}
/* Equivalent of Windows __cpuid for x86 processors on other platforms. */
#if (!defined(_WIN32) || defined(FREE_WINDOWS)) && (defined(__x86_64__) || defined(__i386__))
static void __cpuid(int data[4], int selector)

View File

@@ -22,36 +22,9 @@
CCL_NAMESPACE_BEGIN
/* Make sure CPU groups / NUMA API is initialized. */
bool system_cpu_ensure_initialized();
/* Get total number of threads in all NUMA nodes / CPU groups. */
int system_cpu_thread_count();
/* Get width in characters of the current console output. */
int system_console_width();
/* Get number of available nodes.
*
* This is in fact an index of last node plus one and it's not guaranteed
* that all nodes up to this one are available. */
int system_cpu_num_numa_nodes();
/* Returns truth if the given node is available for compute. */
bool system_cpu_is_numa_node_available(int node);
/* Get number of available processors on a given node. */
int system_cpu_num_numa_node_processors(int node);
/* Runs the current thread and its children on a specific node.
*
* Returns truth if affinity has successfully changed. */
bool system_cpu_run_thread_on_node(int node);
/* Number of processors within the current CPU group (or within active thread
* thread affinity). */
int system_cpu_num_active_group_processors();
string system_cpu_brand_string();
int system_cpu_bits();
bool system_cpu_support_sse2();

View File

@@ -89,7 +89,7 @@ void TaskScheduler::init(int num_threads)
active_num_threads = num_threads;
}
else {
active_num_threads = system_cpu_thread_count();
active_num_threads = tbb::this_task_arena::max_concurrency();
}
}
@@ -109,9 +109,10 @@ void TaskScheduler::free_memory()
assert(users == 0);
}
int TaskScheduler::num_threads()
int TaskScheduler::max_concurrency()
{
return active_num_threads;
thread_scoped_lock lock(mutex);
return (users > 0) ? active_num_threads : tbb::this_task_arena::max_concurrency();
}
/* Dedicated Task Pool */

View File

@@ -86,10 +86,9 @@ class TaskScheduler {
static void exit();
static void free_memory();
/* Approximate number of threads that will work on task, which may be lower
* or higher than the actual number of threads. Use as little as possible and
* leave splitting up tasks to the scheduler. */
static int num_threads();
/* Maximum number of threads that will work on task. Use as little as
* possible and leave scheduling and splitting up tasks to the scheduler. */
static int max_concurrency();
protected:
static thread_mutex mutex;

View File

@@ -21,7 +21,7 @@
CCL_NAMESPACE_BEGIN
thread::thread(function<void()> run_cb, int node) : run_cb_(run_cb), joined_(false), node_(node)
thread::thread(function<void()> run_cb) : run_cb_(run_cb), joined_(false)
{
#ifdef __APPLE__
/* Set the stack size to 2MB to match Linux. The default 512KB on macOS is
@@ -46,9 +46,6 @@ thread::~thread()
void *thread::run(void *arg)
{
thread *self = (thread *)(arg);
if (self->node_ != -1) {
system_cpu_run_thread_on_node(self->node_);
}
self->run_cb_();
return NULL;
}

View File

@@ -46,9 +46,7 @@ typedef std::condition_variable thread_condition_variable;
class thread {
public:
/* NOTE: Node index of -1 means that affinity will be inherited from the
* parent thread and no override on top of that will happen. */
thread(function<void()> run_cb, int node = -1);
thread(function<void()> run_cb);
~thread();
static void *run(void *arg);
@@ -62,7 +60,6 @@ class thread {
std::thread std_thread;
#endif
bool joined_;
int node_;
};
using thread_spin_lock = tbb::spin_mutex;

View File

@@ -496,8 +496,6 @@ typedef struct {
int target_start;
/** Represents the position of the end of the selection */
int target_end;
/** custom temporal data */
GHOST_TUserDataPtr tmp;
} GHOST_TEventImeData;
typedef struct {

View File

@@ -106,7 +106,7 @@ bool GHOST_ImeWin32::IsImeKeyEvent(char ascii)
if (IsLanguage(IMELANG_JAPANESE) && (ascii >= ' ' && ascii <= '~')) {
return true;
}
else if (IsLanguage(IMELANG_CHINESE) && ascii && strchr("!\"$'(),.:;<>?[\\]^_`", ascii)) {
else if (IsLanguage(IMELANG_CHINESE) && ascii && strchr("!\"$'(),.:;<>?[\\]^_`/", ascii)) {
return true;
}
}

View File

@@ -1552,8 +1552,8 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
* button is press for menu. To prevent this we must return preventing DefWindowProc.
*
* Note that the four low-order bits of the wParam parameter are used internally by the
* OS. To obtain the correct result when testing the value of wParam, an application
* must combine the value 0xFFF0 with the wParam value by using the bitwise AND operator.
* OS. To obtain the correct result when testing the value of wParam, an application must
* combine the value 0xFFF0 with the wParam value by using the bit-wise AND operator.
*/
switch (wParam & 0xFFF0) {
case SC_KEYMENU:

View File

@@ -41,8 +41,8 @@ class GHOST_Window : public GHOST_IWindow {
* Constructor.
* Creates a new window and opens it.
* To check if the window was created properly, use the getValid() method.
* \param width: The width the window.
* \param height: The height the window.
* \param width: The width of the window.
* \param height: The height of the window.
* \param state: The state the window is initially opened with.
* \param wantStereoVisual: Stereo visual for quad buffered stereo.
* \param exclusive: Use to show the window ontop and ignore others (used full-screen).

View File

@@ -298,14 +298,12 @@ GHOST_TabletData GHOST_Wintab::getLastTabletData()
void GHOST_Wintab::getInput(std::vector<GHOST_WintabInfoWin32> &outWintabInfo)
{
const int numPackets = m_fpPacketsGet(m_context.get(), m_pkts.size(), m_pkts.data());
outWintabInfo.resize(numPackets);
size_t outExtent = 0;
outWintabInfo.reserve(numPackets);
for (int i = 0; i < numPackets; i++) {
PACKET pkt = m_pkts[i];
GHOST_WintabInfoWin32 &out = outWintabInfo[i + outExtent];
GHOST_WintabInfoWin32 out;
out.tabletData = GHOST_TABLET_DATA_NONE;
/* % 3 for multiple devices ("DualTrack"). */
switch (pkt.pkCursor % 3) {
case 0:
@@ -328,12 +326,7 @@ void GHOST_Wintab::getInput(std::vector<GHOST_WintabInfoWin32> &outWintabInfo)
}
if ((m_maxAzimuth > 0) && (m_maxAltitude > 0)) {
ORIENTATION ort = pkt.pkOrientation;
float vecLen;
float altRad, azmRad; /* In radians. */
/*
* From the wintab spec:
/* From the wintab spec:
* orAzimuth: Specifies the clockwise rotation of the cursor about the z axis through a
* full circular range.
* orAltitude: Specifies the angle with the x-y plane through a signed, semicircular range.
@@ -346,12 +339,14 @@ void GHOST_Wintab::getInput(std::vector<GHOST_WintabInfoWin32> &outWintabInfo)
* value.
*/
ORIENTATION ort = pkt.pkOrientation;
/* Convert raw fixed point data to radians. */
altRad = (float)((fabs((float)ort.orAltitude) / (float)m_maxAltitude) * M_PI / 2.0);
azmRad = (float)(((float)ort.orAzimuth / (float)m_maxAzimuth) * M_PI * 2.0);
float altRad = (float)((fabs((float)ort.orAltitude) / (float)m_maxAltitude) * M_PI / 2.0);
float azmRad = (float)(((float)ort.orAzimuth / (float)m_maxAzimuth) * M_PI * 2.0);
/* Find length of the stylus' projected vector on the XY plane. */
vecLen = cos(altRad);
float vecLen = cos(altRad);
/* From there calculate X and Y components based on azimuth. */
out.tabletData.Xtilt = sin(azmRad) * vecLen;
@@ -362,13 +357,8 @@ void GHOST_Wintab::getInput(std::vector<GHOST_WintabInfoWin32> &outWintabInfo)
/* Some Wintab libraries don't handle relative button input, so we track button presses
* manually. */
out.button = GHOST_kButtonMaskNone;
out.type = GHOST_kEventCursorMove;
DWORD buttonsChanged = m_buttons ^ pkt.pkButtons;
WORD buttonIndex = 0;
GHOST_WintabInfoWin32 buttonRef = out;
int buttons = 0;
while (buttonsChanged) {
if (buttonsChanged & 1) {
@@ -376,23 +366,14 @@ void GHOST_Wintab::getInput(std::vector<GHOST_WintabInfoWin32> &outWintabInfo)
GHOST_TButtonMask button = mapWintabToGhostButton(pkt.pkCursor, buttonIndex);
if (button != GHOST_kButtonMaskNone) {
/* Extend output if multiple buttons are pressed. We don't extend input until we confirm
* a Wintab buttons maps to a system button. */
if (buttons > 0) {
outWintabInfo.resize(outWintabInfo.size() + 1);
outExtent++;
GHOST_WintabInfoWin32 &out = outWintabInfo[i + outExtent];
out = buttonRef;
/* If this is not the first button found, push info for the prior Wintab button. */
if (out.button != GHOST_kButtonMaskNone) {
outWintabInfo.push_back(out);
}
buttons++;
out.button = button;
if (buttonsChanged & pkt.pkButtons) {
out.type = GHOST_kEventButtonDown;
}
else {
out.type = GHOST_kEventButtonUp;
}
out.type = buttonsChanged & pkt.pkButtons ? GHOST_kEventButtonDown :
GHOST_kEventButtonUp;
}
m_buttons ^= 1 << buttonIndex;
@@ -401,6 +382,8 @@ void GHOST_Wintab::getInput(std::vector<GHOST_WintabInfoWin32> &outWintabInfo)
buttonsChanged >>= 1;
buttonIndex++;
}
outWintabInfo.push_back(out);
}
if (!outWintabInfo.empty()) {

View File

@@ -56,11 +56,12 @@ typedef std::unique_ptr<std::remove_pointer_t<HMODULE>, decltype(&::FreeLibrary)
typedef std::unique_ptr<std::remove_pointer_t<HCTX>, GHOST_WIN32_WTClose> unique_hctx;
struct GHOST_WintabInfoWin32 {
int32_t x, y;
GHOST_TEventType type;
GHOST_TButtonMask button;
uint64_t time;
GHOST_TabletData tabletData;
int32_t x = 0;
int32_t y = 0;
GHOST_TEventType type = GHOST_kEventCursorMove;
GHOST_TButtonMask button = GHOST_kButtonMaskNone;
uint64_t time = 0;
GHOST_TabletData tabletData = GHOST_TABLET_DATA_NONE;
};
class GHOST_Wintab {

View File

@@ -196,12 +196,12 @@ void IK_QJacobian::InvertSDLS()
// Compute the dampeds least squeares pseudo inverse of J.
//
// Since J is usually not invertible (most of the times it's not even
// square), the psuedo inverse is used. This gives us a least squares
// square), the pseudo inverse is used. This gives us a least squares
// solution.
//
// This is fine when the J*Jt is of full rank. When J*Jt is near to
// singular the least squares inverse tries to minimize |J(dtheta) - dX)|
// and doesn't try to minimize dTheta. This results in eratic changes in
// and doesn't try to minimize dTheta. This results in erratic changes in
// angle. The damped least squares minimizes |dtheta| to try and reduce this
// erratic behavior.
//
@@ -323,7 +323,7 @@ void IK_QJacobian::InvertDLS()
// least squares solution. This is fine when the m_jjt is
// of full rank. When m_jjt is near to singular the least squares
// inverse tries to minimize |J(dtheta) - dX)| and doesn't
// try to minimize dTheta. This results in eratic changes in angle.
// try to minimize dTheta. This results in erratic changes in angle.
// Damped least squares minimizes |dtheta| to try and reduce this
// erratic behavior.

View File

@@ -38,8 +38,6 @@ set(LIB
)
if(WITH_LIBMV)
setup_libdirs()
if(WIN32)
add_definitions(-D_USE_MATH_DEFINES)
endif()

View File

@@ -118,8 +118,6 @@ set(LIB
)
if(WITH_LIBMV)
setup_libdirs()
if(WIN32)
add_definitions(-D_USE_MATH_DEFINES)
endif()

View File

@@ -178,7 +178,7 @@ bool AutoTrack::TrackMarker(Marker* tracked_marker,
return false;
}
// Store original position befoer tracking, so we can claculate offset later.
// Store original position before tracking, so we can claculate offset later.
Vec2f original_center = tracked_marker->center;
// Do the tracking!

View File

@@ -239,7 +239,7 @@
// Check what is the latest C++ specification the compiler supports.
//
// NOTE: Use explicit definition here to avoid expansion-to-defined warning from
// being geenrated. While this will most likely a false-positive warning in this
// being generated. While this will most likely a false-positive warning in this
// particular case, that warning might be helpful to catch errors elsewhere.
// C++11 check.

View File

@@ -25,7 +25,7 @@
namespace libmv {
// A vector of elements with fixed lenght and deep copy semantics.
// A vector of elements with fixed length and deep copy semantics.
template <typename T, int N>
class Tuple {
public:

View File

@@ -38,7 +38,7 @@ namespace libmv {
// The 2-point algorithm solves for the rotation of the camera with a single
// focal length (4 degrees of freedom).
//
// Compute from 1 to 3 possible focal lenght for 2 point correspondences.
// Compute from 1 to 3 possible focal length for 2 point correspondences.
// Suppose that the cameras share the same optical center and focal lengths:
//
// Image 1 => H*x = x' => Image 2

View File

@@ -261,7 +261,7 @@ Mat3 RotationRodrigues(const Vec3& axis);
// positive z-axis, and y is oriented close to up.
Mat3 LookAt(Vec3 center);
// Return a diagonal matrix from a vector containg the diagonal values.
// Return a diagonal matrix from a vector containing the diagonal values.
template <typename TVec>
inline Mat Diag(const TVec& x) {
return x.asDiagonal();

View File

@@ -50,7 +50,7 @@ int SolveCubicPolynomial(Real a, Real b, Real c, Real* x0, Real* x1, Real* x2) {
Real CQ3 = 2916 * q * q * q;
if (R == 0 && Q == 0) {
// Tripple root in one place.
// Triple root in one place.
*x0 = *x1 = *x2 = -a / 3;
return 3;

View File

@@ -41,7 +41,7 @@
class MEM_RefCounted {
public:
/**
* Constructs a a shared object.
* Constructs a shared object.
*/
MEM_RefCounted() : m_refCount(1)
{

View File

@@ -1 +0,0 @@
Sergey Sharybin <sergey.vfx@gmail.com>

View File

@@ -1,42 +0,0 @@
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ***** END GPL LICENSE BLOCK *****
set(INC
include
)
set(INC_SYS
)
set(SRC
source/numaapi.c
source/numaapi_linux.c
source/numaapi_stub.c
source/numaapi_win32.c
include/numaapi.h
source/build_config.h
)
set(LIB
)
add_definitions(-DWITH_DYNLOAD)
blender_add_lib(bf_intern_numaapi "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")

View File

@@ -1,19 +0,0 @@
Copyright (c) 2016 libnumaapi authors.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.

View File

@@ -1,7 +0,0 @@
LibNumaAPI is aimed to provide one common cross-platform API for all
possible platforms, so cross-platform applications might not worry
about implementation details.
LICENSE
LibNumaAPI library is released under the MIT license.

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