Cycles/Blender API redesign #79131
Labels
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser
Interest
Asset Browser Project Overview
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
EEVEE & Viewport
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
EEVEE & Viewport
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
8 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: blender/blender#79131
Loading…
Reference in New Issue
No description provided.
Delete Branch "%!s(<nil>)"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
This design task is to propose and discuss ideas related to improvements to the Cycles API. Proposed changes will affect the Blender session and scene synchronization.
Problem
The current API to create a Cycles scene is too specific to the data types and exposes internal behaviors and class members to API users (clients hereafter). There exists a system in place, using the concept of Nodes and Sockets, to unify Cycles objects, and to generically manipulate them. The Nodes represent the objects (like a Mesh or a Light) and the Sockets represent their properties (like their vertices or intensity). However, it is not used throughout the API and clients have to directly manipulate certain properties in an unsafe manner. This direct manipulation has also two drawbacks related to scene updates. On one hand, we have to manually tag the objects or the system for an update; forgetting this can lead to missing objects or shaders in the render. On the other hand, there is no real way of telling what exactly has changed, so we may resort to making unnecessary work: simply modifying the vertex positions, without using displacement, should not free the device memory, but could simply copy the new positions in place (granularity of updates and fast scene rebuild shall be discussed in a separate task).
Ideally, the API should be simple, as generic as possible (i.e. to add the same shader to different nodes sharing a common property) while still allowing for strict typing (meaning we should not be able to set vertices on a camera if we know it is a Camera). Tagging for an update, and other bookkeeping behaviors if any, should become automatic. For this, we have to generalize the concept of Nodes and Sockets and use it throughout the public API. This will encapsulate internal behaviors for individual Nodes and the entire scene.
Abstraction
Every object accessible through the public API should become a Node, and public members of C++ classes in the current API, should be marked private.
Each node will have publicly accessible members exposed as sockets through setters/getters. Other member variables will be private and not be exposed as sockets.
Getters/Setters
Accessing sockets should be done via the various methods of the Node class. The different subclasses (Mesh, Curve, Light, etc.) could have more specific APIs to access and modify data.
For example, the
vertices
socket on the Mesh Node could be either accessed thoughNode::get_float3_array("vertices")
orMesh::get_vertices()
. The specific APIs can get huge if done for every property, so it could either be constrained to only commonly used properties, or its generation could be automated somehow.The reason to have
Mesh::get_vertices()
is for type safety, if the Cycles sockets change then there will be a compile error rather than a runtime error.Updates
The
X::tag_update(scene)
will become automatic on socket (and attribute) changes. Each socket will have an associated bitflag, and when the socket value set function is called and the value is different, that bitflag will be set on the node.Current logic in
tag_update
for indirectly tagging other nodes for update will be done later, as part of scene update.Internally, some optimizations might be done to immediately also tag managers for update, or add updated nodes to a set so it is not required to loop over all nodes in scene update. This kind of optimization can be done as a second step.
D8644: Cycles: add update flags to Node and SocketType
Attributes
Geometry attributes are similar to sockets, but we prefer to keep them separate. This is to ensure there are no name collisions with sockets, and to support additional features and slightly different behavior where needed.
Attributes would use the same update flag mechanism. For performance reasons, comparing the old and new values detect if there was an actual changes would be optional. If the caller knows that the values has changed, it would be a waste of time to compare memory on a large array.
Further, we should support attributes taking ownership of array pointers rather than copying the array contents. For example for a system that already has vertex locations cached in memory for the entire animation, no expensive copy should be required.
Similarly for motion blur, we can have an efficient way to shift the motion blur steps, removing the first step and adding a new step at the end. For this each step would need to be stored in a separate array, rather than a single array with all time steps as is done now.
Creating Nodes and Ownership
Creating (and deleting) Nodes of various types should be done via an API (perhaps
Scene::create_*_node()
), instead of naively callingnew
anddelete
.Nodes will optionally have an owner, to support #79174 (Cycles Procedural API and faster scene update). This ensures that when Alembic or USD procedurals create nodes, e.g. the Blender exporter will not try to delete them. Rather they would be owned by a procedural node, and deleted along with it.
D8540: Cycles: introduce an ownership system to define if nodes should be removed from the scene.
Node Types
The available node types would be the same as the existing ones, plus a few additional ones to make the whole system more consistent.
Serialization
If the entire data structure is node based, serializing entire scenes becomes possible. However defining our own supported file format is not a goal, and we will likely just remove the XML support for now. Instead we should document the API well with examples.
Example
Here's an (incomplete) example on how rendering a simple scene would look like. The idea is to render something with the minimum amount of setup. This is using an approach where data is accessed using a specific API for each Node Type. A more complete example for the Mesh Node can be made.
Added subscriber: @kevindietrich
Added subscriber: @LazyDodo
First of all I love the approach of starting from a hypothetical client using the API.
This seems somewhat counter intuitive, perhaps
ccl::array<ccl::int3>
was meant here?This bit will need a bit of work, as the example is currently structured this would probably be more intuitive in
session
rather thanscene
, scene ideally is a scene description, it ought to not concern it self with hardware enumeration/configuration.Added subscriber: @fx
Added subscriber: @KenzieMac130
Ah yes, it's a typo.
I agree, the idea is to make everything a node and to centralize a bit node creation, since most nodes are in the scene it made sense to have the scene create all of them. The Scene already contains a pointer to the Device, however it does not create it.
This issue was referenced by blender/cycles@5c8fb3c37c
This issue was referenced by blender/cycles@4c672f0163
This issue was referenced by
aa1e4baa22
This issue was referenced by blender/cycles@c19302e499
This issue was referenced by
429afe0c62
This issue was referenced by blender/cycles@d3720f188c
This issue was referenced by
626201683e
Added subscriber: @BartekMoniewski
Added subscriber: @larrywberg
Hi Guys. My first time here on the forum.
I would like to put in a vote to keep xml parsing compiling if it's not causing specific problems.
I am currently porting the latest cycles into a new version of Poser and have been fleshing out the xml for our use. I could share back to the community any parts of it that would be commonly useful if you keep the xml files in place.
Changed status from 'Needs Triage' to: 'Confirmed'
Added subscriber: @brecht
So @kevindietrich has done a bunch of work to get us closer to the code sample in the original post, but we're not there yet.
We still have the concept of
SceneParams
,SessionParams
which are not exactly like nodes. The Session needs to be recreated when adding devices or enabled denoising. And it's not obvious when you can edit a Session's scene, how to mutex luck, when to reset, etc. There's still a bunch oftag_update
calls that need to be made when changing certain data. And for denoising the user needs to manually sync some data between various Cycles data structures.Ideally we can get towards a state where the scene and it's nodes can just be updated, and then the Session can figure out what to do in response to that. Restart the render if needed, recreate devices, etc.
Following the above example code, dynamically updating the scene in an interactive session should ideally be something like this.
I did some work towards this in a branch, and will post some WIP patches soon. Adding the basic begin/end scene edit mechanism, eliminating the need to call
tag_update()
, and did some work towards making denoising and passes be handled more automatically.However there's still some significant roadblocks towards getting it this simple, and I'm not sure it's entirely practical. For example recreating devices (also for denoising) or changing the shading system between SVM/OSL seems impractical. That's because they persistently modify scene data and do not keep around the original for memory efficiency and ease of implementation. So I think there are a few high-level parameters that we may not allow changing dynamically, and that will continue to require recreating the session in an interactive session. But we should be able to minimize and document them.