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:
Brecht Van Lommel 2026-04-09 11:24:32 +02:00 • committed by Brecht Van Lommel
parent c00226a6ae
commit 7ee94c067c
60 changed files with 4806 additions and 4130 deletions

View file

@ -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

View file

@ -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 */

View file

@ -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);
}
}

View file

@ -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

View file

@ -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

View file

@ -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__ */

View file

@ -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

View file

@ -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

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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

View file

@ -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:

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);
}
}

View file

@ -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 */

View file

@ -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));
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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, &param1_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

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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__ */

View file

@ -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);
}
}

View file

@ -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);
}
}
}

View file

@ -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;
}

View file

@ -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");

View file

@ -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

View file

@ -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,

View file

@ -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)
{

View file

@ -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

View file

@ -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, &center_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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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

View file

@ -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)

View file

@ -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);
}

View file

@ -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;
};

View file

@ -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. */

View file

@ -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