mirror of
https://github.com/blender/blender
synced 2026-09-29 04:37:17 +03:00
Refactor: Cycles: Replace uint4 SVM packing with structs
* Pass socket links and values in structs for each SVM node. * Always pass default values along with stack offset, encoded in SVMInputFloat and SVMInputFloat3. For slightly more efficient memory access the stack offset is encoded in a NaN float. * Simplify SVMCompiler API to use input_float, input_float3 input_link and output functions, instead of manual stack assignment. This was a leftover from early CUDA versions and old GPUs, where data was stored in textures as there was no L1/L2 cache for global memory. Assisted-by: Claude Opus 4.6 Co-authored-by: Sergey Sharybin <sergey@blender.org> Pull Request: https://projects.blender.org/blender/blender/pulls/156612
This commit is contained in:
parent
c00226a6ae
commit
7ee94c067c
60 changed files with 4806 additions and 4130 deletions
|
|
@ -85,6 +85,7 @@ set(SRC_KERNEL_SVM_HEADERS
|
|||
svm/math.h
|
||||
svm/math_util.h
|
||||
svm/mix.h
|
||||
svm/node_types.h
|
||||
svm/node_types_template.h
|
||||
svm/noise.h
|
||||
svm/noisetex.h
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ KERNEL_DATA_ARRAY(uint, triangle_to_tree)
|
|||
KERNEL_DATA_ARRAY(KernelParticle, particles)
|
||||
|
||||
/* shaders */
|
||||
KERNEL_DATA_ARRAY(uint4, svm_nodes)
|
||||
KERNEL_DATA_ARRAY(uint, svm_nodes)
|
||||
KERNEL_DATA_ARRAY(KernelShader, shaders)
|
||||
|
||||
/* lookup tables */
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "kernel/sample/mapping.h"
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
|
@ -104,42 +105,31 @@ ccl_device_noinline
|
|||
svm_node_ao(KernelGlobals kg,
|
||||
ConstIntegratorGenericState state,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint4 node)
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeAmbientOcclusion &ccl_restrict node)
|
||||
{
|
||||
uint flags;
|
||||
uint dist_offset;
|
||||
uint normal_offset;
|
||||
uint out_ao_offset;
|
||||
svm_unpack_node_uchar4(node.y, &flags, &dist_offset, &normal_offset, &out_ao_offset);
|
||||
|
||||
uint color_offset;
|
||||
uint out_color_offset;
|
||||
uint samples;
|
||||
svm_unpack_node_uchar3(node.z, &color_offset, &out_color_offset, &samples);
|
||||
|
||||
float ao = 1.0f;
|
||||
|
||||
IF_KERNEL_NODES_FEATURE(RAYTRACE)
|
||||
{
|
||||
float dist = stack_load_float_default(stack, dist_offset, node.w);
|
||||
float3 normal = stack_valid(normal_offset) ? stack_load_float3(stack, normal_offset) : sd->N;
|
||||
float dist = stack_load(stack, node.dist);
|
||||
float3 normal = stack_load_float3_default(stack, node.normal_offset, sd->N);
|
||||
normal = safe_normalize(normal);
|
||||
|
||||
# ifdef __KERNEL_OPTIX__
|
||||
ao = optixDirectCall<float>(0, kg, state, sd, normal, dist, samples, flags);
|
||||
ao = optixDirectCall<float>(0, kg, state, sd, normal, dist, node.samples, node.flags);
|
||||
# else
|
||||
ao = svm_ao(kg, state, sd, normal, dist, samples, flags);
|
||||
ao = svm_ao(kg, state, sd, normal, dist, node.samples, node.flags);
|
||||
# endif
|
||||
}
|
||||
|
||||
if (stack_valid(out_ao_offset)) {
|
||||
stack_store_float(stack, out_ao_offset, ao);
|
||||
if (stack_valid(node.out_ao_offset)) {
|
||||
stack_store_float(stack, node.out_ao_offset, ao);
|
||||
}
|
||||
|
||||
if (stack_valid(out_color_offset)) {
|
||||
const float3 color = stack_load_float3(stack, color_offset);
|
||||
stack_store_float3(stack, out_color_offset, ao * color);
|
||||
if (stack_valid(node.out_color_offset)) {
|
||||
const float3 color = stack_load(stack, node.color);
|
||||
stack_store_float3(stack, node.out_color_offset, ao * color);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "kernel/film/aov_passes.h"
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
|
@ -23,8 +24,8 @@ template<uint node_feature_mask, typename ConstIntegratorGenericState>
|
|||
ccl_device void svm_node_aov_color(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ConstIntegratorGenericState state,
|
||||
ccl_private float *stack,
|
||||
const uint4 node,
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeAOVColor &ccl_restrict node,
|
||||
ccl_global float *render_buffer)
|
||||
{
|
||||
IF_KERNEL_NODES_FEATURE(AOV)
|
||||
|
|
@ -34,8 +35,8 @@ ccl_device void svm_node_aov_color(KernelGlobals kg,
|
|||
return;
|
||||
}
|
||||
|
||||
const float3 val = stack_load_float3(stack, node.y);
|
||||
film_write_aov_pass_color(kg, state, render_buffer, node.z, val);
|
||||
const float3 val = stack_load(stack, node.color);
|
||||
film_write_aov_pass_color(kg, state, render_buffer, node.aov_offset, val);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -43,8 +44,8 @@ template<uint node_feature_mask, typename ConstIntegratorGenericState>
|
|||
ccl_device void svm_node_aov_value(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ConstIntegratorGenericState state,
|
||||
ccl_private float *stack,
|
||||
const uint4 node,
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeAOVValue &ccl_restrict node,
|
||||
ccl_global float *render_buffer)
|
||||
{
|
||||
IF_KERNEL_NODES_FEATURE(AOV)
|
||||
|
|
@ -54,8 +55,8 @@ ccl_device void svm_node_aov_value(KernelGlobals kg,
|
|||
return;
|
||||
}
|
||||
|
||||
const float val = stack_load_float(stack, node.y);
|
||||
film_write_aov_pass_value(kg, state, render_buffer, node.z, val);
|
||||
const float val = stack_load(stack, node.value);
|
||||
film_write_aov_pass_value(kg, state, render_buffer, node.aov_offset, val);
|
||||
}
|
||||
}
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include "kernel/geom/primitive.h"
|
||||
#include "kernel/geom/volume.h"
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
|
@ -19,29 +20,26 @@ CCL_NAMESPACE_BEGIN
|
|||
|
||||
ccl_device AttributeDescriptor svm_node_attr_init(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
const uint4 node,
|
||||
ccl_private NodeAttributeOutputType *type,
|
||||
ccl_private uint *out_offset)
|
||||
const ccl_global SVMNodeAttr &ccl_restrict node,
|
||||
ccl_private NodeAttributeOutputType *type)
|
||||
{
|
||||
uint type_value;
|
||||
svm_unpack_node_uchar2(node.z, out_offset, &type_value);
|
||||
*type = (NodeAttributeOutputType)type_value;
|
||||
*type = node.output_type;
|
||||
|
||||
AttributeDescriptor desc;
|
||||
|
||||
if (sd->object != OBJECT_NONE) {
|
||||
desc = find_attribute(kg, sd, node.y);
|
||||
desc = find_attribute(kg, sd, node.attr);
|
||||
if (desc.offset == ATTR_STD_NOT_FOUND) {
|
||||
desc = attribute_not_found();
|
||||
desc.offset = 0;
|
||||
desc.type = (NodeAttributeType)type_value;
|
||||
desc.type = (NodeAttributeType)node.output_type;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* background */
|
||||
desc = attribute_not_found();
|
||||
desc.offset = 0;
|
||||
desc.type = (NodeAttributeType)type_value;
|
||||
desc.type = (NodeAttributeType)node.output_type;
|
||||
}
|
||||
|
||||
return desc;
|
||||
|
|
@ -69,15 +67,16 @@ ccl_device_inline void svm_node_attr_store(const NodeAttributeOutputType type,
|
|||
* and computes derivatives when Float3Type is a dual type. */
|
||||
|
||||
template<typename Float3Type>
|
||||
ccl_device_inline Float3Type svm_node_attr_surface_eval(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
const uint4 node,
|
||||
const NodeAttributeOutputType type,
|
||||
const AttributeDescriptor desc)
|
||||
ccl_device_inline Float3Type
|
||||
svm_node_attr_surface_eval(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
const ccl_global SVMNodeAttr &ccl_restrict node,
|
||||
const NodeAttributeOutputType type,
|
||||
const AttributeDescriptor desc)
|
||||
{
|
||||
using FloatType = dual_scalar_t<Float3Type>;
|
||||
|
||||
if (sd->type == PRIMITIVE_LAMP && node.y == ATTR_STD_UV) {
|
||||
if (sd->type == PRIMITIVE_LAMP && node.attr == ATTR_STD_UV) {
|
||||
Float3Type uv(make_float3(1.0f - sd->u - sd->v, sd->u, 0.0f));
|
||||
if constexpr (is_dual_v<Float3Type>) {
|
||||
uv.dx = make_float3(-sd->du.dx - sd->dv.dx, sd->du.dx, 0.0f);
|
||||
|
|
@ -86,7 +85,7 @@ ccl_device_inline Float3Type svm_node_attr_surface_eval(KernelGlobals kg,
|
|||
return uv;
|
||||
}
|
||||
|
||||
if (node.y == ATTR_STD_GENERATED && desc.element == ATTR_ELEMENT_NONE) {
|
||||
if (node.attr == ATTR_STD_GENERATED && desc.element == ATTR_ELEMENT_NONE) {
|
||||
Float3Type f = shading_position<Float3Type>(sd);
|
||||
object_inverse_position_transform_if_object(kg, sd, &f);
|
||||
return f;
|
||||
|
|
@ -160,15 +159,14 @@ ccl_device_inline Float3Type svm_node_attr_surface_eval(KernelGlobals kg,
|
|||
/* Surface attribute node. */
|
||||
ccl_device_noinline void svm_node_attr_surface(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint4 node)
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeAttr &ccl_restrict node)
|
||||
{
|
||||
NodeAttributeOutputType type = NODE_ATTR_OUTPUT_FLOAT;
|
||||
uint out_offset = 0;
|
||||
const AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
|
||||
const AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type);
|
||||
|
||||
float3 data = svm_node_attr_surface_eval<float3>(kg, sd, node, type, desc);
|
||||
svm_node_attr_store(type, stack, out_offset, data);
|
||||
svm_node_attr_store(type, stack, node.out_offset, data);
|
||||
}
|
||||
|
||||
/* Evaluate surface attributes with derivatives and optional bump offset.
|
||||
|
|
@ -176,30 +174,25 @@ ccl_device_noinline void svm_node_attr_surface(KernelGlobals kg,
|
|||
|
||||
ccl_device_noinline void svm_node_attr_derivative(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint4 node)
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeAttr &ccl_restrict node)
|
||||
{
|
||||
NodeAttributeOutputType type = NODE_ATTR_OUTPUT_FLOAT;
|
||||
uint out_offset = 0;
|
||||
const AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
|
||||
|
||||
uint unused1, unused2, bump_offset, store_derivatives;
|
||||
svm_unpack_node_uchar4(node.z, &unused1, &unused2, &bump_offset, &store_derivatives);
|
||||
const float bump_filter_width = __uint_as_float(node.w);
|
||||
const AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type);
|
||||
|
||||
dual3 data = svm_node_attr_surface_eval<dual3>(kg, sd, node, type, desc);
|
||||
if (bump_offset == NODE_BUMP_OFFSET_DX) {
|
||||
data.val += data.dx * bump_filter_width;
|
||||
if (node.bump_offset == NODE_BUMP_OFFSET_DX) {
|
||||
data.val += data.dx * node.bump_filter_width;
|
||||
}
|
||||
else if (bump_offset == NODE_BUMP_OFFSET_DY) {
|
||||
data.val += data.dy * bump_filter_width;
|
||||
else if (node.bump_offset == NODE_BUMP_OFFSET_DY) {
|
||||
data.val += data.dy * node.bump_filter_width;
|
||||
}
|
||||
|
||||
if (store_derivatives) {
|
||||
svm_node_attr_store(type, stack, out_offset, data);
|
||||
if (node.store_derivatives) {
|
||||
svm_node_attr_store(type, stack, node.out_offset, data);
|
||||
}
|
||||
else {
|
||||
svm_node_attr_store(type, stack, out_offset, float3(data.val));
|
||||
svm_node_attr_store(type, stack, node.out_offset, float3(data.val));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -207,26 +200,25 @@ ccl_device_noinline void svm_node_attr_derivative(KernelGlobals kg,
|
|||
/* Volume attribute node. Volumes have no derivatives or bump. */
|
||||
ccl_device_noinline void svm_node_attr_volume(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint4 node)
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeAttr &ccl_restrict node)
|
||||
{
|
||||
kernel_assert(primitive_is_volume_attribute(sd));
|
||||
|
||||
NodeAttributeOutputType type = NODE_ATTR_OUTPUT_FLOAT;
|
||||
uint out_offset = 0;
|
||||
const AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
|
||||
const AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type);
|
||||
|
||||
const bool stochastic_sample = node.w;
|
||||
const bool stochastic_sample = __float_as_uint(node.bump_filter_width);
|
||||
const float4 value = volume_attribute_float4(kg, sd, desc, stochastic_sample);
|
||||
|
||||
if (type == NODE_ATTR_OUTPUT_FLOAT) {
|
||||
stack_store_float(stack, out_offset, volume_attribute_value<float>(value));
|
||||
stack_store_float(stack, node.out_offset, volume_attribute_value<float>(value));
|
||||
}
|
||||
else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
|
||||
stack_store_float3(stack, out_offset, volume_attribute_value<float3>(value));
|
||||
stack_store_float3(stack, node.out_offset, volume_attribute_value<float3>(value));
|
||||
}
|
||||
else {
|
||||
stack_store_float(stack, out_offset, volume_attribute_alpha(value));
|
||||
stack_store_float(stack, node.out_offset, volume_attribute_alpha(value));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "kernel/integrator/path_state.h"
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
|
@ -299,35 +300,29 @@ ccl_device_noinline
|
|||
svm_node_bevel(KernelGlobals kg,
|
||||
ConstIntegratorGenericState state,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint4 node)
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeBevel &ccl_restrict node)
|
||||
{
|
||||
uint num_samples;
|
||||
uint radius_offset;
|
||||
uint normal_offset;
|
||||
uint out_offset;
|
||||
svm_unpack_node_uchar4(node.y, &num_samples, &radius_offset, &normal_offset, &out_offset);
|
||||
|
||||
float3 bevel_N = sd->N;
|
||||
|
||||
IF_KERNEL_NODES_FEATURE(RAYTRACE)
|
||||
{
|
||||
float radius = stack_load_float(stack, radius_offset);
|
||||
float radius = stack_load(stack, node.radius);
|
||||
|
||||
# ifdef __KERNEL_OPTIX__
|
||||
bevel_N = optixDirectCall<float3>(1, kg, state, sd, radius, num_samples);
|
||||
bevel_N = optixDirectCall<float3>(1, kg, state, sd, radius, node.num_samples);
|
||||
# else
|
||||
bevel_N = svm_bevel(kg, state, sd, radius, num_samples);
|
||||
bevel_N = svm_bevel(kg, state, sd, radius, node.num_samples);
|
||||
# endif
|
||||
|
||||
if (stack_valid(normal_offset)) {
|
||||
if (stack_valid(node.normal_offset)) {
|
||||
/* Preserve input normal. */
|
||||
const float3 ref_N = stack_load_float3(stack, normal_offset);
|
||||
const float3 ref_N = stack_load_float3(stack, node.normal_offset);
|
||||
bevel_N = normalize(ref_N + (bevel_N - sd->N));
|
||||
}
|
||||
}
|
||||
|
||||
stack_store_float3(stack, out_offset, bevel_N);
|
||||
stack_store_float3(stack, node.out_offset, bevel_N);
|
||||
}
|
||||
|
||||
#endif /* __SHADER_RAYTRACE__ */
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include "kernel/globals.h"
|
||||
|
||||
#include "kernel/svm/math_util.h"
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
#include "kernel/util/colorspace.h"
|
||||
|
|
@ -19,17 +20,16 @@ CCL_NAMESPACE_BEGIN
|
|||
/* Blackbody Node */
|
||||
|
||||
ccl_device_noinline void svm_node_blackbody(KernelGlobals kg,
|
||||
ccl_private float *stack,
|
||||
const uint temperature_offset,
|
||||
const uint col_offset)
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeBlackbody &ccl_restrict node)
|
||||
{
|
||||
/* Input */
|
||||
const float temperature = stack_load_float(stack, temperature_offset);
|
||||
const float temperature = stack_load(stack, node.temperature);
|
||||
|
||||
float3 color_rgb = rec709_to_rgb(kg, svm_math_blackbody_color_rec709(temperature));
|
||||
color_rgb = max(color_rgb, zero_float3());
|
||||
|
||||
stack_store_float3(stack, col_offset, color_rgb);
|
||||
stack_store_float3(stack, node.color_offset, color_rgb);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
|
@ -66,55 +67,21 @@ ccl_device_noinline_cpu float2 svm_brick(const float3 p,
|
|||
return make_float2(tint, mortar);
|
||||
}
|
||||
|
||||
ccl_device_noinline int svm_node_tex_brick(KernelGlobals kg,
|
||||
ccl_private float *stack,
|
||||
const uint4 node,
|
||||
int offset)
|
||||
ccl_device_noinline void svm_node_tex_brick(ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeTexBrick &ccl_restrict node)
|
||||
{
|
||||
const uint4 node2 = read_node(kg, &offset);
|
||||
const uint4 node3 = read_node(kg, &offset);
|
||||
const uint4 node4 = read_node(kg, &offset);
|
||||
const float3 co = stack_load_float3(stack, node.co);
|
||||
|
||||
/* Input and Output Sockets */
|
||||
uint co_offset;
|
||||
uint color1_offset;
|
||||
uint color2_offset;
|
||||
uint mortar_offset;
|
||||
uint scale_offset;
|
||||
uint mortar_size_offset;
|
||||
uint bias_offset;
|
||||
uint brick_width_offset;
|
||||
uint row_height_offset;
|
||||
uint color_offset;
|
||||
uint fac_offset;
|
||||
uint mortar_smooth_offset;
|
||||
float3 color1 = stack_load(stack, node.color1);
|
||||
const float3 color2 = stack_load(stack, node.color2);
|
||||
const float3 mortar = stack_load(stack, node.mortar);
|
||||
|
||||
/* RNA properties */
|
||||
uint offset_frequency;
|
||||
uint squash_frequency;
|
||||
|
||||
svm_unpack_node_uchar4(node.y, &co_offset, &color1_offset, &color2_offset, &mortar_offset);
|
||||
svm_unpack_node_uchar4(
|
||||
node.z, &scale_offset, &mortar_size_offset, &bias_offset, &brick_width_offset);
|
||||
svm_unpack_node_uchar4(
|
||||
node.w, &row_height_offset, &color_offset, &fac_offset, &mortar_smooth_offset);
|
||||
|
||||
svm_unpack_node_uchar2(node2.x, &offset_frequency, &squash_frequency);
|
||||
|
||||
const float3 co = stack_load_float3(stack, co_offset);
|
||||
|
||||
float3 color1 = stack_load_float3(stack, color1_offset);
|
||||
const float3 color2 = stack_load_float3(stack, color2_offset);
|
||||
const float3 mortar = stack_load_float3(stack, mortar_offset);
|
||||
|
||||
const float scale = stack_load_float_default(stack, scale_offset, node2.y);
|
||||
const float mortar_size = stack_load_float_default(stack, mortar_size_offset, node2.z);
|
||||
const float mortar_smooth = stack_load_float_default(stack, mortar_smooth_offset, node4.x);
|
||||
const float bias = stack_load_float_default(stack, bias_offset, node2.w);
|
||||
const float brick_width = stack_load_float_default(stack, brick_width_offset, node3.x);
|
||||
const float row_height = stack_load_float_default(stack, row_height_offset, node3.y);
|
||||
const float offset_amount = __int_as_float(node3.z);
|
||||
const float squash_amount = __int_as_float(node3.w);
|
||||
const float scale = stack_load(stack, node.scale);
|
||||
const float mortar_size = stack_load(stack, node.mortar_size);
|
||||
const float mortar_smooth = stack_load(stack, node.mortar_smooth);
|
||||
const float bias = stack_load(stack, node.bias);
|
||||
const float brick_width = stack_load(stack, node.brick_width);
|
||||
const float row_height = stack_load(stack, node.row_height);
|
||||
|
||||
const float2 f2 = svm_brick(co * scale,
|
||||
mortar_size,
|
||||
|
|
@ -122,10 +89,10 @@ ccl_device_noinline int svm_node_tex_brick(KernelGlobals kg,
|
|||
bias,
|
||||
brick_width,
|
||||
row_height,
|
||||
offset_amount,
|
||||
offset_frequency,
|
||||
squash_amount,
|
||||
squash_frequency);
|
||||
node.offset_amount,
|
||||
node.offset_frequency,
|
||||
node.squash_amount,
|
||||
node.squash_frequency);
|
||||
|
||||
const float tint = f2.x;
|
||||
const float f = f2.y;
|
||||
|
|
@ -135,13 +102,12 @@ ccl_device_noinline int svm_node_tex_brick(KernelGlobals kg,
|
|||
color1 = facm * color1 + tint * color2;
|
||||
}
|
||||
|
||||
if (stack_valid(color_offset)) {
|
||||
stack_store_float3(stack, color_offset, color1 * (1.0f - f) + mortar * f);
|
||||
if (stack_valid(node.color_offset)) {
|
||||
stack_store_float3(stack, node.color_offset, color1 * (1.0f - f) + mortar * f);
|
||||
}
|
||||
if (stack_valid(fac_offset)) {
|
||||
stack_store_float(stack, fac_offset, f);
|
||||
if (stack_valid(node.fac_offset)) {
|
||||
stack_store_float(stack, node.fac_offset, f);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -5,27 +5,23 @@
|
|||
#pragma once
|
||||
|
||||
#include "kernel/svm/color_util.h"
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
ccl_device_noinline void svm_node_brightness(ccl_private float *stack,
|
||||
const uint in_color,
|
||||
const uint out_color,
|
||||
const uint node)
|
||||
ccl_device_noinline void svm_node_brightness(ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeBrightContrast &ccl_restrict
|
||||
node)
|
||||
{
|
||||
uint bright_offset;
|
||||
uint contrast_offset;
|
||||
float3 color = stack_load_float3(stack, in_color);
|
||||
|
||||
svm_unpack_node_uchar2(node, &bright_offset, &contrast_offset);
|
||||
const float brightness = stack_load_float(stack, bright_offset);
|
||||
const float contrast = stack_load_float(stack, contrast_offset);
|
||||
float3 color = stack_load(stack, node.color);
|
||||
const float brightness = stack_load(stack, node.bright);
|
||||
const float contrast = stack_load(stack, node.contrast);
|
||||
|
||||
color = svm_brightness_contrast(color, brightness, contrast);
|
||||
|
||||
if (stack_valid(out_color)) {
|
||||
stack_store_float3(stack, out_color, color);
|
||||
if (stack_valid(node.out_offset)) {
|
||||
stack_store_float3(stack, node.out_offset, color);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include "kernel/geom/object.h"
|
||||
#include "kernel/geom/primitive.h"
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
#include "kernel/util/differential.h"
|
||||
|
|
@ -21,8 +22,10 @@ CCL_NAMESPACE_BEGIN
|
|||
ccl_device_noinline void svm_node_enter_bump_eval(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint offset)
|
||||
const ccl_global SVMNodeEnterBumpEval &node)
|
||||
{
|
||||
const uint offset = node.state_offset;
|
||||
|
||||
/* save state */
|
||||
stack_store_float3(stack, offset + 0, sd->P);
|
||||
stack_store_float(stack, offset + 3, sd->dP);
|
||||
|
|
@ -48,8 +51,10 @@ ccl_device_noinline void svm_node_enter_bump_eval(KernelGlobals kg,
|
|||
|
||||
ccl_device_noinline void svm_node_leave_bump_eval(ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint offset)
|
||||
const ccl_global SVMNodeLeaveBumpEval &node)
|
||||
{
|
||||
const uint offset = node.state_offset;
|
||||
|
||||
/* restore state */
|
||||
sd->P = stack_load_float3(stack, offset + 0);
|
||||
sd->dP = stack_load_float(stack, offset + 3);
|
||||
|
|
|
|||
|
|
@ -6,36 +6,31 @@
|
|||
|
||||
#include "kernel/globals.h"
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
ccl_device_noinline void svm_node_camera(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint out_vector,
|
||||
const uint out_zdepth,
|
||||
const uint out_distance)
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeCamera &ccl_restrict node)
|
||||
{
|
||||
float distance;
|
||||
float zdepth;
|
||||
float3 vector;
|
||||
|
||||
const Transform tfm = kernel_data.cam.worldtocamera;
|
||||
vector = transform_point(&tfm, sd->P);
|
||||
zdepth = vector.z;
|
||||
distance = len(vector);
|
||||
const float3 vector = transform_point(&tfm, sd->P);
|
||||
const float zdepth = vector.z;
|
||||
const float distance = len(vector);
|
||||
|
||||
if (stack_valid(out_vector)) {
|
||||
stack_store_float3(stack, out_vector, normalize(vector));
|
||||
if (stack_valid(node.vector_offset)) {
|
||||
stack_store_float3(stack, node.vector_offset, normalize(vector));
|
||||
}
|
||||
|
||||
if (stack_valid(out_zdepth)) {
|
||||
stack_store_float(stack, out_zdepth, zdepth);
|
||||
if (stack_valid(node.zdepth_offset)) {
|
||||
stack_store_float(stack, node.zdepth_offset, zdepth);
|
||||
}
|
||||
|
||||
if (stack_valid(out_distance)) {
|
||||
stack_store_float(stack, out_distance, distance);
|
||||
if (stack_valid(node.distance_offset)) {
|
||||
stack_store_float(stack, node.distance_offset, distance);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
|
@ -24,30 +25,21 @@ ccl_device float svm_checker(float3 p)
|
|||
return ((xi % 2 == yi % 2) == (zi % 2)) ? 1.0f : 0.0f;
|
||||
}
|
||||
|
||||
ccl_device_noinline void svm_node_tex_checker(ccl_private float *stack, const uint4 node)
|
||||
ccl_device_noinline void svm_node_tex_checker(
|
||||
ccl_private float *ccl_restrict stack, const ccl_global SVMNodeTexChecker &ccl_restrict node)
|
||||
{
|
||||
uint co_offset;
|
||||
uint color1_offset;
|
||||
uint color2_offset;
|
||||
uint scale_offset;
|
||||
uint color_offset;
|
||||
uint fac_offset;
|
||||
|
||||
svm_unpack_node_uchar4(node.y, &co_offset, &color1_offset, &color2_offset, &scale_offset);
|
||||
svm_unpack_node_uchar2(node.z, &color_offset, &fac_offset);
|
||||
|
||||
const float3 co = stack_load_float3(stack, co_offset);
|
||||
const float3 color1 = stack_load_float3(stack, color1_offset);
|
||||
const float3 color2 = stack_load_float3(stack, color2_offset);
|
||||
const float scale = stack_load_float_default(stack, scale_offset, node.w);
|
||||
const float3 co = stack_load_float3(stack, node.co);
|
||||
const float3 color1 = stack_load(stack, node.color1);
|
||||
const float3 color2 = stack_load(stack, node.color2);
|
||||
const float scale = stack_load(stack, node.scale);
|
||||
|
||||
const float f = svm_checker(co * scale);
|
||||
|
||||
if (stack_valid(color_offset)) {
|
||||
stack_store_float3(stack, color_offset, (f == 1.0f) ? color1 : color2);
|
||||
if (stack_valid(node.color_offset)) {
|
||||
stack_store_float3(stack, node.color_offset, (f == 1.0f) ? color1 : color2);
|
||||
}
|
||||
if (stack_valid(fac_offset)) {
|
||||
stack_store_float(stack, fac_offset, f);
|
||||
if (stack_valid(node.fac_offset)) {
|
||||
stack_store_float(stack, node.fac_offset, f);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,37 +4,26 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Clamp Node */
|
||||
|
||||
ccl_device_noinline int svm_node_clamp(KernelGlobals kg,
|
||||
ccl_private float *stack,
|
||||
const uint value_stack_offset,
|
||||
const uint parameters_stack_offsets,
|
||||
const uint result_stack_offset,
|
||||
int offset)
|
||||
ccl_device_noinline void svm_node_clamp(ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeClamp &ccl_restrict node)
|
||||
{
|
||||
uint min_stack_offset;
|
||||
uint max_stack_offset;
|
||||
uint type;
|
||||
svm_unpack_node_uchar3(parameters_stack_offsets, &min_stack_offset, &max_stack_offset, &type);
|
||||
const float value = stack_load(stack, node.value);
|
||||
const float min = stack_load(stack, node.min);
|
||||
const float max = stack_load(stack, node.max);
|
||||
|
||||
const uint4 defaults = read_node(kg, &offset);
|
||||
|
||||
const float value = stack_load_float(stack, value_stack_offset);
|
||||
const float min = stack_load_float_default(stack, min_stack_offset, defaults.x);
|
||||
const float max = stack_load_float_default(stack, max_stack_offset, defaults.y);
|
||||
|
||||
if (type == NODE_CLAMP_RANGE && (min > max)) {
|
||||
stack_store_float(stack, result_stack_offset, clamp(value, max, min));
|
||||
if (node.clamp_type == NODE_CLAMP_RANGE && (min > max)) {
|
||||
stack_store_float(stack, node.result_offset, clamp(value, max, min));
|
||||
}
|
||||
else {
|
||||
stack_store_float(stack, result_stack_offset, clamp(value, min, max));
|
||||
stack_store_float(stack, node.result_offset, clamp(value, min, max));
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
#include "kernel/util/colorspace.h"
|
||||
|
|
@ -13,53 +14,54 @@ CCL_NAMESPACE_BEGIN
|
|||
/* Conversion Nodes */
|
||||
|
||||
template<typename FloatType, typename Float3Type>
|
||||
ccl_device_noinline void svm_node_convert(
|
||||
KernelGlobals kg, ccl_private float *stack, const uint type, const uint from, const uint to)
|
||||
ccl_device_noinline void svm_node_convert(KernelGlobals kg,
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeConvert &ccl_restrict node)
|
||||
{
|
||||
|
||||
switch ((NodeConvert)type) {
|
||||
switch (node.convert_type) {
|
||||
case NODE_CONVERT_FI: {
|
||||
/* TODO(weizhen): should actually store 0 for int, but none of the nodes that we compute
|
||||
* derivatives for has int inputs, so seems fine. */
|
||||
const float f = stack_load_float(stack, from);
|
||||
stack_store_int(stack, to, float_to_int(f));
|
||||
const float f = stack_load_float(stack, node.from_offset);
|
||||
stack_store_int(stack, node.to_offset, float_to_int(f));
|
||||
break;
|
||||
}
|
||||
case NODE_CONVERT_FV: {
|
||||
const FloatType f = stack_load<FloatType>(stack, from);
|
||||
stack_store(stack, to, make_float3(f, f, f));
|
||||
const FloatType f = stack_load<FloatType>(stack, node.from_offset);
|
||||
stack_store(stack, node.to_offset, make_float3(f, f, f));
|
||||
break;
|
||||
}
|
||||
case NODE_CONVERT_CF: {
|
||||
const Float3Type f = stack_load<Float3Type>(stack, from);
|
||||
stack_store(stack, to, linear_rgb_to_gray(kg, f));
|
||||
const Float3Type f = stack_load<Float3Type>(stack, node.from_offset);
|
||||
stack_store(stack, node.to_offset, linear_rgb_to_gray(kg, f));
|
||||
break;
|
||||
}
|
||||
case NODE_CONVERT_CI: {
|
||||
const float3 f = stack_load_float3(stack, from);
|
||||
const float3 f = stack_load_float3(stack, node.from_offset);
|
||||
const int i = (int)linear_rgb_to_gray(kg, f);
|
||||
stack_store_int(stack, to, i);
|
||||
stack_store_int(stack, node.to_offset, i);
|
||||
break;
|
||||
}
|
||||
case NODE_CONVERT_VF: {
|
||||
const Float3Type f = stack_load<Float3Type>(stack, from);
|
||||
stack_store(stack, to, average(f));
|
||||
const Float3Type f = stack_load<Float3Type>(stack, node.from_offset);
|
||||
stack_store(stack, node.to_offset, average(f));
|
||||
break;
|
||||
}
|
||||
case NODE_CONVERT_VI: {
|
||||
const float3 f = stack_load_float3(stack, from);
|
||||
const float3 f = stack_load_float3(stack, node.from_offset);
|
||||
const int i = (int)average(f);
|
||||
stack_store_int(stack, to, i);
|
||||
stack_store_int(stack, node.to_offset, i);
|
||||
break;
|
||||
}
|
||||
case NODE_CONVERT_IF: {
|
||||
const float f = (float)stack_load_int(stack, from);
|
||||
stack_store(stack, to, FloatType(f));
|
||||
const float f = (float)stack_load_int(stack, node.from_offset);
|
||||
stack_store(stack, node.to_offset, FloatType(f));
|
||||
break;
|
||||
}
|
||||
case NODE_CONVERT_IV: {
|
||||
const float f = (float)stack_load_int(stack, from);
|
||||
stack_store(stack, to, Float3Type(make_float3(f, f, f)));
|
||||
const float f = (float)stack_load_int(stack, node.from_offset);
|
||||
stack_store(stack, node.to_offset, Float3Type(make_float3(f, f, f)));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include "kernel/geom/object.h"
|
||||
#include "kernel/geom/primitive.h"
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
#include "kernel/util/differential.h"
|
||||
|
|
@ -16,43 +17,29 @@ CCL_NAMESPACE_BEGIN
|
|||
|
||||
/* Bump Node */
|
||||
template<uint node_feature_mask>
|
||||
ccl_device_noinline int svm_node_set_bump(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint4 node,
|
||||
int offset)
|
||||
ccl_device_noinline void svm_node_set_bump(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const ccl_global SVMNodeSetBump &node)
|
||||
{
|
||||
uint out_offset;
|
||||
uint bump_state_offset;
|
||||
svm_unpack_node_uchar2(node.w, &out_offset, &bump_state_offset);
|
||||
const uint4 data_node = read_node(kg, &offset);
|
||||
const float bump_filter_width = __uint_as_float(data_node.x);
|
||||
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
IF_KERNEL_NODES_FEATURE(BUMP)
|
||||
{
|
||||
/* get normal input */
|
||||
uint normal_offset;
|
||||
uint scale_offset;
|
||||
uint invert;
|
||||
uint use_object_space;
|
||||
svm_unpack_node_uchar4(node.y, &normal_offset, &scale_offset, &invert, &use_object_space);
|
||||
|
||||
float3 normal_in = stack_valid(normal_offset) ? stack_load_float3(stack, normal_offset) :
|
||||
sd->N;
|
||||
float3 normal_in = stack_load_float3_default(stack, node.normal_offset, sd->N);
|
||||
|
||||
/* If we have saved bump state, read the full differential from there.
|
||||
* Just using the compact form in those cases leads to incorrect normals (see #111588). */
|
||||
differential3 dP;
|
||||
if (bump_state_offset == SVM_STACK_INVALID) {
|
||||
if (node.bump_state_offset == SVM_STACK_INVALID) {
|
||||
dP = differential_from_compact(sd->Ng, sd->dP);
|
||||
}
|
||||
else {
|
||||
dP.dx = stack_load_float3(stack, bump_state_offset + 4);
|
||||
dP.dy = stack_load_float3(stack, bump_state_offset + 7);
|
||||
dP.dx = stack_load_float3(stack, node.bump_state_offset + 4);
|
||||
dP.dy = stack_load_float3(stack, node.bump_state_offset + 7);
|
||||
}
|
||||
|
||||
if (use_object_space) {
|
||||
if (node.use_object_space) {
|
||||
object_inverse_normal_transform(kg, sd, &normal_in);
|
||||
object_inverse_dir_transform(kg, sd, &dP.dx);
|
||||
object_inverse_dir_transform(kg, sd, &dP.dy);
|
||||
|
|
@ -63,15 +50,9 @@ ccl_device_noinline int svm_node_set_bump(KernelGlobals kg,
|
|||
const float3 Ry = cross(normal_in, dP.dx);
|
||||
|
||||
/* get bump values */
|
||||
uint c_offset;
|
||||
uint x_offset;
|
||||
uint y_offset;
|
||||
uint strength_offset;
|
||||
svm_unpack_node_uchar4(node.z, &c_offset, &x_offset, &y_offset, &strength_offset);
|
||||
|
||||
const float h_c = stack_load_float(stack, c_offset);
|
||||
const float h_x = stack_load_float(stack, x_offset);
|
||||
const float h_y = stack_load_float(stack, y_offset);
|
||||
const float h_c = stack_load_float(stack, node.center_offset);
|
||||
const float h_x = stack_load_float(stack, node.dx_offset);
|
||||
const float h_y = stack_load_float(stack, node.dy_offset);
|
||||
|
||||
/* compute surface gradient and determinant */
|
||||
const float det = dot(dP.dx, Rx);
|
||||
|
|
@ -79,10 +60,10 @@ ccl_device_noinline int svm_node_set_bump(KernelGlobals kg,
|
|||
|
||||
const float absdet = fabsf(det);
|
||||
|
||||
float strength = stack_load_float(stack, strength_offset);
|
||||
float scale = stack_load_float(stack, scale_offset);
|
||||
float strength = stack_load(stack, node.strength);
|
||||
float scale = stack_load(stack, node.scale);
|
||||
|
||||
if (invert) {
|
||||
if (node.invert) {
|
||||
scale *= -1.0f;
|
||||
}
|
||||
|
||||
|
|
@ -95,7 +76,7 @@ ccl_device_noinline int svm_node_set_bump(KernelGlobals kg,
|
|||
* = cross(dPdx, dPdy) - scale * ((h_y - h_c) / filter_width * Ry + (h_x - h_c) /
|
||||
* filter_width * Rx) ≈ det * normal_in - scale * surfgrad / filter_width
|
||||
*/
|
||||
float3 normal_out = safe_normalize(bump_filter_width * absdet * normal_in -
|
||||
float3 normal_out = safe_normalize(node.bump_filter_width * absdet * normal_in -
|
||||
scale * signf(det) * surfgrad);
|
||||
if (is_zero(normal_out)) {
|
||||
normal_out = normal_in;
|
||||
|
|
@ -104,18 +85,16 @@ ccl_device_noinline int svm_node_set_bump(KernelGlobals kg,
|
|||
normal_out = normalize(strength * normal_out + (1.0f - strength) * normal_in);
|
||||
}
|
||||
|
||||
if (use_object_space) {
|
||||
if (node.use_object_space) {
|
||||
object_normal_transform(kg, sd, &normal_out);
|
||||
}
|
||||
|
||||
stack_store_float3(stack, out_offset, normal_out);
|
||||
stack_store_float3(stack, node.out_offset, normal_out);
|
||||
}
|
||||
else {
|
||||
stack_store_float3(stack, out_offset, zero_float3());
|
||||
stack_store_float3(stack, node.out_offset, zero_float3());
|
||||
}
|
||||
#endif
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
/* Displacement Node */
|
||||
|
|
@ -123,11 +102,11 @@ ccl_device_noinline int svm_node_set_bump(KernelGlobals kg,
|
|||
template<uint node_feature_mask>
|
||||
ccl_device void svm_node_set_displacement(ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint fac_offset)
|
||||
const ccl_global SVMNodeSetDisplacement &node)
|
||||
{
|
||||
IF_KERNEL_NODES_FEATURE(BUMP)
|
||||
{
|
||||
const float3 dP = stack_load_float3(stack, fac_offset);
|
||||
const float3 dP = stack_load_float3(stack, node.fac_offset);
|
||||
sd->P += dP;
|
||||
}
|
||||
}
|
||||
|
|
@ -136,27 +115,18 @@ template<uint node_feature_mask>
|
|||
ccl_device_noinline void svm_node_displacement(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint4 node)
|
||||
const ccl_global SVMNodeDisplacement &node)
|
||||
{
|
||||
IF_KERNEL_NODES_FEATURE(BUMP)
|
||||
{
|
||||
uint height_offset;
|
||||
uint midlevel_offset;
|
||||
uint scale_offset;
|
||||
uint normal_offset;
|
||||
svm_unpack_node_uchar4(
|
||||
node.y, &height_offset, &midlevel_offset, &scale_offset, &normal_offset);
|
||||
|
||||
const float height = stack_load_float(stack, height_offset);
|
||||
const float midlevel = stack_load_float(stack, midlevel_offset);
|
||||
const float scale = stack_load_float(stack, scale_offset);
|
||||
const float3 normal = stack_valid(normal_offset) ? stack_load_float3(stack, normal_offset) :
|
||||
sd->N;
|
||||
const uint space = node.w;
|
||||
const float height = stack_load(stack, node.height);
|
||||
const float midlevel = stack_load(stack, node.midlevel);
|
||||
const float scale = stack_load(stack, node.scale);
|
||||
const float3 normal = stack_load_float3_default(stack, node.normal_offset, sd->N);
|
||||
|
||||
float3 dP = normal;
|
||||
|
||||
if (space == NODE_NORMAL_MAP_OBJECT) {
|
||||
if (node.space == NODE_NORMAL_MAP_OBJECT) {
|
||||
/* Object space. */
|
||||
object_inverse_normal_transform(kg, sd, &dP);
|
||||
dP *= (height - midlevel) * scale;
|
||||
|
|
@ -167,43 +137,33 @@ ccl_device_noinline void svm_node_displacement(KernelGlobals kg,
|
|||
dP *= (height - midlevel) * scale;
|
||||
}
|
||||
|
||||
stack_store_float3(stack, node.z, dP);
|
||||
stack_store_float3(stack, node.out_offset, dP);
|
||||
}
|
||||
else {
|
||||
stack_store_float3(stack, node.z, zero_float3());
|
||||
stack_store_float3(stack, node.out_offset, zero_float3());
|
||||
}
|
||||
}
|
||||
|
||||
template<uint node_feature_mask>
|
||||
ccl_device_noinline int svm_node_vector_displacement(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint4 node,
|
||||
int offset)
|
||||
ccl_device_noinline void svm_node_vector_displacement(
|
||||
KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const ccl_global SVMNodeVectorDisplacement &node)
|
||||
{
|
||||
const uint4 data_node = read_node(kg, &offset);
|
||||
uint vector_offset;
|
||||
uint midlevel_offset;
|
||||
uint scale_offset;
|
||||
uint displacement_offset;
|
||||
svm_unpack_node_uchar4(
|
||||
node.y, &vector_offset, &midlevel_offset, &scale_offset, &displacement_offset);
|
||||
|
||||
IF_KERNEL_NODES_FEATURE(BUMP)
|
||||
{
|
||||
const uint space = data_node.x;
|
||||
|
||||
const float3 vector = stack_load_float3(stack, vector_offset);
|
||||
const float midlevel = stack_load_float(stack, midlevel_offset);
|
||||
const float scale = stack_load_float(stack, scale_offset);
|
||||
const float3 vector = stack_load(stack, node.vector);
|
||||
const float midlevel = stack_load(stack, node.midlevel);
|
||||
const float scale = stack_load(stack, node.scale);
|
||||
float3 dP = (vector - make_float3(midlevel, midlevel, midlevel)) * scale;
|
||||
|
||||
if (space == NODE_NORMAL_MAP_TANGENT) {
|
||||
if (node.space == NODE_NORMAL_MAP_TANGENT) {
|
||||
/* Tangent space. */
|
||||
float3 normal = sd->N;
|
||||
object_inverse_normal_transform(kg, sd, &normal);
|
||||
|
||||
const AttributeDescriptor attr = find_attribute(kg, sd, node.z);
|
||||
const AttributeDescriptor attr = find_attribute(kg, sd, node.attr);
|
||||
float3 tangent;
|
||||
if (attr.offset != ATTR_STD_NOT_FOUND) {
|
||||
tangent = primitive_surface_attribute<float3>(kg, sd, attr);
|
||||
|
|
@ -213,7 +173,7 @@ ccl_device_noinline int svm_node_vector_displacement(KernelGlobals kg,
|
|||
}
|
||||
|
||||
float3 bitangent = safe_normalize(cross(normal, tangent));
|
||||
const AttributeDescriptor attr_sign = find_attribute(kg, sd, node.w);
|
||||
const AttributeDescriptor attr_sign = find_attribute(kg, sd, node.attr_sign);
|
||||
if (attr_sign.offset != ATTR_STD_NOT_FOUND) {
|
||||
const float sign = primitive_surface_attribute<float>(kg, sd, attr_sign);
|
||||
bitangent *= sign;
|
||||
|
|
@ -222,19 +182,16 @@ ccl_device_noinline int svm_node_vector_displacement(KernelGlobals kg,
|
|||
dP = tangent * dP.x + normal * dP.y + bitangent * dP.z;
|
||||
}
|
||||
|
||||
if (space != NODE_NORMAL_MAP_WORLD) {
|
||||
if (node.space != NODE_NORMAL_MAP_WORLD) {
|
||||
/* Tangent or object space. */
|
||||
object_dir_transform(kg, sd, &dP);
|
||||
}
|
||||
|
||||
stack_store_float3(stack, displacement_offset, dP);
|
||||
stack_store_float3(stack, node.displacement_offset, dP);
|
||||
}
|
||||
else {
|
||||
stack_store_float3(stack, displacement_offset, zero_float3());
|
||||
(void)data_node;
|
||||
stack_store_float3(stack, node.displacement_offset, zero_float3());
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "kernel/closure/bsdf_util.h"
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
|
@ -13,49 +14,33 @@ CCL_NAMESPACE_BEGIN
|
|||
/* Fresnel Node */
|
||||
|
||||
ccl_device_noinline void svm_node_fresnel(ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint ior_offset,
|
||||
const uint ior_value,
|
||||
const uint node)
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeFresnel &ccl_restrict node)
|
||||
{
|
||||
uint normal_offset;
|
||||
uint out_offset;
|
||||
svm_unpack_node_uchar2(node, &normal_offset, &out_offset);
|
||||
float eta = (stack_valid(ior_offset)) ? stack_load_float(stack, ior_offset) :
|
||||
__uint_as_float(ior_value);
|
||||
const float3 normal_in = stack_valid(normal_offset) ? stack_load_float3(stack, normal_offset) :
|
||||
sd->N;
|
||||
float eta = stack_load(stack, node.ior);
|
||||
const float3 normal_in = stack_load_float3_default(stack, node.normal_offset, sd->N);
|
||||
|
||||
eta = fmaxf(eta, 1e-5f);
|
||||
eta = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta;
|
||||
|
||||
const float f = fresnel_dielectric_cos(dot(sd->wi, normal_in), eta);
|
||||
|
||||
stack_store_float(stack, out_offset, f);
|
||||
stack_store_float(stack, node.out_offset, f);
|
||||
}
|
||||
|
||||
/* Layer Weight Node */
|
||||
|
||||
ccl_device_noinline void svm_node_layer_weight(ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint4 node)
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeLayerWeight &ccl_restrict
|
||||
node)
|
||||
{
|
||||
const uint blend_offset = node.y;
|
||||
const uint blend_value = node.z;
|
||||
|
||||
uint type;
|
||||
uint normal_offset;
|
||||
uint out_offset;
|
||||
svm_unpack_node_uchar3(node.w, &type, &normal_offset, &out_offset);
|
||||
|
||||
float blend = (stack_valid(blend_offset)) ? stack_load_float(stack, blend_offset) :
|
||||
__uint_as_float(blend_value);
|
||||
const float3 normal_in = (stack_valid(normal_offset)) ? stack_load_float3(stack, normal_offset) :
|
||||
sd->N;
|
||||
float blend = stack_load(stack, node.blend);
|
||||
const float3 normal_in = stack_load_float3_default(stack, node.normal_offset, sd->N);
|
||||
|
||||
float f;
|
||||
|
||||
if (type == NODE_LAYER_WEIGHT_FRESNEL) {
|
||||
if (node.weight_type == NODE_LAYER_WEIGHT_FRESNEL) {
|
||||
float eta = fmaxf(1.0f - blend, 1e-5f);
|
||||
eta = (sd->flag & SD_BACKFACING) ? eta : 1.0f / eta;
|
||||
|
||||
|
|
@ -74,7 +59,7 @@ ccl_device_noinline void svm_node_layer_weight(ccl_private ShaderData *sd,
|
|||
f = 1.0f - f;
|
||||
}
|
||||
|
||||
stack_store_float(stack, out_offset, f);
|
||||
stack_store_float(stack, node.out_offset, f);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
#include "util/hash.h"
|
||||
|
|
@ -301,45 +302,16 @@ ccl_device float2 compute_3d_gabor_noise(const float3 coordinates,
|
|||
return sum;
|
||||
}
|
||||
|
||||
ccl_device_noinline int svm_node_tex_gabor(KernelGlobals kg,
|
||||
ccl_private float *stack,
|
||||
const uint type,
|
||||
const uint stack_offsets_1,
|
||||
const uint stack_offsets_2,
|
||||
int offset)
|
||||
ccl_device_noinline void svm_node_tex_gabor(ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeTexGabor &ccl_restrict node)
|
||||
{
|
||||
uint coordinates_stack_offset;
|
||||
uint scale_stack_offset;
|
||||
uint frequency_stack_offset;
|
||||
uint anisotropy_stack_offset;
|
||||
uint orientation_2d_stack_offset;
|
||||
uint orientation_3d_stack_offset;
|
||||
const float3 coordinates = stack_load_float3(stack, node.coordinates);
|
||||
|
||||
svm_unpack_node_uchar4(stack_offsets_1,
|
||||
&coordinates_stack_offset,
|
||||
&scale_stack_offset,
|
||||
&frequency_stack_offset,
|
||||
&anisotropy_stack_offset);
|
||||
svm_unpack_node_uchar2(
|
||||
stack_offsets_2, &orientation_2d_stack_offset, &orientation_3d_stack_offset);
|
||||
|
||||
const float3 coordinates = stack_load_float3(stack, coordinates_stack_offset);
|
||||
|
||||
uint value_stack_offset;
|
||||
uint phase_stack_offset;
|
||||
uint intensity_stack_offset;
|
||||
|
||||
const uint4 node_1 = read_node(kg, &offset);
|
||||
svm_unpack_node_uchar3(
|
||||
node_1.x, &value_stack_offset, &phase_stack_offset, &intensity_stack_offset);
|
||||
const float scale = stack_load_float_default(stack, scale_stack_offset, node_1.y);
|
||||
float frequency = stack_load_float_default(stack, frequency_stack_offset, node_1.z);
|
||||
const float anisotropy = stack_load_float_default(stack, anisotropy_stack_offset, node_1.w);
|
||||
|
||||
const uint4 node_2 = read_node(kg, &offset);
|
||||
const float orientation_2d = stack_load_float_default(
|
||||
stack, orientation_2d_stack_offset, node_2.x);
|
||||
const float3 orientation_3d = stack_load_float3(stack, orientation_3d_stack_offset);
|
||||
const float scale = stack_load(stack, node.scale);
|
||||
float frequency = stack_load(stack, node.frequency);
|
||||
const float anisotropy = stack_load(stack, node.anisotropy);
|
||||
const float orientation_2d = stack_load(stack, node.orientation_2d);
|
||||
const float3 orientation_3d = stack_load(stack, node.orientation_3d);
|
||||
|
||||
const float3 scaled_coordinates = coordinates * scale;
|
||||
const float isotropy = 1.0f - clamp(anisotropy, 0.0f, 1.0f);
|
||||
|
|
@ -347,7 +319,7 @@ ccl_device_noinline int svm_node_tex_gabor(KernelGlobals kg,
|
|||
|
||||
float2 phasor = make_float2(0.0f, 0.0f);
|
||||
float standard_deviation = 1.0f;
|
||||
switch ((NodeGaborType)type) {
|
||||
switch (node.gabor_type) {
|
||||
case NODE_GABOR_TYPE_2D: {
|
||||
phasor = compute_2d_gabor_noise(make_float2(scaled_coordinates.x, scaled_coordinates.y),
|
||||
frequency,
|
||||
|
|
@ -370,23 +342,21 @@ ccl_device_noinline int svm_node_tex_gabor(KernelGlobals kg,
|
|||
|
||||
/* As discussed in compute_2d_gabor_kernel, we use the imaginary part of the phasor as the Gabor
|
||||
* value. But remap to [0, 1] from [-1, 1]. */
|
||||
if (stack_valid(value_stack_offset)) {
|
||||
stack_store_float(stack, value_stack_offset, (phasor.y / normalization_factor) * 0.5f + 0.5f);
|
||||
if (stack_valid(node.value_offset)) {
|
||||
stack_store_float(stack, node.value_offset, (phasor.y / normalization_factor) * 0.5f + 0.5f);
|
||||
}
|
||||
|
||||
/* Compute the phase based on equation (9) in Tricard's paper. But remap the phase into the
|
||||
* [0, 1] range. */
|
||||
if (stack_valid(phase_stack_offset)) {
|
||||
if (stack_valid(node.phase_offset)) {
|
||||
const float phase = (atan2f(phasor.y, phasor.x) + M_PI_F) / (2.0f * M_PI_F);
|
||||
stack_store_float(stack, phase_stack_offset, phase);
|
||||
stack_store_float(stack, node.phase_offset, phase);
|
||||
}
|
||||
|
||||
/* Compute the intensity based on equation (8) in Tricard's paper. */
|
||||
if (stack_valid(intensity_stack_offset)) {
|
||||
stack_store_float(stack, intensity_stack_offset, len(phasor) / normalization_factor);
|
||||
if (stack_valid(node.intensity_offset)) {
|
||||
stack_store_float(stack, node.intensity_offset, len(phasor) / normalization_factor);
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -5,22 +5,21 @@
|
|||
#pragma once
|
||||
|
||||
#include "kernel/svm/math_util.h"
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
ccl_device_noinline void svm_node_gamma(ccl_private float *stack,
|
||||
const uint in_gamma,
|
||||
const uint in_color,
|
||||
const uint out_color)
|
||||
ccl_device_noinline void svm_node_gamma(ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeGamma &ccl_restrict node)
|
||||
{
|
||||
float3 color = stack_load_float3(stack, in_color);
|
||||
const float gamma = stack_load_float(stack, in_gamma);
|
||||
float3 color = stack_load(stack, node.color);
|
||||
const float gamma = stack_load(stack, node.gamma);
|
||||
|
||||
color = svm_math_gamma_color(color, gamma);
|
||||
|
||||
if (stack_valid(out_color)) {
|
||||
stack_store_float3(stack, out_color, color);
|
||||
if (stack_valid(node.out_offset)) {
|
||||
stack_store_float3(stack, node.out_offset, color);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include "kernel/geom/primitive.h"
|
||||
|
||||
#include "kernel/svm/attribute.h"
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
#include "util/hash.h"
|
||||
|
|
@ -19,7 +20,7 @@ CCL_NAMESPACE_BEGIN
|
|||
template<typename Float3Type>
|
||||
ccl_device_inline Float3Type svm_node_geometry_eval(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
const uint type)
|
||||
const NodeGeometry type)
|
||||
{
|
||||
Float3Type data;
|
||||
|
||||
|
|
@ -55,38 +56,31 @@ ccl_device_inline Float3Type svm_node_geometry_eval(KernelGlobals kg,
|
|||
return data;
|
||||
}
|
||||
|
||||
template<typename Float3Type>
|
||||
ccl_device_noinline void svm_node_geometry(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint4 node)
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeGeometry &ccl_restrict node)
|
||||
{
|
||||
uint type, unused1, unused2;
|
||||
svm_unpack_node_uchar3(node.y, &type, &unused1, &unused2);
|
||||
stack_store(stack, node.z, svm_node_geometry_eval<float3>(kg, sd, type));
|
||||
}
|
||||
Float3Type data = svm_node_geometry_eval<Float3Type>(kg, sd, node.geom_type);
|
||||
|
||||
ccl_device_noinline void svm_node_geometry_derivative(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint4 node)
|
||||
{
|
||||
uint type, bump_offset, store_derivatives;
|
||||
svm_unpack_node_uchar3(node.y, &type, &bump_offset, &store_derivatives);
|
||||
|
||||
/* Compute with derivatives, then apply first-order bump offset. */
|
||||
dual3 data = svm_node_geometry_eval<dual3>(kg, sd, type);
|
||||
const float bump_filter_width = __uint_as_float(node.w);
|
||||
if (bump_offset == NODE_BUMP_OFFSET_DX) {
|
||||
data.val += data.dx * bump_filter_width;
|
||||
}
|
||||
else if (bump_offset == NODE_BUMP_OFFSET_DY) {
|
||||
data.val += data.dy * bump_filter_width;
|
||||
}
|
||||
if (store_derivatives) {
|
||||
stack_store(stack, node.z, data);
|
||||
if constexpr (is_dual_v<Float3Type>) {
|
||||
/* Apply first-order bump offset. */
|
||||
if (node.bump_offset == NODE_BUMP_OFFSET_DX) {
|
||||
data.val += data.dx * node.bump_filter_width;
|
||||
}
|
||||
else if (node.bump_offset == NODE_BUMP_OFFSET_DY) {
|
||||
data.val += data.dy * node.bump_filter_width;
|
||||
}
|
||||
if (node.store_derivatives) {
|
||||
stack_store(stack, node.out_offset, data);
|
||||
}
|
||||
else {
|
||||
stack_store(stack, node.out_offset, data.val);
|
||||
}
|
||||
}
|
||||
else {
|
||||
stack_store(stack, node.z, data.val);
|
||||
stack_store(stack, node.out_offset, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -94,19 +88,19 @@ ccl_device_noinline void svm_node_geometry_derivative(KernelGlobals kg,
|
|||
|
||||
ccl_device_noinline void svm_node_object_info(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint type,
|
||||
const uint out_offset)
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeObjectInfo &ccl_restrict
|
||||
node)
|
||||
{
|
||||
float data;
|
||||
|
||||
switch (type) {
|
||||
switch (node.info_type) {
|
||||
case NODE_INFO_OB_LOCATION: {
|
||||
stack_store_float3(stack, out_offset, object_location(kg, sd));
|
||||
stack_store_float3(stack, node.out_offset, object_location(kg, sd));
|
||||
return;
|
||||
}
|
||||
case NODE_INFO_OB_COLOR: {
|
||||
stack_store_float3(stack, out_offset, object_color(kg, sd->object));
|
||||
stack_store_float3(stack, node.out_offset, object_color(kg, sd->object));
|
||||
return;
|
||||
}
|
||||
case NODE_INFO_OB_ALPHA:
|
||||
|
|
@ -127,64 +121,64 @@ ccl_device_noinline void svm_node_object_info(KernelGlobals kg,
|
|||
break;
|
||||
}
|
||||
|
||||
stack_store_float(stack, out_offset, data);
|
||||
stack_store_float(stack, node.out_offset, data);
|
||||
}
|
||||
|
||||
/* Particle Info */
|
||||
|
||||
ccl_device_noinline void svm_node_particle_info(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint type,
|
||||
const uint out_offset)
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeParticleInfo &ccl_restrict
|
||||
node)
|
||||
{
|
||||
switch ((NodeParticleInfo)type) {
|
||||
switch (node.info_type) {
|
||||
case NODE_INFO_PAR_INDEX: {
|
||||
const int particle_id = object_particle_id(kg, sd->object);
|
||||
stack_store_float(stack, out_offset, particle_index(kg, particle_id));
|
||||
stack_store_float(stack, node.out_offset, particle_index(kg, particle_id));
|
||||
break;
|
||||
}
|
||||
case NODE_INFO_PAR_RANDOM: {
|
||||
const int particle_id = object_particle_id(kg, sd->object);
|
||||
const float random = hash_uint2_to_float(particle_index(kg, particle_id), 0);
|
||||
stack_store_float(stack, out_offset, random);
|
||||
stack_store_float(stack, node.out_offset, random);
|
||||
break;
|
||||
}
|
||||
case NODE_INFO_PAR_AGE: {
|
||||
const int particle_id = object_particle_id(kg, sd->object);
|
||||
stack_store_float(stack, out_offset, particle_age(kg, particle_id));
|
||||
stack_store_float(stack, node.out_offset, particle_age(kg, particle_id));
|
||||
break;
|
||||
}
|
||||
case NODE_INFO_PAR_LIFETIME: {
|
||||
const int particle_id = object_particle_id(kg, sd->object);
|
||||
stack_store_float(stack, out_offset, particle_lifetime(kg, particle_id));
|
||||
stack_store_float(stack, node.out_offset, particle_lifetime(kg, particle_id));
|
||||
break;
|
||||
}
|
||||
case NODE_INFO_PAR_LOCATION: {
|
||||
const int particle_id = object_particle_id(kg, sd->object);
|
||||
stack_store_float3(stack, out_offset, particle_location(kg, particle_id));
|
||||
stack_store_float3(stack, node.out_offset, particle_location(kg, particle_id));
|
||||
break;
|
||||
}
|
||||
#if 0 /* XXX float4 currently not supported in SVM stack */
|
||||
case NODE_INFO_PAR_ROTATION: {
|
||||
int particle_id = object_particle_id(kg, sd->object);
|
||||
stack_store_float4(stack, out_offset, particle_rotation(kg, particle_id));
|
||||
stack_store_float4(stack, node.out_offset, particle_rotation(kg, particle_id));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case NODE_INFO_PAR_SIZE: {
|
||||
const int particle_id = object_particle_id(kg, sd->object);
|
||||
stack_store_float(stack, out_offset, particle_size(kg, particle_id));
|
||||
stack_store_float(stack, node.out_offset, particle_size(kg, particle_id));
|
||||
break;
|
||||
}
|
||||
case NODE_INFO_PAR_VELOCITY: {
|
||||
const int particle_id = object_particle_id(kg, sd->object);
|
||||
stack_store_float3(stack, out_offset, particle_velocity(kg, particle_id));
|
||||
stack_store_float3(stack, node.out_offset, particle_velocity(kg, particle_id));
|
||||
break;
|
||||
}
|
||||
case NODE_INFO_PAR_ANGULAR_VELOCITY: {
|
||||
const int particle_id = object_particle_id(kg, sd->object);
|
||||
stack_store_float3(stack, out_offset, particle_angular_velocity(kg, particle_id));
|
||||
stack_store_float3(stack, node.out_offset, particle_angular_velocity(kg, particle_id));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -196,17 +190,16 @@ ccl_device_noinline void svm_node_particle_info(KernelGlobals kg,
|
|||
|
||||
ccl_device_noinline void svm_node_hair_info(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint type,
|
||||
const uint out_offset)
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeHairInfo &ccl_restrict node)
|
||||
{
|
||||
float data;
|
||||
float3 data3;
|
||||
|
||||
switch ((NodeHairInfo)type) {
|
||||
switch (node.info_type) {
|
||||
case NODE_INFO_CURVE_IS_STRAND: {
|
||||
data = (sd->type & PRIMITIVE_CURVE) != 0;
|
||||
stack_store_float(stack, out_offset, data);
|
||||
stack_store_float(stack, node.out_offset, data);
|
||||
break;
|
||||
}
|
||||
case NODE_INFO_CURVE_INTERCEPT:
|
||||
|
|
@ -217,12 +210,12 @@ ccl_device_noinline void svm_node_hair_info(KernelGlobals kg,
|
|||
break; /* handled as attribute */
|
||||
case NODE_INFO_CURVE_THICKNESS: {
|
||||
data = curve_thickness(kg, sd);
|
||||
stack_store_float(stack, out_offset, data);
|
||||
stack_store_float(stack, node.out_offset, data);
|
||||
break;
|
||||
}
|
||||
case NODE_INFO_CURVE_TANGENT_NORMAL: {
|
||||
data3 = curve_tangent_normal(sd);
|
||||
stack_store_float3(stack, out_offset, data3);
|
||||
stack_store_float3(stack, node.out_offset, data3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -235,16 +228,15 @@ ccl_device_noinline void svm_node_hair_info(KernelGlobals kg,
|
|||
|
||||
ccl_device_noinline void svm_node_point_info(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint type,
|
||||
const uint out_offset)
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodePointInfo &ccl_restrict node)
|
||||
{
|
||||
switch ((NodePointInfo)type) {
|
||||
switch (node.info_type) {
|
||||
case NODE_INFO_POINT_POSITION:
|
||||
stack_store_float3(stack, out_offset, point_position(kg, sd));
|
||||
stack_store_float3(stack, node.out_offset, point_position(kg, sd));
|
||||
break;
|
||||
case NODE_INFO_POINT_RADIUS:
|
||||
stack_store_float(stack, out_offset, point_radius(kg, sd));
|
||||
stack_store_float(stack, node.out_offset, point_radius(kg, sd));
|
||||
break;
|
||||
case NODE_INFO_POINT_RANDOM:
|
||||
break; /* handled as attribute */
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
|
@ -55,25 +56,19 @@ ccl_device float svm_gradient(const float3 p, NodeGradientType type)
|
|||
return 0.0f;
|
||||
}
|
||||
|
||||
ccl_device_noinline void svm_node_tex_gradient(ccl_private float *stack, const uint4 node)
|
||||
ccl_device_noinline void svm_node_tex_gradient(
|
||||
ccl_private float *ccl_restrict stack, const ccl_global SVMNodeTexGradient &ccl_restrict node)
|
||||
{
|
||||
uint type;
|
||||
uint co_offset;
|
||||
uint color_offset;
|
||||
uint fac_offset;
|
||||
const float3 co = stack_load_float3(stack, node.co);
|
||||
|
||||
svm_unpack_node_uchar4(node.y, &type, &co_offset, &fac_offset, &color_offset);
|
||||
|
||||
const float3 co = stack_load_float3(stack, co_offset);
|
||||
|
||||
float f = svm_gradient(co, (NodeGradientType)type);
|
||||
float f = svm_gradient(co, node.gradient_type);
|
||||
f = saturatef(f);
|
||||
|
||||
if (stack_valid(fac_offset)) {
|
||||
stack_store_float(stack, fac_offset, f);
|
||||
if (stack_valid(node.fac_offset)) {
|
||||
stack_store_float(stack, node.fac_offset, f);
|
||||
}
|
||||
if (stack_valid(color_offset)) {
|
||||
stack_store_float3(stack, color_offset, make_float3(f, f, f));
|
||||
if (stack_valid(node.color_offset)) {
|
||||
stack_store_float3(stack, node.color_offset, make_float3(f, f, f));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,30 +4,23 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
#include "util/color.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
ccl_device_noinline void svm_node_hsv(ccl_private float *stack, const uint4 node)
|
||||
ccl_device_noinline void svm_node_hsv(ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeHSV &ccl_restrict node)
|
||||
{
|
||||
uint in_color_offset;
|
||||
uint fac_offset;
|
||||
uint out_color_offset;
|
||||
uint hue_offset;
|
||||
uint sat_offset;
|
||||
uint val_offset;
|
||||
svm_unpack_node_uchar3(node.y, &in_color_offset, &fac_offset, &out_color_offset);
|
||||
svm_unpack_node_uchar3(node.z, &hue_offset, &sat_offset, &val_offset);
|
||||
|
||||
const float fac = stack_load_float(stack, fac_offset);
|
||||
const float3 in_color = stack_load_float3(stack, in_color_offset);
|
||||
const float fac = stack_load(stack, node.fac);
|
||||
const float3 in_color = stack_load(stack, node.color);
|
||||
float3 color = in_color;
|
||||
|
||||
const float hue = stack_load_float(stack, hue_offset);
|
||||
const float sat = stack_load_float(stack, sat_offset);
|
||||
const float val = stack_load_float(stack, val_offset);
|
||||
const float hue = stack_load(stack, node.hue);
|
||||
const float sat = stack_load(stack, node.sat);
|
||||
const float val = stack_load(stack, node.val);
|
||||
|
||||
color = rgb_to_hsv(color);
|
||||
|
||||
|
|
@ -46,8 +39,8 @@ ccl_device_noinline void svm_node_hsv(ccl_private float *stack, const uint4 node
|
|||
color.y = max(color.y, 0.0f);
|
||||
color.z = max(color.z, 0.0f);
|
||||
|
||||
if (stack_valid(out_color_offset)) {
|
||||
stack_store_float3(stack, out_color_offset, color);
|
||||
if (stack_valid(node.out_color_offset)) {
|
||||
stack_store_float3(stack, node.out_color_offset, color);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
#include "kernel/util/ies.h"
|
||||
|
|
@ -13,25 +14,19 @@ CCL_NAMESPACE_BEGIN
|
|||
ccl_device_noinline void svm_node_ies(KernelGlobals kg,
|
||||
ccl_private ShaderData * /*sd*/,
|
||||
ccl_private float *stack,
|
||||
const uint4 node)
|
||||
const ccl_global SVMNodeIES &ccl_restrict node)
|
||||
{
|
||||
uint vector_offset;
|
||||
uint strength_offset;
|
||||
uint fac_offset;
|
||||
const uint slot = node.z;
|
||||
svm_unpack_node_uchar3(node.y, &strength_offset, &vector_offset, &fac_offset);
|
||||
|
||||
float3 vector = stack_load_float3(stack, vector_offset);
|
||||
const float strength = stack_load_float_default(stack, strength_offset, node.w);
|
||||
float3 vector = stack_load_float3(stack, node.vector_offset);
|
||||
const float strength = stack_load(stack, node.strength);
|
||||
|
||||
vector = normalize(vector);
|
||||
const float v_angle = safe_acosf(-vector.z);
|
||||
const float h_angle = atan2f(vector.x, vector.y) + M_PI_F;
|
||||
|
||||
const float fac = strength * kernel_ies_interp(kg, slot, h_angle, v_angle);
|
||||
const float fac = strength * kernel_ies_interp(kg, node.slot, h_angle, v_angle);
|
||||
|
||||
if (stack_valid(fac_offset)) {
|
||||
stack_store_float(stack, fac_offset, fac);
|
||||
if (stack_valid(node.fac_offset)) {
|
||||
stack_store_float(stack, node.fac_offset, fac);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "kernel/geom/object.h"
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
#include "util/color.h"
|
||||
|
|
@ -55,45 +56,31 @@ ccl_device_inline auto svm_node_tex_image_mapping(const Float3Type co, const uin
|
|||
return make_float2(co);
|
||||
}
|
||||
|
||||
template<class Float3Type>
|
||||
ccl_device_noinline void svm_node_tex_image(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint4 node,
|
||||
const bool derivative)
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeTexImage &ccl_restrict node)
|
||||
{
|
||||
uint co_offset;
|
||||
uint out_offset;
|
||||
uint alpha_offset;
|
||||
uint flags;
|
||||
const Float3Type co = stack_load<Float3Type>(stack, node.co);
|
||||
const dual2 tex_co(svm_node_tex_image_mapping(co, node.projection));
|
||||
|
||||
svm_unpack_node_uchar4(node.z, &co_offset, &out_offset, &alpha_offset, &flags);
|
||||
const float4 f = svm_image_texture(kg, sd, node.id, tex_co, node.flags);
|
||||
|
||||
dual2 tex_co;
|
||||
if (derivative) {
|
||||
const dual3 co = stack_load<dual3>(stack, co_offset);
|
||||
tex_co = svm_node_tex_image_mapping(co, node.w);
|
||||
if (stack_valid(node.out_offset)) {
|
||||
stack_store_float3(stack, node.out_offset, make_float3(f));
|
||||
}
|
||||
else {
|
||||
const float3 co = stack_load_float3(stack, co_offset);
|
||||
tex_co = dual2(svm_node_tex_image_mapping(co, node.w));
|
||||
}
|
||||
|
||||
const int id = node.y;
|
||||
const float4 f = svm_image_texture(kg, sd, id, tex_co, flags);
|
||||
|
||||
if (stack_valid(out_offset)) {
|
||||
stack_store_float3(stack, out_offset, make_float3(f));
|
||||
}
|
||||
if (stack_valid(alpha_offset)) {
|
||||
stack_store_float(stack, alpha_offset, f.w);
|
||||
if (stack_valid(node.alpha_offset)) {
|
||||
stack_store_float(stack, node.alpha_offset, f.w);
|
||||
}
|
||||
}
|
||||
|
||||
template<class Float3Type>
|
||||
ccl_device_noinline void svm_node_tex_image_box(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint4 node,
|
||||
const bool derivative)
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeTexImageBox &ccl_restrict
|
||||
node)
|
||||
{
|
||||
/* get object space normal */
|
||||
float3 N = sd->N;
|
||||
|
|
@ -118,7 +105,7 @@ ccl_device_noinline void svm_node_tex_image_box(KernelGlobals kg,
|
|||
* 7 zones, with an `if()` test for each zone. */
|
||||
|
||||
float3 weight = make_float3(0.0f, 0.0f, 0.0f);
|
||||
const float blend = __int_as_float(node.w);
|
||||
const float blend = node.blend;
|
||||
const float limit = 0.5f * (1.0f + blend);
|
||||
|
||||
/* first test for corners with single texture */
|
||||
|
|
@ -161,37 +148,29 @@ ccl_device_noinline void svm_node_tex_image_box(KernelGlobals kg,
|
|||
}
|
||||
|
||||
/* now fetch textures */
|
||||
uint co_offset;
|
||||
uint out_offset;
|
||||
uint alpha_offset;
|
||||
uint flags;
|
||||
svm_unpack_node_uchar4(node.z, &co_offset, &out_offset, &alpha_offset, &flags);
|
||||
|
||||
const uint id = node.y;
|
||||
float4 f = zero_float4();
|
||||
|
||||
const dual3 co = (derivative) ? stack_load<dual3>(stack, co_offset) :
|
||||
dual3(stack_load_float3(stack, co_offset));
|
||||
const dual3 co = dual3(stack_load<Float3Type>(stack, node.co));
|
||||
|
||||
/* Map so that no textures are flipped, rotation is somewhat arbitrary. */
|
||||
if (weight.x > 0.0f) {
|
||||
const dual2 uv = make_float2((signed_N.x < 0.0f) ? 1.0f - co.y() : co.y(), co.z());
|
||||
f += weight.x * svm_image_texture(kg, sd, id, uv, flags);
|
||||
f += weight.x * svm_image_texture(kg, sd, node.id, uv, node.flags);
|
||||
}
|
||||
if (weight.y > 0.0f) {
|
||||
const dual2 uv = make_float2((signed_N.y > 0.0f) ? 1.0f - co.x() : co.x(), co.z());
|
||||
f += weight.y * svm_image_texture(kg, sd, id, uv, flags);
|
||||
f += weight.y * svm_image_texture(kg, sd, node.id, uv, node.flags);
|
||||
}
|
||||
if (weight.z > 0.0f) {
|
||||
const dual2 uv = make_float2((signed_N.z > 0.0f) ? 1.0f - co.y() : co.y(), co.x());
|
||||
f += weight.z * svm_image_texture(kg, sd, id, uv, flags);
|
||||
f += weight.z * svm_image_texture(kg, sd, node.id, uv, node.flags);
|
||||
}
|
||||
|
||||
if (stack_valid(out_offset)) {
|
||||
stack_store_float3(stack, out_offset, make_float3(f.x, f.y, f.z));
|
||||
if (stack_valid(node.out_offset)) {
|
||||
stack_store_float3(stack, node.out_offset, make_float3(f.x, f.y, f.z));
|
||||
}
|
||||
if (stack_valid(alpha_offset)) {
|
||||
stack_store_float(stack, alpha_offset, f.w);
|
||||
if (stack_valid(node.alpha_offset)) {
|
||||
stack_store_float(stack, node.alpha_offset, f.w);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -205,37 +184,23 @@ ccl_device_inline auto svm_node_tex_environment_projection(Float3Type co, const
|
|||
return direction_to_mirrorball(co);
|
||||
}
|
||||
|
||||
ccl_device_noinline void svm_node_tex_environment(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint4 node,
|
||||
const bool derivative)
|
||||
template<class Float3Type>
|
||||
ccl_device_noinline void svm_node_tex_environment(
|
||||
KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeTexEnvironment &ccl_restrict node)
|
||||
{
|
||||
const uint id = node.y;
|
||||
uint co_offset;
|
||||
uint out_offset;
|
||||
uint alpha_offset;
|
||||
uint flags;
|
||||
const Float3Type co = stack_load<Float3Type>(stack, node.co);
|
||||
const dual2 uv(svm_node_tex_environment_projection(co, node.projection));
|
||||
|
||||
svm_unpack_node_uchar4(node.z, &co_offset, &out_offset, &alpha_offset, &flags);
|
||||
const float4 f = svm_image_texture(kg, sd, node.id, uv, node.flags);
|
||||
|
||||
dual2 uv;
|
||||
if (derivative) {
|
||||
const dual3 co = stack_load<dual3>(stack, co_offset);
|
||||
uv = svm_node_tex_environment_projection(co, node.w);
|
||||
if (stack_valid(node.out_offset)) {
|
||||
stack_store_float3(stack, node.out_offset, make_float3(f.x, f.y, f.z));
|
||||
}
|
||||
else {
|
||||
const float3 co = stack_load_float3(stack, co_offset);
|
||||
uv = dual2(svm_node_tex_environment_projection(co, node.w));
|
||||
}
|
||||
|
||||
const float4 f = svm_image_texture(kg, sd, id, uv, flags);
|
||||
|
||||
if (stack_valid(out_offset)) {
|
||||
stack_store_float3(stack, out_offset, make_float3(f.x, f.y, f.z));
|
||||
}
|
||||
if (stack_valid(alpha_offset)) {
|
||||
stack_store_float(stack, alpha_offset, f.w);
|
||||
if (stack_valid(node.alpha_offset)) {
|
||||
stack_store_float(stack, node.alpha_offset, f.w);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
|
@ -13,20 +14,18 @@ ccl_device float invert(const float color, const float factor)
|
|||
return factor * (1.0f - color) + (1.0f - factor) * color;
|
||||
}
|
||||
|
||||
ccl_device_noinline void svm_node_invert(ccl_private float *stack,
|
||||
const uint in_fac,
|
||||
const uint in_color,
|
||||
const uint out_color)
|
||||
ccl_device_noinline void svm_node_invert(ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeInvert &ccl_restrict node)
|
||||
{
|
||||
const float factor = stack_load_float(stack, in_fac);
|
||||
float3 color = stack_load_float3(stack, in_color);
|
||||
const float factor = stack_load(stack, node.fac);
|
||||
float3 color = stack_load(stack, node.color);
|
||||
|
||||
color.x = invert(color.x, factor);
|
||||
color.y = invert(color.y, factor);
|
||||
color.z = invert(color.z, factor);
|
||||
|
||||
if (stack_valid(out_color)) {
|
||||
stack_store_float3(stack, out_color, color);
|
||||
if (stack_valid(node.out_offset)) {
|
||||
stack_store_float3(stack, node.out_offset, color);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
|
@ -14,14 +15,13 @@ template<uint node_feature_mask, typename ConstIntegratorGenericState>
|
|||
ccl_device_noinline void svm_node_light_path(KernelGlobals kg,
|
||||
ConstIntegratorGenericState state,
|
||||
const ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint type,
|
||||
const uint out_offset,
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeLightPath &ccl_restrict node,
|
||||
const uint32_t path_flag)
|
||||
{
|
||||
float info = 0.0f;
|
||||
|
||||
switch ((NodeLightPath)type) {
|
||||
switch (node.path_type) {
|
||||
case NODE_LP_camera:
|
||||
info = (path_flag & PATH_RAY_CAMERA) ? 1.0f : 0.0f;
|
||||
break;
|
||||
|
|
@ -101,32 +101,25 @@ ccl_device_noinline void svm_node_light_path(KernelGlobals kg,
|
|||
break;
|
||||
}
|
||||
|
||||
stack_store_float(stack, out_offset, info);
|
||||
stack_store_float(stack, node.out_offset, info);
|
||||
}
|
||||
|
||||
/* Light Falloff Node */
|
||||
|
||||
ccl_device_noinline void svm_node_light_falloff(ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint4 node)
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeLightFalloff &ccl_restrict
|
||||
node)
|
||||
{
|
||||
uint strength_offset;
|
||||
uint out_offset;
|
||||
uint smooth_offset;
|
||||
|
||||
svm_unpack_node_uchar3(node.z, &strength_offset, &smooth_offset, &out_offset);
|
||||
|
||||
float strength = stack_load_float(stack, strength_offset);
|
||||
float strength = stack_load(stack, node.strength);
|
||||
if (sd->ray_length == FLT_MAX) {
|
||||
/* Distant lights (which have a ray_length of FLT_MAX) overflow when using most outputs of
|
||||
* the light falloff node. So just ignore the node in that case. */
|
||||
stack_store_float(stack, out_offset, strength);
|
||||
stack_store_float(stack, node.out_offset, strength);
|
||||
return;
|
||||
}
|
||||
|
||||
const uint type = node.y;
|
||||
|
||||
switch ((NodeLightFalloff)type) {
|
||||
switch (node.falloff_type) {
|
||||
case NODE_LIGHT_FALLOFF_QUADRATIC:
|
||||
break;
|
||||
case NODE_LIGHT_FALLOFF_LINEAR:
|
||||
|
|
@ -137,14 +130,14 @@ ccl_device_noinline void svm_node_light_falloff(ccl_private ShaderData *sd,
|
|||
break;
|
||||
}
|
||||
|
||||
const float smooth = stack_load_float(stack, smooth_offset);
|
||||
const float smooth = stack_load(stack, node.smooth);
|
||||
|
||||
if (smooth > 0.0f) {
|
||||
const float squared = sd->ray_length * sd->ray_length;
|
||||
strength *= squared / (smooth + squared);
|
||||
}
|
||||
|
||||
stack_store_float(stack, out_offset, strength);
|
||||
stack_store_float(stack, node.out_offset, strength);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
|
@ -98,35 +99,21 @@ ccl_device_noinline_cpu float3 svm_magic(const float3 p,
|
|||
return make_float3(0.5f - x, 0.5f - y, 0.5f - z);
|
||||
}
|
||||
|
||||
ccl_device_noinline int svm_node_tex_magic(KernelGlobals kg,
|
||||
ccl_private float *stack,
|
||||
const uint4 node,
|
||||
int offset)
|
||||
ccl_device_noinline void svm_node_tex_magic(ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeTexMagic &ccl_restrict node)
|
||||
{
|
||||
uint depth;
|
||||
uint scale_offset;
|
||||
uint distortion_offset;
|
||||
uint co_offset;
|
||||
uint fac_offset;
|
||||
uint color_offset;
|
||||
const float3 co = stack_load_float3(stack, node.co);
|
||||
const float scale = stack_load(stack, node.scale);
|
||||
const float distortion = stack_load(stack, node.distortion);
|
||||
|
||||
svm_unpack_node_uchar3(node.y, &depth, &color_offset, &fac_offset);
|
||||
svm_unpack_node_uchar3(node.z, &co_offset, &scale_offset, &distortion_offset);
|
||||
const float3 color = svm_magic(co, scale, node.depth, distortion);
|
||||
|
||||
const uint4 node2 = read_node(kg, &offset);
|
||||
const float3 co = stack_load_float3(stack, co_offset);
|
||||
const float scale = stack_load_float_default(stack, scale_offset, node2.x);
|
||||
const float distortion = stack_load_float_default(stack, distortion_offset, node2.y);
|
||||
|
||||
const float3 color = svm_magic(co, scale, depth, distortion);
|
||||
|
||||
if (stack_valid(fac_offset)) {
|
||||
stack_store_float(stack, fac_offset, average(color));
|
||||
if (stack_valid(node.fac_offset)) {
|
||||
stack_store_float(stack, node.fac_offset, average(color));
|
||||
}
|
||||
if (stack_valid(color_offset)) {
|
||||
stack_store_float3(stack, color_offset, color);
|
||||
if (stack_valid(node.color_offset)) {
|
||||
stack_store_float3(stack, node.color_offset, color);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
|
@ -16,43 +17,21 @@ ccl_device_inline float smootherstep(const float edge0, const float edge1, float
|
|||
return x * x * x * (x * (x * 6.0f - 15.0f) + 10.0f);
|
||||
}
|
||||
|
||||
ccl_device_noinline int svm_node_map_range(KernelGlobals kg,
|
||||
ccl_private float *stack,
|
||||
const uint value_stack_offset,
|
||||
const uint parameters_stack_offsets,
|
||||
const uint results_stack_offsets,
|
||||
int offset)
|
||||
ccl_device_noinline void svm_node_map_range(ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeMapRange &ccl_restrict node)
|
||||
{
|
||||
uint from_min_stack_offset;
|
||||
uint from_max_stack_offset;
|
||||
uint to_min_stack_offset;
|
||||
uint to_max_stack_offset;
|
||||
uint type_stack_offset;
|
||||
uint steps_stack_offset;
|
||||
uint result_stack_offset;
|
||||
svm_unpack_node_uchar4(parameters_stack_offsets,
|
||||
&from_min_stack_offset,
|
||||
&from_max_stack_offset,
|
||||
&to_min_stack_offset,
|
||||
&to_max_stack_offset);
|
||||
svm_unpack_node_uchar3(
|
||||
results_stack_offsets, &type_stack_offset, &steps_stack_offset, &result_stack_offset);
|
||||
|
||||
const uint4 defaults = read_node(kg, &offset);
|
||||
const uint4 defaults2 = read_node(kg, &offset);
|
||||
|
||||
const float value = stack_load_float(stack, value_stack_offset);
|
||||
const float from_min = stack_load_float_default(stack, from_min_stack_offset, defaults.x);
|
||||
const float from_max = stack_load_float_default(stack, from_max_stack_offset, defaults.y);
|
||||
const float to_min = stack_load_float_default(stack, to_min_stack_offset, defaults.z);
|
||||
const float to_max = stack_load_float_default(stack, to_max_stack_offset, defaults.w);
|
||||
const float steps = stack_load_float_default(stack, steps_stack_offset, defaults2.x);
|
||||
const float value = stack_load(stack, node.value);
|
||||
const float from_min = stack_load(stack, node.from_min);
|
||||
const float from_max = stack_load(stack, node.from_max);
|
||||
const float to_min = stack_load(stack, node.to_min);
|
||||
const float to_max = stack_load(stack, node.to_max);
|
||||
const float steps = stack_load(stack, node.steps);
|
||||
|
||||
float result;
|
||||
|
||||
if (from_max != from_min) {
|
||||
float factor = value;
|
||||
switch (type_stack_offset) {
|
||||
switch (node.range_type) {
|
||||
default:
|
||||
case NODE_MAP_RANGE_LINEAR:
|
||||
factor = (value - from_min) / (from_max - from_min);
|
||||
|
|
@ -78,50 +57,27 @@ ccl_device_noinline int svm_node_map_range(KernelGlobals kg,
|
|||
else {
|
||||
result = 0.0f;
|
||||
}
|
||||
stack_store_float(stack, result_stack_offset, result);
|
||||
return offset;
|
||||
stack_store_float(stack, node.result_offset, result);
|
||||
}
|
||||
|
||||
ccl_device_noinline int svm_node_vector_map_range(ccl_private float *stack,
|
||||
const uint value_stack_offset,
|
||||
const uint parameters_stack_offsets,
|
||||
const uint results_stack_offsets,
|
||||
const int offset)
|
||||
ccl_device_noinline void svm_node_vector_map_range(
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeVectorMapRange &ccl_restrict node)
|
||||
{
|
||||
uint from_min_stack_offset;
|
||||
uint from_max_stack_offset;
|
||||
uint to_min_stack_offset;
|
||||
uint to_max_stack_offset;
|
||||
uint steps_stack_offset;
|
||||
uint clamp_stack_offset;
|
||||
uint range_type_stack_offset;
|
||||
uint result_stack_offset;
|
||||
svm_unpack_node_uchar4(parameters_stack_offsets,
|
||||
&from_min_stack_offset,
|
||||
&from_max_stack_offset,
|
||||
&to_min_stack_offset,
|
||||
&to_max_stack_offset);
|
||||
svm_unpack_node_uchar4(results_stack_offsets,
|
||||
&steps_stack_offset,
|
||||
&clamp_stack_offset,
|
||||
&range_type_stack_offset,
|
||||
&result_stack_offset);
|
||||
const float3 value = stack_load(stack, node.value);
|
||||
const float3 from_min = stack_load(stack, node.from_min);
|
||||
const float3 from_max = stack_load(stack, node.from_max);
|
||||
const float3 to_min = stack_load(stack, node.to_min);
|
||||
const float3 to_max = stack_load(stack, node.to_max);
|
||||
const float3 steps = stack_load(stack, node.steps);
|
||||
|
||||
const float3 value = stack_load_float3(stack, value_stack_offset);
|
||||
const float3 from_min = stack_load_float3(stack, from_min_stack_offset);
|
||||
const float3 from_max = stack_load_float3(stack, from_max_stack_offset);
|
||||
const float3 to_min = stack_load_float3(stack, to_min_stack_offset);
|
||||
const float3 to_max = stack_load_float3(stack, to_max_stack_offset);
|
||||
const float3 steps = stack_load_float3(stack, steps_stack_offset);
|
||||
|
||||
const int type = range_type_stack_offset;
|
||||
const int use_clamp = (type == NODE_MAP_RANGE_SMOOTHSTEP ||
|
||||
type == NODE_MAP_RANGE_SMOOTHERSTEP) ?
|
||||
const int use_clamp = (node.range_type == NODE_MAP_RANGE_SMOOTHSTEP ||
|
||||
node.range_type == NODE_MAP_RANGE_SMOOTHERSTEP) ?
|
||||
0 :
|
||||
clamp_stack_offset;
|
||||
node.use_clamp;
|
||||
float3 result;
|
||||
float3 factor = value;
|
||||
switch (range_type_stack_offset) {
|
||||
switch (node.range_type) {
|
||||
default:
|
||||
case NODE_MAP_RANGE_LINEAR:
|
||||
factor = safe_divide((value - from_min), (from_max - from_min));
|
||||
|
|
@ -157,8 +113,7 @@ ccl_device_noinline int svm_node_vector_map_range(ccl_private float *stack,
|
|||
clamp(result.z, to_min.z, to_max.z);
|
||||
}
|
||||
|
||||
stack_store_float3(stack, result_stack_offset, result);
|
||||
return offset;
|
||||
stack_store_float3(stack, node.result_offset, result);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "kernel/svm/mapping_util.h"
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
|
@ -12,64 +13,41 @@ CCL_NAMESPACE_BEGIN
|
|||
/* Mapping Node */
|
||||
|
||||
template<typename Float3Type>
|
||||
ccl_device_noinline void svm_node_mapping(ccl_private float *stack,
|
||||
const uint type,
|
||||
const uint inputs_stack_offsets,
|
||||
const uint result_stack_offset)
|
||||
ccl_device_noinline void svm_node_mapping(ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeMapping &ccl_restrict node)
|
||||
{
|
||||
uint vector_stack_offset;
|
||||
uint location_stack_offset;
|
||||
uint rotation_stack_offset;
|
||||
uint scale_stack_offset;
|
||||
svm_unpack_node_uchar4(inputs_stack_offsets,
|
||||
&vector_stack_offset,
|
||||
&location_stack_offset,
|
||||
&rotation_stack_offset,
|
||||
&scale_stack_offset);
|
||||
const float3 location = stack_load(stack, node.location);
|
||||
const float3 rotation = stack_load(stack, node.rotation);
|
||||
const float3 scale = stack_load(stack, node.scale);
|
||||
|
||||
const float3 location = stack_load_float3(stack, location_stack_offset);
|
||||
const float3 rotation = stack_load_float3(stack, rotation_stack_offset);
|
||||
const float3 scale = stack_load_float3(stack, scale_stack_offset);
|
||||
|
||||
const Float3Type vector = stack_load<Float3Type>(stack, vector_stack_offset);
|
||||
const Float3Type result = svm_mapping((NodeMappingType)type, vector, location, rotation, scale);
|
||||
stack_store(stack, result_stack_offset, result);
|
||||
const Float3Type vector = stack_load<Float3Type>(stack, node.vector);
|
||||
const Float3Type result = svm_mapping(node.mapping_type, vector, location, rotation, scale);
|
||||
stack_store(stack, node.result_offset, result);
|
||||
}
|
||||
|
||||
/* Texture Mapping */
|
||||
|
||||
ccl_device_noinline int svm_node_texture_mapping(KernelGlobals kg,
|
||||
ccl_private float *stack,
|
||||
const uint vec_offset,
|
||||
const uint out_offset,
|
||||
int offset)
|
||||
ccl_device_noinline void svm_node_texture_mapping(
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeTextureMapping &ccl_restrict node)
|
||||
{
|
||||
const float3 v = stack_load_float3(stack, vec_offset);
|
||||
|
||||
Transform tfm;
|
||||
tfm.x = read_node_float(kg, &offset);
|
||||
tfm.y = read_node_float(kg, &offset);
|
||||
tfm.z = read_node_float(kg, &offset);
|
||||
const float3 v = stack_load_float3(stack, node.vec_offset);
|
||||
const Transform tfm = make_transform(node.tfm);
|
||||
|
||||
const float3 r = transform_point(&tfm, v);
|
||||
stack_store_float3(stack, out_offset, r);
|
||||
return offset;
|
||||
stack_store_float3(stack, node.out_offset, r);
|
||||
}
|
||||
|
||||
ccl_device_noinline int svm_node_min_max(KernelGlobals kg,
|
||||
ccl_private float *stack,
|
||||
const uint vec_offset,
|
||||
const uint out_offset,
|
||||
int offset)
|
||||
ccl_device_noinline void svm_node_min_max(ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeMinMax &ccl_restrict node)
|
||||
{
|
||||
const float3 v = stack_load_float3(stack, vec_offset);
|
||||
const float3 v = stack_load_float3(stack, node.vec_offset);
|
||||
|
||||
const float3 mn = make_float3(read_node_float(kg, &offset));
|
||||
const float3 mx = make_float3(read_node_float(kg, &offset));
|
||||
const float3 mn = node.mn;
|
||||
const float3 mx = node.mx;
|
||||
|
||||
const float3 r = min(max(mn, v), mx);
|
||||
stack_store_float3(stack, out_offset, r);
|
||||
return offset;
|
||||
stack_store_float3(stack, node.out_offset, r);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -5,72 +5,43 @@
|
|||
#pragma once
|
||||
|
||||
#include "kernel/svm/math_util.h"
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
ccl_device_noinline void svm_node_math(ccl_private float *stack,
|
||||
const uint type,
|
||||
const uint inputs_stack_offsets,
|
||||
const uint result_stack_offset)
|
||||
ccl_device_noinline void svm_node_math(ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeMath &ccl_restrict node)
|
||||
{
|
||||
uint a_stack_offset;
|
||||
uint b_stack_offset;
|
||||
uint c_stack_offset;
|
||||
svm_unpack_node_uchar3(inputs_stack_offsets, &a_stack_offset, &b_stack_offset, &c_stack_offset);
|
||||
const float a = stack_load(stack, node.value1);
|
||||
const float b = stack_load(stack, node.value2);
|
||||
const float c = stack_load(stack, node.value3);
|
||||
const float result = svm_math(node.math_type, a, b, c);
|
||||
|
||||
const float a = stack_load_float(stack, a_stack_offset);
|
||||
const float b = stack_load_float(stack, b_stack_offset);
|
||||
const float c = stack_load_float(stack, c_stack_offset);
|
||||
const float result = svm_math((NodeMathType)type, a, b, c);
|
||||
|
||||
stack_store_float(stack, result_stack_offset, result);
|
||||
stack_store_float(stack, node.result_offset, result);
|
||||
}
|
||||
|
||||
template<typename Float3Type>
|
||||
ccl_device_noinline int svm_node_vector_math(KernelGlobals kg,
|
||||
ccl_private float *stack,
|
||||
const uint type,
|
||||
const uint inputs_stack_offsets,
|
||||
const uint outputs_stack_offsets,
|
||||
int offset)
|
||||
ccl_device_noinline void svm_node_vector_math(
|
||||
ccl_private float *ccl_restrict stack, const ccl_global SVMNodeVectorMath &ccl_restrict node)
|
||||
{
|
||||
using FloatType = dual_scalar_t<Float3Type>;
|
||||
|
||||
uint value_stack_offset;
|
||||
uint vector_stack_offset;
|
||||
uint a_stack_offset;
|
||||
uint b_stack_offset;
|
||||
uint param1_stack_offset;
|
||||
svm_unpack_node_uchar3(
|
||||
inputs_stack_offsets, &a_stack_offset, &b_stack_offset, ¶m1_stack_offset);
|
||||
svm_unpack_node_uchar2(outputs_stack_offsets, &value_stack_offset, &vector_stack_offset);
|
||||
|
||||
const Float3Type a = stack_load<Float3Type>(stack, a_stack_offset);
|
||||
const Float3Type b = stack_load<Float3Type>(stack, b_stack_offset);
|
||||
Float3Type c = make_zero<Float3Type>();
|
||||
const FloatType param1 = stack_load<FloatType>(stack, param1_stack_offset);
|
||||
|
||||
/* 3 Vector Operators */
|
||||
if (type == NODE_VECTOR_MATH_WRAP || type == NODE_VECTOR_MATH_FACEFORWARD ||
|
||||
type == NODE_VECTOR_MATH_MULTIPLY_ADD)
|
||||
{
|
||||
const uint4 extra_node = read_node(kg, &offset);
|
||||
c = stack_load<Float3Type>(stack, extra_node.x);
|
||||
}
|
||||
const Float3Type a = stack_load<Float3Type>(stack, node.a);
|
||||
const Float3Type b = stack_load<Float3Type>(stack, node.b);
|
||||
const Float3Type c = stack_load<Float3Type>(stack, node.c);
|
||||
const FloatType param1 = stack_load<FloatType>(stack, node.param1);
|
||||
|
||||
FloatType value = make_zero<FloatType>();
|
||||
Float3Type vector = make_zero<Float3Type>();
|
||||
svm_vector_math(&value, &vector, (NodeVectorMathType)type, a, b, c, param1);
|
||||
svm_vector_math(&value, &vector, node.math_type, a, b, c, param1);
|
||||
|
||||
if (stack_valid(value_stack_offset)) {
|
||||
stack_store(stack, value_stack_offset, value);
|
||||
if (stack_valid(node.value_offset)) {
|
||||
stack_store(stack, node.value_offset, value);
|
||||
}
|
||||
if (stack_valid(vector_stack_offset)) {
|
||||
stack_store(stack, vector_stack_offset, vector);
|
||||
if (stack_valid(node.vector_offset)) {
|
||||
stack_store(stack, node.vector_offset, vector);
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -5,121 +5,79 @@
|
|||
#pragma once
|
||||
|
||||
#include "kernel/svm/color_util.h"
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Node */
|
||||
|
||||
ccl_device_noinline int svm_node_mix(KernelGlobals kg,
|
||||
ccl_private float *stack,
|
||||
const uint fac_offset,
|
||||
const uint c1_offset,
|
||||
const uint c2_offset,
|
||||
int offset)
|
||||
ccl_device_noinline void svm_node_mix(ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeMix &ccl_restrict node)
|
||||
{
|
||||
/* read extra data */
|
||||
const uint4 node1 = read_node(kg, &offset);
|
||||
const float fac = stack_load(stack, node.fac);
|
||||
const float3 c1 = stack_load(stack, node.c1);
|
||||
const float3 c2 = stack_load(stack, node.c2);
|
||||
const float3 result = svm_mix_clamped_factor(node.mix_type, fac, c1, c2);
|
||||
|
||||
const float fac = stack_load_float(stack, fac_offset);
|
||||
const float3 c1 = stack_load_float3(stack, c1_offset);
|
||||
const float3 c2 = stack_load_float3(stack, c2_offset);
|
||||
const float3 result = svm_mix_clamped_factor((NodeMix)node1.y, fac, c1, c2);
|
||||
|
||||
stack_store_float3(stack, node1.z, result);
|
||||
return offset;
|
||||
stack_store_float3(stack, node.result_offset, result);
|
||||
}
|
||||
|
||||
ccl_device_noinline void svm_node_mix_color(ccl_private float *stack,
|
||||
const uint options,
|
||||
const uint input_offset,
|
||||
const uint result_offset)
|
||||
ccl_device_noinline void svm_node_mix_color(ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeMixColor &ccl_restrict node)
|
||||
{
|
||||
uint use_clamp;
|
||||
uint blend_type;
|
||||
uint use_clamp_result;
|
||||
uint fac_in_stack_offset;
|
||||
uint a_in_stack_offset;
|
||||
uint b_in_stack_offset;
|
||||
svm_unpack_node_uchar3(options, &use_clamp, &blend_type, &use_clamp_result);
|
||||
svm_unpack_node_uchar3(
|
||||
input_offset, &fac_in_stack_offset, &a_in_stack_offset, &b_in_stack_offset);
|
||||
|
||||
float t = stack_load_float(stack, fac_in_stack_offset);
|
||||
if (use_clamp > 0) {
|
||||
float t = stack_load(stack, node.fac);
|
||||
if (node.use_clamp > 0) {
|
||||
t = saturatef(t);
|
||||
}
|
||||
const float3 a = stack_load_float3(stack, a_in_stack_offset);
|
||||
const float3 b = stack_load_float3(stack, b_in_stack_offset);
|
||||
float3 result = svm_mix((NodeMix)blend_type, t, a, b);
|
||||
if (use_clamp_result) {
|
||||
const float3 a = stack_load(stack, node.a);
|
||||
const float3 b = stack_load(stack, node.b);
|
||||
float3 result = svm_mix(node.blend_type, t, a, b);
|
||||
if (node.use_clamp_result) {
|
||||
result = saturate(result);
|
||||
}
|
||||
stack_store_float3(stack, result_offset, result);
|
||||
stack_store_float3(stack, node.result_offset, result);
|
||||
}
|
||||
|
||||
ccl_device_noinline void svm_node_mix_float(ccl_private float *stack,
|
||||
const uint use_clamp,
|
||||
const uint input_offset,
|
||||
const uint result_offset)
|
||||
ccl_device_noinline void svm_node_mix_float(ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeMixFloat &ccl_restrict node)
|
||||
{
|
||||
uint fac_in_stack_offset;
|
||||
uint a_in_stack_offset;
|
||||
uint b_in_stack_offset;
|
||||
svm_unpack_node_uchar3(
|
||||
input_offset, &fac_in_stack_offset, &a_in_stack_offset, &b_in_stack_offset);
|
||||
|
||||
float t = stack_load_float(stack, fac_in_stack_offset);
|
||||
if (use_clamp > 0) {
|
||||
float t = stack_load(stack, node.fac);
|
||||
if (node.use_clamp > 0) {
|
||||
t = saturatef(t);
|
||||
}
|
||||
const float a = stack_load_float(stack, a_in_stack_offset);
|
||||
const float b = stack_load_float(stack, b_in_stack_offset);
|
||||
const float a = stack_load(stack, node.a);
|
||||
const float b = stack_load(stack, node.b);
|
||||
const float result = a * (1 - t) + b * t;
|
||||
|
||||
stack_store_float(stack, result_offset, result);
|
||||
stack_store_float(stack, node.result_offset, result);
|
||||
}
|
||||
|
||||
ccl_device_noinline void svm_node_mix_vector(ccl_private float *stack,
|
||||
const uint input_offset,
|
||||
const uint result_offset)
|
||||
ccl_device_noinline void svm_node_mix_vector(ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeMixVector &ccl_restrict node)
|
||||
{
|
||||
uint use_clamp;
|
||||
uint fac_in_stack_offset;
|
||||
uint a_in_stack_offset;
|
||||
uint b_in_stack_offset;
|
||||
svm_unpack_node_uchar4(
|
||||
input_offset, &use_clamp, &fac_in_stack_offset, &a_in_stack_offset, &b_in_stack_offset);
|
||||
|
||||
float t = stack_load_float(stack, fac_in_stack_offset);
|
||||
if (use_clamp > 0) {
|
||||
float t = stack_load(stack, node.fac);
|
||||
if (node.use_clamp > 0) {
|
||||
t = saturatef(t);
|
||||
}
|
||||
const float3 a = stack_load_float3(stack, a_in_stack_offset);
|
||||
const float3 b = stack_load_float3(stack, b_in_stack_offset);
|
||||
const float3 a = stack_load(stack, node.a);
|
||||
const float3 b = stack_load(stack, node.b);
|
||||
const float3 result = a * (one_float3() - t) + b * t;
|
||||
stack_store_float3(stack, result_offset, result);
|
||||
stack_store_float3(stack, node.result_offset, result);
|
||||
}
|
||||
|
||||
ccl_device_noinline void svm_node_mix_vector_non_uniform(ccl_private float *stack,
|
||||
const uint input_offset,
|
||||
const uint result_offset)
|
||||
ccl_device_noinline void svm_node_mix_vector_non_uniform(
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeMixVectorNonUniform &ccl_restrict node)
|
||||
{
|
||||
uint use_clamp;
|
||||
uint fac_in_stack_offset;
|
||||
uint a_in_stack_offset;
|
||||
uint b_in_stack_offset;
|
||||
svm_unpack_node_uchar4(
|
||||
input_offset, &use_clamp, &fac_in_stack_offset, &a_in_stack_offset, &b_in_stack_offset);
|
||||
|
||||
float3 t = stack_load_float3(stack, fac_in_stack_offset);
|
||||
if (use_clamp > 0) {
|
||||
float3 t = stack_load(stack, node.fac);
|
||||
if (node.use_clamp > 0) {
|
||||
t = saturate(t);
|
||||
}
|
||||
const float3 a = stack_load_float3(stack, a_in_stack_offset);
|
||||
const float3 b = stack_load_float3(stack, b_in_stack_offset);
|
||||
const float3 a = stack_load(stack, node.a);
|
||||
const float3 b = stack_load(stack, node.b);
|
||||
const float3 result = a * (one_float3() - t) + b * t;
|
||||
stack_store_float3(stack, result_offset, result);
|
||||
stack_store_float3(stack, node.result_offset, result);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
|||
1298
intern/cycles/kernel/svm/node_types.h
Normal file
1298
intern/cycles/kernel/svm/node_types.h
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -5,6 +5,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "kernel/svm/fractal_noise.h"
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
|
@ -242,52 +243,18 @@ ccl_device void noise_texture_4d(const float4 co,
|
|||
}
|
||||
}
|
||||
|
||||
ccl_device_noinline int svm_node_tex_noise(KernelGlobals kg,
|
||||
ccl_private float *stack,
|
||||
const uint offsets1,
|
||||
const uint offsets2,
|
||||
const uint offsets3,
|
||||
int node_offset)
|
||||
ccl_device_noinline void svm_node_tex_noise(ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeTexNoise &ccl_restrict node)
|
||||
{
|
||||
uint vector_stack_offset;
|
||||
uint w_stack_offset;
|
||||
uint scale_stack_offset;
|
||||
uint detail_stack_offset;
|
||||
uint roughness_stack_offset;
|
||||
uint lacunarity_stack_offset;
|
||||
uint offset_stack_offset;
|
||||
uint gain_stack_offset;
|
||||
uint distortion_stack_offset;
|
||||
uint value_stack_offset;
|
||||
uint color_stack_offset;
|
||||
|
||||
svm_unpack_node_uchar4(
|
||||
offsets1, &vector_stack_offset, &w_stack_offset, &scale_stack_offset, &detail_stack_offset);
|
||||
svm_unpack_node_uchar4(offsets2,
|
||||
&roughness_stack_offset,
|
||||
&lacunarity_stack_offset,
|
||||
&offset_stack_offset,
|
||||
&gain_stack_offset);
|
||||
svm_unpack_node_uchar3(
|
||||
offsets3, &distortion_stack_offset, &value_stack_offset, &color_stack_offset);
|
||||
|
||||
const uint4 defaults1 = read_node(kg, &node_offset);
|
||||
const uint4 defaults2 = read_node(kg, &node_offset);
|
||||
const uint4 properties = read_node(kg, &node_offset);
|
||||
|
||||
const uint dimensions = properties.x;
|
||||
const uint type = properties.y;
|
||||
const uint normalize = properties.z;
|
||||
|
||||
float3 vector = stack_load_float3(stack, vector_stack_offset);
|
||||
float w = stack_load_float_default(stack, w_stack_offset, defaults1.x);
|
||||
const float scale = stack_load_float_default(stack, scale_stack_offset, defaults1.y);
|
||||
float detail = stack_load_float_default(stack, detail_stack_offset, defaults1.z);
|
||||
float roughness = stack_load_float_default(stack, roughness_stack_offset, defaults1.w);
|
||||
const float lacunarity = stack_load_float_default(stack, lacunarity_stack_offset, defaults2.x);
|
||||
const float offset = stack_load_float_default(stack, offset_stack_offset, defaults2.y);
|
||||
const float gain = stack_load_float_default(stack, gain_stack_offset, defaults2.z);
|
||||
const float distortion = stack_load_float_default(stack, distortion_stack_offset, defaults2.w);
|
||||
float3 vector = stack_load_float3(stack, node.vector);
|
||||
float w = stack_load(stack, node.w);
|
||||
const float scale = stack_load(stack, node.scale);
|
||||
float detail = stack_load(stack, node.detail);
|
||||
float roughness = stack_load(stack, node.roughness);
|
||||
const float lacunarity = stack_load(stack, node.lacunarity);
|
||||
const float offset = stack_load(stack, node.offset);
|
||||
const float gain = stack_load(stack, node.gain);
|
||||
const float distortion = stack_load(stack, node.distortion);
|
||||
|
||||
detail = clamp(detail, 0.0f, 15.0f);
|
||||
roughness = fmaxf(roughness, 0.0f);
|
||||
|
|
@ -297,7 +264,7 @@ ccl_device_noinline int svm_node_tex_noise(KernelGlobals kg,
|
|||
|
||||
float value;
|
||||
float3 color;
|
||||
switch (dimensions) {
|
||||
switch (node.dimensions) {
|
||||
case 1:
|
||||
noise_texture_1d(w,
|
||||
detail,
|
||||
|
|
@ -306,9 +273,9 @@ ccl_device_noinline int svm_node_tex_noise(KernelGlobals kg,
|
|||
offset,
|
||||
gain,
|
||||
distortion,
|
||||
type,
|
||||
normalize,
|
||||
stack_valid(color_stack_offset),
|
||||
node.noise_type,
|
||||
node.normalize,
|
||||
stack_valid(node.color_offset),
|
||||
&value,
|
||||
&color);
|
||||
break;
|
||||
|
|
@ -320,9 +287,9 @@ ccl_device_noinline int svm_node_tex_noise(KernelGlobals kg,
|
|||
offset,
|
||||
gain,
|
||||
distortion,
|
||||
type,
|
||||
normalize,
|
||||
stack_valid(color_stack_offset),
|
||||
node.noise_type,
|
||||
node.normalize,
|
||||
stack_valid(node.color_offset),
|
||||
&value,
|
||||
&color);
|
||||
break;
|
||||
|
|
@ -334,9 +301,9 @@ ccl_device_noinline int svm_node_tex_noise(KernelGlobals kg,
|
|||
offset,
|
||||
gain,
|
||||
distortion,
|
||||
type,
|
||||
normalize,
|
||||
stack_valid(color_stack_offset),
|
||||
node.noise_type,
|
||||
node.normalize,
|
||||
stack_valid(node.color_offset),
|
||||
&value,
|
||||
&color);
|
||||
break;
|
||||
|
|
@ -348,9 +315,9 @@ ccl_device_noinline int svm_node_tex_noise(KernelGlobals kg,
|
|||
offset,
|
||||
gain,
|
||||
distortion,
|
||||
type,
|
||||
normalize,
|
||||
stack_valid(color_stack_offset),
|
||||
node.noise_type,
|
||||
node.normalize,
|
||||
stack_valid(node.color_offset),
|
||||
&value,
|
||||
&color);
|
||||
break;
|
||||
|
|
@ -358,13 +325,12 @@ ccl_device_noinline int svm_node_tex_noise(KernelGlobals kg,
|
|||
kernel_assert(0);
|
||||
}
|
||||
|
||||
if (stack_valid(value_stack_offset)) {
|
||||
stack_store_float(stack, value_stack_offset, value);
|
||||
if (stack_valid(node.value_offset)) {
|
||||
stack_store_float(stack, node.value_offset, value);
|
||||
}
|
||||
if (stack_valid(color_stack_offset)) {
|
||||
stack_store_float3(stack, color_stack_offset, color);
|
||||
if (stack_valid(node.color_offset)) {
|
||||
stack_store_float3(stack, node.color_offset, color);
|
||||
}
|
||||
return node_offset;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -4,35 +4,26 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
ccl_device_noinline int svm_node_normal(KernelGlobals kg,
|
||||
ccl_private float *stack,
|
||||
const uint in_normal_offset,
|
||||
const uint out_normal_offset,
|
||||
const uint out_dot_offset,
|
||||
int offset)
|
||||
ccl_device_noinline void svm_node_normal(ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeNormal &ccl_restrict node)
|
||||
{
|
||||
/* read extra data */
|
||||
const uint4 node1 = read_node(kg, &offset);
|
||||
const float3 normal = stack_load_float3(stack, in_normal_offset);
|
||||
const float3 normal = stack_load(stack, node.in_normal);
|
||||
|
||||
float3 direction;
|
||||
direction.x = __int_as_float(node1.x);
|
||||
direction.y = __int_as_float(node1.y);
|
||||
direction.z = __int_as_float(node1.z);
|
||||
float3 direction = make_float3(node.direction_x, node.direction_y, node.direction_z);
|
||||
direction = normalize(direction);
|
||||
|
||||
if (stack_valid(out_normal_offset)) {
|
||||
stack_store_float3(stack, out_normal_offset, direction);
|
||||
if (stack_valid(node.out_normal_offset)) {
|
||||
stack_store_float3(stack, node.out_normal_offset, direction);
|
||||
}
|
||||
|
||||
if (stack_valid(out_dot_offset)) {
|
||||
stack_store_float(stack, out_dot_offset, dot(direction, normalize(normal)));
|
||||
if (stack_valid(node.out_dot_offset)) {
|
||||
stack_store_float(stack, node.out_dot_offset, dot(direction, normalize(normal)));
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Define macro flags for code adaption. */
|
||||
|
|
@ -15,67 +18,48 @@ CCL_NAMESPACE_BEGIN
|
|||
/* Undefine macro flags used for code adaption. */
|
||||
#undef ADAPT_TO_SVM
|
||||
|
||||
struct RoundedPolygonStackOffsets {
|
||||
uint vector;
|
||||
uint r_gon_sides;
|
||||
uint r_gon_roundness;
|
||||
uint segment_coordinates;
|
||||
uint segment_id;
|
||||
uint max_unit_parameter;
|
||||
uint x_axis_A_angle_bisector;
|
||||
};
|
||||
|
||||
template<uint node_feature_mask>
|
||||
ccl_device_noinline int svm_node_radial_tiling(ccl_private float *stack, uint4 node, int offset)
|
||||
ccl_device_noinline void svm_node_radial_tiling(
|
||||
ccl_private float *ccl_restrict stack, const ccl_global SVMNodeRadialTiling &ccl_restrict node)
|
||||
{
|
||||
RoundedPolygonStackOffsets so;
|
||||
const bool calculate_r_gon_parameter_field = stack_valid(node.segment_coordinates_offset);
|
||||
const bool calculate_segment_id = stack_valid(node.segment_id_offset);
|
||||
const bool calculate_max_unit_parameter = stack_valid(node.max_unit_parameter_offset);
|
||||
const bool calculate_x_axis_A_angle_bisector = stack_valid(node.x_axis_A_angle_bisector_offset);
|
||||
|
||||
uint normalize_r_gon_parameter = node.y;
|
||||
|
||||
svm_unpack_node_uchar4(
|
||||
node.z, &(so.vector), &(so.r_gon_sides), &(so.r_gon_roundness), &(so.segment_coordinates));
|
||||
svm_unpack_node_uchar3(
|
||||
node.w, &(so.segment_id), &(so.max_unit_parameter), &(so.x_axis_A_angle_bisector));
|
||||
|
||||
bool calculate_r_gon_parameter_field = stack_valid(so.segment_coordinates);
|
||||
bool calculate_segment_id = stack_valid(so.segment_id);
|
||||
bool calculate_max_unit_parameter = stack_valid(so.max_unit_parameter);
|
||||
bool calculate_x_axis_A_angle_bisector = stack_valid(so.x_axis_A_angle_bisector);
|
||||
|
||||
float3 coord = stack_load_float3(stack, so.vector);
|
||||
float r_gon_sides = stack_load_float(stack, so.r_gon_sides);
|
||||
float r_gon_roundness = stack_load_float(stack, so.r_gon_roundness);
|
||||
const float3 coord = stack_load(stack, node.vector);
|
||||
const float r_gon_sides = stack_load(stack, node.r_gon_sides);
|
||||
const float r_gon_roundness = stack_load(stack, node.r_gon_roundness);
|
||||
|
||||
if (calculate_r_gon_parameter_field || calculate_max_unit_parameter ||
|
||||
calculate_x_axis_A_angle_bisector)
|
||||
{
|
||||
float4 out_variables = calculate_out_variables(calculate_r_gon_parameter_field,
|
||||
calculate_max_unit_parameter,
|
||||
normalize_r_gon_parameter,
|
||||
node.normalize_r_gon_parameter,
|
||||
fmaxf(r_gon_sides, 2.0f),
|
||||
clamp(r_gon_roundness, 0.0f, 1.0f),
|
||||
make_float2(coord.x, coord.y));
|
||||
|
||||
if (calculate_r_gon_parameter_field) {
|
||||
stack_store_float3(
|
||||
stack, so.segment_coordinates, make_float3(out_variables.y, out_variables.x, 0.0f));
|
||||
stack_store_float3(stack,
|
||||
node.segment_coordinates_offset,
|
||||
make_float3(out_variables.y, out_variables.x, 0.0f));
|
||||
}
|
||||
if (calculate_max_unit_parameter) {
|
||||
stack_store_float(stack, so.max_unit_parameter, out_variables.z);
|
||||
stack_store_float(stack, node.max_unit_parameter_offset, out_variables.z);
|
||||
}
|
||||
if (calculate_x_axis_A_angle_bisector) {
|
||||
stack_store_float(stack, so.x_axis_A_angle_bisector, out_variables.w);
|
||||
stack_store_float(stack, node.x_axis_A_angle_bisector_offset, out_variables.w);
|
||||
}
|
||||
}
|
||||
|
||||
if (calculate_segment_id) {
|
||||
stack_store_float(
|
||||
stack,
|
||||
so.segment_id,
|
||||
node.segment_id_offset,
|
||||
calculate_out_segment_id(fmaxf(r_gon_sides, 2.0f), make_float2(coord.x, coord.y)));
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
|
@ -12,8 +13,7 @@ CCL_NAMESPACE_BEGIN
|
|||
|
||||
ccl_device_inline float fetch_float(KernelGlobals kg, const int offset)
|
||||
{
|
||||
const uint4 node = kernel_data_fetch(svm_nodes, offset);
|
||||
return __uint_as_float(node.x);
|
||||
return __uint_as_float(kernel_data_fetch(svm_nodes, offset));
|
||||
}
|
||||
|
||||
ccl_device_inline float float_ramp_lookup(KernelGlobals kg,
|
||||
|
|
@ -65,13 +65,13 @@ ccl_device_inline float4 rgb_ramp_lookup(KernelGlobals kg,
|
|||
float4 t0;
|
||||
float4 dy;
|
||||
if (f < 0.0f) {
|
||||
t0 = fetch_node_float(kg, offset);
|
||||
dy = t0 - fetch_node_float(kg, offset + 1);
|
||||
t0 = svm_node_get_data_float4(kg, offset);
|
||||
dy = t0 - svm_node_get_data_float4(kg, offset + 4);
|
||||
f = -f;
|
||||
}
|
||||
else {
|
||||
t0 = fetch_node_float(kg, offset + table_size - 1);
|
||||
dy = t0 - fetch_node_float(kg, offset + table_size - 2);
|
||||
t0 = svm_node_get_data_float4(kg, offset + (table_size - 1) * 4);
|
||||
dy = t0 - svm_node_get_data_float4(kg, offset + (table_size - 2) * 4);
|
||||
f = f - 1.0f;
|
||||
}
|
||||
return t0 + dy * f * (table_size - 1);
|
||||
|
|
@ -83,10 +83,10 @@ ccl_device_inline float4 rgb_ramp_lookup(KernelGlobals kg,
|
|||
const int i = clamp(float_to_int(f), 0, table_size - 1);
|
||||
const float t = f - (float)i;
|
||||
|
||||
float4 a = fetch_node_float(kg, offset + i);
|
||||
float4 a = svm_node_get_data_float4(kg, offset + i * 4);
|
||||
|
||||
if (interpolate && t > 0.0f) {
|
||||
a = (1.0f - t) * a + t * fetch_node_float(kg, offset + i + 1);
|
||||
a = (1.0f - t) * a + t * svm_node_get_data_float4(kg, offset + (i + 1) * 4);
|
||||
}
|
||||
|
||||
return a;
|
||||
|
|
@ -94,91 +94,62 @@ ccl_device_inline float4 rgb_ramp_lookup(KernelGlobals kg,
|
|||
|
||||
ccl_device_noinline int svm_node_rgb_ramp(KernelGlobals kg,
|
||||
ccl_private float *stack,
|
||||
const uint4 node,
|
||||
const ccl_global SVMNodeRGBRamp &node,
|
||||
int offset)
|
||||
{
|
||||
uint fac_offset;
|
||||
uint color_offset;
|
||||
uint alpha_offset;
|
||||
const uint interpolate = node.z;
|
||||
const float fac = stack_load(stack, node.fac);
|
||||
const float4 color = rgb_ramp_lookup(kg, offset, fac, node.interpolate, false, node.table_size);
|
||||
|
||||
svm_unpack_node_uchar3(node.y, &fac_offset, &color_offset, &alpha_offset);
|
||||
|
||||
const uint table_size = read_node(kg, &offset).x;
|
||||
|
||||
const float fac = stack_load_float(stack, fac_offset);
|
||||
const float4 color = rgb_ramp_lookup(kg, offset, fac, interpolate, false, table_size);
|
||||
|
||||
if (stack_valid(color_offset)) {
|
||||
stack_store_float3(stack, color_offset, make_float3(color));
|
||||
if (stack_valid(node.color_offset)) {
|
||||
stack_store_float3(stack, node.color_offset, make_float3(color));
|
||||
}
|
||||
if (stack_valid(alpha_offset)) {
|
||||
stack_store_float(stack, alpha_offset, color.w);
|
||||
if (stack_valid(node.alpha_offset)) {
|
||||
stack_store_float(stack, node.alpha_offset, color.w);
|
||||
}
|
||||
|
||||
offset += table_size;
|
||||
offset += node.table_size * 4;
|
||||
return offset;
|
||||
}
|
||||
|
||||
ccl_device_noinline int svm_node_curves(KernelGlobals kg,
|
||||
ccl_private float *stack,
|
||||
const uint4 node,
|
||||
const ccl_global SVMNodeCurves &node,
|
||||
int offset)
|
||||
{
|
||||
uint fac_offset;
|
||||
uint color_offset;
|
||||
uint out_offset;
|
||||
uint extrapolate;
|
||||
svm_unpack_node_uchar4(node.y, &fac_offset, &color_offset, &out_offset, &extrapolate);
|
||||
const float fac = stack_load(stack, node.fac);
|
||||
float3 color = stack_load(stack, node.color);
|
||||
|
||||
const uint table_size = read_node(kg, &offset).x;
|
||||
const float range_x = node.max_x - node.min_x;
|
||||
const float3 relpos = (color - make_float3(node.min_x, node.min_x, node.min_x)) / range_x;
|
||||
|
||||
const float fac = stack_load_float(stack, fac_offset);
|
||||
float3 color = stack_load_float3(stack, color_offset);
|
||||
|
||||
const float min_x = __int_as_float(node.z);
|
||||
const float max_x = __int_as_float(node.w);
|
||||
const float range_x = max_x - min_x;
|
||||
const float3 relpos = (color - make_float3(min_x, min_x, min_x)) / range_x;
|
||||
|
||||
const float r = rgb_ramp_lookup(kg, offset, relpos.x, true, extrapolate, table_size).x;
|
||||
const float g = rgb_ramp_lookup(kg, offset, relpos.y, true, extrapolate, table_size).y;
|
||||
const float b = rgb_ramp_lookup(kg, offset, relpos.z, true, extrapolate, table_size).z;
|
||||
const float r = rgb_ramp_lookup(kg, offset, relpos.x, true, node.extrapolate, node.table_size).x;
|
||||
const float g = rgb_ramp_lookup(kg, offset, relpos.y, true, node.extrapolate, node.table_size).y;
|
||||
const float b = rgb_ramp_lookup(kg, offset, relpos.z, true, node.extrapolate, node.table_size).z;
|
||||
|
||||
color = (1.0f - fac) * color + fac * make_float3(r, g, b);
|
||||
stack_store_float3(stack, out_offset, color);
|
||||
stack_store_float3(stack, node.out_offset, color);
|
||||
|
||||
offset += table_size;
|
||||
offset += node.table_size * 4;
|
||||
return offset;
|
||||
}
|
||||
|
||||
ccl_device_noinline int svm_node_curve(KernelGlobals kg,
|
||||
ccl_private float *stack,
|
||||
const uint4 node,
|
||||
const ccl_global SVMNodeFloatCurve &node,
|
||||
int offset)
|
||||
{
|
||||
uint fac_offset;
|
||||
uint value_in_offset;
|
||||
uint out_offset;
|
||||
uint extrapolate;
|
||||
svm_unpack_node_uchar4(node.y, &fac_offset, &value_in_offset, &out_offset, &extrapolate);
|
||||
const float fac = stack_load(stack, node.fac);
|
||||
float in = stack_load(stack, node.value_in);
|
||||
|
||||
const uint table_size = read_node(kg, &offset).x;
|
||||
const float range = node.max_x - node.min_x;
|
||||
const float relpos = (in - node.min_x) / range;
|
||||
|
||||
const float fac = stack_load_float(stack, fac_offset);
|
||||
float in = stack_load_float(stack, value_in_offset);
|
||||
|
||||
const float min = __int_as_float(node.z);
|
||||
const float max = __int_as_float(node.w);
|
||||
const float range = max - min;
|
||||
const float relpos = (in - min) / range;
|
||||
|
||||
const float v = float_ramp_lookup(kg, offset, relpos, true, extrapolate, table_size);
|
||||
const float v = float_ramp_lookup(kg, offset, relpos, true, node.extrapolate, node.table_size);
|
||||
|
||||
in = (1.0f - fac) * in + fac * v;
|
||||
stack_store_float(stack, out_offset, in);
|
||||
stack_store_float(stack, node.out_offset, in);
|
||||
|
||||
offset += table_size;
|
||||
offset += node.table_size;
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "kernel/sample/mapping.h"
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
#include "kernel/geom/shader_data.h"
|
||||
|
|
@ -110,29 +111,14 @@ ccl_device_inline
|
|||
# else
|
||||
ccl_device_noinline
|
||||
# endif
|
||||
int
|
||||
void
|
||||
svm_node_raycast(KernelGlobals kg,
|
||||
ConstIntegratorGenericState state,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint4 node,
|
||||
int offset)
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeRaycast &ccl_restrict node)
|
||||
{
|
||||
uint position_offset;
|
||||
uint direction_offset;
|
||||
uint distance_offset;
|
||||
uint is_hit_offset;
|
||||
svm_unpack_node_uchar4(
|
||||
node.y, &position_offset, &direction_offset, &distance_offset, &is_hit_offset);
|
||||
|
||||
uint is_self_hit_offset;
|
||||
uint hit_distance_offset;
|
||||
uint hit_position_offset;
|
||||
uint hit_normal_offset;
|
||||
svm_unpack_node_uchar4(
|
||||
node.z, &is_self_hit_offset, &hit_distance_offset, &hit_position_offset, &hit_normal_offset);
|
||||
|
||||
float distance = stack_load_float_default(stack, distance_offset, 0.0f);
|
||||
float distance = stack_load(stack, node.distance);
|
||||
|
||||
float is_hit = 0.0f;
|
||||
float is_self_hit = 0.0f;
|
||||
|
|
@ -140,17 +126,12 @@ ccl_device_noinline
|
|||
float3 hit_position = make_float3(0.0f);
|
||||
float3 hit_normal = make_float3(0.0f);
|
||||
|
||||
uint4 data_node = read_node(kg, &offset);
|
||||
|
||||
IF_KERNEL_NODES_FEATURE(RAYTRACE)
|
||||
{
|
||||
const uint only_local = node.w;
|
||||
const float bump_filter_width = __uint_as_float(data_node.x);
|
||||
|
||||
float3 position = stack_load_float3(stack, position_offset);
|
||||
float3 direction = stack_load_float3(stack, direction_offset);
|
||||
float3 position = stack_load(stack, node.position);
|
||||
float3 direction = stack_load(stack, node.direction);
|
||||
RaycastResult result = svm_raycast(
|
||||
kg, state, sd, position, direction, distance, only_local, bump_filter_width);
|
||||
kg, state, sd, position, direction, distance, node.only_local, node.bump_filter_width);
|
||||
|
||||
if (result.distance >= 0.0f) {
|
||||
is_hit = 1.0f;
|
||||
|
|
@ -161,23 +142,21 @@ ccl_device_noinline
|
|||
}
|
||||
}
|
||||
|
||||
if (stack_valid(is_hit_offset)) {
|
||||
stack_store_float(stack, is_hit_offset, is_hit);
|
||||
if (stack_valid(node.is_hit_offset)) {
|
||||
stack_store_float(stack, node.is_hit_offset, is_hit);
|
||||
}
|
||||
if (stack_valid(is_self_hit_offset)) {
|
||||
stack_store_float(stack, is_self_hit_offset, is_self_hit);
|
||||
if (stack_valid(node.is_self_hit_offset)) {
|
||||
stack_store_float(stack, node.is_self_hit_offset, is_self_hit);
|
||||
}
|
||||
if (stack_valid(hit_distance_offset)) {
|
||||
stack_store_float(stack, hit_distance_offset, hit_distance);
|
||||
if (stack_valid(node.hit_distance_offset)) {
|
||||
stack_store_float(stack, node.hit_distance_offset, hit_distance);
|
||||
}
|
||||
if (stack_valid(hit_position_offset)) {
|
||||
stack_store_float3(stack, hit_position_offset, hit_position);
|
||||
if (stack_valid(node.hit_position_offset)) {
|
||||
stack_store_float3(stack, node.hit_position_offset, hit_position);
|
||||
}
|
||||
if (stack_valid(hit_normal_offset)) {
|
||||
stack_store_float3(stack, hit_normal_offset, hit_normal);
|
||||
if (stack_valid(node.hit_normal_offset)) {
|
||||
stack_store_float3(stack, node.hit_normal_offset, hit_normal);
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
#endif /* __SHADER_RAYTRACE__ */
|
||||
|
|
|
|||
|
|
@ -5,57 +5,43 @@
|
|||
#pragma once
|
||||
|
||||
#include "kernel/svm/color_util.h"
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
ccl_device_noinline void svm_node_combine_color(ccl_private float *stack,
|
||||
const uint color_type,
|
||||
const uint inputs_stack_offsets,
|
||||
const uint result_stack_offset)
|
||||
ccl_device_noinline void svm_node_combine_color(
|
||||
ccl_private float *ccl_restrict stack, const ccl_global SVMNodeCombineColor &ccl_restrict node)
|
||||
{
|
||||
uint red_stack_offset;
|
||||
uint green_stack_offset;
|
||||
uint blue_stack_offset;
|
||||
svm_unpack_node_uchar3(
|
||||
inputs_stack_offsets, &red_stack_offset, &green_stack_offset, &blue_stack_offset);
|
||||
|
||||
const float r = stack_load_float(stack, red_stack_offset);
|
||||
const float g = stack_load_float(stack, green_stack_offset);
|
||||
const float b = stack_load_float(stack, blue_stack_offset);
|
||||
const float r = stack_load(stack, node.red);
|
||||
const float g = stack_load(stack, node.green);
|
||||
const float b = stack_load(stack, node.blue);
|
||||
|
||||
/* Combine, and convert back to RGB */
|
||||
const float3 color = svm_combine_color((NodeCombSepColorType)color_type, make_float3(r, g, b));
|
||||
const float3 color = svm_combine_color(node.color_type, make_float3(r, g, b));
|
||||
|
||||
if (stack_valid(result_stack_offset)) {
|
||||
stack_store_float3(stack, result_stack_offset, color);
|
||||
if (stack_valid(node.color_offset)) {
|
||||
stack_store_float3(stack, node.color_offset, color);
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device_noinline void svm_node_separate_color(ccl_private float *stack,
|
||||
const uint color_type,
|
||||
const uint input_stack_offset,
|
||||
const uint results_stack_offsets)
|
||||
ccl_device_noinline void svm_node_separate_color(
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeSeparateColor &ccl_restrict node)
|
||||
{
|
||||
float3 color = stack_load_float3(stack, input_stack_offset);
|
||||
float3 color = stack_load(stack, node.color);
|
||||
|
||||
/* Convert color space */
|
||||
color = svm_separate_color((NodeCombSepColorType)color_type, color);
|
||||
color = svm_separate_color(node.color_type, color);
|
||||
|
||||
uint red_stack_offset;
|
||||
uint green_stack_offset;
|
||||
uint blue_stack_offset;
|
||||
svm_unpack_node_uchar3(
|
||||
results_stack_offsets, &red_stack_offset, &green_stack_offset, &blue_stack_offset);
|
||||
|
||||
if (stack_valid(red_stack_offset)) {
|
||||
stack_store_float(stack, red_stack_offset, color.x);
|
||||
if (stack_valid(node.red_offset)) {
|
||||
stack_store_float(stack, node.red_offset, color.x);
|
||||
}
|
||||
if (stack_valid(green_stack_offset)) {
|
||||
stack_store_float(stack, green_stack_offset, color.y);
|
||||
if (stack_valid(node.green_offset)) {
|
||||
stack_store_float(stack, node.green_offset, color.y);
|
||||
}
|
||||
if (stack_valid(blue_stack_offset)) {
|
||||
stack_store_float(stack, blue_stack_offset, color.z);
|
||||
if (stack_valid(node.blue_offset)) {
|
||||
stack_store_float(stack, node.blue_offset, color.z);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
|
@ -11,55 +12,51 @@ CCL_NAMESPACE_BEGIN
|
|||
/* Vector combine / separate, used for the RGB and XYZ nodes */
|
||||
|
||||
template<typename Float3Type>
|
||||
ccl_device void svm_node_combine_vector(ccl_private float *stack,
|
||||
const uint in_offset,
|
||||
const uint vector_index,
|
||||
const uint out_offset)
|
||||
ccl_device void svm_node_combine_vector(ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeCombineVector &ccl_restrict node)
|
||||
{
|
||||
using FloatType = dual_scalar_t<Float3Type>;
|
||||
const FloatType value = stack_load<FloatType>(stack, in_offset);
|
||||
const FloatType value = stack_load<FloatType>(stack, node.in);
|
||||
|
||||
if (stack_valid(out_offset)) {
|
||||
if (stack_valid(node.out_offset)) {
|
||||
if constexpr (is_dual_v<Float3Type>) {
|
||||
stack_store_float(stack, out_offset + vector_index, value.val);
|
||||
stack_store_float(stack, out_offset + vector_index + 3, value.dx);
|
||||
stack_store_float(stack, out_offset + vector_index + 6, value.dy);
|
||||
stack_store_float(stack, node.out_offset + node.vector_index, value.val);
|
||||
stack_store_float(stack, node.out_offset + node.vector_index + 3, value.dx);
|
||||
stack_store_float(stack, node.out_offset + node.vector_index + 6, value.dy);
|
||||
}
|
||||
else {
|
||||
stack_store_float(stack, out_offset + vector_index, value);
|
||||
stack_store_float(stack, node.out_offset + node.vector_index, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Float3Type>
|
||||
ccl_device void svm_node_separate_vector(ccl_private float *stack,
|
||||
const uint ivector_offset,
|
||||
const uint vector_index,
|
||||
const uint out_offset)
|
||||
ccl_device void svm_node_separate_vector(ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeSeparateVector &ccl_restrict node)
|
||||
{
|
||||
const Float3Type vector = stack_load<Float3Type>(stack, ivector_offset);
|
||||
const Float3Type vector = stack_load<Float3Type>(stack, node.vector);
|
||||
|
||||
if (stack_valid(out_offset)) {
|
||||
if (stack_valid(node.out_offset)) {
|
||||
if constexpr (is_dual_v<Float3Type>) {
|
||||
if (vector_index == 0) {
|
||||
stack_store(stack, out_offset, vector.x());
|
||||
if (node.vector_index == 0) {
|
||||
stack_store(stack, node.out_offset, vector.x());
|
||||
}
|
||||
else if (vector_index == 1) {
|
||||
stack_store(stack, out_offset, vector.y());
|
||||
else if (node.vector_index == 1) {
|
||||
stack_store(stack, node.out_offset, vector.y());
|
||||
}
|
||||
else {
|
||||
stack_store(stack, out_offset, vector.z());
|
||||
stack_store(stack, node.out_offset, vector.z());
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (vector_index == 0) {
|
||||
stack_store(stack, out_offset, vector.x);
|
||||
if (node.vector_index == 0) {
|
||||
stack_store(stack, node.out_offset, vector.x);
|
||||
}
|
||||
else if (vector_index == 1) {
|
||||
stack_store(stack, out_offset, vector.y);
|
||||
else if (node.vector_index == 1) {
|
||||
stack_store(stack, node.out_offset, vector.y);
|
||||
}
|
||||
else {
|
||||
stack_store(stack, out_offset, vector.z);
|
||||
stack_store(stack, node.out_offset, vector.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "kernel/image.h"
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
|
|
@ -184,87 +185,40 @@ ccl_device float3 sky_radiance_nishita(KernelGlobals kg,
|
|||
ccl_device_noinline int svm_node_tex_sky(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
const uint32_t path_flag,
|
||||
ccl_private float *stack,
|
||||
const uint4 node,
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeTexSky &ccl_restrict node,
|
||||
int offset)
|
||||
{
|
||||
/* Load data */
|
||||
const uint dir_offset = node.y;
|
||||
const uint out_offset = node.z;
|
||||
const NodeSkyType sky_type = NodeSkyType(node.w);
|
||||
const NodeSkyType sky_type = node.sky_type;
|
||||
|
||||
const float3 dir = stack_load_float3(stack, dir_offset);
|
||||
const float3 dir = stack_load_float3(stack, node.dir_offset);
|
||||
float3 rgb;
|
||||
|
||||
/* Preetham and Hosek share the same data */
|
||||
if (sky_type == NODE_SKY_PREETHAM || sky_type == NODE_SKY_HOSEK) {
|
||||
/* Define variables */
|
||||
float sunphi;
|
||||
float suntheta;
|
||||
float radiance_x;
|
||||
float radiance_y;
|
||||
float radiance_z;
|
||||
float config_x[9];
|
||||
float config_y[9];
|
||||
float config_z[9];
|
||||
const ccl_global SVMNodeTexSkyPreethamData &preetham =
|
||||
*reinterpret_cast<const ccl_global SVMNodeTexSkyPreethamData *>(
|
||||
&kernel_data_fetch(svm_nodes, offset));
|
||||
offset += sizeof(SVMNodeTexSkyPreethamData) / sizeof(uint);
|
||||
|
||||
float4 data = read_node_float(kg, &offset);
|
||||
sunphi = data.x;
|
||||
suntheta = data.y;
|
||||
radiance_x = data.z;
|
||||
radiance_y = data.w;
|
||||
|
||||
data = read_node_float(kg, &offset);
|
||||
radiance_z = data.x;
|
||||
config_x[0] = data.y;
|
||||
config_x[1] = data.z;
|
||||
config_x[2] = data.w;
|
||||
|
||||
data = read_node_float(kg, &offset);
|
||||
config_x[3] = data.x;
|
||||
config_x[4] = data.y;
|
||||
config_x[5] = data.z;
|
||||
config_x[6] = data.w;
|
||||
|
||||
data = read_node_float(kg, &offset);
|
||||
config_x[7] = data.x;
|
||||
config_x[8] = data.y;
|
||||
config_y[0] = data.z;
|
||||
config_y[1] = data.w;
|
||||
|
||||
data = read_node_float(kg, &offset);
|
||||
config_y[2] = data.x;
|
||||
config_y[3] = data.y;
|
||||
config_y[4] = data.z;
|
||||
config_y[5] = data.w;
|
||||
|
||||
data = read_node_float(kg, &offset);
|
||||
config_y[6] = data.x;
|
||||
config_y[7] = data.y;
|
||||
config_y[8] = data.z;
|
||||
config_z[0] = data.w;
|
||||
|
||||
data = read_node_float(kg, &offset);
|
||||
config_z[1] = data.x;
|
||||
config_z[2] = data.y;
|
||||
config_z[3] = data.z;
|
||||
config_z[4] = data.w;
|
||||
|
||||
data = read_node_float(kg, &offset);
|
||||
config_z[5] = data.x;
|
||||
config_z[6] = data.y;
|
||||
config_z[7] = data.z;
|
||||
config_z[8] = data.w;
|
||||
/* Copy config arrays to private memory for GPU compatibility. */
|
||||
float config_x[9], config_y[9], config_z[9];
|
||||
for (int i = 0; i < 9; i++) {
|
||||
config_x[i] = preetham.config_x[i];
|
||||
config_y[i] = preetham.config_y[i];
|
||||
config_z[i] = preetham.config_z[i];
|
||||
}
|
||||
|
||||
/* Compute Sky */
|
||||
if (sky_type == NODE_SKY_PREETHAM) {
|
||||
rgb = sky_radiance_preetham(kg,
|
||||
dir,
|
||||
sunphi,
|
||||
suntheta,
|
||||
radiance_x,
|
||||
radiance_y,
|
||||
radiance_z,
|
||||
preetham.phi,
|
||||
preetham.theta,
|
||||
preetham.radiance_x,
|
||||
preetham.radiance_y,
|
||||
preetham.radiance_z,
|
||||
config_x,
|
||||
config_y,
|
||||
config_z);
|
||||
|
|
@ -272,11 +226,11 @@ ccl_device_noinline int svm_node_tex_sky(KernelGlobals kg,
|
|||
else {
|
||||
rgb = sky_radiance_hosek(kg,
|
||||
dir,
|
||||
sunphi,
|
||||
suntheta,
|
||||
radiance_x,
|
||||
radiance_y,
|
||||
radiance_z,
|
||||
preetham.phi,
|
||||
preetham.theta,
|
||||
preetham.radiance_x,
|
||||
preetham.radiance_y,
|
||||
preetham.radiance_z,
|
||||
config_x,
|
||||
config_y,
|
||||
config_z);
|
||||
|
|
@ -284,30 +238,27 @@ ccl_device_noinline int svm_node_tex_sky(KernelGlobals kg,
|
|||
}
|
||||
/* Nishita */
|
||||
else {
|
||||
float4 data = read_node_float(kg, &offset);
|
||||
const float3 pixel_bottom = make_float3(data.x, data.y, data.z);
|
||||
float3 pixel_top;
|
||||
pixel_top.x = data.w;
|
||||
const ccl_global SVMNodeTexSkyNishitaData &nishita =
|
||||
*reinterpret_cast<const ccl_global SVMNodeTexSkyNishitaData *>(
|
||||
&kernel_data_fetch(svm_nodes, offset));
|
||||
offset += sizeof(SVMNodeTexSkyNishitaData) / sizeof(uint);
|
||||
|
||||
float sky_data[5];
|
||||
data = read_node_float(kg, &offset);
|
||||
pixel_top.y = data.x;
|
||||
pixel_top.z = data.y;
|
||||
sky_data[0] = data.z;
|
||||
sky_data[1] = data.w;
|
||||
|
||||
data = read_node_float(kg, &offset);
|
||||
sky_data[2] = data.x;
|
||||
sky_data[3] = data.y;
|
||||
sky_data[4] = data.z;
|
||||
const uint texture_id = __float_as_uint(data.w);
|
||||
const float3 pixel_bottom = make_float3(
|
||||
nishita.pixel_bottom_x, nishita.pixel_bottom_y, nishita.pixel_bottom_z);
|
||||
const float3 pixel_top = make_float3(
|
||||
nishita.pixel_top_x, nishita.pixel_top_y, nishita.pixel_top_z);
|
||||
const float sky_data[5] = {nishita.sun_elevation,
|
||||
nishita.sun_rotation,
|
||||
nishita.angular_diameter,
|
||||
nishita.sun_intensity,
|
||||
nishita.earth_intersection_angle};
|
||||
|
||||
/* Compute Sky */
|
||||
rgb = sky_radiance_nishita(
|
||||
kg, sd, dir, path_flag, pixel_bottom, pixel_top, sky_data, texture_id);
|
||||
kg, sd, dir, path_flag, pixel_bottom, pixel_top, sky_data, nishita.texture_id);
|
||||
}
|
||||
|
||||
stack_store_float3(stack, out_offset, rgb);
|
||||
stack_store_float3(stack, node.out_offset, rgb);
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@
|
|||
#include "kernel/svm/wavelength.h"
|
||||
#include "kernel/svm/white_noise.h"
|
||||
#include "kernel/svm/wireframe.h"
|
||||
#include "util/defines.h"
|
||||
|
||||
#ifdef __SHADER_RAYTRACE__
|
||||
# include "kernel/svm/ao.h"
|
||||
|
|
@ -106,24 +107,25 @@ ccl_device void svm_eval_nodes(KernelGlobals kg,
|
|||
float stack[SVM_STACK_SIZE];
|
||||
/* Initialize to silence (false positive?) warning about uninitialized use on Windows. */
|
||||
Spectrum closure_weight = zero_spectrum();
|
||||
int offset = sd->shader & SHADER_MASK;
|
||||
int offset = (sd->shader & SHADER_MASK) * (1 + sizeof(SVMNodeShaderJump) / sizeof(uint));
|
||||
|
||||
while (true) {
|
||||
uint4 node = read_node(kg, &offset);
|
||||
const uint node_type = kernel_data_fetch(svm_nodes, offset++);
|
||||
|
||||
switch (node.x) {
|
||||
switch (node_type) {
|
||||
SVM_CASE(NODE_END)
|
||||
return;
|
||||
SVM_CASE(NODE_SHADER_JUMP)
|
||||
{
|
||||
const SVMNodeShaderJump jump = svm_node_get<SVMNodeShaderJump>(kg, &offset);
|
||||
if (type == SHADER_TYPE_SURFACE) {
|
||||
offset = int(node.y);
|
||||
offset = jump.offset_surface;
|
||||
}
|
||||
else if (type == SHADER_TYPE_VOLUME) {
|
||||
offset = int(node.z);
|
||||
offset = jump.offset_volume;
|
||||
}
|
||||
else if (type == SHADER_TYPE_DISPLACEMENT) {
|
||||
offset = int(node.w);
|
||||
offset = jump.offset_displacement;
|
||||
}
|
||||
else {
|
||||
return;
|
||||
|
|
@ -131,383 +133,435 @@ ccl_device void svm_eval_nodes(KernelGlobals kg,
|
|||
break;
|
||||
}
|
||||
SVM_CASE(NODE_CLOSURE_BSDF)
|
||||
offset = svm_node_closure_bsdf<node_feature_mask, type>(
|
||||
kg, sd, stack, closure_weight, node, path_flag, offset);
|
||||
{
|
||||
const ccl_global SVMNodeClosureBsdf &bsdf_node = svm_node_get<SVMNodeClosureBsdf>(kg,
|
||||
&offset);
|
||||
offset = svm_node_closure_bsdf<node_feature_mask, type>(
|
||||
kg, sd, stack, closure_weight, bsdf_node, path_flag, offset);
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_CLOSURE_EMISSION)
|
||||
IF_KERNEL_NODES_FEATURE(EMISSION)
|
||||
{
|
||||
svm_node_closure_emission(kg, sd, stack, closure_weight, node);
|
||||
svm_node_closure_emission(
|
||||
kg, sd, stack, closure_weight, svm_node_get<SVMNodeClosureEmission>(kg, &offset));
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_CLOSURE_BACKGROUND)
|
||||
IF_KERNEL_NODES_FEATURE(EMISSION)
|
||||
{
|
||||
svm_node_closure_background(sd, stack, closure_weight, node);
|
||||
svm_node_closure_background(
|
||||
sd, stack, closure_weight, svm_node_get<SVMNodeClosureBackground>(kg, &offset));
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_CLOSURE_SET_WEIGHT)
|
||||
svm_node_closure_set_weight(&closure_weight, node.y, node.z, node.w);
|
||||
svm_node_closure_set_weight(&closure_weight,
|
||||
svm_node_get<SVMNodeClosureSetWeight>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_CLOSURE_WEIGHT)
|
||||
svm_node_closure_weight(stack, &closure_weight, node.y);
|
||||
svm_node_closure_weight(
|
||||
stack, &closure_weight, svm_node_get<SVMNodeClosureWeight>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_EMISSION_WEIGHT)
|
||||
IF_KERNEL_NODES_FEATURE(EMISSION)
|
||||
{
|
||||
svm_node_emission_weight(stack, &closure_weight, node);
|
||||
svm_node_emission_weight(
|
||||
stack, &closure_weight, svm_node_get<SVMNodeEmissionWeight>(kg, &offset));
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_MIX_CLOSURE)
|
||||
svm_node_mix_closure(stack, node);
|
||||
svm_node_mix_closure(stack, svm_node_get<SVMNodeMixClosure>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_JUMP_IF_ZERO)
|
||||
if (stack_load_float(stack, node.z) <= 0.0f) {
|
||||
offset += node.y;
|
||||
{
|
||||
const SVMNodeJumpIfZero jump = svm_node_get<SVMNodeJumpIfZero>(kg, &offset);
|
||||
if (stack_load_float(stack, jump.stack_offset) <= 0.0f) {
|
||||
offset += jump.jump_offset;
|
||||
}
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_JUMP_IF_ONE)
|
||||
if (stack_load_float(stack, node.z) >= 1.0f) {
|
||||
offset += node.y;
|
||||
{
|
||||
const SVMNodeJumpIfOne jump = svm_node_get<SVMNodeJumpIfOne>(kg, &offset);
|
||||
if (stack_load_float(stack, jump.stack_offset) >= 1.0f) {
|
||||
offset += jump.jump_offset;
|
||||
}
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_GEOMETRY)
|
||||
svm_node_geometry(kg, sd, stack, node);
|
||||
svm_node_geometry<float3>(kg, sd, stack, svm_node_get<SVMNodeGeometry>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_GEOMETRY_DERIVATIVE)
|
||||
IF_NOT_KERNEL_NODES_FEATURE(VOLUME)
|
||||
{
|
||||
svm_node_geometry_derivative(kg, sd, stack, node);
|
||||
svm_node_geometry<dual3>(kg, sd, stack, svm_node_get<SVMNodeGeometry>(kg, &offset));
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_CONVERT)
|
||||
svm_node_convert<float, float3>(kg, stack, node.y, node.z, node.w);
|
||||
svm_node_convert<float, float3>(kg, stack, svm_node_get<SVMNodeConvert>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_CONVERT_DERIVATIVE)
|
||||
IF_NOT_KERNEL_NODES_FEATURE(VOLUME)
|
||||
{
|
||||
svm_node_convert<dual1, dual3>(kg, stack, node.y, node.z, node.w);
|
||||
svm_node_convert<dual1, dual3>(kg, stack, svm_node_get<SVMNodeConvert>(kg, &offset));
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_TEX_COORD)
|
||||
offset = svm_node_tex_coord(kg, sd, path_flag, stack, node, offset);
|
||||
{
|
||||
const ccl_global auto &node = svm_node_get<SVMNodeTexCoord>(kg, &offset);
|
||||
offset = svm_node_tex_coord(kg, sd, path_flag, stack, node, offset);
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_TEX_COORD_DERIVATIVE)
|
||||
IF_NOT_KERNEL_NODES_FEATURE(VOLUME)
|
||||
{
|
||||
const ccl_global auto &node = svm_node_get<SVMNodeTexCoord>(kg, &offset);
|
||||
offset = svm_node_tex_coord_derivative(kg, sd, path_flag, stack, node, offset);
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_VALUE_F)
|
||||
svm_node_value_f<float>(stack, node.y, node.z);
|
||||
svm_node_value_f<float>(stack, svm_node_get<SVMNodeValueF>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_VALUE_F_DERIVATIVE)
|
||||
IF_NOT_KERNEL_NODES_FEATURE(VOLUME)
|
||||
{
|
||||
svm_node_value_f<dual1>(stack, node.y, node.z);
|
||||
svm_node_value_f<dual1>(stack, svm_node_get<SVMNodeValueF>(kg, &offset));
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_VALUE_V)
|
||||
offset = svm_node_value_v<float3>(kg, stack, node.y, offset);
|
||||
svm_node_value_v<float3>(stack, svm_node_get<SVMNodeValueV>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_VALUE_V_DERIVATIVE)
|
||||
IF_NOT_KERNEL_NODES_FEATURE(VOLUME)
|
||||
{
|
||||
offset = svm_node_value_v<dual3>(kg, stack, node.y, offset);
|
||||
svm_node_value_v<dual3>(stack, svm_node_get<SVMNodeValueV>(kg, &offset));
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_ATTR)
|
||||
IF_KERNEL_NODES_FEATURE(VOLUME)
|
||||
{
|
||||
#ifdef __VOLUME__
|
||||
svm_node_attr_volume(kg, sd, stack, node);
|
||||
svm_node_attr_volume(kg, sd, stack, svm_node_get<SVMNodeAttr>(kg, &offset));
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
svm_node_attr_surface(kg, sd, stack, node);
|
||||
svm_node_attr_surface(kg, sd, stack, svm_node_get<SVMNodeAttr>(kg, &offset));
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_ATTR_DERIVATIVE)
|
||||
IF_NOT_KERNEL_NODES_FEATURE(VOLUME)
|
||||
{
|
||||
svm_node_attr_derivative(kg, sd, stack, node);
|
||||
svm_node_attr_derivative(kg, sd, stack, svm_node_get<SVMNodeAttr>(kg, &offset));
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_VERTEX_COLOR)
|
||||
svm_node_vertex_color(kg, sd, stack, node);
|
||||
svm_node_vertex_color(kg, sd, stack, svm_node_get<SVMNodeVertexColor>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_VERTEX_COLOR_DERIVATIVE)
|
||||
IF_NOT_KERNEL_NODES_FEATURE(VOLUME)
|
||||
{
|
||||
svm_node_vertex_color_derivative(kg, sd, stack, node);
|
||||
svm_node_vertex_color_derivative(
|
||||
kg, sd, stack, svm_node_get<SVMNodeVertexColor>(kg, &offset));
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_SET_DISPLACEMENT)
|
||||
svm_node_set_displacement<node_feature_mask>(sd, stack, node.y);
|
||||
svm_node_set_displacement<node_feature_mask>(
|
||||
sd, stack, svm_node_get<SVMNodeSetDisplacement>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_DISPLACEMENT)
|
||||
svm_node_displacement<node_feature_mask>(kg, sd, stack, node);
|
||||
svm_node_displacement<node_feature_mask>(
|
||||
kg, sd, stack, svm_node_get<SVMNodeDisplacement>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_VECTOR_DISPLACEMENT)
|
||||
offset = svm_node_vector_displacement<node_feature_mask>(kg, sd, stack, node, offset);
|
||||
svm_node_vector_displacement<node_feature_mask>(
|
||||
kg, sd, stack, svm_node_get<SVMNodeVectorDisplacement>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_TEX_IMAGE)
|
||||
svm_node_tex_image(kg, sd, stack, node, false);
|
||||
svm_node_tex_image<float3>(kg, sd, stack, svm_node_get<SVMNodeTexImage>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_TEX_IMAGE_DERIVATIVE)
|
||||
IF_NOT_KERNEL_NODES_FEATURE(VOLUME)
|
||||
{
|
||||
svm_node_tex_image(kg, sd, stack, node, true);
|
||||
svm_node_tex_image<dual3>(kg, sd, stack, svm_node_get<SVMNodeTexImage>(kg, &offset));
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_TEX_IMAGE_BOX)
|
||||
svm_node_tex_image_box(kg, sd, stack, node, false);
|
||||
svm_node_tex_image_box<float3>(kg, sd, stack, svm_node_get<SVMNodeTexImageBox>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_TEX_IMAGE_BOX_DERIVATIVE)
|
||||
IF_NOT_KERNEL_NODES_FEATURE(VOLUME)
|
||||
{
|
||||
svm_node_tex_image_box(kg, sd, stack, node, true);
|
||||
svm_node_tex_image_box<dual3>(
|
||||
kg, sd, stack, svm_node_get<SVMNodeTexImageBox>(kg, &offset));
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_TEX_NOISE)
|
||||
offset = svm_node_tex_noise(kg, stack, node.y, node.z, node.w, offset);
|
||||
svm_node_tex_noise(stack, svm_node_get<SVMNodeTexNoise>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_SET_BUMP)
|
||||
offset = svm_node_set_bump<node_feature_mask>(kg, sd, stack, node, offset);
|
||||
svm_node_set_bump<node_feature_mask>(
|
||||
kg, sd, stack, svm_node_get<SVMNodeSetBump>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_CLOSURE_SET_NORMAL)
|
||||
IF_KERNEL_NODES_FEATURE(BUMP)
|
||||
{
|
||||
svm_node_set_normal(sd, stack, node.y, node.z);
|
||||
svm_node_set_normal(sd, stack, svm_node_get<SVMNodeClosureSetNormal>(kg, &offset));
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_ENTER_BUMP_EVAL)
|
||||
IF_KERNEL_NODES_FEATURE(BUMP_STATE)
|
||||
{
|
||||
svm_node_enter_bump_eval(kg, sd, stack, node.y);
|
||||
svm_node_enter_bump_eval(kg, sd, stack, svm_node_get<SVMNodeEnterBumpEval>(kg, &offset));
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_LEAVE_BUMP_EVAL)
|
||||
IF_KERNEL_NODES_FEATURE(BUMP_STATE)
|
||||
{
|
||||
svm_node_leave_bump_eval(sd, stack, node.y);
|
||||
svm_node_leave_bump_eval(sd, stack, svm_node_get<SVMNodeLeaveBumpEval>(kg, &offset));
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_HSV)
|
||||
svm_node_hsv(stack, node);
|
||||
svm_node_hsv(stack, svm_node_get<SVMNodeHSV>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_CLOSURE_HOLDOUT)
|
||||
svm_node_closure_holdout(sd, stack, closure_weight, node);
|
||||
svm_node_closure_holdout(
|
||||
sd, stack, closure_weight, svm_node_get<SVMNodeClosureHoldout>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_FRESNEL)
|
||||
svm_node_fresnel(sd, stack, node.y, node.z, node.w);
|
||||
svm_node_fresnel(sd, stack, svm_node_get<SVMNodeFresnel>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_LAYER_WEIGHT)
|
||||
svm_node_layer_weight(sd, stack, node);
|
||||
svm_node_layer_weight(sd, stack, svm_node_get<SVMNodeLayerWeight>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_CLOSURE_VOLUME)
|
||||
IF_KERNEL_NODES_FEATURE(VOLUME)
|
||||
{
|
||||
svm_node_closure_volume<type>(kg, sd, stack, closure_weight, node);
|
||||
svm_node_closure_volume<type>(
|
||||
kg, sd, stack, closure_weight, svm_node_get<SVMNodeClosureVolume>(kg, &offset));
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_VOLUME_COEFFICIENTS)
|
||||
IF_KERNEL_NODES_FEATURE(VOLUME)
|
||||
{
|
||||
svm_node_volume_coefficients<type>(kg, sd, stack, closure_weight, node, path_flag);
|
||||
svm_node_volume_coefficients<type>(kg,
|
||||
sd,
|
||||
stack,
|
||||
closure_weight,
|
||||
svm_node_get<SVMNodeVolumeCoefficients>(kg, &offset),
|
||||
path_flag);
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_PRINCIPLED_VOLUME)
|
||||
IF_KERNEL_NODES_FEATURE(VOLUME)
|
||||
{
|
||||
offset = svm_node_principled_volume<type>(
|
||||
kg, sd, stack, closure_weight, node, path_flag, offset);
|
||||
svm_node_principled_volume<type>(kg,
|
||||
sd,
|
||||
stack,
|
||||
closure_weight,
|
||||
svm_node_get<SVMNodePrincipledVolume>(kg, &offset),
|
||||
path_flag);
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_MATH)
|
||||
svm_node_math(stack, node.y, node.z, node.w);
|
||||
svm_node_math(stack, svm_node_get<SVMNodeMath>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_VECTOR_MATH)
|
||||
offset = svm_node_vector_math<float3>(kg, stack, node.y, node.z, node.w, offset);
|
||||
svm_node_vector_math<float3>(stack, svm_node_get<SVMNodeVectorMath>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_VECTOR_MATH_DERIVATIVE)
|
||||
IF_NOT_KERNEL_NODES_FEATURE(VOLUME)
|
||||
{
|
||||
offset = svm_node_vector_math<dual3>(kg, stack, node.y, node.z, node.w, offset);
|
||||
svm_node_vector_math<dual3>(stack, svm_node_get<SVMNodeVectorMath>(kg, &offset));
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_RGB_RAMP)
|
||||
offset = svm_node_rgb_ramp(kg, stack, node, offset);
|
||||
{
|
||||
const ccl_global auto &node = svm_node_get<SVMNodeRGBRamp>(kg, &offset);
|
||||
offset = svm_node_rgb_ramp(kg, stack, node, offset);
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_GAMMA)
|
||||
svm_node_gamma(stack, node.y, node.z, node.w);
|
||||
svm_node_gamma(stack, svm_node_get<SVMNodeGamma>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_BRIGHTCONTRAST)
|
||||
svm_node_brightness(stack, node.y, node.z, node.w);
|
||||
svm_node_brightness(stack, svm_node_get<SVMNodeBrightContrast>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_LIGHT_PATH)
|
||||
svm_node_light_path<node_feature_mask>(kg, state, sd, stack, node.y, node.z, path_flag);
|
||||
svm_node_light_path<node_feature_mask>(
|
||||
kg, state, sd, stack, svm_node_get<SVMNodeLightPath>(kg, &offset), path_flag);
|
||||
break;
|
||||
SVM_CASE(NODE_OBJECT_INFO)
|
||||
svm_node_object_info(kg, sd, stack, node.y, node.z);
|
||||
svm_node_object_info(kg, sd, stack, svm_node_get<SVMNodeObjectInfo>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_PARTICLE_INFO)
|
||||
svm_node_particle_info(kg, sd, stack, node.y, node.z);
|
||||
svm_node_particle_info(kg, sd, stack, svm_node_get<SVMNodeParticleInfo>(kg, &offset));
|
||||
break;
|
||||
#if defined(__HAIR__)
|
||||
SVM_CASE(NODE_HAIR_INFO)
|
||||
svm_node_hair_info(kg, sd, stack, node.y, node.z);
|
||||
svm_node_hair_info(kg, sd, stack, svm_node_get<SVMNodeHairInfo>(kg, &offset));
|
||||
break;
|
||||
#endif
|
||||
#if defined(__POINTCLOUD__)
|
||||
SVM_CASE(NODE_POINT_INFO)
|
||||
svm_node_point_info(kg, sd, stack, node.y, node.z);
|
||||
svm_node_point_info(kg, sd, stack, svm_node_get<SVMNodePointInfo>(kg, &offset));
|
||||
break;
|
||||
#endif
|
||||
SVM_CASE(NODE_TEXTURE_MAPPING)
|
||||
offset = svm_node_texture_mapping(kg, stack, node.y, node.z, offset);
|
||||
svm_node_texture_mapping(stack, svm_node_get<SVMNodeTextureMapping>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_MAPPING)
|
||||
svm_node_mapping<float3>(stack, node.y, node.z, node.w);
|
||||
svm_node_mapping<float3>(stack, svm_node_get<SVMNodeMapping>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_MAPPING_DERIVATIVE)
|
||||
IF_NOT_KERNEL_NODES_FEATURE(VOLUME)
|
||||
{
|
||||
svm_node_mapping<dual3>(stack, node.y, node.z, node.w);
|
||||
svm_node_mapping<dual3>(stack, svm_node_get<SVMNodeMapping>(kg, &offset));
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_MIN_MAX)
|
||||
offset = svm_node_min_max(kg, stack, node.y, node.z, offset);
|
||||
svm_node_min_max(stack, svm_node_get<SVMNodeMinMax>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_CAMERA)
|
||||
svm_node_camera(kg, sd, stack, node.y, node.z, node.w);
|
||||
svm_node_camera(kg, sd, stack, svm_node_get<SVMNodeCamera>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_TEX_ENVIRONMENT)
|
||||
svm_node_tex_environment(kg, sd, stack, node, false);
|
||||
svm_node_tex_environment<float3>(
|
||||
kg, sd, stack, svm_node_get<SVMNodeTexEnvironment>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_TEX_ENVIRONMENT_DERIVATIVE)
|
||||
IF_NOT_KERNEL_NODES_FEATURE(VOLUME)
|
||||
{
|
||||
svm_node_tex_environment(kg, sd, stack, node, true);
|
||||
svm_node_tex_environment<dual3>(
|
||||
kg, sd, stack, svm_node_get<SVMNodeTexEnvironment>(kg, &offset));
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_TEX_SKY)
|
||||
offset = svm_node_tex_sky(kg, sd, path_flag, stack, node, offset);
|
||||
{
|
||||
const ccl_global auto &node = svm_node_get<SVMNodeTexSky>(kg, &offset);
|
||||
offset = svm_node_tex_sky(kg, sd, path_flag, stack, node, offset);
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_TEX_GRADIENT)
|
||||
svm_node_tex_gradient(stack, node);
|
||||
svm_node_tex_gradient(stack, svm_node_get<SVMNodeTexGradient>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_TEX_VORONOI)
|
||||
offset = svm_node_tex_voronoi<node_feature_mask>(kg, stack, node.y, node.z, node.w, offset);
|
||||
svm_node_tex_voronoi<node_feature_mask>(stack, svm_node_get<SVMNodeTexVoronoi>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_TEX_GABOR)
|
||||
offset = svm_node_tex_gabor(kg, stack, node.y, node.z, node.w, offset);
|
||||
svm_node_tex_gabor(stack, svm_node_get<SVMNodeTexGabor>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_TEX_WAVE)
|
||||
offset = svm_node_tex_wave(kg, stack, node, offset);
|
||||
svm_node_tex_wave(stack, svm_node_get<SVMNodeTexWave>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_TEX_MAGIC)
|
||||
offset = svm_node_tex_magic(kg, stack, node, offset);
|
||||
svm_node_tex_magic(stack, svm_node_get<SVMNodeTexMagic>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_TEX_CHECKER)
|
||||
svm_node_tex_checker(stack, node);
|
||||
svm_node_tex_checker(stack, svm_node_get<SVMNodeTexChecker>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_TEX_BRICK)
|
||||
offset = svm_node_tex_brick(kg, stack, node, offset);
|
||||
svm_node_tex_brick(stack, svm_node_get<SVMNodeTexBrick>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_TEX_WHITE_NOISE)
|
||||
svm_node_tex_white_noise(stack, node.y, node.z, node.w);
|
||||
svm_node_tex_white_noise(stack, svm_node_get<SVMNodeTexWhiteNoise>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_NORMAL)
|
||||
offset = svm_node_normal(kg, stack, node.y, node.z, node.w, offset);
|
||||
svm_node_normal(stack, svm_node_get<SVMNodeNormal>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_LIGHT_FALLOFF)
|
||||
svm_node_light_falloff(sd, stack, node);
|
||||
svm_node_light_falloff(sd, stack, svm_node_get<SVMNodeLightFalloff>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_IES)
|
||||
svm_node_ies(kg, sd, stack, node);
|
||||
svm_node_ies(kg, sd, stack, svm_node_get<SVMNodeIES>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_CURVES)
|
||||
offset = svm_node_curves(kg, stack, node, offset);
|
||||
{
|
||||
const ccl_global auto &node = svm_node_get<SVMNodeCurves>(kg, &offset);
|
||||
offset = svm_node_curves(kg, stack, node, offset);
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_TANGENT)
|
||||
svm_node_tangent<float3>(kg, sd, stack, node);
|
||||
svm_node_tangent<float3>(kg, sd, stack, svm_node_get<SVMNodeTangent>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_TANGENT_DERIVATIVE)
|
||||
IF_NOT_KERNEL_NODES_FEATURE(VOLUME)
|
||||
{
|
||||
svm_node_tangent<dual3>(kg, sd, stack, node);
|
||||
svm_node_tangent<dual3>(kg, sd, stack, svm_node_get<SVMNodeTangent>(kg, &offset));
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_NORMAL_MAP)
|
||||
svm_node_normal_map(kg, sd, stack, node);
|
||||
svm_node_normal_map(kg, sd, stack, svm_node_get<SVMNodeNormalMap>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_RADIAL_TILING)
|
||||
offset = svm_node_radial_tiling<node_feature_mask>(stack, node, offset);
|
||||
svm_node_radial_tiling<node_feature_mask>(stack,
|
||||
svm_node_get<SVMNodeRadialTiling>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_INVERT)
|
||||
svm_node_invert(stack, node.y, node.z, node.w);
|
||||
svm_node_invert(stack, svm_node_get<SVMNodeInvert>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_MIX)
|
||||
offset = svm_node_mix(kg, stack, node.y, node.z, node.w, offset);
|
||||
svm_node_mix(stack, svm_node_get<SVMNodeMix>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_SEPARATE_COLOR)
|
||||
svm_node_separate_color(stack, node.y, node.z, node.w);
|
||||
svm_node_separate_color(stack, svm_node_get<SVMNodeSeparateColor>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_COMBINE_COLOR)
|
||||
svm_node_combine_color(stack, node.y, node.z, node.w);
|
||||
svm_node_combine_color(stack, svm_node_get<SVMNodeCombineColor>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_SEPARATE_VECTOR)
|
||||
svm_node_separate_vector<float3>(stack, node.y, node.z, node.w);
|
||||
svm_node_separate_vector<float3>(stack, svm_node_get<SVMNodeSeparateVector>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_SEPARATE_VECTOR_DERIVATIVE)
|
||||
IF_NOT_KERNEL_NODES_FEATURE(VOLUME)
|
||||
{
|
||||
svm_node_separate_vector<dual3>(stack, node.y, node.z, node.w);
|
||||
svm_node_separate_vector<dual3>(stack, svm_node_get<SVMNodeSeparateVector>(kg, &offset));
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_COMBINE_VECTOR)
|
||||
svm_node_combine_vector<float3>(stack, node.y, node.z, node.w);
|
||||
svm_node_combine_vector<float3>(stack, svm_node_get<SVMNodeCombineVector>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_COMBINE_VECTOR_DERIVATIVE)
|
||||
IF_NOT_KERNEL_NODES_FEATURE(VOLUME)
|
||||
{
|
||||
svm_node_combine_vector<dual3>(stack, node.y, node.z, node.w);
|
||||
svm_node_combine_vector<dual3>(stack, svm_node_get<SVMNodeCombineVector>(kg, &offset));
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_VECTOR_ROTATE)
|
||||
svm_node_vector_rotate(stack, node.y, node.z, node.w);
|
||||
svm_node_vector_rotate(stack, svm_node_get<SVMNodeVectorRotate>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_VECTOR_TRANSFORM)
|
||||
svm_node_vector_transform(kg, sd, stack, node);
|
||||
svm_node_vector_transform(kg, sd, stack, svm_node_get<SVMNodeVectorTransform>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_WIREFRAME)
|
||||
svm_node_wireframe(kg, sd, stack, node);
|
||||
svm_node_wireframe(kg, sd, stack, svm_node_get<SVMNodeWireframe>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_WAVELENGTH)
|
||||
svm_node_wavelength(kg, stack, node.y, node.z);
|
||||
svm_node_wavelength(kg, stack, svm_node_get<SVMNodeWavelength>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_BLACKBODY)
|
||||
svm_node_blackbody(kg, stack, node.y, node.z);
|
||||
svm_node_blackbody(kg, stack, svm_node_get<SVMNodeBlackbody>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_MAP_RANGE)
|
||||
offset = svm_node_map_range(kg, stack, node.y, node.z, node.w, offset);
|
||||
svm_node_map_range(stack, svm_node_get<SVMNodeMapRange>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_VECTOR_MAP_RANGE)
|
||||
offset = svm_node_vector_map_range(stack, node.y, node.z, node.w, offset);
|
||||
svm_node_vector_map_range(stack, svm_node_get<SVMNodeVectorMapRange>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_CLAMP)
|
||||
offset = svm_node_clamp(kg, stack, node.y, node.z, node.w, offset);
|
||||
svm_node_clamp(stack, svm_node_get<SVMNodeClamp>(kg, &offset));
|
||||
break;
|
||||
#ifdef __SHADER_RAYTRACE__
|
||||
SVM_CASE(NODE_BEVEL)
|
||||
svm_node_bevel<node_feature_mask>(kg, state, sd, stack, node);
|
||||
svm_node_bevel<node_feature_mask>(
|
||||
kg, state, sd, stack, svm_node_get<SVMNodeBevel>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_AMBIENT_OCCLUSION)
|
||||
svm_node_ao<node_feature_mask>(kg, state, sd, stack, node);
|
||||
svm_node_ao<node_feature_mask>(
|
||||
kg, state, sd, stack, svm_node_get<SVMNodeAmbientOcclusion>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_RAYCAST)
|
||||
offset = svm_node_raycast<node_feature_mask>(kg, state, sd, stack, node, offset);
|
||||
svm_node_raycast<node_feature_mask>(
|
||||
kg, state, sd, stack, svm_node_get<SVMNodeRaycast>(kg, &offset));
|
||||
break;
|
||||
#endif
|
||||
SVM_CASE(NODE_AOV_START)
|
||||
|
|
@ -516,25 +570,31 @@ ccl_device void svm_eval_nodes(KernelGlobals kg,
|
|||
}
|
||||
break;
|
||||
SVM_CASE(NODE_AOV_COLOR)
|
||||
svm_node_aov_color<node_feature_mask>(kg, sd, state, stack, node, render_buffer);
|
||||
svm_node_aov_color<node_feature_mask>(
|
||||
kg, sd, state, stack, svm_node_get<SVMNodeAOVColor>(kg, &offset), render_buffer);
|
||||
break;
|
||||
SVM_CASE(NODE_AOV_VALUE)
|
||||
svm_node_aov_value<node_feature_mask>(kg, sd, state, stack, node, render_buffer);
|
||||
svm_node_aov_value<node_feature_mask>(
|
||||
kg, sd, state, stack, svm_node_get<SVMNodeAOVValue>(kg, &offset), render_buffer);
|
||||
break;
|
||||
SVM_CASE(NODE_FLOAT_CURVE)
|
||||
offset = svm_node_curve(kg, stack, node, offset);
|
||||
{
|
||||
const ccl_global auto &node = svm_node_get<SVMNodeFloatCurve>(kg, &offset);
|
||||
offset = svm_node_curve(kg, stack, node, offset);
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_MIX_COLOR)
|
||||
svm_node_mix_color(stack, node.y, node.z, node.w);
|
||||
svm_node_mix_color(stack, svm_node_get<SVMNodeMixColor>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_MIX_FLOAT)
|
||||
svm_node_mix_float(stack, node.y, node.z, node.w);
|
||||
svm_node_mix_float(stack, svm_node_get<SVMNodeMixFloat>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_MIX_VECTOR)
|
||||
svm_node_mix_vector(stack, node.y, node.z);
|
||||
svm_node_mix_vector(stack, svm_node_get<SVMNodeMixVector>(kg, &offset));
|
||||
break;
|
||||
SVM_CASE(NODE_MIX_VECTOR_NON_UNIFORM)
|
||||
svm_node_mix_vector_non_uniform(stack, node.y, node.z);
|
||||
svm_node_mix_vector_non_uniform(stack,
|
||||
svm_node_get<SVMNodeMixVectorNonUniform>(kg, &offset));
|
||||
break;
|
||||
default:
|
||||
kernel_assert(!"Unknown node type was passed to the SVM machine");
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include "kernel/geom/primitive.h"
|
||||
|
||||
#include "kernel/svm/attribute.h"
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
#include "util/math_base.h"
|
||||
|
|
@ -91,12 +92,12 @@ template<typename Float3Type>
|
|||
ccl_device_noinline Float3Type svm_node_tex_coord_eval(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
const uint32_t path_flag,
|
||||
const uint type,
|
||||
const NodeTexCoord type,
|
||||
ccl_private int *offset)
|
||||
{
|
||||
Float3Type data;
|
||||
|
||||
switch ((NodeTexCoord)type) {
|
||||
switch (type) {
|
||||
case NODE_TEXCO_OBJECT:
|
||||
case NODE_TEXCO_OBJECT_WITH_TRANSFORM: {
|
||||
data = shading_position<Float3Type>(sd);
|
||||
|
|
@ -104,10 +105,7 @@ ccl_device_noinline Float3Type svm_node_tex_coord_eval(KernelGlobals kg,
|
|||
object_inverse_position_transform_if_object(kg, sd, &data);
|
||||
}
|
||||
else {
|
||||
Transform tfm;
|
||||
tfm.x = read_node_float(kg, offset);
|
||||
tfm.y = read_node_float(kg, offset);
|
||||
tfm.z = read_node_float(kg, offset);
|
||||
const Transform tfm = make_transform(svm_node_get<PackedTransform>(kg, offset));
|
||||
data = transform_point(&tfm, data);
|
||||
}
|
||||
break;
|
||||
|
|
@ -181,90 +179,75 @@ ccl_device_noinline Float3Type svm_node_tex_coord_eval(KernelGlobals kg,
|
|||
ccl_device_noinline int svm_node_tex_coord(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
const uint32_t path_flag,
|
||||
ccl_private float *stack,
|
||||
const uint4 node,
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeTexCoord &ccl_restrict node,
|
||||
int offset)
|
||||
{
|
||||
uint type, unused1, unused2;
|
||||
svm_unpack_node_uchar3(node.y, &type, &unused1, &unused2);
|
||||
const float3 data = svm_node_tex_coord_eval<float3>(kg, sd, path_flag, type, &offset);
|
||||
stack_store(stack, node.z, data);
|
||||
const float3 data = svm_node_tex_coord_eval<float3>(kg, sd, path_flag, node.texco_type, &offset);
|
||||
stack_store(stack, node.out_offset, data);
|
||||
return offset;
|
||||
}
|
||||
|
||||
ccl_device_noinline int svm_node_tex_coord_derivative(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
const uint32_t path_flag,
|
||||
ccl_private float *stack,
|
||||
const uint4 node,
|
||||
int offset)
|
||||
ccl_device_noinline int svm_node_tex_coord_derivative(
|
||||
KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
const uint32_t path_flag,
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeTexCoord &ccl_restrict node,
|
||||
int offset)
|
||||
{
|
||||
uint type, bump_offset, store_derivatives;
|
||||
svm_unpack_node_uchar3(node.y, &type, &bump_offset, &store_derivatives);
|
||||
|
||||
dual3 data = svm_node_tex_coord_eval<dual3>(kg, sd, path_flag, type, &offset);
|
||||
const float bump_filter_width = __uint_as_float(node.w);
|
||||
if (bump_offset == NODE_BUMP_OFFSET_DX) {
|
||||
data.val += data.dx * bump_filter_width;
|
||||
dual3 data = svm_node_tex_coord_eval<dual3>(kg, sd, path_flag, node.texco_type, &offset);
|
||||
if (node.bump_offset == NODE_BUMP_OFFSET_DX) {
|
||||
data.val += data.dx * node.bump_filter_width;
|
||||
}
|
||||
else if (bump_offset == NODE_BUMP_OFFSET_DY) {
|
||||
data.val += data.dy * bump_filter_width;
|
||||
else if (node.bump_offset == NODE_BUMP_OFFSET_DY) {
|
||||
data.val += data.dy * node.bump_filter_width;
|
||||
}
|
||||
/* Normal texture coordinate must be normalized after bump offset, matching OSL. */
|
||||
if (type == NODE_TEXCO_NORMAL) {
|
||||
if (node.texco_type == NODE_TEXCO_NORMAL) {
|
||||
data = safe_normalize(data);
|
||||
}
|
||||
if (store_derivatives) {
|
||||
stack_store(stack, node.z, data);
|
||||
if (node.store_derivatives) {
|
||||
stack_store(stack, node.out_offset, data);
|
||||
}
|
||||
else {
|
||||
stack_store(stack, node.z, data.val);
|
||||
stack_store(stack, node.out_offset, data.val);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
ccl_device_noinline void svm_node_normal_map(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint4 node)
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeNormalMap &ccl_restrict node)
|
||||
{
|
||||
uint color_offset;
|
||||
uint strength_offset;
|
||||
uint normal_offset;
|
||||
uint flags;
|
||||
svm_unpack_node_uchar4(node.y, &color_offset, &strength_offset, &normal_offset, &flags);
|
||||
|
||||
const uint space = flags & NODE_NORMAL_MAP_FLAG_SPACE_MASK;
|
||||
const bool invert_green = (flags & NODE_NORMAL_MAP_FLAG_DIRECTX) != 0;
|
||||
const bool use_original_base = (flags & NODE_NORMAL_MAP_FLAG_ORIGINAL) != 0;
|
||||
|
||||
float3 color = stack_load_float3(stack, color_offset);
|
||||
float3 color = stack_load(stack, node.color);
|
||||
color = 2.0f * make_float3(color.x - 0.5f, color.y - 0.5f, color.z - 0.5f);
|
||||
|
||||
if (invert_green) {
|
||||
if (node.invert_green) {
|
||||
color.y = -color.y;
|
||||
}
|
||||
|
||||
const bool is_backfacing = (sd->flag & SD_BACKFACING) != 0;
|
||||
float3 N;
|
||||
float strength = stack_load_float(stack, strength_offset);
|
||||
float strength = stack_load(stack, node.strength);
|
||||
bool linear_interpolate_strength = false;
|
||||
|
||||
if (space == NODE_NORMAL_MAP_TANGENT) {
|
||||
if (node.space == NODE_NORMAL_MAP_TANGENT) {
|
||||
/* tangent space */
|
||||
if (sd->object == OBJECT_NONE || (sd->type & PRIMITIVE_TRIANGLE) == 0) {
|
||||
/* Fall back to unperturbed normal. */
|
||||
stack_store_float3(stack, normal_offset, sd->N);
|
||||
stack_store_float3(stack, node.normal_offset, sd->N);
|
||||
return;
|
||||
}
|
||||
|
||||
/* first try to get tangent attribute */
|
||||
const AttributeDescriptor attr = find_attribute(kg, sd, node.z);
|
||||
const AttributeDescriptor attr_sign = find_attribute(kg, sd, node.w);
|
||||
const AttributeDescriptor attr = find_attribute(kg, sd, node.attr);
|
||||
const AttributeDescriptor attr_sign = find_attribute(kg, sd, node.attr_sign);
|
||||
|
||||
if (attr.offset == ATTR_STD_NOT_FOUND || attr_sign.offset == ATTR_STD_NOT_FOUND) {
|
||||
/* Fall back to unperturbed normal. */
|
||||
stack_store_float3(stack, normal_offset, sd->N);
|
||||
stack_store_float3(stack, node.normal_offset, sd->N);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -275,7 +258,7 @@ ccl_device_noinline void svm_node_normal_map(KernelGlobals kg,
|
|||
|
||||
if (sd->shader & SHADER_SMOOTH_NORMAL) {
|
||||
const AttributeDescriptor attr_undisplaced_normal =
|
||||
(use_original_base) ?
|
||||
(node.use_original_base) ?
|
||||
find_attribute(kg, sd->object, sd->prim, ATTR_STD_NORMAL_UNDISPLACED) :
|
||||
AttributeDescriptor{ATTR_ELEMENT_NONE, NODE_ATTR_FLOAT3, ATTR_STD_NOT_FOUND};
|
||||
if (attr_undisplaced_normal.offset != ATTR_STD_NOT_FOUND) {
|
||||
|
|
@ -321,7 +304,9 @@ ccl_device_noinline void svm_node_normal_map(KernelGlobals kg,
|
|||
linear_interpolate_strength = true;
|
||||
|
||||
/* strange blender convention */
|
||||
if (space == NODE_NORMAL_MAP_BLENDER_OBJECT || space == NODE_NORMAL_MAP_BLENDER_WORLD) {
|
||||
if (node.space == NODE_NORMAL_MAP_BLENDER_OBJECT ||
|
||||
node.space == NODE_NORMAL_MAP_BLENDER_WORLD)
|
||||
{
|
||||
color.y = -color.y;
|
||||
color.z = -color.z;
|
||||
}
|
||||
|
|
@ -329,7 +314,7 @@ ccl_device_noinline void svm_node_normal_map(KernelGlobals kg,
|
|||
/* object, world space */
|
||||
N = color;
|
||||
|
||||
if (space == NODE_NORMAL_MAP_OBJECT || space == NODE_NORMAL_MAP_BLENDER_OBJECT) {
|
||||
if (node.space == NODE_NORMAL_MAP_OBJECT || node.space == NODE_NORMAL_MAP_BLENDER_OBJECT) {
|
||||
object_normal_transform(kg, sd, &N);
|
||||
}
|
||||
else {
|
||||
|
|
@ -352,27 +337,22 @@ ccl_device_noinline void svm_node_normal_map(KernelGlobals kg,
|
|||
N = sd->N;
|
||||
}
|
||||
|
||||
stack_store_float3(stack, normal_offset, N);
|
||||
stack_store_float3(stack, node.normal_offset, N);
|
||||
}
|
||||
|
||||
template<typename Float3Type>
|
||||
ccl_device_noinline void svm_node_tangent(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint4 node)
|
||||
const ccl_global SVMNodeTangent &ccl_restrict node)
|
||||
{
|
||||
uint tangent_offset;
|
||||
uint direction_type;
|
||||
uint axis;
|
||||
svm_unpack_node_uchar3(node.y, &tangent_offset, &direction_type, &axis);
|
||||
|
||||
const AttributeDescriptor desc = find_attribute(kg, sd, node.z);
|
||||
const AttributeDescriptor desc = find_attribute(kg, sd, node.attr);
|
||||
|
||||
Float3Type tangent;
|
||||
if (direction_type == NODE_TANGENT_UVMAP) {
|
||||
if (node.direction_type == NODE_TANGENT_UVMAP) {
|
||||
/* UV map */
|
||||
if (desc.offset == ATTR_STD_NOT_FOUND) {
|
||||
stack_store(stack, tangent_offset, Float3Type());
|
||||
stack_store(stack, node.tangent_offset, Float3Type());
|
||||
return;
|
||||
}
|
||||
if (desc.type == NODE_ATTR_FLOAT2) {
|
||||
|
|
@ -407,10 +387,10 @@ ccl_device_noinline void svm_node_tangent(KernelGlobals kg,
|
|||
|
||||
if constexpr (is_dual_v<Float3Type>) {
|
||||
using FloatType = dual_scalar_t<Float3Type>;
|
||||
if (axis == NODE_TANGENT_AXIS_X) {
|
||||
if (node.axis == NODE_TANGENT_AXIS_X) {
|
||||
tangent = make_float3(FloatType(), -(generated.z() - 0.5f), (generated.y() - 0.5f));
|
||||
}
|
||||
else if (axis == NODE_TANGENT_AXIS_Y) {
|
||||
else if (node.axis == NODE_TANGENT_AXIS_Y) {
|
||||
tangent = make_float3(-(generated.z() - 0.5f), FloatType(), (generated.x() - 0.5f));
|
||||
}
|
||||
else {
|
||||
|
|
@ -418,10 +398,10 @@ ccl_device_noinline void svm_node_tangent(KernelGlobals kg,
|
|||
}
|
||||
}
|
||||
else {
|
||||
if (axis == NODE_TANGENT_AXIS_X) {
|
||||
if (node.axis == NODE_TANGENT_AXIS_X) {
|
||||
tangent = make_float3(0.0f, -(generated.z - 0.5f), (generated.y - 0.5f));
|
||||
}
|
||||
else if (axis == NODE_TANGENT_AXIS_Y) {
|
||||
else if (node.axis == NODE_TANGENT_AXIS_Y) {
|
||||
tangent = make_float3(-(generated.z - 0.5f), 0.0f, (generated.x - 0.5f));
|
||||
}
|
||||
else {
|
||||
|
|
@ -432,7 +412,7 @@ ccl_device_noinline void svm_node_tangent(KernelGlobals kg,
|
|||
|
||||
object_normal_transform(kg, sd, &tangent);
|
||||
tangent = cross(sd->N, normalize(cross(tangent, sd->N)));
|
||||
stack_store(stack, tangent_offset, tangent);
|
||||
stack_store(stack, node.tangent_offset, tangent);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -4,22 +4,43 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "util/transform.h"
|
||||
#include "util/types.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Stack */
|
||||
|
||||
/* Stack offset type. Stack offsets are in the range [0, SVM_STACK_SIZE]. */
|
||||
using SVMStackOffset = uint8_t;
|
||||
|
||||
/* Encodes a node float input, as either float value or a stack offset
|
||||
* encoded in a NaN bit pattern. */
|
||||
struct SVMInputFloat {
|
||||
uint bits;
|
||||
};
|
||||
|
||||
/* Encodes a node float input, as either float3 value or a stack offset
|
||||
* encoded in a NaN bit pattern in the x component. */
|
||||
struct SVMInputFloat3 {
|
||||
SVMInputFloat x, y, z;
|
||||
};
|
||||
|
||||
/* Bit mask for encoding stack offset as NaN. */
|
||||
#define SVM_INPUT_STACK_OFFSET_MASK 0x7FC00000u
|
||||
|
||||
// NOLINTBEGIN
|
||||
/* SVM stack has a fixed size */
|
||||
#define SVM_STACK_SIZE 255
|
||||
/* SVM stack offsets with this value indicate that it's not on the stack */
|
||||
#define SVM_STACK_INVALID 255
|
||||
#define SVM_STACK_INVALID SVMStackOffset(255)
|
||||
|
||||
#define SVM_BUMP_EVAL_STATE_SIZE 10
|
||||
// NOLINTEND
|
||||
|
||||
/* Nodes */
|
||||
|
||||
enum ShaderNodeType {
|
||||
enum ShaderNodeType : uint {
|
||||
#define SHADER_NODE_TYPE(name) name,
|
||||
#define SHADER_NODE_TYPE_DERIVATIVE(name) name, name##_DERIVATIVE,
|
||||
#include "node_types_template.h"
|
||||
|
|
@ -27,13 +48,13 @@ enum ShaderNodeType {
|
|||
NODE_NUM
|
||||
};
|
||||
|
||||
enum NodeAttributeOutputType {
|
||||
enum NodeAttributeOutputType : uint8_t {
|
||||
NODE_ATTR_OUTPUT_FLOAT3 = 0,
|
||||
NODE_ATTR_OUTPUT_FLOAT,
|
||||
NODE_ATTR_OUTPUT_FLOAT_ALPHA,
|
||||
};
|
||||
|
||||
enum NodeAttributeType {
|
||||
enum NodeAttributeType : uint8_t {
|
||||
NODE_ATTR_FLOAT = 0,
|
||||
NODE_ATTR_FLOAT2,
|
||||
NODE_ATTR_FLOAT3,
|
||||
|
|
@ -42,7 +63,7 @@ enum NodeAttributeType {
|
|||
NODE_ATTR_MATRIX
|
||||
};
|
||||
|
||||
enum NodeGeometry {
|
||||
enum NodeGeometry : uint8_t {
|
||||
NODE_GEOM_P = 0,
|
||||
NODE_GEOM_N,
|
||||
NODE_GEOM_T,
|
||||
|
|
@ -51,7 +72,7 @@ enum NodeGeometry {
|
|||
NODE_GEOM_uv
|
||||
};
|
||||
|
||||
enum NodeObjectInfo {
|
||||
enum NodeObjectInfo : uint {
|
||||
NODE_INFO_OB_LOCATION,
|
||||
NODE_INFO_OB_COLOR,
|
||||
NODE_INFO_OB_ALPHA,
|
||||
|
|
@ -60,7 +81,7 @@ enum NodeObjectInfo {
|
|||
NODE_INFO_OB_RANDOM
|
||||
};
|
||||
|
||||
enum NodeParticleInfo {
|
||||
enum NodeParticleInfo : uint {
|
||||
NODE_INFO_PAR_INDEX,
|
||||
NODE_INFO_PAR_RANDOM,
|
||||
NODE_INFO_PAR_AGE,
|
||||
|
|
@ -72,7 +93,7 @@ enum NodeParticleInfo {
|
|||
NODE_INFO_PAR_ANGULAR_VELOCITY
|
||||
};
|
||||
|
||||
enum NodeHairInfo {
|
||||
enum NodeHairInfo : uint {
|
||||
NODE_INFO_CURVE_IS_STRAND,
|
||||
NODE_INFO_CURVE_INTERCEPT,
|
||||
NODE_INFO_CURVE_LENGTH,
|
||||
|
|
@ -81,13 +102,13 @@ enum NodeHairInfo {
|
|||
NODE_INFO_CURVE_RANDOM,
|
||||
};
|
||||
|
||||
enum NodePointInfo {
|
||||
enum NodePointInfo : uint {
|
||||
NODE_INFO_POINT_POSITION,
|
||||
NODE_INFO_POINT_RADIUS,
|
||||
NODE_INFO_POINT_RANDOM,
|
||||
};
|
||||
|
||||
enum NodeLightPath {
|
||||
enum NodeLightPath : uint {
|
||||
NODE_LP_camera = 0,
|
||||
NODE_LP_shadow,
|
||||
NODE_LP_diffuse,
|
||||
|
|
@ -106,13 +127,13 @@ enum NodeLightPath {
|
|||
NODE_LP_ray_portal,
|
||||
};
|
||||
|
||||
enum NodeLightFalloff {
|
||||
enum NodeLightFalloff : uint {
|
||||
NODE_LIGHT_FALLOFF_QUADRATIC,
|
||||
NODE_LIGHT_FALLOFF_LINEAR,
|
||||
NODE_LIGHT_FALLOFF_CONSTANT
|
||||
};
|
||||
|
||||
enum NodeTexCoord {
|
||||
enum NodeTexCoord : uint8_t {
|
||||
NODE_TEXCO_NORMAL,
|
||||
NODE_TEXCO_OBJECT,
|
||||
NODE_TEXCO_OBJECT_WITH_TRANSFORM,
|
||||
|
|
@ -124,7 +145,7 @@ enum NodeTexCoord {
|
|||
NODE_TEXCO_VOLUME_GENERATED
|
||||
};
|
||||
|
||||
enum NodeMix {
|
||||
enum NodeMix : uint {
|
||||
NODE_MIX_BLEND = 0,
|
||||
NODE_MIX_ADD,
|
||||
NODE_MIX_MUL,
|
||||
|
|
@ -147,7 +168,7 @@ enum NodeMix {
|
|||
NODE_MIX_CLAMP /* used for the clamp UI option */
|
||||
};
|
||||
|
||||
enum NodeMathType {
|
||||
enum NodeMathType : uint {
|
||||
NODE_MATH_ADD,
|
||||
NODE_MATH_SUBTRACT,
|
||||
NODE_MATH_MULTIPLY,
|
||||
|
|
@ -191,7 +212,7 @@ enum NodeMathType {
|
|||
NODE_MATH_FLOORED_MODULO,
|
||||
};
|
||||
|
||||
enum NodeVectorMathType {
|
||||
enum NodeVectorMathType : uint {
|
||||
NODE_VECTOR_MATH_ADD,
|
||||
NODE_VECTOR_MATH_SUBTRACT,
|
||||
NODE_VECTOR_MATH_MULTIPLY,
|
||||
|
|
@ -227,26 +248,26 @@ enum NodeVectorMathType {
|
|||
NODE_VECTOR_MATH_ROUND,
|
||||
};
|
||||
|
||||
enum NodeClampType {
|
||||
enum NodeClampType : uint {
|
||||
NODE_CLAMP_MINMAX,
|
||||
NODE_CLAMP_RANGE,
|
||||
};
|
||||
|
||||
enum NodeMapRangeType {
|
||||
enum NodeMapRangeType : uint {
|
||||
NODE_MAP_RANGE_LINEAR,
|
||||
NODE_MAP_RANGE_STEPPED,
|
||||
NODE_MAP_RANGE_SMOOTHSTEP,
|
||||
NODE_MAP_RANGE_SMOOTHERSTEP,
|
||||
};
|
||||
|
||||
enum NodeMappingType {
|
||||
enum NodeMappingType : uint {
|
||||
NODE_MAPPING_TYPE_POINT,
|
||||
NODE_MAPPING_TYPE_TEXTURE,
|
||||
NODE_MAPPING_TYPE_VECTOR,
|
||||
NODE_MAPPING_TYPE_NORMAL
|
||||
};
|
||||
|
||||
enum NodeVectorRotateType {
|
||||
enum NodeVectorRotateType : uint {
|
||||
NODE_VECTOR_ROTATE_TYPE_AXIS,
|
||||
NODE_VECTOR_ROTATE_TYPE_AXIS_X,
|
||||
NODE_VECTOR_ROTATE_TYPE_AXIS_Y,
|
||||
|
|
@ -254,19 +275,19 @@ enum NodeVectorRotateType {
|
|||
NODE_VECTOR_ROTATE_TYPE_EULER_XYZ,
|
||||
};
|
||||
|
||||
enum NodeVectorTransformType {
|
||||
enum NodeVectorTransformType : uint {
|
||||
NODE_VECTOR_TRANSFORM_TYPE_VECTOR,
|
||||
NODE_VECTOR_TRANSFORM_TYPE_POINT,
|
||||
NODE_VECTOR_TRANSFORM_TYPE_NORMAL
|
||||
};
|
||||
|
||||
enum NodeVectorTransformConvertSpace {
|
||||
enum NodeVectorTransformConvertSpace : uint {
|
||||
NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD,
|
||||
NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT,
|
||||
NODE_VECTOR_TRANSFORM_CONVERT_SPACE_CAMERA
|
||||
};
|
||||
|
||||
enum NodeConvert {
|
||||
enum NodeConvert : uint {
|
||||
NODE_CONVERT_FV,
|
||||
NODE_CONVERT_FI,
|
||||
NODE_CONVERT_CF,
|
||||
|
|
@ -278,7 +299,7 @@ enum NodeConvert {
|
|||
NODE_CONVERT_NONE,
|
||||
};
|
||||
|
||||
enum NodeNoiseType {
|
||||
enum NodeNoiseType : uint {
|
||||
NODE_NOISE_MULTIFRACTAL,
|
||||
NODE_NOISE_FBM,
|
||||
NODE_NOISE_HYBRID_MULTIFRACTAL,
|
||||
|
|
@ -286,41 +307,41 @@ enum NodeNoiseType {
|
|||
NODE_NOISE_HETERO_TERRAIN
|
||||
};
|
||||
|
||||
enum NodeGaborType {
|
||||
enum NodeGaborType : uint {
|
||||
NODE_GABOR_TYPE_2D,
|
||||
NODE_GABOR_TYPE_3D,
|
||||
};
|
||||
|
||||
enum NodeWaveType { NODE_WAVE_BANDS, NODE_WAVE_RINGS };
|
||||
enum NodeWaveType : uint { NODE_WAVE_BANDS, NODE_WAVE_RINGS };
|
||||
|
||||
enum NodeWaveBandsDirection {
|
||||
enum NodeWaveBandsDirection : uint {
|
||||
NODE_WAVE_BANDS_DIRECTION_X,
|
||||
NODE_WAVE_BANDS_DIRECTION_Y,
|
||||
NODE_WAVE_BANDS_DIRECTION_Z,
|
||||
NODE_WAVE_BANDS_DIRECTION_DIAGONAL
|
||||
};
|
||||
|
||||
enum NodeWaveRingsDirection {
|
||||
enum NodeWaveRingsDirection : uint {
|
||||
NODE_WAVE_RINGS_DIRECTION_X,
|
||||
NODE_WAVE_RINGS_DIRECTION_Y,
|
||||
NODE_WAVE_RINGS_DIRECTION_Z,
|
||||
NODE_WAVE_RINGS_DIRECTION_SPHERICAL
|
||||
};
|
||||
|
||||
enum NodeWaveProfile {
|
||||
enum NodeWaveProfile : uint {
|
||||
NODE_WAVE_PROFILE_SIN,
|
||||
NODE_WAVE_PROFILE_SAW,
|
||||
NODE_WAVE_PROFILE_TRI,
|
||||
};
|
||||
|
||||
enum NodeSkyType {
|
||||
enum NodeSkyType : uint {
|
||||
NODE_SKY_PREETHAM,
|
||||
NODE_SKY_HOSEK,
|
||||
NODE_SKY_SINGLE_SCATTERING,
|
||||
NODE_SKY_MULTIPLE_SCATTERING
|
||||
};
|
||||
|
||||
enum NodeGradientType {
|
||||
enum NodeGradientType : uint {
|
||||
NODE_BLEND_LINEAR,
|
||||
NODE_BLEND_QUADRATIC,
|
||||
NODE_BLEND_EASING,
|
||||
|
|
@ -330,14 +351,14 @@ enum NodeGradientType {
|
|||
NODE_BLEND_SPHERICAL
|
||||
};
|
||||
|
||||
enum NodeVoronoiDistanceMetric {
|
||||
enum NodeVoronoiDistanceMetric : uint {
|
||||
NODE_VORONOI_EUCLIDEAN,
|
||||
NODE_VORONOI_MANHATTAN,
|
||||
NODE_VORONOI_CHEBYCHEV,
|
||||
NODE_VORONOI_MINKOWSKI,
|
||||
};
|
||||
|
||||
enum NodeVoronoiFeature {
|
||||
enum NodeVoronoiFeature : uint {
|
||||
NODE_VORONOI_F1,
|
||||
NODE_VORONOI_F2,
|
||||
NODE_VORONOI_SMOOTH_F1,
|
||||
|
|
@ -345,13 +366,13 @@ enum NodeVoronoiFeature {
|
|||
NODE_VORONOI_N_SPHERE_RADIUS,
|
||||
};
|
||||
|
||||
enum NodeBlendWeightType { NODE_LAYER_WEIGHT_FRESNEL, NODE_LAYER_WEIGHT_FACING };
|
||||
enum NodeBlendWeightType : uint { NODE_LAYER_WEIGHT_FRESNEL, NODE_LAYER_WEIGHT_FACING };
|
||||
|
||||
enum NodeTangentDirectionType { NODE_TANGENT_RADIAL, NODE_TANGENT_UVMAP };
|
||||
enum NodeTangentDirectionType : uint { NODE_TANGENT_RADIAL, NODE_TANGENT_UVMAP };
|
||||
|
||||
enum NodeTangentAxis { NODE_TANGENT_AXIS_X, NODE_TANGENT_AXIS_Y, NODE_TANGENT_AXIS_Z };
|
||||
enum NodeTangentAxis : uint { NODE_TANGENT_AXIS_X, NODE_TANGENT_AXIS_Y, NODE_TANGENT_AXIS_Z };
|
||||
|
||||
enum NodeNormalMapSpace {
|
||||
enum NodeNormalMapSpace : uint {
|
||||
NODE_NORMAL_MAP_TANGENT,
|
||||
NODE_NORMAL_MAP_OBJECT,
|
||||
NODE_NORMAL_MAP_WORLD,
|
||||
|
|
@ -376,7 +397,7 @@ enum NodeNormalMapFlags {
|
|||
NODE_NORMAL_MAP_FLAG_ORIGINAL = (1 << 4),
|
||||
};
|
||||
|
||||
enum NodeImageProjection {
|
||||
enum NodeImageProjection : uint {
|
||||
NODE_IMAGE_PROJ_FLAT = 0,
|
||||
NODE_IMAGE_PROJ_BOX = 1,
|
||||
NODE_IMAGE_PROJ_SPHERE = 2,
|
||||
|
|
@ -388,12 +409,12 @@ enum NodeImageFlags {
|
|||
NODE_IMAGE_ALPHA_UNASSOCIATE = 2,
|
||||
};
|
||||
|
||||
enum NodeEnvironmentProjection {
|
||||
enum NodeEnvironmentProjection : uint {
|
||||
NODE_ENVIRONMENT_EQUIRECTANGULAR = 0,
|
||||
NODE_ENVIRONMENT_MIRROR_BALL = 1,
|
||||
};
|
||||
|
||||
enum NodeBumpOffset {
|
||||
enum NodeBumpOffset : uint8_t {
|
||||
NODE_BUMP_OFFSET_CENTER,
|
||||
NODE_BUMP_OFFSET_DX,
|
||||
NODE_BUMP_OFFSET_DY,
|
||||
|
|
@ -412,20 +433,20 @@ enum ShaderType {
|
|||
SHADER_TYPE_BUMP,
|
||||
};
|
||||
|
||||
enum NodePrincipledHairModel {
|
||||
enum NodePrincipledHairModel : uint {
|
||||
NODE_PRINCIPLED_HAIR_CHIANG = 0,
|
||||
NODE_PRINCIPLED_HAIR_HUANG = 1,
|
||||
NODE_PRINCIPLED_HAIR_MODEL_NUM,
|
||||
};
|
||||
|
||||
enum NodePrincipledHairParametrization {
|
||||
enum NodePrincipledHairParametrization : uint {
|
||||
NODE_PRINCIPLED_HAIR_REFLECTANCE = 0,
|
||||
NODE_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION = 1,
|
||||
NODE_PRINCIPLED_HAIR_DIRECT_ABSORPTION = 2,
|
||||
NODE_PRINCIPLED_HAIR_PARAMETRIZATION_NUM,
|
||||
};
|
||||
|
||||
enum NodeCombSepColorType {
|
||||
enum NodeCombSepColorType : uint {
|
||||
NODE_COMBSEP_COLOR_RGB,
|
||||
NODE_COMBSEP_COLOR_HSV,
|
||||
NODE_COMBSEP_COLOR_HSL,
|
||||
|
|
@ -433,7 +454,7 @@ enum NodeCombSepColorType {
|
|||
|
||||
/* Closure */
|
||||
|
||||
enum ClosureType {
|
||||
enum ClosureType : uint {
|
||||
/* Special type, flags generic node as a non-BSDF. */
|
||||
CLOSURE_NONE_ID,
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,21 @@
|
|||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Stack */
|
||||
/* Stack Load */
|
||||
|
||||
ccl_device_inline float stack_load_float(const ccl_private float *stack, const uint a)
|
||||
{
|
||||
kernel_assert(a < SVM_STACK_SIZE);
|
||||
|
||||
return stack[a];
|
||||
}
|
||||
|
||||
ccl_device_inline float stack_load_float_default(const ccl_private float *stack,
|
||||
const uint a,
|
||||
const float value)
|
||||
{
|
||||
return (a == (uint)SVM_STACK_INVALID) ? value : stack_load_float(stack, a);
|
||||
}
|
||||
|
||||
ccl_device_inline float3 stack_load_float3(const ccl_private float *stack, const uint a)
|
||||
{
|
||||
|
|
@ -28,38 +42,11 @@ ccl_device_inline float3 stack_load_float3_default(const ccl_private float *stac
|
|||
return (a == (uint)SVM_STACK_INVALID) ? value : stack_load_float3(stack, a);
|
||||
}
|
||||
|
||||
ccl_device_inline void stack_store_float3(ccl_private float *stack, const uint a, const float3 f)
|
||||
{
|
||||
kernel_assert(a + 2 < SVM_STACK_SIZE);
|
||||
copy_v3_v3(stack + a, f);
|
||||
}
|
||||
|
||||
ccl_device_inline float stack_load_float(const ccl_private float *stack, const uint a)
|
||||
ccl_device_inline int stack_load_int(const ccl_private float *stack, const uint a)
|
||||
{
|
||||
kernel_assert(a < SVM_STACK_SIZE);
|
||||
|
||||
return stack[a];
|
||||
}
|
||||
|
||||
ccl_device_inline float stack_load_float_default(const ccl_private float *stack,
|
||||
const uint a,
|
||||
const uint value)
|
||||
{
|
||||
return (a == (uint)SVM_STACK_INVALID) ? __uint_as_float(value) : stack_load_float(stack, a);
|
||||
}
|
||||
|
||||
ccl_device_inline float stack_load_float_default(const ccl_private float *stack,
|
||||
const uint a,
|
||||
const float value)
|
||||
{
|
||||
return (a == (uint)SVM_STACK_INVALID) ? value : stack_load_float(stack, a);
|
||||
}
|
||||
|
||||
ccl_device_inline void stack_store_float(ccl_private float *stack, const uint a, const float f)
|
||||
{
|
||||
kernel_assert(a < SVM_STACK_SIZE);
|
||||
|
||||
stack[a] = f;
|
||||
return __float_as_int(stack[a]);
|
||||
}
|
||||
|
||||
/* Type-based stack load. T can be float, float3, dual1, or dual3.
|
||||
|
|
@ -90,6 +77,83 @@ ccl_device_template_spec dual3 stack_load(const ccl_private float *stack, const
|
|||
stack_load_float3(stack, a + 6)};
|
||||
}
|
||||
|
||||
/* Load from SVMInputFloat and SVMInputFloat3. With template versions to support duals
|
||||
* for loading derivatives from adjacent stack slots. */
|
||||
|
||||
ccl_device_inline float stack_load(const ccl_private float *ccl_restrict stack,
|
||||
const SVMInputFloat v)
|
||||
{
|
||||
if ((v.bits >> 8) == (SVM_INPUT_STACK_OFFSET_MASK >> 8)) {
|
||||
return stack_load_float(stack, v.bits & 0xFFu);
|
||||
}
|
||||
return __uint_as_float(v.bits);
|
||||
}
|
||||
|
||||
ccl_device_inline float3 stack_load(const ccl_private float *ccl_restrict stack,
|
||||
const SVMInputFloat3 v)
|
||||
{
|
||||
if ((v.x.bits >> 8) == (SVM_INPUT_STACK_OFFSET_MASK >> 8)) {
|
||||
return stack_load_float3(stack, v.x.bits & 0xFFu);
|
||||
}
|
||||
return make_float3(
|
||||
__uint_as_float(v.x.bits), __uint_as_float(v.y.bits), __uint_as_float(v.z.bits));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ccl_device_inline T stack_load(const ccl_private float *stack, const SVMInputFloat v);
|
||||
|
||||
ccl_device_template_spec float stack_load(const ccl_private float *stack, const SVMInputFloat v)
|
||||
{
|
||||
return stack_load(stack, v);
|
||||
}
|
||||
|
||||
ccl_device_template_spec dual1 stack_load(const ccl_private float *stack, const SVMInputFloat v)
|
||||
{
|
||||
if ((v.bits >> 8) == (SVM_INPUT_STACK_OFFSET_MASK >> 8)) {
|
||||
return stack_load<dual1>(stack, v.bits & 0xFFu);
|
||||
}
|
||||
return dual1(__uint_as_float(v.bits));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ccl_device_inline T stack_load(const ccl_private float *stack, const SVMInputFloat3 v);
|
||||
|
||||
ccl_device_template_spec float3 stack_load(const ccl_private float *stack, const SVMInputFloat3 v)
|
||||
{
|
||||
return stack_load(stack, v);
|
||||
}
|
||||
|
||||
ccl_device_template_spec dual3 stack_load(const ccl_private float *stack, const SVMInputFloat3 v)
|
||||
{
|
||||
if ((v.x.bits >> 8) == (SVM_INPUT_STACK_OFFSET_MASK >> 8)) {
|
||||
return stack_load<dual3>(stack, v.x.bits & 0xFFu);
|
||||
}
|
||||
return dual3(make_float3(
|
||||
__uint_as_float(v.x.bits), __uint_as_float(v.y.bits), __uint_as_float(v.z.bits)));
|
||||
}
|
||||
|
||||
/* Stack Store */
|
||||
|
||||
ccl_device_inline void stack_store_float(ccl_private float *stack, const uint a, const float f)
|
||||
{
|
||||
kernel_assert(a < SVM_STACK_SIZE);
|
||||
|
||||
stack[a] = f;
|
||||
}
|
||||
|
||||
ccl_device_inline void stack_store_float3(ccl_private float *stack, const uint a, const float3 f)
|
||||
{
|
||||
kernel_assert(a + 2 < SVM_STACK_SIZE);
|
||||
copy_v3_v3(stack + a, f);
|
||||
}
|
||||
|
||||
ccl_device_inline void stack_store_int(ccl_private float *stack, const uint a, const int i)
|
||||
{
|
||||
kernel_assert(a < SVM_STACK_SIZE);
|
||||
|
||||
stack[a] = __int_as_float(i);
|
||||
}
|
||||
|
||||
/* Type-based stack store. Overloaded for plain and dual types.
|
||||
* For dual types, derivatives are stored in adjacent stack slots. */
|
||||
|
||||
|
|
@ -117,26 +181,7 @@ ccl_device_inline void stack_store(ccl_private float *stack, const uint a, const
|
|||
stack_store_float3(stack, a + 6, f.dy);
|
||||
}
|
||||
|
||||
ccl_device_inline int stack_load_int(const ccl_private float *stack, const uint a)
|
||||
{
|
||||
kernel_assert(a < SVM_STACK_SIZE);
|
||||
|
||||
return __float_as_int(stack[a]);
|
||||
}
|
||||
|
||||
ccl_device_inline int stack_load_int_default(ccl_private float *stack,
|
||||
const uint a,
|
||||
const uint value)
|
||||
{
|
||||
return (a == (uint)SVM_STACK_INVALID) ? (int)value : stack_load_int(stack, a);
|
||||
}
|
||||
|
||||
ccl_device_inline void stack_store_int(ccl_private float *stack, const uint a, const int i)
|
||||
{
|
||||
kernel_assert(a < SVM_STACK_SIZE);
|
||||
|
||||
stack[a] = __int_as_float(i);
|
||||
}
|
||||
/* Stack Utility */
|
||||
|
||||
ccl_device_inline bool stack_valid(const uint a)
|
||||
{
|
||||
|
|
@ -145,62 +190,29 @@ ccl_device_inline bool stack_valid(const uint a)
|
|||
|
||||
/* Reading Nodes */
|
||||
|
||||
ccl_device_inline uint4 read_node(KernelGlobals kg, ccl_private int *const offset)
|
||||
/* Read a typed node struct directly from the SVM bytecode stream. The struct T must be a
|
||||
* multiple of sizeof(uint) and its memory layout must match the bytecode encoding. Returns
|
||||
* a const reference into the bytecode array and advances the offset past the struct. */
|
||||
template<typename T>
|
||||
ccl_device_inline const ccl_global T &svm_node_get(KernelGlobals kg, ccl_private int *const offset)
|
||||
{
|
||||
uint4 node = kernel_data_fetch(svm_nodes, *offset);
|
||||
(*offset)++;
|
||||
static_assert(alignof(T) <= alignof(uint));
|
||||
static_assert(sizeof(T) % sizeof(uint) == 0);
|
||||
const ccl_global T &node = *reinterpret_cast<const ccl_global T *>(
|
||||
&kernel_data_fetch(svm_nodes, *offset));
|
||||
*offset += sizeof(T) / sizeof(uint);
|
||||
return node;
|
||||
}
|
||||
|
||||
ccl_device_inline float4 read_node_float(KernelGlobals kg, ccl_private int *const offset)
|
||||
ccl_device_inline float4 svm_node_get_data_float4(KernelGlobals kg, const int offset)
|
||||
{
|
||||
const uint4 node = kernel_data_fetch(svm_nodes, *offset);
|
||||
const float4 f = make_float4(__uint_as_float(node.x),
|
||||
__uint_as_float(node.y),
|
||||
__uint_as_float(node.z),
|
||||
__uint_as_float(node.w));
|
||||
(*offset)++;
|
||||
return f;
|
||||
return make_float4(__uint_as_float(kernel_data_fetch(svm_nodes, offset)),
|
||||
__uint_as_float(kernel_data_fetch(svm_nodes, offset + 1)),
|
||||
__uint_as_float(kernel_data_fetch(svm_nodes, offset + 2)),
|
||||
__uint_as_float(kernel_data_fetch(svm_nodes, offset + 3)));
|
||||
}
|
||||
|
||||
ccl_device_inline float4 fetch_node_float(KernelGlobals kg, const int offset)
|
||||
{
|
||||
const uint4 node = kernel_data_fetch(svm_nodes, offset);
|
||||
return make_float4(__uint_as_float(node.x),
|
||||
__uint_as_float(node.y),
|
||||
__uint_as_float(node.z),
|
||||
__uint_as_float(node.w));
|
||||
}
|
||||
|
||||
ccl_device_forceinline void svm_unpack_node_uchar2(const uint i,
|
||||
ccl_private uint *x,
|
||||
ccl_private uint *y)
|
||||
{
|
||||
*x = (i & 0xFF);
|
||||
*y = ((i >> 8) & 0xFF);
|
||||
}
|
||||
|
||||
ccl_device_forceinline void svm_unpack_node_uchar3(const uint i,
|
||||
ccl_private uint *x,
|
||||
ccl_private uint *y,
|
||||
ccl_private uint *z)
|
||||
{
|
||||
*x = (i & 0xFF);
|
||||
*y = ((i >> 8) & 0xFF);
|
||||
*z = ((i >> 16) & 0xFF);
|
||||
}
|
||||
|
||||
ccl_device_forceinline void svm_unpack_node_uchar4(const uint i,
|
||||
ccl_private uint *x,
|
||||
ccl_private uint *y,
|
||||
ccl_private uint *z,
|
||||
ccl_private uint *w)
|
||||
{
|
||||
*x = (i & 0xFF);
|
||||
*y = ((i >> 8) & 0xFF);
|
||||
*z = ((i >> 16) & 0xFF);
|
||||
*w = ((i >> 24) & 0xFF);
|
||||
}
|
||||
/* Shading Helpers */
|
||||
|
||||
ccl_device_forceinline float3 dPdx(const ccl_private ShaderData *sd)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
|
@ -11,28 +12,19 @@ CCL_NAMESPACE_BEGIN
|
|||
/* Value Nodes */
|
||||
|
||||
template<typename FloatType>
|
||||
ccl_device void svm_node_value_f(ccl_private float *stack,
|
||||
const uint ivalue,
|
||||
const uint out_offset)
|
||||
ccl_device void svm_node_value_f(ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeValueF &ccl_restrict node)
|
||||
{
|
||||
/* Derivative of a constant is zero. */
|
||||
stack_store(stack, out_offset, FloatType(__uint_as_float(ivalue)));
|
||||
stack_store(stack, node.out_offset, FloatType(node.value));
|
||||
}
|
||||
|
||||
template<typename Float3Type>
|
||||
ccl_device int svm_node_value_v(KernelGlobals kg,
|
||||
ccl_private float *stack,
|
||||
const uint out_offset,
|
||||
int offset)
|
||||
ccl_device void svm_node_value_v(ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeValueV &ccl_restrict node)
|
||||
{
|
||||
/* read extra data */
|
||||
const uint4 node1 = read_node(kg, &offset);
|
||||
const float3 p = make_float3(
|
||||
__uint_as_float(node1.y), __uint_as_float(node1.z), __uint_as_float(node1.w));
|
||||
|
||||
/* Derivative of a constant is zero. */
|
||||
stack_store(stack, out_offset, Float3Type(p));
|
||||
return offset;
|
||||
stack_store(stack, node.out_offset, Float3Type(node.value));
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -4,40 +4,26 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Vector Rotate */
|
||||
|
||||
ccl_device_noinline void svm_node_vector_rotate(ccl_private float *stack,
|
||||
const uint input_stack_offsets,
|
||||
const uint axis_stack_offsets,
|
||||
const uint result_stack_offset)
|
||||
ccl_device_noinline void svm_node_vector_rotate(
|
||||
ccl_private float *ccl_restrict stack, const ccl_global SVMNodeVectorRotate &ccl_restrict node)
|
||||
{
|
||||
uint type;
|
||||
uint vector_stack_offset;
|
||||
uint rotation_stack_offset;
|
||||
uint center_stack_offset;
|
||||
uint axis_stack_offset;
|
||||
uint angle_stack_offset;
|
||||
uint invert;
|
||||
if (stack_valid(node.result_offset)) {
|
||||
|
||||
svm_unpack_node_uchar4(
|
||||
input_stack_offsets, &type, &vector_stack_offset, &rotation_stack_offset, &invert);
|
||||
svm_unpack_node_uchar3(
|
||||
axis_stack_offsets, ¢er_stack_offset, &axis_stack_offset, &angle_stack_offset);
|
||||
|
||||
if (stack_valid(result_stack_offset)) {
|
||||
|
||||
const float3 vector = stack_load_float3(stack, vector_stack_offset);
|
||||
const float3 center = stack_load_float3(stack, center_stack_offset);
|
||||
const float3 vector = stack_load(stack, node.vector);
|
||||
const float3 center = stack_load(stack, node.center);
|
||||
float3 result = make_float3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
if (type == NODE_VECTOR_ROTATE_TYPE_EULER_XYZ) {
|
||||
const float3 rotation = stack_load_float3(stack, rotation_stack_offset); // Default XYZ.
|
||||
if (node.rotate_type == NODE_VECTOR_ROTATE_TYPE_EULER_XYZ) {
|
||||
const float3 rotation = stack_load(stack, node.rotation); // Default XYZ.
|
||||
const Transform rotationTransform = euler_to_transform(rotation);
|
||||
if (invert) {
|
||||
if (node.invert) {
|
||||
result = transform_direction_transposed(&rotationTransform, vector - center) + center;
|
||||
}
|
||||
else {
|
||||
|
|
@ -47,7 +33,7 @@ ccl_device_noinline void svm_node_vector_rotate(ccl_private float *stack,
|
|||
else {
|
||||
float3 axis;
|
||||
float axis_length;
|
||||
switch (type) {
|
||||
switch (node.rotate_type) {
|
||||
case NODE_VECTOR_ROTATE_TYPE_AXIS_X:
|
||||
axis = make_float3(1.0f, 0.0f, 0.0f);
|
||||
axis_length = 1.0f;
|
||||
|
|
@ -61,18 +47,18 @@ ccl_device_noinline void svm_node_vector_rotate(ccl_private float *stack,
|
|||
axis_length = 1.0f;
|
||||
break;
|
||||
default:
|
||||
axis = stack_load_float3(stack, axis_stack_offset);
|
||||
axis = stack_load(stack, node.axis);
|
||||
axis_length = len(axis);
|
||||
break;
|
||||
}
|
||||
float angle = stack_load_float(stack, angle_stack_offset);
|
||||
angle = invert ? -angle : angle;
|
||||
float angle = stack_load(stack, node.angle);
|
||||
angle = node.invert ? -angle : angle;
|
||||
result = (axis_length != 0.0f) ?
|
||||
rotate_around_axis(vector - center, axis / axis_length, angle) + center :
|
||||
vector;
|
||||
}
|
||||
|
||||
stack_store_float3(stack, result_stack_offset, result);
|
||||
stack_store_float3(stack, node.result_offset, result);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,31 +5,24 @@
|
|||
#pragma once
|
||||
|
||||
#include "kernel/geom/object.h"
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Vector Transform */
|
||||
|
||||
ccl_device_noinline void svm_node_vector_transform(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint4 node)
|
||||
ccl_device_noinline void svm_node_vector_transform(
|
||||
KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeVectorTransform &ccl_restrict node)
|
||||
{
|
||||
uint itype;
|
||||
uint ifrom;
|
||||
uint ito;
|
||||
uint vector_in;
|
||||
uint vector_out;
|
||||
float3 in = stack_load(stack, node.vector_in);
|
||||
|
||||
svm_unpack_node_uchar3(node.y, &itype, &ifrom, &ito);
|
||||
svm_unpack_node_uchar2(node.z, &vector_in, &vector_out);
|
||||
|
||||
float3 in = stack_load_float3(stack, vector_in);
|
||||
|
||||
const NodeVectorTransformType type = (NodeVectorTransformType)itype;
|
||||
const NodeVectorTransformConvertSpace from = (NodeVectorTransformConvertSpace)ifrom;
|
||||
const NodeVectorTransformConvertSpace to = (NodeVectorTransformConvertSpace)ito;
|
||||
const NodeVectorTransformType type = node.transform_type;
|
||||
const NodeVectorTransformConvertSpace from = node.convert_from;
|
||||
const NodeVectorTransformConvertSpace to = node.convert_to;
|
||||
|
||||
Transform tfm;
|
||||
const bool is_object = (sd->object != OBJECT_NONE);
|
||||
|
|
@ -122,8 +115,8 @@ ccl_device_noinline void svm_node_vector_transform(KernelGlobals kg,
|
|||
}
|
||||
|
||||
/* Output */
|
||||
if (stack_valid(vector_out)) {
|
||||
stack_store_float3(stack, vector_out, in);
|
||||
if (stack_valid(node.vector_out_offset)) {
|
||||
stack_store_float3(stack, node.vector_out_offset, in);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "kernel/geom/attribute.h"
|
||||
#include "kernel/geom/primitive.h"
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
#include "util/math_base.h"
|
||||
|
||||
|
|
@ -13,73 +14,82 @@ CCL_NAMESPACE_BEGIN
|
|||
|
||||
ccl_device_noinline void svm_node_vertex_color(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint4 node)
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeVertexColor &ccl_restrict
|
||||
node)
|
||||
{
|
||||
uint layer_id;
|
||||
uint color_offset;
|
||||
uint alpha_offset;
|
||||
svm_unpack_node_uchar3(node.y, &layer_id, &color_offset, &alpha_offset);
|
||||
float3 color;
|
||||
float alpha;
|
||||
|
||||
const AttributeDescriptor descriptor = find_attribute(kg, sd, layer_id);
|
||||
const AttributeDescriptor descriptor = find_attribute(kg, sd, node.layer_id);
|
||||
if (descriptor.offset != ATTR_STD_NOT_FOUND) {
|
||||
if (descriptor.type == NODE_ATTR_FLOAT4 || descriptor.type == NODE_ATTR_RGBA) {
|
||||
const float4 vertex_color = primitive_surface_attribute<float4>(kg, sd, descriptor);
|
||||
stack_store_float3(stack, color_offset, make_float3(vertex_color));
|
||||
stack_store_float(stack, alpha_offset, vertex_color.w);
|
||||
color = make_float3(vertex_color);
|
||||
alpha = vertex_color.w;
|
||||
}
|
||||
else {
|
||||
const float3 vertex_color = primitive_surface_attribute<float3>(kg, sd, descriptor);
|
||||
stack_store_float3(stack, color_offset, vertex_color);
|
||||
stack_store_float(stack, alpha_offset, 1.0f);
|
||||
color = primitive_surface_attribute<float3>(kg, sd, descriptor);
|
||||
alpha = 1.0f;
|
||||
}
|
||||
}
|
||||
else {
|
||||
stack_store_float3(stack, color_offset, make_float3(0.0f, 0.0f, 0.0f));
|
||||
stack_store_float(stack, alpha_offset, 0.0f);
|
||||
color = make_float3(0.0f, 0.0f, 0.0f);
|
||||
alpha = 0.0f;
|
||||
}
|
||||
|
||||
if (stack_valid(node.color_offset)) {
|
||||
stack_store_float3(stack, node.color_offset, color);
|
||||
}
|
||||
if (stack_valid(node.alpha_offset)) {
|
||||
stack_store_float(stack, node.alpha_offset, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device_noinline void svm_node_vertex_color_derivative(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint4 node)
|
||||
ccl_device_noinline void svm_node_vertex_color_derivative(
|
||||
KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeVertexColor &ccl_restrict node)
|
||||
{
|
||||
uint layer_id;
|
||||
uint color_offset;
|
||||
uint alpha_offset;
|
||||
uint bump_offset;
|
||||
svm_unpack_node_uchar4(node.y, &layer_id, &color_offset, &alpha_offset, &bump_offset);
|
||||
const float bump_filter_width = __uint_as_float(node.z);
|
||||
float3 color;
|
||||
float alpha;
|
||||
|
||||
const AttributeDescriptor descriptor = find_attribute(kg, sd, layer_id);
|
||||
const AttributeDescriptor descriptor = find_attribute(kg, sd, node.layer_id);
|
||||
if (descriptor.offset != ATTR_STD_NOT_FOUND) {
|
||||
if (descriptor.type == NODE_ATTR_FLOAT4 || descriptor.type == NODE_ATTR_RGBA) {
|
||||
dual4 vertex_color = primitive_surface_attribute<dual4>(kg, sd, descriptor);
|
||||
if (bump_offset == NODE_BUMP_OFFSET_DX) {
|
||||
vertex_color.val += vertex_color.dx * bump_filter_width;
|
||||
if (node.bump_offset == NODE_BUMP_OFFSET_DX) {
|
||||
vertex_color.val += vertex_color.dx * node.bump_filter_width;
|
||||
}
|
||||
else if (bump_offset == NODE_BUMP_OFFSET_DY) {
|
||||
vertex_color.val += vertex_color.dy * bump_filter_width;
|
||||
else if (node.bump_offset == NODE_BUMP_OFFSET_DY) {
|
||||
vertex_color.val += vertex_color.dy * node.bump_filter_width;
|
||||
}
|
||||
stack_store_float3(stack, color_offset, make_float3(vertex_color.val));
|
||||
stack_store_float(stack, alpha_offset, vertex_color.val.w);
|
||||
color = make_float3(vertex_color.val);
|
||||
alpha = vertex_color.val.w;
|
||||
}
|
||||
else {
|
||||
dual3 vertex_color = primitive_surface_attribute<dual3>(kg, sd, descriptor);
|
||||
if (bump_offset == NODE_BUMP_OFFSET_DX) {
|
||||
vertex_color.val += vertex_color.dx * bump_filter_width;
|
||||
if (node.bump_offset == NODE_BUMP_OFFSET_DX) {
|
||||
vertex_color.val += vertex_color.dx * node.bump_filter_width;
|
||||
}
|
||||
else if (bump_offset == NODE_BUMP_OFFSET_DY) {
|
||||
vertex_color.val += vertex_color.dy * bump_filter_width;
|
||||
else if (node.bump_offset == NODE_BUMP_OFFSET_DY) {
|
||||
vertex_color.val += vertex_color.dy * node.bump_filter_width;
|
||||
}
|
||||
stack_store_float3(stack, color_offset, vertex_color.val);
|
||||
stack_store_float(stack, alpha_offset, 1.0f);
|
||||
color = vertex_color.val;
|
||||
alpha = 1.0f;
|
||||
}
|
||||
}
|
||||
else {
|
||||
stack_store_float3(stack, color_offset, make_float3(0.0f, 0.0f, 0.0f));
|
||||
stack_store_float(stack, alpha_offset, 0.0f);
|
||||
color = make_float3(0.0f, 0.0f, 0.0f);
|
||||
alpha = 0.0f;
|
||||
}
|
||||
|
||||
if (stack_valid(node.color_offset)) {
|
||||
stack_store_float3(stack, node.color_offset, color);
|
||||
}
|
||||
if (stack_valid(node.alpha_offset)) {
|
||||
stack_store_float(stack, node.alpha_offset, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
#include "util/hash.h"
|
||||
|
||||
|
|
@ -1035,95 +1036,51 @@ ccl_device float fractal_voronoi_distance_to_edge(const ccl_private VoronoiParam
|
|||
return distance;
|
||||
}
|
||||
|
||||
ccl_device void svm_voronoi_output(const uint4 stack_offsets,
|
||||
ccl_private float *stack,
|
||||
ccl_device void svm_voronoi_output(ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeTexVoronoi &ccl_restrict node,
|
||||
const float distance,
|
||||
const float3 color,
|
||||
const float3 position,
|
||||
const float w,
|
||||
const float radius)
|
||||
{
|
||||
uint distance_stack_offset;
|
||||
uint color_stack_offset;
|
||||
uint position_stack_offset;
|
||||
uint w_out_stack_offset;
|
||||
uint radius_stack_offset;
|
||||
uint unused;
|
||||
|
||||
svm_unpack_node_uchar4(
|
||||
stack_offsets.z, &unused, &unused, &distance_stack_offset, &color_stack_offset);
|
||||
svm_unpack_node_uchar3(
|
||||
stack_offsets.w, &position_stack_offset, &w_out_stack_offset, &radius_stack_offset);
|
||||
|
||||
if (stack_valid(distance_stack_offset)) {
|
||||
stack_store_float(stack, distance_stack_offset, distance);
|
||||
if (stack_valid(node.distance_offset)) {
|
||||
stack_store_float(stack, node.distance_offset, distance);
|
||||
}
|
||||
if (stack_valid(color_stack_offset)) {
|
||||
stack_store_float3(stack, color_stack_offset, color);
|
||||
if (stack_valid(node.color_offset)) {
|
||||
stack_store_float3(stack, node.color_offset, color);
|
||||
}
|
||||
if (stack_valid(position_stack_offset)) {
|
||||
stack_store_float3(stack, position_stack_offset, position);
|
||||
if (stack_valid(node.position_offset)) {
|
||||
stack_store_float3(stack, node.position_offset, position);
|
||||
}
|
||||
if (stack_valid(w_out_stack_offset)) {
|
||||
stack_store_float(stack, w_out_stack_offset, w);
|
||||
if (stack_valid(node.w_out_offset)) {
|
||||
stack_store_float(stack, node.w_out_offset, w);
|
||||
}
|
||||
if (stack_valid(radius_stack_offset)) {
|
||||
stack_store_float(stack, radius_stack_offset, radius);
|
||||
if (stack_valid(node.radius_offset)) {
|
||||
stack_store_float(stack, node.radius_offset, radius);
|
||||
}
|
||||
}
|
||||
|
||||
template<uint node_feature_mask>
|
||||
ccl_device_noinline int svm_node_tex_voronoi(KernelGlobals kg,
|
||||
ccl_private float *stack,
|
||||
const uint dimensions,
|
||||
const uint feature,
|
||||
const uint metric,
|
||||
int offset)
|
||||
ccl_device_noinline void svm_node_tex_voronoi(
|
||||
ccl_private float *ccl_restrict stack, const ccl_global SVMNodeTexVoronoi &ccl_restrict node)
|
||||
{
|
||||
/* Read node defaults and stack offsets. */
|
||||
const uint4 stack_offsets = read_node(kg, &offset);
|
||||
const uint4 defaults1 = read_node(kg, &offset);
|
||||
const uint4 defaults2 = read_node(kg, &offset);
|
||||
|
||||
uint coord_stack_offset;
|
||||
uint w_stack_offset;
|
||||
uint scale_stack_offset;
|
||||
uint detail_stack_offset;
|
||||
uint roughness_stack_offset;
|
||||
uint lacunarity_stack_offset;
|
||||
uint smoothness_stack_offset;
|
||||
uint exponent_stack_offset;
|
||||
uint randomness_stack_offset;
|
||||
uint normalize;
|
||||
|
||||
svm_unpack_node_uchar4(stack_offsets.x,
|
||||
&coord_stack_offset,
|
||||
&w_stack_offset,
|
||||
&scale_stack_offset,
|
||||
&detail_stack_offset);
|
||||
svm_unpack_node_uchar4(stack_offsets.y,
|
||||
&roughness_stack_offset,
|
||||
&lacunarity_stack_offset,
|
||||
&smoothness_stack_offset,
|
||||
&exponent_stack_offset);
|
||||
svm_unpack_node_uchar2(stack_offsets.z, &randomness_stack_offset, &normalize);
|
||||
|
||||
/* Read from stack. */
|
||||
float3 coord = stack_load_float3(stack, coord_stack_offset);
|
||||
float w = stack_load_float_default(stack, w_stack_offset, defaults1.x);
|
||||
float3 coord = stack_load_float3(stack, node.coord);
|
||||
float w = stack_load(stack, node.w);
|
||||
|
||||
VoronoiParams params;
|
||||
params.feature = (NodeVoronoiFeature)feature;
|
||||
params.metric = (NodeVoronoiDistanceMetric)metric;
|
||||
params.scale = stack_load_float_default(stack, scale_stack_offset, defaults1.y);
|
||||
params.detail = stack_load_float_default(stack, detail_stack_offset, defaults1.z);
|
||||
params.roughness = stack_load_float_default(stack, roughness_stack_offset, defaults1.w);
|
||||
params.lacunarity = stack_load_float_default(stack, lacunarity_stack_offset, defaults2.x);
|
||||
params.smoothness = stack_load_float_default(stack, smoothness_stack_offset, defaults2.y);
|
||||
params.exponent = stack_load_float_default(stack, exponent_stack_offset, defaults2.z);
|
||||
params.randomness = stack_load_float_default(stack, randomness_stack_offset, defaults2.w);
|
||||
params.feature = node.feature;
|
||||
params.metric = node.metric;
|
||||
params.scale = stack_load(stack, node.scale);
|
||||
params.detail = stack_load(stack, node.detail);
|
||||
params.roughness = stack_load(stack, node.roughness);
|
||||
params.lacunarity = stack_load(stack, node.lacunarity);
|
||||
params.smoothness = stack_load(stack, node.smoothness);
|
||||
params.exponent = stack_load(stack, node.exponent);
|
||||
params.randomness = stack_load(stack, node.randomness);
|
||||
params.max_distance = 0.0f;
|
||||
params.normalize = normalize;
|
||||
params.normalize = node.normalize;
|
||||
|
||||
params.detail = clamp(params.detail, 0.0f, 15.0f);
|
||||
params.roughness = clamp(params.roughness, 0.0f, 1.0f);
|
||||
|
|
@ -1138,7 +1095,7 @@ ccl_device_noinline int svm_node_tex_voronoi(KernelGlobals kg,
|
|||
case NODE_VORONOI_DISTANCE_TO_EDGE: {
|
||||
float distance = 0.0f;
|
||||
params.max_distance = 0.5f + 0.5f * params.randomness;
|
||||
switch (dimensions) {
|
||||
switch (node.dimensions) {
|
||||
case 1:
|
||||
distance = fractal_voronoi_distance_to_edge(params, w);
|
||||
break;
|
||||
|
|
@ -1156,12 +1113,12 @@ ccl_device_noinline int svm_node_tex_voronoi(KernelGlobals kg,
|
|||
break;
|
||||
}
|
||||
|
||||
svm_voronoi_output(stack_offsets, stack, distance, zero_float3(), zero_float3(), 0.0f, 0.0f);
|
||||
svm_voronoi_output(stack, node, distance, zero_float3(), zero_float3(), 0.0f, 0.0f);
|
||||
break;
|
||||
}
|
||||
case NODE_VORONOI_N_SPHERE_RADIUS: {
|
||||
float radius = 0.0f;
|
||||
switch (dimensions) {
|
||||
switch (node.dimensions) {
|
||||
case 1:
|
||||
radius = voronoi_n_sphere_radius(params, w);
|
||||
break;
|
||||
|
|
@ -1179,12 +1136,12 @@ ccl_device_noinline int svm_node_tex_voronoi(KernelGlobals kg,
|
|||
break;
|
||||
}
|
||||
|
||||
svm_voronoi_output(stack_offsets, stack, 0.0f, zero_float3(), zero_float3(), 0.0f, radius);
|
||||
svm_voronoi_output(stack, node, 0.0f, zero_float3(), zero_float3(), 0.0f, radius);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
VoronoiOutput output;
|
||||
switch (dimensions) {
|
||||
switch (node.dimensions) {
|
||||
case 1:
|
||||
params.max_distance = (0.5f + 0.5f * params.randomness) *
|
||||
((params.feature == NODE_VORONOI_F2) ? 2.0f : 1.0f);
|
||||
|
|
@ -1231,8 +1188,8 @@ ccl_device_noinline int svm_node_tex_voronoi(KernelGlobals kg,
|
|||
break;
|
||||
}
|
||||
|
||||
svm_voronoi_output(stack_offsets,
|
||||
stack,
|
||||
svm_voronoi_output(stack,
|
||||
node,
|
||||
output.distance,
|
||||
output.color,
|
||||
make_float3(output.position),
|
||||
|
|
@ -1241,8 +1198,6 @@ ccl_device_noinline int svm_node_tex_voronoi(KernelGlobals kg,
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "kernel/svm/fractal_noise.h"
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
|
@ -75,49 +76,21 @@ ccl_device_noinline_cpu float svm_wave(NodeWaveType type,
|
|||
return fabsf(n - floorf(n + 0.5f)) * 2.0f;
|
||||
}
|
||||
|
||||
ccl_device_noinline int svm_node_tex_wave(KernelGlobals kg,
|
||||
ccl_private float *stack,
|
||||
const uint4 node,
|
||||
int offset)
|
||||
ccl_device_noinline void svm_node_tex_wave(ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeTexWave &ccl_restrict node)
|
||||
{
|
||||
const uint4 node2 = read_node(kg, &offset);
|
||||
const uint4 node3 = read_node(kg, &offset);
|
||||
const float3 co = stack_load_float3(stack, node.co);
|
||||
const float scale = stack_load(stack, node.scale);
|
||||
const float distortion = stack_load(stack, node.distortion);
|
||||
const float detail = stack_load(stack, node.detail);
|
||||
const float dscale = stack_load(stack, node.dscale);
|
||||
const float droughness = stack_load(stack, node.droughness);
|
||||
const float phase = stack_load(stack, node.phase);
|
||||
|
||||
/* RNA properties */
|
||||
uint type_offset;
|
||||
uint bands_dir_offset;
|
||||
uint rings_dir_offset;
|
||||
uint profile_offset;
|
||||
/* Inputs, Outputs */
|
||||
uint co_offset;
|
||||
uint scale_offset;
|
||||
uint distortion_offset;
|
||||
uint detail_offset;
|
||||
uint dscale_offset;
|
||||
uint droughness_offset;
|
||||
uint phase_offset;
|
||||
uint color_offset;
|
||||
uint fac_offset;
|
||||
|
||||
svm_unpack_node_uchar4(
|
||||
node.y, &type_offset, &bands_dir_offset, &rings_dir_offset, &profile_offset);
|
||||
svm_unpack_node_uchar3(node.z, &co_offset, &scale_offset, &distortion_offset);
|
||||
svm_unpack_node_uchar4(
|
||||
node.w, &detail_offset, &dscale_offset, &droughness_offset, &phase_offset);
|
||||
svm_unpack_node_uchar2(node2.x, &color_offset, &fac_offset);
|
||||
|
||||
const float3 co = stack_load_float3(stack, co_offset);
|
||||
const float scale = stack_load_float_default(stack, scale_offset, node2.y);
|
||||
const float distortion = stack_load_float_default(stack, distortion_offset, node2.z);
|
||||
const float detail = stack_load_float_default(stack, detail_offset, node2.w);
|
||||
const float dscale = stack_load_float_default(stack, dscale_offset, node3.x);
|
||||
const float droughness = stack_load_float_default(stack, droughness_offset, node3.y);
|
||||
const float phase = stack_load_float_default(stack, phase_offset, node3.z);
|
||||
|
||||
const float f = svm_wave((NodeWaveType)type_offset,
|
||||
(NodeWaveBandsDirection)bands_dir_offset,
|
||||
(NodeWaveRingsDirection)rings_dir_offset,
|
||||
(NodeWaveProfile)profile_offset,
|
||||
const float f = svm_wave(node.wave_type,
|
||||
node.bands_direction,
|
||||
node.rings_direction,
|
||||
node.profile,
|
||||
co * scale,
|
||||
distortion,
|
||||
detail,
|
||||
|
|
@ -125,13 +98,12 @@ ccl_device_noinline int svm_node_tex_wave(KernelGlobals kg,
|
|||
droughness,
|
||||
phase);
|
||||
|
||||
if (stack_valid(fac_offset)) {
|
||||
stack_store_float(stack, fac_offset, f);
|
||||
if (stack_valid(node.fac_offset)) {
|
||||
stack_store_float(stack, node.fac_offset, f);
|
||||
}
|
||||
if (stack_valid(color_offset)) {
|
||||
stack_store_float3(stack, color_offset, make_float3(f, f, f));
|
||||
if (stack_valid(node.color_offset)) {
|
||||
stack_store_float3(stack, node.color_offset, make_float3(f, f, f));
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "kernel/svm/math_util.h"
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
|
||||
#include "kernel/util/colorspace.h"
|
||||
|
|
@ -17,11 +18,10 @@ CCL_NAMESPACE_BEGIN
|
|||
/* Wavelength to RGB */
|
||||
|
||||
ccl_device_noinline void svm_node_wavelength(KernelGlobals kg,
|
||||
ccl_private float *stack,
|
||||
const uint wavelength,
|
||||
const uint color_out)
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeWavelength &ccl_restrict node)
|
||||
{
|
||||
const float lambda_nm = stack_load_float(stack, wavelength);
|
||||
const float lambda_nm = stack_load(stack, node.wavelength);
|
||||
|
||||
float3 color = svm_math_wavelength_color_xyz(lambda_nm);
|
||||
color = xyz_to_rgb(kg, color);
|
||||
|
|
@ -30,7 +30,7 @@ ccl_device_noinline void svm_node_wavelength(KernelGlobals kg,
|
|||
/* Clamp to zero if values are smaller */
|
||||
color = max(color, make_float3(0.0f, 0.0f, 0.0f));
|
||||
|
||||
stack_store_float3(stack, color_out, color);
|
||||
stack_store_float3(stack, node.color_offset, color);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -4,29 +4,22 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
#include "util/hash.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
ccl_device_noinline void svm_node_tex_white_noise(ccl_private float *stack,
|
||||
const uint dimensions,
|
||||
const uint inputs_stack_offsets,
|
||||
const uint outputs_stack_offsets)
|
||||
ccl_device_noinline void svm_node_tex_white_noise(
|
||||
ccl_private float *ccl_restrict stack,
|
||||
const ccl_global SVMNodeTexWhiteNoise &ccl_restrict node)
|
||||
{
|
||||
uint vector_stack_offset;
|
||||
uint w_stack_offset;
|
||||
uint value_stack_offset;
|
||||
uint color_stack_offset;
|
||||
svm_unpack_node_uchar2(inputs_stack_offsets, &vector_stack_offset, &w_stack_offset);
|
||||
svm_unpack_node_uchar2(outputs_stack_offsets, &value_stack_offset, &color_stack_offset);
|
||||
const float3 vector = stack_load(stack, node.vector);
|
||||
const float w = stack_load(stack, node.w);
|
||||
|
||||
const float3 vector = stack_load_float3(stack, vector_stack_offset);
|
||||
const float w = stack_load_float(stack, w_stack_offset);
|
||||
|
||||
if (stack_valid(color_stack_offset)) {
|
||||
if (stack_valid(node.color_offset)) {
|
||||
float3 color;
|
||||
switch (dimensions) {
|
||||
switch (node.dimensions) {
|
||||
case 1:
|
||||
color = hash_float_to_float3(w);
|
||||
break;
|
||||
|
|
@ -44,12 +37,12 @@ ccl_device_noinline void svm_node_tex_white_noise(ccl_private float *stack,
|
|||
kernel_assert(0);
|
||||
break;
|
||||
}
|
||||
stack_store_float3(stack, color_stack_offset, color);
|
||||
stack_store_float3(stack, node.color_offset, color);
|
||||
}
|
||||
|
||||
if (stack_valid(value_stack_offset)) {
|
||||
if (stack_valid(node.value_offset)) {
|
||||
float value;
|
||||
switch (dimensions) {
|
||||
switch (node.dimensions) {
|
||||
case 1:
|
||||
value = hash_float_to_float(w);
|
||||
break;
|
||||
|
|
@ -67,7 +60,7 @@ ccl_device_noinline void svm_node_tex_white_noise(ccl_private float *stack,
|
|||
kernel_assert(0);
|
||||
break;
|
||||
}
|
||||
stack_store_float(stack, value_stack_offset, value);
|
||||
stack_store_float(stack, node.value_offset, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include "kernel/geom/motion_triangle.h"
|
||||
#include "kernel/geom/object.h"
|
||||
#include "kernel/geom/triangle.h"
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
#include "kernel/util/differential.h"
|
||||
#include "util/math_base.h"
|
||||
|
|
@ -82,34 +83,27 @@ ccl_device_inline float wireframe(KernelGlobals kg,
|
|||
ccl_device_noinline void svm_node_wireframe(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint4 node)
|
||||
const ccl_global SVMNodeWireframe &ccl_restrict node)
|
||||
{
|
||||
const uint in_size = node.y;
|
||||
const float bump_filter_width = __uint_as_float(node.z);
|
||||
uint use_pixel_size;
|
||||
uint bump_offset;
|
||||
uint out_fac;
|
||||
svm_unpack_node_uchar3(node.w, &use_pixel_size, &bump_offset, &out_fac);
|
||||
|
||||
/* Input Data */
|
||||
const float size = stack_load_float(stack, in_size);
|
||||
const int pixel_size = (int)use_pixel_size;
|
||||
const float size = stack_load(stack, node.in_size);
|
||||
const int pixel_size = (int)node.use_pixel_size;
|
||||
|
||||
/* Calculate wireframe */
|
||||
const differential3 dP = differential_from_compact(sd->Ng, sd->dP);
|
||||
|
||||
float3 P = sd->P;
|
||||
if (bump_offset == NODE_BUMP_OFFSET_DX) {
|
||||
P += dP.dx * bump_filter_width;
|
||||
if (node.bump_offset == NODE_BUMP_OFFSET_DX) {
|
||||
P += dP.dx * node.bump_filter_width;
|
||||
}
|
||||
else if (bump_offset == NODE_BUMP_OFFSET_DY) {
|
||||
P += dP.dy * bump_filter_width;
|
||||
else if (node.bump_offset == NODE_BUMP_OFFSET_DY) {
|
||||
P += dP.dy * node.bump_filter_width;
|
||||
}
|
||||
|
||||
const float f = wireframe(kg, sd, dP, size, pixel_size, &P);
|
||||
|
||||
if (stack_valid(out_fac)) {
|
||||
stack_store_float(stack, out_fac, f);
|
||||
if (stack_valid(node.out_fac_offset)) {
|
||||
stack_store_float(stack, node.out_fac_offset, f);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ class DeviceScene {
|
|||
device_vector<KernelParticle> particles;
|
||||
|
||||
/* shaders */
|
||||
device_vector<int4> svm_nodes;
|
||||
device_vector<int> svm_nodes;
|
||||
device_vector<KernelShader> shaders;
|
||||
|
||||
/* lookup tables */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -5,6 +5,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "graph/node.h"
|
||||
#include "kernel/svm/node_types.h"
|
||||
#include "kernel/svm/types.h"
|
||||
#include "scene/image.h"
|
||||
#include "scene/shader_graph.h"
|
||||
|
|
@ -27,12 +28,16 @@ class TextureMapping {
|
|||
TextureMapping();
|
||||
Transform compute_transform();
|
||||
bool skip();
|
||||
void compile(SVMCompiler &compiler, const int offset_in, const int offset_out);
|
||||
void compile(SVMCompiler &compiler,
|
||||
const SVMStackOffset offset_in,
|
||||
const SVMStackOffset offset_out);
|
||||
int compile(SVMCompiler &compiler, ShaderInput *vector_in);
|
||||
void compile(OSLCompiler &compiler);
|
||||
|
||||
int compile_begin(SVMCompiler &compiler, ShaderInput *vector_in);
|
||||
void compile_end(SVMCompiler &compiler, ShaderInput *vector_in, const int vector_offset);
|
||||
SVMStackOffset compile_begin(SVMCompiler &compiler, ShaderInput *vector_in);
|
||||
void compile_end(SVMCompiler &compiler,
|
||||
ShaderInput *vector_in,
|
||||
const SVMStackOffset vector_offset);
|
||||
|
||||
float3 translation;
|
||||
float3 rotation;
|
||||
|
|
@ -514,13 +519,6 @@ class BsdfNode : public BsdfBaseNode {
|
|||
explicit BsdfNode(const NodeType *node_type);
|
||||
SHADER_NODE_BASE_CLASS(BsdfNode)
|
||||
|
||||
void compile(SVMCompiler &compiler,
|
||||
ShaderInput *bsdf_y,
|
||||
ShaderInput *bsdf_z,
|
||||
ShaderInput *data_y = nullptr,
|
||||
ShaderInput *data_z = nullptr,
|
||||
ShaderInput *data_w = nullptr);
|
||||
|
||||
NODE_SOCKET_API(float3, color)
|
||||
NODE_SOCKET_API(float3, normal)
|
||||
NODE_SOCKET_API(float, surface_mix_weight)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
#include "scene/stats.h"
|
||||
#include "scene/svm.h"
|
||||
|
||||
#include "kernel/svm/node_types.h"
|
||||
|
||||
#include "util/log.h"
|
||||
#include "util/math_float3.h"
|
||||
#include "util/progress.h"
|
||||
|
|
@ -33,7 +35,7 @@ SVMShaderManager::~SVMShaderManager() = default;
|
|||
void SVMShaderManager::device_update_shader(Scene *scene,
|
||||
Shader *shader,
|
||||
Progress &progress,
|
||||
array<int4> *svm_nodes)
|
||||
array<int> *svm_nodes)
|
||||
{
|
||||
if (progress.get_cancel()) {
|
||||
return;
|
||||
|
|
@ -76,7 +78,7 @@ void SVMShaderManager::device_update_specific(Device *device,
|
|||
|
||||
/* Build all shaders. */
|
||||
TaskPool task_pool;
|
||||
vector<array<int4>> shader_svm_nodes(num_shaders);
|
||||
vector<array<int>> shader_svm_nodes(num_shaders);
|
||||
for (int i = 0; i < num_shaders; i++) {
|
||||
task_pool.push([this, scene, &progress, &shader_svm_nodes, i] {
|
||||
device_update_shader(scene, scene->shaders[i], progress, &shader_svm_nodes[i]);
|
||||
|
|
@ -88,17 +90,18 @@ void SVMShaderManager::device_update_specific(Device *device,
|
|||
return;
|
||||
}
|
||||
|
||||
/* The global node list contains a jump table (one node per shader)
|
||||
/* The global node list contains a jump table (one jump node per shader)
|
||||
* followed by the nodes of all shaders. */
|
||||
int svm_nodes_size = num_shaders;
|
||||
const int jump_node_size = 1 + sizeof(SVMNodeShaderJump) / sizeof(int);
|
||||
int svm_nodes_size = num_shaders * jump_node_size;
|
||||
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. */
|
||||
svm_nodes_size += shader_svm_nodes[i].size() - 1;
|
||||
/* Since we're not copying the local jump node, the size ends up lower. */
|
||||
svm_nodes_size += shader_svm_nodes[i].size() - jump_node_size;
|
||||
}
|
||||
|
||||
int4 *svm_nodes = dscene->svm_nodes.alloc(svm_nodes_size);
|
||||
int *svm_nodes = dscene->svm_nodes.alloc(svm_nodes_size);
|
||||
|
||||
int node_offset = num_shaders;
|
||||
int node_offset = num_shaders * jump_node_size;
|
||||
for (int i = 0; i < num_shaders; i++) {
|
||||
Shader *shader = scene->shaders[i];
|
||||
|
||||
|
|
@ -110,24 +113,22 @@ void SVMShaderManager::device_update_specific(Device *device,
|
|||
/* 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];
|
||||
const int4 &local_jump_node = shader_svm_nodes[i][0];
|
||||
|
||||
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;
|
||||
|
||||
node_offset += shader_svm_nodes[i].size() - 1;
|
||||
const int base = shader->id * jump_node_size;
|
||||
svm_nodes[base + 0] = NODE_SHADER_JUMP;
|
||||
*reinterpret_cast<SVMNodeShaderJump *>(&svm_nodes[base + 1]) = SVMNodeShaderJump{
|
||||
.offset_surface = shader_svm_nodes[i][1] - jump_node_size + node_offset,
|
||||
.offset_volume = shader_svm_nodes[i][2] - jump_node_size + node_offset,
|
||||
.offset_displacement = shader_svm_nodes[i][3] - jump_node_size + node_offset};
|
||||
node_offset += shader_svm_nodes[i].size() - jump_node_size;
|
||||
}
|
||||
|
||||
/* Copy the nodes of each shader into the correct location. */
|
||||
svm_nodes += num_shaders;
|
||||
int *dst = svm_nodes + num_shaders * jump_node_size;
|
||||
for (int i = 0; i < num_shaders; i++) {
|
||||
const int shader_size = shader_svm_nodes[i].size() - 1;
|
||||
const int shader_size = shader_svm_nodes[i].size() - jump_node_size;
|
||||
|
||||
std::copy_n(&shader_svm_nodes[i][1], shader_size, svm_nodes);
|
||||
svm_nodes += shader_size;
|
||||
std::copy_n(&shader_svm_nodes[i][jump_node_size], shader_size, dst);
|
||||
dst += shader_size;
|
||||
}
|
||||
|
||||
if (progress.get_cancel()) {
|
||||
|
|
@ -200,7 +201,7 @@ int SVMCompiler::stack_size(const ShaderIO *io)
|
|||
return derivative ? stack_size(type) * 3 : stack_size(type);
|
||||
}
|
||||
|
||||
int SVMCompiler::stack_find_offset(const int size)
|
||||
SVMStackOffset SVMCompiler::stack_find_offset(const int size)
|
||||
{
|
||||
int offset = -1;
|
||||
|
||||
|
|
@ -234,12 +235,12 @@ int SVMCompiler::stack_find_offset(const int size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int SVMCompiler::stack_find_offset(const ShaderIO *io)
|
||||
SVMStackOffset SVMCompiler::stack_find_offset(const ShaderIO *io)
|
||||
{
|
||||
return stack_find_offset(stack_size(io));
|
||||
}
|
||||
|
||||
void SVMCompiler::stack_clear_offset(const ShaderIO *io, const int offset)
|
||||
void SVMCompiler::stack_clear_offset(const ShaderIO *io, const SVMStackOffset offset)
|
||||
{
|
||||
const int size = stack_size(io);
|
||||
|
||||
|
|
@ -248,7 +249,7 @@ void SVMCompiler::stack_clear_offset(const ShaderIO *io, const int offset)
|
|||
}
|
||||
}
|
||||
|
||||
int SVMCompiler::stack_assign(ShaderInput *input)
|
||||
SVMStackOffset SVMCompiler::stack_assign(ShaderInput *input)
|
||||
{
|
||||
/* stack offset assign? */
|
||||
if (input->stack_offset == SVM_STACK_INVALID) {
|
||||
|
|
@ -264,11 +265,11 @@ int SVMCompiler::stack_assign(ShaderInput *input)
|
|||
input->stack_offset = stack_find_offset(input);
|
||||
|
||||
if (input->type() == SocketType::FLOAT) {
|
||||
add_value_node(
|
||||
node, __float_as_int(node->get_float(input->socket_type)), input->stack_offset);
|
||||
add_value_node(node, node->get_float(input->socket_type), input->stack_offset);
|
||||
}
|
||||
else if (input->type() == SocketType::INT) {
|
||||
add_value_node(node, node->get_int(input->socket_type), input->stack_offset);
|
||||
add_value_node(
|
||||
node, __int_as_float(node->get_int(input->socket_type)), input->stack_offset);
|
||||
}
|
||||
else if (input->type() == SocketType::VECTOR || input->type() == SocketType::NORMAL ||
|
||||
input->type() == SocketType::POINT || input->type() == SocketType::COLOR)
|
||||
|
|
@ -284,7 +285,7 @@ int SVMCompiler::stack_assign(ShaderInput *input)
|
|||
return input->stack_offset;
|
||||
}
|
||||
|
||||
int SVMCompiler::stack_assign(ShaderOutput *output)
|
||||
SVMStackOffset SVMCompiler::stack_assign(ShaderOutput *output)
|
||||
{
|
||||
/* if no stack offset assigned yet, find one */
|
||||
if (output->stack_offset == SVM_STACK_INVALID) {
|
||||
|
|
@ -294,45 +295,57 @@ int SVMCompiler::stack_assign(ShaderOutput *output)
|
|||
return output->stack_offset;
|
||||
}
|
||||
|
||||
bool SVMCompiler::is_linked(ShaderInput *input)
|
||||
SVMInputFloat SVMCompiler::input_float(const char *name)
|
||||
{
|
||||
return (input->link || input->constant_folded_in);
|
||||
ShaderInput *input = current_node->input(name);
|
||||
if (input->link) {
|
||||
return SVMInputFloat{SVM_INPUT_STACK_OFFSET_MASK | uint(stack_assign(input))};
|
||||
}
|
||||
float default_value = input->parent->get_float(input->socket_type);
|
||||
/* Filter out NaN that would collide with SVM_INPUT_STACK_OFFSET_MASK. */
|
||||
if (!isfinite_safe(default_value)) {
|
||||
default_value = 0.0f;
|
||||
}
|
||||
return SVMInputFloat{__float_as_uint(default_value)};
|
||||
}
|
||||
|
||||
int SVMCompiler::stack_assign_if_linked(ShaderInput *input)
|
||||
SVMInputFloat3 SVMCompiler::input_float3(const char *name)
|
||||
{
|
||||
if (is_linked(input)) {
|
||||
return stack_assign(input);
|
||||
ShaderInput *input = current_node->input(name);
|
||||
if (input->link) {
|
||||
return SVMInputFloat3{
|
||||
SVMInputFloat{SVM_INPUT_STACK_OFFSET_MASK | uint(stack_assign(input))}, {0}, {0}};
|
||||
}
|
||||
|
||||
return SVM_STACK_INVALID;
|
||||
float3 default_value = input->parent->get_float3(input->socket_type);
|
||||
/* Filter out NaN that would collide with SVM_INPUT_STACK_OFFSET_MASK. */
|
||||
if (!isfinite_safe(default_value)) {
|
||||
default_value = zero_float3();
|
||||
}
|
||||
return SVMInputFloat3{
|
||||
{__float_as_uint(default_value.x)},
|
||||
{__float_as_uint(default_value.y)},
|
||||
{__float_as_uint(default_value.z)},
|
||||
};
|
||||
}
|
||||
|
||||
int SVMCompiler::stack_assign_if_linked(ShaderOutput *output)
|
||||
SVMInputFloat3 SVMCompiler::input_float3_from_offset(const SVMStackOffset offset)
|
||||
{
|
||||
if (!output->links.empty()) {
|
||||
return stack_assign(output);
|
||||
}
|
||||
|
||||
return SVM_STACK_INVALID;
|
||||
return SVMInputFloat3{SVMInputFloat{SVM_INPUT_STACK_OFFSET_MASK | uint(offset)}, {0}, {0}};
|
||||
}
|
||||
|
||||
int SVMCompiler::stack_assign_if_not_equal(ShaderInput *input, const float value)
|
||||
SVMStackOffset SVMCompiler::input_link(const char *name)
|
||||
{
|
||||
if (is_linked(input) || input->parent->get_float(input->socket_type) != value) {
|
||||
return stack_assign(input);
|
||||
}
|
||||
|
||||
return SVM_STACK_INVALID;
|
||||
/* This is for sockets like normal which always expect a link. For the constant_folded_in we have
|
||||
* to write the value to the stack with another load and return a linked svm offset, as these
|
||||
* never store the default value in the SVMNode. */
|
||||
ShaderInput *input = current_node->input(name);
|
||||
return (input->link || input->constant_folded_in) ? stack_assign(input) : SVM_STACK_INVALID;
|
||||
}
|
||||
|
||||
int SVMCompiler::stack_assign_if_not_equal(ShaderInput *input, const float3 value)
|
||||
SVMStackOffset SVMCompiler::output(const char *name)
|
||||
{
|
||||
if (is_linked(input) || input->parent->get_float3(input->socket_type) != value) {
|
||||
return stack_assign(input);
|
||||
}
|
||||
|
||||
return SVM_STACK_INVALID;
|
||||
ShaderOutput *output = current_node->output(name);
|
||||
return (!output->links.empty()) ? stack_assign(output) : SVM_STACK_INVALID;
|
||||
}
|
||||
|
||||
void SVMCompiler::stack_link(ShaderInput *input, ShaderOutput *output)
|
||||
|
|
@ -367,7 +380,7 @@ void SVMCompiler::stack_clear_users(ShaderNode *node, ShaderNodeSet &done)
|
|||
|
||||
/* optimization we should add: verify if in->parent is actually used */
|
||||
for (ShaderInput *in : output->links) {
|
||||
if (in->parent != node && done.find(in->parent) == done.end()) {
|
||||
if (in->parent != node && !done.contains(in->parent)) {
|
||||
all_done = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -394,26 +407,12 @@ void SVMCompiler::stack_clear_temporary(ShaderNode *node)
|
|||
}
|
||||
}
|
||||
|
||||
uint SVMCompiler::encode_uchar4(const uint x, const uint y, uint z, const 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(const int a, const int b, int c, const int d)
|
||||
{
|
||||
current_svm_nodes.push_back_slow(make_int4(a, b, c, d));
|
||||
}
|
||||
|
||||
void SVMCompiler::add_node(ShaderNodeType type, const int a, int b, const int c)
|
||||
void SVMCompiler::add_node(ShaderNodeType type)
|
||||
{
|
||||
svm_node_types_used[type] = true;
|
||||
current_svm_nodes.push_back_slow(make_int4(type, a, b, c));
|
||||
current_svm_nodes.push_back_slow(type);
|
||||
}
|
||||
|
||||
static ShaderNodeType svm_node_type_with_derivatives(ShaderNodeType type)
|
||||
{
|
||||
switch (type) {
|
||||
|
|
@ -421,6 +420,7 @@ static ShaderNodeType svm_node_type_with_derivatives(ShaderNodeType type)
|
|||
case name: \
|
||||
return name##_DERIVATIVE;
|
||||
#include "kernel/svm/node_types_template.h"
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -428,47 +428,53 @@ static ShaderNodeType svm_node_type_with_derivatives(ShaderNodeType type)
|
|||
return type;
|
||||
}
|
||||
|
||||
void SVMCompiler::add_node_derivative(
|
||||
const ShaderNodeType type, const bool need_derivatives, const int a, const int b, const int c)
|
||||
ShaderNodeType SVMCompiler::node_type(const ShaderNode *shader_node,
|
||||
const ShaderNodeType type,
|
||||
const bool use_derivatives)
|
||||
{
|
||||
/* Only support derivatives for surface for now. */
|
||||
const ShaderNodeType node_x = (need_derivatives && current_type != SHADER_TYPE_VOLUME) ?
|
||||
svm_node_type_with_derivatives(type) :
|
||||
type;
|
||||
svm_node_types_used[node_x] = true;
|
||||
add_node(node_x, a, b, c);
|
||||
if ((use_derivatives || (shader_node && shader_node->need_derivatives())) &&
|
||||
current_type != SHADER_TYPE_VOLUME)
|
||||
{
|
||||
return svm_node_type_with_derivatives(type);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
void SVMCompiler::add_node(const ShaderNode *node, const int a, int b, const int c)
|
||||
void SVMCompiler::add_node_data_float4(const float4 &f)
|
||||
{
|
||||
const ShaderNodeType type = node->shader_node_type();
|
||||
assert(type != NODE_NONE);
|
||||
add_node_derivative(type, node->need_derivatives(), a, b, c);
|
||||
current_svm_nodes.push_back_slow(__float_as_int(f.x));
|
||||
current_svm_nodes.push_back_slow(__float_as_int(f.y));
|
||||
current_svm_nodes.push_back_slow(__float_as_int(f.z));
|
||||
current_svm_nodes.push_back_slow(__float_as_int(f.w));
|
||||
}
|
||||
|
||||
void SVMCompiler::add_node(const ShaderNodeType type, const float3 &f, const bool need_derivatives)
|
||||
void SVMCompiler::add_node_data_float(const float f)
|
||||
{
|
||||
add_node_derivative(
|
||||
type, need_derivatives, __float_as_int(f.x), __float_as_int(f.y), __float_as_int(f.z));
|
||||
current_svm_nodes.push_back_slow(__float_as_int(f));
|
||||
}
|
||||
|
||||
void SVMCompiler::add_node(const float4 &f)
|
||||
void SVMCompiler::add_value_node(const ShaderNode *shader_node,
|
||||
const float value,
|
||||
const int stack_offset)
|
||||
{
|
||||
current_svm_nodes.push_back_slow(make_int4(
|
||||
__float_as_int(f.x), __float_as_int(f.y), __float_as_int(f.z), __float_as_int(f.w)));
|
||||
add_node(shader_node,
|
||||
NODE_VALUE_F,
|
||||
SVMNodeValueF{
|
||||
.value = value,
|
||||
.out_offset = (SVMStackOffset)stack_offset,
|
||||
});
|
||||
}
|
||||
|
||||
void SVMCompiler::add_value_node(const ShaderNode *node, const int value, const int stack_offset)
|
||||
{
|
||||
add_node_derivative(NODE_VALUE_F, node->need_derivatives(), value, stack_offset);
|
||||
}
|
||||
|
||||
void SVMCompiler::add_value_node(const ShaderNode *node,
|
||||
void SVMCompiler::add_value_node(const ShaderNode *shader_node,
|
||||
const float3 &value,
|
||||
const int stack_offset)
|
||||
{
|
||||
add_node_derivative(NODE_VALUE_V, node->need_derivatives(), stack_offset);
|
||||
add_node(NODE_VALUE_V, value, node->need_derivatives());
|
||||
add_node(shader_node,
|
||||
NODE_VALUE_V,
|
||||
SVMNodeValueV{
|
||||
.out_offset = (SVMStackOffset)stack_offset,
|
||||
.value = value,
|
||||
});
|
||||
}
|
||||
|
||||
void SVMCompiler::stack_zero_incomplete_derivatives(const ShaderNode *node)
|
||||
|
|
@ -493,14 +499,12 @@ void SVMCompiler::stack_zero_incomplete_derivatives(const ShaderNode *node)
|
|||
}
|
||||
const int base_size = stack_size(output->type());
|
||||
if (base_size == 3) {
|
||||
add_node(NODE_VALUE_V, output->stack_offset + 3);
|
||||
add_node(NODE_VALUE_V, zero_float3(), false);
|
||||
add_node(NODE_VALUE_V, output->stack_offset + 6);
|
||||
add_node(NODE_VALUE_V, zero_float3(), false);
|
||||
add_value_node(nullptr, zero_float3(), output->stack_offset + 3);
|
||||
add_value_node(nullptr, zero_float3(), output->stack_offset + 6);
|
||||
}
|
||||
else if (base_size == 1) {
|
||||
add_node(NODE_VALUE_F, __float_as_int(0.0f), output->stack_offset + 1);
|
||||
add_node(NODE_VALUE_F, __float_as_int(0.0f), output->stack_offset + 2);
|
||||
add_value_node(nullptr, 0.0f, output->stack_offset + 1);
|
||||
add_value_node(nullptr, 0.0f, output->stack_offset + 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -527,8 +531,7 @@ void SVMCompiler::find_dependencies(ShaderNodeSet &dependencies,
|
|||
ShaderNode *skip_node)
|
||||
{
|
||||
ShaderNode *node = (input->link) ? input->link->parent : nullptr;
|
||||
if (node != nullptr && done.find(node) == done.end() && node != skip_node &&
|
||||
dependencies.find(node) == dependencies.end())
|
||||
if (node != nullptr && !done.contains(node) && node != skip_node && !dependencies.contains(node))
|
||||
{
|
||||
for (ShaderInput *in : node->inputs) {
|
||||
find_dependencies(dependencies, done, in, skip_node);
|
||||
|
|
@ -539,7 +542,9 @@ void SVMCompiler::find_dependencies(ShaderNodeSet &dependencies,
|
|||
|
||||
void SVMCompiler::generate_node(ShaderNode *node, ShaderNodeSet &done)
|
||||
{
|
||||
current_node = node;
|
||||
node->compile(*this);
|
||||
current_node = nullptr;
|
||||
stack_zero_incomplete_derivatives(node);
|
||||
stack_clear_users(node, done);
|
||||
stack_clear_temporary(node);
|
||||
|
|
@ -649,7 +654,7 @@ void SVMCompiler::generated_shared_closure_nodes(ShaderNode *root_node,
|
|||
CompilerState *state,
|
||||
const ShaderNodeSet &shared)
|
||||
{
|
||||
if (shared.find(node) != shared.end()) {
|
||||
if (shared.contains(node)) {
|
||||
generate_multi_closure(root_node, node, state);
|
||||
}
|
||||
else {
|
||||
|
|
@ -685,7 +690,7 @@ void SVMCompiler::generate_multi_closure(ShaderNode *root_node,
|
|||
CompilerState *state)
|
||||
{
|
||||
/* only generate once */
|
||||
if (state->closure_done.find(node) != state->closure_done.end()) {
|
||||
if (state->closure_done.contains(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -784,15 +789,15 @@ void SVMCompiler::generate_multi_closure(ShaderNode *root_node,
|
|||
/* Add instruction to skip closure and its dependencies if mix
|
||||
* weight is zero.
|
||||
*/
|
||||
svm_node_types_used[NODE_JUMP_IF_ONE] = true;
|
||||
current_svm_nodes.push_back_slow(make_int4(NODE_JUMP_IF_ONE, 0, stack_assign(facin), 0));
|
||||
const int node_jump_skip_index = current_svm_nodes.size() - 1;
|
||||
const int node_start = current_svm_nodes.size();
|
||||
add_node(nullptr, NODE_JUMP_IF_ONE, SVMNodeJumpIfOne{0, stack_assign(facin)});
|
||||
|
||||
generate_multi_closure(root_node, cl1in->link->parent, state);
|
||||
|
||||
/* 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;
|
||||
const int jump_node_size = 1 + sizeof(SVMNodeJumpIfOne) / sizeof(int);
|
||||
current_svm_nodes[node_start + 1] = current_svm_nodes.size() -
|
||||
(node_start + jump_node_size);
|
||||
}
|
||||
|
||||
/* generate instructions for input closure 2 */
|
||||
|
|
@ -800,15 +805,15 @@ void SVMCompiler::generate_multi_closure(ShaderNode *root_node,
|
|||
/* Add instruction to skip closure and its dependencies if mix
|
||||
* weight is zero.
|
||||
*/
|
||||
svm_node_types_used[NODE_JUMP_IF_ZERO] = true;
|
||||
current_svm_nodes.push_back_slow(make_int4(NODE_JUMP_IF_ZERO, 0, stack_assign(facin), 0));
|
||||
const int node_jump_skip_index = current_svm_nodes.size() - 1;
|
||||
const int node_start = current_svm_nodes.size();
|
||||
add_node(nullptr, NODE_JUMP_IF_ZERO, SVMNodeJumpIfZero{0, stack_assign(facin)});
|
||||
|
||||
generate_multi_closure(root_node, cl2in->link->parent, state);
|
||||
|
||||
/* 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;
|
||||
const int jump_node_size = 1 + sizeof(SVMNodeJumpIfZero) / sizeof(int);
|
||||
current_svm_nodes[node_start + 1] = current_svm_nodes.size() -
|
||||
(node_start + jump_node_size);
|
||||
}
|
||||
|
||||
/* unassign */
|
||||
|
|
@ -862,7 +867,7 @@ static void mark_nodes_requiring_derivatives(const SVMCompiler &compiler,
|
|||
if (input->link == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if (scheduled.find(input->link->parent) != scheduled.end()) {
|
||||
if (scheduled.contains(input->link->parent)) {
|
||||
continue;
|
||||
}
|
||||
traverse_queue.push(input->link->parent);
|
||||
|
|
@ -934,7 +939,8 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
|
|||
(shader->get_displacement_method() == DISPLACE_BOTH);
|
||||
if (need_bump_state) {
|
||||
bump_state_offset = stack_find_offset(SVM_BUMP_EVAL_STATE_SIZE);
|
||||
add_node(NODE_ENTER_BUMP_EVAL, bump_state_offset);
|
||||
add_node(
|
||||
nullptr, NODE_ENTER_BUMP_EVAL, SVMNodeEnterBumpEval{.state_offset = bump_state_offset});
|
||||
}
|
||||
|
||||
if (shader->reference_count()) {
|
||||
|
|
@ -971,7 +977,9 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
|
|||
}
|
||||
|
||||
/* compile output node */
|
||||
current_node = output;
|
||||
output->compile(*this);
|
||||
current_node = nullptr;
|
||||
|
||||
if (!state.aov_nodes.empty()) {
|
||||
/* AOV passes are only written if the object is directly visible, so
|
||||
|
|
@ -980,14 +988,15 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
|
|||
* 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);
|
||||
add_node(NODE_AOV_START);
|
||||
generate_svm_nodes(state.aov_nodes, &state);
|
||||
}
|
||||
}
|
||||
|
||||
/* add node to restore state after bump shader has finished */
|
||||
if (need_bump_state) {
|
||||
add_node(NODE_LEAVE_BUMP_EVAL, bump_state_offset);
|
||||
add_node(
|
||||
nullptr, NODE_LEAVE_BUMP_EVAL, SVMNodeLeaveBumpEval{.state_offset = bump_state_offset});
|
||||
bump_state_offset = SVM_STACK_INVALID;
|
||||
}
|
||||
|
||||
|
|
@ -1000,17 +1009,16 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
|
|||
/* for bump shaders we fall thru to the surface shader, but if this is any other kind of shader
|
||||
* it ends here */
|
||||
if (type != SHADER_TYPE_BUMP) {
|
||||
add_node(NODE_END, 0, 0, 0);
|
||||
add_node(NODE_END);
|
||||
}
|
||||
}
|
||||
|
||||
void SVMCompiler::compile(Shader *shader,
|
||||
array<int4> &svm_nodes,
|
||||
const int index,
|
||||
Summary *summary)
|
||||
void SVMCompiler::compile(Shader *shader, array<int> &svm_nodes, const int index, Summary *summary)
|
||||
{
|
||||
svm_node_types_used[NODE_SHADER_JUMP] = true;
|
||||
svm_nodes.push_back_slow(make_int4(NODE_SHADER_JUMP, 0, 0, 0));
|
||||
add_node(nullptr, NODE_SHADER_JUMP, SVMNodeShaderJump{0, 0, 0});
|
||||
svm_nodes.append(current_svm_nodes);
|
||||
current_svm_nodes.clear();
|
||||
|
||||
/* copy graph for shader with bump mapping */
|
||||
const int start_num_svm_nodes = svm_nodes.size();
|
||||
|
|
@ -1025,7 +1033,7 @@ void SVMCompiler::compile(Shader *shader,
|
|||
if (has_bump_from_displacement) {
|
||||
const scoped_timer timer((summary != nullptr) ? &summary->time_generate_bump : nullptr);
|
||||
compile_type(shader, shader->graph.get(), SHADER_TYPE_BUMP);
|
||||
svm_nodes[index].y = svm_nodes.size();
|
||||
svm_nodes[index + 1] = svm_nodes.size();
|
||||
svm_nodes.append(current_svm_nodes);
|
||||
}
|
||||
|
||||
|
|
@ -1036,7 +1044,7 @@ void SVMCompiler::compile(Shader *shader,
|
|||
/* only set jump offset if there's no bump shader, as the bump shader will fall thru to this
|
||||
* one if it exists */
|
||||
if (!has_bump_from_displacement) {
|
||||
svm_nodes[index].y = svm_nodes.size();
|
||||
svm_nodes[index + 1] = svm_nodes.size();
|
||||
}
|
||||
svm_nodes.append(current_svm_nodes);
|
||||
}
|
||||
|
|
@ -1045,7 +1053,7 @@ void SVMCompiler::compile(Shader *shader,
|
|||
{
|
||||
const scoped_timer timer((summary != nullptr) ? &summary->time_generate_volume : nullptr);
|
||||
compile_type(shader, shader->graph.get(), SHADER_TYPE_VOLUME);
|
||||
svm_nodes[index].z = svm_nodes.size();
|
||||
svm_nodes[index + 2] = svm_nodes.size();
|
||||
svm_nodes.append(current_svm_nodes);
|
||||
}
|
||||
|
||||
|
|
@ -1054,7 +1062,7 @@ void SVMCompiler::compile(Shader *shader,
|
|||
const scoped_timer timer((summary != nullptr) ? &summary->time_generate_displacement :
|
||||
nullptr);
|
||||
compile_type(shader, shader->graph.get(), SHADER_TYPE_DISPLACEMENT);
|
||||
svm_nodes[index].w = svm_nodes.size();
|
||||
svm_nodes[index + 3] = svm_nodes.size();
|
||||
svm_nodes.append(current_svm_nodes);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class SVMShaderManager : public ShaderManager {
|
|||
void device_update_shader(Scene *scene,
|
||||
Shader *shader,
|
||||
Progress &progress,
|
||||
array<int4> *svm_nodes);
|
||||
array<int> *svm_nodes);
|
||||
};
|
||||
|
||||
/* Graph Compiler */
|
||||
|
|
@ -76,44 +76,67 @@ class SVMCompiler {
|
|||
};
|
||||
|
||||
SVMCompiler(Scene *scene, Progress &progress);
|
||||
void compile(Shader *shader,
|
||||
array<int4> &svm_nodes,
|
||||
const int index,
|
||||
Summary *summary = nullptr);
|
||||
void compile(Shader *shader, array<int> &svm_nodes, const int index, Summary *summary = nullptr);
|
||||
|
||||
int stack_assign(ShaderOutput *output);
|
||||
int stack_assign(ShaderInput *input);
|
||||
bool is_linked(ShaderInput *input);
|
||||
int stack_assign_if_linked(ShaderInput *input);
|
||||
int stack_assign_if_linked(ShaderOutput *output);
|
||||
int stack_assign_if_not_equal(ShaderInput *input, const float value);
|
||||
int stack_assign_if_not_equal(ShaderInput *input, const float3 value);
|
||||
int stack_find_offset(const int size);
|
||||
int stack_find_offset(const ShaderIO *io);
|
||||
void stack_clear_offset(const ShaderIO *io, const int offset);
|
||||
/* Create input and output node parameters for struct T passed to add_node. */
|
||||
SVMInputFloat input_float(const char *name);
|
||||
SVMInputFloat3 input_float3(const char *name);
|
||||
SVMInputFloat3 input_float3_from_offset(SVMStackOffset offset);
|
||||
SVMStackOffset input_link(const char *name);
|
||||
SVMStackOffset output(const char *name);
|
||||
|
||||
/* Add simple SVM node without parameters. */
|
||||
void add_node(ShaderNodeType type);
|
||||
|
||||
/* Add SVM node with parameters in struct T. */
|
||||
template<typename T>
|
||||
void add_node(const ShaderNode *shader_node,
|
||||
const ShaderNodeType type,
|
||||
const T &node,
|
||||
const bool use_derivatives = false)
|
||||
requires(std::is_class_v<T> && sizeof(T) % sizeof(int) == 0 && alignof(T) <= sizeof(uint))
|
||||
{
|
||||
const ShaderNodeType resolved_type = node_type(shader_node, type, use_derivatives);
|
||||
current_svm_nodes.push_back_slow(resolved_type);
|
||||
const int *data = reinterpret_cast<const int *>(&node);
|
||||
svm_node_types_used[resolved_type] = true;
|
||||
for (size_t i = 0; i < sizeof(T) / sizeof(int); i++) {
|
||||
current_svm_nodes.push_back_slow(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add value node. */
|
||||
void add_value_node(const ShaderNode *shader_node, const float value, const int stack_offset);
|
||||
void add_value_node(const ShaderNode *shader_node, const float3 &value, const int stack_offset);
|
||||
|
||||
/* Add extra node data following add_node. */
|
||||
template<typename T>
|
||||
void add_node_data(const T &data)
|
||||
requires(std::is_class_v<T> && sizeof(T) % sizeof(int) == 0 && alignof(T) <= sizeof(uint))
|
||||
{
|
||||
const int *ptr = reinterpret_cast<const int *>(&data);
|
||||
for (size_t i = 0; i < sizeof(T) / sizeof(int); i++) {
|
||||
current_svm_nodes.push_back_slow(ptr[i]);
|
||||
}
|
||||
}
|
||||
void add_node_data_float4(const float4 &f);
|
||||
void add_node_data_float(const float f);
|
||||
|
||||
/* Low level input and output handling for some special nodes. Usually the functions
|
||||
* above should be used instead of these. */
|
||||
SVMStackOffset stack_assign(ShaderInput *input);
|
||||
SVMStackOffset stack_find_offset(const ShaderIO *io);
|
||||
void stack_clear_offset(const ShaderIO *io, const SVMStackOffset offset);
|
||||
void stack_link(ShaderInput *input, ShaderOutput *output);
|
||||
|
||||
void add_node(ShaderNodeType type, const int a = 0, const int b = 0, const int c = 0);
|
||||
void add_node_derivative(const ShaderNodeType type,
|
||||
const bool need_derivatives,
|
||||
const int a = 0,
|
||||
const int b = 0,
|
||||
const int c = 0);
|
||||
void add_node(const int a = 0, const int b = 0, const int c = 0, const int d = 0);
|
||||
void add_node(const ShaderNode *node, const int a = 0, const int b = 0, const int c = 0);
|
||||
void add_node(ShaderNodeType type, const float3 &f, const bool need_derivatives = 0);
|
||||
void add_node(const float4 &f);
|
||||
void add_value_node(const ShaderNode *node, const int value, const int stack_offset);
|
||||
void add_value_node(const ShaderNode *node, const float3 &value, const int stack_offset);
|
||||
uint attribute(ustring name);
|
||||
uint attribute(AttributeStandard std);
|
||||
uint attribute_standard(ustring name);
|
||||
uint encode_uchar4(const uint x, const uint y = 0, const uint z = 0, const uint w = 0);
|
||||
uint closure_mix_weight_offset()
|
||||
SVMStackOffset closure_mix_weight_offset()
|
||||
{
|
||||
return mix_weight_offset;
|
||||
}
|
||||
uint get_bump_state_offset()
|
||||
SVMStackOffset get_bump_state_offset()
|
||||
{
|
||||
return bump_state_offset;
|
||||
}
|
||||
|
|
@ -126,6 +149,7 @@ class SVMCompiler {
|
|||
Scene *scene;
|
||||
Progress &progress;
|
||||
ShaderGraph *current_graph;
|
||||
ShaderNode *current_node;
|
||||
bool background;
|
||||
|
||||
protected:
|
||||
|
|
@ -200,6 +224,13 @@ class SVMCompiler {
|
|||
uint node_feature_mask;
|
||||
};
|
||||
|
||||
ShaderNodeType node_type(const ShaderNode *shader_node,
|
||||
const ShaderNodeType type,
|
||||
const bool use_derivatives);
|
||||
|
||||
SVMStackOffset stack_assign(ShaderOutput *output);
|
||||
SVMStackOffset stack_find_offset(const int size);
|
||||
|
||||
void stack_clear_temporary(ShaderNode *node);
|
||||
int stack_size(SocketType::Type type);
|
||||
int stack_size(const ShaderIO *io);
|
||||
|
|
@ -230,13 +261,13 @@ class SVMCompiler {
|
|||
void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);
|
||||
|
||||
std::atomic_int *svm_node_types_used;
|
||||
array<int4> current_svm_nodes;
|
||||
array<int> current_svm_nodes;
|
||||
ShaderType current_type;
|
||||
Shader *current_shader;
|
||||
Stack active_stack;
|
||||
int max_stack_use;
|
||||
uint mix_weight_offset;
|
||||
uint bump_state_offset;
|
||||
SVMStackOffset mix_weight_offset;
|
||||
SVMStackOffset bump_state_offset;
|
||||
bool compile_failed;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -687,6 +687,39 @@ Transform transform_from_viewplane(BoundBox2D &viewplane);
|
|||
|
||||
#endif
|
||||
|
||||
/* Packed Transform.
|
||||
*
|
||||
* Transform type with no alignment requirements.
|
||||
* It does not support any mathematical operations, only conversion to Transform. */
|
||||
|
||||
struct PackedTransform {
|
||||
ccl_device_inline_method PackedTransform() = default;
|
||||
|
||||
ccl_device_inline_method PackedTransform(const Transform a) : x(a.x), y(a.y), z(a.z) {}
|
||||
|
||||
ccl_device_inline_method PackedTransform operator=(const Transform a)
|
||||
{
|
||||
x = a.x;
|
||||
y = a.y;
|
||||
z = a.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
packed_float4 x, y, z;
|
||||
};
|
||||
static_assert(alignof(PackedTransform) == alignof(float),
|
||||
"PackedTransform expected to have the same alignment as float");
|
||||
static_assert(sizeof(PackedTransform) == 48, "packed_float4 expected to be exactly 48 bytes");
|
||||
|
||||
ccl_device_inline Transform make_transform(const PackedTransform packed_tfm)
|
||||
{
|
||||
Transform tfm;
|
||||
tfm.x = packed_tfm.x;
|
||||
tfm.y = packed_tfm.y;
|
||||
tfm.z = packed_tfm.z;
|
||||
return tfm;
|
||||
}
|
||||
|
||||
/* TODO: This can be removed when we know if no devices will require explicit
|
||||
* address space qualifiers for this case. */
|
||||
|
||||
|
|
|
|||
|
|
@ -131,4 +131,39 @@ ccl_device_inline void print_float4(const ccl_private char *label, const float4
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Packed float4.
|
||||
*
|
||||
* float4 type with no alignment requirements.
|
||||
* It does not support any mathematical operations, only conversion to float4. */
|
||||
|
||||
#if defined(__KERNEL_METAL__)
|
||||
/* Metal has native packed_float4. */
|
||||
#else
|
||||
struct packed_float4 {
|
||||
ccl_device_inline_method packed_float4() = default;
|
||||
|
||||
ccl_device_inline_method packed_float4(const float4 a) : x(a.x), y(a.y), z(a.z), w(a.w) {}
|
||||
|
||||
ccl_device_inline_method operator float4() const
|
||||
{
|
||||
return make_float4(x, y, z, w);
|
||||
}
|
||||
|
||||
ccl_device_inline_method packed_float4 &operator=(const float4 &a)
|
||||
{
|
||||
x = a.x;
|
||||
y = a.y;
|
||||
z = a.z;
|
||||
w = a.w;
|
||||
return *this;
|
||||
}
|
||||
|
||||
float x, y, z, w;
|
||||
};
|
||||
#endif
|
||||
|
||||
static_assert(alignof(packed_float4) == alignof(float),
|
||||
"packed_float4 expected to have the same alignment as float");
|
||||
static_assert(sizeof(packed_float4) == 16, "packed_float4 expected to be exactly 16 bytes");
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue