Files
workinf_Blender_Wasm/blender-5.2.0/intern/cycles/kernel/svm/util.h
2026-08-12 04:47:48 -04:00

270 lines
7.9 KiB
C++

/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
#pragma once
#include "kernel/globals.h"
#include "kernel/types.h"
#include "kernel/svm/types.h"
CCL_NAMESPACE_BEGIN
/* 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)
{
kernel_assert(a + 2 < SVM_STACK_SIZE);
const ccl_private float *stack_a = stack + a;
return make_float3(stack_a[0], stack_a[1], stack_a[2]);
}
ccl_device_inline float3 stack_load_float3_default(const ccl_private float *stack,
const uint a,
const float3 value)
{
return (a == (uint)SVM_STACK_INVALID) ? value : stack_load_float3(stack, a);
}
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]);
}
/* Type-based stack load. T can be float, float3, dual1, or dual3.
* When T is a dual type, derivatives are loaded from adjacent stack slots. */
template<typename T> ccl_device_inline T stack_load(const ccl_private float *stack, const uint a);
ccl_device_template_spec float stack_load(const ccl_private float *stack, const uint a)
{
return stack_load_float(stack, a);
}
ccl_device_template_spec float3 stack_load(const ccl_private float *stack, const uint a)
{
return stack_load_float3(stack, a);
}
ccl_device_template_spec dual1 stack_load(const ccl_private float *stack, const uint a)
{
return {
stack_load_float(stack, a), stack_load_float(stack, a + 1), stack_load_float(stack, a + 2)};
}
ccl_device_template_spec dual3 stack_load(const ccl_private float *stack, const uint a)
{
return {stack_load_float3(stack, a),
stack_load_float3(stack, a + 3),
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));
}
ccl_device_inline int stack_load(const ccl_private float *stack, const SVMInputInt v)
{
if (v.offset == SVM_STACK_INVALID) {
return v.value;
}
return stack_load_int(stack, v.offset);
}
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. */
ccl_device_inline void stack_store(ccl_private float *stack, const uint a, const float f)
{
stack_store_float(stack, a, f);
}
ccl_device_inline void stack_store(ccl_private float *stack, const uint a, const float3 f)
{
stack_store_float3(stack, a, f);
}
ccl_device_inline void stack_store(ccl_private float *stack, const uint a, const dual1 f)
{
stack_store_float(stack, a, f.val);
stack_store_float(stack, a + 1, f.dx);
stack_store_float(stack, a + 2, f.dy);
}
ccl_device_inline void stack_store(ccl_private float *stack, const uint a, const dual3 f)
{
stack_store_float3(stack, a, f.val);
stack_store_float3(stack, a + 3, f.dx);
stack_store_float3(stack, a + 6, f.dy);
}
/* Stack Utility */
ccl_device_inline bool stack_valid(const uint a)
{
return a != (uint)SVM_STACK_INVALID;
}
/* Reading Nodes */
/* Read a typed node struct directly from the SVM byte-code stream. The struct T must be a
* multiple of sizeof(uint) and its memory layout must match the byte-code encoding. Returns
* a const reference into the byte-code 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)
{
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 svm_node_get_data_float4(KernelGlobals kg, const int offset)
{
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)));
}
/* Shading Helpers */
ccl_device_forceinline float3 dPdx(const ccl_private ShaderData *sd)
{
return sd->dPdu * sd->du.dx + sd->dPdv * sd->dv.dx;
}
ccl_device_forceinline float3 dPdy(const ccl_private ShaderData *sd)
{
return sd->dPdu * sd->du.dy + sd->dPdv * sd->dv.dy;
}
/* Shading position, returns Float3Type = float3 (no derivatives) or dual3 (with derivatives). */
template<typename Float3Type>
ccl_device_inline Float3Type shading_position(const ccl_private ShaderData *sd)
{
if constexpr (is_dual_v<Float3Type>) {
dual3 P(sd->P);
P.dx = dPdx(sd);
P.dy = dPdy(sd);
return P;
}
else {
return sd->P;
}
}
/* Shading incoming direction, returns Float3Type = float3 or dual3. */
template<typename Float3Type>
ccl_device_inline Float3Type shading_incoming(const ccl_private ShaderData *sd)
{
if constexpr (is_dual_v<Float3Type>) {
dual3 I(sd->wi);
float3 dIdx, dIdy;
make_orthonormals(sd->wi, &dIdx, &dIdy);
I.dx = sd->dI * dIdx;
I.dy = sd->dI * dIdy;
return I;
}
else {
return sd->wi;
}
}
CCL_NAMESPACE_END