2011-04-27 11:58:34 +00:00
|
|
|
/*
|
2013-08-18 14:16:15 +00:00
|
|
|
* Copyright 2011-2013 Blender Foundation
|
2011-04-27 11:58:34 +00:00
|
|
|
*
|
2013-08-18 14:16:15 +00:00
|
|
|
* 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
|
2011-04-27 11:58:34 +00:00
|
|
|
*
|
2013-08-18 14:16:15 +00:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2011-04-27 11:58:34 +00:00
|
|
|
*
|
2013-08-18 14:16:15 +00:00
|
|
|
* 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
|
2014-12-25 01:50:24 +00:00
|
|
|
* limitations under the License.
|
2011-04-27 11:58:34 +00:00
|
|
|
*/
|
|
|
|
|
Cycles: Make all #include statements relative to cycles source directory
The idea is to make include statements more explicit and obvious where the
file is coming from, additionally reducing chance of wrong header being
picked up.
For example, it was not obvious whether bvh.h was refferring to builder
or traversal, whenter node.h is a generic graph node or a shader node
and cases like that.
Surely this might look obvious for the active developers, but after some
time of not touching the code it becomes less obvious where file is coming
from.
This was briefly mentioned in T50824 and seems @brecht is fine with such
explicitness, but need to agree with all active developers before committing
this.
Please note that this patch is lacking changes related on GPU/OpenCL
support. This will be solved if/when we all agree this is a good idea to move
forward.
Reviewers: brecht, lukasstockner97, maiself, nirved, dingto, juicyfruit, swerner
Reviewed By: lukasstockner97, maiself, nirved, dingto
Subscribers: brecht
Differential Revision: https://developer.blender.org/D2586
2017-03-28 18:39:14 +00:00
|
|
|
#include "device/device.h"
|
2020-01-20 12:42:26 +00:00
|
|
|
|
2021-10-24 12:19:19 +00:00
|
|
|
#include "scene/background.h"
|
|
|
|
#include "scene/light.h"
|
|
|
|
#include "scene/mesh.h"
|
|
|
|
#include "scene/scene.h"
|
|
|
|
#include "scene/shader.h"
|
|
|
|
#include "scene/shader_graph.h"
|
|
|
|
#include "scene/shader_nodes.h"
|
|
|
|
#include "scene/stats.h"
|
|
|
|
#include "scene/svm.h"
|
Cycles: Make all #include statements relative to cycles source directory
The idea is to make include statements more explicit and obvious where the
file is coming from, additionally reducing chance of wrong header being
picked up.
For example, it was not obvious whether bvh.h was refferring to builder
or traversal, whenter node.h is a generic graph node or a shader node
and cases like that.
Surely this might look obvious for the active developers, but after some
time of not touching the code it becomes less obvious where file is coming
from.
This was briefly mentioned in T50824 and seems @brecht is fine with such
explicitness, but need to agree with all active developers before committing
this.
Please note that this patch is lacking changes related on GPU/OpenCL
support. This will be solved if/when we all agree this is a good idea to move
forward.
Reviewers: brecht, lukasstockner97, maiself, nirved, dingto, juicyfruit, swerner
Reviewed By: lukasstockner97, maiself, nirved, dingto
Subscribers: brecht
Differential Revision: https://developer.blender.org/D2586
2017-03-28 18:39:14 +00:00
|
|
|
|
2021-10-24 12:19:19 +00:00
|
|
|
#include "util/foreach.h"
|
|
|
|
#include "util/log.h"
|
|
|
|
#include "util/progress.h"
|
|
|
|
#include "util/task.h"
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
CCL_NAMESPACE_BEGIN
|
|
|
|
|
|
|
|
/* Shader Manager */
|
|
|
|
|
|
|
|
SVMShaderManager::SVMShaderManager()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
SVMShaderManager::~SVMShaderManager()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2015-03-27 10:47:55 +00:00
|
|
|
void SVMShaderManager::reset(Scene * /*scene*/)
|
2013-02-14 16:11:47 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-10-21 12:52:34 +00:00
|
|
|
void SVMShaderManager::device_update_shader(Scene *scene,
|
|
|
|
Shader *shader,
|
|
|
|
Progress *progress,
|
|
|
|
array<int4> *svm_nodes)
|
2016-09-09 10:27:51 +00:00
|
|
|
{
|
|
|
|
if (progress->get_cancel()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
assert(shader->graph);
|
|
|
|
|
2019-07-31 06:29:18 +00:00
|
|
|
svm_nodes->push_back_slow(make_int4(NODE_SHADER_JUMP, 0, 0, 0));
|
2016-09-09 10:27:51 +00:00
|
|
|
|
|
|
|
SVMCompiler::Summary summary;
|
Add support for tiled images and the UDIM naming scheme
This patch contains the work that I did during my week at the Code Quest - adding support for tiled images to Blender.
With this patch, images now contain a list of tiles. By default, this just contains one tile, but if the source type is set to Tiled, the user can add additional tiles. When acquiring an ImBuf, the tile to be loaded is specified in the ImageUser.
Therefore, code that is not yet aware of tiles will just access the default tile as usual.
The filenames of the additional tiles are derived from the original filename according to the UDIM naming scheme - the filename contains an index that is calculated as (1001 + 10*<y coordinate of the tile> + <x coordinate of the tile>), where the x coordinate never goes above 9.
Internally, the various tiles are stored in a cache just like sequences. When acquired for the first time, the code will try to load the corresponding file from disk. Alternatively, a new operator can be used to initialize the tile similar to the New Image operator.
The following features are supported so far:
- Automatic detection and loading of all tiles when opening the first tile (1001)
- Saving all tiles
- Adding and removing tiles
- Filling tiles with generated images
- Drawing all tiles in the Image Editor
- Viewing a tiled grid even if no image is selected
- Rendering tiled images in Eevee
- Rendering tiled images in Cycles (in SVM mode)
- Automatically skipping loading of unused tiles in Cycles
- 2D texture painting (also across tiles)
- 3D texture painting (also across tiles, only limitation: individual faces can not cross tile borders)
- Assigning custom labels to individual tiles (drawn in the Image Editor instead of the ID)
- Different resolutions between tiles
There still are some missing features that will be added later (see T72390):
- Workbench engine support
- Packing/Unpacking support
- Baking support
- Cycles OSL support
- many other Blender features that rely on images
Thanks to Brecht for the review and to all who tested the intermediate versions!
Differential Revision: https://developer.blender.org/D3509
2019-12-12 15:06:08 +00:00
|
|
|
SVMCompiler compiler(scene);
|
2020-01-20 12:42:26 +00:00
|
|
|
compiler.background = (shader == scene->background->get_shader(scene));
|
Add support for tiled images and the UDIM naming scheme
This patch contains the work that I did during my week at the Code Quest - adding support for tiled images to Blender.
With this patch, images now contain a list of tiles. By default, this just contains one tile, but if the source type is set to Tiled, the user can add additional tiles. When acquiring an ImBuf, the tile to be loaded is specified in the ImageUser.
Therefore, code that is not yet aware of tiles will just access the default tile as usual.
The filenames of the additional tiles are derived from the original filename according to the UDIM naming scheme - the filename contains an index that is calculated as (1001 + 10*<y coordinate of the tile> + <x coordinate of the tile>), where the x coordinate never goes above 9.
Internally, the various tiles are stored in a cache just like sequences. When acquired for the first time, the code will try to load the corresponding file from disk. Alternatively, a new operator can be used to initialize the tile similar to the New Image operator.
The following features are supported so far:
- Automatic detection and loading of all tiles when opening the first tile (1001)
- Saving all tiles
- Adding and removing tiles
- Filling tiles with generated images
- Drawing all tiles in the Image Editor
- Viewing a tiled grid even if no image is selected
- Rendering tiled images in Eevee
- Rendering tiled images in Cycles (in SVM mode)
- Automatically skipping loading of unused tiles in Cycles
- 2D texture painting (also across tiles)
- 3D texture painting (also across tiles, only limitation: individual faces can not cross tile borders)
- Assigning custom labels to individual tiles (drawn in the Image Editor instead of the ID)
- Different resolutions between tiles
There still are some missing features that will be added later (see T72390):
- Workbench engine support
- Packing/Unpacking support
- Baking support
- Cycles OSL support
- many other Blender features that rely on images
Thanks to Brecht for the review and to all who tested the intermediate versions!
Differential Revision: https://developer.blender.org/D3509
2019-12-12 15:06:08 +00:00
|
|
|
compiler.compile(shader, *svm_nodes, 0, &summary);
|
2016-09-09 10:27:51 +00:00
|
|
|
|
2021-10-31 12:30:56 +00:00
|
|
|
VLOG(3) << "Compilation summary:\n"
|
2016-09-09 10:27:51 +00:00
|
|
|
<< "Shader name: " << shader->name << "\n"
|
|
|
|
<< summary.full_report();
|
|
|
|
}
|
|
|
|
|
2021-05-02 00:34:56 +00:00
|
|
|
void SVMShaderManager::device_update_specific(Device *device,
|
|
|
|
DeviceScene *dscene,
|
|
|
|
Scene *scene,
|
|
|
|
Progress &progress)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
Cycles: optimize device updates
This optimizes device updates (during user edits or frame changes in
the viewport) by avoiding unnecessary computations. To achieve this,
we use a combination of the sockets' update flags as well as some new
flags passed to the various managers when tagging for an update to tell
exactly what the tagging is for (e.g. shader was modified, object was
removed, etc.).
Besides avoiding recomputations, we also avoid resending to the devices
unmodified data arrays, thus reducing bandwidth usage. For OptiX and
Embree, BVH packing was also multithreaded.
The performance improvements may vary depending on the used device (CPU
or GPU), and the content of the scene. Simple scenes (e.g. with no adaptive
subdivision or volumes) rendered using OptiX will benefit from this work
the most.
On average, for a variety of animated scenes, this gives a 3x speedup.
Reviewed By: #cycles, brecht
Maniphest Tasks: T79174
Differential Revision: https://developer.blender.org/D9555
2021-01-22 14:01:26 +00:00
|
|
|
if (!need_update())
|
2011-04-27 11:58:34 +00:00
|
|
|
return;
|
|
|
|
|
2020-10-01 21:16:01 +00:00
|
|
|
scoped_callback_timer timer([scene](double time) {
|
|
|
|
if (scene->update_stats) {
|
|
|
|
scene->update_stats->svm.times.add_entry({"device_update", time});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2019-07-31 06:29:18 +00:00
|
|
|
const int num_shaders = scene->shaders.size();
|
|
|
|
|
|
|
|
VLOG(1) << "Total " << num_shaders << " shaders.";
|
2016-04-22 08:55:26 +00:00
|
|
|
|
2016-09-09 09:39:27 +00:00
|
|
|
double start_time = time_dt();
|
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
/* test if we need to update */
|
2013-04-01 20:26:52 +00:00
|
|
|
device_free(device, dscene, scene);
|
2011-04-27 11:58:34 +00:00
|
|
|
|
2021-10-21 12:52:34 +00:00
|
|
|
/* Build all shaders. */
|
|
|
|
TaskPool task_pool;
|
|
|
|
vector<array<int4>> shader_svm_nodes(num_shaders);
|
|
|
|
for (int i = 0; i < num_shaders; i++) {
|
|
|
|
task_pool.push(function_bind(&SVMShaderManager::device_update_shader,
|
|
|
|
this,
|
|
|
|
scene,
|
|
|
|
scene->shaders[i],
|
|
|
|
&progress,
|
|
|
|
&shader_svm_nodes[i]));
|
|
|
|
}
|
|
|
|
task_pool.wait_work();
|
|
|
|
|
2016-09-09 10:27:51 +00:00
|
|
|
if (progress.get_cancel()) {
|
|
|
|
return;
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
2019-07-31 06:29:18 +00:00
|
|
|
/* The global node list contains a jump table (one node per shader)
|
|
|
|
* followed by the nodes of all shaders. */
|
|
|
|
int svm_nodes_size = num_shaders;
|
|
|
|
for (int i = 0; i < num_shaders; i++) {
|
|
|
|
/* Since we're not copying the local jump node, the size ends up being one node lower. */
|
2021-10-21 12:52:34 +00:00
|
|
|
svm_nodes_size += shader_svm_nodes[i].size() - 1;
|
2019-07-31 06:29:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int4 *svm_nodes = dscene->svm_nodes.alloc(svm_nodes_size);
|
2011-04-27 11:58:34 +00:00
|
|
|
|
2019-07-31 06:29:18 +00:00
|
|
|
int node_offset = num_shaders;
|
|
|
|
for (int i = 0; i < num_shaders; i++) {
|
2011-04-27 11:58:34 +00:00
|
|
|
Shader *shader = scene->shaders[i];
|
2019-07-31 06:29:18 +00:00
|
|
|
|
2020-11-04 10:17:38 +00:00
|
|
|
shader->clear_modified();
|
|
|
|
if (shader->get_use_mis() && shader->has_surface_emission) {
|
Cycles: optimize device updates
This optimizes device updates (during user edits or frame changes in
the viewport) by avoiding unnecessary computations. To achieve this,
we use a combination of the sockets' update flags as well as some new
flags passed to the various managers when tagging for an update to tell
exactly what the tagging is for (e.g. shader was modified, object was
removed, etc.).
Besides avoiding recomputations, we also avoid resending to the devices
unmodified data arrays, thus reducing bandwidth usage. For OptiX and
Embree, BVH packing was also multithreaded.
The performance improvements may vary depending on the used device (CPU
or GPU), and the content of the scene. Simple scenes (e.g. with no adaptive
subdivision or volumes) rendered using OptiX will benefit from this work
the most.
On average, for a variety of animated scenes, this gives a 3x speedup.
Reviewed By: #cycles, brecht
Maniphest Tasks: T79174
Differential Revision: https://developer.blender.org/D9555
2021-01-22 14:01:26 +00:00
|
|
|
scene->light_manager->tag_update(scene, LightManager::SHADER_COMPILED);
|
2019-07-31 06:29:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Update the global jump table.
|
|
|
|
* Each compiled shader starts with a jump node that has offsets local
|
|
|
|
* to the shader, so copy those and add the offset into the global node list. */
|
|
|
|
int4 &global_jump_node = svm_nodes[shader->id];
|
2021-10-21 12:52:34 +00:00
|
|
|
int4 &local_jump_node = shader_svm_nodes[i][0];
|
2019-07-31 06:29:18 +00:00
|
|
|
|
|
|
|
global_jump_node.x = NODE_SHADER_JUMP;
|
|
|
|
global_jump_node.y = local_jump_node.y - 1 + node_offset;
|
|
|
|
global_jump_node.z = local_jump_node.z - 1 + node_offset;
|
|
|
|
global_jump_node.w = local_jump_node.w - 1 + node_offset;
|
|
|
|
|
2021-10-21 12:52:34 +00:00
|
|
|
node_offset += shader_svm_nodes[i].size() - 1;
|
2019-07-31 06:29:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Copy the nodes of each shader into the correct location. */
|
|
|
|
svm_nodes += num_shaders;
|
|
|
|
for (int i = 0; i < num_shaders; i++) {
|
2021-10-21 12:52:34 +00:00
|
|
|
int shader_size = shader_svm_nodes[i].size() - 1;
|
2019-07-31 06:29:18 +00:00
|
|
|
|
2021-10-21 12:52:34 +00:00
|
|
|
memcpy(svm_nodes, &shader_svm_nodes[i][1], sizeof(int4) * shader_size);
|
2019-07-31 06:29:18 +00:00
|
|
|
svm_nodes += shader_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (progress.get_cancel()) {
|
|
|
|
return;
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
2019-07-31 06:29:18 +00:00
|
|
|
dscene->svm_nodes.copy_to_device();
|
|
|
|
|
2011-09-27 20:37:24 +00:00
|
|
|
device_update_common(device, dscene, scene, progress);
|
|
|
|
|
Cycles: optimize device updates
This optimizes device updates (during user edits or frame changes in
the viewport) by avoiding unnecessary computations. To achieve this,
we use a combination of the sockets' update flags as well as some new
flags passed to the various managers when tagging for an update to tell
exactly what the tagging is for (e.g. shader was modified, object was
removed, etc.).
Besides avoiding recomputations, we also avoid resending to the devices
unmodified data arrays, thus reducing bandwidth usage. For OptiX and
Embree, BVH packing was also multithreaded.
The performance improvements may vary depending on the used device (CPU
or GPU), and the content of the scene. Simple scenes (e.g. with no adaptive
subdivision or volumes) rendered using OptiX will benefit from this work
the most.
On average, for a variety of animated scenes, this gives a 3x speedup.
Reviewed By: #cycles, brecht
Maniphest Tasks: T79174
Differential Revision: https://developer.blender.org/D9555
2021-01-22 14:01:26 +00:00
|
|
|
update_flags = UPDATE_NONE;
|
2016-09-09 09:39:27 +00:00
|
|
|
|
2019-07-31 06:29:18 +00:00
|
|
|
VLOG(1) << "Shader manager updated " << num_shaders << " shaders in " << time_dt() - start_time
|
|
|
|
<< " seconds.";
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
2013-04-01 20:26:52 +00:00
|
|
|
void SVMShaderManager::device_free(Device *device, DeviceScene *dscene, Scene *scene)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
2013-04-01 20:26:52 +00:00
|
|
|
device_free_common(device, dscene, scene);
|
2011-09-27 20:37:24 +00:00
|
|
|
|
2017-10-20 23:09:59 +00:00
|
|
|
dscene->svm_nodes.free();
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Graph Compiler */
|
|
|
|
|
Add support for tiled images and the UDIM naming scheme
This patch contains the work that I did during my week at the Code Quest - adding support for tiled images to Blender.
With this patch, images now contain a list of tiles. By default, this just contains one tile, but if the source type is set to Tiled, the user can add additional tiles. When acquiring an ImBuf, the tile to be loaded is specified in the ImageUser.
Therefore, code that is not yet aware of tiles will just access the default tile as usual.
The filenames of the additional tiles are derived from the original filename according to the UDIM naming scheme - the filename contains an index that is calculated as (1001 + 10*<y coordinate of the tile> + <x coordinate of the tile>), where the x coordinate never goes above 9.
Internally, the various tiles are stored in a cache just like sequences. When acquired for the first time, the code will try to load the corresponding file from disk. Alternatively, a new operator can be used to initialize the tile similar to the New Image operator.
The following features are supported so far:
- Automatic detection and loading of all tiles when opening the first tile (1001)
- Saving all tiles
- Adding and removing tiles
- Filling tiles with generated images
- Drawing all tiles in the Image Editor
- Viewing a tiled grid even if no image is selected
- Rendering tiled images in Eevee
- Rendering tiled images in Cycles (in SVM mode)
- Automatically skipping loading of unused tiles in Cycles
- 2D texture painting (also across tiles)
- 3D texture painting (also across tiles, only limitation: individual faces can not cross tile borders)
- Assigning custom labels to individual tiles (drawn in the Image Editor instead of the ID)
- Different resolutions between tiles
There still are some missing features that will be added later (see T72390):
- Workbench engine support
- Packing/Unpacking support
- Baking support
- Cycles OSL support
- many other Blender features that rely on images
Thanks to Brecht for the review and to all who tested the intermediate versions!
Differential Revision: https://developer.blender.org/D3509
2019-12-12 15:06:08 +00:00
|
|
|
SVMCompiler::SVMCompiler(Scene *scene) : scene(scene)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
|
|
|
max_stack_use = 0;
|
2011-10-12 23:03:12 +00:00
|
|
|
current_type = SHADER_TYPE_SURFACE;
|
2011-04-27 11:58:34 +00:00
|
|
|
current_shader = NULL;
|
2013-09-03 22:39:21 +00:00
|
|
|
current_graph = NULL;
|
2011-04-27 11:58:34 +00:00
|
|
|
background = false;
|
2011-09-12 13:13:56 +00:00
|
|
|
mix_weight_offset = SVM_STACK_INVALID;
|
2014-01-16 21:36:30 +00:00
|
|
|
compile_failed = false;
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
2016-05-07 23:32:09 +00:00
|
|
|
int SVMCompiler::stack_size(SocketType::Type type)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
2013-05-09 15:20:00 +00:00
|
|
|
int size = 0;
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2015-10-08 14:08:28 +00:00
|
|
|
switch (type) {
|
2016-05-07 23:32:09 +00:00
|
|
|
case SocketType::FLOAT:
|
|
|
|
case SocketType::INT:
|
2013-05-09 15:20:00 +00:00
|
|
|
size = 1;
|
|
|
|
break;
|
2016-05-07 23:32:09 +00:00
|
|
|
case SocketType::COLOR:
|
|
|
|
case SocketType::VECTOR:
|
|
|
|
case SocketType::NORMAL:
|
|
|
|
case SocketType::POINT:
|
2013-05-09 15:20:00 +00:00
|
|
|
size = 3;
|
|
|
|
break;
|
2016-05-07 23:32:09 +00:00
|
|
|
case SocketType::CLOSURE:
|
2013-05-09 15:20:00 +00:00
|
|
|
size = 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert(0);
|
|
|
|
break;
|
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2013-05-09 15:20:00 +00:00
|
|
|
return size;
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
2016-08-14 15:44:25 +00:00
|
|
|
int SVMCompiler::stack_find_offset(int size)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
|
|
|
int offset = -1;
|
2018-07-06 08:17:58 +00:00
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
/* find free space in stack & mark as used */
|
|
|
|
for (int i = 0, num_unused = 0; i < SVM_STACK_SIZE; i++) {
|
|
|
|
if (active_stack.users[i])
|
|
|
|
num_unused = 0;
|
|
|
|
else
|
|
|
|
num_unused++;
|
|
|
|
|
|
|
|
if (num_unused == size) {
|
|
|
|
offset = i + 1 - size;
|
|
|
|
max_stack_use = max(i + 1, max_stack_use);
|
|
|
|
|
|
|
|
while (i >= offset)
|
|
|
|
active_stack.users[i--] = 1;
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-16 21:36:30 +00:00
|
|
|
if (!compile_failed) {
|
|
|
|
compile_failed = true;
|
|
|
|
fprintf(stderr,
|
|
|
|
"Cycles: out of SVM stack space, shader \"%s\" too big.\n",
|
|
|
|
current_shader->name.c_str());
|
|
|
|
}
|
2011-04-27 11:58:34 +00:00
|
|
|
|
2014-01-16 21:36:30 +00:00
|
|
|
return 0;
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
2016-08-14 15:44:25 +00:00
|
|
|
int SVMCompiler::stack_find_offset(SocketType::Type type)
|
|
|
|
{
|
|
|
|
return stack_find_offset(stack_size(type));
|
|
|
|
}
|
|
|
|
|
2016-05-07 23:32:09 +00:00
|
|
|
void SVMCompiler::stack_clear_offset(SocketType::Type type, int offset)
|
2012-03-08 19:52:58 +00:00
|
|
|
{
|
|
|
|
int size = stack_size(type);
|
|
|
|
|
|
|
|
for (int i = 0; i < size; i++)
|
|
|
|
active_stack.users[offset + i]--;
|
|
|
|
}
|
|
|
|
|
2016-05-02 18:12:42 +00:00
|
|
|
int SVMCompiler::stack_assign(ShaderInput *input)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
|
|
|
/* stack offset assign? */
|
|
|
|
if (input->stack_offset == SVM_STACK_INVALID) {
|
|
|
|
if (input->link) {
|
|
|
|
/* linked to output -> use output offset */
|
2018-12-11 13:34:28 +00:00
|
|
|
assert(input->link->stack_offset != SVM_STACK_INVALID);
|
2011-04-27 11:58:34 +00:00
|
|
|
input->stack_offset = input->link->stack_offset;
|
|
|
|
}
|
|
|
|
else {
|
2016-05-07 17:48:28 +00:00
|
|
|
Node *node = input->parent;
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
/* not linked to output -> add nodes to load default value */
|
2016-05-07 23:32:09 +00:00
|
|
|
input->stack_offset = stack_find_offset(input->type());
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2016-05-07 23:32:09 +00:00
|
|
|
if (input->type() == SocketType::FLOAT) {
|
2016-05-07 17:48:28 +00:00
|
|
|
add_node(NODE_VALUE_F,
|
|
|
|
__float_as_int(node->get_float(input->socket_type)),
|
|
|
|
input->stack_offset);
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
2016-05-07 23:32:09 +00:00
|
|
|
else if (input->type() == SocketType::INT) {
|
2016-05-07 17:48:28 +00:00
|
|
|
add_node(NODE_VALUE_F, node->get_int(input->socket_type), input->stack_offset);
|
2012-10-20 13:11:45 +00:00
|
|
|
}
|
2016-05-07 23:32:09 +00:00
|
|
|
else if (input->type() == SocketType::VECTOR || input->type() == SocketType::NORMAL ||
|
|
|
|
input->type() == SocketType::POINT || input->type() == SocketType::COLOR) {
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
add_node(NODE_VALUE_V, input->stack_offset);
|
2016-05-07 17:48:28 +00:00
|
|
|
add_node(NODE_VALUE_V, node->get_float3(input->socket_type));
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
else /* should not get called for closure */
|
|
|
|
assert(0);
|
|
|
|
}
|
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2016-05-02 18:12:42 +00:00
|
|
|
return input->stack_offset;
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
2016-05-02 18:12:42 +00:00
|
|
|
int SVMCompiler::stack_assign(ShaderOutput *output)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
|
|
|
/* if no stack offset assigned yet, find one */
|
|
|
|
if (output->stack_offset == SVM_STACK_INVALID)
|
2016-05-07 23:32:09 +00:00
|
|
|
output->stack_offset = stack_find_offset(output->type());
|
2016-05-02 18:12:42 +00:00
|
|
|
|
|
|
|
return output->stack_offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
int SVMCompiler::stack_assign_if_linked(ShaderInput *input)
|
|
|
|
{
|
2021-06-28 21:15:32 +00:00
|
|
|
if (input->link || input->constant_folded_in)
|
2016-05-02 18:12:42 +00:00
|
|
|
return stack_assign(input);
|
|
|
|
|
|
|
|
return SVM_STACK_INVALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
int SVMCompiler::stack_assign_if_linked(ShaderOutput *output)
|
|
|
|
{
|
|
|
|
if (!output->links.empty())
|
|
|
|
return stack_assign(output);
|
|
|
|
|
|
|
|
return SVM_STACK_INVALID;
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SVMCompiler::stack_link(ShaderInput *input, ShaderOutput *output)
|
|
|
|
{
|
|
|
|
if (output->stack_offset == SVM_STACK_INVALID) {
|
|
|
|
assert(input->link);
|
2016-05-07 23:32:09 +00:00
|
|
|
assert(stack_size(output->type()) == stack_size(input->link->type()));
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
output->stack_offset = input->link->stack_offset;
|
|
|
|
|
2016-05-07 23:32:09 +00:00
|
|
|
int size = stack_size(output->type());
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < size; i++)
|
|
|
|
active_stack.users[output->stack_offset + i]++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-25 08:07:29 +00:00
|
|
|
void SVMCompiler::stack_clear_users(ShaderNode *node, ShaderNodeSet &done)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
|
|
|
/* optimization we should add:
|
2012-06-09 17:22:52 +00:00
|
|
|
* find and lower user counts for outputs for which all inputs are done.
|
|
|
|
* this is done before the node is compiled, under the assumption that the
|
|
|
|
* node will first load all inputs from the stack and then writes its
|
|
|
|
* outputs. this used to work, but was disabled because it gave trouble
|
|
|
|
* with inputs getting stack positions assigned */
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
foreach (ShaderInput *input, node->inputs) {
|
|
|
|
ShaderOutput *output = input->link;
|
|
|
|
|
|
|
|
if (output && output->stack_offset != SVM_STACK_INVALID) {
|
|
|
|
bool all_done = true;
|
|
|
|
|
|
|
|
/* optimization we should add: verify if in->parent is actually used */
|
|
|
|
foreach (ShaderInput *in, output->links)
|
|
|
|
if (in->parent != node && done.find(in->parent) == done.end())
|
|
|
|
all_done = false;
|
|
|
|
|
|
|
|
if (all_done) {
|
2016-05-07 23:32:09 +00:00
|
|
|
stack_clear_offset(output->type(), output->stack_offset);
|
2011-09-16 13:00:09 +00:00
|
|
|
output->stack_offset = SVM_STACK_INVALID;
|
|
|
|
|
|
|
|
foreach (ShaderInput *in, output->links)
|
|
|
|
in->stack_offset = SVM_STACK_INVALID;
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SVMCompiler::stack_clear_temporary(ShaderNode *node)
|
|
|
|
{
|
|
|
|
foreach (ShaderInput *input, node->inputs) {
|
|
|
|
if (!input->link && input->stack_offset != SVM_STACK_INVALID) {
|
2016-05-07 23:32:09 +00:00
|
|
|
stack_clear_offset(input->type(), input->stack_offset);
|
2011-09-16 13:00:09 +00:00
|
|
|
input->stack_offset = SVM_STACK_INVALID;
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint SVMCompiler::encode_uchar4(uint x, uint y, uint z, uint w)
|
|
|
|
{
|
|
|
|
assert(x <= 255);
|
|
|
|
assert(y <= 255);
|
|
|
|
assert(z <= 255);
|
|
|
|
assert(w <= 255);
|
|
|
|
|
|
|
|
return (x) | (y << 8) | (z << 16) | (w << 24);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SVMCompiler::add_node(int a, int b, int c, int d)
|
|
|
|
{
|
2017-10-20 02:32:29 +00:00
|
|
|
current_svm_nodes.push_back_slow(make_int4(a, b, c, d));
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
2016-05-07 17:47:37 +00:00
|
|
|
void SVMCompiler::add_node(ShaderNodeType type, int a, int b, int c)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
2017-10-20 02:32:29 +00:00
|
|
|
current_svm_nodes.push_back_slow(make_int4(type, a, b, c));
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
2016-05-07 17:47:37 +00:00
|
|
|
void SVMCompiler::add_node(ShaderNodeType type, const float3 &f)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
2017-10-20 02:32:29 +00:00
|
|
|
current_svm_nodes.push_back_slow(
|
2011-04-27 11:58:34 +00:00
|
|
|
make_int4(type, __float_as_int(f.x), __float_as_int(f.y), __float_as_int(f.z)));
|
|
|
|
}
|
|
|
|
|
|
|
|
void SVMCompiler::add_node(const float4 &f)
|
|
|
|
{
|
2017-10-20 02:32:29 +00:00
|
|
|
current_svm_nodes.push_back_slow(make_int4(
|
2011-04-27 11:58:34 +00:00
|
|
|
__float_as_int(f.x), __float_as_int(f.y), __float_as_int(f.z), __float_as_int(f.w)));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint SVMCompiler::attribute(ustring name)
|
|
|
|
{
|
Add support for tiled images and the UDIM naming scheme
This patch contains the work that I did during my week at the Code Quest - adding support for tiled images to Blender.
With this patch, images now contain a list of tiles. By default, this just contains one tile, but if the source type is set to Tiled, the user can add additional tiles. When acquiring an ImBuf, the tile to be loaded is specified in the ImageUser.
Therefore, code that is not yet aware of tiles will just access the default tile as usual.
The filenames of the additional tiles are derived from the original filename according to the UDIM naming scheme - the filename contains an index that is calculated as (1001 + 10*<y coordinate of the tile> + <x coordinate of the tile>), where the x coordinate never goes above 9.
Internally, the various tiles are stored in a cache just like sequences. When acquired for the first time, the code will try to load the corresponding file from disk. Alternatively, a new operator can be used to initialize the tile similar to the New Image operator.
The following features are supported so far:
- Automatic detection and loading of all tiles when opening the first tile (1001)
- Saving all tiles
- Adding and removing tiles
- Filling tiles with generated images
- Drawing all tiles in the Image Editor
- Viewing a tiled grid even if no image is selected
- Rendering tiled images in Eevee
- Rendering tiled images in Cycles (in SVM mode)
- Automatically skipping loading of unused tiles in Cycles
- 2D texture painting (also across tiles)
- 3D texture painting (also across tiles, only limitation: individual faces can not cross tile borders)
- Assigning custom labels to individual tiles (drawn in the Image Editor instead of the ID)
- Different resolutions between tiles
There still are some missing features that will be added later (see T72390):
- Workbench engine support
- Packing/Unpacking support
- Baking support
- Cycles OSL support
- many other Blender features that rely on images
Thanks to Brecht for the review and to all who tested the intermediate versions!
Differential Revision: https://developer.blender.org/D3509
2019-12-12 15:06:08 +00:00
|
|
|
return scene->shader_manager->get_attribute_id(name);
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
2012-04-30 12:49:26 +00:00
|
|
|
uint SVMCompiler::attribute(AttributeStandard std)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
Add support for tiled images and the UDIM naming scheme
This patch contains the work that I did during my week at the Code Quest - adding support for tiled images to Blender.
With this patch, images now contain a list of tiles. By default, this just contains one tile, but if the source type is set to Tiled, the user can add additional tiles. When acquiring an ImBuf, the tile to be loaded is specified in the ImageUser.
Therefore, code that is not yet aware of tiles will just access the default tile as usual.
The filenames of the additional tiles are derived from the original filename according to the UDIM naming scheme - the filename contains an index that is calculated as (1001 + 10*<y coordinate of the tile> + <x coordinate of the tile>), where the x coordinate never goes above 9.
Internally, the various tiles are stored in a cache just like sequences. When acquired for the first time, the code will try to load the corresponding file from disk. Alternatively, a new operator can be used to initialize the tile similar to the New Image operator.
The following features are supported so far:
- Automatic detection and loading of all tiles when opening the first tile (1001)
- Saving all tiles
- Adding and removing tiles
- Filling tiles with generated images
- Drawing all tiles in the Image Editor
- Viewing a tiled grid even if no image is selected
- Rendering tiled images in Eevee
- Rendering tiled images in Cycles (in SVM mode)
- Automatically skipping loading of unused tiles in Cycles
- 2D texture painting (also across tiles)
- 3D texture painting (also across tiles, only limitation: individual faces can not cross tile borders)
- Assigning custom labels to individual tiles (drawn in the Image Editor instead of the ID)
- Different resolutions between tiles
There still are some missing features that will be added later (see T72390):
- Workbench engine support
- Packing/Unpacking support
- Baking support
- Cycles OSL support
- many other Blender features that rely on images
Thanks to Brecht for the review and to all who tested the intermediate versions!
Differential Revision: https://developer.blender.org/D3509
2019-12-12 15:06:08 +00:00
|
|
|
return scene->shader_manager->get_attribute_id(std);
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
2018-02-18 02:20:39 +00:00
|
|
|
uint SVMCompiler::attribute_standard(ustring name)
|
|
|
|
{
|
|
|
|
AttributeStandard std = Attribute::name_standard(name.c_str());
|
|
|
|
return (std) ? attribute(std) : attribute(name);
|
|
|
|
}
|
|
|
|
|
2015-11-25 08:07:29 +00:00
|
|
|
void SVMCompiler::find_dependencies(ShaderNodeSet &dependencies,
|
|
|
|
const ShaderNodeSet &done,
|
2014-07-11 12:19:14 +00:00
|
|
|
ShaderInput *input,
|
|
|
|
ShaderNode *skip_node)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
|
|
|
ShaderNode *node = (input->link) ? input->link->parent : NULL;
|
2015-11-25 08:46:51 +00:00
|
|
|
if (node != NULL && done.find(node) == done.end() && node != skip_node &&
|
|
|
|
dependencies.find(node) == dependencies.end()) {
|
2018-12-11 13:33:24 +00:00
|
|
|
foreach (ShaderInput *in, node->inputs) {
|
|
|
|
find_dependencies(dependencies, done, in, skip_node);
|
|
|
|
}
|
2011-04-27 11:58:34 +00:00
|
|
|
dependencies.insert(node);
|
2019-04-17 04:17:24 +00:00
|
|
|
}
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2015-11-25 08:07:29 +00:00
|
|
|
void SVMCompiler::generate_node(ShaderNode *node, ShaderNodeSet &done)
|
2014-04-03 20:04:39 +00:00
|
|
|
{
|
|
|
|
node->compile(*this);
|
|
|
|
stack_clear_users(node, done);
|
|
|
|
stack_clear_temporary(node);
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2016-02-05 21:13:51 +00:00
|
|
|
if (current_type == SHADER_TYPE_SURFACE) {
|
|
|
|
if (node->has_spatial_varying())
|
|
|
|
current_shader->has_surface_spatial_varying = true;
|
Cycles: merge of cycles-x branch, a major update to the renderer
This includes much improved GPU rendering performance, viewport interactivity,
new shadow catcher, revamped sampling settings, subsurface scattering anisotropy,
new GPU volume sampling, improved PMJ sampling pattern, and more.
Some features have also been removed or changed, breaking backwards compatibility.
Including the removal of the OpenCL backend, for which alternatives are under
development.
Release notes and code docs:
https://wiki.blender.org/wiki/Reference/Release_Notes/3.0/Cycles
https://wiki.blender.org/wiki/Source/Render/Cycles
Credits:
* Sergey Sharybin
* Brecht Van Lommel
* Patrick Mours (OptiX backend)
* Christophe Hery (subsurface scattering anisotropy)
* William Leeson (PMJ sampling pattern)
* Alaska (various fixes and tweaks)
* Thomas Dinges (various fixes)
For the full commit history, see the cycles-x branch. This squashes together
all the changes since intermediate changes would often fail building or tests.
Ref T87839, T87837, T87836
Fixes T90734, T89353, T80267, T80267, T77185, T69800
2021-09-20 15:59:20 +00:00
|
|
|
if (node->get_feature() & KERNEL_FEATURE_NODE_RAYTRACE)
|
|
|
|
current_shader->has_surface_raytrace = true;
|
2016-02-05 21:13:51 +00:00
|
|
|
}
|
|
|
|
else if (current_type == SHADER_TYPE_VOLUME) {
|
2014-04-03 20:04:39 +00:00
|
|
|
if (node->has_spatial_varying())
|
2016-02-05 20:33:37 +00:00
|
|
|
current_shader->has_volume_spatial_varying = true;
|
2020-03-07 13:38:52 +00:00
|
|
|
if (node->has_attribute_dependency())
|
|
|
|
current_shader->has_volume_attribute_dependency = true;
|
2014-04-03 20:04:39 +00:00
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2015-11-20 13:18:27 +00:00
|
|
|
if (node->has_integrator_dependency()) {
|
|
|
|
current_shader->has_integrator_dependency = true;
|
2019-04-17 04:17:24 +00:00
|
|
|
}
|
2015-11-20 13:18:27 +00:00
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2015-12-30 14:21:19 +00:00
|
|
|
void SVMCompiler::generate_svm_nodes(const ShaderNodeSet &nodes, CompilerState *state)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
2015-12-30 14:21:19 +00:00
|
|
|
ShaderNodeSet &done = state->nodes_done;
|
2015-12-29 15:42:20 +00:00
|
|
|
vector<bool> &done_flag = state->nodes_done_flag;
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
bool nodes_done;
|
|
|
|
do {
|
|
|
|
nodes_done = true;
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
foreach (ShaderNode *node, nodes) {
|
2015-12-29 15:42:20 +00:00
|
|
|
if (!done_flag[node->id]) {
|
2011-04-27 11:58:34 +00:00
|
|
|
bool inputs_done = true;
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2018-12-11 13:33:24 +00:00
|
|
|
foreach (ShaderInput *input, node->inputs) {
|
|
|
|
if (input->link && !done_flag[input->link->parent->id]) {
|
|
|
|
inputs_done = false;
|
2019-04-17 04:17:24 +00:00
|
|
|
}
|
2018-12-11 13:33:24 +00:00
|
|
|
}
|
2011-04-27 11:58:34 +00:00
|
|
|
if (inputs_done) {
|
2014-04-03 20:04:39 +00:00
|
|
|
generate_node(node, done);
|
2011-04-27 11:58:34 +00:00
|
|
|
done.insert(node);
|
2015-12-29 15:42:20 +00:00
|
|
|
done_flag[node->id] = true;
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
2018-12-11 13:33:24 +00:00
|
|
|
else {
|
2011-04-27 11:58:34 +00:00
|
|
|
nodes_done = false;
|
2019-04-17 04:17:24 +00:00
|
|
|
}
|
|
|
|
}
|
2018-12-11 13:33:24 +00:00
|
|
|
}
|
2011-04-27 11:58:34 +00:00
|
|
|
} while (!nodes_done);
|
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2015-12-30 14:21:19 +00:00
|
|
|
void SVMCompiler::generate_closure_node(ShaderNode *node, CompilerState *state)
|
2014-04-21 15:17:24 +00:00
|
|
|
{
|
Cycles: merge of cycles-x branch, a major update to the renderer
This includes much improved GPU rendering performance, viewport interactivity,
new shadow catcher, revamped sampling settings, subsurface scattering anisotropy,
new GPU volume sampling, improved PMJ sampling pattern, and more.
Some features have also been removed or changed, breaking backwards compatibility.
Including the removal of the OpenCL backend, for which alternatives are under
development.
Release notes and code docs:
https://wiki.blender.org/wiki/Reference/Release_Notes/3.0/Cycles
https://wiki.blender.org/wiki/Source/Render/Cycles
Credits:
* Sergey Sharybin
* Brecht Van Lommel
* Patrick Mours (OptiX backend)
* Christophe Hery (subsurface scattering anisotropy)
* William Leeson (PMJ sampling pattern)
* Alaska (various fixes and tweaks)
* Thomas Dinges (various fixes)
For the full commit history, see the cycles-x branch. This squashes together
all the changes since intermediate changes would often fail building or tests.
Ref T87839, T87837, T87836
Fixes T90734, T89353, T80267, T80267, T77185, T69800
2021-09-20 15:59:20 +00:00
|
|
|
/* Skip generating closure that are not supported or needed for a particular
|
|
|
|
* type of shader. For example a BSDF in a volume shader. */
|
|
|
|
const int node_feature = node->get_feature();
|
|
|
|
if ((state->node_feature_mask & node_feature) != node_feature) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-04-21 15:17:24 +00:00
|
|
|
/* execute dependencies for closure */
|
|
|
|
foreach (ShaderInput *in, node->inputs) {
|
2018-12-11 13:33:24 +00:00
|
|
|
if (in->link != NULL) {
|
2015-11-25 08:07:29 +00:00
|
|
|
ShaderNodeSet dependencies;
|
2015-12-30 14:21:19 +00:00
|
|
|
find_dependencies(dependencies, state->nodes_done, in);
|
|
|
|
generate_svm_nodes(dependencies, state);
|
2019-04-17 04:17:24 +00:00
|
|
|
}
|
2014-04-21 15:17:24 +00:00
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2014-04-21 15:17:24 +00:00
|
|
|
/* closure mix weight */
|
|
|
|
const char *weight_name = (current_type == SHADER_TYPE_VOLUME) ? "VolumeMixWeight" :
|
|
|
|
"SurfaceMixWeight";
|
|
|
|
ShaderInput *weight_in = node->input(weight_name);
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2016-05-07 17:48:28 +00:00
|
|
|
if (weight_in && (weight_in->link || node->get_float(weight_in->socket_type) != 1.0f))
|
2016-05-02 18:12:42 +00:00
|
|
|
mix_weight_offset = stack_assign(weight_in);
|
2014-04-21 15:17:24 +00:00
|
|
|
else
|
|
|
|
mix_weight_offset = SVM_STACK_INVALID;
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2014-04-21 15:17:24 +00:00
|
|
|
/* compile closure itself */
|
2015-12-30 14:21:19 +00:00
|
|
|
generate_node(node, state->nodes_done);
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2014-04-21 15:17:24 +00:00
|
|
|
mix_weight_offset = SVM_STACK_INVALID;
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2014-04-21 15:17:24 +00:00
|
|
|
if (current_type == SHADER_TYPE_SURFACE) {
|
|
|
|
if (node->has_surface_emission())
|
|
|
|
current_shader->has_surface_emission = true;
|
|
|
|
if (node->has_surface_transparent())
|
|
|
|
current_shader->has_surface_transparent = true;
|
|
|
|
if (node->has_surface_bssrdf()) {
|
|
|
|
current_shader->has_surface_bssrdf = true;
|
|
|
|
if (node->has_bssrdf_bump())
|
|
|
|
current_shader->has_bssrdf_bump = true;
|
|
|
|
}
|
2017-08-20 01:25:13 +00:00
|
|
|
if (node->has_bump()) {
|
|
|
|
current_shader->has_bump = true;
|
|
|
|
}
|
2014-04-21 15:17:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-11 12:19:14 +00:00
|
|
|
void SVMCompiler::generated_shared_closure_nodes(ShaderNode *root_node,
|
|
|
|
ShaderNode *node,
|
2015-12-30 14:21:19 +00:00
|
|
|
CompilerState *state,
|
2015-11-25 08:07:29 +00:00
|
|
|
const ShaderNodeSet &shared)
|
2014-04-21 15:17:24 +00:00
|
|
|
{
|
|
|
|
if (shared.find(node) != shared.end()) {
|
2015-12-30 14:21:19 +00:00
|
|
|
generate_multi_closure(root_node, node, state);
|
2014-04-21 15:17:24 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
foreach (ShaderInput *in, node->inputs) {
|
2016-05-07 23:32:09 +00:00
|
|
|
if (in->type() == SocketType::CLOSURE && in->link)
|
2015-12-30 14:21:19 +00:00
|
|
|
generated_shared_closure_nodes(root_node, in->link->parent, state, shared);
|
2014-04-21 15:17:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-21 23:50:22 +00:00
|
|
|
void SVMCompiler::find_aov_nodes_and_dependencies(ShaderNodeSet &aov_nodes,
|
|
|
|
ShaderGraph *graph,
|
|
|
|
CompilerState *state)
|
2019-12-04 18:57:28 +00:00
|
|
|
{
|
2020-12-21 23:50:22 +00:00
|
|
|
foreach (ShaderNode *node, graph->nodes) {
|
|
|
|
if (node->special_type == SHADER_SPECIAL_TYPE_OUTPUT_AOV) {
|
|
|
|
OutputAOVNode *aov_node = static_cast<OutputAOVNode *>(node);
|
Cycles: merge of cycles-x branch, a major update to the renderer
This includes much improved GPU rendering performance, viewport interactivity,
new shadow catcher, revamped sampling settings, subsurface scattering anisotropy,
new GPU volume sampling, improved PMJ sampling pattern, and more.
Some features have also been removed or changed, breaking backwards compatibility.
Including the removal of the OpenCL backend, for which alternatives are under
development.
Release notes and code docs:
https://wiki.blender.org/wiki/Reference/Release_Notes/3.0/Cycles
https://wiki.blender.org/wiki/Source/Render/Cycles
Credits:
* Sergey Sharybin
* Brecht Van Lommel
* Patrick Mours (OptiX backend)
* Christophe Hery (subsurface scattering anisotropy)
* William Leeson (PMJ sampling pattern)
* Alaska (various fixes and tweaks)
* Thomas Dinges (various fixes)
For the full commit history, see the cycles-x branch. This squashes together
all the changes since intermediate changes would often fail building or tests.
Ref T87839, T87837, T87836
Fixes T90734, T89353, T80267, T80267, T77185, T69800
2021-09-20 15:59:20 +00:00
|
|
|
if (aov_node->offset >= 0) {
|
2020-12-21 23:50:22 +00:00
|
|
|
aov_nodes.insert(aov_node);
|
|
|
|
foreach (ShaderInput *in, node->inputs) {
|
|
|
|
if (in->link != NULL) {
|
|
|
|
find_dependencies(aov_nodes, state->nodes_done, in);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-12-04 18:57:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-11 12:19:14 +00:00
|
|
|
void SVMCompiler::generate_multi_closure(ShaderNode *root_node,
|
|
|
|
ShaderNode *node,
|
2015-12-30 14:21:19 +00:00
|
|
|
CompilerState *state)
|
2011-09-12 13:13:56 +00:00
|
|
|
{
|
2012-11-26 21:59:41 +00:00
|
|
|
/* only generate once */
|
2015-12-30 14:21:19 +00:00
|
|
|
if (state->closure_done.find(node) != state->closure_done.end())
|
2012-11-26 21:59:41 +00:00
|
|
|
return;
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2015-12-30 14:21:19 +00:00
|
|
|
state->closure_done.insert(node);
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2016-05-07 22:41:01 +00:00
|
|
|
if (node->special_type == SHADER_SPECIAL_TYPE_COMBINE_CLOSURE) {
|
2012-11-26 21:59:41 +00:00
|
|
|
/* weighting is already taken care of in ShaderGraph::transform_multi_closure */
|
2011-09-12 13:13:56 +00:00
|
|
|
ShaderInput *cl1in = node->input("Closure1");
|
|
|
|
ShaderInput *cl2in = node->input("Closure2");
|
2014-04-18 11:40:30 +00:00
|
|
|
ShaderInput *facin = node->input("Fac");
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2014-04-18 11:40:30 +00:00
|
|
|
/* skip empty mix/add closure nodes */
|
|
|
|
if (!cl1in->link && !cl2in->link)
|
|
|
|
return;
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2014-04-18 11:40:30 +00:00
|
|
|
if (facin && facin->link) {
|
|
|
|
/* mix closure: generate instructions to compute mix weight */
|
2015-11-25 08:07:29 +00:00
|
|
|
ShaderNodeSet dependencies;
|
2015-12-30 14:21:19 +00:00
|
|
|
find_dependencies(dependencies, state->nodes_done, facin);
|
|
|
|
generate_svm_nodes(dependencies, state);
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2014-04-18 11:40:30 +00:00
|
|
|
/* execute shared dependencies. this is needed to allow skipping
|
|
|
|
* of zero weight closures and their dependencies later, so we
|
|
|
|
* ensure that they only skip dependencies that are unique to them */
|
2015-11-25 08:07:29 +00:00
|
|
|
ShaderNodeSet cl1deps, cl2deps, shareddeps;
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2015-12-30 14:21:19 +00:00
|
|
|
find_dependencies(cl1deps, state->nodes_done, cl1in);
|
|
|
|
find_dependencies(cl2deps, state->nodes_done, cl2in);
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2015-11-25 11:04:45 +00:00
|
|
|
ShaderNodeIDComparator node_id_comp;
|
2014-04-18 11:40:30 +00:00
|
|
|
set_intersection(cl1deps.begin(),
|
|
|
|
cl1deps.end(),
|
2014-05-04 16:19:08 +00:00
|
|
|
cl2deps.begin(),
|
|
|
|
cl2deps.end(),
|
2015-11-25 11:04:45 +00:00
|
|
|
std::inserter(shareddeps, shareddeps.begin()),
|
|
|
|
node_id_comp);
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2014-07-11 12:19:14 +00:00
|
|
|
/* it's possible some nodes are not shared between this mix node
|
|
|
|
* inputs, but still needed to be always executed, this mainly
|
|
|
|
* happens when a node of current subbranch is used by a parent
|
|
|
|
* node or so */
|
|
|
|
if (root_node != node) {
|
|
|
|
foreach (ShaderInput *in, root_node->inputs) {
|
2015-11-25 08:07:29 +00:00
|
|
|
ShaderNodeSet rootdeps;
|
2015-12-30 14:21:19 +00:00
|
|
|
find_dependencies(rootdeps, state->nodes_done, in, node);
|
2014-07-11 12:19:14 +00:00
|
|
|
set_intersection(rootdeps.begin(),
|
|
|
|
rootdeps.end(),
|
|
|
|
cl1deps.begin(),
|
|
|
|
cl1deps.end(),
|
2015-11-25 11:04:45 +00:00
|
|
|
std::inserter(shareddeps, shareddeps.begin()),
|
|
|
|
node_id_comp);
|
2014-07-11 12:19:14 +00:00
|
|
|
set_intersection(rootdeps.begin(),
|
|
|
|
rootdeps.end(),
|
|
|
|
cl2deps.begin(),
|
|
|
|
cl2deps.end(),
|
2015-11-25 11:04:45 +00:00
|
|
|
std::inserter(shareddeps, shareddeps.begin()),
|
|
|
|
node_id_comp);
|
2014-07-11 12:19:14 +00:00
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
}
|
|
|
|
|
2020-12-21 23:50:22 +00:00
|
|
|
/* For dependencies AOV nodes, prevent them from being categorized
|
|
|
|
* as exclusive deps of one or the other closure, since the need to
|
|
|
|
* execute them for AOV writing is not dependent on the closure
|
|
|
|
* weights. */
|
|
|
|
if (state->aov_nodes.size()) {
|
|
|
|
set_intersection(state->aov_nodes.begin(),
|
|
|
|
state->aov_nodes.end(),
|
|
|
|
cl1deps.begin(),
|
|
|
|
cl1deps.end(),
|
|
|
|
std::inserter(shareddeps, shareddeps.begin()),
|
|
|
|
node_id_comp);
|
|
|
|
set_intersection(state->aov_nodes.begin(),
|
|
|
|
state->aov_nodes.end(),
|
|
|
|
cl2deps.begin(),
|
|
|
|
cl2deps.end(),
|
|
|
|
std::inserter(shareddeps, shareddeps.begin()),
|
|
|
|
node_id_comp);
|
|
|
|
}
|
|
|
|
|
2014-04-21 15:17:24 +00:00
|
|
|
if (!shareddeps.empty()) {
|
2014-07-11 12:19:14 +00:00
|
|
|
if (cl1in->link) {
|
2015-12-30 14:21:19 +00:00
|
|
|
generated_shared_closure_nodes(root_node, cl1in->link->parent, state, shareddeps);
|
2014-07-11 12:19:14 +00:00
|
|
|
}
|
|
|
|
if (cl2in->link) {
|
2015-12-30 14:21:19 +00:00
|
|
|
generated_shared_closure_nodes(root_node, cl2in->link->parent, state, shareddeps);
|
2014-07-11 12:19:14 +00:00
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2015-12-30 14:21:19 +00:00
|
|
|
generate_svm_nodes(shareddeps, state);
|
2014-04-21 15:17:24 +00:00
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2014-04-18 11:40:30 +00:00
|
|
|
/* generate instructions for input closure 1 */
|
|
|
|
if (cl1in->link) {
|
2016-09-09 10:27:51 +00:00
|
|
|
/* Add instruction to skip closure and its dependencies if mix
|
|
|
|
* weight is zero.
|
|
|
|
*/
|
2017-10-20 02:32:29 +00:00
|
|
|
current_svm_nodes.push_back_slow(make_int4(NODE_JUMP_IF_ONE, 0, stack_assign(facin), 0));
|
2016-09-09 10:27:51 +00:00
|
|
|
int node_jump_skip_index = current_svm_nodes.size() - 1;
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2015-12-30 14:21:19 +00:00
|
|
|
generate_multi_closure(root_node, cl1in->link->parent, state);
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2016-09-09 10:27:51 +00:00
|
|
|
/* Fill in jump instruction location to be after closure. */
|
|
|
|
current_svm_nodes[node_jump_skip_index].y = current_svm_nodes.size() -
|
|
|
|
node_jump_skip_index - 1;
|
2014-04-18 11:40:30 +00:00
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2014-04-18 11:40:30 +00:00
|
|
|
/* generate instructions for input closure 2 */
|
|
|
|
if (cl2in->link) {
|
2016-09-09 10:27:51 +00:00
|
|
|
/* Add instruction to skip closure and its dependencies if mix
|
|
|
|
* weight is zero.
|
|
|
|
*/
|
2017-10-20 02:32:29 +00:00
|
|
|
current_svm_nodes.push_back_slow(make_int4(NODE_JUMP_IF_ZERO, 0, stack_assign(facin), 0));
|
2016-09-09 10:27:51 +00:00
|
|
|
int node_jump_skip_index = current_svm_nodes.size() - 1;
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2015-12-30 14:21:19 +00:00
|
|
|
generate_multi_closure(root_node, cl2in->link->parent, state);
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2016-09-09 10:27:51 +00:00
|
|
|
/* Fill in jump instruction location to be after closure. */
|
|
|
|
current_svm_nodes[node_jump_skip_index].y = current_svm_nodes.size() -
|
|
|
|
node_jump_skip_index - 1;
|
2014-04-18 11:40:30 +00:00
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2014-04-18 11:40:30 +00:00
|
|
|
/* unassign */
|
2014-04-21 13:53:20 +00:00
|
|
|
facin->stack_offset = SVM_STACK_INVALID;
|
2014-04-18 11:40:30 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* execute closures and their dependencies, no runtime checks
|
|
|
|
* to skip closures here because was already optimized due to
|
|
|
|
* fixed weight or add closure that always needs both */
|
|
|
|
if (cl1in->link)
|
2015-12-30 14:21:19 +00:00
|
|
|
generate_multi_closure(root_node, cl1in->link->parent, state);
|
2014-04-18 11:40:30 +00:00
|
|
|
if (cl2in->link)
|
2015-12-30 14:21:19 +00:00
|
|
|
generate_multi_closure(root_node, cl2in->link->parent, state);
|
2014-04-18 11:40:30 +00:00
|
|
|
}
|
2011-09-12 13:13:56 +00:00
|
|
|
}
|
|
|
|
else {
|
2015-12-30 14:21:19 +00:00
|
|
|
generate_closure_node(node, state);
|
2011-09-12 13:13:56 +00:00
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2015-12-30 14:21:19 +00:00
|
|
|
state->nodes_done.insert(node);
|
2016-01-04 12:11:52 +00:00
|
|
|
state->nodes_done_flag[node->id] = true;
|
2011-09-12 13:13:56 +00:00
|
|
|
}
|
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType type)
|
|
|
|
{
|
|
|
|
/* Converting a shader graph into svm_nodes that can be executed
|
|
|
|
* sequentially on the virtual machine is fairly simple. We can keep
|
|
|
|
* looping over nodes and each time all the inputs of a node are
|
|
|
|
* ready, we add svm_nodes for it that read the inputs from the
|
|
|
|
* stack and write outputs back to the stack.
|
|
|
|
*
|
|
|
|
* With the SVM, we always sample only a single closure. We can think
|
|
|
|
* of all closures nodes as a binary tree with mix closures as inner
|
|
|
|
* nodes and other closures as leafs. The SVM will traverse that tree,
|
|
|
|
* each time deciding to go left or right depending on the mix weights,
|
|
|
|
* until a closure is found.
|
|
|
|
*
|
|
|
|
* We only execute nodes that are needed for the mix weights and chosen
|
|
|
|
* closure.
|
|
|
|
*/
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
current_type = type;
|
2011-09-21 11:54:28 +00:00
|
|
|
current_graph = graph;
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
/* get input in output node */
|
2019-12-04 18:57:28 +00:00
|
|
|
ShaderNode *output = graph->output();
|
2011-04-27 11:58:34 +00:00
|
|
|
ShaderInput *clin = NULL;
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2015-10-08 14:08:28 +00:00
|
|
|
switch (type) {
|
2013-05-09 15:20:00 +00:00
|
|
|
case SHADER_TYPE_SURFACE:
|
2019-12-04 18:57:28 +00:00
|
|
|
clin = output->input("Surface");
|
2013-05-09 15:20:00 +00:00
|
|
|
break;
|
|
|
|
case SHADER_TYPE_VOLUME:
|
2019-12-04 18:57:28 +00:00
|
|
|
clin = output->input("Volume");
|
2013-05-09 15:20:00 +00:00
|
|
|
break;
|
|
|
|
case SHADER_TYPE_DISPLACEMENT:
|
2019-12-04 18:57:28 +00:00
|
|
|
clin = output->input("Displacement");
|
2013-05-09 15:20:00 +00:00
|
|
|
break;
|
2016-08-14 15:44:25 +00:00
|
|
|
case SHADER_TYPE_BUMP:
|
2019-12-04 18:57:28 +00:00
|
|
|
clin = output->input("Normal");
|
2016-08-14 15:44:25 +00:00
|
|
|
break;
|
2013-05-09 15:20:00 +00:00
|
|
|
default:
|
|
|
|
assert(0);
|
|
|
|
break;
|
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
/* clear all compiler state */
|
2018-06-11 10:54:17 +00:00
|
|
|
memset((void *)&active_stack, 0, sizeof(active_stack));
|
2016-09-09 10:27:51 +00:00
|
|
|
current_svm_nodes.clear();
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2019-12-04 18:57:28 +00:00
|
|
|
foreach (ShaderNode *node, graph->nodes) {
|
|
|
|
foreach (ShaderInput *input, node->inputs)
|
2011-04-27 11:58:34 +00:00
|
|
|
input->stack_offset = SVM_STACK_INVALID;
|
2019-12-04 18:57:28 +00:00
|
|
|
foreach (ShaderOutput *output, node->outputs)
|
2011-04-27 11:58:34 +00:00
|
|
|
output->stack_offset = SVM_STACK_INVALID;
|
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2016-08-14 15:44:25 +00:00
|
|
|
/* for the bump shader we need add a node to store the shader state */
|
2016-09-07 23:33:41 +00:00
|
|
|
bool need_bump_state = (type == SHADER_TYPE_BUMP) &&
|
2020-11-04 10:17:38 +00:00
|
|
|
(shader->get_displacement_method() == DISPLACE_BOTH);
|
2016-08-14 15:44:25 +00:00
|
|
|
int bump_state_offset = SVM_STACK_INVALID;
|
2016-09-07 23:33:41 +00:00
|
|
|
if (need_bump_state) {
|
2016-08-14 15:44:25 +00:00
|
|
|
bump_state_offset = stack_find_offset(SVM_BUMP_EVAL_STATE_SIZE);
|
|
|
|
add_node(NODE_ENTER_BUMP_EVAL, bump_state_offset);
|
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2021-05-02 00:34:56 +00:00
|
|
|
if (shader->reference_count()) {
|
2019-12-04 18:57:28 +00:00
|
|
|
CompilerState state(graph);
|
2012-10-30 11:51:17 +00:00
|
|
|
if (clin->link) {
|
|
|
|
bool generate = false;
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2015-10-08 14:08:28 +00:00
|
|
|
switch (type) {
|
2018-07-06 08:17:58 +00:00
|
|
|
case SHADER_TYPE_SURFACE: /* generate surface shader */
|
2013-05-09 15:20:00 +00:00
|
|
|
generate = true;
|
|
|
|
shader->has_surface = true;
|
Cycles: merge of cycles-x branch, a major update to the renderer
This includes much improved GPU rendering performance, viewport interactivity,
new shadow catcher, revamped sampling settings, subsurface scattering anisotropy,
new GPU volume sampling, improved PMJ sampling pattern, and more.
Some features have also been removed or changed, breaking backwards compatibility.
Including the removal of the OpenCL backend, for which alternatives are under
development.
Release notes and code docs:
https://wiki.blender.org/wiki/Reference/Release_Notes/3.0/Cycles
https://wiki.blender.org/wiki/Source/Render/Cycles
Credits:
* Sergey Sharybin
* Brecht Van Lommel
* Patrick Mours (OptiX backend)
* Christophe Hery (subsurface scattering anisotropy)
* William Leeson (PMJ sampling pattern)
* Alaska (various fixes and tweaks)
* Thomas Dinges (various fixes)
For the full commit history, see the cycles-x branch. This squashes together
all the changes since intermediate changes would often fail building or tests.
Ref T87839, T87837, T87836
Fixes T90734, T89353, T80267, T80267, T77185, T69800
2021-09-20 15:59:20 +00:00
|
|
|
state.node_feature_mask = KERNEL_FEATURE_NODE_MASK_SURFACE;
|
2013-05-09 15:20:00 +00:00
|
|
|
break;
|
|
|
|
case SHADER_TYPE_VOLUME: /* generate volume shader */
|
|
|
|
generate = true;
|
|
|
|
shader->has_volume = true;
|
Cycles: merge of cycles-x branch, a major update to the renderer
This includes much improved GPU rendering performance, viewport interactivity,
new shadow catcher, revamped sampling settings, subsurface scattering anisotropy,
new GPU volume sampling, improved PMJ sampling pattern, and more.
Some features have also been removed or changed, breaking backwards compatibility.
Including the removal of the OpenCL backend, for which alternatives are under
development.
Release notes and code docs:
https://wiki.blender.org/wiki/Reference/Release_Notes/3.0/Cycles
https://wiki.blender.org/wiki/Source/Render/Cycles
Credits:
* Sergey Sharybin
* Brecht Van Lommel
* Patrick Mours (OptiX backend)
* Christophe Hery (subsurface scattering anisotropy)
* William Leeson (PMJ sampling pattern)
* Alaska (various fixes and tweaks)
* Thomas Dinges (various fixes)
For the full commit history, see the cycles-x branch. This squashes together
all the changes since intermediate changes would often fail building or tests.
Ref T87839, T87837, T87836
Fixes T90734, T89353, T80267, T80267, T77185, T69800
2021-09-20 15:59:20 +00:00
|
|
|
state.node_feature_mask = KERNEL_FEATURE_NODE_MASK_VOLUME;
|
2013-05-09 15:20:00 +00:00
|
|
|
break;
|
|
|
|
case SHADER_TYPE_DISPLACEMENT: /* generate displacement shader */
|
|
|
|
generate = true;
|
|
|
|
shader->has_displacement = true;
|
Cycles: merge of cycles-x branch, a major update to the renderer
This includes much improved GPU rendering performance, viewport interactivity,
new shadow catcher, revamped sampling settings, subsurface scattering anisotropy,
new GPU volume sampling, improved PMJ sampling pattern, and more.
Some features have also been removed or changed, breaking backwards compatibility.
Including the removal of the OpenCL backend, for which alternatives are under
development.
Release notes and code docs:
https://wiki.blender.org/wiki/Reference/Release_Notes/3.0/Cycles
https://wiki.blender.org/wiki/Source/Render/Cycles
Credits:
* Sergey Sharybin
* Brecht Van Lommel
* Patrick Mours (OptiX backend)
* Christophe Hery (subsurface scattering anisotropy)
* William Leeson (PMJ sampling pattern)
* Alaska (various fixes and tweaks)
* Thomas Dinges (various fixes)
For the full commit history, see the cycles-x branch. This squashes together
all the changes since intermediate changes would often fail building or tests.
Ref T87839, T87837, T87836
Fixes T90734, T89353, T80267, T80267, T77185, T69800
2021-09-20 15:59:20 +00:00
|
|
|
state.node_feature_mask = KERNEL_FEATURE_NODE_MASK_DISPLACEMENT;
|
2013-05-09 15:20:00 +00:00
|
|
|
break;
|
2016-08-14 15:44:25 +00:00
|
|
|
case SHADER_TYPE_BUMP: /* generate bump shader */
|
|
|
|
generate = true;
|
Cycles: merge of cycles-x branch, a major update to the renderer
This includes much improved GPU rendering performance, viewport interactivity,
new shadow catcher, revamped sampling settings, subsurface scattering anisotropy,
new GPU volume sampling, improved PMJ sampling pattern, and more.
Some features have also been removed or changed, breaking backwards compatibility.
Including the removal of the OpenCL backend, for which alternatives are under
development.
Release notes and code docs:
https://wiki.blender.org/wiki/Reference/Release_Notes/3.0/Cycles
https://wiki.blender.org/wiki/Source/Render/Cycles
Credits:
* Sergey Sharybin
* Brecht Van Lommel
* Patrick Mours (OptiX backend)
* Christophe Hery (subsurface scattering anisotropy)
* William Leeson (PMJ sampling pattern)
* Alaska (various fixes and tweaks)
* Thomas Dinges (various fixes)
For the full commit history, see the cycles-x branch. This squashes together
all the changes since intermediate changes would often fail building or tests.
Ref T87839, T87837, T87836
Fixes T90734, T89353, T80267, T80267, T77185, T69800
2021-09-20 15:59:20 +00:00
|
|
|
state.node_feature_mask = KERNEL_FEATURE_NODE_MASK_BUMP;
|
2016-08-14 15:44:25 +00:00
|
|
|
break;
|
2013-05-09 15:20:00 +00:00
|
|
|
default:
|
|
|
|
break;
|
2012-10-30 11:51:17 +00:00
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2012-10-30 11:51:17 +00:00
|
|
|
if (generate) {
|
2020-12-21 23:50:22 +00:00
|
|
|
if (type == SHADER_TYPE_SURFACE) {
|
|
|
|
find_aov_nodes_and_dependencies(state.aov_nodes, graph, &state);
|
|
|
|
}
|
2015-12-30 14:21:19 +00:00
|
|
|
generate_multi_closure(clin->link->parent, clin->link->parent, &state);
|
2011-09-12 13:13:56 +00:00
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
}
|
|
|
|
|
2012-10-30 11:51:17 +00:00
|
|
|
/* compile output node */
|
2019-12-04 18:57:28 +00:00
|
|
|
output->compile(*this);
|
|
|
|
|
2020-12-21 23:50:22 +00:00
|
|
|
if (!state.aov_nodes.empty()) {
|
|
|
|
/* AOV passes are only written if the object is directly visible, so
|
|
|
|
* there is no point in evaluating all the nodes generated only for the
|
|
|
|
* AOV outputs if that's not the case. Therefore, we insert
|
|
|
|
* NODE_AOV_START into the shader before the AOV-only nodes are
|
|
|
|
* generated which tells the kernel that it can stop evaluation
|
|
|
|
* early if AOVs will not be written. */
|
|
|
|
add_node(NODE_AOV_START, 0, 0, 0);
|
|
|
|
generate_svm_nodes(state.aov_nodes, &state);
|
2019-12-04 18:57:28 +00:00
|
|
|
}
|
2012-10-30 11:51:17 +00:00
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2016-08-14 15:44:25 +00:00
|
|
|
/* add node to restore state after bump shader has finished */
|
2016-09-07 23:33:41 +00:00
|
|
|
if (need_bump_state) {
|
2016-08-14 15:44:25 +00:00
|
|
|
add_node(NODE_LEAVE_BUMP_EVAL, bump_state_offset);
|
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2014-01-16 21:36:30 +00:00
|
|
|
/* if compile failed, generate empty shader */
|
|
|
|
if (compile_failed) {
|
2016-09-09 10:27:51 +00:00
|
|
|
current_svm_nodes.clear();
|
2014-01-16 21:36:30 +00:00
|
|
|
compile_failed = false;
|
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2019-05-01 11:14:11 +00:00
|
|
|
/* for bump shaders we fall thru to the surface shader, but if this is any other kind of shader
|
|
|
|
* it ends here */
|
2016-08-14 15:44:25 +00:00
|
|
|
if (type != SHADER_TYPE_BUMP) {
|
|
|
|
add_node(NODE_END, 0, 0, 0);
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
}
|
|
|
|
|
Add support for tiled images and the UDIM naming scheme
This patch contains the work that I did during my week at the Code Quest - adding support for tiled images to Blender.
With this patch, images now contain a list of tiles. By default, this just contains one tile, but if the source type is set to Tiled, the user can add additional tiles. When acquiring an ImBuf, the tile to be loaded is specified in the ImageUser.
Therefore, code that is not yet aware of tiles will just access the default tile as usual.
The filenames of the additional tiles are derived from the original filename according to the UDIM naming scheme - the filename contains an index that is calculated as (1001 + 10*<y coordinate of the tile> + <x coordinate of the tile>), where the x coordinate never goes above 9.
Internally, the various tiles are stored in a cache just like sequences. When acquired for the first time, the code will try to load the corresponding file from disk. Alternatively, a new operator can be used to initialize the tile similar to the New Image operator.
The following features are supported so far:
- Automatic detection and loading of all tiles when opening the first tile (1001)
- Saving all tiles
- Adding and removing tiles
- Filling tiles with generated images
- Drawing all tiles in the Image Editor
- Viewing a tiled grid even if no image is selected
- Rendering tiled images in Eevee
- Rendering tiled images in Cycles (in SVM mode)
- Automatically skipping loading of unused tiles in Cycles
- 2D texture painting (also across tiles)
- 3D texture painting (also across tiles, only limitation: individual faces can not cross tile borders)
- Assigning custom labels to individual tiles (drawn in the Image Editor instead of the ID)
- Different resolutions between tiles
There still are some missing features that will be added later (see T72390):
- Workbench engine support
- Packing/Unpacking support
- Baking support
- Cycles OSL support
- many other Blender features that rely on images
Thanks to Brecht for the review and to all who tested the intermediate versions!
Differential Revision: https://developer.blender.org/D3509
2019-12-12 15:06:08 +00:00
|
|
|
void SVMCompiler::compile(Shader *shader, array<int4> &svm_nodes, int index, Summary *summary)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
|
|
|
/* copy graph for shader with bump mapping */
|
2017-08-20 12:02:16 +00:00
|
|
|
ShaderNode *output = shader->graph->output();
|
2016-09-09 10:27:51 +00:00
|
|
|
int start_num_svm_nodes = svm_nodes.size();
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2015-12-30 14:35:21 +00:00
|
|
|
const double time_start = time_dt();
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2020-11-04 10:17:38 +00:00
|
|
|
bool has_bump = (shader->get_displacement_method() != DISPLACE_TRUE) &&
|
2017-08-20 12:02:16 +00:00
|
|
|
output->input("Surface")->link && output->input("Displacement")->link;
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
/* finalize */
|
2015-12-30 14:35:21 +00:00
|
|
|
{
|
|
|
|
scoped_timer timer((summary != NULL) ? &summary->time_finalize : NULL);
|
|
|
|
shader->graph->finalize(scene,
|
2017-08-20 12:02:16 +00:00
|
|
|
has_bump,
|
|
|
|
shader->has_integrator_dependency,
|
2020-11-04 10:17:38 +00:00
|
|
|
shader->get_displacement_method() == DISPLACE_BOTH);
|
2015-11-20 13:18:27 +00:00
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
current_shader = shader;
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2011-10-12 23:03:12 +00:00
|
|
|
shader->has_surface = false;
|
2011-04-27 11:58:34 +00:00
|
|
|
shader->has_surface_emission = false;
|
2011-09-27 20:37:24 +00:00
|
|
|
shader->has_surface_transparent = false;
|
Cycles: merge of cycles-x branch, a major update to the renderer
This includes much improved GPU rendering performance, viewport interactivity,
new shadow catcher, revamped sampling settings, subsurface scattering anisotropy,
new GPU volume sampling, improved PMJ sampling pattern, and more.
Some features have also been removed or changed, breaking backwards compatibility.
Including the removal of the OpenCL backend, for which alternatives are under
development.
Release notes and code docs:
https://wiki.blender.org/wiki/Reference/Release_Notes/3.0/Cycles
https://wiki.blender.org/wiki/Source/Render/Cycles
Credits:
* Sergey Sharybin
* Brecht Van Lommel
* Patrick Mours (OptiX backend)
* Christophe Hery (subsurface scattering anisotropy)
* William Leeson (PMJ sampling pattern)
* Alaska (various fixes and tweaks)
* Thomas Dinges (various fixes)
For the full commit history, see the cycles-x branch. This squashes together
all the changes since intermediate changes would often fail building or tests.
Ref T87839, T87837, T87836
Fixes T90734, T89353, T80267, T80267, T77185, T69800
2021-09-20 15:59:20 +00:00
|
|
|
shader->has_surface_raytrace = false;
|
2013-04-01 20:26:52 +00:00
|
|
|
shader->has_surface_bssrdf = false;
|
2017-08-20 12:02:16 +00:00
|
|
|
shader->has_bump = has_bump;
|
|
|
|
shader->has_bssrdf_bump = has_bump;
|
2011-04-27 11:58:34 +00:00
|
|
|
shader->has_volume = false;
|
|
|
|
shader->has_displacement = false;
|
2016-02-05 21:13:51 +00:00
|
|
|
shader->has_surface_spatial_varying = false;
|
2016-02-05 20:33:37 +00:00
|
|
|
shader->has_volume_spatial_varying = false;
|
2020-03-07 13:38:52 +00:00
|
|
|
shader->has_volume_attribute_dependency = false;
|
2015-11-20 13:18:27 +00:00
|
|
|
shader->has_integrator_dependency = false;
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2016-08-14 15:44:25 +00:00
|
|
|
/* generate bump shader */
|
2017-08-20 12:02:16 +00:00
|
|
|
if (has_bump) {
|
2016-08-14 15:44:25 +00:00
|
|
|
scoped_timer timer((summary != NULL) ? &summary->time_generate_bump : NULL);
|
2017-08-20 12:02:16 +00:00
|
|
|
compile_type(shader, shader->graph, SHADER_TYPE_BUMP);
|
2016-09-09 10:27:51 +00:00
|
|
|
svm_nodes[index].y = svm_nodes.size();
|
2017-10-20 02:32:29 +00:00
|
|
|
svm_nodes.append(current_svm_nodes);
|
2015-12-30 14:35:21 +00:00
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2016-08-14 15:44:25 +00:00
|
|
|
/* generate surface shader */
|
|
|
|
{
|
|
|
|
scoped_timer timer((summary != NULL) ? &summary->time_generate_surface : NULL);
|
|
|
|
compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
|
2019-05-01 11:14:11 +00:00
|
|
|
/* only set jump offset if there's no bump shader, as the bump shader will fall thru to this
|
|
|
|
* one if it exists */
|
2017-08-20 12:02:16 +00:00
|
|
|
if (!has_bump) {
|
2016-09-09 10:27:51 +00:00
|
|
|
svm_nodes[index].y = svm_nodes.size();
|
2016-08-14 15:44:25 +00:00
|
|
|
}
|
2017-10-20 02:32:29 +00:00
|
|
|
svm_nodes.append(current_svm_nodes);
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2011-10-12 23:03:12 +00:00
|
|
|
/* generate volume shader */
|
2015-12-30 14:35:21 +00:00
|
|
|
{
|
|
|
|
scoped_timer timer((summary != NULL) ? &summary->time_generate_volume : NULL);
|
|
|
|
compile_type(shader, shader->graph, SHADER_TYPE_VOLUME);
|
2016-09-09 10:27:51 +00:00
|
|
|
svm_nodes[index].z = svm_nodes.size();
|
2017-10-20 02:32:29 +00:00
|
|
|
svm_nodes.append(current_svm_nodes);
|
2015-12-30 14:35:21 +00:00
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
/* generate displacement shader */
|
2015-12-30 14:35:21 +00:00
|
|
|
{
|
|
|
|
scoped_timer timer((summary != NULL) ? &summary->time_generate_displacement : NULL);
|
|
|
|
compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT);
|
2016-09-09 10:27:51 +00:00
|
|
|
svm_nodes[index].w = svm_nodes.size();
|
2017-10-20 02:32:29 +00:00
|
|
|
svm_nodes.append(current_svm_nodes);
|
2015-12-30 14:35:21 +00:00
|
|
|
}
|
2019-04-17 04:17:24 +00:00
|
|
|
|
2015-12-28 14:30:43 +00:00
|
|
|
/* Fill in summary information. */
|
|
|
|
if (summary != NULL) {
|
2015-12-30 14:35:21 +00:00
|
|
|
summary->time_total = time_dt() - time_start;
|
2015-12-28 14:30:43 +00:00
|
|
|
summary->peak_stack_usage = max_stack_use;
|
2016-09-09 10:27:51 +00:00
|
|
|
summary->num_svm_nodes = svm_nodes.size() - start_num_svm_nodes;
|
2015-12-28 14:30:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Compiler summary implementation. */
|
|
|
|
|
|
|
|
SVMCompiler::Summary::Summary()
|
|
|
|
: num_svm_nodes(0),
|
2015-12-29 16:20:10 +00:00
|
|
|
peak_stack_usage(0),
|
|
|
|
time_finalize(0.0),
|
|
|
|
time_generate_surface(0.0),
|
|
|
|
time_generate_bump(0.0),
|
|
|
|
time_generate_volume(0.0),
|
|
|
|
time_generate_displacement(0.0),
|
|
|
|
time_total(0.0)
|
2015-12-28 14:30:43 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
string SVMCompiler::Summary::full_report() const
|
|
|
|
{
|
|
|
|
string report = "";
|
|
|
|
report += string_printf("Number of SVM nodes: %d\n", num_svm_nodes);
|
2015-12-29 16:20:10 +00:00
|
|
|
report += string_printf("Peak stack usage: %d\n", peak_stack_usage);
|
|
|
|
|
|
|
|
report += string_printf("Time (in seconds):\n");
|
2017-08-20 12:02:16 +00:00
|
|
|
report += string_printf("Finalize: %f\n", time_finalize);
|
2015-12-29 16:20:10 +00:00
|
|
|
report += string_printf(" Surface: %f\n", time_generate_surface);
|
|
|
|
report += string_printf(" Bump: %f\n", time_generate_bump);
|
|
|
|
report += string_printf(" Volume: %f\n", time_generate_volume);
|
|
|
|
report += string_printf(" Displacement: %f\n", time_generate_displacement);
|
|
|
|
report += string_printf("Generate: %f\n",
|
|
|
|
time_generate_surface + time_generate_bump + time_generate_volume +
|
|
|
|
time_generate_displacement);
|
|
|
|
report += string_printf("Total: %f\n", time_total);
|
|
|
|
|
2015-12-28 14:30:43 +00:00
|
|
|
return report;
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
2015-12-29 15:42:20 +00:00
|
|
|
/* Global state of the compiler. */
|
|
|
|
|
|
|
|
SVMCompiler::CompilerState::CompilerState(ShaderGraph *graph)
|
|
|
|
{
|
|
|
|
int max_id = 0;
|
|
|
|
foreach (ShaderNode *node, graph->nodes) {
|
|
|
|
max_id = max(node->id, max_id);
|
|
|
|
}
|
|
|
|
nodes_done_flag.resize(max_id + 1, false);
|
Cycles: merge of cycles-x branch, a major update to the renderer
This includes much improved GPU rendering performance, viewport interactivity,
new shadow catcher, revamped sampling settings, subsurface scattering anisotropy,
new GPU volume sampling, improved PMJ sampling pattern, and more.
Some features have also been removed or changed, breaking backwards compatibility.
Including the removal of the OpenCL backend, for which alternatives are under
development.
Release notes and code docs:
https://wiki.blender.org/wiki/Reference/Release_Notes/3.0/Cycles
https://wiki.blender.org/wiki/Source/Render/Cycles
Credits:
* Sergey Sharybin
* Brecht Van Lommel
* Patrick Mours (OptiX backend)
* Christophe Hery (subsurface scattering anisotropy)
* William Leeson (PMJ sampling pattern)
* Alaska (various fixes and tweaks)
* Thomas Dinges (various fixes)
For the full commit history, see the cycles-x branch. This squashes together
all the changes since intermediate changes would often fail building or tests.
Ref T87839, T87837, T87836
Fixes T90734, T89353, T80267, T80267, T77185, T69800
2021-09-20 15:59:20 +00:00
|
|
|
node_feature_mask = 0;
|
2015-12-29 15:42:20 +00:00
|
|
|
}
|
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
CCL_NAMESPACE_END
|