Previously, Float2 images were internally stored as either Float3 or Float4 images due to limitations in the implementation, which no longer exists. So this patch refactors the compositor code to store Float2 images in actual Float2 containers, which gives better performance and memory savings. Some algorithms were adjusted to operate on Float2 instead of Float3 as was previously the case. Pull Request: https://projects.blender.org/blender/blender/pulls/140855
119 lines
3.4 KiB
C++
119 lines
3.4 KiB
C++
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#include "BLI_math_vector.h"
|
|
#include "BLI_string_ref.hh"
|
|
|
|
#include "DNA_node_types.h"
|
|
|
|
#include "NOD_derived_node_tree.hh"
|
|
|
|
#include "GPU_material.hh"
|
|
|
|
#include "COM_shader_node.hh"
|
|
#include "COM_utilities.hh"
|
|
#include "COM_utilities_gpu_material.hh"
|
|
|
|
namespace blender::compositor {
|
|
|
|
using namespace nodes::derived_node_tree_types;
|
|
|
|
ShaderNode::ShaderNode(DNode node) : node_(node)
|
|
{
|
|
this->populate_inputs();
|
|
this->populate_outputs();
|
|
}
|
|
|
|
void ShaderNode::compile(GPUMaterial *material)
|
|
{
|
|
node_->typeinfo->gpu_fn(
|
|
material, const_cast<bNode *>(node_.bnode()), nullptr, inputs_.data(), outputs_.data());
|
|
}
|
|
|
|
GPUNodeStack &ShaderNode::get_input(const StringRef identifier)
|
|
{
|
|
return get_shader_node_input(*node_, inputs_.data(), identifier);
|
|
}
|
|
|
|
GPUNodeStack &ShaderNode::get_output(const StringRef identifier)
|
|
{
|
|
return get_shader_node_output(*node_, outputs_.data(), identifier);
|
|
}
|
|
|
|
static eGPUType gpu_type_from_socket(DSocket socket)
|
|
{
|
|
switch (eNodeSocketDatatype(socket->type)) {
|
|
case SOCK_FLOAT:
|
|
return GPU_FLOAT;
|
|
case SOCK_INT:
|
|
/* GPUMaterial doesn't support int, so it is passed as a float. */
|
|
return GPU_FLOAT;
|
|
case SOCK_BOOLEAN:
|
|
/* GPUMaterial doesn't support boolean, so it is passed as a float. */
|
|
return GPU_FLOAT;
|
|
case SOCK_VECTOR:
|
|
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;
|
|
}
|
|
case SOCK_RGBA:
|
|
return GPU_VEC4;
|
|
default:
|
|
/* 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. */
|
|
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;
|
|
/* This will be initialized by the GPU material compiler if needed. */
|
|
zero_v4(stack.vec);
|
|
|
|
stack.sockettype = socket->type;
|
|
stack.type = gpu_type_from_socket(socket);
|
|
|
|
stack.hasinput = socket->is_logically_linked();
|
|
stack.hasoutput = socket->is_logically_linked();
|
|
}
|
|
|
|
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. */
|
|
const int num_input_sockets = node_->input_sockets().size();
|
|
inputs_.resize(num_input_sockets + 1);
|
|
inputs_.last().end = true;
|
|
|
|
for (int i = 0; i < num_input_sockets; i++) {
|
|
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. */
|
|
const int num_output_sockets = node_->output_sockets().size();
|
|
outputs_.resize(num_output_sockets + 1);
|
|
outputs_.last().end = true;
|
|
|
|
for (int i = 0; i < num_output_sockets; i++) {
|
|
populate_gpu_node_stack(node_.output(i), outputs_[i]);
|
|
}
|
|
}
|
|
|
|
} // namespace blender::compositor
|