2023-08-16 00:20:26 +10:00
|
|
|
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
2023-05-31 16:19:06 +02:00
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2022-08-10 09:14:22 +02:00
|
|
|
|
|
|
|
|
#include "BLI_math_vector.h"
|
|
|
|
|
#include "BLI_string_ref.hh"
|
|
|
|
|
|
|
|
|
|
#include "DNA_node_types.h"
|
|
|
|
|
|
|
|
|
|
#include "NOD_derived_node_tree.hh"
|
|
|
|
|
|
2024-02-01 10:40:24 -05:00
|
|
|
#include "GPU_material.hh"
|
2022-08-10 09:14:22 +02:00
|
|
|
|
|
|
|
|
#include "COM_shader_node.hh"
|
|
|
|
|
#include "COM_utilities.hh"
|
2025-02-10 11:51:57 +01:00
|
|
|
#include "COM_utilities_gpu_material.hh"
|
2022-08-10 09:14:22 +02:00
|
|
|
|
2024-12-17 11:39:04 +01:00
|
|
|
namespace blender::compositor {
|
2022-08-10 09:14:22 +02:00
|
|
|
|
|
|
|
|
using namespace nodes::derived_node_tree_types;
|
|
|
|
|
|
|
|
|
|
ShaderNode::ShaderNode(DNode node) : node_(node)
|
|
|
|
|
{
|
2025-03-18 11:23:43 +02:00
|
|
|
this->populate_inputs();
|
|
|
|
|
this->populate_outputs();
|
2022-08-10 09:14:22 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-10 11:51:57 +01:00
|
|
|
void ShaderNode::compile(GPUMaterial *material)
|
2022-08-10 09:14:22 +02:00
|
|
|
{
|
2025-02-10 11:51:57 +01:00
|
|
|
node_->typeinfo->gpu_fn(
|
|
|
|
|
material, const_cast<bNode *>(node_.bnode()), nullptr, inputs_.data(), outputs_.data());
|
2022-08-10 09:14:22 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-10 11:51:57 +01:00
|
|
|
GPUNodeStack &ShaderNode::get_input(const StringRef identifier)
|
2022-08-10 09:14:22 +02:00
|
|
|
{
|
2025-02-10 11:51:57 +01:00
|
|
|
return get_shader_node_input(*node_, inputs_.data(), identifier);
|
2022-08-10 09:14:22 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-10 11:51:57 +01:00
|
|
|
GPUNodeStack &ShaderNode::get_output(const StringRef identifier)
|
2022-08-10 09:14:22 +02:00
|
|
|
{
|
2025-02-10 11:51:57 +01:00
|
|
|
return get_shader_node_output(*node_, outputs_.data(), identifier);
|
2022-08-10 09:14:22 +02:00
|
|
|
}
|
|
|
|
|
|
2025-06-23 14:34:37 +02:00
|
|
|
static eGPUType gpu_type_from_socket(DSocket socket)
|
2022-08-10 09:14:22 +02:00
|
|
|
{
|
2025-06-23 14:34:37 +02:00
|
|
|
switch (eNodeSocketDatatype(socket->type)) {
|
2022-08-10 09:14:22 +02:00
|
|
|
case SOCK_FLOAT:
|
|
|
|
|
return GPU_FLOAT;
|
Compositor: Support node integer sockets
This patch adds support for using integer sockets in compositor nodes.
This involves updating the Result class, node tree compiler, implicit
conversion operation, multi-function procedure operation, shader
operation, and some operations that supports multiple types.
Shader operation internally treats integers as floats, doing conversion
to and from int when reading and writing. That's because the GPUMaterial
compiler doesn't support integers. This is also the same workaround used
by the shader system. Though the GPU module are eyeing adding support
for integers, so we will update the code once they do that.
Domain realization is not yet supported for integer types, but this is
an internal limitation so far, as we do not plan to add nodes that
outputs integers soon. We are not yet sure how realization should happen
with regards to interpolation and we do not have base functions to
sample integer images, that's why I decided to delay its implementation
when it is actually needed.
Pull Request: https://projects.blender.org/blender/blender/pulls/132599
2025-01-06 10:09:26 +01:00
|
|
|
case SOCK_INT:
|
|
|
|
|
/* GPUMaterial doesn't support int, so it is passed as a float. */
|
|
|
|
|
return GPU_FLOAT;
|
2025-04-15 12:51:41 +02:00
|
|
|
case SOCK_BOOLEAN:
|
|
|
|
|
/* GPUMaterial doesn't support boolean, so it is passed as a float. */
|
|
|
|
|
return GPU_FLOAT;
|
2022-08-10 09:14:22 +02:00
|
|
|
case SOCK_VECTOR:
|
2025-06-23 14:34:37 +02:00
|
|
|
switch (socket->default_value_typed<bNodeSocketValueVector>()->dimensions) {
|
|
|
|
|
case 2:
|
|
|
|
|
return GPU_VEC2;
|
|
|
|
|
case 3:
|
|
|
|
|
return GPU_VEC3;
|
|
|
|
|
case 4:
|
|
|
|
|
return GPU_VEC4;
|
|
|
|
|
default:
|
|
|
|
|
BLI_assert_unreachable();
|
|
|
|
|
return GPU_NONE;
|
|
|
|
|
}
|
2022-08-10 09:14:22 +02:00
|
|
|
case SOCK_RGBA:
|
|
|
|
|
return GPU_VEC4;
|
2025-07-18 11:08:30 +02:00
|
|
|
case SOCK_MENU:
|
|
|
|
|
/* Single only types do not support GPU code path. */
|
|
|
|
|
BLI_assert(Result::is_single_value_only_type(get_node_socket_result_type(socket.bsocket())));
|
|
|
|
|
BLI_assert_unreachable();
|
|
|
|
|
return GPU_NONE;
|
2022-08-10 09:14:22 +02:00
|
|
|
default:
|
2025-02-27 14:34:23 +02:00
|
|
|
/* The GPU material compiler will skip unsupported sockets if GPU_NONE is provided. So this
|
|
|
|
|
* is an appropriate and a valid type for unsupported sockets. */
|
2022-08-10 09:14:22 +02:00
|
|
|
return GPU_NONE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void populate_gpu_node_stack(DSocket socket, GPUNodeStack &stack)
|
|
|
|
|
{
|
|
|
|
|
/* Make sure this stack is not marked as the end of the stack array. */
|
|
|
|
|
stack.end = false;
|
|
|
|
|
/* This will be initialized later by the GPU material compiler or the compile method. */
|
|
|
|
|
stack.link = nullptr;
|
2025-03-18 11:23:43 +02:00
|
|
|
/* This will be initialized by the GPU material compiler if needed. */
|
|
|
|
|
zero_v4(stack.vec);
|
2022-08-10 09:14:22 +02:00
|
|
|
|
2022-08-31 12:15:57 +02:00
|
|
|
stack.sockettype = socket->type;
|
2025-06-23 14:34:37 +02:00
|
|
|
stack.type = gpu_type_from_socket(socket);
|
2025-03-18 11:23:43 +02:00
|
|
|
|
|
|
|
|
stack.hasinput = socket->is_logically_linked();
|
|
|
|
|
stack.hasoutput = socket->is_logically_linked();
|
2022-08-10 09:14:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ShaderNode::populate_inputs()
|
|
|
|
|
{
|
|
|
|
|
/* Reserve a stack for each input in addition to an extra stack at the end to mark the end of the
|
|
|
|
|
* array, as this is what the GPU module functions expect. */
|
2022-08-31 12:15:57 +02:00
|
|
|
const int num_input_sockets = node_->input_sockets().size();
|
|
|
|
|
inputs_.resize(num_input_sockets + 1);
|
2022-08-10 09:14:22 +02:00
|
|
|
inputs_.last().end = true;
|
|
|
|
|
|
2022-08-31 12:15:57 +02:00
|
|
|
for (int i = 0; i < num_input_sockets; i++) {
|
2022-08-10 09:14:22 +02:00
|
|
|
populate_gpu_node_stack(node_.input(i), inputs_[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ShaderNode::populate_outputs()
|
|
|
|
|
{
|
|
|
|
|
/* Reserve a stack for each output in addition to an extra stack at the end to mark the end of
|
|
|
|
|
* the array, as this is what the GPU module functions expect. */
|
2022-08-31 12:15:57 +02:00
|
|
|
const int num_output_sockets = node_->output_sockets().size();
|
|
|
|
|
outputs_.resize(num_output_sockets + 1);
|
2022-08-10 09:14:22 +02:00
|
|
|
outputs_.last().end = true;
|
|
|
|
|
|
2022-08-31 12:15:57 +02:00
|
|
|
for (int i = 0; i < num_output_sockets; i++) {
|
2022-08-10 09:14:22 +02:00
|
|
|
populate_gpu_node_stack(node_.output(i), outputs_[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-17 11:39:04 +01:00
|
|
|
} // namespace blender::compositor
|