mirror of
https://github.com/blender/blender
synced 2026-09-29 04:37:17 +03:00
Compositor: Support value inspection for image pixel operation
This patch supports value inspection for image pixel operations as a
follow up to ffd88022c9. This is done by logging the operation domain
and context precision for all internal non single value inputs and
outputs.
This does not yet support single value pixel operations.
Pull Request: https://projects.blender.org/blender/blender/pulls/158581
This commit is contained in:
parent
86afcda0e7
commit
3081bf63ee
5 changed files with 96 additions and 13 deletions
|
|
@ -57,9 +57,6 @@ class MultiFunctionProcedureOperation : public PixelOperation {
|
|||
* output results for each of the parameters in the procedure. Note that parameters have no
|
||||
* identifiers and are identified solely by their order. */
|
||||
Vector<std::string> parameter_identifiers_;
|
||||
/* True if the operation operates on single values, that is, all of its inputs and outputs are
|
||||
* single values. */
|
||||
const bool is_single_value_;
|
||||
|
||||
public:
|
||||
/* Build a multi-function procedure as well as an executor for it from the given pixel compile
|
||||
|
|
|
|||
|
|
@ -100,14 +100,19 @@ class PixelOperation : public Operation {
|
|||
/* A vector set that stores all output sockets that are used as previews for nodes inside the
|
||||
* pixel operation. */
|
||||
VectorSet<const bNodeSocket *> preview_outputs_;
|
||||
/* True if the operation operates on single values, that is, all of its inputs and outputs are
|
||||
* single values. */
|
||||
const bool is_single_value_;
|
||||
|
||||
public:
|
||||
PixelOperation(Context &context,
|
||||
PixelCompileUnit &compile_unit,
|
||||
const Schedule &schedule,
|
||||
const ComputeContext &compute_context);
|
||||
const ComputeContext &compute_context,
|
||||
const bool is_single_value);
|
||||
|
||||
/* Log a node preview for all nodes in the pixel operations if the node requires a preview.
|
||||
/* Log the values of all inputs and outputs of nodes inside the pixel operation as well as node
|
||||
* previews for all nodes in the pixel operations if the node requires a preview.
|
||||
*
|
||||
* Previews are computed from results that are populated for outputs that are used to compute
|
||||
* previews even if they are internally linked, and those outputs are stored and tracked in the
|
||||
|
|
|
|||
|
|
@ -51,9 +51,8 @@ MultiFunctionProcedureOperation::MultiFunctionProcedureOperation(
|
|||
const Schedule &schedule,
|
||||
const bool is_single_value,
|
||||
const ComputeContext &compute_context)
|
||||
: PixelOperation(context, compile_unit, schedule, compute_context),
|
||||
procedure_builder_(procedure_),
|
||||
is_single_value_(is_single_value)
|
||||
: PixelOperation(context, compile_unit, schedule, compute_context, is_single_value),
|
||||
procedure_builder_(procedure_)
|
||||
{
|
||||
this->build_procedure();
|
||||
procedure_executor_ = std::make_unique<mf::ProcedureExecutor>(procedure_);
|
||||
|
|
|
|||
|
|
@ -29,21 +29,103 @@ namespace blender::compositor {
|
|||
PixelOperation::PixelOperation(Context &context,
|
||||
PixelCompileUnit &compile_unit,
|
||||
const Schedule &schedule,
|
||||
const ComputeContext &compute_context)
|
||||
const ComputeContext &compute_context,
|
||||
const bool is_single_value)
|
||||
: Operation(context),
|
||||
compile_unit_(compile_unit),
|
||||
schedule_(schedule),
|
||||
compute_context_(compute_context)
|
||||
compute_context_(compute_context),
|
||||
is_single_value_(is_single_value)
|
||||
{
|
||||
}
|
||||
|
||||
static destruct_ptr<nodes::eval_log::ImageInfoLog> get_image_info_log(
|
||||
LinearAllocator<> *allocator, const Domain &domain, const ResultPrecision &precision)
|
||||
{
|
||||
return allocator->construct<nodes::eval_log::ImageInfoLog>(
|
||||
domain.data_size,
|
||||
domain.display_size,
|
||||
domain.data_offset,
|
||||
domain.transformation,
|
||||
to_string(domain.realization_options.interpolation),
|
||||
to_string(domain.realization_options.extension_x),
|
||||
to_string(domain.realization_options.extension_y),
|
||||
to_string(precision));
|
||||
}
|
||||
|
||||
void PixelOperation::log_data()
|
||||
{
|
||||
/* No logging for single-value pixel operations for now. */
|
||||
if (is_single_value_) {
|
||||
return;
|
||||
}
|
||||
|
||||
nodes::eval_log::NodesEvalLog *log = this->context().nodes_evaluation_log();
|
||||
if (!log) {
|
||||
return;
|
||||
}
|
||||
nodes::eval_log::NodeTreeLogger &tree_logger = log->get_local_tree_logger(compute_context_);
|
||||
|
||||
const Domain domain = this->compute_domain();
|
||||
|
||||
/* All inputs and outputs of pixel operations operate in the same domain, so the operation domain
|
||||
* should be logged for all. The exception is inputs that are single values, in which case, their
|
||||
* value is simply logged. */
|
||||
for (const bNode *node : compile_unit_) {
|
||||
/* Log output values. */
|
||||
for (const bNodeSocket *output_socket : node->output_sockets()) {
|
||||
if (!is_socket_available(output_socket)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!output_socket->is_logically_linked()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
tree_logger.output_socket_values.append(
|
||||
*tree_logger.allocator,
|
||||
{node->identifier,
|
||||
output_socket->index(),
|
||||
get_image_info_log(tree_logger.allocator, domain, this->context().get_precision())});
|
||||
}
|
||||
|
||||
/* Log input values. */
|
||||
for (const bNodeSocket *input_socket : node->input_sockets()) {
|
||||
if (!is_socket_available(input_socket)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!input_socket->is_logically_linked()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* The input is linked to a node that is inside the pixel operation, so skip it since it will
|
||||
* inherit its value from an output that was logged above. */
|
||||
const bNodeSocket &linked_output = *input_socket->logically_linked_sockets()[0];
|
||||
if (compile_unit_.contains(&linked_output.owner_node())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Otherwise, it is linked to a node that is outside of the compile unit. If it is a single
|
||||
* value, log that single value, if not, we log the operation domain. */
|
||||
const std::string &input_identifier = outputs_to_declared_inputs_map_.lookup(&linked_output);
|
||||
const Result &input = this->get_input(input_identifier);
|
||||
if (input.is_single_value()) {
|
||||
tree_logger.log_value(*node, *input_socket, input.single_value());
|
||||
continue;
|
||||
}
|
||||
|
||||
tree_logger.input_socket_values.append(
|
||||
*tree_logger.allocator,
|
||||
{node->identifier,
|
||||
input_socket->index(),
|
||||
get_image_info_log(tree_logger.allocator, domain, this->context().get_precision())});
|
||||
}
|
||||
}
|
||||
|
||||
for (const bNodeSocket *output : preview_outputs_) {
|
||||
Result &result = this->get_result(get_output_identifier_from_output_socket(*output));
|
||||
ImBuf *preview = compositor::compute_preview(context(), result);
|
||||
nodes::eval_log::NodeTreeLogger &tree_logger =
|
||||
this->context().nodes_evaluation_log()->get_local_tree_logger(compute_context_);
|
||||
tree_logger.node_image_previews.append(*tree_logger.allocator,
|
||||
{output->owner_node().identifier, preview});
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ ShaderOperation::ShaderOperation(Context &context,
|
|||
PixelCompileUnit &compile_unit,
|
||||
const Schedule &schedule,
|
||||
const ComputeContext &compute_context)
|
||||
: PixelOperation(context, compile_unit, schedule, compute_context)
|
||||
: PixelOperation(context, compile_unit, schedule, compute_context, false)
|
||||
{
|
||||
material_ = GPU_material_from_callbacks(
|
||||
GPU_MAT_COMPOSITOR, &construct_material, &generate_code, this);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue