Compare commits

..

858 Commits

Author SHA1 Message Date
c8004ff653 Just what version of C++ does the linux buildbot use, anyway. 2021-09-21 00:44:36 -07:00
fdffbf87ac Fix last commit 2021-09-21 00:13:43 -07:00
bee00909bc forgot a line 2021-09-21 00:04:10 -07:00
562723b080 More linux fixes 2021-09-21 00:03:32 -07:00
2195a5eb2c Try to fix another linux compile error 2021-09-20 23:28:03 -07:00
4307c0eb68 try to fix weird gcc compile error 2021-09-20 22:56:02 -07:00
2d473ff4a8 Sculpt: more brush stuff 2021-09-20 22:52:17 -07:00
2b2b569229 Disable a static assert on gcc. 2021-09-20 20:26:53 -07:00
015dae3dc5 add missing files 2021-09-20 19:42:31 -07:00
3fc687ad75 Sculpt: Finish color support for brush channels
* BRUSH_CHANNEL_VEC3/4 are now implemented
* New flag BRUSH_CHANNEL_COLOR
* Also tried to sculpt's usage of wm.radial_control in keymaps
2021-09-20 19:41:00 -07:00
76beed9068 Sculpt: More brush engine stuff, got automasking to work with it
* Sculpt now has an API to get brush channel settings.
  If a sculpt cache exists it will use the channels there
  (ss->cache->channels_final), otherwise it pulls them
  from a brush and Sculpt toolsettings. Exampes:

  float f = SCULPT_get_float(ss, "setting", sd, brush);
  itn i = SCULPT_get_int(ss, "setting", sd, brush);

* Improved the UI a bit
2021-09-20 14:10:35 -07:00
645aee0835 Fix small crash in last commit and a few typos 2021-09-20 03:34:13 -07:00
83bfa950b1 Sculpt: add missing files 2021-09-20 03:14:39 -07:00
898625547f Fix problem in last commit 2021-09-20 03:14:14 -07:00
73150981c8 Sculpt: More brush channel stuff
* The input device curves for brush channels
  now use a copy on write mechanism.
  + It's based on a global cache of curves.
    The alternative is to reference count
    BrushChannels, which I also implemented
    then abandoned.
  + Profiling showed that copying CurveMapping
    instances was actually a problem.

* Lots of small fixes to the old<-> new brush setting
  conversion code;

* Brush commands can now, sortof, have individual
  spacing.  The default brush spacing still acts
  as a minimum though.

* Added a BLI_ghash_lookup_p_ex method that
  returns the key ptr inside the ghash (it
  returns the actual key, not a pointer to
  Entry.key).
* Added a general 1d CurveMapping preset operator
  that uses an RNA path to get the curve.
2021-09-20 03:01:30 -07:00
c9f1e104da Sculpt: Brush channels names are now lower-case instead
of upper case.
2021-09-19 16:17:01 -07:00
336b263b56 Sculpt: brush engine stuff
BrushChannels are now stored in linked lists
instead of simple arrays.  This helps to
avoid memory corruption.

I had originally wanted to be able to pass
BrushChannels by value, but that doesn't really
work since they heap allocd data (the input
mapping curves).
2021-09-19 15:35:10 -07:00
b3ed969b86 commit prior to small refactor 2021-09-19 13:30:43 -07:00
87feba04dd Sculpt: more brush engine stuff; do not test.
Pushing this commit early due to computer
weirdness
2021-09-19 01:11:35 -07:00
1ca57bc5f4 Sculpt: flushed out brush channel RNA and made basic UI 2021-09-18 12:10:14 -07:00
7749b89d74 Sculpt: Added some icons and commit icon_geom.blend into the branch
Help with icons would be appreciated.  The
scene project icon kind of came out looking
like a band-aid.
2021-09-18 02:43:03 -07:00
bae92a0ce5 Disable threading for sculpt project brush 2021-09-18 01:39:40 -07:00
5223f73a1d Fix compile error 2021-09-18 01:26:12 -07:00
fe47584316 Sculpt: Flesh out RNA wrapping of BrushChannels 2021-09-18 00:35:56 -07:00
2d3d6eb7b2 Merge remote-tracking branch 'origin/temp_bmesh_multires' into sculpt-dev 2021-09-17 23:32:08 -07:00
f0c35d16f3 Merge branch 'master' into temp_bmesh_multires 2021-09-17 20:13:39 -07:00
85d274a60c Merge branch 'master' into sculpt-dev 2021-09-17 16:22:10 -07:00
d3bba94bf2 Commit current working copy; having
weird file system issues
2021-09-17 14:43:00 -07:00
04c3690299 Sculpt dyntopo: Roughed out skeleton of new brush engine API
Command Lists

* The new system will be based on command lists
  generated by (eventually) a node editor.
* For now, the lists will be hardcoded.
* Idea is to make a minimal viable
  brush engine that won't cause file breakage
  when the upgrade to node-based brushes happen.

Brush Channels

* Wrote new structures and API to wrange
  brush parameters: BrushChannel.
* Supports, floats, ints, enums, bitmasks,
  with plans for vec3 and vec4.
* This will replace UnifiedPaintStruct,
  most of the members of Brush and the
  DynTopoSettings struct.
* Brush channels can
  be mapped to various input device
  channels (e.g. pen pressure); each
  mapping has its own associated curve
  (CurveMapping instance) and bounds.

Brush channel inheritence chaining

* Brush channels can form inheritence chains
* Channel sets are stored in three places:
  in the scene toolsettings, in Brush, and in
  individual brush commands.
* Node groups will also have a channel set.
* Channels in each set can be flagged to
  inherit from the parent set.
* Inheritence happens in seperate merged
  channel sets at runtime.  The final
  Brush channels live in Brush->channels_final,
  while the final command channels live in
  BrushCommand->params_final.
2021-09-16 20:29:33 -07:00
627edd1efa Merge branch 'master' into temp_bmesh_multires 2021-09-16 13:44:21 -07:00
445889676b commit prior to merge 2021-09-16 10:42:30 -07:00
350e783668 Add skeletal beginnings of C++ sculpt refactor
design study (note that it's #ifdef'd out).

Basic idea is to put all the sculpt brush code
in a single large template.  This template
takes a PBVH adaptor class (of which there
would be three, one per PBVH_XXX type)
as a template argument.

Basically we're using the compiler to generate
three complete copies of every brush implementation.
C++20 concepts are used to validate the pbvh classes.

An example brush implementation:

    pbvh->forVertsInRange(
        {
          .brush = ss->cache->brush,
          .radius = radius,
          .use_threads = true,
          .use_original = false
        },

        [&offset](auto viter, int node_i, void *userdata) {
          //add offset to vertex coordinates

          madd_v3_v3fl(viter.co, offset, viter.fade);
        },

        [](PBVHNode *node, int node_i, void *userdata) {
          BKE_pbvh_node_mark_update(node);
        });
2021-09-15 14:56:19 -07:00
0b2aee5841 Sculpt dyntopo: Fix a few issues from last commit
* Fixed crashing on entering sculpt mode
* Fixed transitioning between sculpt and
  another undo system type sometimes
  corrupting stack.
2021-09-15 02:50:32 -07:00
ecdd6a302e Sculpt dyntopo: fix missing bit from last commit
* BM_mesh_bm_to_me now saves id layers by default.
2021-09-15 02:16:03 -07:00
173f5f94ff Sculpt dyntopo:
Seperate enabling PBVH_BMESH from enabling DynTopo:

* Created a new option to globally disabled
  DynTopo.
* The DynTopo panel header now reads "Dynamic Mode",
  to hopefully signal that turning on PBVH_BMESH is
  a seperate step from enabling or disabling DynTopo
  itself.
* The first checkbox in the panel is "DynTopo" so it
  should be clear enough (it's on by default, with multiple
  layers of file versioning checks).

PBVH_BMesh's undo system:

* CD_MESH_ID layers are now permanently saved once
  they are created (by default they are not).  This
  fixed a *lot* of bugs:

  Before this the undo system had to save maps between
  mesh indices and mesh IDs on transitioning
  between sculpt and global undo steps.  This was
  extremely error prone, and it simply wasn't possible
  to cover all of the corner cases

* Note that there is still an odd bug where the first
  global undo push after a sculpt step gets ignored,
  I dunno what's up with this.

* Dyntopo undo should be nearly (hopefully completely)
  bug-free after this commit.

C++20

* Made a few small changes to get blender to compile
  with c++20.  std::result_of was removed, had to
  replace a couple of usages of it with std::invoke_result.

* I'm planning to do some design studies on rewriting
  sculpt into C++.

* I strongly suspect we are going to need C++20'a new
  concepts feature if we move sculpt into C++.
  I'm planning to do some design studies on how
  that might work.
2021-09-15 01:41:03 -07:00
0eeaeb3fc2 Sculpt dyntopo: fix nasty node splitting bug 2021-09-13 20:14:46 -07:00
3df335d330 Sculpt dyntopo:
* Fixed noise on using autosmooth with tools that use original
  coorinates.  While this was most prominent with DynTopo,
  it did happen with other tools.
* The solution is to smooth the original coordinates as well
  as the explicit coordinates if the active tool requires
  original data.

* I decided to replace the original coordinates system for
  PBVH_FACES and PBVH_GRIDS with the same MDynTopoVert structure
  DynTopo uses.  The alternative would have been extremely messy
  code.

* Todo: Rename MDynTopoVert to. . .SculptInfoVert?
* Todo: Cache boundary flag and corner info in MDynTopoVert->flag
        for PBVH_FACES/GRIDS similar to PBVH_BMESH.
2021-09-13 19:24:21 -07:00
0676928408 Sculpt dyntopo: more collapse fixes
The edge cases just never end.
2021-09-13 02:31:33 -07:00
e68667a835 Sculpt dyntopo:
* A few more collapse fixes
* Fixed boudary handling in surface_smooth_v_safe
2021-09-12 23:39:49 -07:00
86972d294f Dyntopo sculpt: fix bug with boundary flags 2021-09-11 13:38:42 -07:00
f52a03dd71 Sculpt dyntopo: Added a 'hard edge mode' option
to forcibly set autosmooth_fset_slide to zero
(i.e. treat face set boundaries as hard edges
and not project them on the surface).
2021-09-09 10:06:24 -08:00
a52f89a446 Add more int casts for linux 2021-09-08 23:21:57 -08:00
9f3bafc4ab Sculpt dyntopo
* Non-manifold "fins" are now detected and automatically
  deleted.
* Fixed compile error on linux.
2021-09-08 23:18:07 -08:00
bb1096f475 Sculpt dyntopo:
* Collapse now uses code from decimate to detect
  degenerate cases.
* Remaining, unknown (and rare) degenerate cases
  are now detected (via presence of duplicate verts
  in faces) and fixed.
* DynTopo fills in undo size properly now,
  so undo memory limiting works.
2021-09-08 15:51:56 -08:00
3e6edf5278 Sculpt dyntopo:
* BLI_table_gset now internally uses a SmallHash instead of
  a GHash.  Profiling revealed this to be quite a bit
  faster.
* This is something of a stopgap until C++-afication of
  pbvh, when we'll have our pick of a bunch of
  really nice C++ hashmap libs.
* pbvh_collapse_edge bites the dust; dyntopo now uses
  BM_collapse_edge.  Of the three topology operations
  (subdivide edge, collapse edge, dissolve 3/4 valence
  vertex) only dissolve still has a dyntopo-specific
  implementation.
* Fixed a bunch of annoying memory corruption bugs.
* Non-manifold triangles are now detected in more
  places.

SmallHash changes:

* Enabled removal
* Fixed infinite loop bug caused by
  improperly counting free*d* cells
  versus free cells.
* Added a BLI_smallhash_ensure_p method
  that works just like the GHash version.

Sculpt replay system

* Roughed out a simple system to record and
  play back sculpt strokes using a simple
  text format.
* This is exclusively for
  performance profiling and unit tests.
* For each brush stroke the system saves a copy
  of the active StrokeCache and PaintStroke
  and parts of Sculpt.

This should make profiling DRAM thrashing a lot
easier.
2021-09-07 23:49:54 -08:00
37bce7b701 commit working code 2021-09-02 23:19:11 -07:00
6febbd7a55 Linux's gcc's flags are evil 2021-09-02 11:42:06 -07:00
416c7a32d8 Fix warnings 2021-09-02 11:32:46 -07:00
d4badd4b22 Fix compile error 2021-09-02 11:26:28 -07:00
4e43e09cca Sculpt dyntopo: increment subversion. 2021-09-02 11:08:28 -07:00
21b6d78cd2 Sculpt dyntopo: change brush defaults and fix bug
* Changed brush defaults a bit.  New defaults
  are for organic modeling.
* autosmooth_fset_slide now defaults to 1, so
  face set boundaries are smoothed but stick to mesh
  surface (if 0 they would function as hard edges).
* Weight by area smooth mode is on by default for all
  brushes.
* Cleaned up versioning code and made it
  kick in at 3.00:21, with some simple checks to
  try and detect existing data from beta testers.

* Also fixed a small crash bug.
2021-09-02 11:02:44 -07:00
2b20931707 Merge branch 'master' into temp_bmesh_multires 2021-09-02 00:02:20 -07:00
416686707f commit before merge 2021-09-01 21:32:43 -07:00
8bfbbc467a Sculpt dyntopo
* Wrote a simple fix for drawing face sets
  in inverse (ctrl) mode with face set automasking
  on.

* Various fixes related to hard edges and smoothing.

* Started writing some code to defragment bmesh mempools.
  Need to figure out how to avoid triggering excessive
  PBVH node rebuilds.
2021-09-01 11:47:03 -07:00
baa24243a5 Sculpt dyntopo: Dynamic field-propegated topology rake
I might write a paper on this.  Topology rake now locally
updates a vector field, which it uses to smooth the input
and constrain to mesh (including face set) boundaries.
This can make an enormous difference for things like
smoothing.

Note that this is different from the existing 'curvature rake'
mode, which also builds a field and which is fed into the input
of this new one.

The only oddity is that the field is stored in a CD_PROP_COLOR
since we don't have a CD_PROP_FLOAT4, and this shows up in the UI
(not sure if I'm messing up the CD_TEMPORARY flags or if the UI
doesn't check for them).
2021-08-30 15:04:43 -07:00
73529fb1bb Sculpy dyntopo: fixed various topology bugs
* Fixed crash in dyntopo collapse.  The
  loops around vertex iterator dyntopo uses
  doesn't actually work on non-manifold meshes,
  or meshes with invalid normals, this was not
  being checked in pbvh_bmesh_collapse_edge.
* Rotate tool now works with dyntopo.
2021-08-29 16:05:26 -07:00
381ef09073 Sculpt dyntopo: another bugfix from today's earlier commits 2021-08-28 15:33:41 -07:00
56ba339cd8 Fix a few bugs in lat commit 2021-08-28 14:59:54 -07:00
055fa3fa5e fix missing curly braces 2021-08-28 13:59:00 -07:00
7d5c3beb06 Sculpt dyntopo: Fix bug with edge collapse 2021-08-28 13:30:46 -07:00
39b0e9df81 Sculpt dyntopo: Add edge API
* Added a minimal edge API to query edge
  boundary states.
* This is necassary because the previous approximation,
  testing if two adjacent verts are boundaries, breaks
  for triangles.
2021-08-28 12:14:59 -07:00
6648f82ef7 Merge branch 'master' into sculpt-dev 2021-08-28 19:58:13 +02:00
320ff87948 Sculpt: Quantize mask filter 2021-08-28 19:57:32 +02:00
b21595cdf9 Tweak last commit to not affect base face set. 2021-08-27 21:54:15 -07:00
e4b36fb6bc Sculpt dyntopo: split face set boundaries on mirror boundary
Added an option to split face set boundaries on mirror
boundaries; currently only DynTopo supports this.

Very useful for making hard edges along mirror lines.
2021-08-27 20:02:20 -07:00
966e4ba9ae Sculpt dyntopo: improved boundary smoothing
It's kind of hackish mathematically.
2021-08-27 18:13:18 -07:00
268682527f Sculpt dyntopo: added a smoothing factor for sharp boundaries
Works by projecting non-boundary verts onto boundary vert
normals and weighting by boundary_smooth_Factor.
2021-08-27 14:18:50 -07:00
cdb52aee9f Missed an ATTR_NONNULL fix 2021-08-27 01:59:34 -07:00
8b02ab86f1 change 'error' to 'warning' in a printf 2021-08-27 01:57:13 -07:00
019700583b Sculpt dyntopo: undo bugfixes
* Fixed nasty undo bug related
  to now rewinding BMLogEntry subchains properly.
* Fixed bug in dyntopo collapse
2021-08-27 01:51:56 -07:00
31d2b04411 Sculpt dyntopo: Who knew gcc's nonnull attribute is 1-based 2021-08-26 20:23:17 -07:00
3508c699fb Sculpt dyntopo: Cleanup past few commits
* Removed some ATTR_NO_OPTs
* Made pbvh_split_edges disallowed
  4-valence splits if cleanup topology
  mode is on
2021-08-26 20:10:54 -07:00
8ea7c93a37 Sculpt dyntopo: support sharp edge flags
* Sharp edge flags are now supported and are
  treated much the same as face set boundaries:
 + Dyntopo preserves them
 + Interior smoothing treats them as boundaries
 + Corners are detected and pinned in smoothing
 + TODO: add a brush flag to ignore sharp boundaries
   for smoothing.
* Seams are also preserved, but don't affect smoothing.
* BMLog now saves edges.
* The new edge split function is enabled.
* Dyntopo now pushes new combined BMLog entries in
  its top-level function, to avoid scary id reuse
  edge cases.
* SCULPT_vertex_is_boundary/corner now take a bitmask
  of which types of boundaries you wish to query instead
  of check_face_sets.
2021-08-26 18:00:29 -07:00
8b8733e76c Sculpt Vertex Colors: New sample color operator 2021-08-27 01:07:07 +02:00
4dda04eaa9 Merge branch 'master' into sculpt-dev 2021-08-26 23:19:21 +02:00
30691560fa Fix C++20 designated initializer build issue. 2021-08-26 20:56:13 +05:30
12f87d02c6 commit prior to small cleanup 2021-08-25 03:01:56 -07:00
9680edf77c * Implemented bounday/face set corner handling.
* New function SCULPT_vertex_is_corner, similar to
  SCULPT_vertex_is_boundary it takes argument to
  check face sets.  PBVH_FACES/GRIDS version is
  incomplete.  It returns a bitmask of whether
  the vert is a boundary corner and/or a face
  set one.
* PBVH_BMESH uses a somewhat more expensive
  calculation to detect corners of face set islands by
  edge angle. This is currently not done for boundary
  corners.

Corner pinning now happens in:

* The internal smoother dyntopo uses for stability reasons.
* SCULPT_vertex_neighbor_average_interior.
* Topology rake.
* Dyntopo collapse.

Note that DynTopo always pins face set corners
but everything else only does so if preserve face
sets is on.
2021-08-24 13:18:36 -07:00
a00bfa8976 Sculpt dyntopo: more smooth stuff
* All of the smooth brushes now use the SculptCustomLayer
  system for temporary data, so all work with dyntopo now.
* You can now use a flat array in SculptCustomLayer with
  PBVH_BMESH (though you have to build the structure manually).
  The mesh filter code uses this.
* Smooth (and autosmooth) now have an option to preserve face
  set boundaries.  Corners are currently not handled.
* Simplify brush has preserve face set boundaries autosmooth
  flag set by default.
* SCULPT_vertex_is_boundary now takes an addition argument
  for whether to check for face set boundaries.
2021-08-23 22:55:17 -07:00
bde54e127e Sculpt dyntopo: Smooth improvements and bug fixes
* Added an option to weight smooth by face areas
* Dyntopo now caches face areas in a CD_PROP_FLOAT layer
* Dyntopo also caches number of edges around verts inside of
  MDynTopoVert.  To avoid increasing the struct size flag was
  made a short.
* Cleanup mode (dissolves 3/4-valence verts) now piggybacks on
  subdivide code to build list of verts; this is much faster.
2021-08-23 21:06:10 -07:00
9b8c82e2ed Sculpt dyntopo: fix mem cache test function, how did this
ever work
2021-08-23 02:28:19 -07:00
5866a4680d Dyntopo Sculpt: Wrote new edge split code, currently disabled 2021-08-23 01:19:55 -07:00
d795144f54 I hate default int 2021-08-22 13:31:05 -07:00
de6258c618 Silly me, don't use alloca in this situation 2021-08-22 13:16:10 -07:00
d912ceeb40 Fix compile error on linux 2021-08-22 13:15:08 -07:00
9a197a1185 Sculpt dyntopo: Temp fix for nasty GCC compiler bug on linux.
I'll file a bug report with GCC tomorrow.
2021-08-22 12:51:53 -07:00
36785c83f0 Sculpt dyntopo: Fix a dumb mistake I made in space_toolsystem_toolbar.py 2021-08-22 10:29:36 -07:00
8eb7a04150 fix signed/unsigned warning 2021-08-21 20:46:08 -07:00
97c3e5944c Sculpt dyntopo: Finished bmesh cache coherency tester
To run, in the python console enter:

bpy.msgbus.pbvh_bmesh_do_cache_test()

The output will be in the regular console.  The test
build a half-million vert cube and smooths it. It runs
several passes (all of which perform the same smoothing
operation):

1; Randomized order pass
2. Ordered pass (by vertex clustering)
3. Same as 2 but with a purely data-oriented version
   of the bmesh structs.
4. Same as 2, but using a version of the bmesh structs
   with all pointers replaced by integer indices.

At least on my laptop #3 and #2 are about a third faster
then #1, and #2 tends to be around 15%.
2021-08-21 20:40:22 -07:00
6f523ffacb Sculpt dyntopo: Don't allow dyntopo when multires modfier exists
Note that thoeretically we could support multires in dyntopo,
but numerical instability would probably make the grid data
explode.
2021-08-21 15:19:15 -07:00
04562794df Sculpt dyntopo: disable mem cache test executable
from compiling altogether
2021-08-20 20:52:22 -07:00
93004c7b19 Dyntopo: Disable mem cache test executable for now as it
doens't link on mac
2021-08-20 20:49:29 -07:00
0d542db1e1 Sculpt dyntopo:
* Fixed multires apply base feeding bad original coordinates to
  deform modifiers.
* Roughed out some code for cache performance testing.
* Wrote skeleton code for a PBVH texel API; hasn't been tested
  yet and may be removed.
2021-08-20 20:36:04 -07:00
de1f2c41fa * BM_mesh_remap can now reorder loops
* Wrote yet another BKE_pbvh_reorder_bmesh function
2021-08-18 21:43:59 -07:00
106f542ac4 Sculpt dyntopo: yet another undo bug
BKE_pbvh_bmesh_add_face had a branch where it ignored
the log_face argument, leading to corruption in
BMLog.
2021-08-17 14:58:37 -07:00
83f94ebb6f Sculpt dyntopo: remove debug ATTR_NO_OPT's 2021-08-17 00:31:04 -07:00
954aa88ba4 Sculpt dyntopo: more undo fixes
Yay for massively overdetermined bugs.
2021-08-17 00:09:43 -07:00
9503751c83 Sculpt dyntopo
* Added a limited "fast draw" mode to pbvh drawing
  that tries to limit data sent to the GPU.
 - Facesets and mask data are disabled.
 - Indexed mode is forced.
 - Does not work (at all) for multires.

* Finally fixed some outstanding bmesh sculpt undo bugs:
 - Forgot to mark pbvh nodes to update their bounds, which
   produced a bug I had thought was caused by something else.
 - Hopefully fixed a long-standing occasional memory corruption
   bug.
2021-08-16 20:50:02 -07:00
dcaba4c5e3 Sculpt dyntopo: fix various faceset init operator bugs
that crept in.
2021-08-16 16:34:35 -07:00
fb463a13cd Sculpt dyntopo: Fix memory corruption caused by improperly disabled
code.
2021-08-16 02:12:30 -07:00
b5100e73c8 Sculpt dyntopo: Fix boundary brush for multires
This commit fixes boundary brush for multires which
broke two commits ago.

This required implementing the geodesic api for PBVH_GRIDS,
which I did by building topology maps in a rather. . .
haphazard fashion.

Basically I built a vert->edge map and then used it to
derive a pseudo edge to quads mapping (it maps edges
to all the verts in the two surrounding quads except
the edge's own verts).

Just for fun I enabled geodesic mode in mask expand;
it seems to work.
2021-08-16 01:44:31 -07:00
ab632243e6 Merge branch 'master' into temp_bmesh_multires 2021-08-15 18:14:41 -07:00
8510c77b9c Sculpt dyntopo: improve boundary brush for irregular topology
(still a wip)

The boundary brush now builds a geodesic distance
  field (from the boundary) from which it derives a tangent
  field:

* These now define the rotation plane for bend mode.
* Rotation origins snap to these planes.

There is also typedef'd code for visualization tangents
in a temporary object (note the sculpt object), to enable
define VISBM in sculpt_boundary.c.  This will be removed
lated.

Additional changes:

* Added a function to get the number of edges around verts,
  SCULPT_vertex_valence_get.
* Added an API to calculate cotangent weights for vert fans,
  SCULPT_cotangents_begin (call in main thread first) and
  SCULPT_get_cotangents.
* Sculpt neighbors for PBVH_FACES now uses ss->vemap if it exists.
* The Mesh topology mapping code now takes extra parameters for
  sorting vert/edge cycles geometrically.
* Similarly, there is now a function to sort BMesh edge cycles,
  BM_sort_disk_cycle.
* MDynTopoVert->flag now has a bitflag for when the disk cycle
  sorting needs to be redone, DYNVERT_NEED_DISK_SORT.
* The sculpt geodesic code now supports passing in custom vertex
  coordinates.
* The geodesic API can also build an optional map of which vertex
  in the initial vertex list is closest to any other vertex.
2021-08-15 18:02:16 -07:00
40aa321dc7 Sculpt dyntopo: fix bug with dyntopo geometry undo push 2021-08-11 22:51:09 -07:00
a80c381ec5 Sculpt Dyntopo: PBVH draw fixes
* The PBVH draw subsystem is now told whether any viewports
  have drawtype >= OB_MATERIAL before anything in any windows
  are drawn.  There are no alternatives given the design
  constraints of sculpting, where simply uploading data to the GPU
  quickly becomes a bottleneck.

* Fixed flat vcol shading mode.
2021-08-07 22:28:00 -07:00
1e9a7383ef * Don't rely on BMLog's stored normals, instead flag pbvh nodes to
update normals on undo/redo.
2021-08-07 19:25:36 -07:00
dc738de90c Sculpt dyntopo: Fix bug in cleanup_valence_3_4 2021-08-06 18:39:54 -07:00
8ed4c5fc61 Merge branch 'master' into temp_bmesh_multires
Also fixed a pbvh corruption bug
2021-08-06 12:51:18 -07:00
76bd253be7 Dyntopo sculpt: add dev operator to debug memory cache coherency 2021-08-06 09:58:46 -07:00
c78b0874ad Asset Browser: Support dropping materials into Face Sets 2021-08-06 17:33:18 +02:00
b991a92aab Merge branch 'master' into sculpt-dev 2021-08-05 20:10:57 +02:00
01965a275c Cursor: Change face set color and wireframe preview 2021-08-04 22:17:48 +02:00
b2dc8bd92e Merge branch 'master' into sculpt-dev 2021-08-02 21:35:31 +02:00
d3faf09082 Merge branch 'master' into sculpt-dev 2021-07-31 17:16:02 +02:00
b243eb2646 Merge branch 'master' into temp_bmesh_multires
Also:

* added BMLog function to save mesh IDs.
  - Used by SCULPT_UNDO_DYNTOPO_BEGIN/END instead of
    saving the whole mesh, which was the previous behavior.
* SCULPT_UNDO_DYNTOPO_BEGIN no longer pushes a non-dyntopo
  geomtry undo node, as this is no longer necassary.

This greatly speeds up going into/out of sculpt mode
with dyntopo enabled, as before it was copying
the mesh twice.
2021-07-29 16:08:14 -07:00
fcfb47b983 Merge branch 'master' into sculpt-dev 2021-07-27 22:00:24 +02:00
c1f5ac7cfe Array Brush: Support array editing with the voxel remesher 2021-07-25 20:36:56 +02:00
89897140cf Merge branch 'master' into sculpt-dev 2021-07-25 18:20:27 +02:00
af71984942 sculpt dyntopo: fix memory corruption and associated memory leak 2021-07-25 05:28:54 -07:00
ec4b9dff19 Add 'projection' option for volume-preserving smoothing to
smooth corrective modifier
2021-07-23 15:46:01 -07:00
d71b6d37fe Array Brush: Initial radial and linear array editing 2021-07-23 21:29:07 +02:00
2689124320 Array Brush: Path edit mode working 2021-07-21 23:27:46 +02:00
70a4956020 Sculpt dyntopo: Removed triangle limit for PBVH_BMESH
* PBVH_BMESH now supports faces other then triangles;

* Dyntopo triangulates faces as it finds them.
  - I looked into methods of preserving quads and failed to
    find anything that worked well in practice; it actually
    worked better to use topology rake to align triangles
    into quads and then mark diagonal edges for later dissolving
    then to try to preserve quads explicitly (I've not
    implementated that here, that was research code).
  - To avoid excessive cache-destroying loops over vertex-faces,
    DynTopo flags which verts have non-triangle faces.

* PBVHTriBuf now builds edge buffers so we can avoid drawing
  tesselation phantom edges.

* BMLog also now supports arbitrary faces.  It still does not
  support edges though.

TODO:

* Fix vcol cell shading mode
* Make sure indexed drawing works
2021-07-20 19:46:00 -07:00
93305b97df Merge branch 'master' into sculpt-dev 2021-07-20 18:28:53 +02:00
7cd74015f8 Sculpt dyntopo: Another fix for faceset boundary handling
* Turned out pbvh->cd_faceset_offset wasn't being updated
  correctly.
2021-07-20 05:47:08 -07:00
7bd521a5c4 Sculpt dyntopo: Another small fix 2021-07-20 04:56:29 -07:00
7dda5ac5ba A few small fixes for last commit 2021-07-20 04:29:23 -07:00
1694e2aca4 Sculpt dyntopo: Face set boundaries are now presered with dyntopo
* Face set boundaries are now preserved on dyntopo remeshing.
* MDynTopoVert->flag now has a DYNVERT_FSET_BOUNDARY flag
  in addition to DYNVERT_BOUNDARY.
* Instrumented uiBut with ASAN poison regions to hopefully
  find the super evil memory corruption bug that's been driving
  me insane.  It's frustratingly intermittent.  There are five
  poison regions.
2021-07-20 04:14:59 -07:00
2fddbebf93 Sculpt dyntopo: Dyntopo now handles mesh boundaries in a more
intelligent way.
2021-07-19 15:32:41 -07:00
4247a56cde Add back hackish fix for clang bug. I should probably
file a bug report with the clang people.
2021-07-18 13:15:43 -07:00
e3b58b6451 Sculpt dyntopo: Split off dyntopo stuff from pbvh_bmesh.c into a new file, dyntopo.c. 2021-07-18 13:12:08 -07:00
5b10d08db3 Sculpt dyntopo:
* Prototyped a threaded bmesh->Mesh converter function.  It's about
  20-30% faster.  Currently disabled.
* Tried to fix more of the bugs when stepping between sculpt and
  other undo step types in the global undo stack.
2021-07-17 04:10:28 -07:00
7c4eb4f8db Merge branch 'master' into temp_bmesh_multires 2021-07-17 00:44:01 -07:00
792292e3de Sculpt dyntopo: BLI_mempool now adds redzones when compiled with ASAN 2021-07-16 23:29:28 -07:00
95a969e7d5 Array Brush: Disable debug drawing 2021-07-15 21:20:48 +02:00
f9c0c9e70c Merge branch 'master' into sculpt-dev 2021-07-15 21:16:12 +02:00
aousdfh
3600e9057b Array Brush: expose fill holes and orientation lock 2021-07-15 21:00:14 +02:00
aousdfh
a78ecfe0f3 Array Brush: Fix crash 2021-07-14 02:57:07 +02:00
aousdfh
65127f9875 Array Brush: Refactor array indices access 2021-07-14 02:02:26 +02:00
aousdfh
37c2bbe5ea Array Brush: Fix EEVEE and modifier evaluation 2021-07-13 19:22:00 +02:00
aousdfh
ceac1d91e2 Array Brush: Fix scale, symmetry and rotation jittering 2021-07-13 02:16:05 +02:00
aousdfh
dfab5a0c4a Array Brush: Array rotation orientations working 2021-07-13 00:37:10 +02:00
aousdfh
85379482d5 Array Brush: Orientation detection working 2021-07-12 23:49:22 +02:00
4ca249018d More msvc errors 2021-07-12 16:03:22 -04:00
d529e13d65 Sculpt dyntopo: fix msvc compiler error 2021-07-12 16:01:17 -04:00
4e797dbc69 Definitely going to modify BLI_strict_types.h 2021-07-12 12:30:23 -04:00
aousdfh
41a8e94d4d Array Brush: First attempt to copy orientation (disabled) 2021-07-12 17:48:42 +02:00
1b9a835893 Make gcc happy 2021-07-11 23:57:14 -04:00
320a1b6f35 Fix bug in previous commit; customdata_bmesh_set_default now ignores
CD_MESH_ID layers
2021-07-11 23:28:19 -04:00
f07f56aa37 BM_mesh_create will now add mesh_id customdata layers when asked,
instead of leaving that to the client.

Also semi-fixed uninitialized memory bug in bmesh unit test (dunno
how best to memset a C struct in C++ won't won't run afoul of some
random compiler somewhere).
2021-07-11 22:02:52 -04:00
4e91e72d53 Let's try that again 2021-07-11 21:21:10 -04:00
58b4688c34 Weird linux compile error 2021-07-11 21:20:37 -04:00
2f862bc7b9 Fix more dyntopo sculpt undo memory corruption 2021-07-11 21:14:49 -04:00
4674795591 Sculpt dyntopo: another attempt to fix undo memory corruption bug 2021-07-11 13:14:24 -04:00
be9017c349 Fix implicit int error 2021-07-11 06:01:39 -04:00
4c2f5b80b7 Remove extraneous code 2021-07-11 05:25:41 -04:00
0502b0103f Merge branch 'master' into temp_bmesh_multires 2021-07-11 05:23:24 -04:00
e8b717ee42 Sculpt dyntopo: Exposed UV smooth bruth in experimental features prefs.
* Also got undo working for it
2021-07-11 04:12:20 -04:00
4b4ac93acd Sculpt dyntopo: Wrote a little UV smoother sculpt brush.
It uses a simple LSCM-like solver; hold ctrl to do simple
laplacian relaxation.

There are some interesting artistic possibilities to using
DynTopo with UV maps, the point of this tool is to help
explore them.

Note that I'm not planning to merge this into master with
the rest of this branch.  When the time comes I plan to
move it into a new branch for sculpt research stuff.
2021-07-11 03:43:47 -04:00
aousdfh
f283c527d2 Array Brush: Scale and stroke strength working 2021-07-09 00:01:56 +02:00
aousdfh
820d086719 Array Brush: Count and deform mode brush properties 2021-07-07 03:26:52 +02:00
aousdfh
69668d62ba Array Brush: Working code for path and radial arrays 2021-07-07 02:20:14 +02:00
aousdfh
351744f2b0 Sculpt Array: Debug path drawing 2021-07-06 01:21:14 +02:00
aousdfh
5ac471a021 Sculpt Array: Initial code for path and path points 2021-07-06 01:06:15 +02:00
aousdfh
db932ccde6 Array Brush: Implement symmetry datalayers 2021-07-06 00:44:49 +02:00
57286eed8d Sculpt dyntopo: Add support for multiple materials to dyntopo
pbvh drawing.

* Dyntopo now stores a list of PBVHTriBufs in leaf nodes, one per material
  used by the node.
* Actual drawing buffers live in a new mat_draw_buffers PBVHNode member.
2021-07-02 13:14:00 -07:00
9dbf3b9fab Array Brush: Implement array instances datalayer 2021-07-02 22:10:21 +02:00
4f8c63e77b Array Brush: BMesh duplication working 2021-07-02 19:52:58 +02:00
47c226cbe3 Array Brush: Add template code and support geometry modifications 2021-07-02 16:38:37 +02:00
d0759840a0 Merge branch 'master' into temp_bmesh_multires 2021-06-30 21:38:18 -07:00
5b19b2cb56 remove debug printf 2021-06-30 21:25:46 -07:00
dcb00bf529 * Enable mask/fset extract for dyntopo]
* Fix nasty memory corruption bug
2021-06-30 21:13:24 -07:00
e8e062f866 Merge branch 'master' into sculpt-dev 2021-06-30 18:12:50 +02:00
9838e9e485 Merge branch 'master' into sculpt-dev 2021-06-30 01:31:21 +02:00
d66d5b431e Clean up a few warnings 2021-06-29 05:50:40 -07:00
43a0fe378f Merge branch 'master' into temp_bmesh_multires 2021-06-29 04:35:53 -07:00
199f846072 Merge branch 'master' into sculpt-dev 2021-06-28 19:44:07 +02:00
fb6636c812 Sculpt dyntopo: fix bug with automasking being needlessly initialized 2021-06-26 23:46:47 -07:00
adc8980dec Sculpt dyntopo: fix symmetrix undo bug from last commit 2021-06-26 22:52:35 -07:00
48c41b189a fix type of code line being after the parenthesis
instead of before
2021-06-26 21:40:07 -07:00
7562ad5777 Sculpt dyntopo: BMLog now uses the new bmesh unique id system
A few notes:

* MESH_ID layers are not saved on conversion to Mesh unless
  you ask for it in BM_mesh_bm_to_me's params.
* Still need to test the box/lasso trim tools.
* Need to find some way to test loop/edge ids, which aren't
  used by dyntopo.
2021-06-26 21:26:33 -07:00
27986e9b56 Sculpt dyntopo: Added a function to add multiple customdata
layers to a bmesh at once.  Helpful since bmesh customdata
layers are allocated in single blocks, thus adding
layers individually can lead to lots of memory
copying.
2021-06-26 19:12:07 -07:00
dba4f30328 Sculpt dyntopo: Added (optional) support for unique mesh id tracking in
bmesh

* System is per element type.  So you can have unique ids for verts and
  faces, but not edges and loops.
* Supports an optional id to element lookup table.
* Uses single id space for all elements
* Added a new CD_FLAG_ELEM_NOCOPY flag to tell
  customdata_bmesh_copy_data to ignore that layer.
* IDs are stored as a temporary customdata layer with
  CD_FLAG_ELEM_NOCOPY set.
2021-06-26 18:24:00 -07:00
83c491f044 Merge branch 'master' into temp_bmesh_multires 2021-06-26 13:00:26 -07:00
7ef7843ada Sculpt Dyntopo: Fix memory corruption in dyntopo undo
ss->active_XXX_index wasn't being handled properly.
2021-06-25 17:10:12 -07:00
5a7b9adef1 Dyntopo sculpt: add support for asan to mempool 2021-06-25 15:04:09 -07:00
d293de425f Sculpt Dyntopo: fix bug in dyntopo brush spacing. 2021-06-25 11:49:28 -07:00
17d4c7abb1 Sculpt dyntopo:
* Got automasking to work with dyntopo properly.
  - AutomaskingCache->factor
    has been replaced with the new temp layer API (which works for all
    PBVH modes).
  - AutomaskingCache->factor is, however, only initialized for
    topology and face set boundary modes (if DynTopo is enabled)
    since it's probably better to calculate the rest dynamically
    in that case.
* Fixed stats bug
2021-06-24 23:50:49 -07:00
2f81449a70 Twist brush: use relax instead of smooth 2021-06-22 01:20:36 +02:00
ca4ac36c59 Merge branch 'master' into temp_bmesh_multires 2021-06-20 15:58:24 -07:00
5c328ab8b0 Twist Brush: Add separate smooth step 2021-06-20 18:32:19 +02:00
7a67cb2aeb Twist Brush: Fix bug in rotation 2021-06-20 17:53:35 +02:00
178c3a4064 Twist Brush: Scale brush tip space per vertex 2021-06-20 17:34:20 +02:00
15884510e8 Twist Brush: Deform rotation space 2021-06-20 17:21:53 +02:00
22e2e4f062 Twist Brush: Rotate in brush tip space 2021-06-20 17:12:05 +02:00
3ccc160682 Merge branch 'master' into sculpt-dev 2021-06-20 16:46:21 +02:00
00fd823bcd Sculpt dyntopo: Don't calculate curvature info in topology rake if curvature
mode is not enabled.
2021-06-19 23:54:51 -07:00
d9badbf25c Merge branch 'master' into sculpt-dev 2021-06-19 22:12:13 +02:00
f16e35ce0a Twist Brush: Initial working version 2021-06-18 22:01:26 +02:00
425e5c8d76 Twitst Brush: initial commit 2021-06-18 21:44:29 +02:00
1ab412f13d Merge branch 'master' into sculpt-dev 2021-06-18 21:24:36 +02:00
ee1c0c682b Fix build in edit mode mesh fairing 2021-06-16 21:06:27 +02:00
59f0811ac9 Merge branch 'master' into sculpt-dev 2021-06-16 21:01:43 +02:00
45f522888b Merge branch 'master' into sculpt-dev 2021-06-14 22:53:41 +02:00
d15262ded1 Merge branch 'master' into sculpt-dev 2021-06-11 21:58:12 +02:00
ab5b138805 Merge branch 'master' into sculpt-dev 2021-06-08 22:56:21 +02:00
8ca52a7757 Merge branch 'master' into temp_bmesh_multires 2021-06-07 16:57:33 -07:00
d4af8a8d26 Sculpt: Make subdivision surface modifier use the On Cage option 2021-06-04 16:20:38 +02:00
b1e59f1a20 Merge branch 'master' into sculpt-dev 2021-06-03 22:46:38 +02:00
bd34d77a90 Merge branch 'master' into sculpt-dev 2021-06-03 20:24:11 +02:00
3ac83dcc73 Merge branch 'master' into sculpt-dev 2021-06-01 14:26:49 +02:00
900178d438 Fix build after merge 2021-06-01 14:22:49 +02:00
414b8b7628 Merge branch 'master' into sculpt-dev 2021-06-01 12:52:07 +02:00
4adc0a7798 Dyntopo: do a little bit of code cleanup 2021-05-31 10:53:22 -07:00
88620e8cd9 Merge branch 'master' into sculpt-dev 2021-05-31 11:14:07 +02:00
552e44bd25 Fix implicit int error 2021-05-27 14:30:45 -07:00
1f19a86150 DynTopo:
* Fixed failed patch reversion from a while ago
* Also tweaked a few comments.
2021-05-27 12:15:49 -07:00
702376e935 Merge branch 'master' into sculpt-dev 2021-05-27 11:24:32 +02:00
3ca3098ed7 DynTopo: Enable BLI_linklist_stack type checking for clang-cl
and fix a few errors.
2021-05-24 11:40:05 -07:00
995702da48 Let's try that again. 2021-05-23 21:39:37 -07:00
33066542ca MIssed a flag in bli_strict_types.h 2021-05-23 21:34:20 -07:00
5a26ea0961 DynTopo: Attempt to fix compiling on macos 2021-05-23 21:02:29 -07:00
1e3e79fe7b Fix one more strict flags violation 2021-05-23 20:52:25 -07:00
d4292bbd28 * Added clang-cl support to BLI_strict_flags.h 2021-05-23 20:39:52 -07:00
a97c5d7daa DynTopo: started refactoring pbvh drawing to handle customdata layers in
a more generic (and maintainable) way.
2021-05-23 16:11:16 -07:00
6b009b8890 Merge branch 'master' into temp_bmesh_multires 2021-05-23 14:30:32 -07:00
3d16099a77 Dyntopo:
Fix multires not setting pbvh->depth_limit
2021-05-20 17:59:09 -07:00
4352980b0f Dyntopo
* Got threaded mesh->bmesh conversion working (it's disabled
  pending further testing however).

Note that SCULPT_dynamic_topology_enable_ex calls BKE_scene_graph_update_tagged,
which in tests was adding ~1 second to conversion time for larger
meshes.  Do we need this call?
2021-05-19 14:36:00 -07:00
3d6ac0bd7b Dyntopo: code cleanup 2021-05-19 12:21:46 -07:00
71959181ad * Fix bug with symmetrize creating non-manifold geometry.
* Fix bug in pbvh face create
2021-05-18 22:26:49 -07:00
daa4a33383 Merge branch 'master' into temp_bmesh_multires 2021-05-17 19:48:16 -07:00
d3695eb12c * Fix corner case in last commit 2021-05-17 14:23:02 -07:00
c1f236dcd4 BMLogFace now stores the face normal. 2021-05-17 14:02:31 -07:00
3276c3b4a1 Merge branch 'master' into sculpt-dev 2021-05-17 22:08:28 +02:00
a90533e9b8 Cleanup failed patch reversion 2021-05-17 00:45:07 -07:00
9bea7259e1 Merge branch 'master' into temp_bmesh_multires 2021-05-16 23:32:35 -07:00
7fca310f25 Dyntopo now updates the existing pbvh on undo instead of building
a new one from scratch, an operation that can be slow despite being
  threaded.

PBVH building is a memory bound operation (not just on the CPU side
either, remember the draw buffers have to be fully regenerated too).
Incrementally updating it this way is enormously faster (about as fast
as non-dyntopo undo).

The downside is we don't have the convienience of users regularly
building the pbvh from scratch anymore.  Dyntopo does try to
join empty PBVH nodes (which happens after every stroke), but
that's not a complete substitute for a decent tree balancer.
That's on the todo list.
2021-05-15 21:19:20 -07:00
27f4f761e7 Tried to make pbvh bmesh normals calc a bit more efficient. 2021-05-15 11:51:14 -07:00
17fafe2f63 fix memory leak 2021-05-14 21:21:01 -07:00
89d56ea225 fix missing null pointer check. 2021-05-14 21:12:23 -07:00
cfd6d48aab * Prototyped a faster smooth algo, currently disabled.
* Wrote a new API for wrangling temporary customdata layers across pbvh types:
  - SCULPT_temp_customlayer_ensure: makes sure a (named) customdata
    layer exists.  Works for multires; since these are temporary
    layers we can safely allocate them in a temporary CustomData
    structure (in ss->temp_vdata).
  - SCULPT_temp_customlayer_get: initializes a special structure,
    SculptCustomLayer, that is used to get per elem customdata.
  - SCULPT_temp_cdata_get: Uses a SculptCustomLayer ref along with
    a SculptVertexRef to look up the data.
2021-05-14 18:26:41 -07:00
6be2c079c1 Did some profiling with VTune.
* Sculpt code seems to be memory bandwidth bound.
  * Some key topology loops will have to be written manually
    instead of using BM_ITER.

I wrote a function to re-allocate a bmesh with elements ordered by
PBVH leaf nodes, SCULPT_reorder_bmesh.  It's currently disabled.

This is going to take more profiling, but my original proxy refactor
idea might be worth revisiting.  Might be more cache efficient.

The good news is that the worst case is the smooth code, which I can speed
up significantly by keeping a bit of state around.
2021-05-14 15:56:04 -07:00
ae5d971e8f Merge branch 'master' into sculpt-dev 2021-05-14 19:09:06 +02:00
13bdc4a7e6 Merge branch 'master' into sculpt-dev 2021-05-14 19:08:19 +02:00
72aad83780 Merge branch 'master' into sculpt-dev 2021-05-13 17:43:21 +02:00
32ceaa7919 Update ATTR_NO_OPT macro 2021-05-12 22:27:35 -07:00
ec4786d00b Dyntopo branch
* Sculpt expand now works with dyntopo in more cases
* Fixed various dyntopo face set bugs

Stuff from several commits ago:

* There is now an API to get face sets using SculptFaceRef's.
  + SCULPT_face_set_get
  + SCULPT_face_set_set

* Prototyped a faster geodesic propagation function, but it currently
  doesn't work.

* Dyntopo triangulation now preserves face flags (took some work as BM_triangulate_face explicitly prevents selection flags from being preserved).
* Also face smooth flags are no longer being overriden.
* Most of the faceset create operators work (I'm not sure I've tested
  all of them though).
* SCULPT_face_set.c now has helper functions that checks if a pbvh
  is *not* PBVH_BMESH, in which case it builds a temporary bmesh,
  otherwise ss->bm is used (sculpt_faceset_bm_begin and sculpt_faceset_bm_end).
  + Note that some functions were able to use SCULPT_face_set_XXX
    instead and avoid bmesh entirely.
2021-05-12 16:22:39 -07:00
582c30d32f Fix nasty edge case for BMLog. 2021-05-11 22:57:06 -07:00
b047b333b0 Remove yet more debugging crap . . . 2021-05-11 21:48:14 -07:00
f2c9706781 Get rid of various ATTR_NO_OPT debug attributes left from two
commits ago.
2021-05-11 21:46:44 -07:00
fa06238aa7 Fix bug in last commit. 2021-05-11 21:45:43 -07:00
b8a8e4f9b1 Today I ran outside screaming and an hour later came back in and made BMLog
reference counted.  This fixes various undo bugs caused by dyntopo
needing to execute an undo push but not being able too (e.g. during
file load, and I think it also happens sometimes with global undo).

A much better way of fixing this would be to add unique IDs to mesh
verts and faces, perhaps as a customdata layer.

The root problem is that BMLog assigns unique IDs to mesh elements,
which it does via a series of GHash's.  I imagine this is a fairly
serious violation of the undo system's design rules, since it means
BMLogs are tied to specific instances of the bmesh in SculptSession->bm.

There were some hacks to try and get around this, but they were buggy
and needed to push the unstack stack to work, which wasn't possible in
all cases (e.g. if G_MAIN->wm.first->undo_stack is NULL, as it is during
file loading and apparently global undo).

Anyway, long story short each chain of SculptUndoNodes needs some way
to reconstruct their ID GHash's when exiting/entering the chain. The
only way I could think to do this was to make BMLog reference counted,
with BMLogEntry the users.

Like I said, having a proper system to assign unique IDs to mesh
elements would be *much* better.
2021-05-11 21:14:45 -07:00
dbe767f5d9 Merge branch 'master' into temp_bmesh_multires 2021-05-11 14:18:48 -07:00
fad42fc6c7 Merge branch 'master' into sculpt-dev 2021-05-10 19:01:57 +02:00
7cf3b1f472 Get face set create operator working for dyntopo 2021-05-07 07:04:19 -07:00
6c3b29a14c Merge branch 'master' into temp_bmesh_multires 2021-05-05 08:52:14 -07:00
febfaecd97 * Added new paint API method paint_stroke_apply_subspacing, for various
things that need custom spacing (that is coaser than the brush radius),
  and refactored the existing dyntopo spacing code to use it.

* Added option to topology rake to ignore brush falloff settings
  (it forcibly uses Smooth falloff).

* Smooth and topology rake support custom spacing now.
  + This is especially important for the clay brush, which works
    better at smaller spacings and with a bit of autosmoothing.
    Now you can tell it to override the smooth spacing to be coarser,
    leading to much better performance.

* Topology rake now has a projection setting similar to autosmooth
  which defaults to 1.0 (to preserve current behavior).

The main motivation for this commit was to make topology rake work
better for normal brushes.  This is now possible, however it tends to
make the brush slower and also the settings are a bit fiddly.
We might want to make dedicated brush presets for this.

Btw, the UI for brush settings are becoming a real mess. Help!
2021-05-02 14:29:30 -07:00
2d98802905 * Added a "projection" option to smooth/autosmooth. It works by
projection neighboring vertices onto the current smooth vert's normal
  plane, multiplied by a "projection" factor.  This is extremely similar
  to what the surface laplacian produces, but is much simpler, uses
  no temporary state and thus can be used in more places.
2021-05-02 10:54:12 -07:00
f70a8c1581 Merge branch 'master' into temp_bmesh_multires
Also fixed a pose brush bug that may or may not have been
the result of the merge nixing code, need to check master.
2021-04-29 10:17:22 -07:00
8eeacca9cb Fix a few cast warnings 2021-04-29 08:01:32 -07:00
82847af9f9 Fix invalid parameter type in bmlog. 2021-04-29 06:28:37 -07:00
ee19a80041 * Eeek, left in an ATTR_NO_OPT attribute 2021-04-28 19:31:43 -07:00
013eee7ec6 * The dyntopo remesher is now a bit smarter about avoiding
certain degenerate cases that produce lots of bad geometry (and
  also bad PBVHs that slows down the whole mesh).
 + A very small amount of surface smoothing is now applied by dyntopo.
 + The recursive functions that expand the region considered by dyntopo
   now ignore "front face only" for depths less then 5.
 + The number of edges dyntopo can split or collapse in one run has been cut in
   half to 4k.
   - This limit is also now dynamically adjusted by a measure
     of how skinny the edges are.
2021-04-28 19:11:23 -07:00
ce0b4e6681 Merge branch 'master' into sculpt-dev 2021-04-28 21:55:09 +02:00
d1cf59e547 Sculpt: Add operator to store a limit surface manually 2021-04-27 23:54:04 +02:00
d0407b0ed5 Merge branch 'master' into sculpt-dev 2021-04-27 22:42:21 +02:00
83a855a8a1 fix compile error 2021-04-27 13:38:14 -07:00
9e46eebcf1 Fix last commit flipping the order of booleans. 2021-04-27 13:20:36 -07:00
786781304c * Got box trim tool working for dyntopo
- This required implementing SCULPT_UNDO_GEOMETRY for dyntopo.
    That turned out to be more work then I expected.  Basically
    it writes an entire Mesh to BMLogEntry, which can be swapped
    with current bmesh.  Tricky part was patching bm log ids.
2021-04-27 13:04:36 -07:00
2e888bfe6c Fix possible crash with dyntopo and clay strips normal filter 2021-04-27 21:31:25 +02:00
901d6e68d7 Merge branch 'master' into sculpt-dev 2021-04-27 21:31:00 +02:00
3028d53865 Edit face set brush now works for pbvh bmesh 2021-04-27 09:51:49 -07:00
fb5f6e762e Merge branch 'master' into sculpt-dev 2021-04-27 18:31:19 +02:00
02b4df9827 Enable color filter brush for pbvh bmesh 2021-04-27 09:12:35 -07:00
815d77192f One more null ptr check 2021-04-27 09:07:00 -07:00
9fab16f0f3 * Fix null ptr bug in automasking code 2021-04-27 09:01:32 -07:00
82f5e0200c * Fix bug in last commit where boundary flags weren't properly
updated after symmetrize.
2021-04-26 17:44:38 -07:00
032a35fb50 Fix memory corruption in sculpt neighbors code 2021-04-25 15:12:11 -07:00
8a700673db * Boundary info is no longer initialized with
SCULPT_boundary_info_ensure, instead PBVH_BMESH keeps
  track of boundary vert flags internally.  This prevents
  nasty first-click lag on the smooth brush as well as anything
  with autosmooth.
2021-04-25 14:51:31 -07:00
0386350de6 * Fixed SCULPT_dynamic_topology_sync_layers to properly sync
active/render/clone/mask layers indices.
* Fixed sculpt color bugs in pbvh drawing for bmesh.
2021-04-25 14:02:39 -07:00
d912d4735a Merge branch 'master' into sculpt-dev 2021-04-22 21:23:44 +02:00
97fc606c65 Fix nasty crash in dyntopo with non-manifold geometry. 2021-04-21 10:00:02 -07:00
14be52f0fc * Fixed vcol drawing in indexed smooth shading mode 2021-04-20 15:40:03 -07:00
739bb8f1d2 Merge branch 'master' into sculpt-dev 2021-04-20 22:43:50 +02:00
7107753f73 Merge branch 'master' into sculpt-dev 2021-04-20 17:56:22 +02:00
73c590e1eb Added detail_size to local dyntopo brush settings 2021-04-20 06:34:35 -07:00
44fd07c1c8 Merge branch 'master' into sculpt-dev 2021-04-19 23:24:55 +02:00
931a8da26c Merge branch 'master' into sculpt-dev 2021-04-19 20:14:24 +02:00
895fef5ccb Sculpt: Add area normal test to clay strips for better front faces detection 2021-04-18 20:10:12 +02:00
b82a2fd9ab Fix wrong visibility flush with Face Sets 2021-04-18 19:36:44 +02:00
18a86af416 Fix neighbor connectivy with hidden edges 2021-04-18 19:00:02 +02:00
a0b5fd9cb6 Fix Scene project brush after merge 2021-04-18 18:14:45 +02:00
553e8ffd1a Merge branch 'master' into sculpt-dev 2021-04-18 18:04:00 +02:00
fdc6fb2c53 SCULPT_calc_principle_curvatures now has option to use
slower but more accurate BLI_eigen_solve_selfadjoint_m3 solver.
2021-04-17 20:25:51 -07:00
8bc9286c4c Merge branch 'master' into sculpt-dev 2021-04-16 19:52:23 +02:00
4f8693652b Sculpt Symmetrize: Fix missing updates with modifiers 2021-04-16 01:47:27 +02:00
d29378c2f2 Sculpt Symmetrize: Free the symmetrize map on changes 2021-04-16 01:31:44 +02:00
0e6c07c063 Sculpt Symmetrize: Prevent crash with dyntopo and multires 2021-04-16 01:30:02 +02:00
cb3e0ff344 Sculpt Symmetrize: Add brush falloff 2021-04-16 01:29:12 +02:00
11d1fdeb34 Sculpt Symmetrize: Fix bug in main brush loop 2021-04-16 01:25:22 +02:00
430641d481 Sculpt Symmetrize: Initial working version 2021-04-16 01:24:49 +02:00
4745f29971 Sculpt Symmetrize: Add base symmetrize map code 2021-04-16 00:56:39 +02:00
8512b1b5dd Sculpt Symmetrize: sculpt_symmetrize file and main loop 2021-04-16 00:47:08 +02:00
674bc2e4b4 Sculpt Symmetrize: Initial commit 2021-04-16 00:38:47 +02:00
b240973412 Object: Make flash animation slower 2021-04-15 20:28:04 +02:00
39994c3208 Object: Use theme select color for animation 2021-04-15 20:26:45 +02:00
8189f2c806 Merge branch 'master' into sculpt-dev 2021-04-15 20:14:30 +02:00
237ac342c9 Merge branch 'master' into temp_bmesh_multires 2021-04-14 22:07:27 -07:00
465e804193 commit prior to merge 2021-04-14 22:04:36 -07:00
4ab8614cd1 Last attempt at fixing boundary brush for now. Unassigned boundary
verts now get bend data from their neighbors.  Still isn't quite
satisfactory but better then before.
2021-04-14 22:02:32 -07:00
dabff9af7d * Fix crash in boundary sculpt tool
* For some reason boundary tool sometimes fails to match verts to
  boundary verts.  It now simply freezes them in place if that happens
2021-04-14 18:41:23 -07:00
384a0930d1 Commit current code state 2021-04-14 15:55:09 -07:00
a5fa9ec310 Fix another crash 2021-04-13 01:44:29 -07:00
ed15d0c1b9 Fix infinite loop bug 2021-04-13 01:08:05 -07:00
e07a95b86d Fix extremely nastly memory corruption bug in pbvh 2021-04-12 04:19:49 -07:00
b52e04f794 * Fix bug in last commit, broke draw brush 2021-04-11 23:39:25 -07:00
e74c298cf9 Fix dyntopo undo bug 2021-04-11 22:03:16 -07:00
cd485a7c6f fix last commit 2021-04-11 21:44:00 -07:00
06341c19c4 Fix crash 2021-04-11 21:42:47 -07:00
a527bd5f48 Get rid of various __attribute__((optnone)) I had scattered throughout
the code
2021-04-11 19:29:06 -07:00
7f14d519c0 * Dyntopo cleanup mode is now on by default.
* Fixed undo bug
2021-04-11 18:19:13 -07:00
64337d087d * Merge branch 'master' into temp_bmesh_multires
* Implemented DynTopo option to dissolve 3 and 4-valence
  vertices.
* Fixed bug in dyntopo collapse customdata snapping.
2021-04-11 17:59:16 -07:00
e1fae3cbee Fix do_versions check 2021-04-11 12:34:15 -07:00
7dbb4c9b2d Fix issues with last commit. Also, simplify brush now
uses dyntopo local overrides to always enable collapse instead
of being hardcoded.
2021-04-11 12:27:02 -07:00
fe67ca56d6 * Fixed wireframe drawing in vcol cell drawing mode
* Added UI for editing local brush dyntopo settings.
2021-04-11 11:38:27 -07:00
68e4e1bb41 Merge branch 'master' into sculpt-dev 2021-04-11 17:43:40 +02:00
881df30a46 Cavity masking now has a checkbox in the UI, instead of simply turning
itself on if the concave mask factor is > 0.
2021-04-07 22:49:39 -07:00
6f91eaad39 * Fixed an annoying number of undo bugs
* Original data for bmesh pbvh is no longer handled by the undo code.
  This should eliminate a whole class of subtle and hard to track down
  bugs.
2021-04-07 20:39:16 -07:00
55045ed85a SCULPT_dyntopo_ensure_templayer no longer returns a customdata offset.
Making multiply layers sequentially can lead to corrupted offsets.
Instead, ensure all layers exist with SCULPT_dyntopo_ensure_templayer
first,

then get all the offsets at once.
2021-04-07 02:03:32 -07:00
2582090824 Fix bug in previous commit, code was being subject to inside
brush test that should not ahve been.
2021-04-07 01:46:10 -07:00
55415cd62a * Layer brush now supports dyntopo.
- To do this I made a little API to make scratch
    customdata layers: SCULPT_dyntopo_[ensure/get]_templayer.
    Takes a customdata type and a layer name (e.g.
    '__dyntopo_bleh") and returns a customdata offset.
  - Note that I also did this for the persistent base code.

* Added a macro to check if a tool supports splitting the PBVH
  during a stroke, DYNTOPO_HAS_DYNAMIC_SPLIT.  It is in sculpt_intern.h
  (for now) to avoid the enormous amount of recompiling that is
  triggered if DNA_brush_enum.h is modified.

* TODO: Right now the undo code resets original vertex coordinates for
  bmesh PBVH.  This means tools that rely on original data (sharp and
  layer) can't split the pbvh during the stroke, since that will
  allocate new undo nodes and reset original coords.

  The solution is to move the original data API entirely out of the undo
  code.
2021-04-07 01:20:21 -07:00
d29bdda34c Fix build error with include 2021-04-06 19:56:17 +02:00
e3ee04dec5 Object: Flash objects on mode transfer 2021-04-06 19:49:18 +02:00
347c8255ed Merge branch 'master' into sculpt-dev 2021-04-06 17:49:13 +02:00
8aac19cab5 Merge branch 'master' into temp_bmesh_multires 2021-04-05 21:26:04 -07:00
b4536d274c Forgot to increase array size for data transfer modifier struct. 2021-04-05 21:24:38 -07:00
d3ffaa8e52 Merge branch 'master' into sculpt-dev 2021-04-05 18:22:38 +02:00
f5588dfb70 Merge branch 'master' into temp_bmesh_multires 2021-04-03 19:29:12 -07:00
4b308888d8 Add support for sculpt colors to the data transfer modifier 2021-04-03 19:23:15 -07:00
fdfa2045ec Add a paranoia check 2021-04-02 13:55:48 -07:00
33af94dc46 Fixed an out of bounds read error. 2021-04-02 13:42:29 -07:00
8ea624aeaf fix gcc build errors 2021-04-01 15:58:56 -07:00
e29cd298fe Fix last commit to handle symmetrical brushing properly 2021-04-01 15:09:50 -07:00
7bba304c57 * Dyntopo now has its own brush spacing. This is a huge performance
boost for brushes with fine spacing, e.g. the clay brush.
2021-04-01 14:51:10 -07:00
0dc09668ce Finished curvature rake. 2021-04-01 13:07:10 -07:00
cfa6753518 wrote a fast and inaccurate distance to triangle function
for DynTopo.  Profiling consistently showed it to be a bottleneck.
I've now written scalar versions of this function four times.

For now I'm committing this inaccuration version.  I'm also committing
code for a vectorized version I found in a paper.  Still need to rejigger
the dyntopo code to use it though.
2021-03-30 19:00:08 -07:00
2cf8c35578 Merge branch 'master' into temp_bmesh_multires 2021-03-30 00:57:43 -07:00
aa116ba5ba Added per-brush DynTopo settings which are stored in a new DynTopoSettings struct.
This system is designed to inherit settings from scene dyntopo defaults
in a highly flexible way; settings can be individually overridden via the
.inherit bitmask.

At stroke time the scene settings and brush->dyntopo are merged
and stored in brush->cached_dyntopo.

Note that brush->flag has a bit flag, DYNTOPO_DISABLED, with a few
subtlies.  It does not switch the PBVH back to PBVH_FACES mode, it
simply disbles dyntopo topology update.  It also doesn't inherit from
any default settings.  And it's the only setting
that's currently exposed in the UI.
2021-03-30 00:08:09 -07:00
d2c1357fc5 Sculpt: Initial implementation of uniform smoothing 2021-03-27 21:52:24 +01:00
0bf2a1f8fe Merge branch 'master' into sculpt-dev 2021-03-27 21:27:41 +01:00
7be027075f Add this file 2021-03-26 14:23:31 -07:00
215c346017 Only send all vcol layers to gpu (for pbvh drawing) in a material
draw mode.
2021-03-25 17:38:27 -07:00
7c9235d0e0 * Sculpt color layers are now properly handle by pbvh bmesh draw code.
Before only the active layer was uploaded to the GPU, now all of them
  (except the autogenerated original color layer) are.
2021-03-25 17:17:42 -07:00
e254cc23b2 Code cleanup 2021-03-25 11:32:20 -07:00
f5a122309d Sculpt Poly Loop: Fix symmetry 2021-03-25 02:46:00 +01:00
dee286fc7e clean up code a bit 2021-03-24 17:01:53 -07:00
ab9b89ac5d Fixed two remaining performance bugs with dyntopo:
* Normals are now updated in threads.
* The sculpt neighbor code was using the slower BM_LOOPS_OF_VERT
  instead of BM_EDGES_OF_VERT, fixed.
2021-03-24 14:09:02 -07:00
ce9e0b53b1 Sculpt Expand: Default Face Set boundary modes to topology 2021-03-24 21:20:09 +01:00
ce6d9112aa Sculpt Poly Loop: Symmetry support 2021-03-24 20:55:31 +01:00
20f4fe138e Merge branch 'master' into sculpt-dev 2021-03-24 20:55:05 +01:00
ecbf642ddd Cleanup: Clang format 2021-03-24 18:48:39 +01:00
caf5f5767f Cloth Filter: Add pinch origin modes 2021-03-24 18:47:01 +01:00
e0cc387124 Cloth Filter: Add symmetry support to pinch deformation mode 2021-03-24 18:12:55 +01:00
ebeb144701 Merge branch 'master' into sculpt-dev 2021-03-23 17:54:08 +01:00
924b13b03a * Added a new CustomData type for dyntopo vertex data: MDynTopoVert.
It stores:
   - Original coordiates, colors and mask (which were previously four
     seperate layers).
   - A bitmask with (currently) one bitflag, whether or not a vertex is
     on a boundary.

I needed to cache calculating vertex boundary state (which involves
iterating over the edges surrounding a vertex) and got fed up with
having so many CD layers for dyntopo.  This struct consolidates them
and saves having yet another layer just to store a flag.
2021-03-21 16:26:38 -07:00
75a1116b51 Merge from master 2021-03-19 18:01:12 -07:00
73a4b885ec Merge branch 'master' into sculpt-dev 2021-03-19 20:08:30 +01:00
f6cda6bf88 Merge branch 'master' into temp_bmesh_multires 2021-03-19 10:57:32 -07:00
9ce0a2815d Merge branch 'master' into sculpt-dev 2021-03-19 18:44:23 +01:00
7d7dcce859 Merge branch 'master' into sculpt-dev 2021-03-18 16:42:53 +01:00
f429a7dc13 Sculpt Expand: Split snap event into two separate events 2021-03-17 16:58:56 +01:00
257562ad6d Sculpt Expand: Add Poly Loop Falloff mode 2021-03-17 16:49:08 +01:00
8883c76b9a Merge branch 'master' into sculpt-dev 2021-03-17 16:20:44 +01:00
dd77b22626 Face Sets Topology: Improve keymap and creation delay 2021-03-17 03:03:02 +01:00
3d70805a68 Sculpt Poly Loop: Improve loop direction detection 2021-03-17 01:39:08 +01:00
b6f0176c10 Face Sets Topology: Add repeat last and default keymap 2021-03-17 01:20:50 +01:00
6835ea72f2 Sculpt Poly Loop: Move poly loop code to its own file 2021-03-17 00:07:41 +01:00
6408c4ebf6 Sculpt Poly Loop: refactor poly loop code for reusability 2021-03-16 23:46:46 +01:00
e557e4d03c Face Sets Topology: Initial working version 2021-03-16 23:17:08 +01:00
02d482e8f2 Face Sets Topology: Initial loop iteration implementation (one side only) 2021-03-16 22:48:31 +01:00
525badbd7d Face Sets Topology: Initial edge loop detection 2021-03-16 22:28:39 +01:00
49fa3dd5ff Face Sets Topology: Initial commit 2021-03-16 22:03:22 +01:00
8b0bc7e3e8 Cleanup: Clang format 2021-03-16 21:25:56 +01:00
ef4abf1212 Sculpt IPMask: Working exec callback for scripts 2021-03-16 21:24:08 +01:00
6ce37c59ec Sculpt IPMask: Refactor filter initialization 2021-03-16 21:05:10 +01:00
6824d73b75 Sculpt IPMask: Add direction property to the filter 2021-03-16 20:45:58 +01:00
06762eefcf Sculpt IPMask: Start implementing exec callback 2021-03-16 20:42:12 +01:00
f791fc031e Sculpt IPMask: Fix memory leak in step compute 2021-03-16 20:26:55 +01:00
57b7eba4b6 Merge branch 'master' into sculpt-dev 2021-03-16 20:00:37 +01:00
abda36c076 Sculpt: Apply latest clang-format changes to the branch 2021-03-14 21:15:47 +01:00
476b333a3e Merge branch 'master' into sculpt-dev 2021-03-14 21:14:58 +01:00
4ad1a7ab31 Cleanup: Clang format 2021-03-14 21:14:39 +01:00
5f5aa43ab1 Sculpt: Fair all by tangency mode for face set edit 2021-03-14 21:14:19 +01:00
4293db60b3 Merge branch 'master' into sculpt-dev 2021-03-12 21:57:37 +01:00
647c065b9c Merge branch 'master' into sculpt-dev 2021-03-12 16:51:18 +01:00
497e532e23 Merge branch 'master' into sculpt-dev 2021-03-12 01:46:40 +01:00
e1f338b9f4 Merge branch 'master' into sculpt-dev 2021-03-11 17:53:47 +01:00
15ef2d42f3 Merge branch 'master' into sculpt-dev 2021-03-10 18:55:12 +01:00
a9083cc0ee Sculpt: Move Mask Init to its own file 2021-03-09 22:11:23 +01:00
c8a03bc716 Sculpt IPMask: Increase sensitivity of contrast mask filter 2021-03-09 21:53:19 +01:00
3efb094fd3 Merge branch 'master' into sculpt-dev 2021-03-09 21:50:31 +01:00
251440f538 Merge branch 'master' into sculpt-dev 2021-03-09 18:44:15 +01:00
cb0f159155 Merge branch 'master' into temp_bmesh_multires
Merge not finished, but need to commit to move to different computer;
laptop being sent in for repairs
2021-03-08 13:57:21 -08:00
409a525fa9 Merge branch 'master' into sculpt-dev 2021-03-08 21:18:53 +01:00
966af5a075 Cleanup: Clang format 2021-03-08 17:37:57 +01:00
5234e23c2c Voxel Remesher: Option to preserver material slots 2021-03-08 17:37:47 +01:00
11613f8c7a Merge branch 'master' into sculpt-dev 2021-03-07 18:06:27 +01:00
8a98189bfb commit before merge 2021-03-07 04:00:14 -08:00
3678b87272 Merge branch 'master' into sculpt-dev 2021-03-06 18:51:48 +01:00
1f2b48eb45 Add a little todo list 2021-03-05 16:54:19 -08:00
dd1c4c84c9 Merge branch 'master' into sculpt-dev 2021-03-04 20:06:27 +01:00
de2625518b Merge branch 'master' into sculpt-dev 2021-03-04 17:32:05 +01:00
75709e4d57 Fix crash in Boundary brush expand mode after refactor 2021-03-03 22:13:19 +01:00
6a74211f99 Merge branch 'master' into sculpt-dev 2021-03-03 20:25:18 +01:00
d3742022c2 Sculpt: Make global smooth factor control the strengh directly 2021-03-03 18:52:16 +01:00
75794afdcd Cleaup: Clang format 2021-03-03 18:51:35 +01:00
b1b49f6130 Sculpt IPMask: Tweak default filter sensitivity 2021-03-03 17:29:46 +01:00
ca60d520d9 Sculp IPMask: Property to enable/disable step interpolation 2021-03-03 17:29:24 +01:00
2fd22fd663 Cleanup: Clang format 2021-03-03 17:12:38 +01:00
04c85de559 Sculpt IPMask: Implement restoring and cancelling the filter 2021-03-03 17:10:09 +01:00
407dd37573 Merge branch 'master' into sculpt-dev 2021-03-03 17:08:59 +01:00
0acaa40c08 Fix after merge 2021-03-03 16:43:41 +01:00
f2024f7d99 Merge branch 'master' into sculpt-dev 2021-03-02 17:05:00 +01:00
a7b5bbf13f Merge branch 'master' into sculpt-dev 2021-03-01 22:28:41 +01:00
e696280b88 Sculpt IPMask: Fix crash in original data updates 2021-03-01 22:14:22 +01:00
5e9eb1930f Sculpt IPMask: Implement filters that use original data 2021-03-01 22:03:22 +01:00
9a7cbff535 Sculpt IPMask: Some experiments for a better sharpen filter 2021-03-01 20:21:23 +01:00
8dec2ca7ba Sculpt IPMask: Tweak default sensitivity of each step 2021-03-01 19:24:58 +01:00
098d0d782a Sculp IPMask: First working version of substep interpolation 2021-03-01 19:19:41 +01:00
779a268c6e Sculpt IPMask: Initial refactor to support step interpolation 2021-03-01 18:52:27 +01:00
13b7b69e7f Merge branch 'master' into sculpt-dev 2021-03-01 18:01:17 +01:00
148b39caec Added some code to calculate principle curvature direction for
uniform triangle tesselations (dyntopo).  This will be used for
a version of topological rake that aligns edge flows to lines of curvature
automatically.
2021-03-01 01:09:27 -08:00
e9f9217f75 Merge from master 2021-02-28 17:05:35 -08:00
dd45a4bc6e Merge branch 'master' into temp_bmesh_multires 2021-02-28 04:59:03 -08:00
1ccd92d0bb commit prior to merge 2021-02-28 04:23:45 -08:00
9f78a24eca Merge branch 'master' into sculpt-dev 2021-02-27 18:32:35 +01:00
930a9edc1e Sculpt IPMask: First version of contrast filter 2021-02-26 22:03:48 +01:00
5cfe7bf72c Merge branch 'master' into sculpt-dev 2021-02-26 20:34:38 +01:00
422b1c64cd Merge branch 'master' into sculpt-dev 2021-02-26 19:05:58 +01:00
1edad56ffc Sculpt IPMask: update pie menu 2021-02-26 17:17:00 +01:00
ef3d68f17b Sculpt IPMask: Use the new mask filter in the pie menu 2021-02-26 14:46:02 +01:00
094ffcf669 Sculpt IPMask: Implement some other filterts (hard/soft) 2021-02-26 02:47:49 +01:00
56d33186a4 Sculpt IPMask: Move main data update to its own function 2021-02-26 01:41:23 +01:00
d570feeffc Cleanup: Clang format 2021-02-26 01:36:13 +01:00
158397a007 Sculpt IPMask: Ignore inbetween mouse events 2021-02-26 01:35:30 +01:00
4e8c430c6e Sculpt IPMask: Free ghash when finishing 2021-02-26 01:31:49 +01:00
d8a4ebb068 Sculpt IPMask: Multithreaded and fast mesh updates 2021-02-26 01:23:45 +01:00
6d46a3ca4e Sculpt IPMask: Enable iteration count 2021-02-26 01:12:14 +01:00
1751b3c7c1 Sculpt IPMask: Refactor, prepare for iteration counts 2021-02-26 01:08:21 +01:00
8ae0573c0f Sculpt IPMask: Unify function to apply delta steps 2021-02-26 00:50:25 +01:00
be0194ef3e Sculpt IPMask: Remove debug prints 2021-02-26 00:47:45 +01:00
0a2ca5860f Sculpt IPMask: Implement automasking for the filter 2021-02-26 00:46:52 +01:00
151cf0b9d9 Sculpt IPMask: Implement filter selection 2021-02-26 00:43:46 +01:00
12cb22d5f6 Sculpt IPMask: Multithreaded compute step 2021-02-26 00:25:06 +01:00
5c2bb6f93a Sculpt IPMask: Implement undo 2021-02-26 00:14:11 +01:00
2e99348da7 Sculpt IPMask: Generalize compute function 2021-02-26 00:08:25 +01:00
817ccc3a99 Sculpt IPMask: Implement smooth and sharpen callbacks 2021-02-26 00:03:44 +01:00
a429f73d2b Sculpt IPMask: Fix bugs in stack index, start refactor 2021-02-25 23:52:41 +01:00
5898cc25c9 Sculpt IPMask: First working version 2021-02-25 23:09:56 +01:00
c05c2c3fb7 Merge branch 'master' into sculpt-dev 2021-02-25 22:24:03 +01:00
f55c39a974 Sculpt IPMask: Functions to step back/forward in the stack 2021-02-25 18:24:09 +01:00
ebf94179b5 Sculpt IPMask: Dummy function to compute a step 2021-02-24 20:48:12 +01:00
9e5a219f3f Sculpt IPMask: delta steps struct and packing 2021-02-24 20:10:34 +01:00
76de0eeb95 Sculpt: Add mask filter tool and target step count 2021-02-24 20:00:02 +01:00
773c5c7464 Sculpt: Initial commit for Mask Filter tool with interactive preview
Hopefully this will become a mask filter that can grow/shrink and smooth/
sharpen any mask shape interactively by dragging the pen, like the rest
of the filters.
2021-02-24 16:50:24 +01:00
7abdfb5c2a Merge branch 'master' into sculpt-dev 2021-02-24 16:23:38 +01:00
ad743c056f Fix crash in versioning code 2021-02-23 23:27:51 +01:00
05bb102a30 Sculpt: Add global smooth strength factor for alt-smooth 2021-02-23 22:52:40 +01:00
b37fd7a14b Sculpt: Add extra options to Face Set pie menu 2021-02-23 22:36:43 +01:00
4154943eef Merge branch 'master' into sculpt-dev 2021-02-23 18:58:53 +01:00
5d7f7b7065 Sculpt: Initial support for bend deformations in Pose 2021-02-23 17:33:21 +01:00
09e394583e Sculpt Expand: Silence warning 2021-02-21 19:33:53 +01:00
7baa3c7df3 Sculpt Expand: Fix artifacts in sculpt geodesic distances 2021-02-21 19:33:32 +01:00
06a8b84792 Merge branch 'master' into sculpt-dev 2021-02-21 17:57:56 +01:00
343950f0c0 Merge branch 'master' into sculpt-dev 2021-02-21 17:28:13 +01:00
da0ef1daac Merge branch 'master' into sculpt-dev 2021-02-19 22:24:49 +01:00
2eb35c7cc0 Merge branch 'master' into sculpt-dev 2021-02-17 19:21:38 +01:00
13952ecec1 Merge branch 'master' into sculpt-dev 2021-02-17 18:02:01 +01:00
214e802f5f Sculpt Expand: More comment on ExpandCache 2021-02-17 17:50:18 +01:00
697e6e53b8 Sculpt Expand: Improve and fix Face Set snapping whit Face Sets 2021-02-17 17:44:00 +01:00
64c0f1fc3f Sculpt Expand: ExpandCache comments 2021-02-17 17:40:14 +01:00
ca5ccb52e5 Sculpt Expand: Expose normals expand in the keymap 2021-02-17 17:39:50 +01:00
51e90a0ada Sculpt Expand: Fix normals falloff 2021-02-17 16:50:41 +01:00
822bbb19f1 Merge branch 'master' into sculpt-dev 2021-02-17 16:35:48 +01:00
a35da15228 Merge branch 'master' into sculpt-dev 2021-02-17 16:35:31 +01:00
53874b413e Sculpt Expand: More comments 2021-02-17 00:17:49 +01:00
1b029b790b Sculpt Expand: Refactor, more comments 2021-02-16 21:03:34 +01:00
acd99f12e7 Sculpt Expand: Cleanup, comments 2021-02-16 20:38:06 +01:00
1a11ac5e34 Sculpt Expand: rename texture options to distortion 2021-02-15 19:41:23 +01:00
416afcb1c3 Sculpt: Move geodesic distances code to its own file 2021-02-15 19:11:49 +01:00
3539cbc497 Sculpt Expand: Fix face set snapping with Multires 2021-02-15 19:07:59 +01:00
4288b2a1d1 Sculpt Expand: Fix crash when editing an existing face set with Multires 2021-02-15 18:56:58 +01:00
d4548fe55b install_deps: Bump OpenEXR to 2.5.5 version. 2021-02-15 18:29:47 +01:00
7b360abb18 Cleanup: Remove code duplication (merge error) 2021-02-15 18:29:47 +01:00
b30294ba41 Cleanup: clang tidy 2021-02-15 18:29:47 +01:00
50f1bd6f09 Cleanup: Spelling in function name 2021-02-15 18:29:47 +01:00
Peter Fog
83d530688b FFmpeg: Improve multi-threading settings for VSE proxies
Following code from D8627 this patch corrects multi threaded processing
of proxies, where a 60 sec proxy generation drops to 35 sec.

Differential Revision: https://developer.blender.org/D8659
2021-02-15 18:29:47 +01:00
b790b57fe1 FFmpeg: Improve multi-threading settings
Allow use all system threads for frame encoding/decoding. This is very
straightforward: the value of zero basically disables threading.

Change threading policy to slice when decoding frames. The reason for
this is because decoding happens frame-by-frame, so inter-frame threading
policy will not bring any speedup.

The change for threading policy to slice is less obvious and is based on
benchmark of the demo files from T78986. This gives best performance so
far.

Rendering the following file went down from 190sec down to 160sec.

  https://storage.googleapis.com/institute-storage/vse_simplified_example.zip

This change makes both reading and writing faster. The animation render
is just easiest to get actual time metrics.

Differential Revision: https://developer.blender.org/D8627
2021-02-15 18:29:47 +01:00
14fe422b48 CMake/Deps: upgrade USD 20.05 → 21.02
USD version 21.02 includes two of the changes Blender used to patch in,
which have now been removed from `usd.diff`. Unfortunately 21.02
introduces another issue where LZ4 symbols are accidentally exported,
causing linker errors. Fortunately these symbols are only used for
resting, so I added a patch hunk that simply removes their `extern "C"`
declaration.

The LZ4 linker issue has been reported upstream at
https://github.com/PixarAnimationStudios/USD/issues/1447.

Reviewed By: sebbas, mont29

Differential Revision: https://developer.blender.org/D10367
2021-02-15 18:29:47 +01:00
0af8ddab2d CMake/Deps: OpenImageDenoise 1.2.3 → 1.3.0 2021-02-15 18:29:47 +01:00
Ray molenkamp
79ecc59f0b CMake/Deps: XR_OpenXR v1.0.14
Straight up version bump

Things of note:

They started using API calls only available in windows 8, however given
the Python 3.9 update will forcibly bump us to 8.1+ anyhow this is not
an issue.

Will require some minor tweaks to platform_win32.cmake after adding the
libs to svn which are not included in this diff so this diff can land
without having to have the libs in place yet.

Reviewed By: sebbas, sybren

Differential Revision: https://developer.blender.org/D10349
2021-02-15 18:29:47 +01:00
Ray molenkamp
0ac4824d07 CMake/Deps: OpenVDB 8.0.1
Straight forward version bump, some of the variables to detect a static
OpenEXR changed and the folder structure seemingly changed a little
requiring updates to the diff

Reviewed By: sebbas, sybren

Differential Revision: https://developer.blender.org/D10340
2021-02-15 18:29:47 +01:00
5f8d444a76 CMake/Deps: Alembic 1.7.16
Version bump + no longer using Boost.

Building Alembic with Boost gave compiler errors, and having one less
inter-dependency is good as well.

Reviewed By: sebbas, sybren

Differential Revision: https://developer.blender.org/D10329
2021-02-15 18:29:47 +01:00
Ray molenkamp
42c5fdeff4 CMake/Deps: TBB 2020U2
Straight forward version bump.

2020U2 is significantly louder in the deprecated header usage warning
department, we should probably see if we need to act on this: P1949

Differential Revision: https://developer.blender.org/D10359
2021-02-15 18:29:47 +01:00
Ray molenkamp
54801f695c CMake/Deps: Boost 1.73
Just a simple version bump.

Maniphest Tasks: T85365

Differential Revision: https://developer.blender.org/D10314
2021-02-15 18:29:47 +01:00
39ac38c25f Attributes: return refined Attribute from attributes.new method
Previously `mesh.attributes.new(...)` would return a generic attribute that
one could not do much with. Now it returns refined attributes like `FloatAttribute`.
2021-02-15 18:29:47 +01:00
834d3e15ce Fix T71960: Malformed .bmp files lead to crash
Add a boundary check, avoiding access past actual data.

Ideally would need to report error to the user somehow,
but it doesn't seem to be easy to do.

This is a minimal safe patch. The proper complete fix is
being worked on by Jesse.

Differential Revision: https://developer.blender.org/D10357
2021-02-15 18:29:47 +01:00
b3c00f97be Cleanup: Use enum class for CryptomatteLayerState. 2021-02-15 18:29:47 +01:00
6324e9bae8 Cleanup: Grammar in comments 2021-02-15 18:29:47 +01:00
bbdfd0cabe Fix: incorrect versioning for Attribute Randomize node 2021-02-15 18:29:47 +01:00
6ef557fdf1 Cleanup: unused variable 2021-02-15 18:29:47 +01:00
30897a56e7 Fix T85633: Misspelling of "neighborhood" in description 2021-02-15 18:29:47 +01:00
eb18eb709d Merge branch 'master' into sculpt-dev 2021-02-14 21:20:30 +01:00
fc7c57f4a1 Sculpt Expand: Improve support for Multires and dyntopo 2021-02-14 20:02:24 +01:00
e3fdfcc981 Sculpt Expand: Fix propagation from grids to faces in Multires 2021-02-14 19:53:30 +01:00
e9b6848fe7 Sculpt Expand: Limited support for Multires 2021-02-14 19:50:59 +01:00
38e61c04ea Sculpt Expand: Fix texture strength when switching falloffs 2021-02-14 19:12:48 +01:00
5e56eb8ca2 Sculpt Expand: Make texture strength consistent across falloff modes 2021-02-14 19:09:07 +01:00
ccfc8aacf8 Sculpt: Add option to show the sculpt pivot as part of the cursor 2021-02-14 18:17:29 +01:00
edece9e741 Sculpt Expand: Update Keymap descriptions 2021-02-14 18:07:27 +01:00
6ee1db0d67 Sculpt Expand: Fix wrong expandcache ref when finishing expand 2021-02-14 18:06:43 +01:00
30434e3904 Sculpt Expand: Render the origin of expand as part of the cursor 2021-02-14 17:45:30 +01:00
e45986291d Merge branch 'master' into sculpt-dev 2021-02-14 17:42:08 +01:00
eb6e96006e Cleanup: clang format 2021-02-12 18:47:23 +01:00
9047bf89fa Sculpt Expand: Fix max falloff with texture distorsion 2021-02-12 18:42:14 +01:00
63ef98d056 Sculpt Expand: Support for texture distorsion for mask and colors 2021-02-12 18:34:18 +01:00
bf53622eef Merge branch 'master' into sculpt-dev 2021-02-12 17:57:50 +01:00
f419d4625a Sculpt Expand: Fix and improve behaviour of pivot reposition 2021-02-11 20:32:25 +01:00
ae19d5303a Sculpt Expand: Fix Face Set ID constantly updated when moving 2021-02-11 20:05:29 +01:00
35f883b886 Cleanup: clang format 2021-02-11 20:02:15 +01:00
7d52658d84 Sculpt Expand: Use symmetry and component filtering for pivot reposition 2021-02-11 20:01:58 +01:00
974b50d16b Scupt Expand: Remove unused Face Sets update code 2021-02-11 18:55:49 +01:00
55382bcdd9 Merge branch 'master' into sculpt-dev 2021-02-11 18:55:15 +01:00
51c931ebb5 Fix depth PBVH raycast with grids 2021-02-11 18:48:14 +01:00
0b9aaaf97f Sculpt Expand: Force all enabled when cursor not over the mesh 2021-02-11 18:47:48 +01:00
faccaee6c3 Fix cloth filter not working after merge 2021-02-11 17:54:54 +01:00
a56fb568ed Cleanup: Clang format 2021-02-10 21:09:41 +01:00
c365e0c6b6 Merge branch 'master' into sculpt-dev 2021-02-10 21:08:52 +01:00
0d6deb7e65 Merge branch 'master' into sculpt-dev 2021-02-10 18:04:45 +01:00
50eed6e54f Merge branch 'master' into sculpt-dev 2021-02-10 01:45:53 +01:00
147cddb398 Merge branch 'master' into sculpt-dev 2021-02-10 00:35:07 +01:00
88c4684466 Sculpt expand: Fix crash when missing connected components 2021-02-09 20:18:02 +01:00
77a30a2886 Sculpt: fix pose brush flood fill with symmetry 2021-02-09 00:30:14 +01:00
370e2b5d82 Sculpt Expand: Force expand to work only on active connected components 2021-02-08 20:27:09 +01:00
44dc741e89 Fix crash in versioning code 2021-02-08 19:02:23 +01:00
7a8cf94170 Sculpt Expand: Fix keymap entry for snapping 2021-02-08 19:01:55 +01:00
fd28c19d09 Scupt: Fix failed scene projection with ortographic views 2021-02-08 18:59:26 +01:00
2f5eabf859 Sculpt: Fix wrong vertex normals in Scene Project 2021-02-08 18:42:43 +01:00
1a17c578a8 Merge branch 'master' into temp_bmesh_multires 2021-02-07 23:17:09 -08:00
56e1ae1afa * Yet another attempt at writing a faster distance to tri function.
I think I will end up writing a less accurate version and be done
  with it.  This is a consistent hotspot in profiling.
* Fixed a few more undo bugs
2021-02-07 23:01:09 -08:00
eea78bd112 PBVH depth: Improve detection with normal orientation in trim 2021-02-07 19:33:35 +01:00
d927f54da6 Merge branch 'arcpatch-D9622' into sculpt-dev 2021-02-07 19:18:46 +01:00
Pablo Dobarro
ec8d1b4eae Sculpt: Location option for lasso trim and depth info
This adds a location option to the trim lasso tool to position the shape
in the middle of the volume of the object instead of in the surface
under the cursor.

{F9349724}

In order to make this work, the SCULPT_cursor_geometry_info_update can
now also get the depth of the geometry from the raycast. The depth is
calculated as the second further intersecting triangle in the raycast
over the entire mesh. This information will also be used to improve and
create new tools.

Differential Revision: https://developer.blender.org/D9622
2021-02-07 19:12:37 +01:00
4e4c1f40e0 Sculpt Expand: Use visibility state for enabled values 2021-02-07 18:54:13 +01:00
35ac8cf4dc Sculpt Expand: Fix gradient when using invert 2021-02-07 17:59:15 +01:00
2f2f14ffed Sculpt Expand: Enable gradient when enabling brush gradient 2021-02-07 17:53:38 +01:00
03778b787e Merge branch 'master' into sculpt-dev 2021-02-07 17:49:48 +01:00
f7e062ef3e Sculpt: fix pose and expand floodfill initial vertex 2021-02-07 17:45:28 +01:00
23cf808585 Sculpt: Boundary circle deformation mode 2021-02-07 17:42:51 +01:00
8e8845786f Cleanup: clang format 2021-02-05 21:59:21 +01:00
3ed1a99dd2 Fix elastic deform surface falloff crashing or breaking geometry 2021-02-05 20:44:45 +01:00
0a9bc6944c Rename random per component to random per loose part 2021-02-05 20:33:38 +01:00
ec4e2f32c8 Fix const warning 2021-02-05 20:31:56 +01:00
2ea03ff860 Remove unused variable 2021-02-05 20:31:18 +01:00
9a3f32f80f Fix crash in versioning code 2021-02-05 20:30:54 +01:00
bcf2f30878 Merge branch 'master' into sculpt-dev 2021-02-05 20:23:18 +01:00
23312a6994 Merge branch 'master' into sculpt-dev 2021-02-04 19:06:15 +01:00
cf5a96aa8d Merge branch 'master' into sculpt-dev 2021-02-04 16:46:45 +01:00
7ed64d9430 Merge branch 'master' into sculpt-dev 2021-02-03 21:08:28 +01:00
1cc0f8cf75 Sculpt Expand: Enable repeat events for loop count increase/decrease 2021-02-03 19:26:18 +01:00
b4e90b6e61 Sculpt Expand: fix topology recursion and flood fill 2021-02-03 18:49:03 +01:00
112c67f688 Merge branch 'master' into sculpt-dev 2021-02-03 17:03:50 +01:00
19fa6fd9f4 Cleanup: Clang format 2021-02-03 01:26:24 +01:00
88921150ff Sculpt: Init Face Sets by Face Sets boundary 2021-02-03 01:25:47 +01:00
e973c94036 Sculpt Expand: Add Expand to the keymap by default 2021-02-03 01:12:11 +01:00
b40f1f4c79 Sculpt Expand: Fix multiple crashes when using modifiers 2021-02-03 00:36:54 +01:00
c191344efb Sculpt Expand: Fix modal keymap descriptions 2021-02-03 00:10:28 +01:00
debf4fc7c9 Sculpt Expand: Refactor and pivot reposition 2021-02-02 23:48:06 +01:00
a60aca00bb Sculpt Expand: Implement topology diagonals falloff 2021-02-02 23:06:18 +01:00
763f96526e Sculpt Expand: implement restore, undo and cancel 2021-02-02 22:44:44 +01:00
abfd14817f Merge branch 'master' into sculpt-dev 2021-02-02 22:05:49 +01:00
529cffd804 Merge branch 'master' into sculpt-dev 2021-02-02 16:08:54 +01:00
09bb5e3aa0 Merge branch 'master' into sculpt-dev 2021-02-01 19:34:38 +01:00
5fb15545c1 Merge branch 'master' into sculpt-dev 2021-01-30 18:15:24 +01:00
a2df63e996 Merge branch 'master' into sculpt-dev 2021-01-29 22:44:44 +01:00
ccaba71fdf Merge branch 'master' into sculpt-dev 2021-01-28 01:16:42 +01:00
710c72807f Merge branch 'master' into sculpt-dev 2021-01-27 20:58:23 +01:00
e779eab729 Sculpt: Implement elastic surface falloff 2021-01-26 20:51:53 +01:00
a72cf784a7 Merge branch 'master' into sculpt-dev 2021-01-26 20:30:39 +01:00
78dffe2f16 Fix Face Set init not showing in the menus 2021-01-25 21:06:36 +01:00
9d31943d88 Merge branch 'master' into sculpt-dev 2021-01-25 20:05:56 +01:00
0a2b19e96d Merge branch 'master' into sculpt-dev 2021-01-24 20:23:54 +01:00
46582b3743 Merge branch 'master' into sculpt-dev 2021-01-24 03:04:27 +01:00
c10b19e453 Merge branch 'master' into sculpt-dev 2021-01-20 18:56:37 +01:00
5631bd4f94 Cleanup: Clang format 2021-01-20 18:51:49 +01:00
30b6d7826d Sculpt: Reset all brushes operator 2021-01-20 18:48:34 +01:00
d1b2c55322 Sculpt Expand: Brush Gradients 2021-01-20 18:17:19 +01:00
87ae49c78e Sculpt Expand: Expose geodesic and topology recursions 2021-01-19 00:14:10 +01:00
2765fb6c76 Sculpt Expand: Loops and recursion types 2021-01-18 23:28:49 +01:00
65cea9523e Merge branch 'master' into sculpt-dev 2021-01-18 22:26:46 +01:00
3d311fdaf1 Sculpt Expand: Expand from active 2021-01-16 21:21:16 +01:00
7a0d5e0c9e Sculpt Expand: Expand from face set boundary 2021-01-16 21:05:16 +01:00
e2fb2315fd Cleanup: Clang Format 2021-01-16 20:41:33 +01:00
fc1fc95b79 Sculpt Expand: Modify Active Face Set 2021-01-16 20:41:10 +01:00
05703d630e Sculpt Expand: face set selection snapping 2021-01-16 20:11:37 +01:00
65c358851d Sculpt Expand: Recursivity, move and falloff switching 2021-01-16 18:38:05 +01:00
b997fc5ea1 Sculpt Expand: Initial implementation of face falloff factors 2021-01-16 01:54:36 +01:00
869747e527 Sculpt Expand: Initial face sets expand target 2021-01-16 01:19:56 +01:00
df7857a364 Sculpt Expand: vertex colors target 2021-01-16 00:42:26 +01:00
cd0cf0a5b7 Expand: Support for invert, preserve and mask gradients 2021-01-15 23:37:42 +01:00
abf7518cbf Sculpt expand modal keymap 2021-01-15 22:24:12 +01:00
58406eddb5 Merge branch 'master' into sculpt-dev 2021-01-15 19:47:28 +01:00
97ab225428 Merge branch 'master' into sculpt-dev 2021-01-14 17:56:31 +01:00
24bbe05913 Add automatic falloff type switching to expand 2021-01-14 02:03:49 +01:00
81ac9f61b6 Implement boundary expand 2021-01-14 01:40:32 +01:00
a9f6ab7357 Basic mask expand operation working 2021-01-14 01:05:11 +01:00
df9a5825e1 Initial commit for new generic sculpt expand operator 2021-01-13 22:59:59 +01:00
0c8b9cd7d1 Cleanup: Clang format 2021-01-13 20:28:09 +01:00
142aba9485 Sculpt: Grab brush surface falloff 2021-01-13 20:27:51 +01:00
bf632990e0 Merge branch 'master' into sculpt-dev 2021-01-13 18:53:20 +01:00
3b4a9b2319 Merge branch 'master' into sculpt-dev 2021-01-12 19:43:30 +01:00
38dce1d29d Merge branch 'master' into sculpt-dev 2021-01-09 17:56:44 +01:00
deeb0b3aac Add experimental ripple effects option to the cloth solver 2021-01-06 20:26:38 +01:00
237b1f9d75 Merge branch 'master' into sculpt-dev 2021-01-06 17:34:16 +01:00
11cd86a8d2 Fix crash in fairing and memory optimization 2021-01-06 17:34:01 +01:00
27713d65d1 Merge branch 'master' into sculpt-dev 2021-01-05 23:49:10 +01:00
d37d96437e Fix crash with scene project and dyntopo 2021-01-05 23:32:29 +01:00
940fb3c044 Sculpt Scene Project: Add option to use vertex normals and brush normal 2021-01-05 22:47:22 +01:00
f91a2a0831 Sculpt: add option for use the center of mass to the sphere mesh filter 2021-01-05 21:59:15 +01:00
6d6ab057e4 Add missing random mask init menu 2021-01-05 21:27:59 +01:00
ea12ba5441 Merge branch 'master' into sculpt-dev 2021-01-05 21:03:21 +01:00
601d896fc6 Fix crash with custom input curves versioning 2021-01-05 18:12:32 +01:00
c237a48104 Fix warnings and windows build 2021-01-05 17:53:50 +01:00
29078186f8 Merge branch 'master' into sculpt-dev 2021-01-05 17:52:46 +01:00
7754c4f10f Fix windows build 2021-01-04 21:22:45 +01:00
90931d6de9 Sculpt: Update clay strips presets with custom input curves 2021-01-01 21:47:18 +01:00
4785f80d51 Fix multiple crashes with custom input curves 2021-01-01 20:12:46 +01:00
5136cc701f Merge branch 'master' into sculpt-dev 2021-01-01 17:18:40 +01:00
ef9eb626a8 Sculpt: Initial support for custom pressure input curves 2020-12-31 19:48:25 +01:00
0663576d19 Tweak draw sharp preset to include size-pressure 2020-12-31 18:36:39 +01:00
e1b8577e41 Merge branch 'master' into sculpt-dev 2020-12-31 18:30:27 +01:00
e09d9c86b6 Merge branch 'master' into sculpt-dev 2020-12-30 18:17:24 +01:00
52e99c5639 Merge branch 'master' into sculpt-dev 2020-12-29 16:13:12 +01:00
193806f590 Merge branch 'master' into sculpt-dev 2020-12-28 22:41:46 +01:00
a3e4f9d9a6 Merge branch 'master' into sculpt-dev 2020-12-28 14:21:15 +01:00
482f46a35a Change default cloth grab deform constraints strength 2020-12-27 00:41:45 +01:00
975a17c816 Sculpt: Auto detect the sphere radius in the sphere mesh filter 2020-12-27 00:14:57 +01:00
985c6464e2 Sculpt: Edit face set extrude operation 2020-12-26 20:11:19 +01:00
bca07d9039 Merge branch 'master' into sculpt-dev 2020-12-26 17:52:31 +01:00
35092510ba Merge branch 'master' into temp_bmesh_multires 2020-12-26 04:24:54 -08:00
85842851d5 Fix build 2020-12-25 21:54:14 +01:00
61ec4159c8 Implement radial gradient 2020-12-25 21:51:21 +01:00
c4ebefc1c8 Cleanup: Clang format 2020-12-25 21:36:58 +01:00
eb4f2f1548 Sculpt: Base code for gradient tools 2020-12-25 21:36:31 +01:00
47b4b45011 Optimize fairing weights calculation 2020-12-25 17:25:00 +01:00
7547e28ba4 Merge branch 'master' into sculpt-dev 2020-12-25 17:09:01 +01:00
0b2e4fa52e Cleanup: Clang format 2020-12-24 19:58:09 +01:00
f4900b3d02 Sculpt: Smooth Directional deform mode 2020-12-24 19:57:58 +01:00
1d53fbfd06 Merge branch 'master' into sculpt-dev 2020-12-24 19:30:30 +01:00
c203de25db Merge branch 'master' into sculpt-dev 2020-12-24 16:30:33 +01:00
ac8c589b7c Preparte curvature fairing and Fairing edit mode operator 2020-12-24 16:30:12 +01:00
f32d3f7b06 Merge branch 'master' into sculpt-dev 2020-12-23 19:23:03 +01:00
5385455e6a Fixed undo bugs caused by SculptVertRef refactor. I need to figure out
the right way to make assigning a pointer to a SculptVertRef to an int*
spit out a compiler error.
2020-12-22 22:47:50 -08:00
1bf726f1ad Merge branch 'master' into sculpt-dev 2020-12-22 23:59:48 +01:00
f031000b28 Sculpt: Mask Init operator and random init modes 2020-12-22 23:59:25 +01:00
2c54c641a3 Added a new cavity automasking mode for sculpt colors painting.
In theory it should also work with other sculpt tools (the
automasking code is fairly general) though it doesn't seem
to do much.
2020-12-22 14:11:11 -08:00
554be8d96c Merge branch 'master' into sculpt-dev 2020-12-22 16:30:14 +01:00
f969b3d440 Merge branch 'master' into sculpt-dev 2020-12-21 23:44:17 +01:00
6034a5bd5b Merge branch 'master' into sculpt-dev 2020-12-21 21:17:51 +01:00
eea756e513 Sculpt: Scene Project Brush 2020-12-21 21:16:16 +01:00
ecbf3e2d0f Sculpt: Face Set Edit fill component mode 2020-12-21 20:00:56 +01:00
6fa6a8851f Merge branch 'master' into sculpt-dev 2020-12-21 16:19:03 +01:00
b3fff9b07a Merge remote-tracking branch 'origin/master' into temp_bmesh_multires
Also redid vcol boundary tool icon, and made a little icon for sculpt
color paint.
2020-12-21 01:08:24 -08:00
671ef8f0e9 Merge branch 'master' into sculpt-dev 2020-12-20 16:10:56 +01:00
373b9b4481 Merge branch 'master' into sculpt-dev 2020-12-19 21:00:53 +01:00
0ada9c1638 Sculpt: Improve boundary artifacts in fairing mask with line gestures 2020-12-19 17:46:23 +01:00
31158ef0c9 Merge branch 'master' into sculpt-dev 2020-12-19 17:00:44 +01:00
5fbd436bb1 Merge branch 'master' into sculpt-dev 2020-12-18 20:10:58 +01:00
c0cb475689 Merge branch 'master' into sculpt-dev 2020-12-17 22:28:12 +01:00
b8a0455983 Fix crash in combine proxies 2020-12-17 19:24:45 +01:00
6145a6bc6c Merge branch 'master' into sculpt-dev 2020-12-17 17:48:12 +01:00
5c03d0c30c Fix plane falloff with elastic cloth 2020-12-16 21:09:45 +01:00
6b42781319 Merge branch 'master' into sculpt-dev 2020-12-16 21:02:04 +01:00
6c4a9b83ff Fix elastic drag cloth brush deformation 2020-12-16 20:59:20 +01:00
9453b45e20 Sculpt: Change default damping for cloth deform target 2020-12-16 20:52:52 +01:00
c0f19d6082 Sculpt: Cloth Brush elastic drag deform type 2020-12-16 20:49:02 +01:00
06078a6f92 Merge branch 'master' into sculpt-dev 2020-12-16 20:27:13 +01:00
1199b9e678 Merge branch 'master' into sculpt-dev 2020-12-16 19:10:48 +01:00
92bc9477d1 Merge branch 'master' into sculpt-dev 2020-12-16 16:43:09 +01:00
7bc1657d05 Fix cloth sim artifacts on planes 2020-12-15 22:13:11 +01:00
e582a4dc77 Fix debug build 2020-12-15 22:07:47 +01:00
243e329ec3 Sculpt: Cloth Deform target for transform 2020-12-15 22:07:08 +01:00
5775efba2f Sculpt: Elastic Transform 2020-12-15 21:38:07 +01:00
cab8626cf2 Sculpt: lasso and box project gestures 2020-12-15 21:33:49 +01:00
19cb01aa21 Cleanup: Clang format 2020-12-15 21:15:05 +01:00
6e6828e09d Sculpt: Project gesture fairing deformation mode 2020-12-15 21:14:26 +01:00
72ff64590d Sculpt: Fairing Brush 2020-12-15 20:39:53 +01:00
553724529e Change PBVH leaf limit size 2020-12-15 20:35:29 +01:00
681e2b6134 Fixes from merge 2020-12-08 13:37:00 -08:00
49bd2228cb Merge branch 'master' into temp_bmesh_multires 2020-12-07 13:04:19 -08:00
0a140ec66e Commit before merge 2020-12-07 11:48:32 -08:00
f30225725d Some multires stuff 2020-11-18 18:34:08 -08:00
a1ac104f02 add NULL pointer check 2020-11-11 05:19:35 -08:00
d823f6e2cf Added an "Exponent" slider to Color Boundary brush. 2020-11-09 22:25:03 -08:00
3042f6e608 Tweaked value for smoothing in vcol boundary tool (a slight amount of
smoothing is applied to prevent normal discontiuties from perfectly
colinear triangles).

Also reverted some CLANG compiling stuff.
2020-11-09 18:30:24 -08:00
6115091103 View3D: take clipping into account for Frame All
Clamp the min/max used for Frame All/Selected
by the clipping region if it's set.

Resolve T81050
2020-11-07 02:54:23 -08:00
78ef2d0d84 Cleanup: move plane array intersection into a function
Also add check to ensure a point isn't occluded by it's own plane,
which could happen if a small epsilon values are passed in.
2020-11-07 02:54:23 -08:00
9d92a97562 Cleanup: Rename render texture files to texture_* 2020-11-07 02:54:23 -08:00
192670e8ce Cleanup: Remove unused variable 2020-11-07 02:54:23 -08:00
7ae1cc23fc Cleanup: remove unused includes in readfile.c and writefile.c 2020-11-07 02:54:23 -08:00
ebb6648bda Fix missing include warning
Caused by rB580ff2cb937daf43699908afe1190baea8d117aa
2020-11-07 02:54:23 -08:00
384f2956e5 Cleanup: fix naming and remove unnecessary code 2020-11-07 02:54:23 -08:00
2ba90cf717 Refactor: move Screen .blend data read to blenkernel
Ref T76372.
2020-11-07 02:54:23 -08:00
e5af8597e5 Refactor: move Ipo .blend I/O to IDTypeInfo callbacks 2020-11-07 02:54:23 -08:00
1f6a7785f6 Refactor: move Object .blend I/O to IDTypeInfo callbacks 2020-11-07 02:54:23 -08:00
0ee053fb12 Cleanup: Clang-Tidy modernize-use-nullptr
Replace `NULL` with `nullptr` in C++ code.

No functional changes.
2020-11-07 02:54:20 -08:00
8cd4776764 Clang-Tidy: error out when executable not found
Stop with an error when the Clang-Tidy executable cannot be found.

Without this check, CMake will happily report "Found Clang-Tidy" but with
the fallback version (0, 0, 0), when `CLANG_TIDY_EXECUTABLE` points to a
non-existing executable.
2020-11-07 02:53:25 -08:00
f32bde6bd9 Refactor: move Pose .blend I/O to blenkernel
Ref T76372.
2020-11-07 02:53:25 -08:00
Yevgeny Makarov
8b808cefae UI: Improved macOS Application Icon Progress Bar
Nicer appearance for the progress bar that is drawn over the application icon during long processes on macOS.

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

Reviewed by Brecht Van Lommel
2020-11-07 02:53:24 -08:00
f8466b6284 Refactor: move Constraint .blend I/O to blenkernel
Ref T76372.
2020-11-07 02:53:24 -08:00
4a2d7a2f89 Refactor: move MotionPath .blend I/O to blenkernel
Ref T76372.
2020-11-07 02:53:24 -08:00
67defe866b Fix T81997: Subsurf Optimal Display sticks after object conversion
When using Optimal Display, some edges are not flagged `ME_EDGEDRAW` |
`ME_EDGERENDER`.
When the modifier is applied through the UI in the modifier stack this is
not an issue because the `modifyMesh` callback is run with
`MOD_APPLY_TO_BASE_MESH` (this will effectively turn of Optimal
Display).
When converting to mesh though, this will just get an evaluated mesh
(where the edge flags are still the same as with the subdivision
modifier).
Now ensure every edge is flagged to draw after conversion.

Maniphest Tasks: T81997

Differential Revision: https://developer.blender.org/D9331
2020-11-07 02:53:24 -08:00
b6575fed92 Refactor: move gpencil modifier .blend I/O to blenkernel
Ref T76372.
2020-11-07 02:53:24 -08:00
d6735bfae0 Refactor: move modifier .blend I/O to blenkernel
Ref T76372.
2020-11-07 02:53:24 -08:00
e4c45d0c5e Fix T82251: Outliner Material Drag&Drop missing tree update
Caused by rBb077de086e14.

Not entirely sure why this was rebuilding the tree prior to above
commit, but sending an ND_OB_SHADING notifier is appropriate (and also
what the Outliners listener listens to).

Maniphest Tasks: T82251

Differential Revision: https://developer.blender.org/D9396
2020-11-07 02:53:24 -08:00
c4668b750c Fix T82220 Missing viewport update after manual "HDRI Preview Size" input
This is caused by the TAA being reset after the init phase, leading to
1 sample being kept as valid when it is clearly not.

To fix this, we run the lookdev validation before TAA init.

Reviewed By: Jeroen Bakker

Differential Revision: https://developer.blender.org/D9452
2020-11-07 02:53:24 -08:00
81a85233a7 Cleanup: Clang-Tidy, modernize-make-unique 2020-11-07 02:53:24 -08:00
89f62e5dc3 Cleanup: Sort includes after recent render module cleanup 2020-11-07 02:53:23 -08:00
408e13783d Cleanup: remove unused functions 2020-11-07 02:53:23 -08:00
3900734063 Refactor: move ShaderFx .blend I/O to blenkernel
Ref T76372.
2020-11-07 02:53:23 -08:00
fa688ac593 Cleanup: Render Module: combine intern/ source & include 2020-11-07 02:53:23 -08:00
787f952ef4 Cleanup: whitespace 2020-11-07 02:53:23 -08:00
63241d25b9 Cleanup: Render Module: move header files to main directory
Move headers files from `render/extern/` to `render/`

Part of T73586
2020-11-07 02:53:23 -08:00
Paul Melis
98166b5c98 Add background rectangle option to video sequencer Text strip
This adds a Box option to the Text strip's style properties, plus related Box Margin value:

{F9208309}

When enabled the text is placed on top of a solid-filled rectangle of a chosen color, as shown below:

{F9208324}

When the box option is disabled the text strip works the same as it does now. When the box option is enabled the meaning of the Shadow option changes to provide a drop-shadow on the rectangle (and not on the text itself). The latter made more sense to me.

The box margin is specified as a fraction of the image width. The offset of the drop-down box shadow is fixed to a specific fraction of the image width as well.

I tested this feature on a movie of a couple of minutes containing dozens of text strips (all with box background), edge cases like multi-line strings and text overlapping the image edges.

Reviewed By: ISS

Differential Revision: https://developer.blender.org/D9468
2020-11-07 02:53:23 -08:00
229849af0f Refactor: move ParticleSystem .blend I/O to blenkernel
Ref T76372.
2020-11-07 02:53:23 -08:00
0a1fc855bc Sequencer: Make naming consistent in header and implementation files 2020-11-07 02:53:23 -08:00
46ccaff9a3 VSE: Don't store proxy images in cache
Proxies are expected to be fast to read. Storing them in cache has
little to no effect on performance.

This change also allows to omit invalidation of cache when user switch
between proxies and original media.

Reviewed By: sergey

Differential Revision: https://developer.blender.org/D9473
2020-11-07 02:53:23 -08:00
9c8b0a20c1 Refactor: move Scene .blend expand to IDTypeInfo callback 2020-11-07 02:53:22 -08:00
a42cf75ecb Refactor: move Scene .blend lib reading to IDTypeInfo callback 2020-11-07 02:53:22 -08:00
d77e884bd7 Cleanup: rename time related variables
Variables renaned:
 - cfra -> timeline_frame
 - nr -> frame index
 - cfra_over -> overlap_frame

Function seq_give_stripelem_index was renamed to seq_give_frame_index.
2020-11-07 02:53:22 -08:00
e2111233f0 Blenloader: access report list via api 2020-11-07 02:53:22 -08:00
e4efd04063 Blenloader: expose BLO_reportf_wrap in api
This function is used by a couple of functions that are moved out of blenloader.
2020-11-07 02:53:22 -08:00
8edd20274e Refactor: move Scene .blend data reading to IDTypeInfo callback 2020-11-07 02:53:22 -08:00
9be60839cd Refactor: move Scene .blend writing to IDTypeInfo callback 2020-11-07 02:53:22 -08:00
af934d751d CMake: Fix wrong library used for dependency
Was causing compilation failure on fresh builds.
2020-11-07 02:53:22 -08:00
5ac07c31f0 Refactor: move PointCache .blend I/O to blenkernel
Ref T76372.
2020-11-07 02:53:22 -08:00
f3a7d9375d Cleanup: Fluid engine API return types
Use bool return type where possible instead of int (the return values from fluid object are already boolean instead of int).

Also removed several if guards in API functions. If one of the arguments is in fact invalid / nullptr (should not happen though), it better to catch them directly where they failed and not silently escape them.
2020-11-07 02:53:22 -08:00
a033a0eaaf Cleanup: Clang-Tidy, modernize-use-bool-literals 2020-11-07 02:53:22 -08:00
c137b53569 Refactor: move sequencer modifier .blend I/O to sequencer module
Ref T76372.
2020-11-07 02:53:21 -08:00
f0a9986ccf Cleanup: Alembic, simplify expression
Change `1 + current_mat++` to `++current_mat`.

No functional changes.
2020-11-07 02:53:21 -08:00
f639ffe795 Cleanup: Alembic, simplify material assignment code
Refactor material assignment code such that:
- `build_mat_map()` just returns the built map (instead of relying on
  modifying a map passed as parameter),
- `LISTBASE_FOREACH` is used to loop over a `ListBase` (instead of a
  hand-crafted for-loop),
- just `return` when not enough material slots can be created (instead
  of setting a boolean to false, then doing some useless work, then
  checking the boolean),
- reorder some code for clarity, and
- rename `mat_map` to `matname_to_material` so that the semantics are
  clearer.

No functional changes.
2020-11-07 02:53:21 -08:00
326381bfe1 Refactor: move Paint lib linking to blenkernel
Ref T76372.
2020-11-07 02:53:21 -08:00
174e3c6b65 Refactor: move color settings .blend I/O to blenkernel
Ref T76372.
2020-11-07 02:53:21 -08:00
5c899dcc92 Cleanup: Clang-Tidy, modernize-use-emplace 2020-11-07 02:53:21 -08:00
24ee80f077 Fix compilation error of bf_draw
Similar to previous commit, missing build dependency.
2020-11-07 02:53:21 -08:00
22b69af796 Fix compilation error when building from scratch
Make sure the DNA offset files is ready at a time bf_windowmanager
need it.
2020-11-07 02:53:21 -08:00
0758c006ec Cleanup: Clang-Tidy, modernize-redundant-void-arg 2020-11-07 02:53:21 -08:00
c2a329ec07 Refactor: move LightCache .blend I/O to eevee_lightcache.c
Ref T76372.
2020-11-07 02:53:21 -08:00
bdaee543f3 Refactor: move remaining ViewLayer .blend I/O to blenkernel
Ref T76372.
2020-11-07 02:53:21 -08:00
44d358c384 Cleanup: remove unnecessary function 2020-11-07 02:53:21 -08:00
f87123a6eb Refactor: move Paint .blend I/O to blenkernel
Ref T76372.
2020-11-07 02:53:21 -08:00
f2fc2cd521 Refactor: move wmWindowManager .blend I/O to IDTypeInfo callbacks 2020-11-07 02:53:20 -08:00
af92a39e37 Fix T82364: Widget anim state not updated when deleting channel in Graph Editor
So a keyframed e.g. location slider would stay yellow/green even if its
corresponding channel was removed.

Needs a appropriate notifier so the listeners (e.g.
buttons_area_listener, view3d_buttons_region_listener) would cause a
redraw.

Maniphest Tasks: T82364

Differential Revision: https://developer.blender.org/D9438
2020-11-07 02:53:20 -08:00
49cbb23855 Fix T82457: Python error when clicking on a tool in the viewport
Ths variable was initialized for false, while it was expected to be
true.
2020-11-07 02:53:20 -08:00
9cb84de509 Clang Tidy: Expand modernize category
Gives an idea of which warnings are affecting Blender code base.
2020-11-07 02:53:20 -08:00
53f6991de8 Cleanup: Use nullptr everywhere in fluid code
Switched from NULL to nullptr.
2020-11-07 02:53:20 -08:00
5b696c2bd8 Fix T82407: Negative number input gives syntax error for velocities and
accelerations

Caused by rB45dbc38a8b15.

Above commit would place parentheses surrounding a block until the next
operator was found.
For velocities and accelerations though, the '/' in 'm/s' or 'ft/s'
should not be considered an operator.

Maniphest Tasks: T82407

Differential Revision: https://developer.blender.org/D9467
2020-11-07 02:53:20 -08:00
b95a5c2e68 Fix T82387: Crash loading file saved with recent master in old versions
This fix makes sure new files save `wmWindow.global_areas` under a different
name, so old Blender versions don't recognize and 0-initialize it.

Since enabling global area writing (ef4aa42ea4), loading a file in old
Blender versions would cause `wmWindow.global_areas` to be read, because there
was already reading code for it and `ScrAreaMap` was in SDNA.
However the `ScrArea.global` of the global areas would be NULL, because it was
*not* in SDNA (`ScrGlobalAreaData` was excluded).
Now, issue is that the code assumes that areas in the global area-map have a
valid ScrArea.global pointer.

Think this was a mistake in rB5f6c45498c92. We should have cleared all this data
on reading, until the global area writing was enabled.

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

Reviewed by: Brecht Van Lommel
2020-11-07 02:53:20 -08:00
080e78d205 Cleanup: Clang-Tidy, readability-redundant-member-init 2020-11-07 02:53:20 -08:00
a55a69f81a Fix Outliner editbone selection with 'Sync Selection'
When editbones were selected from the Outliner (and they were connected
to a parent) with the 'Sync Selection' option turned ON, they could not
get duplicated.

For duplication to work, the (connected) parent bone's tip also has to
be selected [which was not the case when selection is done from the
Outliner under above circumstances]. The reason being that
armature_duplicate_selected_exec ->
ED_armature_edit_sync_selection clears the BONE_ROOTSEL flag if the
parent bone's BONE_TIPSEL is not set.

Caused by rB71eb65328078 btw.

The correct "parent-tip-selection" would actually happen in activation
- `tree_element_active_ebone`
-- `tree_element_active_ebone__sel`
but for 'Sync Selection' this happens [also] in
- `outliner_sync_selection_from_outliner`
-- `outliner_select_sync_to_edit_bone`
which did not do the "flushing" to the parent bone's tip

Now use existing dedicated function for this.

ref. T82347

Reviewers: Zachman

Differential Revision: https://developer.blender.org/D9470
2020-11-07 02:53:20 -08:00
596fea8afd Cleanup: Clang-Tidy warnings 2020-11-07 02:53:19 -08:00
47e4adde5a Fix compilation error in GHOST
ELEM macro isn't available in GHOST library.
2020-11-07 02:53:19 -08:00
a349943cd7 Cleanup: Fix the order of info_cfg_option. 2020-11-07 02:53:19 -08:00
360faf5c3c Cleanup: add missing doxygen group 2020-11-07 02:53:19 -08:00
9cf97857d1 Cleanup: Fix wrong doxygen groups
Was missed in rB9b6088cb9da4df1a893361997fc1a22986bf6f2e
2020-11-07 02:53:19 -08:00
44bdf515ba CMake: configue_file() to pass strings for build-info
Using configue_file(..) would have avoided the breakage from
1daa3c3f0a, caused by buildinfo not properly escaping quotes.

Rely on CMake to escaping strings instead using configure_file().
2020-11-07 02:53:19 -08:00
45ccdebad3 Fix uninitialized value
Own mistake in rB74188e65028d268af887ab2140e4253087410c1e
2020-11-07 02:53:19 -08:00
d242d33571 Cleanup: use 'BKE_' prefix for initialization functions 2020-11-07 02:53:19 -08:00
731eaa68d3 Cleanup: use doxy sections for node_group.c 2020-11-07 02:53:19 -08:00
344963bf23 Cleanup: use if/else check for property poll 2020-11-07 02:53:19 -08:00
aaca5731fb Cleanup: replace STREQLEN with STRPREFIX for constant strings 2020-11-07 02:53:19 -08:00
aa7147f665 Cleanup: use STR_ELEM macro 2020-11-07 02:53:19 -08:00
0fb50afdc5 Cleanup: Use LISTBASE_FOREACH macro 2020-11-07 02:53:18 -08:00
f3cc74d216 Cleanup: Use descriptive variable names 2020-11-07 02:53:18 -08:00
0946a8da3b Cleanup: de-duplicate code for instancing objects when linking
Ref D8843
2020-11-07 02:53:18 -08:00
a8e5e63f45 Cleanup: doxygen comments 2020-11-07 02:53:18 -08:00
e52f8ac7ce Cleanup: doxygen comments in ghost
Use colon after parameters, use hash to reference symbols.
2020-11-07 02:53:18 -08:00
71a088582a Cleanup: use ELEM macro (>2 args) 2020-11-07 02:53:18 -08:00
3aab8dd731 Cleanup: clang-format
Missed this last commit.
2020-11-07 02:53:18 -08:00
56d57b2e9d Cleanup: use ELEM macro 2020-11-07 02:53:18 -08:00
b16eb9d7ad Cleanup: follow our code style for float literals 2020-11-07 02:53:17 -08:00
3fcd3d41c4 Cleanup: use bool argument in BLI_noise 2020-11-07 02:53:17 -08:00
0b0bfa0628 Cleanup: BLI_noise
Use common prefix as this collided with existing API's (eg BLI_voronoi).

Also expand some non-obvious abbreviations:

- 'g'  -> 'generic'
- 'vl' -> 'variable_lacunarity'
- 'V'  -> 'v3'
2020-11-07 02:53:17 -08:00
ff9ce5fd98 Cleanup: remove unused BLI_turbulence1
A slightly modified version of BLI_turbulence1, unused for years.
2020-11-07 02:53:17 -08:00
2d99e118b4 Cleanup: use snake case for BLI_args API 2020-11-07 02:53:17 -08:00
a93add61b0 Cleanup: remove unused BLI_argsArgv 2020-11-07 02:53:17 -08:00
7f28a99dd5 Cleanup: use string APPEND/PREPEND
Replace 'set' with 'string(APPEND/PREPEND ...)'.
This avoids duplicating the variable name.
2020-11-07 02:53:10 -08:00
9aaf9857a0 Cleanup: transform.h comments, use doxy sections 2020-11-07 02:52:23 -08:00
e2595de761 Cleanup: sort structs, files 2020-11-07 02:52:23 -08:00
40c4942901 Cleanup: clang-format 2020-11-07 02:52:23 -08:00
2e188dc504 Cleanup: unused variable 2020-11-07 02:52:23 -08:00
Yevgeny Makarov
dfce29b809 UI: Tweaks to the Warning Icon
Warning Sign Alert Icon given a more rounded border.

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

Reviewed by Pablo Vazquez
2020-11-07 02:52:23 -08:00
decf7adcf6 Fix T81915: Draw Face Sets not working with deformed sculpt mesh
The draw face sets brush uses the poly center when used in meshes to increase
its precision when working in low poly geometry. For this to work with deformed
meshes, the deformed coordinates from the PBVH should be used instead.

Reviewed By: sergey

Maniphest Tasks: T81915

Differential Revision: https://developer.blender.org/D9424
2020-11-07 02:52:23 -08:00
81531d5e76 Fix memory leaks in sculpt mode trimming tools
BKE_mesh_free() seems to not free the meshes correctly, so using BKE_id_free() instead.
The looptri array was also not freed.

Reviewed By: sergey

Differential Revision: https://developer.blender.org/D9426
2020-11-07 02:52:23 -08:00
15bc0b7d5d Fix T82400: Dyntopo detail size edit operator visual glitch
Just a missing immUnbindProgram

Reviewed By: sergey

Maniphest Tasks: T82400

Differential Revision: https://developer.blender.org/D9459
2020-11-07 02:52:23 -08:00
17dec471c5 Fix Dyntopo detail size preview orientation not matching the cursor
Used the sampled cursor normal when available instead of the raycast face normal.
This makes the preview match the previous orientation of the cursor.

Reviewed By: sergey

Differential Revision: https://developer.blender.org/D9460
2020-11-07 02:52:23 -08:00
81f05aca29 Move "Camera Parent Lock" from preferences to Object Relations
"Camera Parent Lock" can be useful when rigging cameras, but it is not
intuitive, and has also generated a lot of confusion (bug reports).
This is because it breaks the fundamental parent <-> child relationship
conventions in Blender, and there is no indication that it's intended
without diving into the preferences.

This commit moves the setting to the object level, and exposes it in
the relations panel in the property editor. It is exposed for every
object type because any object type can be "View Locked" in the 3D view.
The property description is also updated to reflect this change and be
more specific without getting too long.

In the future this could become a more general feature of the transform
system, but for now it is limited to "Lock Camera to View".

Differential Revision: https://developer.blender.org/D9239
2020-11-07 02:52:22 -08:00
d1270925a5 Fix T82423: Add modifier key back into keymap
Commit rBf5080c82dd915db6c7b9dd68a52aaaccf2600137
accidentally remove the Shift modifier key from
the `AUTOCONSTRAINPLANE` shortcut.

Differential Revision: https://developer.blender.org/D9480
2020-11-07 02:52:22 -08:00
9e09ae7aff Fix T82164: Knife tool draws huge vertices after using bgl.glPointSize
Since it is possible to have multiple draw callbacks, (some of which
use bgl and others gpu), check and force the reset of the drawing status
at the end of each callback.

Differential Revision: https://developer.blender.org/D9476
2020-11-07 02:52:22 -08:00
Robert Guetzkow
c51a5e1066 Fix T82423: Replace duplicate name in keymap
The two entries `TFM_MODAL_AUTOCONSTRAINT` and
`TFM_MODAL_AUTOCONSTRAINTPLANE` had the same name
displayed in the UI. The latter is now includes
"plane" in it's name.

Reviewed By: mano-wii

Differential Revision: https://developer.blender.org/D9474
2020-11-07 02:52:22 -08:00
758452ffba Fix T80043: missing Cycles displacement update when relinking output sockets 2020-11-07 02:52:22 -08:00
c7cd82c356 Cleanup: Reduce variable scope
Differential Revision: https://developer.blender.org/D9475
2020-11-07 02:52:22 -08:00
cc554eea75 Fix T82428: Cycles crashes when building volume meshes
The Volume Node did not have all of the sockets from its Mesh base class
which are now required due to the recent socket API change.
2020-11-07 02:52:21 -08:00
0d770432d6 pre-merge commit 2020-11-07 02:48:34 -08:00
b2cb9d4b1b Fixed handling of edge seam flags in dyntopo, for some reason did the
code was not brought over from trimesh branch.
2020-11-06 16:23:12 -08:00
08e19c6bc0 Added debug option in dyntopo to draw sculpt colors as solid cells
instead of interpolating (it's next to "draw smooth" in the dyntopo
settings panel).
2020-11-06 03:17:45 -08:00
b928f58849 Made vcol boundary tool avoid perfectly degenerate triangles. 2020-11-06 01:35:52 -08:00
228c1e5345 Replace call to BMLog with origco CD layer.
Also fixed SCULPT_HIDE_FACE_SETS.  It was 1<<16, which overlaps
SCULPT_DYNTOPO_DETAIL_MANUAL.  Changed it to 1<<17.  Someone should do
this in master too.
2020-11-05 16:35:42 -08:00
488af21ae0 Merge remote-tracking branch 'origin' into temp_bmesh_multires 2020-11-05 09:05:02 -08:00
b54d7bfad8 Fix redraw error for dyntopo smooth brush 2020-11-05 09:03:56 -08:00
2babf80ae6 Fixed sculpt colors undo for mesh pbvh. 2020-11-04 21:27:21 -08:00
022dcb8e6c Added autosmooth-like option to run vcol boundary tool in paint tool 2020-11-04 20:36:43 -08:00
6d66e81667 Fixed color boundary tool for faces pbvh 2020-11-04 03:05:38 -08:00
91a5e1aef8 Added an icon for new sculpt colors boundary smooth tool 2020-11-04 02:34:18 -08:00
6d704d57ad Merge remote-tracking branch 'origin' into temp_bmesh_multires 2020-11-03 22:41:57 -08:00
a1b1c840a0 Adjust weighting for color boundary tool 2020-11-03 19:41:18 -08:00
901654dcbf * Added a "color boundary" tool that tries to smooth out vcol boundaries 2020-11-03 19:08:37 -08:00
37a657a45f Added face set support to dyntopo. Still need to finish "edit face
sets" tool and do more testing.
2020-11-03 16:05:38 -08:00
e07bb3955e Enabled dyntopo for sharp brush. Also fixed paint brush strength being
too strong with dyntopo enabled.
2020-11-03 00:47:19 -08:00
7834b59598 Merge remote-tracking branch 'origin' into temp_bmesh_multires 2020-11-02 14:33:52 -08:00
0c8d40d2de Fixed bug with multires editmode code messing up loop indices for draw
code.

Also fixed a bug in dyntopo ray tracing, where r_active_vertex_index
wasn't always being set.
2020-11-02 14:29:45 -08:00
1014b6f455 More fixes for sculpt vertex color undo. Moved one of the undo pushes
outside a thread, since dyntopo undo is not thread safe.
2020-10-31 11:06:15 -07:00
093e29f3c2 Tried to fix sculpt vcol paint undo. It's better, but I still need to
go through and thorougly analyze just what the undo stack is doing.
2020-10-30 20:06:05 -07:00
0f0d1f8e2a Paint brush no long SCULPT_undo_push_node per dab (except for first
stroke) for dyntopo.  Instead it updates the original vertex color
customdata layer.

Calling into the undo system destroys threading with dyntopo, as its
undo code is single-threaded.
2020-10-30 19:37:22 -07:00
43ccbe353f Try to make SCULPT_orig_vert_data_init avoid allocating undo nodes,
which calls into BMLog which, while now threadsafe (ish?) causes
threads to get bogged down in lock contention.
2020-10-30 19:17:03 -07:00
2d861122e1 Remove debugging clang keyword. It's not #ifdef'd code, but still. 2020-10-29 22:39:06 -07:00
66f8852e30 * Edge queue creation for dyntopo edge split/collapse is now
multithreaded.
* Worked on ProxyVert system, but it still needs more work.  Issue is keeping
  topological layers (reasonably) up to date without it being slow.
* Fixed memory leak in bmlog.
2020-10-29 22:33:57 -07:00
54ddb01299 Fixed a variety of memory corruption bugs 2020-10-29 04:28:03 -07:00
3d47323162 Fixed bug with original coordinates/normals not being set when
dyntopo pbvh is first built
2020-10-27 01:38:59 -07:00
5c77439264 * Fix bug in BKE_pbvh_node_color_buffer_get. 2020-10-27 00:20:07 -07:00
e2c92c1341 More fixes for dyntopo undo and vertices (face data still isn't
implemented).
2020-10-26 18:46:12 -07:00
faf8402c19 Added initial support for customdata to dyntopo undo (BMLog).
TODO:
 - Handle face (loop) data
 - Figure out what to do about edge data (warn user? actually handle
   it?)
 - Handle sculpt color undo push nodes properly (shouldn't be hard).
2020-10-26 02:45:56 -07:00
4c0bcc3d13 PBVH drawing now properly names attributes.
NOTE: I've added a new function, DRW_make_cdlayer_attr_aliases, for
this.  It's patterned after extract_uvs.  The appropriate devs from the
draw engine team should take a look.
2020-10-26 00:19:14 -07:00
4fc4a7e1f4 Fixed SCULPT_dynamic_topology_sync_layers from last commit. 2020-10-25 22:55:46 -07:00
f9859a3b2a Got sculpt colors to work, needs more testing 2020-10-25 22:35:02 -07:00
6da9fa1bf2 pre-valgrind commit 2020-10-25 20:00:42 -07:00
5c6407c268 Fixed broken customdata interpolation in dyntopo collapse.
Also added support for uvs to dyntopo gpu buffer building code.
2020-10-25 04:31:06 -07:00
3214b1114f Added support for customdata interpolation to dyntopo.
It seems fast enough for simple cases, I make no promises that it
will be fast in crazy cases lots if there's lots of vgroup layers.

Note I still need to interface properly with the sculpt colors code.
2020-10-25 01:37:52 -07:00
bfbe9a0d55 Fix bugs in last commit. 2020-10-25 01:07:05 -07:00
f482afadab Refactored sculpt code to use a new type, SculptVertRef, that replaces
much of the usage of integer indices.  Meshes and grids simply store the
index here, but bmesh stores a pointer to a BMVert.  This greatly speeds
up DynTopo by reducing the need to maintain flat pointer arrays in bmesh.

To prevent the accidental casting of ScuptVertexRef to indices and vice
versa SculptVertRef is defined as a struct:

typedef struct {intptr_t i} SculptVertRef;

There are also two functions to convert flat index indices to
SculptVertRefs and back:

ScultpVertRef BKE_pbvh_table_index_to_vertex(PBVH *pbvh, int index);
int BKE_pbvh_vertex_index_to_table(PBVH *pbvh, SculptVertRef *ref);

Note that these functions require the aforementioned maintanance of
flat pointer arrays in bmesh, so make sure to call
SCULPT_ensure_vertex_random_access().
2020-10-25 00:32:59 -07:00
661dcd813c Merge performance improvements from trimesh branch into this one. 2020-10-24 19:41:54 -07:00
5541de9a3a Submodule update 2020-10-24 16:03:05 -07:00
3791afa29c Merge remote-tracking branch 'origin' into temp_bmesh_multires 2020-10-24 16:01:45 -07:00
3ae8229843 commit before merge 2020-10-24 16:01:08 -07:00
f61d4b2e3a * Improved multires projection some more in bmesh_interp.c 2020-10-18 18:10:16 -07:00
49f57d8de8 COde cleanup 2020-10-18 16:12:02 -07:00
64c7bad391 New branch to fix multires topology editing. WIP
Changes:
* Brought back bmesh_mdisps_space_set, written from scratch using
  subdiv api, not ccg.
* Wrote a function to smooth multigres grids from within bmesh.  I might
  not need it; unless anyone thinks of a use for it I'll go ahead and
  delete it.

Todo:
* Purge code of all usages of CCG for multires.

This commit:
* Wrote a utility function to dump multires displacements into a (new)
  scene object.
* Consequently, I now know that the CCG_based multires code is not
  compatible with the OpenSubdiv based code.  The former produces gaps
  between grids when converting displacements to object space.
2020-10-17 15:11:02 -07:00
4659855b0f commit multires patch 2020-10-17 01:24:34 -07:00
1210 changed files with 99312 additions and 94224 deletions

View File

@@ -263,6 +263,7 @@ ForEachMacros:
- SET_SLOT_PROBING_BEGIN
- MAP_SLOT_PROBING_BEGIN
- VECTOR_SET_SLOT_PROBING_BEGIN
- TGSET_ITER
StatementMacros:
- PyObject_HEAD

View File

@@ -403,7 +403,7 @@ option(WITH_CYCLES_CUDA_BINARIES "Build Cycles CUDA binaries" OFF)
option(WITH_CYCLES_CUBIN_COMPILER "Build cubins with nvrtc based compiler instead of nvcc" OFF)
option(WITH_CYCLES_CUDA_BUILD_SERIAL "Build cubins one after another (useful on machines with limited RAM)" OFF)
mark_as_advanced(WITH_CYCLES_CUDA_BUILD_SERIAL)
set(CYCLES_TEST_DEVICES CPU CACHE STRING "Run regression tests on the specified device types (CPU CUDA OPTIX)" )
set(CYCLES_TEST_DEVICES CPU CACHE STRING "Run regression tests on the specified device types (CPU CUDA OPTIX OPENCL)" )
set(CYCLES_CUDA_BINARIES_ARCH sm_30 sm_35 sm_37 sm_50 sm_52 sm_60 sm_61 sm_70 sm_75 sm_86 compute_75 CACHE STRING "CUDA architectures to build binaries for")
mark_as_advanced(CYCLES_CUDA_BINARIES_ARCH)
unset(PLATFORM_DEFAULT)
@@ -418,8 +418,12 @@ mark_as_advanced(WITH_CYCLES_DEBUG_NAN)
mark_as_advanced(WITH_CYCLES_NATIVE_ONLY)
option(WITH_CYCLES_DEVICE_CUDA "Enable Cycles CUDA compute support" ON)
option(WITH_CYCLES_DEVICE_OPTIX "Enable Cycles OptiX support" ON)
option(WITH_CYCLES_DEVICE_OPTIX "Enable Cycles OptiX support" OFF)
option(WITH_CYCLES_DEVICE_OPENCL "Enable Cycles OpenCL compute support" ON)
option(WITH_CYCLES_NETWORK "Enable Cycles compute over network support (EXPERIMENTAL and unfinished)" OFF)
mark_as_advanced(WITH_CYCLES_DEVICE_CUDA)
mark_as_advanced(WITH_CYCLES_DEVICE_OPENCL)
mark_as_advanced(WITH_CYCLES_NETWORK)
option(WITH_CUDA_DYNLOAD "Dynamically load CUDA libraries at runtime" ON)
mark_as_advanced(WITH_CUDA_DYNLOAD)
@@ -574,6 +578,12 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\LLVM\\LLVM;]/lib/clang/7.0.0/lib/windows
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\LLVM\\LLVM;]/lib/clang/6.0.0/lib/windows
)
find_library(
COMPILER_ASAN_LIBRARY_THUNK NAMES clang_rt.asan_dll_thunk-x86_64
PATHS
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\LLVM\\LLVM;]/lib/clang/7.0.0/lib/windows
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\LLVM\\LLVM;]/lib/clang/6.0.0/lib/windows
)
elseif(APPLE)
execute_process(COMMAND ${CMAKE_CXX_COMPILER}
-print-file-name=lib
@@ -594,6 +604,7 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
)
endif()
mark_as_advanced(COMPILER_ASAN_LIBRARY_THUNK)
mark_as_advanced(COMPILER_ASAN_LIBRARY)
endif()
endif()
@@ -914,9 +925,9 @@ if(NOT CMAKE_BUILD_TYPE MATCHES "Release")
unset(_list_COMPILER_ASAN_CFLAGS)
unset(_is_CONFIG_DEBUG)
elseif(COMPILER_ASAN_LIBRARY)
set(PLATFORM_LINKLIBS "${PLATFORM_LINKLIBS};${COMPILER_ASAN_LIBRARY}")
set(PLATFORM_LINKFLAGS "${COMPILER_ASAN_LIBRARY} ${COMPILER_ASAN_LINKER_FLAGS}")
set(PLATFORM_LINKFLAGS_DEBUG "${COMPILER_ASAN_LIBRARY} ${COMPILER_ASAN_LINKER_FLAGS}")
set(PLATFORM_LINKLIBS "${PLATFORM_LINKLIBS};\"${COMPILER_ASAN_LIBRARY}\" \"${COMPILER_ASAN_LIBRARY_THUNK}\"")
set(PLATFORM_LINKFLAGS "\"${COMPILER_ASAN_LIBRARY}\" \"${COMPILER_ASAN_LIBRARY_THUNK}\" ${COMPILER_ASAN_LINKER_FLAGS}")
set(PLATFORM_LINKFLAGS_DEBUG "\"${COMPILER_ASAN_LIBRARY}\" \"${COMPILER_ASAN_LIBRARY_THUNK}\" ${COMPILER_ASAN_LINKER_FLAGS}")
endif()
endif()
endif()

View File

@@ -70,18 +70,16 @@
}
--- a/libavcodec/rl.c
+++ b/libavcodec/rl.c
@@ -71,17 +71,19 @@
@@ -71,7 +71,7 @@ av_cold void ff_rl_init(RLTable *rl,
av_cold void ff_rl_init_vlc(RLTable *rl, unsigned static_size)
{
int i, q;
- VLC_TYPE table[1500][2] = {{0}};
+ VLC_TYPE (*table)[2] = av_calloc(sizeof(VLC_TYPE), 1500 * 2);
VLC vlc = { .table = table, .table_allocated = static_size };
- av_assert0(static_size <= FF_ARRAY_ELEMS(table));
+ av_assert0(static_size < 1500);
av_assert0(static_size <= FF_ARRAY_ELEMS(table));
init_vlc(&vlc, 9, rl->n + 1, &rl->table_vlc[0][1], 4, 2, &rl->table_vlc[0][0], 4, 2, INIT_VLC_USE_NEW_STATIC);
for (q = 0; q < 32; q++) {
@@ -80,8 +80,10 @@ av_cold void ff_rl_init_vlc(RLTable *rl, unsigned static_size)
int qmul = q * 2;
int qadd = (q - 1) | 1;
@@ -93,7 +91,7 @@
if (q == 0) {
qmul = 1;
@@ -113,4 +115,5 @@
@@ -113,4 +115,5 @@ av_cold void ff_rl_init_vlc(RLTable *rl, unsigned static_size)
rl->rl_vlc[q][i].run = run;
}
}

View File

@@ -33,23 +33,11 @@ FIND_PATH(OPTIX_INCLUDE_DIR
include
)
IF(EXISTS "${OPTIX_INCLUDE_DIR}/optix.h")
FILE(STRINGS "${OPTIX_INCLUDE_DIR}/optix.h" _optix_version REGEX "^#define OPTIX_VERSION[ \t].*$")
STRING(REGEX MATCHALL "[0-9]+" _optix_version ${_optix_version})
MATH(EXPR _optix_version_major "${_optix_version} / 10000")
MATH(EXPR _optix_version_minor "(${_optix_version} % 10000) / 100")
MATH(EXPR _optix_version_patch "${_optix_version} % 100")
SET(OPTIX_VERSION "${_optix_version_major}.${_optix_version_minor}.${_optix_version_patch}")
ENDIF()
# handle the QUIETLY and REQUIRED arguments and set OPTIX_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OptiX
REQUIRED_VARS OPTIX_INCLUDE_DIR
VERSION_VAR OPTIX_VERSION)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OptiX DEFAULT_MSG
OPTIX_INCLUDE_DIR)
IF(OPTIX_FOUND)
SET(OPTIX_INCLUDE_DIRS ${OPTIX_INCLUDE_DIR})
@@ -57,7 +45,6 @@ ENDIF()
MARK_AS_ADVANCED(
OPTIX_INCLUDE_DIR
OPTIX_VERSION
)
UNSET(_optix_SEARCH_DIRS)

View File

@@ -55,7 +55,7 @@ buildbot:
cuda11:
version: '11.4.1'
optix:
version: '7.3.0'
version: '7.1.0'
cmake:
default:
version: any

View File

@@ -200,20 +200,15 @@ def submodules_update(args, release_version, branch):
if msg:
skip_msg += submodule_path + " skipped: " + msg + "\n"
else:
# Find a matching branch that exists.
call([args.git_command, "fetch", "origin"])
if make_utils.git_branch_exists(args.git_command, submodule_branch):
pass
elif make_utils.git_branch_exists(args.git_command, submodule_branch_fallback):
submodule_branch = submodule_branch_fallback
else:
submodule_branch = None
# Switch to branch and pull.
if submodule_branch:
if make_utils.git_branch(args.git_command) != submodule_branch:
call([args.git_command, "checkout", submodule_branch])
call([args.git_command, "pull", "--rebase", "origin", submodule_branch])
if make_utils.git_branch(args.git_command) != submodule_branch:
call([args.git_command, "fetch", "origin"])
call([args.git_command, "checkout", submodule_branch])
call([args.git_command, "pull", "--rebase", "origin", submodule_branch])
# If we cannot find the specified branch for this submodule, fallback to default one (aka master).
if make_utils.git_branch(args.git_command) != submodule_branch:
call([args.git_command, "fetch", "origin"])
call([args.git_command, "checkout", submodule_branch_fallback])
call([args.git_command, "pull", "--rebase", "origin", submodule_branch_fallback])
finally:
os.chdir(cwd)

View File

@@ -8,19 +8,14 @@ import subprocess
import sys
def call(cmd, exit_on_error=True, silent=False):
if not silent:
print(" ".join(cmd))
def call(cmd, exit_on_error=True):
print(" ".join(cmd))
# Flush to ensure correct order output on Windows.
sys.stdout.flush()
sys.stderr.flush()
if silent:
retcode = subprocess.call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
else:
retcode = subprocess.call(cmd)
retcode = subprocess.call(cmd)
if exit_on_error and retcode != 0:
sys.exit(retcode)
return retcode
@@ -43,11 +38,6 @@ def check_output(cmd, exit_on_error=True):
return output.strip()
def git_branch_exists(git_command, branch):
return call([git_command, "rev-parse", "--verify", branch], exit_on_error=False, silent=True) == 0 or \
call([git_command, "rev-parse", "--verify", "remotes/origin/" + branch], exit_on_error=False, silent=True) == 0
def git_branch(git_command):
# Get current branch name.
try:

View File

@@ -14,7 +14,7 @@ sound = aud.Sound('music.ogg')
# play the audio, this return a handle to control play/pause
handle = device.play(sound)
# if the audio is not too big and will be used often you can buffer it
sound_buffered = aud.Sound.cache(sound)
sound_buffered = aud.Sound.buffer(sound)
handle_buffered = device.play(sound_buffered)
# stop the sounds (otherwise they play until their ends)

View File

@@ -389,7 +389,7 @@
// Does the compiler support result_of?
#ifndef EIGEN_HAS_STD_RESULT_OF
#if EIGEN_MAX_CPP_VER>=11 && ((__has_feature(cxx_lambdas) || (defined(__cplusplus) && __cplusplus >= 201103L)))
#if __cplusplus < 201703L && EIGEN_MAX_CPP_VER>=11 && ((__has_feature(cxx_lambdas) || (defined(__cplusplus) && __cplusplus >= 201103L && __cplusplus)))
#define EIGEN_HAS_STD_RESULT_OF 1
#else
#define EIGEN_HAS_STD_RESULT_OF 0

View File

@@ -129,7 +129,6 @@ set(SRC
src/util/Barrier.cpp
src/util/Buffer.cpp
src/util/BufferReader.cpp
src/util/RingBuffer.cpp
src/util/StreamBuffer.cpp
src/util/ThreadPool.cpp
)
@@ -153,7 +152,6 @@ set(PUBLIC_HDR
include/devices/ThreadedDevice.h
include/Exception.h
include/file/File.h
include/file/FileInfo.h
include/file/FileManager.h
include/file/FileWriter.h
include/file/IFileInput.h
@@ -246,7 +244,6 @@ set(PUBLIC_HDR
include/util/BufferReader.h
include/util/ILockable.h
include/util/Math3D.h
include/util/RingBuffer.h
include/util/StreamBuffer.h
include/util/ThreadPool.h
)
@@ -963,10 +960,7 @@ endif()
if(BUILD_DEMOS)
include_directories(${INCLUDE})
set(DEMOS audainfo audaplay audaconvert audaremap signalgen randsounds dynamicmusic playbackmanager)
add_executable(audainfo demos/audainfo.cpp)
target_link_libraries(audainfo audaspace)
set(DEMOS audaplay audaconvert audaremap signalgen randsounds dynamicmusic playbackmanager)
add_executable(audaplay demos/audaplay.cpp)
target_link_libraries(audaplay audaspace)

View File

@@ -221,7 +221,7 @@ AUD_API void AUD_Device_setListenerVelocity(AUD_Device* device, const float valu
AUD_API double AUD_Device_getRate(AUD_Device* device)
{
auto dev = device ? *device : DeviceManager::getDevice();
return dev->getSpecs().rate;
return dev ? dev->getSpecs().rate : 0.0;
}
AUD_API float AUD_Device_getSpeedOfSound(AUD_Device* device)

View File

@@ -39,7 +39,7 @@ extern AUD_API void AUD_PlaybackManager_free(AUD_PlaybackManager* manager);
* Plays a sound through the playback manager, adding it into a category.
* \param manager The PlaybackManager object.
* \param sound The sound to be played.
* \param catKey The key of the category into which the sound will be added. If it doesn't exist a new one will be created.
* \param catKey The key of the category into which the sound will be added. If it doesn't exist a new one will be creatd.
*/
extern AUD_API void AUD_PlaybackManager_play(AUD_PlaybackManager* manager, AUD_Sound* sound, unsigned int catKey);

View File

@@ -94,40 +94,6 @@ AUD_API int AUD_Sound_getLength(AUD_Sound* sound)
return (*sound)->createReader()->getLength();
}
AUD_API int AUD_Sound_getFileStreams(AUD_Sound* sound, AUD_StreamInfo **stream_infos)
{
assert(sound);
std::shared_ptr<File> file = std::dynamic_pointer_cast<File>(*sound);
if(file)
{
try
{
auto streams = file->queryStreams();
size_t size = sizeof(AUD_StreamInfo) * streams.size();
if(!size)
{
*stream_infos = nullptr;
return 0;
}
*stream_infos = reinterpret_cast<AUD_StreamInfo*>(std::malloc(size));
std::memcpy(*stream_infos, streams.data(), size);
return streams.size();
}
catch(Exception&)
{
}
}
*stream_infos = nullptr;
return 0;
}
AUD_API sample_t* AUD_Sound_data(AUD_Sound* sound, int* length, AUD_Specs* specs)
{
assert(sound);
@@ -286,12 +252,6 @@ AUD_API AUD_Sound* AUD_Sound_bufferFile(unsigned char* buffer, int size)
return new AUD_Sound(new File(buffer, size));
}
AUD_API AUD_Sound* AUD_Sound_bufferFileStream(unsigned char* buffer, int size, int stream)
{
assert(buffer);
return new AUD_Sound(new File(buffer, size, stream));
}
AUD_API AUD_Sound* AUD_Sound_cache(AUD_Sound* sound)
{
assert(sound);
@@ -312,12 +272,6 @@ AUD_API AUD_Sound* AUD_Sound_file(const char* filename)
return new AUD_Sound(new File(filename));
}
AUD_API AUD_Sound* AUD_Sound_fileStream(const char* filename, int stream)
{
assert(filename);
return new AUD_Sound(new File(filename, stream));
}
AUD_API AUD_Sound* AUD_Sound_sawtooth(float frequency, AUD_SampleRate rate)
{
return new AUD_Sound(new Sawtooth(frequency, rate));

View File

@@ -36,15 +36,7 @@ extern AUD_API AUD_Specs AUD_Sound_getSpecs(AUD_Sound* sound);
* \return The length of the sound in samples.
* \note This function creates a reader from the sound and deletes it again.
*/
extern AUD_API int AUD_Sound_getLength(AUD_Sound* sound);
/**
* Retrieves the stream infos of a sound file.
* \param sound The sound to retrieve from which must be a file sound.
* \param infos A pointer to a AUD_StreamInfo array that will be allocated and must afterwards be freed by the caller.
* \return The number of items in the infos array.
*/
extern AUD_API int AUD_Sound_getFileStreams(AUD_Sound* sound, AUD_StreamInfo** stream_infos);
extern AUD_API int AUD_getLength(AUD_Sound* sound);
/**
* Reads a sound's samples into memory.
@@ -97,15 +89,6 @@ extern AUD_API AUD_Sound* AUD_Sound_buffer(sample_t* data, int length, AUD_Specs
*/
extern AUD_API AUD_Sound* AUD_Sound_bufferFile(unsigned char* buffer, int size);
/**
* Loads a sound file from a memory buffer.
* \param buffer The buffer which contains the sound file.
* \param size The size of the buffer.
* \param stream The index of the audio stream within the file if it contains multiple audio streams.
* \return A handle of the sound file.
*/
extern AUD_API AUD_Sound* AUD_Sound_bufferFileStream(unsigned char* buffer, int size, int stream);
/**
* Caches a sound into a memory buffer.
* \param sound The sound to cache.
@@ -120,14 +103,6 @@ extern AUD_API AUD_Sound* AUD_Sound_cache(AUD_Sound* sound);
*/
extern AUD_API AUD_Sound* AUD_Sound_file(const char* filename);
/**
* Loads a sound file.
* \param filename The filename of the sound file.
* \param stream The index of the audio stream within the file if it contains multiple audio streams.
* \return A handle of the sound file.
*/
extern AUD_API AUD_Sound* AUD_Sound_fileStream(const char* filename, int stream);
/**
* Creates a sawtooth sound.
* \param frequency The frequency of the generated sawtooth sound.

View File

@@ -86,6 +86,7 @@ AUD_API AUD_SoundInfo AUD_getInfo(AUD_Sound* sound)
info.specs.channels = AUD_CHANNELS_INVALID;
info.specs.rate = AUD_RATE_INVALID;
info.length = 0.0f;
info.start_offset = 0.0f;
try
{
@@ -95,6 +96,7 @@ AUD_API AUD_SoundInfo AUD_getInfo(AUD_Sound* sound)
{
info.specs = convSpecToC(reader->getSpecs());
info.length = reader->getLength() / (float) info.specs.rate;
info.start_offset = reader->getStartOffset();
}
}
catch(Exception&)
@@ -107,7 +109,7 @@ AUD_API AUD_SoundInfo AUD_getInfo(AUD_Sound* sound)
AUD_API float* AUD_readSoundBuffer(const char* filename, float low, float high,
float attack, float release, float threshold,
int accumulate, int additive, int square,
float sthreshold, double samplerate, int* length, int stream)
float sthreshold, double samplerate, int* length)
{
Buffer buffer;
DeviceSpecs specs;
@@ -115,7 +117,7 @@ AUD_API float* AUD_readSoundBuffer(const char* filename, float low, float high,
specs.rate = (SampleRate)samplerate;
std::shared_ptr<ISound> sound;
std::shared_ptr<ISound> file = std::shared_ptr<ISound>(new File(filename, stream));
std::shared_ptr<ISound> file = std::shared_ptr<ISound>(new File(filename));
int position = 0;
@@ -245,7 +247,7 @@ AUD_API int AUD_readSound(AUD_Sound* sound, float* buffer, int length, int sampl
buffer[i * 3] = min;
buffer[i * 3 + 1] = max;
buffer[i * 3 + 2] = std::sqrt(power / len);
buffer[i * 3 + 2] = sqrt(power / len); // RMS
if(overallmax < max)
overallmax = max;

View File

@@ -37,7 +37,7 @@ extern AUD_API float* AUD_readSoundBuffer(const char* filename, float low, float
float attack, float release, float threshold,
int accumulate, int additive, int square,
float sthreshold, double samplerate,
int* length, int stream);
int* length);
/**
* Pauses a playing sound after a specific amount of time.

View File

@@ -176,17 +176,5 @@ typedef struct
{
AUD_Specs specs;
float length;
double start_offset;
} AUD_SoundInfo;
/// Specification of a sound source.
typedef struct
{
/// Start time in seconds.
double start;
/// Duration in seconds. May be estimated or 0 if unknown.
double duration;
/// Audio data parameters.
AUD_DeviceSpecs specs;
} AUD_StreamInfo;

View File

@@ -89,11 +89,10 @@ Sound_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
self = (Sound*)type->tp_alloc(type, 0);
if(self != nullptr)
{
static const char* kwlist[] = {"filename", "stream", nullptr};
static const char* kwlist[] = {"filename", nullptr};
const char* filename = nullptr;
int stream = 0;
if(!PyArg_ParseTupleAndKeywords(args, kwds, "s|i:Sound", const_cast<char**>(kwlist), &filename, &stream))
if(!PyArg_ParseTupleAndKeywords(args, kwds, "s:Sound", const_cast<char**>(kwlist), &filename))
{
Py_DECREF(self);
return nullptr;
@@ -101,7 +100,7 @@ Sound_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
try
{
self->sound = new std::shared_ptr<ISound>(new File(filename, stream));
self->sound = new std::shared_ptr<ISound>(new File(filename));
}
catch(Exception& e)
{
@@ -408,9 +407,8 @@ static PyObject *
Sound_file(PyTypeObject* type, PyObject* args)
{
const char* filename = nullptr;
int stream = 0;
if(!PyArg_ParseTuple(args, "s|i:file", &filename, &stream))
if(!PyArg_ParseTuple(args, "s:file", &filename))
return nullptr;
Sound* self;
@@ -420,7 +418,7 @@ Sound_file(PyTypeObject* type, PyObject* args)
{
try
{
self->sound = new std::shared_ptr<ISound>(new File(filename, stream));
self->sound = new std::shared_ptr<ISound>(new File(filename));
}
catch(Exception& e)
{

View File

@@ -70,6 +70,12 @@ public:
*/
virtual int getPosition() const=0;
/**
* Returns the start offset the sound should have to line up with related sources.
* \return The required start offset in seconds.
*/
virtual double getStartOffset() const { return 0.0;}
/**
* Returns the specification of the reader.
* \return The Specs structure.

View File

@@ -23,11 +23,9 @@
*/
#include "ISound.h"
#include "FileInfo.h"
#include <string>
#include <memory>
#include <vector>
AUD_NAMESPACE_BEGIN
@@ -50,14 +48,6 @@ private:
*/
std::shared_ptr<Buffer> m_buffer;
/**
* The index of the stream within the file if it contains multiple.
* The first audio stream in the file has index 0 and the index increments by one
* for every other audio stream in the file. Other types of streams in the file
* do not count.
*/
int m_stream;
// delete copy constructor and operator=
File(const File&) = delete;
File& operator=(const File&) = delete;
@@ -67,25 +57,16 @@ public:
* Creates a new sound.
* The file is read from the file system using the given path.
* \param filename The sound file path.
* \param stream The index of the audio stream within the file if it contains multiple audio streams.
*/
File(std::string filename, int stream = 0);
File(std::string filename);
/**
* Creates a new sound.
* The file is read from memory using the supplied buffer.
* \param buffer The buffer to read from.
* \param size The size of the buffer.
* \param stream The index of the audio stream within the file if it contains multiple audio streams.
*/
File(const data_t* buffer, int size, int stream = 0);
/**
* Queries the streams of the file.
* \return A vector with as many streams as there are in the file.
* \exception Exception Thrown if the file specified cannot be read.
*/
std::vector<StreamInfo> queryStreams();
File(const data_t* buffer, int size);
virtual std::shared_ptr<IReader> createReader();
};

View File

@@ -1,42 +0,0 @@
/*******************************************************************************
* Copyright 2009-2016 Jörg Müller
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
#pragma once
/**
* @file FileInfo.h
* @ingroup file
* The FileInfo data structures.
*/
#include "respec/Specification.h"
AUD_NAMESPACE_BEGIN
/// Specification of a sound source.
struct StreamInfo
{
/// Start time in seconds.
double start;
/// Duration in seconds. May be estimated or 0 if unknown.
double duration;
/// Audio data parameters.
DeviceSpecs specs;
};
AUD_NAMESPACE_END

View File

@@ -22,14 +22,12 @@
* The FileManager class.
*/
#include "FileInfo.h"
#include "respec/Specification.h"
#include "IWriter.h"
#include <list>
#include <memory>
#include <string>
#include <vector>
AUD_NAMESPACE_BEGIN
@@ -68,36 +66,18 @@ public:
/**
* Creates a file reader for the given filename if a registed IFileInput is able to read it.
* @param filename The path to the file.
* @param stream The index of the audio stream within the file if it contains multiple audio streams.
* @return The reader created.
* @exception Exception If no file input can read the file an exception is thrown.
*/
static std::shared_ptr<IReader> createReader(std::string filename, int stream = 0);
static std::shared_ptr<IReader> createReader(std::string filename);
/**
* Creates a file reader for the given buffer if a registed IFileInput is able to read it.
* @param buffer The buffer to read the file from.
* @param stream The index of the audio stream within the file if it contains multiple audio streams.
* @return The reader created.
* @exception Exception If no file input can read the file an exception is thrown.
*/
static std::shared_ptr<IReader> createReader(std::shared_ptr<Buffer> buffer, int stream = 0);
/**
* Queries the streams of a sound file.
* \param filename Path to the file to be read.
* \return A vector with as many streams as there are in the file.
* \exception Exception Thrown if the file specified cannot be read.
*/
static std::vector<StreamInfo> queryStreams(std::string filename);
/**
* Queries the streams of a sound file.
* \param buffer The in-memory file buffer.
* \return A vector with as many streams as there are in the file.
* \exception Exception Thrown if the file specified cannot be read.
*/
static std::vector<StreamInfo> queryStreams(std::shared_ptr<Buffer> buffer);
static std::shared_ptr<IReader> createReader(std::shared_ptr<Buffer> buffer);
/**
* Creates a file writer that writes a sound to the given file path.

View File

@@ -23,11 +23,9 @@
*/
#include "Audaspace.h"
#include "FileInfo.h"
#include <memory>
#include <string>
#include <vector>
AUD_NAMESPACE_BEGIN
@@ -50,36 +48,18 @@ public:
/**
* Creates a reader for a file to be read.
* \param filename Path to the file to be read.
* \param stream The index of the audio stream within the file if it contains multiple audio streams.
* \return The reader that reads the file.
* \exception Exception Thrown if the file specified cannot be read.
*/
virtual std::shared_ptr<IReader> createReader(std::string filename, int stream = 0)=0;
virtual std::shared_ptr<IReader> createReader(std::string filename)=0;
/**
* Creates a reader for a file to be read from memory.
* \param buffer The in-memory file buffer.
* \param stream The index of the audio stream within the file if it contains multiple audio streams.
* \return The reader that reads the file.
* \exception Exception Thrown if the file specified cannot be read.
*/
virtual std::shared_ptr<IReader> createReader(std::shared_ptr<Buffer> buffer, int stream = 0)=0;
/**
* Queries the streams of a sound file.
* \param filename Path to the file to be read.
* \return A vector with as many streams as there are in the file.
* \exception Exception Thrown if the file specified cannot be read.
*/
virtual std::vector<StreamInfo> queryStreams(std::string filename)=0;
/**
* Queries the streams of a sound file.
* \param buffer The in-memory file buffer.
* \return A vector with as many streams as there are in the file.
* \exception Exception Thrown if the file specified cannot be read.
*/
virtual std::vector<StreamInfo> queryStreams(std::shared_ptr<Buffer> buffer)=0;
virtual std::shared_ptr<IReader> createReader(std::shared_ptr<Buffer> buffer)=0;
};
AUD_NAMESPACE_END

View File

@@ -67,4 +67,4 @@ public:
virtual void read(int& length, bool& eos, sample_t* buffer);
};
AUD_NAMESPACE_END
AUD_NAMESPACE_END

View File

@@ -1,97 +0,0 @@
/*******************************************************************************
* Copyright 2009-2021 Jörg Müller
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
#pragma once
/**
* @file RingBuffer.h
* @ingroup util
* The RingBuffer class.
*/
#include "Audaspace.h"
#include "Buffer.h"
#include <cstddef>
AUD_NAMESPACE_BEGIN
/**
* This class is a simple ring buffer in RAM which is 32 Byte aligned and provides
* functionality for concurrent reading and writting without locks.
*/
class AUD_API RingBuffer
{
private:
/// The buffer storing the actual data.
Buffer m_buffer;
/// The reading pointer.
volatile size_t m_read;
/// The writing pointer.
volatile size_t m_write;
// delete copy constructor and operator=
RingBuffer(const RingBuffer&) = delete;
RingBuffer& operator=(const RingBuffer&) = delete;
public:
/**
* Creates a new ring buffer.
* \param size The size of the buffer in bytes.
*/
RingBuffer(int size = 0);
/**
* Returns the pointer to the ring buffer in memory.
*/
sample_t* getBuffer() const;
/**
* Returns the size of the ring buffer in bytes.
*/
int getSize() const;
size_t getReadSize() const;
size_t getWriteSize() const;
size_t read(data_t* target, size_t size);
size_t write(data_t* source, size_t size);
/**
* Resets the ring buffer to a state where nothing has been written or read.
*/
void reset();
/**
* Resizes the ring buffer.
* \param size The new size of the ring buffer, measured in bytes.
*/
void resize(int size);
/**
* Makes sure the ring buffer has a minimum size.
* If size is >= current size, nothing will happen.
* Otherwise the ring buffer is resized with keep as parameter.
* \param size The new minimum size of the ring buffer, measured in bytes.
*/
void assureSize(int size);
};
AUD_NAMESPACE_END

View File

@@ -87,11 +87,17 @@ public:
* \param args The arguments of the task.
* \return A future of the same type as the return type of the task.
*/
#if __cplusplus > 201703L
template<class T, class... Args>
std::future<typename std::invoke_result<T, Args...>::type> enqueue(T&& t, Args&&... args)
{
using pkgdTask = std::packaged_task<typename std::invoke_result<T, Args...>::type()>;
#else
template<class T, class... Args>
std::future<typename std::result_of<T(Args...)>::type> enqueue(T&& t, Args&&... args)
{
using pkgdTask = std::packaged_task<typename std::result_of<T(Args...)>::type()>;
#endif
std::shared_ptr<pkgdTask> task = std::make_shared<pkgdTask>(std::bind(std::forward<T>(t), std::forward<Args>(args)...));
auto result = task->get_future();

View File

@@ -35,24 +35,14 @@ void FFMPEG::registerPlugin()
FileManager::registerOutput(plugin);
}
std::shared_ptr<IReader> FFMPEG::createReader(std::string filename, int stream)
std::shared_ptr<IReader> FFMPEG::createReader(std::string filename)
{
return std::shared_ptr<IReader>(new FFMPEGReader(filename, stream));
return std::shared_ptr<IReader>(new FFMPEGReader(filename));
}
std::shared_ptr<IReader> FFMPEG::createReader(std::shared_ptr<Buffer> buffer, int stream)
std::shared_ptr<IReader> FFMPEG::createReader(std::shared_ptr<Buffer> buffer)
{
return std::shared_ptr<IReader>(new FFMPEGReader(buffer, stream));
}
std::vector<StreamInfo> FFMPEG::queryStreams(std::string filename)
{
return FFMPEGReader(filename).queryStreams();
}
std::vector<StreamInfo> FFMPEG::queryStreams(std::shared_ptr<Buffer> buffer)
{
return FFMPEGReader(buffer).queryStreams();
return std::shared_ptr<IReader>(new FFMPEGReader(buffer));
}
std::shared_ptr<IWriter> FFMPEG::createWriter(std::string filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate)

View File

@@ -52,10 +52,8 @@ public:
*/
static void registerPlugin();
virtual std::shared_ptr<IReader> createReader(std::string filename, int stream = 0);
virtual std::shared_ptr<IReader> createReader(std::shared_ptr<Buffer> buffer, int stream = 0);
virtual std::vector<StreamInfo> queryStreams(std::string filename);
virtual std::vector<StreamInfo> queryStreams(std::shared_ptr<Buffer> buffer);
virtual std::shared_ptr<IReader> createReader(std::string filename);
virtual std::shared_ptr<IReader> createReader(std::shared_ptr<Buffer> buffer);
virtual std::shared_ptr<IWriter> createWriter(std::string filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate);
};

View File

@@ -31,25 +31,6 @@ AUD_NAMESPACE_BEGIN
#define FFMPEG_OLD_CODE
#endif
SampleFormat FFMPEGReader::convertSampleFormat(AVSampleFormat format)
{
switch(av_get_packed_sample_fmt(format))
{
case AV_SAMPLE_FMT_U8:
return FORMAT_U8;
case AV_SAMPLE_FMT_S16:
return FORMAT_S16;
case AV_SAMPLE_FMT_S32:
return FORMAT_S32;
case AV_SAMPLE_FMT_FLT:
return FORMAT_FLOAT32;
case AV_SAMPLE_FMT_DBL:
return FORMAT_FLOAT64;
default:
AUD_THROW(FileException, "FFMPEG sample format unknown.");
}
}
int FFMPEGReader::decode(AVPacket& packet, Buffer& buffer)
{
int buf_size = buffer.getSize();
@@ -87,7 +68,7 @@ int FFMPEGReader::decode(AVPacket& packet, Buffer& buffer)
for(int i = 0; i < m_frame->nb_samples; i++)
{
std::memcpy(((data_t*)buffer.getBuffer()) + buf_pos + ((m_codecCtx->channels * i) + channel) * single_size,
m_frame->data[channel] + i * single_size, single_size);
m_frame->data[channel] + i * single_size, single_size);
}
}
}
@@ -128,7 +109,7 @@ int FFMPEGReader::decode(AVPacket& packet, Buffer& buffer)
for(int i = 0; i < m_frame->nb_samples; i++)
{
std::memcpy(((data_t*)buffer.getBuffer()) + buf_pos + ((m_codecCtx->channels * i) + channel) * single_size,
m_frame->data[channel] + i * single_size, single_size);
m_frame->data[channel] + i * single_size, single_size);
}
}
}
@@ -142,10 +123,13 @@ int FFMPEGReader::decode(AVPacket& packet, Buffer& buffer)
return buf_pos;
}
void FFMPEGReader::init(int stream)
void FFMPEGReader::init()
{
m_position = 0;
m_start_offset = 0.0f;
m_pkgbuf_left = 0;
m_st_time = 0;
m_duration = 0;
if(avformat_find_stream_info(m_formatCtx, nullptr) < 0)
AUD_THROW(FileException, "File couldn't be read, ffmpeg couldn't find the stream info.");
@@ -153,22 +137,43 @@ void FFMPEGReader::init(int stream)
// find audio stream and codec
m_stream = -1;
double dur_sec = 0;
for(unsigned int i = 0; i < m_formatCtx->nb_streams; i++)
{
#ifdef FFMPEG_OLD_CODE
if((m_formatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
if(m_formatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
#else
if((m_formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
if(m_formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
#endif
&& (m_stream < 0))
{
if(stream == 0)
AVStream *audio_stream = m_formatCtx->streams[i];
double audio_timebase = av_q2d(audio_stream->time_base);
if (audio_stream->start_time != AV_NOPTS_VALUE)
{
m_stream=i;
break;
m_st_time = audio_stream->start_time;
}
int64_t ctx_start_time = 0;
if (m_formatCtx->start_time != AV_NOPTS_VALUE) {
ctx_start_time = m_formatCtx->start_time;
}
m_start_offset = m_st_time * audio_timebase - (double)ctx_start_time / AV_TIME_BASE;
if(audio_stream->duration != AV_NOPTS_VALUE)
{
dur_sec = audio_stream->duration * audio_timebase;
}
else
stream--;
{
/* If the audio starts after the stream start time, subract this from the total duration. */
dur_sec = (double)m_formatCtx->duration / AV_TIME_BASE - m_start_offset;
}
m_stream=i;
break;
}
}
@@ -237,9 +242,10 @@ void FFMPEGReader::init(int stream)
}
m_specs.rate = (SampleRate) m_codecCtx->sample_rate;
m_duration = lround(dur_sec * m_codecCtx->sample_rate);
}
FFMPEGReader::FFMPEGReader(std::string filename, int stream) :
FFMPEGReader::FFMPEGReader(std::string filename) :
m_pkgbuf(),
m_formatCtx(nullptr),
m_codecCtx(nullptr),
@@ -253,7 +259,7 @@ FFMPEGReader::FFMPEGReader(std::string filename, int stream) :
try
{
init(stream);
init();
}
catch(Exception&)
{
@@ -262,7 +268,7 @@ FFMPEGReader::FFMPEGReader(std::string filename, int stream) :
}
}
FFMPEGReader::FFMPEGReader(std::shared_ptr<Buffer> buffer, int stream) :
FFMPEGReader::FFMPEGReader(std::shared_ptr<Buffer> buffer) :
m_pkgbuf(),
m_codecCtx(nullptr),
m_frame(nullptr),
@@ -289,7 +295,7 @@ FFMPEGReader::FFMPEGReader(std::shared_ptr<Buffer> buffer, int stream) :
try
{
init(stream);
init();
}
catch(Exception&)
{
@@ -312,51 +318,6 @@ FFMPEGReader::~FFMPEGReader()
avformat_close_input(&m_formatCtx);
}
std::vector<StreamInfo> FFMPEGReader::queryStreams()
{
std::vector<StreamInfo> result;
for(unsigned int i = 0; i < m_formatCtx->nb_streams; i++)
{
#ifdef FFMPEG_OLD_CODE
if(m_formatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
#else
if(m_formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
#endif
{
StreamInfo info;
double time_base = av_q2d(m_formatCtx->streams[i]->time_base);
if(m_formatCtx->streams[i]->start_time != AV_NOPTS_VALUE)
info.start = m_formatCtx->streams[i]->start_time * time_base;
else
info.start = 0;
if(m_formatCtx->streams[i]->duration != AV_NOPTS_VALUE)
info.duration = m_formatCtx->streams[i]->duration * time_base;
else if(m_formatCtx->duration != AV_NOPTS_VALUE)
info.duration = double(m_formatCtx->duration) / AV_TIME_BASE - info.start;
else
info.duration = 0;
#ifdef FFMPEG_OLD_CODE
info.specs.channels = Channels(m_formatCtx->streams[i]->codec->channels);
info.specs.rate = m_formatCtx->streams[i]->codec->sample_rate;
info.specs.format = convertSampleFormat(m_formatCtx->streams[i]->codec->sample_fmt);
#else
info.specs.channels = Channels(m_formatCtx->streams[i]->codecpar->channels);
info.specs.rate = m_formatCtx->streams[i]->codecpar->sample_rate;
info.specs.format = convertSampleFormat(AVSampleFormat(m_formatCtx->streams[i]->codecpar->format));
#endif
result.emplace_back(info);
}
}
return result;
}
int FFMPEGReader::read_packet(void* opaque, uint8_t* buf, int buf_size)
{
FFMPEGReader* reader = reinterpret_cast<FFMPEGReader*>(opaque);
@@ -407,16 +368,18 @@ void FFMPEGReader::seek(int position)
{
if(position >= 0)
{
double pts_time_base = av_q2d(m_formatCtx->streams[m_stream]->time_base);
double pts_time_base =
av_q2d(m_formatCtx->streams[m_stream]->time_base);
uint64_t st_time = m_formatCtx->streams[m_stream]->start_time;
uint64_t seek_pos = (uint64_t)(position / (pts_time_base * m_specs.rate));
uint64_t seek_pts = (((uint64_t)position) / ((uint64_t)m_specs.rate)) / pts_time_base;
if(st_time != AV_NOPTS_VALUE)
seek_pos += st_time;
if(m_st_time != AV_NOPTS_VALUE) {
seek_pts += m_st_time;
}
// a value < 0 tells us that seeking failed
if(av_seek_frame(m_formatCtx, m_stream, seek_pos, AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_ANY) >= 0)
if(av_seek_frame(m_formatCtx, m_stream, seek_pts,
AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_ANY) >= 0)
{
avcodec_flush_buffers(m_codecCtx);
m_position = position;
@@ -437,7 +400,7 @@ void FFMPEGReader::seek(int position)
if(packet.pts != AV_NOPTS_VALUE)
{
// calculate real position, and read to frame!
m_position = (packet.pts - (st_time != AV_NOPTS_VALUE ? st_time : 0)) * pts_time_base * m_specs.rate;
m_position = (packet.pts - m_st_time) * pts_time_base * m_specs.rate;
if(m_position < position)
{
@@ -467,25 +430,8 @@ void FFMPEGReader::seek(int position)
int FFMPEGReader::getLength() const
{
auto stream = m_formatCtx->streams[m_stream];
double time_base = av_q2d(stream->time_base);
double duration;
if(stream->duration != AV_NOPTS_VALUE)
duration = stream->duration * time_base;
else if(m_formatCtx->duration != AV_NOPTS_VALUE)
{
duration = float(m_formatCtx->duration) / AV_TIME_BASE;
if(stream->start_time != AV_NOPTS_VALUE)
duration -= stream->start_time * time_base;
}
else
duration = -1;
// return approximated remaning size
return (int)(duration * m_codecCtx->sample_rate) - m_position;
return m_duration - m_position;
}
int FFMPEGReader::getPosition() const
@@ -493,6 +439,11 @@ int FFMPEGReader::getPosition() const
return m_position;
}
double FFMPEGReader::getStartOffset() const
{
return m_start_offset;
}
Specs FFMPEGReader::getSpecs() const
{
return m_specs.specs;
@@ -529,11 +480,13 @@ void FFMPEGReader::read(int& length, bool& eos, sample_t* buffer)
// decode the package
pkgbuf_pos = decode(packet, m_pkgbuf);
// copy to output buffer
data_size = std::min(pkgbuf_pos, left * sample_size);
m_convert((data_t*) buf, (data_t*) m_pkgbuf.getBuffer(), data_size / AUD_FORMAT_SIZE(m_specs.format));
buf += data_size / AUD_FORMAT_SIZE(m_specs.format);
left -= data_size / sample_size;
if (packet.pts >= m_st_time) {
// copy to output buffer
data_size = std::min(pkgbuf_pos, left * sample_size);
m_convert((data_t*) buf, (data_t*) m_pkgbuf.getBuffer(), data_size / AUD_FORMAT_SIZE(m_specs.format));
buf += data_size / AUD_FORMAT_SIZE(m_specs.format);
left -= data_size / sample_size;
}
}
av_packet_unref(&packet);
}

View File

@@ -29,11 +29,9 @@
#include "respec/ConverterFunctions.h"
#include "IReader.h"
#include "util/Buffer.h"
#include "file/FileInfo.h"
#include <string>
#include <memory>
#include <vector>
struct AVCodecContext;
extern "C" {
@@ -56,6 +54,22 @@ private:
*/
int m_position;
/**
* The start offset in seconds relative to the media container start time.
* IE how much the sound should be delayed to be kept in sync with the rest of the containter streams.
*/
double m_start_offset;
/**
* The start time pts of the stream. All packets before this timestamp shouldn't be played back (only decoded).
*/
int64_t m_st_time;
/**
* The duration of the audio stream in samples.
*/
int64_t m_duration;
/**
* The specification of the audio data.
*/
@@ -121,13 +135,6 @@ private:
*/
bool m_tointerleave;
/**
* Converts an ffmpeg sample format to an audaspace one.
* \param format The AVSampleFormat sample format.
* \return The sample format as SampleFormat.
*/
AUD_LOCAL static SampleFormat convertSampleFormat(AVSampleFormat format);
/**
* Decodes a packet into the given buffer.
* \param packet The AVPacket to decode.
@@ -138,9 +145,8 @@ private:
/**
* Initializes the object.
* \param stream The index of the audio stream within the file if it contains multiple audio streams.
*/
AUD_LOCAL void init(int stream);
AUD_LOCAL void init();
// delete copy constructor and operator=
FFMPEGReader(const FFMPEGReader&) = delete;
@@ -150,33 +156,24 @@ public:
/**
* Creates a new reader.
* \param filename The path to the file to be read.
* \param stream The index of the audio stream within the file if it contains multiple audio streams.
* \exception Exception Thrown if the file specified does not exist or
* cannot be read with ffmpeg.
*/
FFMPEGReader(std::string filename, int stream = 0);
FFMPEGReader(std::string filename);
/**
* Creates a new reader.
* \param buffer The buffer to read from.
* \param stream The index of the audio stream within the file if it contains multiple audio streams.
* \exception Exception Thrown if the buffer specified cannot be read
* with ffmpeg.
*/
FFMPEGReader(std::shared_ptr<Buffer> buffer, int stream = 0);
FFMPEGReader(std::shared_ptr<Buffer> buffer);
/**
* Destroys the reader and closes the file.
*/
virtual ~FFMPEGReader();
/**
* Queries the streams of a sound file.
* \return A vector with as many streams as there are in the file.
* \exception Exception Thrown if the file specified cannot be read.
*/
virtual std::vector<StreamInfo> queryStreams();
/**
* Reads data to a memory buffer.
* This function is used for avio only.
@@ -201,6 +198,7 @@ public:
virtual void seek(int position);
virtual int getLength() const;
virtual int getPosition() const;
virtual double getStartOffset() const;
virtual Specs getSpecs() const;
virtual void read(int& length, bool& eos, sample_t* buffer);
};

View File

@@ -32,26 +32,16 @@ void SndFile::registerPlugin()
FileManager::registerOutput(plugin);
}
std::shared_ptr<IReader> SndFile::createReader(std::string filename, int stream)
std::shared_ptr<IReader> SndFile::createReader(std::string filename)
{
return std::shared_ptr<IReader>(new SndFileReader(filename));
}
std::shared_ptr<IReader> SndFile::createReader(std::shared_ptr<Buffer> buffer, int stream)
std::shared_ptr<IReader> SndFile::createReader(std::shared_ptr<Buffer> buffer)
{
return std::shared_ptr<IReader>(new SndFileReader(buffer));
}
std::vector<StreamInfo> SndFile::queryStreams(std::string filename)
{
return SndFileReader(filename).queryStreams();
}
std::vector<StreamInfo> SndFile::queryStreams(std::shared_ptr<Buffer> buffer)
{
return SndFileReader(buffer).queryStreams();
}
std::shared_ptr<IWriter> SndFile::createWriter(std::string filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate)
{
return std::shared_ptr<IWriter>(new SndFileWriter(filename, specs, format, codec, bitrate));

View File

@@ -52,10 +52,8 @@ public:
*/
static void registerPlugin();
virtual std::shared_ptr<IReader> createReader(std::string filename, int stream = 0);
virtual std::shared_ptr<IReader> createReader(std::shared_ptr<Buffer> buffer, int stream = 0);
virtual std::vector<StreamInfo> queryStreams(std::string filename);
virtual std::vector<StreamInfo> queryStreams(std::shared_ptr<Buffer> buffer);
virtual std::shared_ptr<IReader> createReader(std::string filename);
virtual std::shared_ptr<IReader> createReader(std::shared_ptr<Buffer> buffer);
virtual std::shared_ptr<IWriter> createWriter(std::string filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate);
};

View File

@@ -118,21 +118,6 @@ SndFileReader::~SndFileReader()
sf_close(m_sndfile);
}
std::vector<StreamInfo> SndFileReader::queryStreams()
{
std::vector<StreamInfo> result;
StreamInfo info;
info.start = 0;
info.duration = double(getLength()) / m_specs.rate;
info.specs.specs = m_specs;
info.specs.format = FORMAT_FLOAT32;
result.emplace_back(info);
return result;
}
bool SndFileReader::isSeekable() const
{
return m_seekable;

View File

@@ -28,12 +28,9 @@
* The SndFileReader class.
*/
#include "file/FileInfo.h"
#include <string>
#include <sndfile.h>
#include <memory>
#include <vector>
AUD_NAMESPACE_BEGIN
@@ -99,7 +96,6 @@ public:
/**
* Creates a new reader.
* \param filename The path to the file to be read.
* \param stream The index of the audio stream within the file if it contains multiple audio streams.
* \exception Exception Thrown if the file specified does not exist or
* cannot be read with libsndfile.
*/
@@ -108,7 +104,6 @@ public:
/**
* Creates a new reader.
* \param buffer The buffer to read from.
* \param stream The index of the audio stream within the file if it contains multiple audio streams.
* \exception Exception Thrown if the buffer specified cannot be read
* with libsndfile.
*/
@@ -119,13 +114,6 @@ public:
*/
virtual ~SndFileReader();
/**
* Queries the streams of a sound file.
* \return A vector with as many streams as there are in the file.
* \exception Exception Thrown if the file specified cannot be read.
*/
virtual std::vector<StreamInfo> queryStreams();
virtual bool isSeekable() const;
virtual void seek(int position);
virtual int getLength() const;

View File

@@ -23,121 +23,95 @@
AUD_NAMESPACE_BEGIN
PulseAudioDevice::PulseAudioSynchronizer::PulseAudioSynchronizer(PulseAudioDevice *device) :
m_device(device)
{
}
double PulseAudioDevice::PulseAudioSynchronizer::getPosition(std::shared_ptr<IHandle> handle)
{
pa_usec_t latency;
int negative;
AUD_pa_stream_get_latency(m_device->m_stream, &latency, &negative);
double delay = m_device->m_ring_buffer.getReadSize() / (AUD_SAMPLE_SIZE(m_device->m_specs) * m_device->m_specs.rate) + latency * 1.0e-6;
return handle->getPosition() - delay;
}
void PulseAudioDevice::updateRingBuffer()
{
unsigned int samplesize = AUD_SAMPLE_SIZE(m_specs);
std::unique_lock<std::mutex> lock(m_mixingLock);
Buffer buffer;
while(m_valid)
{
size_t size = m_ring_buffer.getWriteSize();
size_t sample_count = size / samplesize;
if(sample_count > 0)
{
size = sample_count * samplesize;
buffer.assureSize(size);
mix(reinterpret_cast<data_t*>(buffer.getBuffer()), sample_count);
m_ring_buffer.write(reinterpret_cast<data_t*>(buffer.getBuffer()), size);
}
m_mixingCondition.wait(lock);
}
}
void PulseAudioDevice::PulseAudio_state_callback(pa_context *context, void *data)
{
PulseAudioDevice* device = (PulseAudioDevice*)data;
device->m_state = AUD_pa_context_get_state(context);
std::lock_guard<ILockable> lock(*device);
AUD_pa_threaded_mainloop_signal(device->m_mainloop, 0);
device->m_state = AUD_pa_context_get_state(context);
}
void PulseAudioDevice::PulseAudio_request(pa_stream *stream, size_t total_bytes, void *data)
{
PulseAudioDevice* device = (PulseAudioDevice*)data;
data_t* buffer;
size_t sample_size = AUD_DEVICE_SAMPLE_SIZE(device->m_specs);
void* buffer;
while(total_bytes > 0)
{
size_t num_bytes = total_bytes;
AUD_pa_stream_begin_write(stream, reinterpret_cast<void**>(&buffer), &num_bytes);
AUD_pa_stream_begin_write(stream, &buffer, &num_bytes);
size_t readsamples = device->m_ring_buffer.getReadSize();
device->mix((data_t*)buffer, num_bytes / AUD_DEVICE_SAMPLE_SIZE(device->m_specs));
readsamples = std::min(readsamples, size_t(num_bytes)) / sample_size;
device->m_ring_buffer.read(buffer, readsamples * sample_size);
if(readsamples * sample_size < num_bytes)
std::memset(buffer + readsamples * sample_size, 0, num_bytes - readsamples * sample_size);
if(device->m_mixingLock.try_lock())
{
device->m_mixingCondition.notify_all();
device->m_mixingLock.unlock();
}
AUD_pa_stream_write(stream, reinterpret_cast<void*>(buffer), num_bytes, nullptr, 0, PA_SEEK_RELATIVE);
AUD_pa_stream_write(stream, buffer, num_bytes, nullptr, 0, PA_SEEK_RELATIVE);
total_bytes -= num_bytes;
}
}
void PulseAudioDevice::playing(bool playing)
void PulseAudioDevice::PulseAudio_underflow(pa_stream *stream, void *data)
{
m_playback = playing;
PulseAudioDevice* device = (PulseAudioDevice*)data;
AUD_pa_threaded_mainloop_lock(m_mainloop);
AUD_pa_stream_cork(m_stream, playing ? 0 : 1, nullptr, nullptr);
AUD_pa_threaded_mainloop_unlock(m_mainloop);
DeviceSpecs specs = device->getSpecs();
if(++device->m_underflows > 4 && device->m_buffersize < AUD_DEVICE_SAMPLE_SIZE(specs) * specs.rate * 2)
{
device->m_buffersize <<= 1;
device->m_underflows = 0;
pa_buffer_attr buffer_attr;
buffer_attr.fragsize = -1U;
buffer_attr.maxlength = -1U;
buffer_attr.minreq = -1U;
buffer_attr.prebuf = -1U;
buffer_attr.tlength = device->m_buffersize;
AUD_pa_stream_set_buffer_attr(stream, &buffer_attr, nullptr, nullptr);
}
}
void PulseAudioDevice::runMixingThread()
{
for(;;)
{
{
std::lock_guard<ILockable> lock(*this);
if(shouldStop())
{
AUD_pa_stream_cork(m_stream, 1, nullptr, nullptr);
AUD_pa_stream_flush(m_stream, nullptr, nullptr);
doStop();
return;
}
}
if(AUD_pa_stream_is_corked(m_stream))
AUD_pa_stream_cork(m_stream, 0, nullptr, nullptr);
// similar to AUD_pa_mainloop_iterate(m_mainloop, false, nullptr); except with a longer timeout
AUD_pa_mainloop_prepare(m_mainloop, 1 << 14);
AUD_pa_mainloop_poll(m_mainloop);
AUD_pa_mainloop_dispatch(m_mainloop);
}
}
PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buffersize) :
m_synchronizer(this),
m_playback(false),
m_state(PA_CONTEXT_UNCONNECTED),
m_valid(true),
m_underflows(0)
{
m_mainloop = AUD_pa_threaded_mainloop_new();
m_mainloop = AUD_pa_mainloop_new();
AUD_pa_threaded_mainloop_lock(m_mainloop);
m_context = AUD_pa_context_new(AUD_pa_threaded_mainloop_get_api(m_mainloop), name.c_str());
m_context = AUD_pa_context_new(AUD_pa_mainloop_get_api(m_mainloop), name.c_str());
if(!m_context)
{
AUD_pa_threaded_mainloop_unlock(m_mainloop);
AUD_pa_threaded_mainloop_free(m_mainloop);
AUD_pa_mainloop_free(m_mainloop);
AUD_THROW(DeviceException, "Could not connect to PulseAudio.");
}
@@ -146,26 +120,21 @@ PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buff
AUD_pa_context_connect(m_context, nullptr, PA_CONTEXT_NOFLAGS, nullptr);
AUD_pa_threaded_mainloop_start(m_mainloop);
while(m_state != PA_CONTEXT_READY)
{
switch(m_state)
{
case PA_CONTEXT_FAILED:
case PA_CONTEXT_TERMINATED:
AUD_pa_threaded_mainloop_unlock(m_mainloop);
AUD_pa_threaded_mainloop_stop(m_mainloop);
AUD_pa_context_disconnect(m_context);
AUD_pa_context_unref(m_context);
AUD_pa_threaded_mainloop_free(m_mainloop);
AUD_pa_mainloop_free(m_mainloop);
AUD_THROW(DeviceException, "Could not connect to PulseAudio.");
break;
default:
AUD_pa_threaded_mainloop_wait(m_mainloop);
AUD_pa_mainloop_iterate(m_mainloop, true, nullptr);
break;
}
}
@@ -213,18 +182,16 @@ PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buff
if(!m_stream)
{
AUD_pa_threaded_mainloop_unlock(m_mainloop);
AUD_pa_threaded_mainloop_stop(m_mainloop);
AUD_pa_context_disconnect(m_context);
AUD_pa_context_unref(m_context);
AUD_pa_threaded_mainloop_free(m_mainloop);
AUD_pa_mainloop_free(m_mainloop);
AUD_THROW(DeviceException, "Could not create PulseAudio stream.");
}
AUD_pa_stream_set_write_callback(m_stream, PulseAudio_request, this);
AUD_pa_stream_set_underflow_callback(m_stream, PulseAudio_underflow, this);
buffersize *= AUD_DEVICE_SAMPLE_SIZE(m_specs);
m_buffersize = buffersize;
@@ -237,53 +204,31 @@ PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buff
buffer_attr.prebuf = -1U;
buffer_attr.tlength = buffersize;
m_ring_buffer.resize(buffersize);
if(AUD_pa_stream_connect_playback(m_stream, nullptr, &buffer_attr, static_cast<pa_stream_flags_t>(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE), nullptr, nullptr) < 0)
if(AUD_pa_stream_connect_playback(m_stream, nullptr, &buffer_attr, static_cast<pa_stream_flags_t>(PA_STREAM_START_CORKED | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE), nullptr, nullptr) < 0)
{
AUD_pa_threaded_mainloop_unlock(m_mainloop);
AUD_pa_threaded_mainloop_stop(m_mainloop);
AUD_pa_context_disconnect(m_context);
AUD_pa_context_unref(m_context);
AUD_pa_threaded_mainloop_free(m_mainloop);
AUD_pa_mainloop_free(m_mainloop);
AUD_THROW(DeviceException, "Could not connect PulseAudio stream.");
}
AUD_pa_threaded_mainloop_unlock(m_mainloop);
create();
m_mixingThread = std::thread(&PulseAudioDevice::updateRingBuffer, this);
}
PulseAudioDevice::~PulseAudioDevice()
{
m_valid = false;
m_mixingLock.lock();
m_mixingCondition.notify_all();
m_mixingLock.unlock();
m_mixingThread.join();
AUD_pa_threaded_mainloop_stop(m_mainloop);
stopMixingThread();
AUD_pa_context_disconnect(m_context);
AUD_pa_context_unref(m_context);
AUD_pa_threaded_mainloop_free(m_mainloop);
AUD_pa_mainloop_free(m_mainloop);
destroy();
}
ISynchronizer *PulseAudioDevice::getSynchronizer()
{
return &m_synchronizer;
}
class PulseAudioDeviceFactory : public IDeviceFactory
{
private:

View File

@@ -26,11 +26,7 @@
* The PulseAudioDevice class.
*/
#include "devices/SoftwareDevice.h"
#include "util/RingBuffer.h"
#include <condition_variable>
#include <thread>
#include "devices/ThreadedDevice.h"
#include <pulse/pulseaudio.h>
@@ -39,65 +35,17 @@ AUD_NAMESPACE_BEGIN
/**
* This device plays back through PulseAudio, the simple direct media layer.
*/
class AUD_PLUGIN_API PulseAudioDevice : public SoftwareDevice
class AUD_PLUGIN_API PulseAudioDevice : public ThreadedDevice
{
private:
class PulseAudioSynchronizer : public DefaultSynchronizer
{
PulseAudioDevice* m_device;
public:
PulseAudioSynchronizer(PulseAudioDevice* device);
virtual double getPosition(std::shared_ptr<IHandle> handle);
};
/// Synchronizer.
PulseAudioSynchronizer m_synchronizer;
/**
* Whether there is currently playback.
*/
volatile bool m_playback;
pa_threaded_mainloop* m_mainloop;
pa_mainloop* m_mainloop;
pa_context* m_context;
pa_stream* m_stream;
pa_context_state_t m_state;
/**
* The mixing ring buffer.
*/
RingBuffer m_ring_buffer;
/**
* Whether the device is valid.
*/
bool m_valid;
int m_buffersize;
uint32_t m_underflows;
/**
* The mixing thread.
*/
std::thread m_mixingThread;
/**
* Mutex for mixing.
*/
std::mutex m_mixingLock;
/**
* Condition for mixing.
*/
std::condition_variable m_mixingCondition;
/**
* Updates the ring buffer.
*/
AUD_LOCAL void updateRingBuffer();
/**
* Reports the state of the PulseAudio server connection.
* \param context The PulseAudio context.
@@ -113,13 +61,23 @@ private:
*/
AUD_LOCAL static void PulseAudio_request(pa_stream* stream, size_t total_bytes, void* data);
/**
* Reports an underflow from the PulseAudio server.
* Automatically adjusts the latency if this happens too often.
* @param stream The PulseAudio stream.
* \param data The PulseAudio device.
*/
AUD_LOCAL static void PulseAudio_underflow(pa_stream* stream, void* data);
/**
* Streaming thread main function.
*/
AUD_LOCAL void runMixingThread();
// delete copy constructor and operator=
PulseAudioDevice(const PulseAudioDevice&) = delete;
PulseAudioDevice& operator=(const PulseAudioDevice&) = delete;
protected:
virtual void playing(bool playing);
public:
/**
* Opens the PulseAudio audio device for playback.
@@ -135,8 +93,6 @@ public:
*/
virtual ~PulseAudioDevice();
virtual ISynchronizer* getSynchronizer();
/**
* Registers this plugin.
*/

View File

@@ -25,7 +25,6 @@ PULSEAUDIO_SYMBOL(pa_stream_begin_write);
PULSEAUDIO_SYMBOL(pa_stream_connect_playback);
PULSEAUDIO_SYMBOL(pa_stream_cork);
PULSEAUDIO_SYMBOL(pa_stream_flush);
PULSEAUDIO_SYMBOL(pa_stream_get_latency);
PULSEAUDIO_SYMBOL(pa_stream_is_corked);
PULSEAUDIO_SYMBOL(pa_stream_new);
PULSEAUDIO_SYMBOL(pa_stream_set_buffer_attr);
@@ -40,13 +39,3 @@ PULSEAUDIO_SYMBOL(pa_mainloop_iterate);
PULSEAUDIO_SYMBOL(pa_mainloop_prepare);
PULSEAUDIO_SYMBOL(pa_mainloop_poll);
PULSEAUDIO_SYMBOL(pa_mainloop_dispatch);
PULSEAUDIO_SYMBOL(pa_threaded_mainloop_free);
PULSEAUDIO_SYMBOL(pa_threaded_mainloop_get_api);
PULSEAUDIO_SYMBOL(pa_threaded_mainloop_lock);
PULSEAUDIO_SYMBOL(pa_threaded_mainloop_new);
PULSEAUDIO_SYMBOL(pa_threaded_mainloop_signal);
PULSEAUDIO_SYMBOL(pa_threaded_mainloop_start);
PULSEAUDIO_SYMBOL(pa_threaded_mainloop_stop);
PULSEAUDIO_SYMBOL(pa_threaded_mainloop_unlock);
PULSEAUDIO_SYMBOL(pa_threaded_mainloop_wait);

View File

@@ -23,31 +23,23 @@
AUD_NAMESPACE_BEGIN
File::File(std::string filename, int stream) :
m_filename(filename), m_stream(stream)
File::File(std::string filename) :
m_filename(filename)
{
}
File::File(const data_t* buffer, int size, int stream) :
m_buffer(new Buffer(size)), m_stream(stream)
File::File(const data_t* buffer, int size) :
m_buffer(new Buffer(size))
{
std::memcpy(m_buffer->getBuffer(), buffer, size);
}
std::vector<StreamInfo> File::queryStreams()
{
if(m_buffer.get())
return FileManager::queryStreams(m_buffer);
else
return FileManager::queryStreams(m_filename);
}
std::shared_ptr<IReader> File::createReader()
{
if(m_buffer.get())
return FileManager::createReader(m_buffer, m_stream);
return FileManager::createReader(m_buffer);
else
return FileManager::createReader(m_filename, m_stream);
return FileManager::createReader(m_filename);
}
AUD_NAMESPACE_END

View File

@@ -43,13 +43,13 @@ void FileManager::registerOutput(std::shared_ptr<aud::IFileOutput> output)
outputs().push_back(output);
}
std::shared_ptr<IReader> FileManager::createReader(std::string filename, int stream)
std::shared_ptr<IReader> FileManager::createReader(std::string filename)
{
for(std::shared_ptr<IFileInput> input : inputs())
{
try
{
return input->createReader(filename, stream);
return input->createReader(filename);
}
catch(Exception&) {}
}
@@ -57,41 +57,13 @@ std::shared_ptr<IReader> FileManager::createReader(std::string filename, int str
AUD_THROW(FileException, "The file couldn't be read with any installed file reader.");
}
std::shared_ptr<IReader> FileManager::createReader(std::shared_ptr<Buffer> buffer, int stream)
std::shared_ptr<IReader> FileManager::createReader(std::shared_ptr<Buffer> buffer)
{
for(std::shared_ptr<IFileInput> input : inputs())
{
try
{
return input->createReader(buffer, stream);
}
catch(Exception&) {}
}
AUD_THROW(FileException, "The file couldn't be read with any installed file reader.");
}
std::vector<StreamInfo> FileManager::queryStreams(std::string filename)
{
for(std::shared_ptr<IFileInput> input : inputs())
{
try
{
return input->queryStreams(filename);
}
catch(Exception&) {}
}
AUD_THROW(FileException, "The file couldn't be read with any installed file reader.");
}
std::vector<StreamInfo> FileManager::queryStreams(std::shared_ptr<Buffer> buffer)
{
for(std::shared_ptr<IFileInput> input : inputs())
{
try
{
return input->queryStreams(buffer);
return input->createReader(buffer);
}
catch(Exception&) {}
}

View File

@@ -57,4 +57,4 @@ void VolumeReader::read(int& length, bool& eos, sample_t* buffer)
buffer[i] = buffer[i] * m_volumeStorage->getVolume();
}
AUD_NAMESPACE_END
AUD_NAMESPACE_END

View File

@@ -1,137 +0,0 @@
/*******************************************************************************
* Copyright 2009-2021 Jörg Müller
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
#include "util/RingBuffer.h"
#include <algorithm>
#include <cstring>
#include <cstdlib>
#define ALIGNMENT 32
#define ALIGN(a) (a + ALIGNMENT - ((long long)a & (ALIGNMENT-1)))
AUD_NAMESPACE_BEGIN
RingBuffer::RingBuffer(int size) :
m_buffer(size),
m_read(0),
m_write(0)
{
}
sample_t* RingBuffer::getBuffer() const
{
return m_buffer.getBuffer();
}
int RingBuffer::getSize() const
{
return m_buffer.getSize();
}
size_t RingBuffer::getReadSize() const
{
size_t read = m_read;
size_t write = m_write;
if(read > write)
return write + getSize() - read;
else
return write - read;
}
size_t RingBuffer::getWriteSize() const
{
size_t read = m_read;
size_t write = m_write;
if(read > write)
return read - write - 1;
else
return read + getSize() - write - 1;
}
size_t RingBuffer::read(data_t* target, size_t size)
{
size = std::min(size, getReadSize());
data_t* buffer = reinterpret_cast<data_t*>(m_buffer.getBuffer());
if(m_read + size > m_buffer.getSize())
{
size_t read_first = m_buffer.getSize() - m_read;
size_t read_second = size - read_first;
std::memcpy(target, buffer + m_read, read_first);
std::memcpy(target + read_first, buffer, read_second);
m_read = read_second;
}
else
{
std::memcpy(target, buffer + m_read, size);
m_read += size;
}
return size;
}
size_t RingBuffer::write(data_t* source, size_t size)
{
size = std::min(size, getWriteSize());
data_t* buffer = reinterpret_cast<data_t*>(m_buffer.getBuffer());
if(m_write + size > m_buffer.getSize())
{
size_t write_first = m_buffer.getSize() - m_write;
size_t write_second = size - write_first;
std::memcpy(buffer + m_write, source, write_first);
std::memcpy(buffer, source + write_first, write_second);
m_write = write_second;
}
else
{
std::memcpy(buffer + m_write, source, size);
m_write += size;
}
return size;
}
void RingBuffer::reset()
{
m_read = 0;
m_write = 0;
}
void RingBuffer::resize(int size)
{
m_buffer.resize(size);
reset();
}
void RingBuffer::assureSize(int size)
{
m_buffer.assureSize(size);
reset();
}
AUD_NAMESPACE_END

View File

@@ -645,8 +645,7 @@ typedef enum CUdevice_P2PAttribute_enum {
CU_DEVICE_P2P_ATTRIBUTE_PERFORMANCE_RANK = 0x01,
CU_DEVICE_P2P_ATTRIBUTE_ACCESS_SUPPORTED = 0x02,
CU_DEVICE_P2P_ATTRIBUTE_NATIVE_ATOMIC_SUPPORTED = 0x03,
CU_DEVICE_P2P_ATTRIBUTE_ACCESS_ACCESS_SUPPORTED = 0x04,
CU_DEVICE_P2P_ATTRIBUTE_CUDA_ARRAY_ACCESS_SUPPORTED = 0x04,
CU_DEVICE_P2P_ATTRIBUTE_ARRAY_ACCESS_ACCESS_SUPPORTED = 0x04,
} CUdevice_P2PAttribute;
typedef void (CUDA_CB *CUstreamCallback)(CUstream hStream, CUresult status, void* userData);

View File

@@ -1,5 +0,0 @@
Project: JSON
URL: https://github.com/nlohmann/json/
License: MIT License
Upstream version: 3.10.2
Local modifications: None

File diff suppressed because it is too large Load Diff

View File

@@ -67,7 +67,7 @@ SET(LEMON_ENABLE_ILOG YES CACHE STRING "Enable ILOG (CPLEX) solver backend.")
SET(LEMON_ENABLE_COIN YES CACHE STRING "Enable COIN solver backend.")
SET(LEMON_ENABLE_SOPLEX YES CACHE STRING "Enable SoPlex solver backend.")
IF(LEMON_ENABLE_GLPK)
IF(LEMON_ENABLE_GLPK)
FIND_PACKAGE(GLPK 4.33)
ENDIF(LEMON_ENABLE_GLPK)
IF(LEMON_ENABLE_ILOG)

View File

@@ -4,7 +4,7 @@ FIND_PATH(ILOG_ROOT_DIR
PATHS /opt/ibm/ILOG /usr/local/ibm/ILOG /usr/local/ILOG /usr/local/ilog
PATHS "$ENV{HOME}/ILOG" "$ENV{HOME}/.local/ILOG"
PATHS "$ENV{HOME}/ibm/ILOG" "$ENV{HOME}/.local/ibm/ILOG"
PATHS "C:/Program Files/IBM/ILOG"
PATHS "C:/Program Files/IBM/ILOG"
PATH_SUFFIXES "CPLEX_Studio126" "CPLEX_Studio125"
"CPLEX_Studio124" "CPLEX_Studio123" "CPLEX_Studio122"
NO_DEFAULT_PATH

View File

@@ -16,3 +16,4 @@ LINK_DIRECTORIES(
# ADD_EXECUTABLE(myprog myprog-main.cc)
# TARGET_LINK_LIBRARIES(myprog lemon)

View File

@@ -88,3 +88,4 @@ INSTALL(
FILES ${CMAKE_CURRENT_BINARY_DIR}/lemon.pc
DESTINATION lib/pkgconfig
)

View File

@@ -10,6 +10,7 @@
#include <fstream>
#include <unordered_map>
#include <functional>
namespace qflow {
@@ -69,7 +70,7 @@ void load(const char* filename, MatrixXd& V, MatrixXi& F)
};
/// Hash function for obj_vertex
struct obj_vertexHash {
struct obj_vertexHash : std::function<size_t(obj_vertex)> {
std::size_t operator()(const obj_vertex &v) const {
size_t hash = std::hash<uint32_t>()(v.p);
hash = hash * 37 + std::hash<uint32_t>()(v.uv);

View File

@@ -1,6 +0,0 @@
Project: TinyGLTF
URL: https://github.com/syoyo/tinygltf
License: MIT
Upstream version: 2.5.0, 19a41d20ec0
Local modifications:
* Silence "enum value not handled in switch" warnings due to JSON dependency.

File diff suppressed because it is too large Load Diff

BIN
icon_geom.blend Normal file

Binary file not shown.

View File

@@ -49,27 +49,27 @@
/* Unsigned */
ATOMIC_INLINE uint64_t atomic_add_and_fetch_uint64(uint64_t *p, uint64_t x)
{
return InterlockedExchangeAdd64((int64_t *)p, (int64_t)x) + x;
return (uint64_t)(InterlockedExchangeAdd64((int64_t *)p, (int64_t)x) + (int64_t)x);
}
ATOMIC_INLINE uint64_t atomic_sub_and_fetch_uint64(uint64_t *p, uint64_t x)
{
return InterlockedExchangeAdd64((int64_t *)p, -((int64_t)x)) - x;
return (uint64_t)(InterlockedExchangeAdd64((int64_t *)p, -((int64_t)x)) - (int64_t)x);
}
ATOMIC_INLINE uint64_t atomic_cas_uint64(uint64_t *v, uint64_t old, uint64_t _new)
{
return InterlockedCompareExchange64((int64_t *)v, _new, old);
return (uint64_t)(InterlockedCompareExchange64((int64_t *)v, _new, old));
}
ATOMIC_INLINE uint64_t atomic_fetch_and_add_uint64(uint64_t *p, uint64_t x)
{
return InterlockedExchangeAdd64((int64_t *)p, (int64_t)x);
return (uint64_t)InterlockedExchangeAdd64((int64_t *)p, (int64_t)x);
}
ATOMIC_INLINE uint64_t atomic_fetch_and_sub_uint64(uint64_t *p, uint64_t x)
{
return InterlockedExchangeAdd64((int64_t *)p, -((int64_t)x));
return (uint64_t)InterlockedExchangeAdd64((int64_t *)p, -((int64_t)x));
}
/* Signed */
@@ -103,32 +103,32 @@ ATOMIC_INLINE int64_t atomic_fetch_and_sub_int64(int64_t *p, int64_t x)
/* Unsigned */
ATOMIC_INLINE uint32_t atomic_add_and_fetch_uint32(uint32_t *p, uint32_t x)
{
return InterlockedExchangeAdd(p, x) + x;
return (uint32_t)InterlockedExchangeAdd(p, x) + x;
}
ATOMIC_INLINE uint32_t atomic_sub_and_fetch_uint32(uint32_t *p, uint32_t x)
{
return InterlockedExchangeAdd(p, -((int32_t)x)) - x;
return (uint32_t)InterlockedExchangeAdd(p, -((int32_t)x)) - x;
}
ATOMIC_INLINE uint32_t atomic_cas_uint32(uint32_t *v, uint32_t old, uint32_t _new)
{
return InterlockedCompareExchange((long *)v, _new, old);
return (uint32_t)InterlockedCompareExchange((long *)v, _new, old);
}
ATOMIC_INLINE uint32_t atomic_fetch_and_add_uint32(uint32_t *p, uint32_t x)
{
return InterlockedExchangeAdd(p, x);
return (uint32_t)InterlockedExchangeAdd(p, x);
}
ATOMIC_INLINE uint32_t atomic_fetch_and_or_uint32(uint32_t *p, uint32_t x)
{
return InterlockedOr((long *)p, x);
return (uint32_t)InterlockedOr((long *)p, x);
}
ATOMIC_INLINE uint32_t atomic_fetch_and_and_uint32(uint32_t *p, uint32_t x)
{
return InterlockedAnd((long *)p, x);
return (uint32_t)InterlockedAnd((long *)p, x);
}
/* Signed */
@@ -205,9 +205,9 @@ ATOMIC_INLINE uint8_t atomic_fetch_and_or_uint8(uint8_t *p, uint8_t b)
ATOMIC_INLINE int8_t atomic_fetch_and_and_int8(int8_t *p, int8_t b)
{
#if (LG_SIZEOF_PTR == 8 || LG_SIZEOF_INT == 8)
return InterlockedAnd8((char *)p, (char)b);
return (int8_t)InterlockedAnd8((char *)p, (char)b);
#else
return _InterlockedAnd8((char *)p, (char)b);
return (int8_t)_InterlockedAnd8((char *)p, (char)b);
#endif
}
@@ -215,9 +215,9 @@ ATOMIC_INLINE int8_t atomic_fetch_and_and_int8(int8_t *p, int8_t b)
ATOMIC_INLINE int8_t atomic_fetch_and_or_int8(int8_t *p, int8_t b)
{
#if (LG_SIZEOF_PTR == 8 || LG_SIZEOF_INT == 8)
return InterlockedOr8((char *)p, (char)b);
return (int8_t)InterlockedOr8((char *)p, (char)b);
#else
return _InterlockedOr8((char *)p, (char)b);
return (int8_t)_InterlockedOr8((char *)p, (char)b);
#endif
}

View File

@@ -247,7 +247,7 @@ if(WITH_CYCLES_OSL)
endif()
if(WITH_CYCLES_DEVICE_OPTIX)
find_package(OptiX 7.3.0)
find_package(OptiX)
if(OPTIX_FOUND)
add_definitions(-DWITH_OPTIX)
@@ -286,17 +286,11 @@ if(WITH_OPENSUBDIV)
)
endif()
if(WITH_OPENIMAGEDENOISE)
add_definitions(-DWITH_OPENIMAGEDENOISE)
add_definitions(-DOIDN_STATIC_LIB)
include_directories(
SYSTEM
${OPENIMAGEDENOISE_INCLUDE_DIRS}
)
endif()
if(WITH_CYCLES_STANDALONE)
set(WITH_CYCLES_DEVICE_OPENCL TRUE)
set(WITH_CYCLES_DEVICE_CUDA TRUE)
# Experimental and unfinished.
set(WITH_CYCLES_NETWORK FALSE)
endif()
# TODO(sergey): Consider removing it, only causes confusion in interface.
set(WITH_CYCLES_DEVICE_MULTI TRUE)
@@ -392,12 +386,18 @@ if(WITH_CYCLES_BLENDER)
add_subdirectory(blender)
endif()
add_subdirectory(app)
if(WITH_CYCLES_NETWORK)
add_definitions(-DWITH_NETWORK)
endif()
if(WITH_CYCLES_STANDALONE OR WITH_CYCLES_NETWORK OR WITH_CYCLES_CUBIN_COMPILER)
add_subdirectory(app)
endif()
add_subdirectory(bvh)
add_subdirectory(device)
add_subdirectory(doc)
add_subdirectory(graph)
add_subdirectory(integrator)
add_subdirectory(kernel)
add_subdirectory(render)
add_subdirectory(subd)

View File

@@ -90,6 +90,24 @@ if(WITH_CYCLES_STANDALONE)
endif()
endif()
#####################################################################
# Cycles network server executable
#####################################################################
if(WITH_CYCLES_NETWORK)
set(SRC
cycles_server.cpp
)
add_executable(cycles_server ${SRC})
target_link_libraries(cycles_server ${LIBRARIES})
cycles_target_link_libraries(cycles_server)
if(UNIX AND NOT APPLE)
set_target_properties(cycles_server PROPERTIES INSTALL_RPATH $ORIGIN/lib)
endif()
unset(SRC)
endif()
#####################################################################
# Cycles cubin compiler executable
#####################################################################

View File

@@ -53,7 +53,7 @@ struct Options {
SessionParams session_params;
bool quiet;
bool show_help, interactive, pause;
string output_filepath;
string output_path;
} options;
static void session_print(const string &str)
@@ -126,7 +126,7 @@ static BufferParams &session_buffer_params()
static void scene_init()
{
options.scene = options.session->scene;
options.scene = new Scene(options.scene_params, options.session->device);
/* Read XML */
xml_read_file(options.scene, options.filepath.c_str());
@@ -148,7 +148,7 @@ static void scene_init()
static void session_init()
{
options.session_params.write_render_cb = write_render;
options.session = new Session(options.session_params, options.scene_params);
options.session = new Session(options.session_params);
if (options.session_params.background && !options.quiet)
options.session->progress.set_update_callback(function_bind(&session_print_status));
@@ -159,8 +159,9 @@ static void session_init()
/* load scene */
scene_init();
options.session->scene = options.scene;
options.session->reset(options.session_params, session_buffer_params());
options.session->reset(session_buffer_params(), options.session_params.samples);
options.session->start();
}
@@ -222,7 +223,9 @@ static void display_info(Progress &progress)
static void display()
{
options.session->draw();
static DeviceDrawParams draw_params = DeviceDrawParams();
options.session->draw(session_buffer_params(), draw_params);
display_info(options.session->progress);
}
@@ -252,7 +255,7 @@ static void motion(int x, int y, int button)
options.session->scene->camera->need_flags_update = true;
options.session->scene->camera->need_device_update = true;
options.session->reset(options.session_params, session_buffer_params());
options.session->reset(session_buffer_params(), options.session_params.samples);
}
}
@@ -269,7 +272,7 @@ static void resize(int width, int height)
options.session->scene->camera->need_flags_update = true;
options.session->scene->camera->need_device_update = true;
options.session->reset(options.session_params, session_buffer_params());
options.session->reset(session_buffer_params(), options.session_params.samples);
}
}
@@ -281,7 +284,7 @@ static void keyboard(unsigned char key)
/* Reset */
else if (key == 'r')
options.session->reset(options.session_params, session_buffer_params());
options.session->reset(session_buffer_params(), options.session_params.samples);
/* Cancel */
else if (key == 27) // escape
@@ -318,7 +321,7 @@ static void keyboard(unsigned char key)
options.session->scene->camera->need_flags_update = true;
options.session->scene->camera->need_device_update = true;
options.session->reset(options.session_params, session_buffer_params());
options.session->reset(session_buffer_params(), options.session_params.samples);
}
/* Set Max Bounces */
@@ -344,7 +347,7 @@ static void keyboard(unsigned char key)
options.session->scene->integrator->set_max_bounce(bounce);
options.session->reset(options.session_params, session_buffer_params());
options.session->reset(session_buffer_params(), options.session_params.samples);
}
}
#endif
@@ -359,13 +362,11 @@ static int files_parse(int argc, const char *argv[])
static void options_parse(int argc, const char **argv)
{
options.width = 1024;
options.height = 512;
options.width = 0;
options.height = 0;
options.filepath = "";
options.session = NULL;
options.quiet = false;
options.session_params.use_auto_tile = false;
options.session_params.tile_size = 0;
/* device names */
string device_names = "";
@@ -411,7 +412,7 @@ static void options_parse(int argc, const char **argv)
&options.session_params.samples,
"Number of samples to render",
"--output %s",
&options.output_filepath,
&options.output_path,
"File path to write output image",
"--threads %d",
&options.session_params.threads,
@@ -422,9 +423,12 @@ static void options_parse(int argc, const char **argv)
"--height %d",
&options.height,
"Window height in pixel",
"--tile-size %d",
&options.session_params.tile_size,
"Tile size in pixels",
"--tile-width %d",
&options.session_params.tile_size.x,
"Tile width in pixels",
"--tile-height %d",
&options.session_params.tile_size.y,
"Tile height in pixels",
"--list-devices",
&list,
"List information about all available devices",
@@ -486,9 +490,8 @@ static void options_parse(int argc, const char **argv)
options.session_params.background = true;
#endif
if (options.session_params.tile_size > 0) {
options.session_params.use_auto_tile = true;
}
/* Use progressive rendering */
options.session_params.progressive = true;
/* find matching device */
DeviceType device_type = Device::type_from_string(devicename.c_str());
@@ -524,6 +527,9 @@ static void options_parse(int argc, const char **argv)
fprintf(stderr, "No file path specified\n");
exit(EXIT_FAILURE);
}
/* For smoother Viewport */
options.session_params.start_resolution = 64;
}
CCL_NAMESPACE_END

View File

@@ -703,7 +703,7 @@ void xml_read_file(Scene *scene, const char *filepath)
xml_read_include(state, path_filename(filepath));
scene->params.bvh_type = BVH_TYPE_STATIC;
scene->params.bvh_type = SceneParams::BVH_STATIC;
}
CCL_NAMESPACE_END

View File

@@ -33,7 +33,6 @@ set(SRC
blender_device.cpp
blender_image.cpp
blender_geometry.cpp
blender_gpu_display.cpp
blender_light.cpp
blender_mesh.cpp
blender_object.cpp
@@ -51,7 +50,6 @@ set(SRC
CCL_api.h
blender_device.h
blender_gpu_display.h
blender_id_map.h
blender_image.h
blender_object_cull.h
@@ -95,6 +93,14 @@ set(ADDON_FILES
add_definitions(${GL_DEFINITIONS})
if(WITH_CYCLES_DEVICE_OPENCL)
add_definitions(-DWITH_OPENCL)
endif()
if(WITH_CYCLES_NETWORK)
add_definitions(-DWITH_NETWORK)
endif()
if(WITH_MOD_FLUID)
add_definitions(-DWITH_FLUID)
endif()

View File

@@ -58,6 +58,7 @@ class CyclesRender(bpy.types.RenderEngine):
bl_use_eevee_viewport = True
bl_use_preview = True
bl_use_exclude_layers = True
bl_use_save_buffers = True
bl_use_spherical_stereo = True
bl_use_custom_freestyle = True
bl_use_alembic_procedural = True
@@ -84,12 +85,6 @@ class CyclesRender(bpy.types.RenderEngine):
def render(self, depsgraph):
engine.render(self, depsgraph)
def render_frame_finish(self):
engine.render_frame_finish(self)
def draw(self, context, depsgraph):
engine.draw(self, depsgraph, context.space_data)
def bake(self, depsgraph, obj, pass_type, pass_filter, width, height):
engine.bake(self, depsgraph, obj, pass_type, pass_filter, width, height)
@@ -103,7 +98,7 @@ class CyclesRender(bpy.types.RenderEngine):
engine.sync(self, depsgraph, context.blend_data)
def view_draw(self, context, depsgraph):
engine.view_draw(self, depsgraph, context.region, context.space_data, context.region_data)
engine.draw(self, depsgraph, context.region, context.space_data, context.region_data)
def update_script_node(self, node):
if engine.with_osl():

View File

@@ -18,17 +18,62 @@
from __future__ import annotations
def _is_using_buggy_driver():
import gpu
# We need to be conservative here because in multi-GPU systems display card
# might be quite old, but others one might be just good.
#
# So We shouldn't disable possible good dedicated cards just because display
# card seems weak. And instead we only blacklist configurations which are
# proven to cause problems.
if gpu.platform.vendor_get() == "ATI Technologies Inc.":
import re
version = gpu.platform.version_get()
if version.endswith("Compatibility Profile Context"):
# Old HD 4xxx and 5xxx series drivers did not have driver version
# in the version string, but those cards do not quite work and
# causing crashes.
return True
regex = re.compile(".*Compatibility Profile Context ([0-9]+(\\.[0-9]+)+)$")
if not regex.match(version):
# Skip cards like FireGL
return False
version = regex.sub("\\1", version).split('.')
return int(version[0]) == 8
return False
def _workaround_buggy_drivers():
if _is_using_buggy_driver():
import _cycles
if hasattr(_cycles, "opencl_disable"):
print("Cycles: OpenGL driver known to be buggy, disabling OpenCL platform.")
_cycles.opencl_disable()
def _configure_argument_parser():
import argparse
# No help because it conflicts with general Python scripts argument parsing
parser = argparse.ArgumentParser(description="Cycles Addon argument parser",
add_help=False)
parser.add_argument("--cycles-resumable-num-chunks",
help="Number of chunks to split sample range into",
default=None)
parser.add_argument("--cycles-resumable-current-chunk",
help="Current chunk of samples range to render",
default=None)
parser.add_argument("--cycles-resumable-start-chunk",
help="Start chunk to render",
default=None)
parser.add_argument("--cycles-resumable-end-chunk",
help="End chunk to render",
default=None)
parser.add_argument("--cycles-print-stats",
help="Print rendering statistics to stderr",
action='store_true')
parser.add_argument("--cycles-device",
help="Set the device to use for Cycles, overriding user preferences and the scene setting."
"Valid options are 'CPU', 'CUDA' or 'OPTIX'."
"Valid options are 'CPU', 'CUDA', 'OPTIX' or 'OPENCL'."
"Additionally, you can append '+CPU' to any GPU type for hybrid rendering.",
default=None)
return parser
@@ -44,6 +89,21 @@ def _parse_command_line():
parser = _configure_argument_parser()
args, _ = parser.parse_known_args(argv[argv.index("--") + 1:])
if args.cycles_resumable_num_chunks is not None:
if args.cycles_resumable_current_chunk is not None:
import _cycles
_cycles.set_resumable_chunk(
int(args.cycles_resumable_num_chunks),
int(args.cycles_resumable_current_chunk),
)
elif args.cycles_resumable_start_chunk is not None and \
args.cycles_resumable_end_chunk:
import _cycles
_cycles.set_resumable_chunk_range(
int(args.cycles_resumable_num_chunks),
int(args.cycles_resumable_start_chunk),
int(args.cycles_resumable_end_chunk),
)
if args.cycles_print_stats:
import _cycles
_cycles.enable_print_stats()
@@ -58,11 +118,23 @@ def init():
import _cycles
import os.path
# Workaround possibly buggy legacy drivers which crashes on the OpenCL
# device enumeration.
#
# This checks are not really correct because they might still fail
# in the case of multiple GPUs. However, currently buggy drivers
# are really old and likely to be used in single GPU systems only
# anyway.
#
# Can't do it in the background mode, so we hope OpenCL is no enabled
# in the user preferences.
if not bpy.app.background:
_workaround_buggy_drivers()
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()
@@ -105,25 +177,6 @@ def render(engine, depsgraph):
_cycles.render(engine.session, depsgraph.as_pointer())
def render_frame_finish(engine):
if not engine.session:
return
import _cycles
_cycles.render_frame_finish(engine.session)
def draw(engine, depsgraph, space_image):
if not engine.session:
return
depsgraph_ptr = depsgraph.as_pointer()
space_image_ptr = space_image.as_pointer()
screen_ptr = space_image.id_data.as_pointer()
import _cycles
_cycles.draw(engine.session, depsgraph_ptr, screen_ptr, space_image_ptr)
def bake(engine, depsgraph, obj, pass_type, pass_filter, width, height):
import _cycles
session = getattr(engine, "session", None)
@@ -151,14 +204,14 @@ def sync(engine, depsgraph, data):
_cycles.sync(engine.session, depsgraph.as_pointer())
def view_draw(engine, depsgraph, region, v3d, rv3d):
def draw(engine, depsgraph, region, v3d, rv3d):
import _cycles
depsgraph = depsgraph.as_pointer()
v3d = v3d.as_pointer()
rv3d = rv3d.as_pointer()
# draw render image
_cycles.view_draw(engine.session, depsgraph, v3d, rv3d)
_cycles.draw(engine.session, depsgraph, v3d, rv3d)
def available_devices():
@@ -171,6 +224,11 @@ def with_osl():
return _cycles.with_osl
def with_network():
import _cycles
return _cycles.with_network
def system_info():
import _cycles
return _cycles.system_info()
@@ -185,7 +243,6 @@ def list_render_passes(scene, srl):
# Data passes.
if srl.use_pass_z: yield ("Depth", "Z", 'VALUE')
if srl.use_pass_mist: yield ("Mist", "Z", 'VALUE')
if srl.use_pass_position: yield ("Position", "XYZ", 'VECTOR')
if srl.use_pass_normal: yield ("Normal", "XYZ", 'VECTOR')
if srl.use_pass_vector: yield ("Vector", "XYZW", 'VECTOR')
if srl.use_pass_uv: yield ("UV", "UVA", 'VECTOR')
@@ -208,7 +265,6 @@ def list_render_passes(scene, srl):
if srl.use_pass_environment: yield ("Env", "RGB", 'COLOR')
if srl.use_pass_shadow: yield ("Shadow", "RGB", 'COLOR')
if srl.use_pass_ambient_occlusion: yield ("AO", "RGB", 'COLOR')
if crl.use_pass_shadow_catcher: yield ("Shadow Catcher", "RGB", 'COLOR')
# Debug passes.
if crl.pass_debug_render_time: yield ("Debug Render Time", "X", 'VALUE')
@@ -227,20 +283,30 @@ def list_render_passes(scene, srl):
yield ("CryptoAsset" + '{:02d}'.format(i), "RGBA", 'COLOR')
# Denoising passes.
if scene.cycles.use_denoising and crl.use_denoising:
if (scene.cycles.use_denoising and crl.use_denoising) or crl.denoising_store_passes:
yield ("Noisy Image", "RGBA", 'COLOR')
if crl.use_pass_shadow_catcher:
yield ("Noisy Shadow Catcher", "RGBA", 'COLOR')
if crl.denoising_store_passes:
yield ("Denoising Normal", "XYZ", 'VECTOR')
yield ("Denoising Albedo", "RGB", 'COLOR')
if crl.denoising_store_passes:
yield ("Denoising Normal", "XYZ", 'VECTOR')
yield ("Denoising Albedo", "RGB", 'COLOR')
yield ("Denoising Depth", "Z", 'VALUE')
if scene.cycles.denoiser == 'NLM':
yield ("Denoising Shadowing", "X", 'VALUE')
yield ("Denoising Variance", "RGB", 'COLOR')
yield ("Denoising Intensity", "X", 'VALUE')
clean_options = ("denoising_diffuse_direct", "denoising_diffuse_indirect",
"denoising_glossy_direct", "denoising_glossy_indirect",
"denoising_transmission_direct", "denoising_transmission_indirect")
if any(getattr(crl, option) for option in clean_options):
yield ("Denoising Clean", "RGB", 'COLOR')
# Custom AOV passes.
for aov in srl.aovs:
if aov.type == 'VALUE':
yield (aov.name, "X", 'VALUE')
else:
yield (aov.name, "RGB", 'COLOR')
yield (aov.name, "RGBA", 'COLOR')
def register_passes(engine, scene, view_layer):

View File

@@ -60,48 +60,32 @@ class AddPresetSampling(AddPresetBase, Operator):
]
preset_values = [
"cycles.use_adaptive_sampling",
"cycles.samples",
"cycles.adaptive_threshold",
"cycles.adaptive_min_samples",
"cycles.time_limit",
"cycles.use_denoising",
"cycles.denoiser",
"cycles.denoising_input_passes",
"cycles.denoising_prefilter",
"cycles.preview_samples",
"cycles.aa_samples",
"cycles.preview_aa_samples",
"cycles.diffuse_samples",
"cycles.glossy_samples",
"cycles.transmission_samples",
"cycles.ao_samples",
"cycles.mesh_light_samples",
"cycles.subsurface_samples",
"cycles.volume_samples",
"cycles.use_square_samples",
"cycles.progressive",
"cycles.seed",
"cycles.sample_clamp_direct",
"cycles.sample_clamp_indirect",
"cycles.sample_all_lights_direct",
"cycles.sample_all_lights_indirect",
]
preset_subdir = "cycles/sampling"
class AddPresetViewportSampling(AddPresetBase, Operator):
'''Add a Viewport Sampling Preset'''
bl_idname = "render.cycles_viewport_sampling_preset_add"
bl_label = "Add Viewport Sampling Preset"
preset_menu = "CYCLES_PT_viewport_sampling_presets"
preset_defines = [
"cycles = bpy.context.scene.cycles"
]
preset_values = [
"cycles.use_preview_adaptive_sampling",
"cycles.preview_samples",
"cycles.preview_adaptive_threshold",
"cycles.preview_adaptive_min_samples",
"cycles.use_preview_denoising",
"cycles.preview_denoiser",
"cycles.preview_denoising_input_passes",
"cycles.preview_denoising_prefilter",
"cycles.preview_denoising_start_sample",
]
preset_subdir = "cycles/viewport_sampling"
classes = (
AddPresetIntegrator,
AddPresetSampling,
AddPresetViewportSampling,
)

View File

@@ -39,6 +39,11 @@ enum_devices = (
('GPU', "GPU Compute", "Use GPU compute device for rendering, configured in the system tab in the user preferences"),
)
from _cycles import with_network
if with_network:
enum_devices += (('NETWORK', "Networked Device", "Use networked device for rendering"),)
del with_network
enum_feature_set = (
('SUPPORTED', "Supported", "Only use finished and supported features"),
('EXPERIMENTAL', "Experimental", "Use experimental and incomplete features that might be broken or change in the future", 'ERROR', 1),
@@ -79,6 +84,15 @@ enum_curve_shape = (
('THICK', "3D Curves", "Render hair as 3D curve, for accurate results when viewing hair close up"),
)
enum_tile_order = (
('CENTER', "Center", "Render from center to the edges"),
('RIGHT_TO_LEFT', "Right to Left", "Render from right to left"),
('LEFT_TO_RIGHT', "Left to Right", "Render from left to right"),
('TOP_TO_BOTTOM', "Top to Bottom", "Render from top to bottom"),
('BOTTOM_TO_TOP', "Bottom to Top", "Render from bottom to top"),
('HILBERT_SPIRAL', "Hilbert Spiral", "Render in a Hilbert Spiral"),
)
enum_use_layer_samples = (
('USE', "Use", "Per render layer number of samples override scene samples"),
('BOUNDED', "Bounded", "Bound per render layer number of samples by global samples"),
@@ -87,9 +101,15 @@ enum_use_layer_samples = (
enum_sampling_pattern = (
('SOBOL', "Sobol", "Use Sobol random sampling pattern"),
('CORRELATED_MUTI_JITTER', "Correlated Multi-Jitter", "Use Correlated Multi-Jitter random sampling pattern"),
('PROGRESSIVE_MUTI_JITTER', "Progressive Multi-Jitter", "Use Progressive Multi-Jitter random sampling pattern"),
)
enum_integrator = (
('BRANCHED_PATH', "Branched Path Tracing", "Path tracing integrator that branches on the first bounce, giving more control over the number of light and material samples"),
('PATH', "Path Tracing", "Pure path tracing integrator"),
)
enum_volume_sampling = (
('DISTANCE', "Distance", "Use distance sampling, best for dense volumes with lights far away"),
('EQUIANGULAR', "Equiangular", "Use equiangular sampling, best for volumes with low density with light inside or near the volume"),
@@ -111,6 +131,7 @@ enum_device_type = (
('CPU', "CPU", "CPU", 0),
('CUDA', "CUDA", "CUDA", 1),
('OPTIX', "OptiX", "OptiX", 3),
('OPENCL', "OpenCL", "OpenCL", 2)
)
enum_texture_limit = (
@@ -123,46 +144,39 @@ enum_texture_limit = (
('4096', "4096", "Limit texture size to 4096 pixels", 6),
('8192', "8192", "Limit texture size to 8192 pixels", 7),
)
# NOTE: Identifiers are expected to be an upper case version of identifiers from `Pass::get_type_enum()`
enum_view3d_shading_render_pass = (
('', "General", ""),
('COMBINED', "Combined", "Show the Combined Render pass"),
('EMISSION', "Emission", "Show the Emission render pass"),
('BACKGROUND', "Background", "Show the Background render pass"),
('AO', "Ambient Occlusion", "Show the Ambient Occlusion render pass"),
('SHADOW', "Shadow", "Show the Shadow render pass"),
('SHADOW_CATCHER', "Shadow Catcher", "Show the Shadow Catcher render pass"),
('COMBINED', "Combined", "Show the Combined Render pass", 1),
('EMISSION', "Emission", "Show the Emission render pass", 33),
('BACKGROUND', "Background", "Show the Background render pass", 34),
('AO', "Ambient Occlusion", "Show the Ambient Occlusion render pass", 35),
('', "Light", ""),
('DIFFUSE_DIRECT', "Diffuse Direct", "Show the Diffuse Direct render pass"),
('DIFFUSE_INDIRECT', "Diffuse Indirect", "Show the Diffuse Indirect render pass"),
('DIFFUSE_COLOR', "Diffuse Color", "Show the Diffuse Color render pass"),
('DIFFUSE_DIRECT', "Diffuse Direct", "Show the Diffuse Direct render pass", 38),
('DIFFUSE_INDIRECT', "Diffuse Indirect", "Show the Diffuse Indirect render pass", 39),
('DIFFUSE_COLOR', "Diffuse Color", "Show the Diffuse Color render pass", 40),
('GLOSSY_DIRECT', "Glossy Direct", "Show the Glossy Direct render pass"),
('GLOSSY_INDIRECT', "Glossy Indirect", "Show the Glossy Indirect render pass"),
('GLOSSY_COLOR', "Glossy Color", "Show the Glossy Color render pass"),
('GLOSSY_DIRECT', "Glossy Direct", "Show the Glossy Direct render pass", 41),
('GLOSSY_INDIRECT', "Glossy Indirect", "Show the Glossy Indirect render pass", 42),
('GLOSSY_COLOR', "Glossy Color", "Show the Glossy Color render pass", 43),
('', "", ""),
('TRANSMISSION_DIRECT', "Transmission Direct", "Show the Transmission Direct render pass"),
('TRANSMISSION_INDIRECT', "Transmission Indirect", "Show the Transmission Indirect render pass"),
('TRANSMISSION_COLOR', "Transmission Color", "Show the Transmission Color render pass"),
('TRANSMISSION_DIRECT', "Transmission Direct", "Show the Transmission Direct render pass", 44),
('TRANSMISSION_INDIRECT', "Transmission Indirect", "Show the Transmission Indirect render pass", 45),
('TRANSMISSION_COLOR', "Transmission Color", "Show the Transmission Color render pass", 46),
('VOLUME_DIRECT', "Volume Direct", "Show the Volume Direct render pass"),
('VOLUME_INDIRECT', "Volume Indirect", "Show the Volume Indirect render pass"),
('VOLUME_DIRECT', "Volume Direct", "Show the Volume Direct render pass", 50),
('VOLUME_INDIRECT', "Volume Indirect", "Show the Volume Indirect render pass", 51),
('', "Data", ""),
('POSITION', "Position", "Show the Position render pass"),
('NORMAL', "Normal", "Show the Normal render pass"),
('UV', "UV", "Show the UV render pass"),
('MIST', "Mist", "Show the Mist render pass"),
('DENOISING_ALBEDO', "Denoising Albedo", "Albedo pass used by denoiser"),
('DENOISING_NORMAL', "Denoising Normal", "Normal pass used by denoiser"),
('SAMPLE_COUNT', "Sample Count", "Per-pixel number of samples"),
('NORMAL', "Normal", "Show the Normal render pass", 3),
('UV', "UV", "Show the UV render pass", 4),
('MIST', "Mist", "Show the Mist render pass", 32),
)
@@ -194,23 +208,18 @@ def enum_preview_denoiser(self, context):
def enum_denoiser(self, context):
items = []
items = [('NLM', "NLM", "Cycles native non-local means denoiser, running on any compute device", 1)]
items += enum_optix_denoiser(self, context)
items += enum_openimagedenoise_denoiser(self, context)
return items
enum_denoising_input_passes = (
('RGB', "None", "Don't use utility passes for denoising", 1),
('RGB_ALBEDO', "Albedo", "Use albedo pass for denoising", 2),
('RGB_ALBEDO_NORMAL', "Albedo and Normal", "Use albedo and normal passes for denoising", 3),
('RGB', "Color", "Use only color as input", 1),
('RGB_ALBEDO', "Color + Albedo", "Use color and albedo data as input", 2),
('RGB_ALBEDO_NORMAL', "Color + Albedo + Normal", "Use color, albedo and normal data as input", 3),
)
enum_denoising_prefilter = (
('NONE', "None", "No prefiltering, use when guiding passes are noise-free", 1),
('FAST', "Fast", "Denoise color and guiding passes together. Improves quality when guiding passes are noisy using least amount of extra processing time", 2),
('ACCURATE', "Accurate", "Prefilter noisy guiding passes before denoising color. Improves quality when guiding passes are noisy using extra processing time", 3),
)
def update_render_passes(self, context):
scene = context.scene
@@ -243,6 +252,13 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
description="Use Open Shading Language (CPU rendering only)",
)
progressive: EnumProperty(
name="Integrator",
description="Method to sample lights and materials",
items=enum_integrator,
default='PATH',
)
preview_pause: BoolProperty(
name="Pause Preview",
description="Pause all viewport preview renders",
@@ -252,88 +268,110 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
use_denoising: BoolProperty(
name="Use Denoising",
description="Denoise the rendered image",
default=True,
default=False,
update=update_render_passes,
)
denoiser: EnumProperty(
name="Denoiser",
description="Denoise the image with the selected denoiser. "
"For denoising the image after rendering",
items=enum_denoiser,
default=4, # Use integer to avoid error in builds without OpenImageDenoise.
update=update_render_passes,
)
denoising_prefilter: EnumProperty(
name="Denoising Prefilter",
description="Prefilter noisy guiding (albedo and normal) passes to improve denoising quality when using OpenImageDenoiser",
items=enum_denoising_prefilter,
default='ACCURATE',
)
denoising_input_passes: EnumProperty(
name="Denoising Input Passes",
description="Passes used by the denoiser to distinguish noise from shader and geometry detail",
items=enum_denoising_input_passes,
default='RGB_ALBEDO_NORMAL',
)
use_preview_denoising: BoolProperty(
name="Use Viewport Denoising",
description="Denoise the image in the 3D viewport",
default=False,
)
denoiser: EnumProperty(
name="Denoiser",
description="Denoise the image with the selected denoiser. "
"For denoising the image after rendering, denoising data render passes "
"also adapt to the selected denoiser",
items=enum_denoiser,
default=1,
update=update_render_passes,
)
preview_denoiser: EnumProperty(
name="Viewport Denoiser",
description="Denoise the image after each preview update with the selected denoiser",
items=enum_preview_denoiser,
default=0,
)
preview_denoising_prefilter: EnumProperty(
name="Viewport Denoising Prefilter",
description="Prefilter noisy guiding (albedo and normal) passes to improve denoising quality when using OpenImageDenoiser",
items=enum_denoising_prefilter,
default='FAST',
)
preview_denoising_input_passes: EnumProperty(
name="Viewport Denoising Input Passes",
description="Passes used by the denoiser to distinguish noise from shader and geometry detail",
items=enum_denoising_input_passes,
default='RGB_ALBEDO',
)
preview_denoising_start_sample: IntProperty(
name="Start Denoising",
description="Sample to start denoising the preview at",
min=0, max=(1 << 24),
default=1,
use_square_samples: BoolProperty(
name="Square Samples",
description="Square sampling values for easier artist control",
default=False,
)
samples: IntProperty(
name="Samples",
description="Number of samples to render for each pixel",
min=1, max=(1 << 24),
default=4096,
default=128,
)
preview_samples: IntProperty(
name="Viewport Samples",
description="Number of samples to render in the viewport, unlimited if 0",
min=0, max=(1 << 24),
default=1024,
default=32,
)
aa_samples: IntProperty(
name="AA Samples",
description="Number of antialiasing samples to render for each pixel",
min=1, max=2097151,
default=128,
)
preview_aa_samples: IntProperty(
name="AA Samples",
description="Number of antialiasing samples to render in the viewport, unlimited if 0",
min=0, max=2097151,
default=32,
)
time_limit: FloatProperty(
name="Time Limit",
description="Limit the render time (excluding synchronization time)."
"Zero disables the limit",
min=0.0,
default=0.0,
step=100.0,
unit='TIME_ABSOLUTE',
diffuse_samples: IntProperty(
name="Diffuse Samples",
description="Number of diffuse bounce samples to render for each AA sample",
min=1, max=1024,
default=1,
)
glossy_samples: IntProperty(
name="Glossy Samples",
description="Number of glossy bounce samples to render for each AA sample",
min=1, max=1024,
default=1,
)
transmission_samples: IntProperty(
name="Transmission Samples",
description="Number of transmission bounce samples to render for each AA sample",
min=1, max=1024,
default=1,
)
ao_samples: IntProperty(
name="Ambient Occlusion Samples",
description="Number of ambient occlusion samples to render for each AA sample",
min=1, max=1024,
default=1,
)
mesh_light_samples: IntProperty(
name="Mesh Light Samples",
description="Number of mesh emission light samples to render for each AA sample",
min=1, max=1024,
default=1,
)
subsurface_samples: IntProperty(
name="Subsurface Samples",
description="Number of subsurface scattering samples to render for each AA sample",
min=1, max=1024,
default=1,
)
volume_samples: IntProperty(
name="Volume Samples",
description="Number of volume scattering samples to render for each AA sample",
min=1, max=1024,
default=1,
)
sampling_pattern: EnumProperty(
name="Sampling Pattern",
description="Random sampling pattern used by the integrator",
items=enum_sampling_pattern,
default='PROGRESSIVE_MUTI_JITTER',
default='SOBOL',
)
use_layer_samples: EnumProperty(
@@ -343,6 +381,17 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
default='USE',
)
sample_all_lights_direct: BoolProperty(
name="Sample All Direct Lights",
description="Sample all lights (for direct samples), rather than randomly picking one",
default=True,
)
sample_all_lights_indirect: BoolProperty(
name="Sample All Indirect Lights",
description="Sample all lights (for indirect samples), rather than randomly picking one",
default=True,
)
light_sampling_threshold: FloatProperty(
name="Light Sampling Threshold",
description="Probabilistically terminate light samples when the light contribution is below this threshold (more noise but faster rendering). "
@@ -354,39 +403,19 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
use_adaptive_sampling: BoolProperty(
name="Use Adaptive Sampling",
description="Automatically reduce the number of samples per pixel based on estimated noise level",
default=True,
default=False,
)
adaptive_threshold: FloatProperty(
name="Adaptive Sampling Threshold",
description="Noise level step to stop sampling at, lower values reduce noise at the cost of render time. Zero for automatic setting based on number of AA samples",
min=0.0, max=1.0,
soft_min=0.001,
default=0.01,
default=0.0,
precision=4,
)
adaptive_min_samples: IntProperty(
name="Adaptive Min Samples",
description="Minimum AA samples for adaptive sampling, to discover noisy features before stopping sampling. Zero for automatic setting based on noise threshold",
min=0, max=4096,
default=0,
)
use_preview_adaptive_sampling: BoolProperty(
name="Use Adaptive Sampling",
description="Automatically reduce the number of samples per pixel based on estimated noise level, for viewport renders",
default=True,
)
preview_adaptive_threshold: FloatProperty(
name="Adaptive Sampling Threshold",
description="Noise level step to stop sampling at, lower values reduce noise at the cost of render time. Zero for automatic setting based on number of AA samples, for viewport renders",
min=0.0, max=1.0,
soft_min=0.001,
default=0.1,
precision=4,
)
preview_adaptive_min_samples: IntProperty(
name="Adaptive Min Samples",
description="Minimum AA samples for adaptive sampling, to discover noisy features before stopping sampling. Zero for automatic setting based on noise threshold, for viewport renders",
description="Minimum AA samples for adaptive sampling, to discover noisy features before stopping sampling. Zero for automatic setting based on number of AA samples",
min=0, max=4096,
default=0,
)
@@ -603,6 +632,53 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
default=10.0,
)
debug_tile_size: IntProperty(
name="Tile Size",
description="",
min=1, max=4096,
default=1024,
)
preview_start_resolution: IntProperty(
name="Start Resolution",
description="Resolution to start rendering preview at, "
"progressively increasing it to the full viewport size",
min=8, max=16384,
default=64,
subtype='PIXEL'
)
preview_denoising_start_sample: IntProperty(
name="Start Denoising",
description="Sample to start denoising the preview at",
min=0, max=(1 << 24),
default=1,
)
preview_denoising_input_passes: EnumProperty(
name="Viewport Input Passes",
description="Passes used by the denoiser to distinguish noise from shader and geometry detail",
items=enum_denoising_input_passes,
default='RGB_ALBEDO',
)
debug_reset_timeout: FloatProperty(
name="Reset timeout",
description="",
min=0.01, max=10.0,
default=0.1,
)
debug_cancel_timeout: FloatProperty(
name="Cancel timeout",
description="",
min=0.01, max=10.0,
default=0.1,
)
debug_text_timeout: FloatProperty(
name="Text timeout",
description="",
min=0.01, max=10.0,
default=1.0,
)
debug_bvh_type: EnumProperty(
name="Viewport BVH Type",
description="Choose between faster updates, or faster render",
@@ -625,24 +701,38 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
default=0,
min=0, max=16,
)
tile_order: EnumProperty(
name="Tile Order",
description="Tile order for rendering",
items=enum_tile_order,
default='HILBERT_SPIRAL',
options=set(), # Not animatable!
)
use_progressive_refine: BoolProperty(
name="Progressive Refine",
description="Instead of rendering each tile until it is finished, "
"refine the whole image progressively "
"(this renders somewhat slower, "
"but time can be saved by manually stopping the render when the noise is low enough)",
default=False,
)
bake_type: EnumProperty(
name="Bake Type",
default='COMBINED',
description="Type of pass to bake",
items=(
('COMBINED', "Combined", "", 0),
('AO', "Ambient Occlusion", "", 1),
('SHADOW', "Shadow", "", 2),
('POSITION', "Position", "", 11),
('NORMAL', "Normal", "", 3),
('UV', "UV", "", 4),
('ROUGHNESS', "Roughness", "", 5),
('EMIT', "Emit", "", 6),
('ENVIRONMENT', "Environment", "", 7),
('DIFFUSE', "Diffuse", "", 8),
('GLOSSY', "Glossy", "", 9),
('TRANSMISSION', "Transmission", "", 10),
('COMBINED', "Combined", ""),
('AO', "Ambient Occlusion", ""),
('SHADOW', "Shadow", ""),
('NORMAL', "Normal", ""),
('UV', "UV", ""),
('ROUGHNESS', "Roughness", ""),
('EMIT', "Emit", ""),
('ENVIRONMENT', "Environment", ""),
('DIFFUSE', "Diffuse", ""),
('GLOSSY', "Glossy", ""),
('TRANSMISSION', "Transmission", ""),
),
)
@@ -737,18 +827,6 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
min=0, max=1024,
)
use_auto_tile: BoolProperty(
name="Auto Tiles",
description="Automatically render high resolution images in tiles to reduce memory usage, using the specified tile size. Tiles are cached to disk while rendering to save memory",
default=True,
)
tile_size: IntProperty(
name="Tile Size",
default=2048,
description="",
min=8, max=16384,
)
# Various fine-tuning debug flags
def _devices_update_callback(self, context):
@@ -766,13 +844,45 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
items=enum_bvh_layouts,
default='EMBREE',
)
debug_use_cpu_split_kernel: BoolProperty(name="Split Kernel", default=False)
debug_use_cuda_adaptive_compile: BoolProperty(name="Adaptive Compile", default=False)
debug_use_cuda_split_kernel: BoolProperty(name="Split Kernel", default=False)
debug_use_optix_debug: BoolProperty(
name="OptiX Module Debug",
description="Load OptiX module in debug mode: lower logging verbosity level, enable validations, and lower optimization level",
default=False
debug_optix_cuda_streams: IntProperty(name="CUDA Streams", default=1, min=1)
debug_optix_curves_api: BoolProperty(name="Native OptiX Curve Primitive", default=False)
debug_opencl_kernel_type: EnumProperty(
name="OpenCL Kernel Type",
default='DEFAULT',
items=(
('DEFAULT', "Default", ""),
('MEGA', "Mega", ""),
('SPLIT', "Split", ""),
),
update=CyclesRenderSettings._devices_update_callback
)
debug_opencl_device_type: EnumProperty(
name="OpenCL Device Type",
default='ALL',
items=(
('NONE', "None", ""),
('ALL', "All", ""),
('DEFAULT', "Default", ""),
('CPU', "CPU", ""),
('GPU', "GPU", ""),
('ACCELERATOR', "Accelerator", ""),
),
update=CyclesRenderSettings._devices_update_callback
)
debug_use_opencl_debug: BoolProperty(name="Debug OpenCL", default=False)
debug_opencl_mem_limit: IntProperty(
name="Memory limit",
default=0,
description="Artificial limit on OpenCL memory usage in MB (0 to disable limit)"
)
@classmethod
@@ -921,6 +1031,12 @@ class CyclesLightSettings(bpy.types.PropertyGroup):
description="Light casts shadows",
default=True,
)
samples: IntProperty(
name="Samples",
description="Number of light samples to render for each AA sample",
min=1, max=10000,
default=1,
)
max_bounces: IntProperty(
name="Max Bounces",
description="Maximum number of bounces the light will contribute to the render",
@@ -968,6 +1084,12 @@ class CyclesWorldSettings(bpy.types.PropertyGroup):
min=4, max=8192,
default=1024,
)
samples: IntProperty(
name="Samples",
description="Number of light samples to render for each AA sample",
min=1, max=10000,
default=1,
)
max_bounces: IntProperty(
name="Max Bounces",
description="Maximum number of bounces the background light will contribute to the render",
@@ -1221,25 +1343,91 @@ class CyclesRenderLayerSettings(bpy.types.PropertyGroup):
update=update_render_passes,
)
use_pass_shadow_catcher: BoolProperty(
name="Shadow Catcher",
description="Pass containing shadows and light which is to be multiplied into backdrop",
default=False,
update=update_render_passes,
)
use_denoising: BoolProperty(
name="Use Denoising",
description="Denoise the rendered image",
default=True,
update=update_render_passes,
)
denoising_diffuse_direct: BoolProperty(
name="Diffuse Direct",
description="Denoise the direct diffuse lighting",
default=True,
)
denoising_diffuse_indirect: BoolProperty(
name="Diffuse Indirect",
description="Denoise the indirect diffuse lighting",
default=True,
)
denoising_glossy_direct: BoolProperty(
name="Glossy Direct",
description="Denoise the direct glossy lighting",
default=True,
)
denoising_glossy_indirect: BoolProperty(
name="Glossy Indirect",
description="Denoise the indirect glossy lighting",
default=True,
)
denoising_transmission_direct: BoolProperty(
name="Transmission Direct",
description="Denoise the direct transmission lighting",
default=True,
)
denoising_transmission_indirect: BoolProperty(
name="Transmission Indirect",
description="Denoise the indirect transmission lighting",
default=True,
)
denoising_strength: FloatProperty(
name="Denoising Strength",
description="Controls neighbor pixel weighting for the denoising filter (lower values preserve more detail, but aren't as smooth)",
min=0.0, max=1.0,
default=0.5,
)
denoising_feature_strength: FloatProperty(
name="Denoising Feature Strength",
description="Controls removal of noisy image feature passes (lower values preserve more detail, but aren't as smooth)",
min=0.0, max=1.0,
default=0.5,
)
denoising_radius: IntProperty(
name="Denoising Radius",
description="Size of the image area that's used to denoise a pixel (higher values are smoother, but might lose detail and are slower)",
min=1, max=25,
default=8,
subtype="PIXEL",
)
denoising_relative_pca: BoolProperty(
name="Relative Filter",
description="When removing pixels that don't carry information, use a relative threshold instead of an absolute one (can help to reduce artifacts, but might cause detail loss around edges)",
default=False,
)
denoising_store_passes: BoolProperty(
name="Store Denoising Passes",
description="Store the denoising feature passes and the noisy image. The passes adapt to the denoiser selected for rendering",
default=False,
update=update_render_passes,
)
denoising_neighbor_frames: IntProperty(
name="Neighbor Frames",
description="Number of neighboring frames to use for denoising animations (more frames produce smoother results at the cost of performance)",
min=0, max=7,
default=0,
)
denoising_optix_input_passes: EnumProperty(
name="Input Passes",
description="Passes used by the denoiser to distinguish noise from shader and geometry detail",
items=enum_denoising_input_passes,
default='RGB_ALBEDO',
)
denoising_openimagedenoise_input_passes: EnumProperty(
name="Input Passes",
description="Passes used by the denoiser to distinguish noise from shader and geometry detail",
items=enum_denoising_input_passes,
default='RGB_ALBEDO_NORMAL',
)
@classmethod
def register(cls):
@@ -1266,12 +1454,14 @@ class CyclesPreferences(bpy.types.AddonPreferences):
def get_device_types(self, context):
import _cycles
has_cuda, has_optix = _cycles.get_device_types()
has_cuda, has_optix, has_opencl = _cycles.get_device_types()
list = [('NONE', "None", "Don't use compute device", 0)]
if has_cuda:
list.append(('CUDA', "CUDA", "Use CUDA for GPU acceleration", 1))
if has_optix:
list.append(('OPTIX', "OptiX", "Use OptiX for GPU acceleration", 3))
if has_opencl:
list.append(('OPENCL', "OpenCL", "Use OpenCL for GPU acceleration", 2))
return list
compute_device_type: EnumProperty(
@@ -1296,7 +1486,7 @@ class CyclesPreferences(bpy.types.AddonPreferences):
def update_device_entries(self, device_list):
for device in device_list:
if not device[1] in {'CUDA', 'OPTIX', 'CPU'}:
if not device[1] in {'CUDA', 'OPTIX', 'OPENCL', 'CPU'}:
continue
# Try to find existing Device entry
entry = self.find_existing_device_entry(device)
@@ -1330,23 +1520,22 @@ class CyclesPreferences(bpy.types.AddonPreferences):
elif entry.type == 'CPU':
cpu_devices.append(entry)
# Extend all GPU devices with CPU.
if compute_device_type != 'CPU':
if compute_device_type in {'CUDA', 'OPTIX', 'OPENCL'}:
devices.extend(cpu_devices)
return devices
# Refresh device list. This does not happen automatically on Blender
# startup due to unstable OpenCL implementations that can cause crashes.
def refresh_devices(self):
# For backwards compatibility, only returns CUDA and OpenCL but still
# refreshes all devices.
def get_devices(self, compute_device_type=''):
import _cycles
# Ensure `self.devices` is not re-allocated when the second call to
# get_devices_for_type is made, freeing items from the first list.
for device_type in ('CUDA', 'OPTIX', 'OPENCL'):
self.update_device_entries(_cycles.available_devices(device_type))
# Deprecated: use refresh_devices instead.
def get_devices(self, compute_device_type=''):
self.refresh_devices()
return None
cuda_devices = self.get_devices_for_type('CUDA')
opencl_devices = self.get_devices_for_type('OPENCL')
return cuda_devices, opencl_devices
def get_num_gpu_devices(self):
import _cycles
@@ -1412,10 +1601,6 @@ class CyclesView3DShadingSettings(bpy.types.PropertyGroup):
items=enum_view3d_shading_render_pass,
default='COMBINED',
)
show_active_pixels: BoolProperty(
name="Show Active Pixels",
description="When using adaptive sampling highlight pixels which are being sampled",
)
def register():

View File

@@ -34,12 +34,6 @@ class CYCLES_PT_sampling_presets(PresetPanel, Panel):
preset_add_operator = "render.cycles_sampling_preset_add"
COMPAT_ENGINES = {'CYCLES'}
class CYCLES_PT_viewport_sampling_presets(PresetPanel, Panel):
bl_label = "Viewport Sampling Presets"
preset_subdir = "cycles/viewport_sampling"
preset_operator = "script.execute_preset"
preset_add_operator = "render.cycles_viewport_sampling_preset_add"
COMPAT_ENGINES = {'CYCLES'}
class CYCLES_PT_integrator_presets(PresetPanel, Panel):
bl_label = "Integrator Presets"
@@ -60,15 +54,6 @@ class CyclesButtonsPanel:
return context.engine in cls.COMPAT_ENGINES
class CyclesDebugButtonsPanel(CyclesButtonsPanel):
@classmethod
def poll(cls, context):
prefs = bpy.context.preferences
return (CyclesButtonsPanel.poll(context)
and prefs.experimental.use_cycles_debug
and prefs.view.show_developer_ui)
# Adapt properties editor panel to display in node editor. We have to
# copy the class rather than inherit due to the way bpy registration works.
def node_panel(cls):
@@ -93,6 +78,12 @@ def use_cpu(context):
return (get_device_type(context) == 'NONE' or cscene.device == 'CPU')
def use_opencl(context):
cscene = context.scene.cycles
return (get_device_type(context) == 'OPENCL' and cscene.device == 'GPU')
def use_cuda(context):
cscene = context.scene.cycles
@@ -105,6 +96,12 @@ def use_optix(context):
return (get_device_type(context) == 'OPTIX' and cscene.device == 'GPU')
def use_branched_path(context):
cscene = context.scene.cycles
return (cscene.progressive == 'BRANCHED_PATH' and not use_optix(context))
def use_sample_all_lights(context):
cscene = context.scene.cycles
@@ -118,93 +115,55 @@ def show_device_active(context):
return context.preferences.addons[__package__].preferences.has_active_device()
def get_effective_preview_denoiser(context):
scene = context.scene
cscene = scene.cycles
def draw_samples_info(layout, context):
cscene = context.scene.cycles
integrator = cscene.progressive
if cscene.preview_denoiser != "AUTO":
return cscene.preview_denoiser
# Calculate sample values
if integrator == 'PATH':
aa = cscene.samples
if cscene.use_square_samples:
aa = aa * aa
else:
aa = cscene.aa_samples
d = cscene.diffuse_samples
g = cscene.glossy_samples
t = cscene.transmission_samples
ao = cscene.ao_samples
ml = cscene.mesh_light_samples
sss = cscene.subsurface_samples
vol = cscene.volume_samples
if context.preferences.addons[__package__].preferences.get_devices_for_type('OPTIX'):
return 'OPTIX'
return 'OIDN'
if cscene.use_square_samples:
aa = aa * aa
d = d * d
g = g * g
t = t * t
ao = ao * ao
ml = ml * ml
sss = sss * sss
vol = vol * vol
# Draw interface
# Do not draw for progressive, when Square Samples are disabled
if use_branched_path(context) or (cscene.use_square_samples and integrator == 'PATH'):
col = layout.column(align=True)
col.scale_y = 0.6
col.label(text="Total Samples:")
col.separator()
if integrator == 'PATH':
col.label(text="%s AA" % aa)
else:
col.label(text="%s AA, %s Diffuse, %s Glossy, %s Transmission" %
(aa, d * aa, g * aa, t * aa))
col.separator()
col.label(text="%s AO, %s Mesh Light, %s Subsurface, %s Volume" %
(ao * aa, ml * aa, sss * aa, vol * aa))
class CYCLES_RENDER_PT_sampling(CyclesButtonsPanel, Panel):
bl_label = "Sampling"
def draw(self, context):
pass
class CYCLES_RENDER_PT_sampling_viewport(CyclesButtonsPanel, Panel):
bl_label = "Viewport"
bl_parent_id = "CYCLES_RENDER_PT_sampling"
def draw_header_preset(self, context):
CYCLES_PT_viewport_sampling_presets.draw_panel_header(self.layout)
def draw(self, context):
layout = self.layout
scene = context.scene
cscene = scene.cycles
layout.use_property_split = True
layout.use_property_decorate = False
heading = layout.column(align=True, heading="Noise Threshold")
row = heading.row(align=True)
row.prop(cscene, "use_preview_adaptive_sampling", text="")
sub = row.row()
sub.active = cscene.use_preview_adaptive_sampling
sub.prop(cscene, "preview_adaptive_threshold", text="")
if cscene.use_preview_adaptive_sampling:
col = layout.column(align=True)
col.prop(cscene, "preview_samples", text=" Max Samples")
col.prop(cscene, "preview_adaptive_min_samples", text="Min Samples")
else:
layout.prop(cscene, "preview_samples", text="Samples")
class CYCLES_RENDER_PT_sampling_viewport_denoise(CyclesButtonsPanel, Panel):
bl_label = "Denoise"
bl_parent_id = 'CYCLES_RENDER_PT_sampling_viewport'
bl_options = {'DEFAULT_CLOSED'}
def draw_header(self, context):
scene = context.scene
cscene = scene.cycles
self.layout.prop(context.scene.cycles, "use_preview_denoising", text="")
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
scene = context.scene
cscene = scene.cycles
col = layout.column()
col.active = cscene.use_preview_denoising
col.prop(cscene, "preview_denoiser", text="Denoiser")
col.prop(cscene, "preview_denoising_input_passes", text="Passes")
effective_preview_denoiser = get_effective_preview_denoiser(context)
if effective_preview_denoiser == 'OPENIMAGEDENOISE':
col.prop(cscene, "preview_denoising_prefilter", text="Prefilter")
col.prop(cscene, "preview_denoising_start_sample", text="Start Sample")
class CYCLES_RENDER_PT_sampling_render(CyclesButtonsPanel, Panel):
bl_label = "Render"
bl_parent_id = "CYCLES_RENDER_PT_sampling"
def draw_header_preset(self, context):
CYCLES_PT_sampling_presets.draw_panel_header(self.layout)
@@ -217,32 +176,29 @@ class CYCLES_RENDER_PT_sampling_render(CyclesButtonsPanel, Panel):
layout.use_property_split = True
layout.use_property_decorate = False
heading = layout.column(align=True, heading="Noise Threshold")
row = heading.row(align=True)
row.prop(cscene, "use_adaptive_sampling", text="")
sub = row.row()
sub.active = cscene.use_adaptive_sampling
sub.prop(cscene, "adaptive_threshold", text="")
if not use_optix(context):
layout.prop(cscene, "progressive")
col = layout.column(align=True)
if cscene.use_adaptive_sampling:
col.prop(cscene, "samples", text=" Max Samples")
col.prop(cscene, "adaptive_min_samples", text="Min Samples")
if not use_branched_path(context):
col = layout.column(align=True)
col.prop(cscene, "samples", text="Render")
col.prop(cscene, "preview_samples", text="Viewport")
else:
col.prop(cscene, "samples", text="Samples")
col.prop(cscene, "time_limit")
col = layout.column(align=True)
col.prop(cscene, "aa_samples", text="Render")
col.prop(cscene, "preview_aa_samples", text="Viewport")
if not use_branched_path(context):
draw_samples_info(layout, context)
class CYCLES_RENDER_PT_sampling_render_denoise(CyclesButtonsPanel, Panel):
bl_label = "Denoise"
bl_parent_id = 'CYCLES_RENDER_PT_sampling_render'
bl_options = {'DEFAULT_CLOSED'}
class CYCLES_RENDER_PT_sampling_sub_samples(CyclesButtonsPanel, Panel):
bl_label = "Sub Samples"
bl_parent_id = "CYCLES_RENDER_PT_sampling"
def draw_header(self, context):
scene = context.scene
cscene = scene.cycles
self.layout.prop(context.scene.cycles, "use_denoising", text="")
@classmethod
def poll(cls, context):
return use_branched_path(context)
def draw(self, context):
layout = self.layout
@@ -252,12 +208,88 @@ class CYCLES_RENDER_PT_sampling_render_denoise(CyclesButtonsPanel, Panel):
scene = context.scene
cscene = scene.cycles
col = layout.column()
col.active = cscene.use_denoising
col.prop(cscene, "denoiser", text="Denoiser")
col.prop(cscene, "denoising_input_passes", text="Passes")
if cscene.denoiser == 'OPENIMAGEDENOISE':
col.prop(cscene, "denoising_prefilter", text="Prefilter")
col = layout.column(align=True)
col.prop(cscene, "diffuse_samples", text="Diffuse")
col.prop(cscene, "glossy_samples", text="Glossy")
col.prop(cscene, "transmission_samples", text="Transmission")
col.prop(cscene, "ao_samples", text="AO")
sub = col.row(align=True)
sub.active = use_sample_all_lights(context)
sub.prop(cscene, "mesh_light_samples", text="Mesh Light")
col.prop(cscene, "subsurface_samples", text="Subsurface")
col.prop(cscene, "volume_samples", text="Volume")
draw_samples_info(layout, context)
class CYCLES_RENDER_PT_sampling_adaptive(CyclesButtonsPanel, Panel):
bl_label = "Adaptive Sampling"
bl_parent_id = "CYCLES_RENDER_PT_sampling"
bl_options = {'DEFAULT_CLOSED'}
def draw_header(self, context):
layout = self.layout
scene = context.scene
cscene = scene.cycles
layout.prop(cscene, "use_adaptive_sampling", text="")
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
scene = context.scene
cscene = scene.cycles
layout.active = cscene.use_adaptive_sampling
col = layout.column(align=True)
col.prop(cscene, "adaptive_threshold", text="Noise Threshold")
col.prop(cscene, "adaptive_min_samples", text="Min Samples")
class CYCLES_RENDER_PT_sampling_denoising(CyclesButtonsPanel, Panel):
bl_label = "Denoising"
bl_parent_id = "CYCLES_RENDER_PT_sampling"
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
scene = context.scene
cscene = scene.cycles
heading = layout.column(align=True, heading="Render")
row = heading.row(align=True)
row.prop(cscene, "use_denoising", text="")
sub = row.row()
sub.active = cscene.use_denoising
for view_layer in scene.view_layers:
if view_layer.cycles.denoising_store_passes:
sub.active = True
sub.prop(cscene, "denoiser", text="")
layout.separator()
heading = layout.column(align=False, heading="Viewport")
row = heading.row(align=True)
row.prop(cscene, "use_preview_denoising", text="")
sub = row.row()
sub.active = cscene.use_preview_denoising
sub.prop(cscene, "preview_denoiser", text="")
sub = heading.row(align=True)
sub.active = cscene.use_preview_denoising
sub.prop(cscene, "preview_denoising_start_sample", text="Start Sample")
sub = heading.row(align=True)
sub.active = cscene.use_preview_denoising
sub.prop(cscene, "preview_denoising_input_passes", text="Input Passes")
class CYCLES_RENDER_PT_sampling_advanced(CyclesButtonsPanel, Panel):
@@ -281,6 +313,8 @@ class CYCLES_RENDER_PT_sampling_advanced(CyclesButtonsPanel, Panel):
col.active = not(cscene.use_adaptive_sampling)
col.prop(cscene, "sampling_pattern", text="Pattern")
layout.prop(cscene, "use_square_samples")
layout.separator()
col = layout.column(align=True)
@@ -288,6 +322,11 @@ class CYCLES_RENDER_PT_sampling_advanced(CyclesButtonsPanel, Panel):
col.prop(cscene, "min_transparent_bounces")
col.prop(cscene, "light_sampling_threshold", text="Light Threshold")
if cscene.progressive != 'PATH' and use_branched_path(context):
col = layout.column(align=True)
col.prop(cscene, "sample_all_lights_direct")
col.prop(cscene, "sample_all_lights_indirect")
for view_layer in scene.view_layers:
if view_layer.samples > 0:
layout.separator()
@@ -295,6 +334,62 @@ class CYCLES_RENDER_PT_sampling_advanced(CyclesButtonsPanel, Panel):
break
class CYCLES_RENDER_PT_sampling_total(CyclesButtonsPanel, Panel):
bl_label = "Total Samples"
bl_parent_id = "CYCLES_RENDER_PT_sampling"
@classmethod
def poll(cls, context):
scene = context.scene
cscene = scene.cycles
if cscene.use_square_samples:
return True
return cscene.progressive != 'PATH' and use_branched_path(context)
def draw(self, context):
layout = self.layout
cscene = context.scene.cycles
integrator = cscene.progressive
# Calculate sample values
if integrator == 'PATH':
aa = cscene.samples
if cscene.use_square_samples:
aa = aa * aa
else:
aa = cscene.aa_samples
d = cscene.diffuse_samples
g = cscene.glossy_samples
t = cscene.transmission_samples
ao = cscene.ao_samples
ml = cscene.mesh_light_samples
sss = cscene.subsurface_samples
vol = cscene.volume_samples
if cscene.use_square_samples:
aa = aa * aa
d = d * d
g = g * g
t = t * t
ao = ao * ao
ml = ml * ml
sss = sss * sss
vol = vol * vol
col = layout.column(align=True)
col.scale_y = 0.6
if integrator == 'PATH':
col.label(text="%s AA" % aa)
else:
col.label(text="%s AA, %s Diffuse, %s Glossy, %s Transmission" %
(aa, d * aa, g * aa, t * aa))
col.separator()
col.label(text="%s AO, %s Mesh Light, %s Subsurface, %s Volume" %
(ao * aa, ml * aa, sss * aa, vol * aa))
class CYCLES_RENDER_PT_subdivision(CyclesButtonsPanel, Panel):
bl_label = "Subdivision"
bl_options = {'DEFAULT_CLOSED'}
@@ -453,8 +548,6 @@ class CYCLES_RENDER_PT_light_paths_fast_gi(CyclesButtonsPanel, Panel):
layout.use_property_split = True
layout.use_property_decorate = False
layout.active = cscene.use_fast_gi
col = layout.column(align=True)
col.prop(cscene, "ao_bounces", text="Viewport Bounces")
col.prop(cscene, "ao_bounces_render", text="Render Bounces")
@@ -613,8 +706,8 @@ class CYCLES_RENDER_PT_performance_threads(CyclesButtonsPanel, Panel):
sub.prop(rd, "threads")
class CYCLES_RENDER_PT_performance_memory(CyclesButtonsPanel, Panel):
bl_label = "Memory"
class CYCLES_RENDER_PT_performance_tiles(CyclesButtonsPanel, Panel):
bl_label = "Tiles"
bl_parent_id = "CYCLES_RENDER_PT_performance"
def draw(self, context):
@@ -623,13 +716,19 @@ class CYCLES_RENDER_PT_performance_memory(CyclesButtonsPanel, Panel):
layout.use_property_decorate = False
scene = context.scene
rd = scene.render
cscene = scene.cycles
col = layout.column()
col.prop(cscene, "use_auto_tile")
sub = col.column(align=True)
sub.prop(rd, "tile_x", text="Tiles X")
sub.prop(rd, "tile_y", text="Y")
col.prop(cscene, "tile_order", text="Order")
sub = col.column()
sub.active = cscene.use_auto_tile
sub.prop(cscene, "tile_size")
sub.active = not rd.use_save_buffers and not cscene.use_adaptive_sampling
sub.prop(cscene, "use_progressive_refine")
class CYCLES_RENDER_PT_performance_acceleration_structure(CyclesButtonsPanel, Panel):
@@ -679,6 +778,7 @@ class CYCLES_RENDER_PT_performance_final_render(CyclesButtonsPanel, Panel):
col = layout.column()
col.prop(rd, "use_save_buffers")
col.prop(rd, "use_persistent_data", text="Persistent Data")
@@ -697,6 +797,7 @@ class CYCLES_RENDER_PT_performance_viewport(CyclesButtonsPanel, Panel):
col = layout.column()
col.prop(rd, "preview_pixel_size", text="Pixel Size")
col.prop(cscene, "preview_start_resolution", text="Start Pixels")
class CYCLES_RENDER_PT_filter(CyclesButtonsPanel, Panel):
@@ -717,6 +818,7 @@ class CYCLES_RENDER_PT_filter(CyclesButtonsPanel, Panel):
col = layout.column(heading="Include")
col.prop(view_layer, "use_sky", text="Environment")
col.prop(view_layer, "use_ao", text="Ambient Occlusion")
col.prop(view_layer, "use_solid", text="Surfaces")
col.prop(view_layer, "use_strand", text="Hair")
col.prop(view_layer, "use_volumes", text="Volumes")
@@ -725,9 +827,6 @@ class CYCLES_RENDER_PT_filter(CyclesButtonsPanel, Panel):
sub = col.row()
sub.prop(view_layer, "use_motion_blur", text="Motion Blur")
sub.active = rd.use_motion_blur
sub = col.row()
sub.prop(view_layer.cycles, 'use_denoising', text='Denoising')
sub.active = scene.cycles.use_denoising
class CYCLES_RENDER_PT_override(CyclesButtonsPanel, Panel):
@@ -773,7 +872,6 @@ class CYCLES_RENDER_PT_passes_data(CyclesButtonsPanel, Panel):
col.prop(view_layer, "use_pass_combined")
col.prop(view_layer, "use_pass_z")
col.prop(view_layer, "use_pass_mist")
col.prop(view_layer, "use_pass_position")
col.prop(view_layer, "use_pass_normal")
sub = col.column()
sub.active = not rd.use_motion_blur
@@ -830,7 +928,6 @@ class CYCLES_RENDER_PT_passes_light(CyclesButtonsPanel, Panel):
col.prop(view_layer, "use_pass_environment")
col.prop(view_layer, "use_pass_shadow")
col.prop(view_layer, "use_pass_ambient_occlusion", text="Ambient Occlusion")
col.prop(cycles_view_layer, "use_pass_shadow_catcher")
class CYCLES_RENDER_PT_passes_crypto(CyclesButtonsPanel, ViewLayerCryptomattePanel, Panel):
@@ -845,6 +942,70 @@ class CYCLES_RENDER_PT_passes_aov(CyclesButtonsPanel, ViewLayerAOVPanel):
bl_parent_id = "CYCLES_RENDER_PT_passes"
class CYCLES_RENDER_PT_denoising(CyclesButtonsPanel, Panel):
bl_label = "Denoising"
bl_context = "view_layer"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
cscene = context.scene.cycles
return CyclesButtonsPanel.poll(context) and cscene.use_denoising
def draw_header(self, context):
scene = context.scene
view_layer = context.view_layer
cycles_view_layer = view_layer.cycles
layout = self.layout
layout.prop(cycles_view_layer, "use_denoising", text="")
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
scene = context.scene
view_layer = context.view_layer
cycles_view_layer = view_layer.cycles
denoiser = scene.cycles.denoiser
layout.active = denoiser != 'NONE' and cycles_view_layer.use_denoising
col = layout.column()
if denoiser == 'OPTIX':
col.prop(cycles_view_layer, "denoising_optix_input_passes")
return
elif denoiser == 'OPENIMAGEDENOISE':
col.prop(cycles_view_layer, "denoising_openimagedenoise_input_passes")
return
col.prop(cycles_view_layer, "denoising_radius", text="Radius")
col = layout.column()
col.prop(cycles_view_layer, "denoising_strength", slider=True, text="Strength")
col.prop(cycles_view_layer, "denoising_feature_strength", slider=True, text="Feature Strength")
col.prop(cycles_view_layer, "denoising_relative_pca")
layout.separator()
col = layout.column()
col.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes
row = col.row(heading="Diffuse", align=True)
row.prop(cycles_view_layer, "denoising_diffuse_direct", text="Direct", toggle=True)
row.prop(cycles_view_layer, "denoising_diffuse_indirect", text="Indirect", toggle=True)
row = col.row(heading="Glossy", align=True)
row.prop(cycles_view_layer, "denoising_glossy_direct", text="Direct", toggle=True)
row.prop(cycles_view_layer, "denoising_glossy_indirect", text="Indirect", toggle=True)
row = col.row(heading="Transmission", align=True)
row.prop(cycles_view_layer, "denoising_transmission_direct", text="Direct", toggle=True)
row.prop(cycles_view_layer, "denoising_transmission_indirect", text="Indirect", toggle=True)
class CYCLES_PT_post_processing(CyclesButtonsPanel, Panel):
bl_label = "Post Processing"
bl_options = {'DEFAULT_CLOSED'}
@@ -1256,6 +1417,10 @@ class CYCLES_LIGHT_PT_light(CyclesButtonsPanel, Panel):
if not (light.type == 'AREA' and clamp.is_portal):
sub = col.column()
if use_branched_path(context):
subsub = sub.row(align=True)
subsub.active = use_sample_all_lights(context)
subsub.prop(clamp, "samples")
sub.prop(clamp, "max_bounces")
sub = col.column(align=True)
@@ -1361,6 +1526,34 @@ class CYCLES_WORLD_PT_volume(CyclesButtonsPanel, Panel):
panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
class CYCLES_WORLD_PT_ambient_occlusion(CyclesButtonsPanel, Panel):
bl_label = "Ambient Occlusion"
bl_context = "world"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
return context.world and CyclesButtonsPanel.poll(context)
def draw_header(self, context):
light = context.world.light_settings
self.layout.prop(light, "use_ambient_occlusion", text="")
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
light = context.world.light_settings
scene = context.scene
col = layout.column()
sub = col.column()
sub.active = light.use_ambient_occlusion or scene.render.use_simplify
sub.prop(light, "ao_factor", text="Factor")
col.prop(light, "distance", text="Distance")
class CYCLES_WORLD_PT_mist(CyclesButtonsPanel, Panel):
bl_label = "Mist Pass"
bl_context = "world"
@@ -1457,6 +1650,10 @@ class CYCLES_WORLD_PT_settings_surface(CyclesButtonsPanel, Panel):
subsub = sub.row(align=True)
subsub.active = cworld.sampling_method == 'MANUAL'
subsub.prop(cworld, "sample_map_resolution")
if use_branched_path(context):
subsub = sub.column(align=True)
subsub.active = use_sample_all_lights(context)
subsub.prop(cworld, "samples")
sub.prop(cworld, "max_bounces")
@@ -1480,7 +1677,8 @@ class CYCLES_WORLD_PT_settings_volume(CyclesButtonsPanel, Panel):
col = layout.column()
sub = col.column()
col.prop(cworld, "volume_sampling", text="Sampling")
sub.active = use_cpu(context)
sub.prop(cworld, "volume_sampling", text="Sampling")
col.prop(cworld, "volume_interpolation", text="Interpolation")
col.prop(cworld, "homogeneous_volume", text="Homogeneous")
sub = col.column()
@@ -1619,7 +1817,8 @@ class CYCLES_MATERIAL_PT_settings_volume(CyclesButtonsPanel, Panel):
col = layout.column()
sub = col.column()
col.prop(cmat, "volume_sampling", text="Sampling")
sub.active = use_cpu(context)
sub.prop(cmat, "volume_sampling", text="Sampling")
col.prop(cmat, "volume_interpolation", text="Interpolation")
col.prop(cmat, "homogeneous_volume", text="Homogeneous")
sub = col.column()
@@ -1646,6 +1845,9 @@ class CYCLES_RENDER_PT_bake(CyclesButtonsPanel, Panel):
cbk = scene.render.bake
rd = scene.render
if use_optix(context):
layout.label(text="Baking is performed using CUDA instead of OptiX", icon='INFO')
if rd.use_bake_multires:
layout.operator("object.bake_image", icon='RENDER_STILL')
layout.prop(rd, "use_bake_multires")
@@ -1703,6 +1905,7 @@ class CYCLES_RENDER_PT_bake_influence(CyclesButtonsPanel, Panel):
col.prop(cbk, "use_pass_diffuse")
col.prop(cbk, "use_pass_glossy")
col.prop(cbk, "use_pass_transmission")
col.prop(cbk, "use_pass_ambient_occlusion")
col.prop(cbk, "use_pass_emit")
elif cscene.bake_type in {'DIFFUSE', 'GLOSSY', 'TRANSMISSION'}:
@@ -1786,12 +1989,19 @@ class CYCLES_RENDER_PT_bake_output(CyclesButtonsPanel, Panel):
layout.prop(cbk, "use_clear", text="Clear Image")
class CYCLES_RENDER_PT_debug(CyclesDebugButtonsPanel, Panel):
class CYCLES_RENDER_PT_debug(CyclesButtonsPanel, Panel):
bl_label = "Debug"
bl_context = "render"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'CYCLES'}
@classmethod
def poll(cls, context):
prefs = bpy.context.preferences
return (CyclesButtonsPanel.poll(context)
and prefs.experimental.use_cycles_debug
and prefs.view.show_developer_ui)
def draw(self, context):
layout = self.layout
@@ -1808,18 +2018,29 @@ class CYCLES_RENDER_PT_debug(CyclesDebugButtonsPanel, Panel):
row.prop(cscene, "debug_use_cpu_avx", toggle=True)
row.prop(cscene, "debug_use_cpu_avx2", toggle=True)
col.prop(cscene, "debug_bvh_layout")
col.prop(cscene, "debug_use_cpu_split_kernel")
col.separator()
col = layout.column()
col.label(text="CUDA Flags:")
col.prop(cscene, "debug_use_cuda_adaptive_compile")
col.prop(cscene, "debug_use_cuda_split_kernel")
col.separator()
col = layout.column()
col.label(text="OptiX Flags:")
col.prop(cscene, "debug_use_optix_debug")
col.prop(cscene, "debug_optix_cuda_streams")
col.prop(cscene, "debug_optix_curves_api")
col.separator()
col = layout.column()
col.label(text="OpenCL Flags:")
col.prop(cscene, "debug_opencl_device_type", text="Device")
col.prop(cscene, "debug_use_opencl_debug", text="Debug")
col.prop(cscene, "debug_opencl_mem_limit")
col.separator()
@@ -1920,22 +2141,20 @@ class CYCLES_RENDER_PT_simplify_culling(CyclesButtonsPanel, Panel):
sub.prop(cscene, "distance_cull_margin", text="")
class CyclesShadingButtonsPanel(CyclesButtonsPanel):
class CYCLES_VIEW3D_PT_shading_render_pass(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'HEADER'
bl_label = "Render Pass"
bl_parent_id = 'VIEW3D_PT_shading'
COMPAT_ENGINES = {'CYCLES'}
@classmethod
def poll(cls, context):
return (
CyclesButtonsPanel.poll(context) and
context.engine in cls.COMPAT_ENGINES and
context.space_data.shading.type == 'RENDERED'
)
class CYCLES_VIEW3D_PT_shading_render_pass(CyclesShadingButtonsPanel, Panel):
bl_label = "Render Pass"
def draw(self, context):
shading = context.space_data.shading
@@ -1943,26 +2162,6 @@ class CYCLES_VIEW3D_PT_shading_render_pass(CyclesShadingButtonsPanel, Panel):
layout.prop(shading.cycles, "render_pass", text="")
class CYCLES_VIEW3D_PT_shading_debug(CyclesDebugButtonsPanel,
CyclesShadingButtonsPanel,
Panel):
bl_label = "Debug"
@classmethod
def poll(cls, context):
return (
CyclesDebugButtonsPanel.poll(context) and
CyclesShadingButtonsPanel.poll(context)
)
def draw(self, context):
shading = context.space_data.shading
layout = self.layout
layout.active = context.scene.cycles.use_preview_adaptive_sampling
layout.prop(shading.cycles, "show_active_pixels")
class CYCLES_VIEW3D_PT_shading_lighting(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'HEADER'
@@ -2076,13 +2275,11 @@ def get_panels():
classes = (
CYCLES_PT_sampling_presets,
CYCLES_PT_viewport_sampling_presets,
CYCLES_PT_integrator_presets,
CYCLES_RENDER_PT_sampling,
CYCLES_RENDER_PT_sampling_viewport,
CYCLES_RENDER_PT_sampling_viewport_denoise,
CYCLES_RENDER_PT_sampling_render,
CYCLES_RENDER_PT_sampling_render_denoise,
CYCLES_RENDER_PT_sampling_sub_samples,
CYCLES_RENDER_PT_sampling_adaptive,
CYCLES_RENDER_PT_sampling_denoising,
CYCLES_RENDER_PT_sampling_advanced,
CYCLES_RENDER_PT_light_paths,
CYCLES_RENDER_PT_light_paths_max_bounces,
@@ -2099,7 +2296,6 @@ classes = (
CYCLES_VIEW3D_PT_simplify_greasepencil,
CYCLES_VIEW3D_PT_shading_lighting,
CYCLES_VIEW3D_PT_shading_render_pass,
CYCLES_VIEW3D_PT_shading_debug,
CYCLES_RENDER_PT_motion_blur,
CYCLES_RENDER_PT_motion_blur_curve,
CYCLES_RENDER_PT_film,
@@ -2107,7 +2303,7 @@ classes = (
CYCLES_RENDER_PT_film_transparency,
CYCLES_RENDER_PT_performance,
CYCLES_RENDER_PT_performance_threads,
CYCLES_RENDER_PT_performance_memory,
CYCLES_RENDER_PT_performance_tiles,
CYCLES_RENDER_PT_performance_acceleration_structure,
CYCLES_RENDER_PT_performance_final_render,
CYCLES_RENDER_PT_performance_viewport,
@@ -2118,6 +2314,7 @@ classes = (
CYCLES_RENDER_PT_passes_aov,
CYCLES_RENDER_PT_filter,
CYCLES_RENDER_PT_override,
CYCLES_RENDER_PT_denoising,
CYCLES_PT_post_processing,
CYCLES_CAMERA_PT_dof,
CYCLES_CAMERA_PT_dof_aperture,
@@ -2136,6 +2333,7 @@ classes = (
CYCLES_WORLD_PT_preview,
CYCLES_WORLD_PT_surface,
CYCLES_WORLD_PT_volume,
CYCLES_WORLD_PT_ambient_occlusion,
CYCLES_WORLD_PT_mist,
CYCLES_WORLD_PT_ray_visibility,
CYCLES_WORLD_PT_settings,

View File

@@ -109,7 +109,7 @@ def do_versions(self):
library_versions.setdefault(library.version, []).append(library)
# Do versioning per library, since they might have different versions.
max_need_versioning = (3, 0, 25)
max_need_versioning = (2, 93, 7)
for version, libraries in library_versions.items():
if version > max_need_versioning:
continue
@@ -166,6 +166,10 @@ def do_versions(self):
if not cscene.is_property_set("filter_type"):
cscene.pixel_filter_type = 'GAUSSIAN'
# Tile Order
if not cscene.is_property_set("tile_order"):
cscene.tile_order = 'CENTER'
if version <= (2, 76, 10):
cscene = scene.cycles
if cscene.is_property_set("filter_type"):
@@ -182,6 +186,10 @@ def do_versions(self):
if version <= (2, 79, 0):
cscene = scene.cycles
# Default changes
if not cscene.is_property_set("aa_samples"):
cscene.aa_samples = 4
if not cscene.is_property_set("preview_aa_samples"):
cscene.preview_aa_samples = 4
if not cscene.is_property_set("blur_glossy"):
cscene.blur_glossy = 0.0
if not cscene.is_property_set("sample_clamp_indirect"):
@@ -195,6 +203,7 @@ def do_versions(self):
view_layer.use_pass_cryptomatte_material = cview_layer.get("use_pass_crypto_material", False)
view_layer.use_pass_cryptomatte_asset = cview_layer.get("use_pass_crypto_asset", False)
view_layer.pass_cryptomatte_depth = cview_layer.get("pass_crypto_depth", 6)
view_layer.use_pass_cryptomatte_accurate = cview_layer.get("pass_crypto_accurate", True)
if version <= (2, 93, 7):
if scene.render.engine == 'CYCLES':
@@ -220,35 +229,6 @@ def do_versions(self):
cscene.ao_bounces = 1
cscene.ao_bounces_render = 1
if version <= (3, 0, 25):
cscene = scene.cycles
# Default changes.
if not cscene.is_property_set("samples"):
cscene.samples = 128
if not cscene.is_property_set("preview_samples"):
cscene.preview_samples = 32
if not cscene.is_property_set("use_adaptive_sampling"):
cscene.use_adaptive_sampling = False
cscene.use_preview_adaptive_sampling = False
if not cscene.is_property_set("use_denoising"):
cscene.use_denoising = False
if not cscene.is_property_set("use_preview_denoising"):
cscene.use_preview_denoising = False
if not cscene.is_property_set("sampling_pattern"):
cscene.sampling_pattern = 'PROGRESSIVE_MUTI_JITTER'
# Removal of square samples.
cscene = scene.cycles
use_square_samples = cscene.get("use_square_samples", False)
if use_square_samples:
cscene.samples *= cscene.samples
cscene.preview_samples *= cscene.preview_samples
for layer in scene.view_layers:
layer.samples *= layer.samples
cscene["use_square_samples"] = False
# Lamps
for light in bpy.data.lights:
if light.library not in libraries:
@@ -269,6 +249,10 @@ def do_versions(self):
if version <= (2, 76, 9):
cworld = world.cycles
# World MIS Samples
if not cworld.is_property_set("samples"):
cworld.samples = 4
# World MIS Resolution
if not cworld.is_property_set("sample_map_resolution"):
cworld.sample_map_resolution = 256

View File

@@ -894,8 +894,12 @@ void BlenderSync::sync_view(BL::SpaceView3D &b_v3d,
}
}
BufferParams BlenderSync::get_buffer_params(
BL::SpaceView3D &b_v3d, BL::RegionView3D &b_rv3d, Camera *cam, int width, int height)
BufferParams BlenderSync::get_buffer_params(BL::SpaceView3D &b_v3d,
BL::RegionView3D &b_rv3d,
Camera *cam,
int width,
int height,
const bool use_denoiser)
{
BufferParams params;
bool use_border = false;
@@ -927,6 +931,11 @@ BufferParams BlenderSync::get_buffer_params(
params.height = height;
}
PassType display_pass = update_viewport_display_passes(b_v3d, params.passes);
/* Can only denoise the combined image pass */
params.denoising_data_pass = display_pass == PASS_COMBINED && use_denoiser;
return params;
}

View File

@@ -283,13 +283,10 @@ static void ExportCurveSegments(Scene *scene, Hair *hair, ParticleCurveData *CDa
return;
Attribute *attr_intercept = NULL;
Attribute *attr_length = NULL;
Attribute *attr_random = NULL;
if (hair->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT))
attr_intercept = hair->attributes.add(ATTR_STD_CURVE_INTERCEPT);
if (hair->need_attribute(scene, ATTR_STD_CURVE_LENGTH))
attr_length = hair->attributes.add(ATTR_STD_CURVE_LENGTH);
if (hair->need_attribute(scene, ATTR_STD_CURVE_RANDOM))
attr_random = hair->attributes.add(ATTR_STD_CURVE_RANDOM);
@@ -339,10 +336,6 @@ static void ExportCurveSegments(Scene *scene, Hair *hair, ParticleCurveData *CDa
num_curve_keys++;
}
if (attr_length != NULL) {
attr_length->add(CData->curve_length[curve]);
}
if (attr_random != NULL) {
attr_random->add(hash_uint2_to_float(num_curves, 0));
}
@@ -664,15 +657,11 @@ static void export_hair_curves(Scene *scene, Hair *hair, BL::Hair b_hair)
/* Add requested attributes. */
Attribute *attr_intercept = NULL;
Attribute *attr_length = NULL;
Attribute *attr_random = NULL;
if (hair->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT)) {
attr_intercept = hair->attributes.add(ATTR_STD_CURVE_INTERCEPT);
}
if (hair->need_attribute(scene, ATTR_STD_CURVE_LENGTH)) {
attr_length = hair->attributes.add(ATTR_STD_CURVE_LENGTH);
}
if (hair->need_attribute(scene, ATTR_STD_CURVE_RANDOM)) {
attr_random = hair->attributes.add(ATTR_STD_CURVE_RANDOM);
}
@@ -725,10 +714,6 @@ static void export_hair_curves(Scene *scene, Hair *hair, BL::Hair b_hair)
}
}
if (attr_length) {
attr_length->add(length);
}
/* Random number per curve. */
if (attr_random != NULL) {
attr_random->add(hash_uint2_to_float(b_curve.index(), 0));

View File

@@ -25,6 +25,7 @@ CCL_NAMESPACE_BEGIN
enum ComputeDevice {
COMPUTE_DEVICE_CPU = 0,
COMPUTE_DEVICE_CUDA = 1,
COMPUTE_DEVICE_OPENCL = 2,
COMPUTE_DEVICE_OPTIX = 3,
COMPUTE_DEVICE_NUM
@@ -67,6 +68,13 @@ DeviceInfo blender_device_info(BL::Preferences &b_preferences, BL::Scene &b_scen
device = Device::get_multi_device(devices, threads, background);
}
}
else if (get_enum(cscene, "device") == 2) {
/* Find network device. */
vector<DeviceInfo> devices = Device::available_devices(DEVICE_MASK_NETWORK);
if (!devices.empty()) {
device = devices.front();
}
}
else if (get_enum(cscene, "device") == 1) {
/* Test if we are using GPU devices. */
ComputeDevice compute_device = (ComputeDevice)get_enum(
@@ -81,6 +89,9 @@ DeviceInfo blender_device_info(BL::Preferences &b_preferences, BL::Scene &b_scen
else if (compute_device == COMPUTE_DEVICE_OPTIX) {
mask |= DEVICE_MASK_OPTIX;
}
else if (compute_device == COMPUTE_DEVICE_OPENCL) {
mask |= DEVICE_MASK_OPENCL;
}
vector<DeviceInfo> devices = Device::available_devices(mask);
/* Match device preferences and available devices. */

View File

@@ -80,9 +80,7 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
{
/* Test if we can instance or if the object is modified. */
Geometry::Type geom_type = determine_geom_type(b_ob_info, use_particle_hair);
BL::ID b_key_id = (BKE_object_is_modified(b_ob_info.real_object)) ? b_ob_info.real_object :
b_ob_info.object_data;
GeometryKey key(b_key_id.ptr.data, geom_type);
GeometryKey key(b_ob_info.object_data, geom_type);
/* Find shader indices. */
array<Node *> used_shaders = find_used_shaders(b_ob_info.iter_object);
@@ -112,7 +110,7 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
}
else {
/* Test if we need to update existing geometry. */
sync = geometry_map.update(geom, b_key_id);
sync = geometry_map.update(geom, b_ob_info.object_data);
}
if (!sync) {

View File

@@ -1,787 +0,0 @@
/*
* Copyright 2021 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "blender/blender_gpu_display.h"
#include "device/device.h"
#include "util/util_logging.h"
#include "util/util_opengl.h"
extern "C" {
struct RenderEngine;
bool RE_engine_has_render_context(struct RenderEngine *engine);
void RE_engine_render_context_enable(struct RenderEngine *engine);
void RE_engine_render_context_disable(struct RenderEngine *engine);
bool DRW_opengl_context_release();
void DRW_opengl_context_activate(bool drw_state);
void *WM_opengl_context_create();
void WM_opengl_context_activate(void *gl_context);
void WM_opengl_context_dispose(void *gl_context);
void WM_opengl_context_release(void *context);
}
CCL_NAMESPACE_BEGIN
/* --------------------------------------------------------------------
* BlenderDisplayShader.
*/
unique_ptr<BlenderDisplayShader> BlenderDisplayShader::create(BL::RenderEngine &b_engine,
BL::Scene &b_scene)
{
if (b_engine.support_display_space_shader(b_scene)) {
return make_unique<BlenderDisplaySpaceShader>(b_engine, b_scene);
}
return make_unique<BlenderFallbackDisplayShader>();
}
int BlenderDisplayShader::get_position_attrib_location()
{
if (position_attribute_location_ == -1) {
const uint shader_program = get_shader_program();
position_attribute_location_ = glGetAttribLocation(shader_program, position_attribute_name);
}
return position_attribute_location_;
}
int BlenderDisplayShader::get_tex_coord_attrib_location()
{
if (tex_coord_attribute_location_ == -1) {
const uint shader_program = get_shader_program();
tex_coord_attribute_location_ = glGetAttribLocation(shader_program, tex_coord_attribute_name);
}
return tex_coord_attribute_location_;
}
/* --------------------------------------------------------------------
* BlenderFallbackDisplayShader.
*/
/* TODO move shaders to standalone .glsl file. */
static const char *FALLBACK_VERTEX_SHADER =
"#version 330\n"
"uniform vec2 fullscreen;\n"
"in vec2 texCoord;\n"
"in vec2 pos;\n"
"out vec2 texCoord_interp;\n"
"\n"
"vec2 normalize_coordinates()\n"
"{\n"
" return (vec2(2.0) * (pos / fullscreen)) - vec2(1.0);\n"
"}\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = vec4(normalize_coordinates(), 0.0, 1.0);\n"
" texCoord_interp = texCoord;\n"
"}\n\0";
static const char *FALLBACK_FRAGMENT_SHADER =
"#version 330\n"
"uniform sampler2D image_texture;\n"
"in vec2 texCoord_interp;\n"
"out vec4 fragColor;\n"
"\n"
"void main()\n"
"{\n"
" fragColor = texture(image_texture, texCoord_interp);\n"
"}\n\0";
static void shader_print_errors(const char *task, const char *log, const char *code)
{
LOG(ERROR) << "Shader: " << task << " error:";
LOG(ERROR) << "===== shader string ====";
stringstream stream(code);
string partial;
int line = 1;
while (getline(stream, partial, '\n')) {
if (line < 10) {
LOG(ERROR) << " " << line << " " << partial;
}
else {
LOG(ERROR) << line << " " << partial;
}
line++;
}
LOG(ERROR) << log;
}
static int compile_fallback_shader(void)
{
const struct Shader {
const char *source;
const GLenum type;
} shaders[2] = {{FALLBACK_VERTEX_SHADER, GL_VERTEX_SHADER},
{FALLBACK_FRAGMENT_SHADER, GL_FRAGMENT_SHADER}};
const GLuint program = glCreateProgram();
for (int i = 0; i < 2; i++) {
const GLuint shader = glCreateShader(shaders[i].type);
string source_str = shaders[i].source;
const char *c_str = source_str.c_str();
glShaderSource(shader, 1, &c_str, NULL);
glCompileShader(shader);
GLint compile_status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
if (!compile_status) {
GLchar log[5000];
GLsizei length = 0;
glGetShaderInfoLog(shader, sizeof(log), &length, log);
shader_print_errors("compile", log, c_str);
return 0;
}
glAttachShader(program, shader);
}
/* Link output. */
glBindFragDataLocation(program, 0, "fragColor");
/* Link and error check. */
glLinkProgram(program);
/* TODO(sergey): Find a way to nicely de-duplicate the error checking. */
GLint link_status;
glGetProgramiv(program, GL_LINK_STATUS, &link_status);
if (!link_status) {
GLchar log[5000];
GLsizei length = 0;
/* TODO(sergey): Is it really program passed to glGetShaderInfoLog? */
glGetShaderInfoLog(program, sizeof(log), &length, log);
shader_print_errors("linking", log, FALLBACK_VERTEX_SHADER);
shader_print_errors("linking", log, FALLBACK_FRAGMENT_SHADER);
return 0;
}
return program;
}
void BlenderFallbackDisplayShader::bind(int width, int height)
{
create_shader_if_needed();
if (!shader_program_) {
return;
}
glUseProgram(shader_program_);
glUniform1i(image_texture_location_, 0);
glUniform2f(fullscreen_location_, width, height);
}
void BlenderFallbackDisplayShader::unbind()
{
}
uint BlenderFallbackDisplayShader::get_shader_program()
{
return shader_program_;
}
void BlenderFallbackDisplayShader::create_shader_if_needed()
{
if (shader_program_ || shader_compile_attempted_) {
return;
}
shader_compile_attempted_ = true;
shader_program_ = compile_fallback_shader();
if (!shader_program_) {
return;
}
glUseProgram(shader_program_);
image_texture_location_ = glGetUniformLocation(shader_program_, "image_texture");
if (image_texture_location_ < 0) {
LOG(ERROR) << "Shader doesn't contain the 'image_texture' uniform.";
destroy_shader();
return;
}
fullscreen_location_ = glGetUniformLocation(shader_program_, "fullscreen");
if (fullscreen_location_ < 0) {
LOG(ERROR) << "Shader doesn't contain the 'fullscreen' uniform.";
destroy_shader();
return;
}
}
void BlenderFallbackDisplayShader::destroy_shader()
{
glDeleteProgram(shader_program_);
shader_program_ = 0;
}
/* --------------------------------------------------------------------
* BlenderDisplaySpaceShader.
*/
BlenderDisplaySpaceShader::BlenderDisplaySpaceShader(BL::RenderEngine &b_engine,
BL::Scene &b_scene)
: b_engine_(b_engine), b_scene_(b_scene)
{
DCHECK(b_engine_.support_display_space_shader(b_scene_));
}
void BlenderDisplaySpaceShader::bind(int /*width*/, int /*height*/)
{
b_engine_.bind_display_space_shader(b_scene_);
}
void BlenderDisplaySpaceShader::unbind()
{
b_engine_.unbind_display_space_shader();
}
uint BlenderDisplaySpaceShader::get_shader_program()
{
if (!shader_program_) {
glGetIntegerv(GL_CURRENT_PROGRAM, reinterpret_cast<int *>(&shader_program_));
}
if (!shader_program_) {
LOG(ERROR) << "Error retrieving shader program for display space shader.";
}
return shader_program_;
}
/* --------------------------------------------------------------------
* BlenderGPUDisplay.
*/
BlenderGPUDisplay::BlenderGPUDisplay(BL::RenderEngine &b_engine, BL::Scene &b_scene)
: b_engine_(b_engine), display_shader_(BlenderDisplayShader::create(b_engine, b_scene))
{
/* Create context while on the main thread. */
gl_context_create();
}
BlenderGPUDisplay::~BlenderGPUDisplay()
{
gl_resources_destroy();
}
/* --------------------------------------------------------------------
* Update procedure.
*/
bool BlenderGPUDisplay::do_update_begin(const GPUDisplayParams &params,
int texture_width,
int texture_height)
{
/* Note that it's the responsibility of BlenderGPUDisplay to ensure updating and drawing
* the texture does not happen at the same time. This is achieved indirectly.
*
* When enabling the OpenGL context, it uses an internal mutex lock DST.gl_context_lock.
* This same lock is also held when do_draw() is called, which together ensure mutual
* exclusion.
*
* This locking is not performed at the GPU display level, because that would cause lock
* inversion. */
if (!gl_context_enable()) {
return false;
}
if (gl_render_sync_) {
glWaitSync((GLsync)gl_render_sync_, 0, GL_TIMEOUT_IGNORED);
}
if (!gl_texture_resources_ensure()) {
gl_context_disable();
return false;
}
/* Update texture dimensions if needed. */
if (texture_.width != texture_width || texture_.height != texture_height) {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 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;
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.
*
* NOTE: Allocate the PBO for the the size which will fit the final render resolution (as in,
* at a resolution divider 1. This was we don't need to recreate graphics interoperability
* objects which are costly and which are tied to the specific underlying buffer size.
* The downside of this approach is that when graphics interoperability is not used we are
* 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 size_t size_in_bytes = sizeof(half4) * buffer_width * buffer_height;
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture_.gl_pbo_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;
}
/* New content will be provided to the texture in one way or another, so mark this in a
* centralized place. */
texture_.need_update = true;
return true;
}
void BlenderGPUDisplay::do_update_end()
{
gl_upload_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
glFlush();
gl_context_disable();
}
/* --------------------------------------------------------------------
* Texture update from CPU buffer.
*/
void BlenderGPUDisplay::do_copy_pixels_to_texture(
const half4 *rgba_pixels, int texture_x, int texture_y, int pixels_width, int pixels_height)
{
/* This call copies pixels to a Pixel Buffer Object (PBO) which is much cheaper from CPU time
* point of view than to copy data directly to the OpenGL texture.
*
* The possible downside of this approach is that it might require a higher peak memory when
* doing partial updates of the texture (although, in practice even partial updates might peak
* with a full-frame buffer stored on the CPU if the GPU is currently occupied). */
half4 *mapped_rgba_pixels = map_texture_buffer();
if (!mapped_rgba_pixels) {
return;
}
if (texture_x == 0 && texture_y == 0 && pixels_width == texture_.width &&
pixels_height == texture_.height) {
const size_t size_in_bytes = sizeof(half4) * texture_.width * texture_.height;
memcpy(mapped_rgba_pixels, rgba_pixels, size_in_bytes);
}
else {
const half4 *rgba_row = rgba_pixels;
half4 *mapped_rgba_row = mapped_rgba_pixels + texture_y * texture_.width + texture_x;
for (int y = 0; y < pixels_height;
++y, rgba_row += pixels_width, mapped_rgba_row += texture_.width) {
memcpy(mapped_rgba_row, rgba_row, sizeof(half4) * pixels_width);
}
}
unmap_texture_buffer();
}
/* --------------------------------------------------------------------
* Texture buffer mapping.
*/
half4 *BlenderGPUDisplay::do_map_texture_buffer()
{
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture_.gl_pbo_id);
half4 *mapped_rgba_pixels = reinterpret_cast<half4 *>(
glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY));
if (!mapped_rgba_pixels) {
LOG(ERROR) << "Error mapping BlenderGPUDisplay 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;
}
void BlenderGPUDisplay::do_unmap_texture_buffer()
{
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
/* --------------------------------------------------------------------
* Graphics interoperability.
*/
DeviceGraphicsInteropDestination BlenderGPUDisplay::do_graphics_interop_get()
{
DeviceGraphicsInteropDestination 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;
return interop_dst;
}
void BlenderGPUDisplay::graphics_interop_activate()
{
gl_context_enable();
}
void BlenderGPUDisplay::graphics_interop_deactivate()
{
gl_context_disable();
}
/* --------------------------------------------------------------------
* Drawing.
*/
void BlenderGPUDisplay::clear()
{
texture_.need_clear = true;
}
void BlenderGPUDisplay::set_zoom(float zoom_x, float zoom_y)
{
zoom_ = make_float2(zoom_x, zoom_y);
}
void BlenderGPUDisplay::do_draw(const GPUDisplayParams &params)
{
/* See do_update_begin() for why no locking is required here. */
const bool transparent = true; // TODO(sergey): Derive this from Film.
if (texture_.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. */
return;
}
if (!gl_draw_resources_ensure()) {
return;
}
if (use_gl_context_) {
gl_context_mutex_.lock();
}
if (gl_upload_sync_) {
glWaitSync((GLsync)gl_upload_sync_, 0, GL_TIMEOUT_IGNORED);
}
if (transparent) {
glEnable(GL_BLEND);
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? */
GLuint vertex_array_object;
glGenVertexArrays(1, &vertex_array_object);
glBindVertexArray(vertex_array_object);
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));
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glDeleteVertexArrays(1, &vertex_array_object);
display_shader_->unbind();
if (transparent) {
glDisable(GL_BLEND);
}
gl_render_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
glFlush();
if (use_gl_context_) {
gl_context_mutex_.unlock();
}
}
void BlenderGPUDisplay::gl_context_create()
{
/* When rendering in viewport there is no render context available via engine.
* Check whether own context is to be created here.
*
* NOTE: If the `b_engine_`'s context is not available, we are expected to be on a main thread
* here. */
use_gl_context_ = !RE_engine_has_render_context(
reinterpret_cast<RenderEngine *>(b_engine_.ptr.data));
if (use_gl_context_) {
const bool drw_state = DRW_opengl_context_release();
gl_context_ = WM_opengl_context_create();
if (gl_context_) {
/* On Windows an old context is restored after creation, and subsequent release of context
* generates a Win32 error. Harmless for users, but annoying to have possible misleading
* error prints in the console. */
#ifndef _WIN32
WM_opengl_context_release(gl_context_);
#endif
}
else {
LOG(ERROR) << "Error creating OpenGL context.";
}
DRW_opengl_context_activate(drw_state);
}
}
bool BlenderGPUDisplay::gl_context_enable()
{
if (use_gl_context_) {
if (!gl_context_) {
return false;
}
gl_context_mutex_.lock();
WM_opengl_context_activate(gl_context_);
return true;
}
RE_engine_render_context_enable(reinterpret_cast<RenderEngine *>(b_engine_.ptr.data));
return true;
}
void BlenderGPUDisplay::gl_context_disable()
{
if (use_gl_context_) {
if (gl_context_) {
WM_opengl_context_release(gl_context_);
gl_context_mutex_.unlock();
}
return;
}
RE_engine_render_context_disable(reinterpret_cast<RenderEngine *>(b_engine_.ptr.data));
}
void BlenderGPUDisplay::gl_context_dispose()
{
if (gl_context_) {
const bool drw_state = DRW_opengl_context_release();
WM_opengl_context_activate(gl_context_);
WM_opengl_context_dispose(gl_context_);
DRW_opengl_context_activate(drw_state);
}
}
bool BlenderGPUDisplay::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 BlenderGPUDisplay::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;
}
gl_context_disable();
gl_context_dispose();
}
bool BlenderGPUDisplay::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 BlenderGPUDisplay::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 BlenderGPUDisplay::vertex_buffer_update(const GPUDisplayParams &params)
{
/* 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] = params.offset.x;
vpointer[3] = params.offset.y;
vpointer[4] = 1.0f;
vpointer[5] = 0.0f;
vpointer[6] = (float)params.size.x + params.offset.x;
vpointer[7] = params.offset.y;
vpointer[8] = 1.0f;
vpointer[9] = 1.0f;
vpointer[10] = (float)params.size.x + params.offset.x;
vpointer[11] = (float)params.size.y + params.offset.y;
vpointer[12] = 0.0f;
vpointer[13] = 1.0f;
vpointer[14] = params.offset.x;
vpointer[15] = (float)params.size.y + params.offset.y;
glUnmapBuffer(GL_ARRAY_BUFFER);
}
CCL_NAMESPACE_END

View File

@@ -1,215 +0,0 @@
/*
* Copyright 2021 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <atomic>
#include "MEM_guardedalloc.h"
#include "RNA_blender_cpp.h"
#include "render/gpu_display.h"
#include "util/util_unique_ptr.h"
CCL_NAMESPACE_BEGIN
/* Base class of shader used for GPU display rendering. */
class BlenderDisplayShader {
public:
static constexpr const char *position_attribute_name = "pos";
static constexpr const char *tex_coord_attribute_name = "texCoord";
/* Create shader implementation suitable for the given render engine and scene configuration. */
static unique_ptr<BlenderDisplayShader> create(BL::RenderEngine &b_engine, BL::Scene &b_scene);
BlenderDisplayShader() = default;
virtual ~BlenderDisplayShader() = default;
virtual void bind(int width, int height) = 0;
virtual void unbind() = 0;
/* Get attribute location for position and texture coordinate respectively.
* NOTE: The shader needs to be bound to have access to those. */
virtual int get_position_attrib_location();
virtual int get_tex_coord_attrib_location();
protected:
/* Get program of this display shader.
* NOTE: The shader needs to be bound to have access to this. */
virtual uint get_shader_program() = 0;
/* Cached values of various OpenGL resources. */
int position_attribute_location_ = -1;
int tex_coord_attribute_location_ = -1;
};
/* Implementation of display rendering shader used in the case when render engine does not support
* display space shader. */
class BlenderFallbackDisplayShader : public BlenderDisplayShader {
public:
virtual void bind(int width, int height) override;
virtual void unbind() override;
protected:
virtual uint get_shader_program() override;
void create_shader_if_needed();
void destroy_shader();
uint shader_program_ = 0;
int image_texture_location_ = -1;
int fullscreen_location_ = -1;
/* Shader compilation attempted. Which means, that if the shader program is 0 then compilation or
* linking has failed. Do not attempt to re-compile the shader. */
bool shader_compile_attempted_ = false;
};
class BlenderDisplaySpaceShader : public BlenderDisplayShader {
public:
BlenderDisplaySpaceShader(BL::RenderEngine &b_engine, BL::Scene &b_scene);
virtual void bind(int width, int height) override;
virtual void unbind() override;
protected:
virtual uint get_shader_program() override;
BL::RenderEngine b_engine_;
BL::Scene &b_scene_;
/* Cached values of various OpenGL resources. */
uint shader_program_ = 0;
};
/* GPU display implementation which is specific for Blender viewport integration. */
class BlenderGPUDisplay : public GPUDisplay {
public:
BlenderGPUDisplay(BL::RenderEngine &b_engine, BL::Scene &b_scene);
~BlenderGPUDisplay();
virtual void graphics_interop_activate() override;
virtual void graphics_interop_deactivate() override;
virtual void clear() override;
void set_zoom(float zoom_x, float zoom_y);
protected:
virtual bool do_update_begin(const GPUDisplayParams &params,
int texture_width,
int texture_height) override;
virtual void do_update_end() override;
virtual void do_copy_pixels_to_texture(const half4 *rgba_pixels,
int texture_x,
int texture_y,
int pixels_width,
int pixels_height) override;
virtual void do_draw(const GPUDisplayParams &params) override;
virtual half4 *do_map_texture_buffer() override;
virtual void do_unmap_texture_buffer() override;
virtual DeviceGraphicsInteropDestination do_graphics_interop_get() 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 GPUDisplayParams &params);
BL::RenderEngine b_engine_;
/* OpenGL context which is used the render engine doesn't have its own. */
void *gl_context_ = nullptr;
/* The when Blender RenderEngine side context is not available and the GPUDisplay is to create
* its own context. */
bool use_gl_context_ = false;
/* 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;
} texture_;
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;
void *gl_render_sync_ = nullptr;
void *gl_upload_sync_ = nullptr;
float2 zoom_ = make_float2(1.0f, 1.0f);
};
CCL_NAMESPACE_END

View File

@@ -125,10 +125,17 @@ void BlenderSync::sync_light(BL::Object &b_parent,
light->set_shader(static_cast<Shader *>(used_shaders[0]));
/* shadow */
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
PointerRNA clight = RNA_pointer_get(&b_light.ptr, "cycles");
light->set_cast_shadow(get_boolean(clight, "cast_shadow"));
light->set_use_mis(get_boolean(clight, "use_multiple_importance_sampling"));
int samples = get_int(clight, "samples");
if (get_boolean(cscene, "use_square_samples"))
light->set_samples(samples * samples);
else
light->set_samples(samples);
light->set_max_bounces(get_int(clight, "max_bounces"));
if (b_ob_info.real_object != b_ob_info.iter_object) {
@@ -148,12 +155,10 @@ void BlenderSync::sync_light(BL::Object &b_parent,
/* visibility */
uint visibility = object_ray_visibility(b_ob_info.real_object);
light->set_use_camera((visibility & PATH_RAY_CAMERA) != 0);
light->set_use_diffuse((visibility & PATH_RAY_DIFFUSE) != 0);
light->set_use_glossy((visibility & PATH_RAY_GLOSSY) != 0);
light->set_use_transmission((visibility & PATH_RAY_TRANSMIT) != 0);
light->set_use_scatter((visibility & PATH_RAY_VOLUME_SCATTER) != 0);
light->set_is_shadow_catcher(b_ob_info.real_object.is_shadow_catcher());
/* tag */
light->tag_update(scene);
@@ -164,6 +169,7 @@ void BlenderSync::sync_background_light(BL::SpaceView3D &b_v3d, bool use_portal)
BL::World b_world = b_scene.world();
if (b_world) {
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles");
enum SamplingMethod { SAMPLING_NONE = 0, SAMPLING_AUTOMATIC, SAMPLING_MANUAL, SAMPLING_NUM };
@@ -191,6 +197,12 @@ void BlenderSync::sync_background_light(BL::SpaceView3D &b_v3d, bool use_portal)
/* force enable light again when world is resynced */
light->set_is_enabled(true);
int samples = get_int(cworld, "samples");
if (get_boolean(cscene, "use_square_samples"))
light->set_samples(samples * samples);
else
light->set_samples(samples);
light->tag_update(scene);
light_map.set_recalc(b_world);
}
@@ -199,7 +211,7 @@ void BlenderSync::sync_background_light(BL::SpaceView3D &b_v3d, bool use_portal)
world_map = b_world.ptr.data;
world_recalc = false;
viewport_parameters = BlenderViewportParameters(b_v3d, use_developer_ui);
viewport_parameters = BlenderViewportParameters(b_v3d);
}
CCL_NAMESPACE_END

View File

@@ -568,7 +568,7 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
/* object loop */
bool cancel = false;
bool use_portal = false;
const bool show_lights = BlenderViewportParameters(b_v3d, use_developer_ui).use_scene_lights;
const bool show_lights = BlenderViewportParameters(b_v3d).use_scene_lights;
BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval();
BL::Depsgraph::object_instances_iterator b_instance_iter;

View File

@@ -45,6 +45,10 @@
# include <OSL/oslquery.h>
#endif
#ifdef WITH_OPENCL
# include "device/device_intern.h"
#endif
CCL_NAMESPACE_BEGIN
namespace {
@@ -68,10 +72,12 @@ PyObject *pyunicode_from_string(const char *str)
/* Synchronize debug flags from a given Blender scene.
* Return truth when device list needs invalidation.
*/
static void debug_flags_sync_from_scene(BL::Scene b_scene)
bool debug_flags_sync_from_scene(BL::Scene b_scene)
{
DebugFlagsRef flags = DebugFlags();
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
/* Backup some settings for comparison. */
DebugFlags::OpenCL::DeviceType opencl_device_type = flags.opencl.device_type;
/* Synchronize shared flags. */
flags.viewport_static_bvh = get_enum(cscene, "debug_bvh_type");
/* Synchronize CPU flags. */
@@ -81,19 +87,50 @@ static void debug_flags_sync_from_scene(BL::Scene b_scene)
flags.cpu.sse3 = get_boolean(cscene, "debug_use_cpu_sse3");
flags.cpu.sse2 = get_boolean(cscene, "debug_use_cpu_sse2");
flags.cpu.bvh_layout = (BVHLayout)get_enum(cscene, "debug_bvh_layout");
flags.cpu.split_kernel = get_boolean(cscene, "debug_use_cpu_split_kernel");
/* Synchronize CUDA flags. */
flags.cuda.adaptive_compile = get_boolean(cscene, "debug_use_cuda_adaptive_compile");
flags.cuda.split_kernel = get_boolean(cscene, "debug_use_cuda_split_kernel");
/* Synchronize OptiX flags. */
flags.optix.use_debug = get_boolean(cscene, "debug_use_optix_debug");
flags.optix.cuda_streams = get_int(cscene, "debug_optix_cuda_streams");
flags.optix.curves_api = get_boolean(cscene, "debug_optix_curves_api");
/* Synchronize OpenCL device type. */
switch (get_enum(cscene, "debug_opencl_device_type")) {
case 0:
flags.opencl.device_type = DebugFlags::OpenCL::DEVICE_NONE;
break;
case 1:
flags.opencl.device_type = DebugFlags::OpenCL::DEVICE_ALL;
break;
case 2:
flags.opencl.device_type = DebugFlags::OpenCL::DEVICE_DEFAULT;
break;
case 3:
flags.opencl.device_type = DebugFlags::OpenCL::DEVICE_CPU;
break;
case 4:
flags.opencl.device_type = DebugFlags::OpenCL::DEVICE_GPU;
break;
case 5:
flags.opencl.device_type = DebugFlags::OpenCL::DEVICE_ACCELERATOR;
break;
}
/* Synchronize other OpenCL flags. */
flags.opencl.debug = get_boolean(cscene, "debug_use_opencl_debug");
flags.opencl.mem_limit = ((size_t)get_int(cscene, "debug_opencl_mem_limit")) * 1024 * 1024;
return flags.opencl.device_type != opencl_device_type;
}
/* Reset debug flags to default values.
* Return truth when device list needs invalidation.
*/
static void debug_flags_reset()
bool debug_flags_reset()
{
DebugFlagsRef flags = DebugFlags();
/* Backup some settings for comparison. */
DebugFlags::OpenCL::DeviceType opencl_device_type = flags.opencl.device_type;
flags.reset();
return flags.opencl.device_type != opencl_device_type;
}
} /* namespace */
@@ -138,20 +175,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)) {
return nullptr;
if (!PyArg_ParseTuple(args, "OOi", &path, &user_path, &headless)) {
return NULL;
}
PyObject *path_coerce = nullptr, *user_path_coerce = nullptr, *temp_path_coerce = nullptr;
PyObject *path_coerce = NULL, *user_path_coerce = NULL;
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;
@@ -264,50 +299,6 @@ static PyObject *render_func(PyObject * /*self*/, PyObject *args)
Py_RETURN_NONE;
}
static PyObject *render_frame_finish_func(PyObject * /*self*/, PyObject *args)
{
PyObject *pysession;
if (!PyArg_ParseTuple(args, "O", &pysession)) {
return nullptr;
}
BlenderSession *session = (BlenderSession *)PyLong_AsVoidPtr(pysession);
/* Allow Blender to execute other Python scripts. */
python_thread_state_save(&session->python_thread_state);
session->render_frame_finish();
python_thread_state_restore(&session->python_thread_state);
Py_RETURN_NONE;
}
static PyObject *draw_func(PyObject * /*self*/, PyObject *args)
{
PyObject *py_session, *py_graph, *py_screen, *py_space_image;
if (!PyArg_ParseTuple(args, "OOOO", &py_session, &py_graph, &py_screen, &py_space_image)) {
return nullptr;
}
BlenderSession *session = (BlenderSession *)PyLong_AsVoidPtr(py_session);
ID *b_screen = (ID *)PyLong_AsVoidPtr(py_screen);
PointerRNA b_space_image_ptr;
RNA_pointer_create(b_screen,
&RNA_SpaceImageEditor,
pylong_as_voidptr_typesafe(py_space_image),
&b_space_image_ptr);
BL::SpaceImageEditor b_space_image(b_space_image_ptr);
session->draw(b_space_image);
Py_RETURN_NONE;
}
/* pixel_array and result passed as pointers */
static PyObject *bake_func(PyObject * /*self*/, PyObject *args)
{
@@ -345,7 +336,7 @@ static PyObject *bake_func(PyObject * /*self*/, PyObject *args)
Py_RETURN_NONE;
}
static PyObject *view_draw_func(PyObject * /*self*/, PyObject *args)
static PyObject *draw_func(PyObject * /*self*/, PyObject *args)
{
PyObject *pysession, *pygraph, *pyv3d, *pyrv3d;
@@ -359,7 +350,7 @@ static PyObject *view_draw_func(PyObject * /*self*/, PyObject *args)
int viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
session->view_draw(viewport[2], viewport[3]);
session->draw(viewport[2], viewport[3]);
}
Py_RETURN_NONE;
@@ -706,6 +697,40 @@ static PyObject *system_info_func(PyObject * /*self*/, PyObject * /*value*/)
return pyunicode_from_string(system_info.c_str());
}
#ifdef WITH_OPENCL
static PyObject *opencl_disable_func(PyObject * /*self*/, PyObject * /*value*/)
{
VLOG(2) << "Disabling OpenCL platform.";
DebugFlags().opencl.device_type = DebugFlags::OpenCL::DEVICE_NONE;
Py_RETURN_NONE;
}
static PyObject *opencl_compile_func(PyObject * /*self*/, PyObject *args)
{
PyObject *sequence = PySequence_Fast(args, "Arguments must be a sequence");
if (sequence == NULL) {
Py_RETURN_FALSE;
}
vector<string> parameters;
for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(sequence); i++) {
PyObject *item = PySequence_Fast_GET_ITEM(sequence, i);
PyObject *item_as_string = PyObject_Str(item);
const char *parameter_string = PyUnicode_AsUTF8(item_as_string);
parameters.push_back(parameter_string);
Py_DECREF(item_as_string);
}
Py_DECREF(sequence);
if (device_opencl_compile_kernel(parameters)) {
Py_RETURN_TRUE;
}
else {
Py_RETURN_FALSE;
}
}
#endif
static bool image_parse_filepaths(PyObject *pyfilepaths, vector<string> &filepaths)
{
if (PyUnicode_Check(pyfilepaths)) {
@@ -737,10 +762,6 @@ 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};
PyObject *pypreferences, *pyscene, *pyviewlayer;
@@ -814,7 +835,7 @@ static PyObject *denoise_func(PyObject * /*self*/, PyObject *args, PyObject *key
}
/* Create denoiser. */
DenoiserPipeline denoiser(device);
Denoiser denoiser(device);
denoiser.params = params;
denoiser.input = input;
denoiser.output = output;
@@ -831,7 +852,6 @@ static PyObject *denoise_func(PyObject * /*self*/, PyObject *args, PyObject *key
PyErr_SetString(PyExc_ValueError, denoiser.error.c_str());
return NULL;
}
#endif
Py_RETURN_NONE;
}
@@ -883,7 +903,10 @@ static PyObject *debug_flags_update_func(PyObject * /*self*/, PyObject *args)
RNA_id_pointer_create((ID *)PyLong_AsVoidPtr(pyscene), &sceneptr);
BL::Scene b_scene(sceneptr);
debug_flags_sync_from_scene(b_scene);
if (debug_flags_sync_from_scene(b_scene)) {
VLOG(2) << "Tagging device list for update.";
Device::tag_update();
}
VLOG(2) << "Debug flags set to:\n" << DebugFlags();
@@ -894,7 +917,10 @@ static PyObject *debug_flags_update_func(PyObject * /*self*/, PyObject *args)
static PyObject *debug_flags_reset_func(PyObject * /*self*/, PyObject * /*args*/)
{
debug_flags_reset();
if (debug_flags_reset()) {
VLOG(2) << "Tagging device list for update.";
Device::tag_update();
}
if (debug_flags_set) {
VLOG(2) << "Debug flags reset to:\n" << DebugFlags();
debug_flags_set = false;
@@ -902,6 +928,84 @@ static PyObject *debug_flags_reset_func(PyObject * /*self*/, PyObject * /*args*/
Py_RETURN_NONE;
}
static PyObject *set_resumable_chunk_func(PyObject * /*self*/, PyObject *args)
{
int num_resumable_chunks, current_resumable_chunk;
if (!PyArg_ParseTuple(args, "ii", &num_resumable_chunks, &current_resumable_chunk)) {
Py_RETURN_NONE;
}
if (num_resumable_chunks <= 0) {
fprintf(stderr, "Cycles: Bad value for number of resumable chunks.\n");
abort();
Py_RETURN_NONE;
}
if (current_resumable_chunk < 1 || current_resumable_chunk > num_resumable_chunks) {
fprintf(stderr, "Cycles: Bad value for current resumable chunk number.\n");
abort();
Py_RETURN_NONE;
}
VLOG(1) << "Initialized resumable render: "
<< "num_resumable_chunks=" << num_resumable_chunks << ", "
<< "current_resumable_chunk=" << current_resumable_chunk;
BlenderSession::num_resumable_chunks = num_resumable_chunks;
BlenderSession::current_resumable_chunk = current_resumable_chunk;
printf("Cycles: Will render chunk %d of %d\n", current_resumable_chunk, num_resumable_chunks);
Py_RETURN_NONE;
}
static PyObject *set_resumable_chunk_range_func(PyObject * /*self*/, PyObject *args)
{
int num_chunks, start_chunk, end_chunk;
if (!PyArg_ParseTuple(args, "iii", &num_chunks, &start_chunk, &end_chunk)) {
Py_RETURN_NONE;
}
if (num_chunks <= 0) {
fprintf(stderr, "Cycles: Bad value for number of resumable chunks.\n");
abort();
Py_RETURN_NONE;
}
if (start_chunk < 1 || start_chunk > num_chunks) {
fprintf(stderr, "Cycles: Bad value for start chunk number.\n");
abort();
Py_RETURN_NONE;
}
if (end_chunk < 1 || end_chunk > num_chunks) {
fprintf(stderr, "Cycles: Bad value for start chunk number.\n");
abort();
Py_RETURN_NONE;
}
if (start_chunk > end_chunk) {
fprintf(stderr, "Cycles: End chunk should be higher than start one.\n");
abort();
Py_RETURN_NONE;
}
VLOG(1) << "Initialized resumable render: "
<< "num_resumable_chunks=" << num_chunks << ", "
<< "start_resumable_chunk=" << start_chunk << "end_resumable_chunk=" << end_chunk;
BlenderSession::num_resumable_chunks = num_chunks;
BlenderSession::start_resumable_chunk = start_chunk;
BlenderSession::end_resumable_chunk = end_chunk;
printf("Cycles: Will render chunks %d to %d of %d\n", start_chunk, end_chunk, num_chunks);
Py_RETURN_NONE;
}
static PyObject *clear_resumable_chunk_func(PyObject * /*self*/, PyObject * /*value*/)
{
VLOG(1) << "Clear resumable render";
BlenderSession::num_resumable_chunks = 0;
BlenderSession::current_resumable_chunk = 0;
Py_RETURN_NONE;
}
static PyObject *enable_print_stats_func(PyObject * /*self*/, PyObject * /*args*/)
{
BlenderSession::print_render_stats = true;
@@ -911,14 +1015,16 @@ static PyObject *enable_print_stats_func(PyObject * /*self*/, PyObject * /*args*
static PyObject *get_device_types_func(PyObject * /*self*/, PyObject * /*args*/)
{
vector<DeviceType> device_types = Device::available_types();
bool has_cuda = false, has_optix = false;
bool has_cuda = false, has_optix = false, has_opencl = false;
foreach (DeviceType device_type, device_types) {
has_cuda |= (device_type == DEVICE_CUDA);
has_optix |= (device_type == DEVICE_OPTIX);
has_opencl |= (device_type == DEVICE_OPENCL);
}
PyObject *list = PyTuple_New(2);
PyObject *list = PyTuple_New(3);
PyTuple_SET_ITEM(list, 0, PyBool_FromLong(has_cuda));
PyTuple_SET_ITEM(list, 1, PyBool_FromLong(has_optix));
PyTuple_SET_ITEM(list, 2, PyBool_FromLong(has_opencl));
return list;
}
@@ -938,6 +1044,9 @@ static PyObject *set_device_override_func(PyObject * /*self*/, PyObject *arg)
if (override == "CPU") {
BlenderSession::device_override = DEVICE_MASK_CPU;
}
else if (override == "OPENCL") {
BlenderSession::device_override = DEVICE_MASK_OPENCL;
}
else if (override == "CUDA") {
BlenderSession::device_override = DEVICE_MASK_CUDA;
}
@@ -963,10 +1072,8 @@ static PyMethodDef methods[] = {
{"create", create_func, METH_VARARGS, ""},
{"free", free_func, METH_O, ""},
{"render", render_func, METH_VARARGS, ""},
{"render_frame_finish", render_frame_finish_func, METH_VARARGS, ""},
{"draw", draw_func, METH_VARARGS, ""},
{"bake", bake_func, METH_VARARGS, ""},
{"view_draw", view_draw_func, METH_VARARGS, ""},
{"draw", draw_func, METH_VARARGS, ""},
{"sync", sync_func, METH_VARARGS, ""},
{"reset", reset_func, METH_VARARGS, ""},
#ifdef WITH_OSL
@@ -975,6 +1082,10 @@ static PyMethodDef methods[] = {
#endif
{"available_devices", available_devices_func, METH_VARARGS, ""},
{"system_info", system_info_func, METH_NOARGS, ""},
#ifdef WITH_OPENCL
{"opencl_disable", opencl_disable_func, METH_NOARGS, ""},
{"opencl_compile", opencl_compile_func, METH_VARARGS, ""},
#endif
/* Standalone denoising */
{"denoise", (PyCFunction)denoise_func, METH_VARARGS | METH_KEYWORDS, ""},
@@ -987,6 +1098,11 @@ static PyMethodDef methods[] = {
/* Statistics. */
{"enable_print_stats", enable_print_stats_func, METH_NOARGS, ""},
/* Resumable render */
{"set_resumable_chunk", set_resumable_chunk_func, METH_VARARGS, ""},
{"set_resumable_chunk_range", set_resumable_chunk_range_func, METH_VARARGS, ""},
{"clear_resumable_chunk", clear_resumable_chunk_func, METH_NOARGS, ""},
/* Compute Device selection */
{"get_device_types", get_device_types_func, METH_VARARGS, ""},
{"set_device_override", set_device_override_func, METH_O, ""},
@@ -1037,6 +1153,14 @@ void *CCL_python_module_init()
PyModule_AddStringConstant(mod, "osl_version_string", "unknown");
#endif
#ifdef WITH_NETWORK
PyModule_AddObject(mod, "with_network", Py_True);
Py_INCREF(Py_True);
#else /* WITH_NETWORK */
PyModule_AddObject(mod, "with_network", Py_False);
Py_INCREF(Py_False);
#endif /* WITH_NETWORK */
#ifdef WITH_EMBREE
PyModule_AddObject(mod, "with_embree", Py_True);
Py_INCREF(Py_True);

File diff suppressed because it is too large Load Diff

View File

@@ -29,11 +29,12 @@
CCL_NAMESPACE_BEGIN
class BlenderGPUDisplay;
class BlenderSync;
class ImageMetaData;
class Scene;
class Session;
class RenderBuffers;
class RenderTile;
class BlenderSession {
public:
@@ -61,8 +62,6 @@ class BlenderSession {
/* offline render */
void render(BL::Depsgraph &b_depsgraph);
void render_frame_finish();
void bake(BL::Depsgraph &b_depsgrah,
BL::Object &b_object,
const string &pass_type,
@@ -70,29 +69,24 @@ class BlenderSession {
const int bake_width,
const int bake_height);
void write_render_result(BL::RenderLayer &b_rlay);
void write_render_tile();
void update_render_tile();
void full_buffer_written(string_view filename);
void write_render_result(BL::RenderLayer &b_rlay, RenderTile &rtile);
void write_render_tile(RenderTile &rtile);
void read_render_tile(RenderTile &rtile);
/* update functions are used to update display buffer only after sample was rendered
* only needed for better visual feedback */
void update_render_result(BL::RenderLayer &b_rlay);
/* read functions for baking input */
void read_render_tile();
void update_render_result(BL::RenderLayer &b_rlay, RenderTile &rtile);
void update_render_tile(RenderTile &rtile, bool highlight);
/* interactive updates */
void synchronize(BL::Depsgraph &b_depsgraph);
/* drawing */
void draw(BL::SpaceImageEditor &space_image);
void view_draw(int w, int h);
bool draw(int w, int h);
void tag_redraw();
void tag_update();
void get_status(string &status, string &substatus);
void get_kernel_status(string &kernel_status);
void get_progress(float &progress, double &total_time, double &render_time);
void test_cancel();
void update_status_progress();
@@ -129,8 +123,6 @@ class BlenderSession {
void *python_thread_state;
bool use_developer_ui;
/* Global state which is common for all render sessions created from Blender.
* Usually denotes command line arguments.
*/
@@ -142,28 +134,41 @@ class BlenderSession {
*/
static bool headless;
/* ** Resumable render ** */
/* Overall number of chunks in which the sample range is to be divided. */
static int num_resumable_chunks;
/* Current resumable chunk index to render. */
static int current_resumable_chunk;
/* Alternative to single-chunk rendering to render a range of chunks. */
static int start_resumable_chunk;
static int end_resumable_chunk;
static bool print_render_stats;
protected:
void stamp_view_layer_metadata(Scene *scene, const string &view_layer_name);
void do_write_update_render_result(BL::RenderLayer &b_rlay,
RenderTile &rtile,
bool do_update_only);
void do_write_update_render_tile(RenderTile &rtile,
bool do_update_only,
bool do_read_only,
bool highlight);
void builtin_images_load();
/* Update tile manager to reflect resumable render settings. */
void update_resumable_tile_manager(int num_samples);
/* Is used after each render layer synchronization is done with the goal
* of freeing render engine data which is held from Blender side (for
* example, dependency graph).
*/
void free_blender_memory_if_possible();
struct {
thread_mutex mutex;
int last_pass_index = -1;
} draw_state_;
/* NOTE: The BlenderSession references the GPU display. */
BlenderGPUDisplay *gpu_display_ = nullptr;
vector<string> full_buffer_files_;
};
CCL_NAMESPACE_END

View File

@@ -17,7 +17,6 @@
#include "render/background.h"
#include "render/colorspace.h"
#include "render/graph.h"
#include "render/integrator.h"
#include "render/light.h"
#include "render/nodes.h"
#include "render/osl.h"
@@ -476,11 +475,17 @@ static ShaderNode *add_node(Scene *scene,
SubsurfaceScatteringNode *subsurface = graph->create_node<SubsurfaceScatteringNode>();
switch (b_subsurface_node.falloff()) {
case BL::ShaderNodeSubsurfaceScattering::falloff_RANDOM_WALK_FIXED_RADIUS:
subsurface->set_method(CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID);
case BL::ShaderNodeSubsurfaceScattering::falloff_CUBIC:
subsurface->set_falloff(CLOSURE_BSSRDF_CUBIC_ID);
break;
case BL::ShaderNodeSubsurfaceScattering::falloff_GAUSSIAN:
subsurface->set_falloff(CLOSURE_BSSRDF_GAUSSIAN_ID);
break;
case BL::ShaderNodeSubsurfaceScattering::falloff_BURLEY:
subsurface->set_falloff(CLOSURE_BSSRDF_BURLEY_ID);
break;
case BL::ShaderNodeSubsurfaceScattering::falloff_RANDOM_WALK:
subsurface->set_method(CLOSURE_BSSRDF_RANDOM_WALK_ID);
subsurface->set_falloff(CLOSURE_BSSRDF_RANDOM_WALK_ID);
break;
}
@@ -592,11 +597,11 @@ static ShaderNode *add_node(Scene *scene,
break;
}
switch (b_principled_node.subsurface_method()) {
case BL::ShaderNodeBsdfPrincipled::subsurface_method_RANDOM_WALK_FIXED_RADIUS:
principled->set_subsurface_method(CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID);
case BL::ShaderNodeBsdfPrincipled::subsurface_method_BURLEY:
principled->set_subsurface_method(CLOSURE_BSSRDF_PRINCIPLED_ID);
break;
case BL::ShaderNodeBsdfPrincipled::subsurface_method_RANDOM_WALK:
principled->set_subsurface_method(CLOSURE_BSSRDF_RANDOM_WALK_ID);
principled->set_subsurface_method(CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID);
break;
}
node = principled;
@@ -1355,11 +1360,10 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, bool update_all)
{
Background *background = scene->background;
Integrator *integrator = scene->integrator;
BL::World b_world = b_scene.world();
BlenderViewportParameters new_viewport_parameters(b_v3d, use_developer_ui);
BlenderViewportParameters new_viewport_parameters(b_v3d);
if (world_recalc || update_all || b_world.ptr.data != world_map ||
viewport_parameters.shader_modified(new_viewport_parameters)) {
@@ -1451,8 +1455,9 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
/* AO */
BL::WorldLighting b_light = b_world.light_settings();
integrator->set_ao_factor(b_light.ao_factor());
integrator->set_ao_distance(b_light.distance());
background->set_use_ao(b_light.use_ambient_occlusion());
background->set_ao_factor(b_light.ao_factor());
background->set_ao_distance(b_light.distance());
/* visibility */
PointerRNA cvisibility = RNA_pointer_get(&b_world.ptr, "cycles_visibility");
@@ -1467,8 +1472,9 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
background->set_visibility(visibility);
}
else {
integrator->set_ao_factor(1.0f);
integrator->set_ao_distance(10.0f);
background->set_use_ao(false);
background->set_ao_factor(0.0f);
background->set_ao_distance(FLT_MAX);
}
shader->set_graph(graph);
@@ -1490,6 +1496,7 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
background->set_use_shader(view_layer.use_background_shader ||
viewport_parameters.use_custom_shader());
background->set_use_ao(background->get_use_ao() && view_layer.use_background_ao);
background->tag_update(scene);
}

View File

@@ -53,7 +53,6 @@ BlenderSync::BlenderSync(BL::RenderEngine &b_engine,
BL::Scene &b_scene,
Scene *scene,
bool preview,
bool use_developer_ui,
Progress &progress)
: b_engine(b_engine),
b_data(b_data),
@@ -69,7 +68,6 @@ BlenderSync::BlenderSync(BL::RenderEngine &b_engine,
scene(scene),
preview(preview),
experimental(false),
use_developer_ui(use_developer_ui),
dicing_rate(1.0f),
max_subdivisions(12),
progress(progress),
@@ -226,7 +224,7 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
}
if (b_v3d) {
BlenderViewportParameters new_viewport_parameters(b_v3d, use_developer_ui);
BlenderViewportParameters new_viewport_parameters(b_v3d);
if (viewport_parameters.shader_modified(new_viewport_parameters)) {
world_recalc = true;
@@ -253,13 +251,9 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render,
BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval();
/* TODO(sergey): This feels weak to pass view layer to the integrator, and even weaker to have an
* implicit check on whether it is a background render or not. What is the nicer thing here? */
const bool background = !b_v3d;
sync_view_layer(b_view_layer);
sync_integrator(b_view_layer, background);
sync_film(b_view_layer, b_v3d);
sync_integrator();
sync_film(b_v3d);
sync_shaders(b_depsgraph, b_v3d);
sync_images();
@@ -286,7 +280,7 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render,
/* Integrator */
void BlenderSync::sync_integrator(BL::ViewLayer &b_view_layer, bool background)
void BlenderSync::sync_integrator()
{
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
@@ -334,24 +328,59 @@ void BlenderSync::sync_integrator(BL::ViewLayer &b_view_layer, bool background)
integrator->set_motion_blur(view_layer.use_motion_blur);
}
integrator->set_method((Integrator::Method)get_enum(
cscene, "progressive", Integrator::NUM_METHODS, Integrator::PATH));
integrator->set_sample_all_lights_direct(get_boolean(cscene, "sample_all_lights_direct"));
integrator->set_sample_all_lights_indirect(get_boolean(cscene, "sample_all_lights_indirect"));
integrator->set_light_sampling_threshold(get_float(cscene, "light_sampling_threshold"));
SamplingPattern sampling_pattern = (SamplingPattern)get_enum(
cscene, "sampling_pattern", SAMPLING_NUM_PATTERNS, SAMPLING_PATTERN_SOBOL);
integrator->set_sampling_pattern(sampling_pattern);
if (preview) {
integrator->set_use_adaptive_sampling(
RNA_boolean_get(&cscene, "use_preview_adaptive_sampling"));
integrator->set_adaptive_threshold(get_float(cscene, "preview_adaptive_threshold"));
integrator->set_adaptive_min_samples(get_int(cscene, "preview_adaptive_min_samples"));
int adaptive_min_samples = INT_MAX;
if (RNA_boolean_get(&cscene, "use_adaptive_sampling")) {
sampling_pattern = SAMPLING_PATTERN_PMJ;
adaptive_min_samples = get_int(cscene, "adaptive_min_samples");
integrator->set_adaptive_threshold(get_float(cscene, "adaptive_threshold"));
}
else {
integrator->set_use_adaptive_sampling(RNA_boolean_get(&cscene, "use_adaptive_sampling"));
integrator->set_adaptive_threshold(get_float(cscene, "adaptive_threshold"));
integrator->set_adaptive_min_samples(get_int(cscene, "adaptive_min_samples"));
integrator->set_adaptive_threshold(0.0f);
}
integrator->set_sampling_pattern(sampling_pattern);
int diffuse_samples = get_int(cscene, "diffuse_samples");
int glossy_samples = get_int(cscene, "glossy_samples");
int transmission_samples = get_int(cscene, "transmission_samples");
int ao_samples = get_int(cscene, "ao_samples");
int mesh_light_samples = get_int(cscene, "mesh_light_samples");
int subsurface_samples = get_int(cscene, "subsurface_samples");
int volume_samples = get_int(cscene, "volume_samples");
if (get_boolean(cscene, "use_square_samples")) {
integrator->set_diffuse_samples(diffuse_samples * diffuse_samples);
integrator->set_glossy_samples(glossy_samples * glossy_samples);
integrator->set_transmission_samples(transmission_samples * transmission_samples);
integrator->set_ao_samples(ao_samples * ao_samples);
integrator->set_mesh_light_samples(mesh_light_samples * mesh_light_samples);
integrator->set_subsurface_samples(subsurface_samples * subsurface_samples);
integrator->set_volume_samples(volume_samples * volume_samples);
adaptive_min_samples = min(adaptive_min_samples * adaptive_min_samples, INT_MAX);
}
else {
integrator->set_diffuse_samples(diffuse_samples);
integrator->set_glossy_samples(glossy_samples);
integrator->set_transmission_samples(transmission_samples);
integrator->set_ao_samples(ao_samples);
integrator->set_mesh_light_samples(mesh_light_samples);
integrator->set_subsurface_samples(subsurface_samples);
integrator->set_volume_samples(volume_samples);
}
integrator->set_adaptive_min_samples(adaptive_min_samples);
if (get_boolean(cscene, "use_fast_gi")) {
if (preview) {
integrator->set_ao_bounces(get_int(cscene, "ao_bounces"));
@@ -364,38 +393,20 @@ void BlenderSync::sync_integrator(BL::ViewLayer &b_view_layer, bool background)
integrator->set_ao_bounces(0);
}
const DenoiseParams denoise_params = get_denoise_params(b_scene, b_view_layer, background);
integrator->set_use_denoise(denoise_params.use);
/* Only update denoiser parameters if the denoiser is actually used. This allows to tweak
* denoiser parameters before enabling it without render resetting on every change. The downside
* is that the interface and the integrator are technically out of sync. */
if (denoise_params.use) {
integrator->set_denoiser_type(denoise_params.type);
integrator->set_denoise_start_sample(denoise_params.start_sample);
integrator->set_use_denoise_pass_albedo(denoise_params.use_pass_albedo);
integrator->set_use_denoise_pass_normal(denoise_params.use_pass_normal);
integrator->set_denoiser_prefilter(denoise_params.prefilter);
}
/* UPDATE_NONE as we don't want to tag the integrator as modified (this was done by the
* set calls above), but we need to make sure that the dependent things are tagged. */
/* UPDATE_NONE as we don't want to tag the integrator as modified, just tag dependent things */
integrator->tag_update(scene, Integrator::UPDATE_NONE);
}
/* Film */
void BlenderSync::sync_film(BL::ViewLayer &b_view_layer, BL::SpaceView3D &b_v3d)
void BlenderSync::sync_film(BL::SpaceView3D &b_v3d)
{
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
PointerRNA crl = RNA_pointer_get(&b_view_layer.ptr, "cycles");
Film *film = scene->film;
if (b_v3d) {
const BlenderViewportParameters new_viewport_parameters(b_v3d, use_developer_ui);
film->set_display_pass(new_viewport_parameters.display_pass);
film->set_show_active_pixels(new_viewport_parameters.show_active_pixels);
film->set_display_pass(update_viewport_display_passes(b_v3d, scene->passes));
}
film->set_exposure(get_float(cscene, "film_exposure"));
@@ -423,15 +434,6 @@ void BlenderSync::sync_film(BL::ViewLayer &b_view_layer, BL::SpaceView3D &b_v3d)
break;
}
}
/* Blender viewport does not support proper shadow catcher compositing, so force an approximate
* mode to improve visual feedback. */
if (b_v3d) {
film->set_use_approximate_shadow_catcher(true);
}
else {
film->set_use_approximate_shadow_catcher(!get_boolean(crl, "use_pass_shadow_catcher"));
}
}
/* Render Layer */
@@ -442,6 +444,7 @@ void BlenderSync::sync_view_layer(BL::ViewLayer &b_view_layer)
/* Filter. */
view_layer.use_background_shader = b_view_layer.use_sky();
view_layer.use_background_ao = b_view_layer.use_ao();
/* Always enable surfaces for baking, otherwise there is nothing to bake to. */
view_layer.use_surfaces = b_view_layer.use_solid() || scene->bake_manager->get_baking();
view_layer.use_hair = b_view_layer.use_strand();
@@ -461,7 +464,10 @@ void BlenderSync::sync_view_layer(BL::ViewLayer &b_view_layer)
if (use_layer_samples != 2) {
int samples = b_view_layer.samples();
view_layer.samples = samples;
if (get_boolean(cscene, "use_square_samples"))
view_layer.samples = samples * samples;
else
view_layer.samples = samples;
}
}
@@ -493,8 +499,7 @@ void BlenderSync::sync_images()
}
/* Passes */
static PassType get_blender_pass_type(BL::RenderPass &b_pass)
PassType BlenderSync::get_pass_type(BL::RenderPass &b_pass)
{
string name = b_pass.name();
#define MAP_PASS(passname, passtype) \
@@ -502,15 +507,10 @@ static PassType get_blender_pass_type(BL::RenderPass &b_pass)
return passtype; \
} \
((void)0)
/* NOTE: Keep in sync with defined names from DNA_scene_types.h */
MAP_PASS("Combined", PASS_COMBINED);
MAP_PASS("Noisy Image", PASS_COMBINED);
MAP_PASS("Depth", PASS_DEPTH);
MAP_PASS("Mist", PASS_MIST);
MAP_PASS("Position", PASS_POSITION);
MAP_PASS("Normal", PASS_NORMAL);
MAP_PASS("IndexOB", PASS_OBJECT_ID);
MAP_PASS("UV", PASS_UV);
@@ -539,92 +539,118 @@ static PassType get_blender_pass_type(BL::RenderPass &b_pass)
MAP_PASS("BakePrimitive", PASS_BAKE_PRIMITIVE);
MAP_PASS("BakeDifferential", PASS_BAKE_DIFFERENTIAL);
MAP_PASS("Denoising Normal", PASS_DENOISING_NORMAL);
MAP_PASS("Denoising Albedo", PASS_DENOISING_ALBEDO);
MAP_PASS("Shadow Catcher", PASS_SHADOW_CATCHER);
MAP_PASS("Noisy Shadow Catcher", PASS_SHADOW_CATCHER);
MAP_PASS("Debug Render Time", PASS_RENDER_TIME);
MAP_PASS("AdaptiveAuxBuffer", PASS_ADAPTIVE_AUX_BUFFER);
MAP_PASS("Debug Sample Count", PASS_SAMPLE_COUNT);
if (string_startswith(name, cryptomatte_prefix)) {
return PASS_CRYPTOMATTE;
}
#undef MAP_PASS
return PASS_NONE;
}
static Pass *pass_add(Scene *scene,
PassType type,
const char *name,
PassMode mode = PassMode::DENOISED)
int BlenderSync::get_denoising_pass(BL::RenderPass &b_pass)
{
Pass *pass = scene->create_node<Pass>();
string name = b_pass.name();
pass->set_type(type);
pass->set_name(ustring(name));
pass->set_mode(mode);
if (name == "Noisy Image")
return DENOISING_PASS_PREFILTERED_COLOR;
return pass;
if (name.substr(0, 10) != "Denoising ") {
return -1;
}
name = name.substr(10);
#define MAP_PASS(passname, offset) \
if (name == passname) { \
return offset; \
} \
((void)0)
MAP_PASS("Normal", DENOISING_PASS_PREFILTERED_NORMAL);
MAP_PASS("Albedo", DENOISING_PASS_PREFILTERED_ALBEDO);
MAP_PASS("Depth", DENOISING_PASS_PREFILTERED_DEPTH);
MAP_PASS("Shadowing", DENOISING_PASS_PREFILTERED_SHADOWING);
MAP_PASS("Variance", DENOISING_PASS_PREFILTERED_VARIANCE);
MAP_PASS("Intensity", DENOISING_PASS_PREFILTERED_INTENSITY);
MAP_PASS("Clean", DENOISING_PASS_CLEAN);
#undef MAP_PASS
return -1;
}
void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_view_layer)
vector<Pass> BlenderSync::sync_render_passes(BL::Scene &b_scene,
BL::RenderLayer &b_rlay,
BL::ViewLayer &b_view_layer,
bool adaptive_sampling,
const DenoiseParams &denoising)
{
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
vector<Pass> passes;
/* Delete all existing passes. */
set<Pass *> clear_passes(scene->passes.begin(), scene->passes.end());
scene->delete_nodes(clear_passes);
/* Always add combined pass. */
pass_add(scene, PASS_COMBINED, "Combined");
/* Blender built-in data and light passes. */
/* loop over passes */
for (BL::RenderPass &b_pass : b_rlay.passes) {
const PassType pass_type = get_blender_pass_type(b_pass);
if (pass_type == PASS_NONE) {
LOG(ERROR) << "Unknown pass " << b_pass.name();
continue;
}
PassType pass_type = get_pass_type(b_pass);
if (pass_type == PASS_MOTION &&
(b_view_layer.use_motion_blur() && b_scene.render().use_motion_blur())) {
continue;
}
pass_add(scene, pass_type, b_pass.name().c_str());
if (pass_type != PASS_NONE)
Pass::add(pass_type, passes, b_pass.name().c_str());
}
PointerRNA crl = RNA_pointer_get(&b_view_layer.ptr, "cycles");
/* Debug passes. */
int denoising_flags = 0;
if (denoising.use || denoising.store_passes) {
if (denoising.type == DENOISER_NLM) {
#define MAP_OPTION(name, flag) \
if (!get_boolean(crl, name)) { \
denoising_flags |= flag; \
} \
((void)0)
MAP_OPTION("denoising_diffuse_direct", DENOISING_CLEAN_DIFFUSE_DIR);
MAP_OPTION("denoising_diffuse_indirect", DENOISING_CLEAN_DIFFUSE_IND);
MAP_OPTION("denoising_glossy_direct", DENOISING_CLEAN_GLOSSY_DIR);
MAP_OPTION("denoising_glossy_indirect", DENOISING_CLEAN_GLOSSY_IND);
MAP_OPTION("denoising_transmission_direct", DENOISING_CLEAN_TRANSMISSION_DIR);
MAP_OPTION("denoising_transmission_indirect", DENOISING_CLEAN_TRANSMISSION_IND);
#undef MAP_OPTION
}
b_engine.add_pass("Noisy Image", 4, "RGBA", b_view_layer.name().c_str());
}
scene->film->set_denoising_flags(denoising_flags);
if (denoising.store_passes) {
b_engine.add_pass("Denoising Normal", 3, "XYZ", b_view_layer.name().c_str());
b_engine.add_pass("Denoising Albedo", 3, "RGB", b_view_layer.name().c_str());
b_engine.add_pass("Denoising Depth", 1, "Z", b_view_layer.name().c_str());
if (denoising.type == DENOISER_NLM) {
b_engine.add_pass("Denoising Shadowing", 1, "X", b_view_layer.name().c_str());
b_engine.add_pass("Denoising Variance", 3, "RGB", b_view_layer.name().c_str());
b_engine.add_pass("Denoising Intensity", 1, "X", b_view_layer.name().c_str());
}
if (scene->film->get_denoising_flags() & DENOISING_CLEAN_ALL_PASSES) {
b_engine.add_pass("Denoising Clean", 3, "RGB", b_view_layer.name().c_str());
}
}
if (get_boolean(crl, "pass_debug_render_time")) {
b_engine.add_pass("Debug Render Time", 1, "X", b_view_layer.name().c_str());
pass_add(scene, PASS_RENDER_TIME, "Debug Render Time");
Pass::add(PASS_RENDER_TIME, passes, "Debug Render Time");
}
if (get_boolean(crl, "pass_debug_sample_count")) {
b_engine.add_pass("Debug Sample Count", 1, "X", b_view_layer.name().c_str());
pass_add(scene, PASS_SAMPLE_COUNT, "Debug Sample Count");
Pass::add(PASS_SAMPLE_COUNT, passes, "Debug Sample Count");
}
/* Cycles specific passes. */
if (get_boolean(crl, "use_pass_volume_direct")) {
b_engine.add_pass("VolumeDir", 3, "RGB", b_view_layer.name().c_str());
pass_add(scene, PASS_VOLUME_DIRECT, "VolumeDir");
Pass::add(PASS_VOLUME_DIRECT, passes, "VolumeDir");
}
if (get_boolean(crl, "use_pass_volume_indirect")) {
b_engine.add_pass("VolumeInd", 3, "RGB", b_view_layer.name().c_str());
pass_add(scene, PASS_VOLUME_INDIRECT, "VolumeInd");
}
if (get_boolean(crl, "use_pass_shadow_catcher")) {
b_engine.add_pass("Shadow Catcher", 3, "RGB", b_view_layer.name().c_str());
pass_add(scene, PASS_SHADOW_CATCHER, "Shadow Catcher");
Pass::add(PASS_VOLUME_INDIRECT, passes, "VolumeInd");
}
/* Cryptomatte stores two ID/weight pairs per RGBA layer.
@@ -636,7 +662,7 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v
for (int i = 0; i < crypto_depth; i++) {
string passname = cryptomatte_prefix + string_printf("Object%02d", i);
b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str());
pass_add(scene, PASS_CRYPTOMATTE, passname.c_str());
Pass::add(PASS_CRYPTOMATTE, passes, passname.c_str());
}
cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_OBJECT);
}
@@ -644,7 +670,7 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v
for (int i = 0; i < crypto_depth; i++) {
string passname = cryptomatte_prefix + string_printf("Material%02d", i);
b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str());
pass_add(scene, PASS_CRYPTOMATTE, passname.c_str());
Pass::add(PASS_CRYPTOMATTE, passes, passname.c_str());
}
cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_MATERIAL);
}
@@ -652,33 +678,22 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v
for (int i = 0; i < crypto_depth; i++) {
string passname = cryptomatte_prefix + string_printf("Asset%02d", i);
b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str());
pass_add(scene, PASS_CRYPTOMATTE, passname.c_str());
Pass::add(PASS_CRYPTOMATTE, passes, passname.c_str());
}
cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_ASSET);
}
if (b_view_layer.use_pass_cryptomatte_accurate() && cryptomatte_passes != CRYPT_NONE) {
cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_ACCURATE);
}
scene->film->set_cryptomatte_passes(cryptomatte_passes);
/* Denoising passes. */
const bool use_denoising = get_boolean(cscene, "use_denoising") &&
get_boolean(crl, "use_denoising");
const bool store_denoising_passes = get_boolean(crl, "denoising_store_passes");
if (use_denoising) {
b_engine.add_pass("Noisy Image", 4, "RGBA", b_view_layer.name().c_str());
pass_add(scene, PASS_COMBINED, "Noisy Image", PassMode::NOISY);
if (get_boolean(crl, "use_pass_shadow_catcher")) {
b_engine.add_pass("Noisy Shadow Catcher", 3, "RGB", b_view_layer.name().c_str());
pass_add(scene, PASS_SHADOW_CATCHER, "Noisy Shadow Catcher", PassMode::NOISY);
if (adaptive_sampling) {
Pass::add(PASS_ADAPTIVE_AUX_BUFFER, passes);
if (!get_boolean(crl, "pass_debug_sample_count")) {
Pass::add(PASS_SAMPLE_COUNT, passes);
}
}
if (store_denoising_passes) {
b_engine.add_pass("Denoising Normal", 3, "XYZ", b_view_layer.name().c_str());
pass_add(scene, PASS_DENOISING_NORMAL, "Denoising Normal", PassMode::NOISY);
b_engine.add_pass("Denoising Albedo", 3, "RGB", b_view_layer.name().c_str());
pass_add(scene, PASS_DENOISING_ALBEDO, "Denoising Albedo", PassMode::NOISY);
}
/* Custom AOV passes. */
BL::ViewLayer::aovs_iterator b_aov_iter;
for (b_view_layer.aovs.begin(b_aov_iter); b_aov_iter != b_view_layer.aovs.end(); ++b_aov_iter) {
BL::AOV b_aov(*b_aov_iter);
@@ -691,15 +706,28 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v
if (is_color) {
b_engine.add_pass(name.c_str(), 4, "RGBA", b_view_layer.name().c_str());
pass_add(scene, PASS_AOV_COLOR, name.c_str());
Pass::add(PASS_AOV_COLOR, passes, name.c_str());
}
else {
b_engine.add_pass(name.c_str(), 1, "X", b_view_layer.name().c_str());
pass_add(scene, PASS_AOV_VALUE, name.c_str());
Pass::add(PASS_AOV_VALUE, passes, name.c_str());
}
}
scene->film->set_denoising_data_pass(denoising.use || denoising.store_passes);
scene->film->set_denoising_clean_pass(scene->film->get_denoising_flags() &
DENOISING_CLEAN_ALL_PASSES);
scene->film->set_denoising_prefiltered_pass(denoising.store_passes &&
denoising.type == DENOISER_NLM);
scene->film->set_pass_alpha_threshold(b_view_layer.pass_alpha_threshold());
if (!Pass::equals(passes, scene->passes)) {
scene->film->tag_passes_update(scene, passes);
scene->film->tag_modified();
scene->integrator->tag_update(scene, Integrator::UPDATE_ALL);
}
return passes;
}
void BlenderSync::free_data_after_sync(BL::Depsgraph &b_depsgraph)
@@ -745,9 +773,9 @@ SceneParams BlenderSync::get_scene_params(BL::Scene &b_scene, bool background)
params.shadingsystem = SHADINGSYSTEM_OSL;
if (background || DebugFlags().viewport_static_bvh)
params.bvh_type = BVH_TYPE_STATIC;
params.bvh_type = SceneParams::BVH_STATIC;
else
params.bvh_type = BVH_TYPE_DYNAMIC;
params.bvh_type = SceneParams::BVH_DYNAMIC;
params.use_bvh_spatial_split = RNA_boolean_get(&cscene, "debug_use_spatial_splits");
params.use_bvh_unaligned_nodes = RNA_boolean_get(&cscene, "debug_use_hair_bvh");
@@ -790,7 +818,8 @@ bool BlenderSync::get_session_pause(BL::Scene &b_scene, bool background)
SessionParams BlenderSync::get_session_params(BL::RenderEngine &b_engine,
BL::Preferences &b_preferences,
BL::Scene &b_scene,
bool background)
bool background,
BL::ViewLayer b_view_layer)
{
SessionParams params;
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
@@ -798,8 +827,7 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine &b_engine,
/* feature set */
params.experimental = (get_enum(cscene, "feature_set") != 0);
/* Headless and background rendering. */
params.headless = BlenderSession::headless;
/* Background */
params.background = background;
/* Device */
@@ -808,26 +836,111 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine &b_engine,
/* samples */
int samples = get_int(cscene, "samples");
int aa_samples = get_int(cscene, "aa_samples");
int preview_samples = get_int(cscene, "preview_samples");
int preview_aa_samples = get_int(cscene, "preview_aa_samples");
if (background) {
params.samples = samples;
if (get_boolean(cscene, "use_square_samples")) {
aa_samples = aa_samples * aa_samples;
preview_aa_samples = preview_aa_samples * preview_aa_samples;
samples = samples * samples;
preview_samples = preview_samples * preview_samples;
}
if (get_enum(cscene, "progressive") == 0 && params.device.has_branched_path) {
if (background) {
params.samples = aa_samples;
}
else {
params.samples = preview_aa_samples;
if (params.samples == 0)
params.samples = INT_MAX;
}
}
else {
params.samples = preview_samples;
if (params.samples == 0)
params.samples = INT_MAX;
if (background) {
params.samples = samples;
}
else {
params.samples = preview_samples;
if (params.samples == 0)
params.samples = INT_MAX;
}
}
/* Clamp samples. */
params.samples = min(params.samples, Integrator::MAX_SAMPLES);
/* Adaptive sampling. */
params.adaptive_sampling = RNA_boolean_get(&cscene, "use_adaptive_sampling");
/* tiles */
const bool is_cpu = (params.device.type == DEVICE_CPU);
if (!is_cpu && !background) {
/* currently GPU could be much slower than CPU when using tiles,
* still need to be investigated, but meanwhile make it possible
* to work in viewport smoothly
*/
int debug_tile_size = get_int(cscene, "debug_tile_size");
params.tile_size = make_int2(debug_tile_size, debug_tile_size);
}
else {
int tile_x = b_engine.tile_x();
int tile_y = b_engine.tile_y();
params.tile_size = make_int2(tile_x, tile_y);
}
if ((BlenderSession::headless == false) && background) {
params.tile_order = (TileOrder)get_enum(cscene, "tile_order");
}
else {
params.tile_order = TILE_BOTTOM_TO_TOP;
}
/* Denoising */
params.denoising = get_denoise_params(b_scene, b_view_layer, background);
if (params.denoising.use) {
/* Add additional denoising devices if we are rendering and denoising
* with different devices. */
params.device.add_denoising_devices(params.denoising.type);
/* Check if denoiser is supported by device. */
if (!(params.device.denoisers & params.denoising.type)) {
params.denoising.use = false;
}
}
/* Viewport Performance */
params.start_resolution = get_int(cscene, "preview_start_resolution");
params.pixel_size = b_engine.get_preview_pixel_size(b_scene);
/* other parameters */
params.cancel_timeout = (double)get_float(cscene, "debug_cancel_timeout");
params.reset_timeout = (double)get_float(cscene, "debug_reset_timeout");
params.text_timeout = (double)get_float(cscene, "debug_text_timeout");
/* progressive refine */
BL::RenderSettings b_r = b_scene.render();
params.progressive_refine = b_engine.is_preview() ||
get_boolean(cscene, "use_progressive_refine");
if (b_r.use_save_buffers() || params.adaptive_sampling)
params.progressive_refine = false;
if (background) {
if (params.progressive_refine)
params.progressive = true;
else
params.progressive = false;
params.start_resolution = INT_MAX;
params.pixel_size = 1;
}
else
params.progressive = true;
/* shading system - scene level needs full refresh */
const bool shadingsystem = RNA_boolean_get(&cscene, "shading_system");
@@ -837,30 +950,19 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine &b_engine,
else if (shadingsystem == 1)
params.shadingsystem = SHADINGSYSTEM_OSL;
/* Time limit. */
if (background) {
params.time_limit = get_float(cscene, "time_limit");
}
else {
/* For the viewport it kind of makes more sense to think in terms of the noise floor, which is
* usually higher than acceptable level for the final frame. */
/* TODO: It might be useful to support time limit in the viewport as well, but needs some
* extra thoughts and input. */
params.time_limit = 0.0;
/* Color management. */
params.display_buffer_linear = b_engine.support_display_space_shader(b_scene);
if (b_engine.is_preview()) {
/* For preview rendering we're using same timeout as
* blender's job update.
*/
params.progressive_update_timeout = 0.1;
}
/* Profiling. */
params.use_profiling = params.device.has_profiling && !b_engine.is_preview() && background &&
BlenderSession::print_render_stats;
if (background) {
params.use_auto_tile = RNA_boolean_get(&cscene, "use_auto_tile");
params.tile_size = max(get_int(cscene, "tile_size"), 8);
}
else {
params.use_auto_tile = false;
}
return params;
}
@@ -868,34 +970,33 @@ DenoiseParams BlenderSync::get_denoise_params(BL::Scene &b_scene,
BL::ViewLayer &b_view_layer,
bool background)
{
enum DenoiserInput {
DENOISER_INPUT_RGB = 1,
DENOISER_INPUT_RGB_ALBEDO = 2,
DENOISER_INPUT_RGB_ALBEDO_NORMAL = 3,
DENOISER_INPUT_NUM,
};
DenoiseParams denoising;
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
int input_passes = -1;
if (background) {
/* Final Render Denoising */
denoising.use = get_boolean(cscene, "use_denoising");
denoising.type = (DenoiserType)get_enum(cscene, "denoiser", DENOISER_NUM, DENOISER_NONE);
denoising.prefilter = (DenoiserPrefilter)get_enum(
cscene, "denoising_prefilter", DENOISER_PREFILTER_NUM, DENOISER_PREFILTER_NONE);
input_passes = (DenoiserInput)get_enum(
cscene, "denoising_input_passes", DENOISER_INPUT_NUM, DENOISER_INPUT_RGB_ALBEDO_NORMAL);
if (b_view_layer) {
PointerRNA clayer = RNA_pointer_get(&b_view_layer.ptr, "cycles");
if (!get_boolean(clayer, "use_denoising")) {
denoising.use = false;
}
denoising.radius = get_int(clayer, "denoising_radius");
denoising.strength = get_float(clayer, "denoising_strength");
denoising.feature_strength = get_float(clayer, "denoising_feature_strength");
denoising.relative_pca = get_boolean(clayer, "denoising_relative_pca");
denoising.input_passes = (DenoiserInput)get_enum(
clayer,
(denoising.type == DENOISER_OPTIX) ? "denoising_optix_input_passes" :
"denoising_openimagedenoise_input_passes",
DENOISER_INPUT_NUM,
DENOISER_INPUT_RGB_ALBEDO_NORMAL);
denoising.store_passes = get_boolean(clayer, "denoising_store_passes");
}
}
else {
@@ -903,12 +1004,10 @@ DenoiseParams BlenderSync::get_denoise_params(BL::Scene &b_scene,
denoising.use = get_boolean(cscene, "use_preview_denoising");
denoising.type = (DenoiserType)get_enum(
cscene, "preview_denoiser", DENOISER_NUM, DENOISER_NONE);
denoising.prefilter = (DenoiserPrefilter)get_enum(
cscene, "preview_denoising_prefilter", DENOISER_PREFILTER_NUM, DENOISER_PREFILTER_FAST);
denoising.start_sample = get_int(cscene, "preview_denoising_start_sample");
input_passes = (DenoiserInput)get_enum(
cscene, "preview_denoising_input_passes", DENOISER_INPUT_NUM, DENOISER_INPUT_RGB_ALBEDO);
denoising.input_passes = (DenoiserInput)get_enum(
cscene, "preview_denoising_input_passes", DENOISER_INPUT_NUM, (int)denoising.input_passes);
/* Auto select fastest denoiser. */
if (denoising.type == DENOISER_NONE) {
@@ -924,27 +1023,6 @@ DenoiseParams BlenderSync::get_denoise_params(BL::Scene &b_scene,
}
}
switch (input_passes) {
case DENOISER_INPUT_RGB:
denoising.use_pass_albedo = false;
denoising.use_pass_normal = false;
break;
case DENOISER_INPUT_RGB_ALBEDO:
denoising.use_pass_albedo = true;
denoising.use_pass_normal = false;
break;
case DENOISER_INPUT_RGB_ALBEDO_NORMAL:
denoising.use_pass_albedo = true;
denoising.use_pass_normal = true;
break;
default:
LOG(ERROR) << "Unhandled input passes enum " << input_passes;
break;
}
return denoising;
}

View File

@@ -60,7 +60,6 @@ class BlenderSync {
BL::Scene &b_scene,
Scene *scene,
bool preview,
bool use_developer_ui,
Progress &progress);
~BlenderSync();
@@ -76,8 +75,12 @@ class BlenderSync {
int height,
void **python_thread_state);
void sync_view_layer(BL::ViewLayer &b_view_layer);
void sync_render_passes(BL::RenderLayer &b_render_layer, BL::ViewLayer &b_view_layer);
void sync_integrator(BL::ViewLayer &b_view_layer, bool background);
vector<Pass> sync_render_passes(BL::Scene &b_scene,
BL::RenderLayer &b_render_layer,
BL::ViewLayer &b_view_layer,
bool adaptive_sampling,
const DenoiseParams &denoising);
void sync_integrator();
void sync_camera(BL::RenderSettings &b_render,
BL::Object &b_override,
int width,
@@ -95,13 +98,22 @@ class BlenderSync {
/* get parameters */
static SceneParams get_scene_params(BL::Scene &b_scene, bool background);
static SessionParams get_session_params(BL::RenderEngine &b_engine,
BL::Preferences &b_userpref,
BL::Scene &b_scene,
bool background);
static SessionParams get_session_params(
BL::RenderEngine &b_engine,
BL::Preferences &b_userpref,
BL::Scene &b_scene,
bool background,
BL::ViewLayer b_view_layer = BL::ViewLayer(PointerRNA_NULL));
static bool get_session_pause(BL::Scene &b_scene, bool background);
static BufferParams get_buffer_params(
BL::SpaceView3D &b_v3d, BL::RegionView3D &b_rv3d, Camera *cam, int width, int height);
static BufferParams get_buffer_params(BL::SpaceView3D &b_v3d,
BL::RegionView3D &b_rv3d,
Camera *cam,
int width,
int height,
const bool use_denoiser);
static PassType get_pass_type(BL::RenderPass &b_pass);
static int get_denoising_pass(BL::RenderPass &b_pass);
private:
static DenoiseParams get_denoise_params(BL::Scene &b_scene,
@@ -119,7 +131,7 @@ class BlenderSync {
int width,
int height,
void **python_thread_state);
void sync_film(BL::ViewLayer &b_view_layer, BL::SpaceView3D &b_v3d);
void sync_film(BL::SpaceView3D &b_v3d);
void sync_view();
/* Shader */
@@ -233,7 +245,6 @@ class BlenderSync {
Scene *scene;
bool preview;
bool experimental;
bool use_developer_ui;
float dicing_rate;
int max_subdivisions;
@@ -242,6 +253,7 @@ class BlenderSync {
RenderLayerInfo()
: material_override(PointerRNA_NULL),
use_background_shader(true),
use_background_ao(true),
use_surfaces(true),
use_hair(true),
use_volumes(true),
@@ -254,6 +266,7 @@ class BlenderSync {
string name;
BL::Material material_override;
bool use_background_shader;
bool use_background_ao;
bool use_surfaces;
bool use_hair;
bool use_volumes;

View File

@@ -17,8 +17,6 @@
#include "blender_viewport.h"
#include "blender_util.h"
#include "render/pass.h"
#include "util/util_logging.h"
CCL_NAMESPACE_BEGIN
@@ -28,12 +26,11 @@ BlenderViewportParameters::BlenderViewportParameters()
studiolight_rotate_z(0.0f),
studiolight_intensity(1.0f),
studiolight_background_alpha(1.0f),
display_pass(PASS_COMBINED),
show_active_pixels(false)
display_pass(PASS_COMBINED)
{
}
BlenderViewportParameters::BlenderViewportParameters(BL::SpaceView3D &b_v3d, bool use_developer_ui)
BlenderViewportParameters::BlenderViewportParameters(BL::SpaceView3D &b_v3d)
: BlenderViewportParameters()
{
if (!b_v3d) {
@@ -58,25 +55,7 @@ BlenderViewportParameters::BlenderViewportParameters(BL::SpaceView3D &b_v3d, boo
}
/* Film. */
/* Lookup display pass based on the enum identifier.
* This is because integer values of python enum are not aligned with the passes definition in
* the kernel. */
display_pass = PASS_COMBINED;
const string display_pass_identifier = get_enum_identifier(cshading, "render_pass");
if (!display_pass_identifier.empty()) {
const ustring pass_type_identifier(string_to_lower(display_pass_identifier));
const NodeEnum *pass_type_enum = Pass::get_type_enum();
if (pass_type_enum->exists(pass_type_identifier)) {
display_pass = static_cast<PassType>((*pass_type_enum)[pass_type_identifier]);
}
}
if (use_developer_ui) {
show_active_pixels = get_boolean(cshading, "show_active_pixels");
}
display_pass = (PassType)get_enum(cshading, "render_pass", -1, -1);
}
bool BlenderViewportParameters::shader_modified(const BlenderViewportParameters &other) const
@@ -90,7 +69,7 @@ bool BlenderViewportParameters::shader_modified(const BlenderViewportParameters
bool BlenderViewportParameters::film_modified(const BlenderViewportParameters &other) const
{
return display_pass != other.display_pass || show_active_pixels != other.show_active_pixels;
return display_pass != other.display_pass;
}
bool BlenderViewportParameters::modified(const BlenderViewportParameters &other) const
@@ -103,4 +82,18 @@ bool BlenderViewportParameters::use_custom_shader() const
return !(use_scene_world && use_scene_lights);
}
PassType update_viewport_display_passes(BL::SpaceView3D &b_v3d, vector<Pass> &passes)
{
if (b_v3d) {
const BlenderViewportParameters viewport_parameters(b_v3d);
const PassType display_pass = viewport_parameters.display_pass;
passes.clear();
Pass::add(display_pass, passes);
return display_pass;
}
return PASS_NONE;
}
CCL_NAMESPACE_END

View File

@@ -39,10 +39,9 @@ class BlenderViewportParameters {
/* Film. */
PassType display_pass;
bool show_active_pixels;
BlenderViewportParameters();
BlenderViewportParameters(BL::SpaceView3D &b_v3d, bool use_developer_ui);
explicit BlenderViewportParameters(BL::SpaceView3D &b_v3d);
/* Check whether any of shading related settings are different from the given parameters. */
bool shader_modified(const BlenderViewportParameters &other) const;
@@ -58,6 +57,8 @@ class BlenderViewportParameters {
bool use_custom_shader() const;
};
PassType update_viewport_display_passes(BL::SpaceView3D &b_v3d, vector<Pass> &passes);
CCL_NAMESPACE_END
#endif

View File

@@ -832,18 +832,18 @@ BVHNode *BVHBuild::create_leaf_node(const BVHRange &range, const vector<BVHRefer
typedef StackAllocator<256, float2> LeafTimeStackAllocator;
typedef StackAllocator<256, BVHReference> LeafReferenceStackAllocator;
vector<int, LeafStackAllocator> p_type[PRIMITIVE_NUM];
vector<int, LeafStackAllocator> p_index[PRIMITIVE_NUM];
vector<int, LeafStackAllocator> p_object[PRIMITIVE_NUM];
vector<float2, LeafTimeStackAllocator> p_time[PRIMITIVE_NUM];
vector<BVHReference, LeafReferenceStackAllocator> p_ref[PRIMITIVE_NUM];
vector<int, LeafStackAllocator> p_type[PRIMITIVE_NUM_TOTAL];
vector<int, LeafStackAllocator> p_index[PRIMITIVE_NUM_TOTAL];
vector<int, LeafStackAllocator> p_object[PRIMITIVE_NUM_TOTAL];
vector<float2, LeafTimeStackAllocator> p_time[PRIMITIVE_NUM_TOTAL];
vector<BVHReference, LeafReferenceStackAllocator> p_ref[PRIMITIVE_NUM_TOTAL];
/* TODO(sergey): In theory we should be able to store references. */
vector<BVHReference, LeafReferenceStackAllocator> object_references;
uint visibility[PRIMITIVE_NUM] = {0};
uint visibility[PRIMITIVE_NUM_TOTAL] = {0};
/* NOTE: Keep initialization in sync with actual number of primitives. */
BoundBox bounds[PRIMITIVE_NUM] = {
BoundBox bounds[PRIMITIVE_NUM_TOTAL] = {
BoundBox::empty, BoundBox::empty, BoundBox::empty, BoundBox::empty};
int ob_num = 0;
int num_new_prims = 0;
@@ -877,7 +877,7 @@ BVHNode *BVHBuild::create_leaf_node(const BVHRange &range, const vector<BVHRefer
* TODO(sergey): With some pointer trickery we can write directly to the
* destination buffers for the non-spatial split BVH.
*/
BVHNode *leaves[PRIMITIVE_NUM + 1] = {NULL};
BVHNode *leaves[PRIMITIVE_NUM_TOTAL + 1] = {NULL};
int num_leaves = 0;
size_t start_index = 0;
vector<int, LeafStackAllocator> local_prim_type, local_prim_index, local_prim_object;
@@ -888,7 +888,7 @@ BVHNode *BVHBuild::create_leaf_node(const BVHRange &range, const vector<BVHRefer
if (need_prim_time) {
local_prim_time.resize(num_new_prims);
}
for (int i = 0; i < PRIMITIVE_NUM; ++i) {
for (int i = 0; i < PRIMITIVE_NUM_TOTAL; ++i) {
int num = (int)p_type[i].size();
if (num != 0) {
assert(p_type[i].size() == p_index[i].size());

View File

@@ -37,10 +37,10 @@
/* Kernel includes are necessary so that the filter function for Embree can access the packed BVH.
*/
# include "kernel/bvh/bvh_embree.h"
# include "kernel/bvh/bvh_util.h"
# include "kernel/device/cpu/compat.h"
# include "kernel/device/cpu/globals.h"
# include "kernel/kernel_compat_cpu.h"
# include "kernel/kernel_globals.h"
# include "kernel/kernel_random.h"
# include "kernel/split/kernel_split_data_types.h"
# include "render/hair.h"
# include "render/mesh.h"
@@ -73,69 +73,46 @@ static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments *args)
const RTCRay *ray = (RTCRay *)args->ray;
RTCHit *hit = (RTCHit *)args->hit;
CCLIntersectContext *ctx = ((IntersectContext *)args->context)->userRayExt;
const KernelGlobals *kg = ctx->kg;
KernelGlobals *kg = ctx->kg;
switch (ctx->type) {
case CCLIntersectContext::RAY_SHADOW_ALL: {
Intersection current_isect;
kernel_embree_convert_hit(kg, ray, hit, &current_isect);
/* If no transparent shadows, all light is blocked. */
const int flags = intersection_get_shader_flags(kg, &current_isect);
if (!(flags & (SD_HAS_TRANSPARENT_SHADOW)) || ctx->max_hits == 0) {
ctx->opaque_hit = true;
return;
}
/* Test if we need to record this transparent intersection. */
if (ctx->num_hits < ctx->max_hits || ray->tfar < ctx->max_t) {
/* Skip already recorded intersections. */
int num_recorded_hits = min(ctx->num_hits, ctx->max_hits);
for (int i = 0; i < num_recorded_hits; ++i) {
/* Append the intersection to the end of the array. */
if (ctx->num_hits < ctx->max_hits) {
Intersection current_isect;
kernel_embree_convert_hit(kg, ray, hit, &current_isect);
for (size_t i = 0; i < ctx->max_hits; ++i) {
if (current_isect.object == ctx->isect_s[i].object &&
current_isect.prim == ctx->isect_s[i].prim && current_isect.t == ctx->isect_s[i].t) {
/* This intersection was already recorded, skip it. */
*args->valid = 0;
return;
break;
}
}
/* If maximum number of hits was reached, replace the intersection with the
* highest distance. We want to find the N closest intersections. */
int isect_index = num_recorded_hits;
if (num_recorded_hits + 1 >= ctx->max_hits) {
float max_t = ctx->isect_s[0].t;
int max_recorded_hit = 0;
for (int i = 1; i < num_recorded_hits; ++i) {
if (ctx->isect_s[i].t > max_t) {
max_recorded_hit = i;
max_t = ctx->isect_s[i].t;
}
}
if (num_recorded_hits >= ctx->max_hits) {
isect_index = max_recorded_hit;
}
/* Limit the ray distance and stop counting hits beyond this.
* TODO: is there some way we can tell Embree to stop intersecting beyond
* this distance when max number of hits is reached?. Or maybe it will
* become irrelevant if we make max_hits a very high number on the CPU. */
ctx->max_t = max(current_isect.t, max_t);
Intersection *isect = &ctx->isect_s[ctx->num_hits];
++ctx->num_hits;
*isect = current_isect;
int prim = kernel_tex_fetch(__prim_index, isect->prim);
int shader = 0;
if (kernel_tex_fetch(__prim_type, isect->prim) & PRIMITIVE_ALL_TRIANGLE) {
shader = kernel_tex_fetch(__tri_shader, prim);
}
else {
float4 str = kernel_tex_fetch(__curves, prim);
shader = __float_as_int(str.z);
}
int flag = kernel_tex_fetch(__shaders, shader & SHADER_MASK).flags;
/* If no transparent shadows, all light is blocked. */
if (flag & (SD_HAS_TRANSPARENT_SHADOW)) {
/* This tells Embree to continue tracing. */
*args->valid = 0;
}
ctx->isect_s[isect_index] = current_isect;
}
/* Always increase the number of hits, even beyond ray.max_hits so that
* the caller can detect this as and consider it opaque, or trace another
* ray. */
++ctx->num_hits;
/* This tells Embree to continue tracing. */
*args->valid = 0;
else {
/* Increase the number of hits beyond ray.max_hits
* so that the caller can detect this as opaque. */
++ctx->num_hits;
}
break;
}
case CCLIntersectContext::RAY_LOCAL:
@@ -352,7 +329,7 @@ void BVHEmbree::build(Progress &progress, Stats *stats, RTCDevice rtc_device_)
scene = NULL;
}
const bool dynamic = params.bvh_type == BVH_TYPE_DYNAMIC;
const bool dynamic = params.bvh_type == SceneParams::BVH_DYNAMIC;
scene = rtcNewScene(rtc_device);
const RTCSceneFlags scene_flags = (dynamic ? RTC_SCENE_FLAG_DYNAMIC : RTC_SCENE_FLAG_NONE) |

View File

@@ -31,27 +31,6 @@ CCL_NAMESPACE_BEGIN
*/
typedef KernelBVHLayout BVHLayout;
/* Type of BVH, in terms whether it is supported dynamic updates of meshes
* or whether modifying geometry requires full BVH rebuild.
*/
enum BVHType {
/* BVH supports dynamic updates of geometry.
*
* Faster for updating BVH tree when doing modifications in viewport,
* but slower for rendering.
*/
BVH_TYPE_DYNAMIC = 0,
/* BVH tree is calculated for specific scene, updates in geometry
* requires full tree rebuild.
*
* Slower to update BVH tree when modifying objects in viewport, also
* slower to build final BVH tree but gives best possible render speed.
*/
BVH_TYPE_STATIC = 1,
BVH_NUM_TYPES,
};
/* Names bitflag type to denote which BVH layouts are supported by
* particular area.
*

View File

@@ -287,6 +287,9 @@ if(CYCLES_STANDALONE_REPOSITORY)
endif()
set(__boost_packages filesystem regex system thread date_time)
if(WITH_CYCLES_NETWORK)
list(APPEND __boost_packages serialization)
endif()
if(WITH_CYCLES_OSL)
list(APPEND __boost_packages wave)
endif()

View File

@@ -36,70 +36,49 @@ endif()
set(SRC
device.cpp
device_denoise.cpp
device_graphics_interop.cpp
device_kernel.cpp
device_cpu.cpp
device_cuda.cpp
device_denoising.cpp
device_dummy.cpp
device_memory.cpp
device_queue.cpp
)
set(SRC_CPU
cpu/device.cpp
cpu/device.h
cpu/device_impl.cpp
cpu/device_impl.h
cpu/kernel.cpp
cpu/kernel.h
cpu/kernel_function.h
cpu/kernel_thread_globals.cpp
cpu/kernel_thread_globals.h
device_multi.cpp
device_opencl.cpp
device_optix.cpp
device_split_kernel.cpp
device_task.cpp
)
set(SRC_CUDA
cuda/device.cpp
cuda/device.h
cuda/device_impl.cpp
cuda/device_impl.h
cuda/graphics_interop.cpp
cuda/graphics_interop.h
cuda/kernel.cpp
cuda/kernel.h
cuda/queue.cpp
cuda/queue.h
cuda/util.cpp
cuda/util.h
cuda/device_cuda.h
cuda/device_cuda_impl.cpp
)
set(SRC_DUMMY
dummy/device.cpp
dummy/device.h
set(SRC_OPENCL
opencl/device_opencl.h
opencl/device_opencl_impl.cpp
opencl/memory_manager.h
opencl/memory_manager.cpp
opencl/opencl_util.cpp
)
set(SRC_MULTI
multi/device.cpp
multi/device.h
)
set(SRC_OPTIX
optix/device.cpp
optix/device.h
optix/device_impl.cpp
optix/device_impl.h
optix/queue.cpp
optix/queue.h
optix/util.h
)
if(WITH_CYCLES_NETWORK)
list(APPEND SRC
device_network.cpp
)
endif()
set(SRC_HEADERS
device.h
device_denoise.h
device_graphics_interop.h
device_denoising.h
device_memory.h
device_kernel.h
device_queue.h
device_intern.h
device_network.h
device_split_kernel.h
device_task.h
)
set(LIB
cycles_render
cycles_kernel
cycles_util
${CYCLES_GL_LIBRARIES}
@@ -116,7 +95,15 @@ else()
endif()
add_definitions(${GL_DEFINITIONS})
if(WITH_CYCLES_NETWORK)
add_definitions(-DWITH_NETWORK)
endif()
if(WITH_CYCLES_DEVICE_OPENCL)
list(APPEND LIB
extern_clew
)
add_definitions(-DWITH_OPENCL)
endif()
if(WITH_CYCLES_DEVICE_CUDA)
add_definitions(-DWITH_CUDA)
endif()
@@ -128,27 +115,18 @@ if(WITH_CYCLES_DEVICE_MULTI)
endif()
if(WITH_OPENIMAGEDENOISE)
add_definitions(-DWITH_OPENIMAGEDENOISE)
add_definitions(-DOIDN_STATIC_LIB)
list(APPEND INC_SYS
${OPENIMAGEDENOISE_INCLUDE_DIRS}
)
list(APPEND LIB
${OPENIMAGEDENOISE_LIBRARIES}
${TBB_LIBRARIES}
)
endif()
include_directories(${INC})
include_directories(SYSTEM ${INC_SYS})
cycles_add_library(cycles_device "${LIB}"
${SRC}
${SRC_CPU}
${SRC_CUDA}
${SRC_DUMMY}
${SRC_MULTI}
${SRC_OPTIX}
${SRC_HEADERS}
)
source_group("cpu" FILES ${SRC_CPU})
source_group("cuda" FILES ${SRC_CUDA})
source_group("dummy" FILES ${SRC_DUMMY})
source_group("multi" FILES ${SRC_MULTI})
source_group("optix" FILES ${SRC_OPTIX})
source_group("common" FILES ${SRC} ${SRC_HEADERS})
cycles_add_library(cycles_device "${LIB}" ${SRC} ${SRC_CUDA} ${SRC_OPENCL} ${SRC_HEADERS})

View File

@@ -1,64 +0,0 @@
/*
* Copyright 2011-2013 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "device/cpu/device.h"
#include "device/cpu/device_impl.h"
/* Used for `info.denoisers`. */
/* TODO(sergey): The denoisers are probably to be moved completely out of the device into their
* own class. But until then keep API consistent with how it used to work before. */
#include "util/util_openimagedenoise.h"
CCL_NAMESPACE_BEGIN
Device *device_cpu_create(const DeviceInfo &info, Stats &stats, Profiler &profiler)
{
return new CPUDevice(info, stats, profiler);
}
void device_cpu_info(vector<DeviceInfo> &devices)
{
DeviceInfo info;
info.type = DEVICE_CPU;
info.description = system_cpu_brand_string();
info.id = "CPU";
info.num = 0;
info.has_osl = true;
info.has_half_images = true;
info.has_nanovdb = true;
info.has_profiling = true;
if (openimagedenoise_supported()) {
info.denoisers |= DENOISER_OPENIMAGEDENOISE;
}
devices.insert(devices.begin(), info);
}
string device_cpu_capabilities()
{
string capabilities = "";
capabilities += system_cpu_support_sse2() ? "SSE2 " : "";
capabilities += system_cpu_support_sse3() ? "SSE3 " : "";
capabilities += system_cpu_support_sse41() ? "SSE41 " : "";
capabilities += system_cpu_support_avx() ? "AVX " : "";
capabilities += system_cpu_support_avx2() ? "AVX2" : "";
if (capabilities[capabilities.size() - 1] == ' ')
capabilities.resize(capabilities.size() - 1);
return capabilities;
}
CCL_NAMESPACE_END

View File

@@ -1,332 +0,0 @@
/*
* Copyright 2011-2021 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "device/cpu/device_impl.h"
#include <stdlib.h>
#include <string.h>
/* So ImathMath is included before our kernel_cpu_compat. */
#ifdef WITH_OSL
/* So no context pollution happens from indirectly included windows.h */
# include "util/util_windows.h"
# include <OSL/oslexec.h>
#endif
#ifdef WITH_EMBREE
# include <embree3/rtcore.h>
#endif
#include "device/cpu/kernel.h"
#include "device/cpu/kernel_thread_globals.h"
#include "device/device.h"
// clang-format off
#include "kernel/device/cpu/compat.h"
#include "kernel/device/cpu/globals.h"
#include "kernel/device/cpu/kernel.h"
#include "kernel/kernel_types.h"
#include "kernel/osl/osl_shader.h"
#include "kernel/osl/osl_globals.h"
// clang-format on
#include "bvh/bvh_embree.h"
#include "render/buffers.h"
#include "util/util_debug.h"
#include "util/util_foreach.h"
#include "util/util_function.h"
#include "util/util_logging.h"
#include "util/util_map.h"
#include "util/util_openimagedenoise.h"
#include "util/util_optimization.h"
#include "util/util_progress.h"
#include "util/util_system.h"
#include "util/util_task.h"
#include "util/util_thread.h"
CCL_NAMESPACE_BEGIN
CPUDevice::CPUDevice(const DeviceInfo &info_, Stats &stats_, Profiler &profiler_)
: Device(info_, stats_, profiler_), texture_info(this, "__texture_info", MEM_GLOBAL)
{
/* Pick any kernel, all of them are supposed to have same level of microarchitecture
* optimization. */
VLOG(1) << "Will be using " << kernels.integrator_init_from_camera.get_uarch_name()
<< " kernels.";
if (info.cpu_threads == 0) {
info.cpu_threads = TaskScheduler::num_threads();
}
#ifdef WITH_OSL
kernel_globals.osl = &osl_globals;
#endif
#ifdef WITH_EMBREE
embree_device = rtcNewDevice("verbose=0");
#endif
need_texture_info = false;
}
CPUDevice::~CPUDevice()
{
#ifdef WITH_EMBREE
rtcReleaseDevice(embree_device);
#endif
texture_info.free();
}
bool CPUDevice::show_samples() const
{
return (info.cpu_threads == 1);
}
BVHLayoutMask CPUDevice::get_bvh_layout_mask() const
{
BVHLayoutMask bvh_layout_mask = BVH_LAYOUT_BVH2;
#ifdef WITH_EMBREE
bvh_layout_mask |= BVH_LAYOUT_EMBREE;
#endif /* WITH_EMBREE */
return bvh_layout_mask;
}
bool CPUDevice::load_texture_info()
{
if (!need_texture_info) {
return false;
}
texture_info.copy_to_device();
need_texture_info = false;
return true;
}
void CPUDevice::mem_alloc(device_memory &mem)
{
if (mem.type == MEM_TEXTURE) {
assert(!"mem_alloc not supported for textures.");
}
else if (mem.type == MEM_GLOBAL) {
assert(!"mem_alloc not supported for global memory.");
}
else {
if (mem.name) {
VLOG(1) << "Buffer allocate: " << mem.name << ", "
<< string_human_readable_number(mem.memory_size()) << " bytes. ("
<< string_human_readable_size(mem.memory_size()) << ")";
}
if (mem.type == MEM_DEVICE_ONLY) {
assert(!mem.host_pointer);
size_t alignment = MIN_ALIGNMENT_CPU_DATA_TYPES;
void *data = util_aligned_malloc(mem.memory_size(), alignment);
mem.device_pointer = (device_ptr)data;
}
else {
mem.device_pointer = (device_ptr)mem.host_pointer;
}
mem.device_size = mem.memory_size();
stats.mem_alloc(mem.device_size);
}
}
void CPUDevice::mem_copy_to(device_memory &mem)
{
if (mem.type == MEM_GLOBAL) {
global_free(mem);
global_alloc(mem);
}
else if (mem.type == MEM_TEXTURE) {
tex_free((device_texture &)mem);
tex_alloc((device_texture &)mem);
}
else {
if (!mem.device_pointer) {
mem_alloc(mem);
}
/* copy is no-op */
}
}
void CPUDevice::mem_copy_from(
device_memory & /*mem*/, size_t /*y*/, size_t /*w*/, size_t /*h*/, size_t /*elem*/)
{
/* no-op */
}
void CPUDevice::mem_zero(device_memory &mem)
{
if (!mem.device_pointer) {
mem_alloc(mem);
}
if (mem.device_pointer) {
memset((void *)mem.device_pointer, 0, mem.memory_size());
}
}
void CPUDevice::mem_free(device_memory &mem)
{
if (mem.type == MEM_GLOBAL) {
global_free(mem);
}
else if (mem.type == MEM_TEXTURE) {
tex_free((device_texture &)mem);
}
else if (mem.device_pointer) {
if (mem.type == MEM_DEVICE_ONLY) {
util_aligned_free((void *)mem.device_pointer);
}
mem.device_pointer = 0;
stats.mem_free(mem.device_size);
mem.device_size = 0;
}
}
device_ptr CPUDevice::mem_alloc_sub_ptr(device_memory &mem, size_t offset, size_t /*size*/)
{
return (device_ptr)(((char *)mem.device_pointer) + mem.memory_elements_size(offset));
}
void CPUDevice::const_copy_to(const char *name, void *host, size_t size)
{
#if WITH_EMBREE
if (strcmp(name, "__data") == 0) {
assert(size <= sizeof(KernelData));
// Update scene handle (since it is different for each device on multi devices)
KernelData *const data = (KernelData *)host;
data->bvh.scene = embree_scene;
}
#endif
kernel_const_copy(&kernel_globals, name, host, size);
}
void CPUDevice::global_alloc(device_memory &mem)
{
VLOG(1) << "Global memory allocate: " << mem.name << ", "
<< string_human_readable_number(mem.memory_size()) << " bytes. ("
<< string_human_readable_size(mem.memory_size()) << ")";
kernel_global_memory_copy(&kernel_globals, mem.name, mem.host_pointer, mem.data_size);
mem.device_pointer = (device_ptr)mem.host_pointer;
mem.device_size = mem.memory_size();
stats.mem_alloc(mem.device_size);
}
void CPUDevice::global_free(device_memory &mem)
{
if (mem.device_pointer) {
mem.device_pointer = 0;
stats.mem_free(mem.device_size);
mem.device_size = 0;
}
}
void CPUDevice::tex_alloc(device_texture &mem)
{
VLOG(1) << "Texture allocate: " << mem.name << ", "
<< string_human_readable_number(mem.memory_size()) << " bytes. ("
<< string_human_readable_size(mem.memory_size()) << ")";
mem.device_pointer = (device_ptr)mem.host_pointer;
mem.device_size = mem.memory_size();
stats.mem_alloc(mem.device_size);
const uint slot = mem.slot;
if (slot >= texture_info.size()) {
/* Allocate some slots in advance, to reduce amount of re-allocations. */
texture_info.resize(slot + 128);
}
texture_info[slot] = mem.info;
texture_info[slot].data = (uint64_t)mem.host_pointer;
need_texture_info = true;
}
void CPUDevice::tex_free(device_texture &mem)
{
if (mem.device_pointer) {
mem.device_pointer = 0;
stats.mem_free(mem.device_size);
mem.device_size = 0;
need_texture_info = true;
}
}
void CPUDevice::build_bvh(BVH *bvh, Progress &progress, bool refit)
{
#ifdef WITH_EMBREE
if (bvh->params.bvh_layout == BVH_LAYOUT_EMBREE ||
bvh->params.bvh_layout == BVH_LAYOUT_MULTI_OPTIX_EMBREE) {
BVHEmbree *const bvh_embree = static_cast<BVHEmbree *>(bvh);
if (refit) {
bvh_embree->refit(progress);
}
else {
bvh_embree->build(progress, &stats, embree_device);
}
if (bvh->params.top_level) {
embree_scene = bvh_embree->scene;
}
}
else
#endif
Device::build_bvh(bvh, progress, refit);
}
const CPUKernels *CPUDevice::get_cpu_kernels() const
{
return &kernels;
}
void CPUDevice::get_cpu_kernel_thread_globals(
vector<CPUKernelThreadGlobals> &kernel_thread_globals)
{
/* Ensure latest texture info is loaded into kernel globals before returning. */
load_texture_info();
kernel_thread_globals.clear();
void *osl_memory = get_cpu_osl_memory();
for (int i = 0; i < info.cpu_threads; i++) {
kernel_thread_globals.emplace_back(kernel_globals, osl_memory, profiler);
}
}
void *CPUDevice::get_cpu_osl_memory()
{
#ifdef WITH_OSL
return &osl_globals;
#else
return NULL;
#endif
}
bool CPUDevice::load_kernels(const uint /*kernel_features*/)
{
return true;
}
CCL_NAMESPACE_END

View File

@@ -1,102 +0,0 @@
/*
* Copyright 2011-2021 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
/* So ImathMath is included before our kernel_cpu_compat. */
#ifdef WITH_OSL
/* So no context pollution happens from indirectly included windows.h */
# include "util/util_windows.h"
# include <OSL/oslexec.h>
#endif
#ifdef WITH_EMBREE
# include <embree3/rtcore.h>
#endif
#include "device/cpu/kernel.h"
#include "device/device.h"
#include "device/device_memory.h"
// clang-format off
#include "kernel/device/cpu/compat.h"
#include "kernel/device/cpu/kernel.h"
#include "kernel/device/cpu/globals.h"
#include "kernel/osl/osl_shader.h"
#include "kernel/osl/osl_globals.h"
// clang-format on
CCL_NAMESPACE_BEGIN
class CPUDevice : public Device {
public:
KernelGlobals kernel_globals;
device_vector<TextureInfo> texture_info;
bool need_texture_info;
#ifdef WITH_OSL
OSLGlobals osl_globals;
#endif
#ifdef WITH_EMBREE
RTCScene embree_scene = NULL;
RTCDevice embree_device;
#endif
CPUKernels kernels;
CPUDevice(const DeviceInfo &info_, Stats &stats_, Profiler &profiler_);
~CPUDevice();
virtual bool show_samples() const override;
virtual BVHLayoutMask get_bvh_layout_mask() const override;
/* Returns true if the texture info was copied to the device (meaning, some more
* re-initialization might be needed). */
bool load_texture_info();
virtual void mem_alloc(device_memory &mem) override;
virtual void mem_copy_to(device_memory &mem) override;
virtual void mem_copy_from(
device_memory &mem, size_t y, size_t w, size_t h, size_t elem) override;
virtual void mem_zero(device_memory &mem) override;
virtual void mem_free(device_memory &mem) override;
virtual device_ptr mem_alloc_sub_ptr(device_memory &mem,
size_t offset,
size_t /*size*/) override;
virtual void const_copy_to(const char *name, void *host, size_t size) override;
void global_alloc(device_memory &mem);
void global_free(device_memory &mem);
void tex_alloc(device_texture &mem);
void tex_free(device_texture &mem);
void build_bvh(BVH *bvh, Progress &progress, bool refit) override;
virtual const CPUKernels *get_cpu_kernels() const override;
virtual void get_cpu_kernel_thread_globals(
vector<CPUKernelThreadGlobals> &kernel_thread_globals) override;
virtual void *get_cpu_osl_memory() override;
protected:
virtual bool load_kernels(uint /*kernel_features*/) override;
};
CCL_NAMESPACE_END

View File

@@ -1,61 +0,0 @@
/*
* Copyright 2011-2021 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "device/cpu/kernel.h"
#include "kernel/device/cpu/kernel.h"
CCL_NAMESPACE_BEGIN
#define KERNEL_FUNCTIONS(name) \
KERNEL_NAME_EVAL(cpu, name), KERNEL_NAME_EVAL(cpu_sse2, name), \
KERNEL_NAME_EVAL(cpu_sse3, name), KERNEL_NAME_EVAL(cpu_sse41, name), \
KERNEL_NAME_EVAL(cpu_avx, name), KERNEL_NAME_EVAL(cpu_avx2, name)
#define REGISTER_KERNEL(name) name(KERNEL_FUNCTIONS(name))
CPUKernels::CPUKernels()
: /* Integrator. */
REGISTER_KERNEL(integrator_init_from_camera),
REGISTER_KERNEL(integrator_init_from_bake),
REGISTER_KERNEL(integrator_intersect_closest),
REGISTER_KERNEL(integrator_intersect_shadow),
REGISTER_KERNEL(integrator_intersect_subsurface),
REGISTER_KERNEL(integrator_intersect_volume_stack),
REGISTER_KERNEL(integrator_shade_background),
REGISTER_KERNEL(integrator_shade_light),
REGISTER_KERNEL(integrator_shade_shadow),
REGISTER_KERNEL(integrator_shade_surface),
REGISTER_KERNEL(integrator_shade_volume),
REGISTER_KERNEL(integrator_megakernel),
/* Shader evaluation. */
REGISTER_KERNEL(shader_eval_displace),
REGISTER_KERNEL(shader_eval_background),
/* Adaptive sampling. */
REGISTER_KERNEL(adaptive_sampling_convergence_check),
REGISTER_KERNEL(adaptive_sampling_filter_x),
REGISTER_KERNEL(adaptive_sampling_filter_y),
/* Cryptomatte. */
REGISTER_KERNEL(cryptomatte_postprocess),
/* Bake. */
REGISTER_KERNEL(bake)
{
}
#undef REGISTER_KERNEL
#undef KERNEL_FUNCTIONS
CCL_NAMESPACE_END

View File

@@ -1,111 +0,0 @@
/*
* Copyright 2011-2021 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "device/cpu/kernel_function.h"
#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
struct KernelGlobals;
struct IntegratorStateCPU;
struct TileInfo;
class CPUKernels {
public:
/* Integrator. */
using IntegratorFunction =
CPUKernelFunction<void (*)(const KernelGlobals *kg, IntegratorStateCPU *state)>;
using IntegratorShadeFunction = CPUKernelFunction<void (*)(
const KernelGlobals *kg, IntegratorStateCPU *state, ccl_global float *render_buffer)>;
using IntegratorInitFunction = CPUKernelFunction<bool (*)(const KernelGlobals *kg,
IntegratorStateCPU *state,
KernelWorkTile *tile,
ccl_global float *render_buffer)>;
IntegratorInitFunction integrator_init_from_camera;
IntegratorInitFunction integrator_init_from_bake;
IntegratorFunction integrator_intersect_closest;
IntegratorFunction integrator_intersect_shadow;
IntegratorFunction integrator_intersect_subsurface;
IntegratorFunction integrator_intersect_volume_stack;
IntegratorShadeFunction integrator_shade_background;
IntegratorShadeFunction integrator_shade_light;
IntegratorShadeFunction integrator_shade_shadow;
IntegratorShadeFunction integrator_shade_surface;
IntegratorShadeFunction integrator_shade_volume;
IntegratorShadeFunction integrator_megakernel;
/* Shader evaluation. */
using ShaderEvalFunction = CPUKernelFunction<void (*)(
const KernelGlobals *kg, const KernelShaderEvalInput *, float4 *, const int)>;
ShaderEvalFunction shader_eval_displace;
ShaderEvalFunction shader_eval_background;
/* Adaptive stopping. */
using AdaptiveSamplingConvergenceCheckFunction =
CPUKernelFunction<bool (*)(const KernelGlobals *kg,
ccl_global float *render_buffer,
int x,
int y,
float threshold,
bool reset,
int offset,
int stride)>;
using AdaptiveSamplingFilterXFunction =
CPUKernelFunction<void (*)(const KernelGlobals *kg,
ccl_global float *render_buffer,
int y,
int start_x,
int width,
int offset,
int stride)>;
using AdaptiveSamplingFilterYFunction =
CPUKernelFunction<void (*)(const KernelGlobals *kg,
ccl_global float *render_buffer,
int x,
int start_y,
int height,
int offset,
int stride)>;
AdaptiveSamplingConvergenceCheckFunction adaptive_sampling_convergence_check;
AdaptiveSamplingFilterXFunction adaptive_sampling_filter_x;
AdaptiveSamplingFilterYFunction adaptive_sampling_filter_y;
/* Cryptomatte. */
using CryptomattePostprocessFunction = CPUKernelFunction<void (*)(
const KernelGlobals *kg, ccl_global float *render_buffer, int pixel_index)>;
CryptomattePostprocessFunction cryptomatte_postprocess;
/* Bake. */
CPUKernelFunction<void (*)(const KernelGlobals *, float *, int, int, int, int, int)> bake;
CPUKernels();
};
CCL_NAMESPACE_END

View File

@@ -1,124 +0,0 @@
/*
* Copyright 2011-2021 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "util/util_debug.h"
#include "util/util_system.h"
CCL_NAMESPACE_BEGIN
/* A wrapper around per-microarchitecture variant of a kernel function.
*
* Provides a function-call-like API which gets routed to the most suitable implementation.
*
* For example, on a computer which only has SSE4.1 the kernel_sse41 will be used. */
template<typename FunctionType> class CPUKernelFunction {
public:
CPUKernelFunction(FunctionType kernel_default,
FunctionType kernel_sse2,
FunctionType kernel_sse3,
FunctionType kernel_sse41,
FunctionType kernel_avx,
FunctionType kernel_avx2)
{
kernel_info_ = get_best_kernel_info(
kernel_default, kernel_sse2, kernel_sse3, kernel_sse41, kernel_avx, kernel_avx2);
}
template<typename... Args> inline auto operator()(Args... args) const
{
assert(kernel_info_.kernel);
return kernel_info_.kernel(args...);
}
const char *get_uarch_name() const
{
return kernel_info_.uarch_name;
}
protected:
/* Helper class which allows to pass human-readable microarchitecture name together with function
* pointer. */
class KernelInfo {
public:
KernelInfo() : KernelInfo("", nullptr)
{
}
/* TODO(sergey): Use string view, to have higher-level functionality (i.e. comparison) without
* memory allocation. */
KernelInfo(const char *uarch_name, FunctionType kernel)
: uarch_name(uarch_name), kernel(kernel)
{
}
const char *uarch_name;
FunctionType kernel;
};
KernelInfo get_best_kernel_info(FunctionType kernel_default,
FunctionType kernel_sse2,
FunctionType kernel_sse3,
FunctionType kernel_sse41,
FunctionType kernel_avx,
FunctionType kernel_avx2)
{
/* Silence warnings about unused variables when compiling without some architectures. */
(void)kernel_sse2;
(void)kernel_sse3;
(void)kernel_sse41;
(void)kernel_avx;
(void)kernel_avx2;
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX2
if (DebugFlags().cpu.has_avx2() && system_cpu_support_avx2()) {
return KernelInfo("AVX2", kernel_avx2);
}
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX
if (DebugFlags().cpu.has_avx() && system_cpu_support_avx()) {
return KernelInfo("AVX", kernel_avx);
}
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE41
if (DebugFlags().cpu.has_sse41() && system_cpu_support_sse41()) {
return KernelInfo("SSE4.1", kernel_sse41);
}
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE3
if (DebugFlags().cpu.has_sse3() && system_cpu_support_sse3()) {
return KernelInfo("SSE3", kernel_sse3);
}
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE2
if (DebugFlags().cpu.has_sse2() && system_cpu_support_sse2()) {
return KernelInfo("SSE2", kernel_sse2);
}
#endif
return KernelInfo("default", kernel_default);
}
KernelInfo kernel_info_;
};
CCL_NAMESPACE_END

View File

@@ -1,85 +0,0 @@
/*
* Copyright 2011-2021 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "device/cpu/kernel_thread_globals.h"
// clang-format off
#include "kernel/osl/osl_shader.h"
#include "kernel/osl/osl_globals.h"
// clang-format on
#include "util/util_profiling.h"
CCL_NAMESPACE_BEGIN
CPUKernelThreadGlobals::CPUKernelThreadGlobals(const KernelGlobals &kernel_globals,
void *osl_globals_memory,
Profiler &cpu_profiler)
: KernelGlobals(kernel_globals), cpu_profiler_(cpu_profiler)
{
reset_runtime_memory();
#ifdef WITH_OSL
OSLShader::thread_init(this, reinterpret_cast<OSLGlobals *>(osl_globals_memory));
#else
(void)osl_globals_memory;
#endif
}
CPUKernelThreadGlobals::CPUKernelThreadGlobals(CPUKernelThreadGlobals &&other) noexcept
: KernelGlobals(std::move(other)), cpu_profiler_(other.cpu_profiler_)
{
other.reset_runtime_memory();
}
CPUKernelThreadGlobals::~CPUKernelThreadGlobals()
{
#ifdef WITH_OSL
OSLShader::thread_free(this);
#endif
}
CPUKernelThreadGlobals &CPUKernelThreadGlobals::operator=(CPUKernelThreadGlobals &&other)
{
if (this == &other) {
return *this;
}
*static_cast<KernelGlobals *>(this) = *static_cast<KernelGlobals *>(&other);
other.reset_runtime_memory();
return *this;
}
void CPUKernelThreadGlobals::reset_runtime_memory()
{
#ifdef WITH_OSL
osl = nullptr;
#endif
}
void CPUKernelThreadGlobals::start_profiling()
{
cpu_profiler_.add_state(&profiler);
}
void CPUKernelThreadGlobals::stop_profiling()
{
cpu_profiler_.remove_state(&profiler);
}
CCL_NAMESPACE_END

View File

@@ -1,57 +0,0 @@
/*
* Copyright 2011-2021 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "kernel/device/cpu/compat.h"
#include "kernel/device/cpu/globals.h"
CCL_NAMESPACE_BEGIN
class Profiler;
/* A special class which extends memory ownership of the `KernelGlobals` decoupling any resource
* which is not thread-safe for access. Every worker thread which needs to operate on
* `KernelGlobals` needs to initialize its own copy of this object.
*
* NOTE: Only minimal subset of objects are copied: `KernelData` is never copied. This means that
* there is no unnecessary data duplication happening when using this object. */
class CPUKernelThreadGlobals : public KernelGlobals {
public:
/* TODO(sergey): Would be nice to have properly typed OSLGlobals even in the case when building
* without OSL support. Will avoid need to those unnamed pointers and casts. */
CPUKernelThreadGlobals(const KernelGlobals &kernel_globals,
void *osl_globals_memory,
Profiler &cpu_profiler);
~CPUKernelThreadGlobals();
CPUKernelThreadGlobals(const CPUKernelThreadGlobals &other) = delete;
CPUKernelThreadGlobals(CPUKernelThreadGlobals &&other) noexcept;
CPUKernelThreadGlobals &operator=(const CPUKernelThreadGlobals &other) = delete;
CPUKernelThreadGlobals &operator=(CPUKernelThreadGlobals &&other);
void start_profiling();
void stop_profiling();
protected:
void reset_runtime_memory();
Profiler &cpu_profiler_;
};
CCL_NAMESPACE_END

View File

@@ -0,0 +1,270 @@
/*
* Copyright 2011-2013 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef WITH_CUDA
# include "device/device.h"
# include "device/device_denoising.h"
# include "device/device_split_kernel.h"
# include "util/util_map.h"
# include "util/util_task.h"
# ifdef WITH_CUDA_DYNLOAD
# include "cuew.h"
# else
# include "util/util_opengl.h"
# include <cuda.h>
# include <cudaGL.h>
# endif
CCL_NAMESPACE_BEGIN
class CUDASplitKernel;
class CUDADevice : public Device {
friend class CUDASplitKernelFunction;
friend class CUDASplitKernel;
friend class CUDAContextScope;
public:
DedicatedTaskPool task_pool;
CUdevice cuDevice;
CUcontext cuContext;
CUmodule cuModule, cuFilterModule;
size_t device_texture_headroom;
size_t device_working_headroom;
bool move_texture_to_host;
size_t map_host_used;
size_t map_host_limit;
int can_map_host;
int pitch_alignment;
int cuDevId;
int cuDevArchitecture;
bool first_error;
CUDASplitKernel *split_kernel;
struct CUDAMem {
CUDAMem() : texobject(0), array(0), use_mapped_host(false)
{
}
CUtexObject texobject;
CUarray array;
/* If true, a mapped host memory in shared_pointer is being used. */
bool use_mapped_host;
};
typedef map<device_memory *, CUDAMem> CUDAMemMap;
CUDAMemMap cuda_mem_map;
thread_mutex cuda_mem_map_mutex;
struct PixelMem {
GLuint cuPBO;
CUgraphicsResource cuPBOresource;
GLuint cuTexId;
int w, h;
};
map<device_ptr, PixelMem> pixel_mem_map;
/* Bindless Textures */
device_vector<TextureInfo> texture_info;
bool need_texture_info;
/* Kernels */
struct {
bool loaded;
CUfunction adaptive_stopping;
CUfunction adaptive_filter_x;
CUfunction adaptive_filter_y;
CUfunction adaptive_scale_samples;
int adaptive_num_threads_per_block;
} functions;
static bool have_precompiled_kernels();
virtual bool show_samples() const override;
virtual BVHLayoutMask get_bvh_layout_mask() const override;
void set_error(const string &error) override;
CUDADevice(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background_);
virtual ~CUDADevice();
bool support_device(const DeviceRequestedFeatures & /*requested_features*/);
bool check_peer_access(Device *peer_device) override;
bool use_adaptive_compilation();
bool use_split_kernel();
virtual string compile_kernel_get_common_cflags(
const DeviceRequestedFeatures &requested_features, bool filter = false, bool split = false);
string compile_kernel(const DeviceRequestedFeatures &requested_features,
const char *name,
const char *base = "cuda",
bool force_ptx = false);
virtual bool load_kernels(const DeviceRequestedFeatures &requested_features) override;
void load_functions();
void reserve_local_memory(const DeviceRequestedFeatures &requested_features);
void init_host_memory();
void load_texture_info();
void move_textures_to_host(size_t size, bool for_texture);
CUDAMem *generic_alloc(device_memory &mem, size_t pitch_padding = 0);
void generic_copy_to(device_memory &mem);
void generic_free(device_memory &mem);
void mem_alloc(device_memory &mem) override;
void mem_copy_to(device_memory &mem) override;
void mem_copy_from(device_memory &mem, int y, int w, int h, int elem) override;
void mem_zero(device_memory &mem) override;
void mem_free(device_memory &mem) override;
device_ptr mem_alloc_sub_ptr(device_memory &mem, int offset, int /*size*/) override;
virtual void const_copy_to(const char *name, void *host, size_t size) override;
void global_alloc(device_memory &mem);
void global_free(device_memory &mem);
void tex_alloc(device_texture &mem);
void tex_free(device_texture &mem);
bool denoising_non_local_means(device_ptr image_ptr,
device_ptr guide_ptr,
device_ptr variance_ptr,
device_ptr out_ptr,
DenoisingTask *task);
bool denoising_construct_transform(DenoisingTask *task);
bool denoising_accumulate(device_ptr color_ptr,
device_ptr color_variance_ptr,
device_ptr scale_ptr,
int frame,
DenoisingTask *task);
bool denoising_solve(device_ptr output_ptr, DenoisingTask *task);
bool denoising_combine_halves(device_ptr a_ptr,
device_ptr b_ptr,
device_ptr mean_ptr,
device_ptr variance_ptr,
int r,
int4 rect,
DenoisingTask *task);
bool denoising_divide_shadow(device_ptr a_ptr,
device_ptr b_ptr,
device_ptr sample_variance_ptr,
device_ptr sv_variance_ptr,
device_ptr buffer_variance_ptr,
DenoisingTask *task);
bool denoising_get_feature(int mean_offset,
int variance_offset,
device_ptr mean_ptr,
device_ptr variance_ptr,
float scale,
DenoisingTask *task);
bool denoising_write_feature(int out_offset,
device_ptr from_ptr,
device_ptr buffer_ptr,
DenoisingTask *task);
bool denoising_detect_outliers(device_ptr image_ptr,
device_ptr variance_ptr,
device_ptr depth_ptr,
device_ptr output_ptr,
DenoisingTask *task);
void denoise(RenderTile &rtile, DenoisingTask &denoising);
void adaptive_sampling_filter(uint filter_sample,
WorkTile *wtile,
CUdeviceptr d_wtile,
CUstream stream = 0);
void adaptive_sampling_post(RenderTile &rtile,
WorkTile *wtile,
CUdeviceptr d_wtile,
CUstream stream = 0);
void render(DeviceTask &task, RenderTile &rtile, device_vector<WorkTile> &work_tiles);
void film_convert(DeviceTask &task,
device_ptr buffer,
device_ptr rgba_byte,
device_ptr rgba_half);
void shader(DeviceTask &task);
CUdeviceptr map_pixels(device_ptr mem);
void unmap_pixels(device_ptr mem);
void pixels_alloc(device_memory &mem);
void pixels_copy_from(device_memory &mem, int y, int w, int h);
void pixels_free(device_memory &mem);
void draw_pixels(device_memory &mem,
int y,
int w,
int h,
int width,
int height,
int dx,
int dy,
int dw,
int dh,
bool transparent,
const DeviceDrawParams &draw_params) override;
void thread_run(DeviceTask &task);
virtual void task_add(DeviceTask &task) override;
virtual void task_wait() override;
virtual void task_cancel() override;
};
CCL_NAMESPACE_END
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,154 +0,0 @@
/*
* Copyright 2011-2013 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef WITH_CUDA
# include "device/cuda/kernel.h"
# include "device/cuda/queue.h"
# include "device/cuda/util.h"
# include "device/device.h"
# include "util/util_map.h"
# ifdef WITH_CUDA_DYNLOAD
# include "cuew.h"
# else
# include <cuda.h>
# include <cudaGL.h>
# endif
CCL_NAMESPACE_BEGIN
class DeviceQueue;
class CUDADevice : public Device {
friend class CUDAContextScope;
public:
CUdevice cuDevice;
CUcontext cuContext;
CUmodule cuModule;
size_t device_texture_headroom;
size_t device_working_headroom;
bool move_texture_to_host;
size_t map_host_used;
size_t map_host_limit;
int can_map_host;
int pitch_alignment;
int cuDevId;
int cuDevArchitecture;
bool first_error;
struct CUDAMem {
CUDAMem() : texobject(0), array(0), use_mapped_host(false)
{
}
CUtexObject texobject;
CUarray array;
/* If true, a mapped host memory in shared_pointer is being used. */
bool use_mapped_host;
};
typedef map<device_memory *, CUDAMem> CUDAMemMap;
CUDAMemMap cuda_mem_map;
thread_mutex cuda_mem_map_mutex;
/* Bindless Textures */
device_vector<TextureInfo> texture_info;
bool need_texture_info;
CUDADeviceKernels kernels;
static bool have_precompiled_kernels();
virtual bool show_samples() const override;
virtual BVHLayoutMask get_bvh_layout_mask() const override;
void set_error(const string &error) override;
CUDADevice(const DeviceInfo &info, Stats &stats, Profiler &profiler);
virtual ~CUDADevice();
bool support_device(const uint /*kernel_features*/);
bool check_peer_access(Device *peer_device) override;
bool use_adaptive_compilation();
virtual string compile_kernel_get_common_cflags(const uint kernel_features);
string compile_kernel(const uint kernel_features,
const char *name,
const char *base = "cuda",
bool force_ptx = false);
virtual bool load_kernels(const uint kernel_features) override;
void reserve_local_memory(const uint kernel_features);
void init_host_memory();
void load_texture_info();
void move_textures_to_host(size_t size, bool for_texture);
CUDAMem *generic_alloc(device_memory &mem, size_t pitch_padding = 0);
void generic_copy_to(device_memory &mem);
void generic_free(device_memory &mem);
void mem_alloc(device_memory &mem) override;
void mem_copy_to(device_memory &mem) override;
void mem_copy_from(device_memory &mem, size_t y, size_t w, size_t h, size_t elem) override;
void mem_zero(device_memory &mem) override;
void mem_free(device_memory &mem) override;
device_ptr mem_alloc_sub_ptr(device_memory &mem, size_t offset, size_t /*size*/) override;
virtual void const_copy_to(const char *name, void *host, size_t size) override;
void global_alloc(device_memory &mem);
void global_free(device_memory &mem);
void tex_alloc(device_texture &mem);
void tex_free(device_texture &mem);
virtual bool should_use_graphics_interop() override;
virtual unique_ptr<DeviceQueue> gpu_queue_create() override;
int get_num_multiprocessors();
int get_max_num_threads_per_multiprocessor();
protected:
bool get_device_attribute(CUdevice_attribute attribute, int *value);
int get_device_default_attribute(CUdevice_attribute attribute, int default_value);
};
CCL_NAMESPACE_END
#endif

View File

@@ -1,102 +0,0 @@
/*
* Copyright 2011-2021 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef WITH_CUDA
# include "device/cuda/graphics_interop.h"
# include "device/cuda/device_impl.h"
# include "device/cuda/util.h"
CCL_NAMESPACE_BEGIN
CUDADeviceGraphicsInterop::CUDADeviceGraphicsInterop(CUDADeviceQueue *queue)
: queue_(queue), device_(static_cast<CUDADevice *>(queue->device))
{
}
CUDADeviceGraphicsInterop::~CUDADeviceGraphicsInterop()
{
CUDAContextScope scope(device_);
if (cu_graphics_resource_) {
cuda_device_assert(device_, cuGraphicsUnregisterResource(cu_graphics_resource_));
}
}
void CUDADeviceGraphicsInterop::set_destination(
const DeviceGraphicsInteropDestination &destination)
{
const int64_t new_buffer_area = int64_t(destination.buffer_width) * destination.buffer_height;
need_clear_ = destination.need_clear;
if (opengl_pbo_id_ == destination.opengl_pbo_id && buffer_area_ == new_buffer_area) {
return;
}
CUDAContextScope scope(device_);
if (cu_graphics_resource_) {
cuda_device_assert(device_, cuGraphicsUnregisterResource(cu_graphics_resource_));
}
const CUresult result = cuGraphicsGLRegisterBuffer(
&cu_graphics_resource_, destination.opengl_pbo_id, CU_GRAPHICS_MAP_RESOURCE_FLAGS_NONE);
if (result != CUDA_SUCCESS) {
LOG(ERROR) << "Error registering OpenGL buffer: " << cuewErrorString(result);
}
opengl_pbo_id_ = destination.opengl_pbo_id;
buffer_area_ = new_buffer_area;
}
device_ptr CUDADeviceGraphicsInterop::map()
{
if (!cu_graphics_resource_) {
return 0;
}
CUDAContextScope scope(device_);
CUdeviceptr cu_buffer;
size_t bytes;
cuda_device_assert(device_, cuGraphicsMapResources(1, &cu_graphics_resource_, queue_->stream()));
cuda_device_assert(
device_, cuGraphicsResourceGetMappedPointer(&cu_buffer, &bytes, cu_graphics_resource_));
if (need_clear_) {
cuda_device_assert(
device_, cuMemsetD8Async(static_cast<CUdeviceptr>(cu_buffer), 0, bytes, queue_->stream()));
need_clear_ = false;
}
return static_cast<device_ptr>(cu_buffer);
}
void CUDADeviceGraphicsInterop::unmap()
{
CUDAContextScope scope(device_);
cuda_device_assert(device_,
cuGraphicsUnmapResources(1, &cu_graphics_resource_, queue_->stream()));
}
CCL_NAMESPACE_END
#endif

View File

@@ -1,66 +0,0 @@
/*
* Copyright 2011-2021 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef WITH_CUDA
# include "device/device_graphics_interop.h"
# ifdef WITH_CUDA_DYNLOAD
# include "cuew.h"
# else
# include <cuda.h>
# endif
CCL_NAMESPACE_BEGIN
class CUDADevice;
class CUDADeviceQueue;
class CUDADeviceGraphicsInterop : public DeviceGraphicsInterop {
public:
explicit CUDADeviceGraphicsInterop(CUDADeviceQueue *queue);
CUDADeviceGraphicsInterop(const CUDADeviceGraphicsInterop &other) = delete;
CUDADeviceGraphicsInterop(CUDADeviceGraphicsInterop &&other) noexcept = delete;
~CUDADeviceGraphicsInterop();
CUDADeviceGraphicsInterop &operator=(const CUDADeviceGraphicsInterop &other) = delete;
CUDADeviceGraphicsInterop &operator=(CUDADeviceGraphicsInterop &&other) = delete;
virtual void set_destination(const DeviceGraphicsInteropDestination &destination) override;
virtual device_ptr map() override;
virtual void unmap() override;
protected:
CUDADeviceQueue *queue_ = nullptr;
CUDADevice *device_ = nullptr;
/* OpenGL PBO which is currently registered as the destination for the CUDA buffer. */
uint opengl_pbo_id_ = 0;
/* Buffer area in pixels of the corresponding PBO. */
int64_t buffer_area_ = 0;
/* The destination was requested to be cleared. */
bool need_clear_ = false;
CUgraphicsResource cu_graphics_resource_ = nullptr;
};
CCL_NAMESPACE_END
#endif

View File

@@ -1,69 +0,0 @@
/*
* Copyright 2011-2013 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef WITH_CUDA
# include "device/cuda/kernel.h"
# include "device/cuda/device_impl.h"
CCL_NAMESPACE_BEGIN
void CUDADeviceKernels::load(CUDADevice *device)
{
CUmodule cuModule = device->cuModule;
for (int i = 0; i < (int)DEVICE_KERNEL_NUM; i++) {
CUDADeviceKernel &kernel = kernels_[i];
/* No mega-kernel used for GPU. */
if (i == DEVICE_KERNEL_INTEGRATOR_MEGAKERNEL) {
continue;
}
const std::string function_name = std::string("kernel_gpu_") +
device_kernel_as_string((DeviceKernel)i);
cuda_device_assert(device,
cuModuleGetFunction(&kernel.function, cuModule, function_name.c_str()));
if (kernel.function) {
cuda_device_assert(device, cuFuncSetCacheConfig(kernel.function, CU_FUNC_CACHE_PREFER_L1));
cuda_device_assert(
device,
cuOccupancyMaxPotentialBlockSize(
&kernel.min_blocks, &kernel.num_threads_per_block, kernel.function, NULL, 0, 0));
}
else {
LOG(ERROR) << "Unable to load kernel " << function_name;
}
}
loaded = true;
}
const CUDADeviceKernel &CUDADeviceKernels::get(DeviceKernel kernel) const
{
return kernels_[(int)kernel];
}
bool CUDADeviceKernels::available(DeviceKernel kernel) const
{
return kernels_[(int)kernel].function != nullptr;
}
CCL_NAMESPACE_END
#endif /* WITH_CUDA*/

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