2 * Copyright 2011-2016 Blender Foundation
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "testing/testing.h"
18 #include "testing/mock_log.h"
20 #include "render/graph.h"
21 #include "render/scene.h"
22 #include "render/nodes.h"
23 #include "util/util_array.h"
24 #include "util/util_logging.h"
25 #include "util/util_string.h"
26 #include "util/util_vector.h"
28 using testing::AnyNumber;
29 using testing::HasSubstr;
30 using testing::ScopedMockLog;
38 class ShaderNodeBuilder {
40 ShaderNodeBuilder(const string& name)
47 const string& name() const {
51 ShaderNode *node() const {
56 ShaderNodeBuilder& set(const string& input_name, V value)
58 ShaderInput *input_socket = node_->input(input_name.c_str());
59 EXPECT_NE((void*)NULL, input_socket);
60 input_socket->set(value);
64 template<typename T2, typename V>
65 ShaderNodeBuilder& set(V T2::*pfield, V value)
67 static_cast<T*>(node_)->*pfield = value;
76 class ShaderGraphBuilder {
78 ShaderGraphBuilder(ShaderGraph *graph)
81 node_map_["Output"] = graph->output();
84 ShaderNode *find_node(const string& name)
86 map<string, ShaderNode *>::iterator it = node_map_.find(name);
87 if(it == node_map_.end()) {
94 ShaderGraphBuilder& add_node(const T& node)
96 EXPECT_EQ(find_node(node.name()), (void*)NULL);
97 graph_->add(node.node());
98 node_map_[node.name()] = node.node();
102 ShaderGraphBuilder& add_connection(const string& from,
105 vector<string> tokens_from, tokens_to;
106 string_split(tokens_from, from, "::");
107 string_split(tokens_to, to, "::");
108 EXPECT_EQ(tokens_from.size(), 2);
109 EXPECT_EQ(tokens_to.size(), 2);
110 ShaderNode *node_from = find_node(tokens_from[0]),
111 *node_to = find_node(tokens_to[0]);
112 EXPECT_NE((void*)NULL, node_from);
113 EXPECT_NE((void*)NULL, node_to);
114 EXPECT_NE(node_from, node_to);
115 ShaderOutput *socket_from = node_from->output(tokens_from[1].c_str());
116 ShaderInput *socket_to = node_to->input(tokens_to[1].c_str());
117 EXPECT_NE((void*)NULL, socket_from);
118 EXPECT_NE((void*)NULL, socket_to);
119 graph_->connect(socket_from, socket_to);
123 /* Common input/output boilerplate. */
124 ShaderGraphBuilder& add_attribute(const string &name)
127 .add_node(ShaderNodeBuilder<AttributeNode>(name)
128 .set(&AttributeNode::attribute, ustring(name)));
131 ShaderGraphBuilder& output_closure(const string& from)
133 return (*this).add_connection(from, "Output::Surface");
136 ShaderGraphBuilder& output_color(const string& from)
139 .add_node(ShaderNodeBuilder<EmissionNode>("EmissionNode"))
140 .add_connection(from, "EmissionNode::Color")
141 .output_closure("EmissionNode::Emission");
144 ShaderGraphBuilder& output_value(const string& from)
147 .add_node(ShaderNodeBuilder<EmissionNode>("EmissionNode"))
148 .add_connection(from, "EmissionNode::Strength")
149 .output_closure("EmissionNode::Emission");
154 map<string, ShaderNode *> node_map_;
159 class RenderGraph : public testing::Test
165 DeviceInfo device_info;
167 SceneParams scene_params;
170 ShaderGraphBuilder builder;
180 util_logging_start();
181 util_logging_verbosity_set(1);
183 device_cpu = Device::create(device_info, stats, profiler, true);
184 scene = new Scene(scene_params, device_cpu);
187 virtual void TearDown()
194 #define EXPECT_ANY_MESSAGE(log) \
195 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); \
197 #define CORRECT_INFO_MESSAGE(log, message) \
198 EXPECT_CALL(log, Log(google::INFO, _, HasSubstr(message)));
200 #define INVALID_INFO_MESSAGE(log, message) \
201 EXPECT_CALL(log, Log(google::INFO, _, HasSubstr(message))).Times(0);
204 * Test deduplication of nodes that have inputs, some of them folded.
206 TEST_F(RenderGraph, deduplicate_deep)
208 EXPECT_ANY_MESSAGE(log);
209 CORRECT_INFO_MESSAGE(log, "Folding Value1::Value to constant (0.8).");
210 CORRECT_INFO_MESSAGE(log, "Folding Value2::Value to constant (0.8).");
211 CORRECT_INFO_MESSAGE(log, "Deduplicated 2 nodes.");
214 .add_node(ShaderNodeBuilder<GeometryNode>("Geometry1"))
215 .add_node(ShaderNodeBuilder<GeometryNode>("Geometry2"))
216 .add_node(ShaderNodeBuilder<ValueNode>("Value1")
217 .set(&ValueNode::value, 0.8f))
218 .add_node(ShaderNodeBuilder<ValueNode>("Value2")
219 .set(&ValueNode::value, 0.8f))
220 .add_node(ShaderNodeBuilder<NoiseTextureNode>("Noise1"))
221 .add_node(ShaderNodeBuilder<NoiseTextureNode>("Noise2"))
222 .add_node(ShaderNodeBuilder<MixNode>("Mix")
223 .set(&MixNode::type, NODE_MIX_BLEND)
225 .add_connection("Geometry1::Parametric", "Noise1::Vector")
226 .add_connection("Value1::Value", "Noise1::Scale")
227 .add_connection("Noise1::Color", "Mix::Color1")
228 .add_connection("Geometry2::Parametric", "Noise2::Vector")
229 .add_connection("Value2::Value", "Noise2::Scale")
230 .add_connection("Noise2::Color", "Mix::Color2")
231 .output_color("Mix::Color");
233 graph.finalize(scene);
235 EXPECT_EQ(graph.nodes.size(), 5);
239 * Test RGB to BW node.
241 TEST_F(RenderGraph, constant_fold_rgb_to_bw)
243 EXPECT_ANY_MESSAGE(log);
244 CORRECT_INFO_MESSAGE(log, "Folding RGBToBWNodeNode::Val to constant (0.8).");
245 CORRECT_INFO_MESSAGE(log, "Folding convert_float_to_color::value_color to constant (0.8, 0.8, 0.8).");
248 .add_node(ShaderNodeBuilder<RGBToBWNode>("RGBToBWNodeNode")
249 .set("Color", make_float3(0.8f, 0.8f, 0.8f)))
250 .output_color("RGBToBWNodeNode::Val");
252 graph.finalize(scene);
257 * - folding of Emission nodes that don't emit to nothing.
259 TEST_F(RenderGraph, constant_fold_emission1)
261 EXPECT_ANY_MESSAGE(log);
262 CORRECT_INFO_MESSAGE(log, "Discarding closure Emission.");
265 .add_node(ShaderNodeBuilder<EmissionNode>("Emission")
266 .set("Color", make_float3(0.0f, 0.0f, 0.0f)))
267 .output_closure("Emission::Emission");
269 graph.finalize(scene);
272 TEST_F(RenderGraph, constant_fold_emission2)
274 EXPECT_ANY_MESSAGE(log);
275 CORRECT_INFO_MESSAGE(log, "Discarding closure Emission.");
278 .add_node(ShaderNodeBuilder<EmissionNode>("Emission")
279 .set("Strength", 0.0f))
280 .output_closure("Emission::Emission");
282 graph.finalize(scene);
287 * - folding of Background nodes that don't emit to nothing.
289 TEST_F(RenderGraph, constant_fold_background1)
291 EXPECT_ANY_MESSAGE(log);
292 CORRECT_INFO_MESSAGE(log, "Discarding closure Background.");
295 .add_node(ShaderNodeBuilder<BackgroundNode>("Background")
296 .set("Color", make_float3(0.0f, 0.0f, 0.0f)))
297 .output_closure("Background::Background");
299 graph.finalize(scene);
302 TEST_F(RenderGraph, constant_fold_background2)
304 EXPECT_ANY_MESSAGE(log);
305 CORRECT_INFO_MESSAGE(log, "Discarding closure Background.");
308 .add_node(ShaderNodeBuilder<BackgroundNode>("Background")
309 .set("Strength", 0.0f))
310 .output_closure("Background::Background");
312 graph.finalize(scene);
317 * - Folding of Add Closure with only one input.
319 TEST_F(RenderGraph, constant_fold_shader_add)
321 EXPECT_ANY_MESSAGE(log);
322 CORRECT_INFO_MESSAGE(log, "Folding AddClosure1::Closure to socket Diffuse::BSDF.");
323 CORRECT_INFO_MESSAGE(log, "Folding AddClosure2::Closure to socket Diffuse::BSDF.");
324 INVALID_INFO_MESSAGE(log, "Folding AddClosure3");
327 .add_node(ShaderNodeBuilder<DiffuseBsdfNode>("Diffuse"))
328 .add_node(ShaderNodeBuilder<AddClosureNode>("AddClosure1"))
329 .add_node(ShaderNodeBuilder<AddClosureNode>("AddClosure2"))
330 .add_node(ShaderNodeBuilder<AddClosureNode>("AddClosure3"))
331 .add_connection("Diffuse::BSDF", "AddClosure1::Closure1")
332 .add_connection("Diffuse::BSDF", "AddClosure2::Closure2")
333 .add_connection("AddClosure1::Closure", "AddClosure3::Closure1")
334 .add_connection("AddClosure2::Closure", "AddClosure3::Closure2")
335 .output_closure("AddClosure3::Closure");
337 graph.finalize(scene);
342 * - Folding of Mix Closure with 0 or 1 fac.
343 * - Folding of Mix Closure with both inputs folded to the same node.
345 TEST_F(RenderGraph, constant_fold_shader_mix)
347 EXPECT_ANY_MESSAGE(log);
348 CORRECT_INFO_MESSAGE(log, "Folding MixClosure1::Closure to socket Diffuse::BSDF.");
349 CORRECT_INFO_MESSAGE(log, "Folding MixClosure2::Closure to socket Diffuse::BSDF.");
350 CORRECT_INFO_MESSAGE(log, "Folding MixClosure3::Closure to socket Diffuse::BSDF.");
353 .add_attribute("Attribute")
354 .add_node(ShaderNodeBuilder<DiffuseBsdfNode>("Diffuse"))
356 .add_node(ShaderNodeBuilder<MixClosureNode>("MixClosure1")
358 .add_connection("Diffuse::BSDF", "MixClosure1::Closure1")
360 .add_node(ShaderNodeBuilder<MixClosureNode>("MixClosure2")
362 .add_connection("Diffuse::BSDF", "MixClosure2::Closure2")
363 /* both inputs folded the same */
364 .add_node(ShaderNodeBuilder<MixClosureNode>("MixClosure3"))
365 .add_connection("Attribute::Fac", "MixClosure3::Fac")
366 .add_connection("MixClosure1::Closure", "MixClosure3::Closure1")
367 .add_connection("MixClosure2::Closure", "MixClosure3::Closure2")
368 .output_closure("MixClosure3::Closure");
370 graph.finalize(scene);
375 * - Folding of Invert with all constant inputs.
377 TEST_F(RenderGraph, constant_fold_invert)
379 EXPECT_ANY_MESSAGE(log);
380 CORRECT_INFO_MESSAGE(log, "Folding Invert::Color to constant (0.68, 0.5, 0.32).");
383 .add_node(ShaderNodeBuilder<InvertNode>("Invert")
385 .set("Color", make_float3(0.2f, 0.5f, 0.8f)))
386 .output_color("Invert::Color");
388 graph.finalize(scene);
393 * - Folding of Invert with zero Fac.
395 TEST_F(RenderGraph, constant_fold_invert_fac_0)
397 EXPECT_ANY_MESSAGE(log);
398 CORRECT_INFO_MESSAGE(log, "Folding Invert::Color to socket Attribute::Color.");
401 .add_attribute("Attribute")
402 .add_node(ShaderNodeBuilder<InvertNode>("Invert")
404 .add_connection("Attribute::Color", "Invert::Color")
405 .output_color("Invert::Color");
407 graph.finalize(scene);
412 * - Folding of Invert with zero Fac and constant input.
414 TEST_F(RenderGraph, constant_fold_invert_fac_0_const)
416 EXPECT_ANY_MESSAGE(log);
417 CORRECT_INFO_MESSAGE(log, "Folding Invert::Color to constant (0.2, 0.5, 0.8).");
420 .add_node(ShaderNodeBuilder<InvertNode>("Invert")
422 .set("Color", make_float3(0.2f, 0.5f, 0.8f)))
423 .output_color("Invert::Color");
425 graph.finalize(scene);
430 * - Folding of MixRGB Add with all constant inputs (clamp false).
432 TEST_F(RenderGraph, constant_fold_mix_add)
434 EXPECT_ANY_MESSAGE(log);
435 CORRECT_INFO_MESSAGE(log, "Folding MixAdd::Color to constant (0.62, 1.14, 1.42).");
438 .add_node(ShaderNodeBuilder<MixNode>("MixAdd")
439 .set(&MixNode::type, NODE_MIX_ADD)
440 .set(&MixNode::use_clamp, false)
442 .set("Color1", make_float3(0.3, 0.5, 0.7))
443 .set("Color2", make_float3(0.4, 0.8, 0.9)))
444 .output_color("MixAdd::Color");
446 graph.finalize(scene);
451 * - Folding of MixRGB Add with all constant inputs (clamp true).
453 TEST_F(RenderGraph, constant_fold_mix_add_clamp)
455 EXPECT_ANY_MESSAGE(log);
456 CORRECT_INFO_MESSAGE(log, "Folding MixAdd::Color to constant (0.62, 1, 1).");
459 .add_node(ShaderNodeBuilder<MixNode>("MixAdd")
460 .set(&MixNode::type, NODE_MIX_ADD)
461 .set(&MixNode::use_clamp, true)
463 .set("Color1", make_float3(0.3, 0.5, 0.7))
464 .set("Color2", make_float3(0.4, 0.8, 0.9)))
465 .output_color("MixAdd::Color");
467 graph.finalize(scene);
472 * - No folding on fac 0 for dodge.
474 TEST_F(RenderGraph, constant_fold_part_mix_dodge_no_fac_0)
476 EXPECT_ANY_MESSAGE(log);
477 INVALID_INFO_MESSAGE(log, "Folding ");
480 .add_attribute("Attribute1")
481 .add_attribute("Attribute2")
482 .add_node(ShaderNodeBuilder<MixNode>("Mix")
483 .set(&MixNode::type, NODE_MIX_DODGE)
484 .set(&MixNode::use_clamp, false)
486 .add_connection("Attribute1::Color", "Mix::Color1")
487 .add_connection("Attribute2::Color", "Mix::Color2")
488 .output_color("Mix::Color");
490 graph.finalize(scene);
495 * - No folding on fac 0 for light.
497 TEST_F(RenderGraph, constant_fold_part_mix_light_no_fac_0)
499 EXPECT_ANY_MESSAGE(log);
500 INVALID_INFO_MESSAGE(log, "Folding ");
503 .add_attribute("Attribute1")
504 .add_attribute("Attribute2")
505 .add_node(ShaderNodeBuilder<MixNode>("Mix")
506 .set(&MixNode::type, NODE_MIX_LIGHT)
507 .set(&MixNode::use_clamp, false)
509 .add_connection("Attribute1::Color", "Mix::Color1")
510 .add_connection("Attribute2::Color", "Mix::Color2")
511 .output_color("Mix::Color");
513 graph.finalize(scene);
518 * - No folding on fac 0 for burn.
520 TEST_F(RenderGraph, constant_fold_part_mix_burn_no_fac_0)
522 EXPECT_ANY_MESSAGE(log);
523 INVALID_INFO_MESSAGE(log, "Folding ");
526 .add_attribute("Attribute1")
527 .add_attribute("Attribute2")
528 .add_node(ShaderNodeBuilder<MixNode>("Mix")
529 .set(&MixNode::type, NODE_MIX_BURN)
530 .set(&MixNode::use_clamp, false)
532 .add_connection("Attribute1::Color", "Mix::Color1")
533 .add_connection("Attribute2::Color", "Mix::Color2")
534 .output_color("Mix::Color");
536 graph.finalize(scene);
541 * - No folding on fac 0 for clamped blend.
543 TEST_F(RenderGraph, constant_fold_part_mix_blend_clamped_no_fac_0)
545 EXPECT_ANY_MESSAGE(log);
546 INVALID_INFO_MESSAGE(log, "Folding ");
549 .add_attribute("Attribute1")
550 .add_attribute("Attribute2")
551 .add_node(ShaderNodeBuilder<MixNode>("Mix")
552 .set(&MixNode::type, NODE_MIX_BLEND)
553 .set(&MixNode::use_clamp, true)
555 .add_connection("Attribute1::Color", "Mix::Color1")
556 .add_connection("Attribute2::Color", "Mix::Color2")
557 .output_color("Mix::Color");
559 graph.finalize(scene);
564 * - Folding of Mix with 0 or 1 Fac.
565 * - Folding of Mix with both inputs folded to the same node.
567 TEST_F(RenderGraph, constant_fold_part_mix_blend)
569 EXPECT_ANY_MESSAGE(log);
570 CORRECT_INFO_MESSAGE(log, "Folding MixBlend1::Color to socket Attribute1::Color.");
571 CORRECT_INFO_MESSAGE(log, "Folding MixBlend2::Color to socket Attribute1::Color.");
572 CORRECT_INFO_MESSAGE(log, "Folding MixBlend3::Color to socket Attribute1::Color.");
575 .add_attribute("Attribute1")
576 .add_attribute("Attribute2")
578 .add_node(ShaderNodeBuilder<MixNode>("MixBlend1")
579 .set(&MixNode::type, NODE_MIX_BLEND)
580 .set(&MixNode::use_clamp, false)
582 .add_connection("Attribute1::Color", "MixBlend1::Color1")
583 .add_connection("Attribute2::Color", "MixBlend1::Color2")
585 .add_node(ShaderNodeBuilder<MixNode>("MixBlend2")
586 .set(&MixNode::type, NODE_MIX_BLEND)
587 .set(&MixNode::use_clamp, false)
589 .add_connection("Attribute1::Color", "MixBlend2::Color2")
590 .add_connection("Attribute2::Color", "MixBlend2::Color1")
591 /* both inputs folded to Attribute1 */
592 .add_node(ShaderNodeBuilder<MixNode>("MixBlend3")
593 .set(&MixNode::type, NODE_MIX_BLEND)
594 .set(&MixNode::use_clamp, false))
595 .add_connection("Attribute1::Fac", "MixBlend3::Fac")
596 .add_connection("MixBlend1::Color", "MixBlend3::Color1")
597 .add_connection("MixBlend2::Color", "MixBlend3::Color2")
598 .output_color("MixBlend3::Color");
600 graph.finalize(scene);
605 * - NOT folding of MixRGB Sub with the same inputs and fac NOT 1.
607 TEST_F(RenderGraph, constant_fold_part_mix_sub_same_fac_bad)
609 EXPECT_ANY_MESSAGE(log);
610 INVALID_INFO_MESSAGE(log, "Folding Mix::");
613 .add_attribute("Attribute")
614 .add_node(ShaderNodeBuilder<MixNode>("Mix")
615 .set(&MixNode::type, NODE_MIX_SUB)
616 .set(&MixNode::use_clamp, true)
618 .add_connection("Attribute::Color", "Mix::Color1")
619 .add_connection("Attribute::Color", "Mix::Color2")
620 .output_color("Mix::Color");
622 graph.finalize(scene);
627 * - Folding of MixRGB Sub with the same inputs and fac 1.
629 TEST_F(RenderGraph, constant_fold_part_mix_sub_same_fac_1)
631 EXPECT_ANY_MESSAGE(log);
632 CORRECT_INFO_MESSAGE(log, "Folding Mix::Color to constant (0, 0, 0).");
635 .add_attribute("Attribute")
636 .add_node(ShaderNodeBuilder<MixNode>("Mix")
637 .set(&MixNode::type, NODE_MIX_SUB)
638 .set(&MixNode::use_clamp, true)
640 .add_connection("Attribute::Color", "Mix::Color1")
641 .add_connection("Attribute::Color", "Mix::Color2")
642 .output_color("Mix::Color");
644 graph.finalize(scene);
648 * Graph for testing partial folds of MixRGB with one constant argument.
649 * Includes 4 tests: constant on each side with fac either unknown or 1.
651 static void build_mix_partial_test_graph(ShaderGraphBuilder &builder, NodeMix type, float3 constval)
654 .add_attribute("Attribute")
655 /* constant on the left */
656 .add_node(ShaderNodeBuilder<MixNode>("Mix_Cx_Fx")
657 .set(&MixNode::type, type)
658 .set(&MixNode::use_clamp, false)
659 .set("Color1", constval))
660 .add_node(ShaderNodeBuilder<MixNode>("Mix_Cx_F1")
661 .set(&MixNode::type, type)
662 .set(&MixNode::use_clamp, false)
663 .set("Color1", constval)
665 .add_connection("Attribute::Fac", "Mix_Cx_Fx::Fac")
666 .add_connection("Attribute::Color", "Mix_Cx_Fx::Color2")
667 .add_connection("Attribute::Color", "Mix_Cx_F1::Color2")
668 /* constant on the right */
669 .add_node(ShaderNodeBuilder<MixNode>("Mix_xC_Fx")
670 .set(&MixNode::type, type)
671 .set(&MixNode::use_clamp, false)
672 .set("Color2", constval))
673 .add_node(ShaderNodeBuilder<MixNode>("Mix_xC_F1")
674 .set(&MixNode::type, type)
675 .set(&MixNode::use_clamp, false)
676 .set("Color2", constval)
678 .add_connection("Attribute::Fac", "Mix_xC_Fx::Fac")
679 .add_connection("Attribute::Color", "Mix_xC_Fx::Color1")
680 .add_connection("Attribute::Color", "Mix_xC_F1::Color1")
681 /* results of actual tests simply added up to connect to output */
682 .add_node(ShaderNodeBuilder<MixNode>("Out12")
683 .set(&MixNode::type, NODE_MIX_ADD)
684 .set(&MixNode::use_clamp, true)
686 .add_node(ShaderNodeBuilder<MixNode>("Out34")
687 .set(&MixNode::type, NODE_MIX_ADD)
688 .set(&MixNode::use_clamp, true)
690 .add_node(ShaderNodeBuilder<MixNode>("Out1234")
691 .set(&MixNode::type, NODE_MIX_ADD)
692 .set(&MixNode::use_clamp, true)
694 .add_connection("Mix_Cx_Fx::Color", "Out12::Color1")
695 .add_connection("Mix_Cx_F1::Color", "Out12::Color2")
696 .add_connection("Mix_xC_Fx::Color", "Out34::Color1")
697 .add_connection("Mix_xC_F1::Color", "Out34::Color2")
698 .add_connection("Out12::Color", "Out1234::Color1")
699 .add_connection("Out34::Color", "Out1234::Color2")
700 .output_color("Out1234::Color");
704 * Tests: partial folding for RGB Add with known 0.
706 TEST_F(RenderGraph, constant_fold_part_mix_add_0)
708 EXPECT_ANY_MESSAGE(log);
709 /* 0 + X (fac 1) == X */
710 INVALID_INFO_MESSAGE(log, "Folding Mix_Cx_Fx::Color");
711 CORRECT_INFO_MESSAGE(log, "Folding Mix_Cx_F1::Color to socket Attribute::Color.");
712 /* X + 0 (fac ?) == X */
713 CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_Fx::Color to socket Attribute::Color.");
714 CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_F1::Color to socket Attribute::Color.");
715 INVALID_INFO_MESSAGE(log, "Folding Out");
717 build_mix_partial_test_graph(builder, NODE_MIX_ADD, make_float3(0, 0, 0));
718 graph.finalize(scene);
722 * Tests: partial folding for RGB Sub with known 0.
724 TEST_F(RenderGraph, constant_fold_part_mix_sub_0)
726 EXPECT_ANY_MESSAGE(log);
727 INVALID_INFO_MESSAGE(log, "Folding Mix_Cx_Fx::Color");
728 INVALID_INFO_MESSAGE(log, "Folding Mix_Cx_F1::Color");
729 /* X - 0 (fac ?) == X */
730 CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_Fx::Color to socket Attribute::Color.");
731 CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_F1::Color to socket Attribute::Color.");
732 INVALID_INFO_MESSAGE(log, "Folding Out");
734 build_mix_partial_test_graph(builder, NODE_MIX_SUB, make_float3(0, 0, 0));
735 graph.finalize(scene);
739 * Tests: partial folding for RGB Mul with known 1.
741 TEST_F(RenderGraph, constant_fold_part_mix_mul_1)
743 EXPECT_ANY_MESSAGE(log);
744 /* 1 * X (fac 1) == X */
745 INVALID_INFO_MESSAGE(log, "Folding Mix_Cx_Fx::Color");
746 CORRECT_INFO_MESSAGE(log, "Folding Mix_Cx_F1::Color to socket Attribute::Color.");
747 /* X * 1 (fac ?) == X */
748 CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_Fx::Color to socket Attribute::Color.");
749 CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_F1::Color to socket Attribute::Color.");
750 INVALID_INFO_MESSAGE(log, "Folding Out");
752 build_mix_partial_test_graph(builder, NODE_MIX_MUL, make_float3(1, 1, 1));
753 graph.finalize(scene);
757 * Tests: partial folding for RGB Div with known 1.
759 TEST_F(RenderGraph, constant_fold_part_mix_div_1)
761 EXPECT_ANY_MESSAGE(log);
762 INVALID_INFO_MESSAGE(log, "Folding Mix_Cx_Fx::Color");
763 INVALID_INFO_MESSAGE(log, "Folding Mix_Cx_F1::Color");
764 /* X / 1 (fac ?) == X */
765 CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_Fx::Color to socket Attribute::Color.");
766 CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_F1::Color to socket Attribute::Color.");
767 INVALID_INFO_MESSAGE(log, "Folding Out");
769 build_mix_partial_test_graph(builder, NODE_MIX_DIV, make_float3(1, 1, 1));
770 graph.finalize(scene);
774 * Tests: partial folding for RGB Mul with known 0.
776 TEST_F(RenderGraph, constant_fold_part_mix_mul_0)
778 EXPECT_ANY_MESSAGE(log);
779 /* 0 * ? (fac ?) == 0 */
780 CORRECT_INFO_MESSAGE(log, "Folding Mix_Cx_Fx::Color to constant (0, 0, 0).");
781 CORRECT_INFO_MESSAGE(log, "Folding Mix_Cx_F1::Color to constant (0, 0, 0).");
782 /* ? * 0 (fac 1) == 0 */
783 INVALID_INFO_MESSAGE(log, "Folding Mix_xC_Fx::Color");
784 CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_F1::Color to constant (0, 0, 0).");
786 CORRECT_INFO_MESSAGE(log, "Folding Out12::Color to constant (0, 0, 0).");
787 INVALID_INFO_MESSAGE(log, "Folding Out1234");
789 build_mix_partial_test_graph(builder, NODE_MIX_MUL, make_float3(0, 0, 0));
790 graph.finalize(scene);
794 * Tests: partial folding for RGB Div with known 0.
796 TEST_F(RenderGraph, constant_fold_part_mix_div_0)
798 EXPECT_ANY_MESSAGE(log);
799 /* 0 / ? (fac ?) == 0 */
800 CORRECT_INFO_MESSAGE(log, "Folding Mix_Cx_Fx::Color to constant (0, 0, 0).");
801 CORRECT_INFO_MESSAGE(log, "Folding Mix_Cx_F1::Color to constant (0, 0, 0).");
802 INVALID_INFO_MESSAGE(log, "Folding Mix_xC_Fx::Color");
803 INVALID_INFO_MESSAGE(log, "Folding Mix_xC_F1::Color");
805 CORRECT_INFO_MESSAGE(log, "Folding Out12::Color to constant (0, 0, 0).");
806 INVALID_INFO_MESSAGE(log, "Folding Out1234");
808 build_mix_partial_test_graph(builder, NODE_MIX_DIV, make_float3(0, 0, 0));
809 graph.finalize(scene);
813 * Tests: Separate/Combine RGB with all constant inputs.
815 TEST_F(RenderGraph, constant_fold_separate_combine_rgb)
817 EXPECT_ANY_MESSAGE(log);
818 CORRECT_INFO_MESSAGE(log, "Folding SeparateRGB::R to constant (0.3).");
819 CORRECT_INFO_MESSAGE(log, "Folding SeparateRGB::G to constant (0.5).");
820 CORRECT_INFO_MESSAGE(log, "Folding SeparateRGB::B to constant (0.7).");
821 CORRECT_INFO_MESSAGE(log, "Folding CombineRGB::Image to constant (0.3, 0.5, 0.7).");
824 .add_node(ShaderNodeBuilder<SeparateRGBNode>("SeparateRGB")
825 .set("Image", make_float3(0.3f, 0.5f, 0.7f)))
826 .add_node(ShaderNodeBuilder<CombineRGBNode>("CombineRGB"))
827 .add_connection("SeparateRGB::R", "CombineRGB::R")
828 .add_connection("SeparateRGB::G", "CombineRGB::G")
829 .add_connection("SeparateRGB::B", "CombineRGB::B")
830 .output_color("CombineRGB::Image");
832 graph.finalize(scene);
836 * Tests: Separate/Combine XYZ with all constant inputs.
838 TEST_F(RenderGraph, constant_fold_separate_combine_xyz)
840 EXPECT_ANY_MESSAGE(log);
841 CORRECT_INFO_MESSAGE(log, "Folding SeparateXYZ::X to constant (0.3).");
842 CORRECT_INFO_MESSAGE(log, "Folding SeparateXYZ::Y to constant (0.5).");
843 CORRECT_INFO_MESSAGE(log, "Folding SeparateXYZ::Z to constant (0.7).");
844 CORRECT_INFO_MESSAGE(log, "Folding CombineXYZ::Vector to constant (0.3, 0.5, 0.7).");
845 CORRECT_INFO_MESSAGE(log, "Folding convert_vector_to_color::value_color to constant (0.3, 0.5, 0.7).");
848 .add_node(ShaderNodeBuilder<SeparateXYZNode>("SeparateXYZ")
849 .set("Vector", make_float3(0.3f, 0.5f, 0.7f)))
850 .add_node(ShaderNodeBuilder<CombineXYZNode>("CombineXYZ"))
851 .add_connection("SeparateXYZ::X", "CombineXYZ::X")
852 .add_connection("SeparateXYZ::Y", "CombineXYZ::Y")
853 .add_connection("SeparateXYZ::Z", "CombineXYZ::Z")
854 .output_color("CombineXYZ::Vector");
856 graph.finalize(scene);
860 * Tests: Separate/Combine HSV with all constant inputs.
862 TEST_F(RenderGraph, constant_fold_separate_combine_hsv)
864 EXPECT_ANY_MESSAGE(log);
865 CORRECT_INFO_MESSAGE(log, "Folding SeparateHSV::H to constant (0.583333).");
866 CORRECT_INFO_MESSAGE(log, "Folding SeparateHSV::S to constant (0.571429).");
867 CORRECT_INFO_MESSAGE(log, "Folding SeparateHSV::V to constant (0.7).");
868 CORRECT_INFO_MESSAGE(log, "Folding CombineHSV::Color to constant (0.3, 0.5, 0.7).");
871 .add_node(ShaderNodeBuilder<SeparateHSVNode>("SeparateHSV")
872 .set("Color", make_float3(0.3f, 0.5f, 0.7f)))
873 .add_node(ShaderNodeBuilder<CombineHSVNode>("CombineHSV"))
874 .add_connection("SeparateHSV::H", "CombineHSV::H")
875 .add_connection("SeparateHSV::S", "CombineHSV::S")
876 .add_connection("SeparateHSV::V", "CombineHSV::V")
877 .output_color("CombineHSV::Color");
879 graph.finalize(scene);
883 * Tests: Gamma with all constant inputs.
885 TEST_F(RenderGraph, constant_fold_gamma)
887 EXPECT_ANY_MESSAGE(log);
888 CORRECT_INFO_MESSAGE(log, "Folding Gamma::Color to constant (0.164317, 0.353553, 0.585662).");
891 .add_node(ShaderNodeBuilder<GammaNode>("Gamma")
892 .set("Color", make_float3(0.3f, 0.5f, 0.7f))
894 .output_color("Gamma::Color");
896 graph.finalize(scene);
900 * Tests: Gamma with one constant 0 input.
902 TEST_F(RenderGraph, constant_fold_gamma_part_0)
904 EXPECT_ANY_MESSAGE(log);
905 INVALID_INFO_MESSAGE(log, "Folding Gamma_Cx::");
906 CORRECT_INFO_MESSAGE(log, "Folding Gamma_xC::Color to constant (1, 1, 1).");
909 .add_attribute("Attribute")
910 /* constant on the left */
911 .add_node(ShaderNodeBuilder<GammaNode>("Gamma_Cx")
912 .set("Color", make_float3(0.0f, 0.0f, 0.0f)))
913 .add_connection("Attribute::Fac", "Gamma_Cx::Gamma")
914 /* constant on the right */
915 .add_node(ShaderNodeBuilder<GammaNode>("Gamma_xC")
917 .add_connection("Attribute::Color", "Gamma_xC::Color")
919 .add_node(ShaderNodeBuilder<MixNode>("Out")
920 .set(&MixNode::type, NODE_MIX_ADD)
921 .set(&MixNode::use_clamp, true)
923 .add_connection("Gamma_Cx::Color", "Out::Color1")
924 .add_connection("Gamma_xC::Color", "Out::Color2")
925 .output_color("Out::Color");
927 graph.finalize(scene);
931 * Tests: Gamma with one constant 1 input.
933 TEST_F(RenderGraph, constant_fold_gamma_part_1)
935 EXPECT_ANY_MESSAGE(log);
936 CORRECT_INFO_MESSAGE(log, "Folding Gamma_Cx::Color to constant (1, 1, 1).");
937 CORRECT_INFO_MESSAGE(log, "Folding Gamma_xC::Color to socket Attribute::Color.");
940 .add_attribute("Attribute")
941 /* constant on the left */
942 .add_node(ShaderNodeBuilder<GammaNode>("Gamma_Cx")
943 .set("Color", make_float3(1.0f, 1.0f, 1.0f)))
944 .add_connection("Attribute::Fac", "Gamma_Cx::Gamma")
945 /* constant on the right */
946 .add_node(ShaderNodeBuilder<GammaNode>("Gamma_xC")
948 .add_connection("Attribute::Color", "Gamma_xC::Color")
950 .add_node(ShaderNodeBuilder<MixNode>("Out")
951 .set(&MixNode::type, NODE_MIX_ADD)
952 .set(&MixNode::use_clamp, true)
954 .add_connection("Gamma_Cx::Color", "Out::Color1")
955 .add_connection("Gamma_xC::Color", "Out::Color2")
956 .output_color("Out::Color");
958 graph.finalize(scene);
962 * Tests: BrightnessContrast with all constant inputs.
964 TEST_F(RenderGraph, constant_fold_bright_contrast)
966 EXPECT_ANY_MESSAGE(log);
967 CORRECT_INFO_MESSAGE(log, "Folding BrightContrast::Color to constant (0.16, 0.6, 1.04).");
970 .add_node(ShaderNodeBuilder<BrightContrastNode>("BrightContrast")
971 .set("Color", make_float3(0.3f, 0.5f, 0.7f))
973 .set("Contrast", 1.2f))
974 .output_color("BrightContrast::Color");
976 graph.finalize(scene);
980 * Tests: blackbody with all constant inputs.
982 TEST_F(RenderGraph, constant_fold_blackbody)
984 EXPECT_ANY_MESSAGE(log);
985 CORRECT_INFO_MESSAGE(log, "Folding Blackbody::Color to constant (3.94163, 0.226523, 0).");
988 .add_node(ShaderNodeBuilder<BlackbodyNode>("Blackbody")
989 .set("Temperature", 1200.0f))
990 .output_color("Blackbody::Color");
992 graph.finalize(scene);
996 * Tests: Math with all constant inputs (clamp false).
998 TEST_F(RenderGraph, constant_fold_math)
1000 EXPECT_ANY_MESSAGE(log);
1001 CORRECT_INFO_MESSAGE(log, "Folding Math::Value to constant (1.6).");
1004 .add_node(ShaderNodeBuilder<MathNode>("Math")
1005 .set(&MathNode::type, NODE_MATH_ADD)
1006 .set(&MathNode::use_clamp, false)
1007 .set("Value1", 0.7f)
1008 .set("Value2", 0.9f))
1009 .output_value("Math::Value");
1011 graph.finalize(scene);
1015 * Tests: Math with all constant inputs (clamp true).
1017 TEST_F(RenderGraph, constant_fold_math_clamp)
1019 EXPECT_ANY_MESSAGE(log);
1020 CORRECT_INFO_MESSAGE(log, "Folding Math::Value to constant (1).");
1023 .add_node(ShaderNodeBuilder<MathNode>("Math")
1024 .set(&MathNode::type, NODE_MATH_ADD)
1025 .set(&MathNode::use_clamp, true)
1026 .set("Value1", 0.7f)
1027 .set("Value2", 0.9f))
1028 .output_value("Math::Value");
1030 graph.finalize(scene);
1034 * Graph for testing partial folds of Math with one constant argument.
1035 * Includes 2 tests: constant on each side.
1037 static void build_math_partial_test_graph(ShaderGraphBuilder &builder, NodeMath type, float constval)
1040 .add_attribute("Attribute")
1041 /* constant on the left */
1042 .add_node(ShaderNodeBuilder<MathNode>("Math_Cx")
1043 .set(&MathNode::type, type)
1044 .set(&MathNode::use_clamp, false)
1045 .set("Value1", constval))
1046 .add_connection("Attribute::Fac", "Math_Cx::Value2")
1047 /* constant on the right */
1048 .add_node(ShaderNodeBuilder<MathNode>("Math_xC")
1049 .set(&MathNode::type, type)
1050 .set(&MathNode::use_clamp, false)
1051 .set("Value2", constval))
1052 .add_connection("Attribute::Fac", "Math_xC::Value1")
1054 .add_node(ShaderNodeBuilder<MathNode>("Out")
1055 .set(&MathNode::type, NODE_MATH_ADD)
1056 .set(&MathNode::use_clamp, true))
1057 .add_connection("Math_Cx::Value", "Out::Value1")
1058 .add_connection("Math_xC::Value", "Out::Value2")
1059 .output_value("Out::Value");
1063 * Tests: partial folding for Math Add with known 0.
1065 TEST_F(RenderGraph, constant_fold_part_math_add_0)
1067 EXPECT_ANY_MESSAGE(log);
1068 /* X + 0 == 0 + X == X */
1069 CORRECT_INFO_MESSAGE(log, "Folding Math_Cx::Value to socket Attribute::Fac.");
1070 CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Value to socket Attribute::Fac.");
1071 INVALID_INFO_MESSAGE(log, "Folding Out::");
1073 build_math_partial_test_graph(builder, NODE_MATH_ADD, 0.0f);
1074 graph.finalize(scene);
1078 * Tests: partial folding for Math Sub with known 0.
1080 TEST_F(RenderGraph, constant_fold_part_math_sub_0)
1082 EXPECT_ANY_MESSAGE(log);
1084 INVALID_INFO_MESSAGE(log, "Folding Math_Cx::");
1085 CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Value to socket Attribute::Fac.");
1086 INVALID_INFO_MESSAGE(log, "Folding Out::");
1088 build_math_partial_test_graph(builder, NODE_MATH_SUBTRACT, 0.0f);
1089 graph.finalize(scene);
1093 * Tests: partial folding for Math Mul with known 1.
1095 TEST_F(RenderGraph, constant_fold_part_math_mul_1)
1097 EXPECT_ANY_MESSAGE(log);
1098 /* X * 1 == 1 * X == X */
1099 CORRECT_INFO_MESSAGE(log, "Folding Math_Cx::Value to socket Attribute::Fac.");
1100 CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Value to socket Attribute::Fac.");
1101 INVALID_INFO_MESSAGE(log, "Folding Out::");
1103 build_math_partial_test_graph(builder, NODE_MATH_MULTIPLY, 1.0f);
1104 graph.finalize(scene);
1108 * Tests: partial folding for Math Div with known 1.
1110 TEST_F(RenderGraph, constant_fold_part_math_div_1)
1112 EXPECT_ANY_MESSAGE(log);
1114 INVALID_INFO_MESSAGE(log, "Folding Math_Cx::");
1115 CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Value to socket Attribute::Fac.");
1116 INVALID_INFO_MESSAGE(log, "Folding Out::");
1118 build_math_partial_test_graph(builder, NODE_MATH_DIVIDE, 1.0f);
1119 graph.finalize(scene);
1123 * Tests: partial folding for Math Mul with known 0.
1125 TEST_F(RenderGraph, constant_fold_part_math_mul_0)
1127 EXPECT_ANY_MESSAGE(log);
1128 /* X * 0 == 0 * X == 0 */
1129 CORRECT_INFO_MESSAGE(log, "Folding Math_Cx::Value to constant (0).");
1130 CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Value to constant (0).");
1131 CORRECT_INFO_MESSAGE(log, "Folding Out::Value to constant (0)");
1132 CORRECT_INFO_MESSAGE(log, "Discarding closure EmissionNode.");
1134 build_math_partial_test_graph(builder, NODE_MATH_MULTIPLY, 0.0f);
1135 graph.finalize(scene);
1139 * Tests: partial folding for Math Div with known 0.
1141 TEST_F(RenderGraph, constant_fold_part_math_div_0)
1143 EXPECT_ANY_MESSAGE(log);
1145 CORRECT_INFO_MESSAGE(log, "Folding Math_Cx::Value to constant (0).");
1146 INVALID_INFO_MESSAGE(log, "Folding Math_xC::");
1147 INVALID_INFO_MESSAGE(log, "Folding Out::");
1149 build_math_partial_test_graph(builder, NODE_MATH_DIVIDE, 0.0f);
1150 graph.finalize(scene);
1154 * Tests: partial folding for Math Power with known 0.
1156 TEST_F(RenderGraph, constant_fold_part_math_pow_0)
1158 EXPECT_ANY_MESSAGE(log);
1160 INVALID_INFO_MESSAGE(log, "Folding Math_Cx::");
1161 CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Value to constant (1).");
1162 INVALID_INFO_MESSAGE(log, "Folding Out::");
1164 build_math_partial_test_graph(builder, NODE_MATH_POWER, 0.0f);
1165 graph.finalize(scene);
1169 * Tests: partial folding for Math Power with known 1.
1171 TEST_F(RenderGraph, constant_fold_part_math_pow_1)
1173 EXPECT_ANY_MESSAGE(log);
1174 /* 1 ^ X == 1; X ^ 1 == X */
1175 CORRECT_INFO_MESSAGE(log, "Folding Math_Cx::Value to constant (1)");
1176 CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Value to socket Attribute::Fac.");
1177 INVALID_INFO_MESSAGE(log, "Folding Out::");
1179 build_math_partial_test_graph(builder, NODE_MATH_POWER, 1.0f);
1180 graph.finalize(scene);
1184 * Tests: Vector Math with all constant inputs.
1186 TEST_F(RenderGraph, constant_fold_vector_math)
1188 EXPECT_ANY_MESSAGE(log);
1189 CORRECT_INFO_MESSAGE(log, "Folding VectorMath::Value to constant (1).");
1190 CORRECT_INFO_MESSAGE(log, "Folding VectorMath::Vector to constant (3, 0, 0).");
1191 CORRECT_INFO_MESSAGE(log, "Folding convert_vector_to_float::value_float to constant (1).");
1192 CORRECT_INFO_MESSAGE(log, "Folding Math::Value to constant (2).");
1193 CORRECT_INFO_MESSAGE(log, "Folding convert_float_to_color::value_color to constant (2, 2, 2).");
1196 .add_node(ShaderNodeBuilder<VectorMathNode>("VectorMath")
1197 .set(&VectorMathNode::type, NODE_VECTOR_MATH_SUBTRACT)
1198 .set("Vector1", make_float3(1.3f, 0.5f, 0.7f))
1199 .set("Vector2", make_float3(-1.7f, 0.5f, 0.7f)))
1200 .add_node(ShaderNodeBuilder<MathNode>("Math")
1201 .set(&MathNode::type, NODE_MATH_ADD))
1202 .add_connection("VectorMath::Vector", "Math::Value1")
1203 .add_connection("VectorMath::Value", "Math::Value2")
1204 .output_color("Math::Value");
1206 graph.finalize(scene);
1210 * Graph for testing partial folds of Vector Math with one constant argument.
1211 * Includes 2 tests: constant on each side.
1213 static void build_vecmath_partial_test_graph(ShaderGraphBuilder &builder, NodeVectorMath type, float3 constval)
1216 .add_attribute("Attribute")
1217 /* constant on the left */
1218 .add_node(ShaderNodeBuilder<VectorMathNode>("Math_Cx")
1219 .set(&VectorMathNode::type, type)
1220 .set("Vector1", constval))
1221 .add_connection("Attribute::Vector", "Math_Cx::Vector2")
1222 /* constant on the right */
1223 .add_node(ShaderNodeBuilder<VectorMathNode>("Math_xC")
1224 .set(&VectorMathNode::type, type)
1225 .set("Vector2", constval))
1226 .add_connection("Attribute::Vector", "Math_xC::Vector1")
1228 .add_node(ShaderNodeBuilder<VectorMathNode>("Out")
1229 .set(&VectorMathNode::type, NODE_VECTOR_MATH_ADD))
1230 .add_connection("Math_Cx::Vector", "Out::Vector1")
1231 .add_connection("Math_xC::Vector", "Out::Vector2")
1232 .output_color("Out::Vector");
1236 * Tests: partial folding for Vector Math Add with known 0.
1238 TEST_F(RenderGraph, constant_fold_part_vecmath_add_0)
1240 EXPECT_ANY_MESSAGE(log);
1241 /* X + 0 == 0 + X == X */
1242 CORRECT_INFO_MESSAGE(log, "Folding Math_Cx::Vector to socket Attribute::Vector.");
1243 CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Vector to socket Attribute::Vector.");
1244 INVALID_INFO_MESSAGE(log, "Folding Out::");
1246 build_vecmath_partial_test_graph(builder, NODE_VECTOR_MATH_ADD, make_float3(0,0,0));
1247 graph.finalize(scene);
1251 * Tests: partial folding for Vector Math Sub with known 0.
1253 TEST_F(RenderGraph, constant_fold_part_vecmath_sub_0)
1255 EXPECT_ANY_MESSAGE(log);
1257 INVALID_INFO_MESSAGE(log, "Folding Math_Cx::");
1258 CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Vector to socket Attribute::Vector.");
1259 INVALID_INFO_MESSAGE(log, "Folding Out::");
1261 build_vecmath_partial_test_graph(builder, NODE_VECTOR_MATH_SUBTRACT, make_float3(0,0,0));
1262 graph.finalize(scene);
1266 * Tests: partial folding for Vector Math Dot Product with known 0.
1268 TEST_F(RenderGraph, constant_fold_part_vecmath_dot_0)
1270 EXPECT_ANY_MESSAGE(log);
1271 /* X * 0 == 0 * X == X */
1272 CORRECT_INFO_MESSAGE(log, "Folding Math_Cx::Vector to constant (0, 0, 0).");
1273 CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Vector to constant (0, 0, 0).");
1274 CORRECT_INFO_MESSAGE(log, "Folding Out::Vector to constant (0, 0, 0).");
1275 CORRECT_INFO_MESSAGE(log, "Discarding closure EmissionNode.");
1277 build_vecmath_partial_test_graph(builder, NODE_VECTOR_MATH_DOT_PRODUCT, make_float3(0,0,0));
1278 graph.finalize(scene);
1282 * Tests: partial folding for Vector Math Cross Product with known 0.
1284 TEST_F(RenderGraph, constant_fold_part_vecmath_cross_0)
1286 EXPECT_ANY_MESSAGE(log);
1287 /* X * 0 == 0 * X == X */
1288 CORRECT_INFO_MESSAGE(log, "Folding Math_Cx::Vector to constant (0, 0, 0).");
1289 CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Vector to constant (0, 0, 0).");
1290 CORRECT_INFO_MESSAGE(log, "Folding Out::Vector to constant (0, 0, 0).");
1291 CORRECT_INFO_MESSAGE(log, "Discarding closure EmissionNode.");
1293 build_vecmath_partial_test_graph(builder, NODE_VECTOR_MATH_CROSS_PRODUCT, make_float3(0,0,0));
1294 graph.finalize(scene);
1298 * Tests: Bump with no height input folded to Normal input.
1300 TEST_F(RenderGraph, constant_fold_bump)
1302 EXPECT_ANY_MESSAGE(log);
1303 CORRECT_INFO_MESSAGE(log, "Folding Bump::Normal to socket Geometry1::Normal.");
1306 .add_node(ShaderNodeBuilder<GeometryNode>("Geometry1"))
1307 .add_node(ShaderNodeBuilder<BumpNode>("Bump"))
1308 .add_connection("Geometry1::Normal", "Bump::Normal")
1309 .output_color("Bump::Normal");
1311 graph.finalize(scene);
1315 * Tests: Bump with no inputs folded to Geometry::Normal.
1317 TEST_F(RenderGraph, constant_fold_bump_no_input)
1319 EXPECT_ANY_MESSAGE(log);
1320 CORRECT_INFO_MESSAGE(log, "Folding Bump::Normal to socket geometry::Normal.");
1323 .add_node(ShaderNodeBuilder<BumpNode>("Bump"))
1324 .output_color("Bump::Normal");
1326 graph.finalize(scene);
1330 void init_test_curve(array<T> &buffer, T start, T end, int steps)
1332 buffer.resize(steps);
1334 for(int i = 0; i < steps; i++) {
1335 buffer[i] = lerp(start, end, float(i)/(steps-1));
1341 * - Folding of RGB Curves with all constant inputs.
1343 TEST_F(RenderGraph, constant_fold_rgb_curves)
1345 EXPECT_ANY_MESSAGE(log);
1346 CORRECT_INFO_MESSAGE(log, "Folding Curves::Color to constant (0.275, 0.5, 0.475).");
1348 array<float3> curve;
1349 init_test_curve(curve, make_float3(0.0f, 0.25f, 1.0f), make_float3(1.0f, 0.75f, 0.0f), 257);
1352 .add_node(ShaderNodeBuilder<RGBCurvesNode>("Curves")
1353 .set(&CurvesNode::curves, curve)
1354 .set(&CurvesNode::min_x, 0.1f)
1355 .set(&CurvesNode::max_x, 0.9f)
1357 .set("Color", make_float3(0.3f, 0.5f, 0.7f)))
1358 .output_color("Curves::Color");
1360 graph.finalize(scene);
1365 * - Folding of RGB Curves with zero Fac.
1367 TEST_F(RenderGraph, constant_fold_rgb_curves_fac_0)
1369 EXPECT_ANY_MESSAGE(log);
1370 CORRECT_INFO_MESSAGE(log, "Folding Curves::Color to socket Attribute::Color.");
1372 array<float3> curve;
1373 init_test_curve(curve, make_float3(0.0f, 0.25f, 1.0f), make_float3(1.0f, 0.75f, 0.0f), 257);
1376 .add_attribute("Attribute")
1377 .add_node(ShaderNodeBuilder<RGBCurvesNode>("Curves")
1378 .set(&CurvesNode::curves, curve)
1379 .set(&CurvesNode::min_x, 0.1f)
1380 .set(&CurvesNode::max_x, 0.9f)
1382 .add_connection("Attribute::Color", "Curves::Color")
1383 .output_color("Curves::Color");
1385 graph.finalize(scene);
1391 * - Folding of RGB Curves with zero Fac and all constant inputs.
1393 TEST_F(RenderGraph, constant_fold_rgb_curves_fac_0_const)
1395 EXPECT_ANY_MESSAGE(log);
1396 CORRECT_INFO_MESSAGE(log, "Folding Curves::Color to constant (0.3, 0.5, 0.7).");
1398 array<float3> curve;
1399 init_test_curve(curve, make_float3(0.0f, 0.25f, 1.0f), make_float3(1.0f, 0.75f, 0.0f), 257);
1402 .add_node(ShaderNodeBuilder<RGBCurvesNode>("Curves")
1403 .set(&CurvesNode::curves, curve)
1404 .set(&CurvesNode::min_x, 0.1f)
1405 .set(&CurvesNode::max_x, 0.9f)
1407 .set("Color", make_float3(0.3f, 0.5f, 0.7f)))
1408 .output_color("Curves::Color");
1410 graph.finalize(scene);
1415 * - Folding of Vector Curves with all constant inputs.
1417 TEST_F(RenderGraph, constant_fold_vector_curves)
1419 EXPECT_ANY_MESSAGE(log);
1420 CORRECT_INFO_MESSAGE(log, "Folding Curves::Vector to constant (0.275, 0.5, 0.475).");
1422 array<float3> curve;
1423 init_test_curve(curve, make_float3(0.0f, 0.25f, 1.0f), make_float3(1.0f, 0.75f, 0.0f), 257);
1426 .add_node(ShaderNodeBuilder<VectorCurvesNode>("Curves")
1427 .set(&CurvesNode::curves, curve)
1428 .set(&CurvesNode::min_x, 0.1f)
1429 .set(&CurvesNode::max_x, 0.9f)
1431 .set("Vector", make_float3(0.3f, 0.5f, 0.7f)))
1432 .output_color("Curves::Vector");
1434 graph.finalize(scene);
1439 * - Folding of Vector Curves with zero Fac.
1441 TEST_F(RenderGraph, constant_fold_vector_curves_fac_0)
1443 EXPECT_ANY_MESSAGE(log);
1444 CORRECT_INFO_MESSAGE(log, "Folding Curves::Vector to socket Attribute::Vector.");
1446 array<float3> curve;
1447 init_test_curve(curve, make_float3(0.0f, 0.25f, 1.0f), make_float3(1.0f, 0.75f, 0.0f), 257);
1450 .add_attribute("Attribute")
1451 .add_node(ShaderNodeBuilder<VectorCurvesNode>("Curves")
1452 .set(&CurvesNode::curves, curve)
1453 .set(&CurvesNode::min_x, 0.1f)
1454 .set(&CurvesNode::max_x, 0.9f)
1456 .add_connection("Attribute::Vector", "Curves::Vector")
1457 .output_color("Curves::Vector");
1459 graph.finalize(scene);
1464 * - Folding of Color Ramp with all constant inputs.
1466 TEST_F(RenderGraph, constant_fold_rgb_ramp)
1468 EXPECT_ANY_MESSAGE(log);
1469 CORRECT_INFO_MESSAGE(log, "Folding Ramp::Color to constant (0.14, 0.39, 0.64).");
1470 CORRECT_INFO_MESSAGE(log, "Folding Ramp::Alpha to constant (0.89).");
1472 array<float3> curve;
1474 init_test_curve(curve, make_float3(0.0f, 0.25f, 0.5f), make_float3(0.25f, 0.5f, 0.75f), 9);
1475 init_test_curve(alpha, 0.75f, 1.0f, 9);
1478 .add_node(ShaderNodeBuilder<RGBRampNode>("Ramp")
1479 .set(&RGBRampNode::ramp, curve)
1480 .set(&RGBRampNode::ramp_alpha, alpha)
1481 .set(&RGBRampNode::interpolate, true)
1483 .add_node(ShaderNodeBuilder<MixNode>("Mix")
1484 .set(&MixNode::type, NODE_MIX_ADD))
1485 .add_connection("Ramp::Color", "Mix::Color1")
1486 .add_connection("Ramp::Alpha", "Mix::Color2")
1487 .output_color("Mix::Color");
1489 graph.finalize(scene);
1494 * - Folding of Color Ramp with all constant inputs (interpolate false).
1496 TEST_F(RenderGraph, constant_fold_rgb_ramp_flat)
1498 EXPECT_ANY_MESSAGE(log);
1499 CORRECT_INFO_MESSAGE(log, "Folding Ramp::Color to constant (0.125, 0.375, 0.625).");
1500 CORRECT_INFO_MESSAGE(log, "Folding Ramp::Alpha to constant (0.875).");
1502 array<float3> curve;
1504 init_test_curve(curve, make_float3(0.0f, 0.25f, 0.5f), make_float3(0.25f, 0.5f, 0.75f), 9);
1505 init_test_curve(alpha, 0.75f, 1.0f, 9);
1508 .add_node(ShaderNodeBuilder<RGBRampNode>("Ramp")
1509 .set(&RGBRampNode::ramp, curve)
1510 .set(&RGBRampNode::ramp_alpha, alpha)
1511 .set(&RGBRampNode::interpolate, false)
1513 .add_node(ShaderNodeBuilder<MixNode>("Mix")
1514 .set(&MixNode::type, NODE_MIX_ADD))
1515 .add_connection("Ramp::Color", "Mix::Color1")
1516 .add_connection("Ramp::Alpha", "Mix::Color2")
1517 .output_color("Mix::Color");
1519 graph.finalize(scene);
1524 * - Folding of redundant conversion of float to color to float.
1526 TEST_F(RenderGraph, constant_fold_convert_float_color_float)
1528 EXPECT_ANY_MESSAGE(log);
1529 CORRECT_INFO_MESSAGE(log, "Folding Invert::Color to socket convert_float_to_color::value_color.");
1530 CORRECT_INFO_MESSAGE(log, "Folding convert_color_to_float::value_float to socket Attribute::Fac.");
1533 .add_attribute("Attribute")
1534 .add_node(ShaderNodeBuilder<InvertNode>("Invert")
1536 .add_connection("Attribute::Fac", "Invert::Color")
1537 .output_value("Invert::Color");
1539 graph.finalize(scene);
1544 * - Folding of redundant conversion of color to vector to color.
1546 TEST_F(RenderGraph, constant_fold_convert_color_vector_color)
1548 EXPECT_ANY_MESSAGE(log);
1549 CORRECT_INFO_MESSAGE(log, "Folding VecAdd::Vector to socket convert_color_to_vector::value_vector.");
1550 CORRECT_INFO_MESSAGE(log, "Folding convert_vector_to_color::value_color to socket Attribute::Color.");
1553 .add_attribute("Attribute")
1554 .add_node(ShaderNodeBuilder<VectorMathNode>("VecAdd")
1555 .set(&VectorMathNode::type, NODE_VECTOR_MATH_ADD)
1556 .set("Vector2", make_float3(0,0,0)))
1557 .add_connection("Attribute::Color", "VecAdd::Vector1")
1558 .output_color("VecAdd::Vector");
1560 graph.finalize(scene);
1565 * - NOT folding conversion of color to float to color.
1567 TEST_F(RenderGraph, constant_fold_convert_color_float_color)
1569 EXPECT_ANY_MESSAGE(log);
1570 CORRECT_INFO_MESSAGE(log, "Folding MathAdd::Value to socket convert_color_to_float::value_float.");
1571 INVALID_INFO_MESSAGE(log, "Folding convert_float_to_color::");
1574 .add_attribute("Attribute")
1575 .add_node(ShaderNodeBuilder<MathNode>("MathAdd")
1576 .set(&MathNode::type, NODE_MATH_ADD)
1577 .set("Value2", 0.0f))
1578 .add_connection("Attribute::Color", "MathAdd::Value1")
1579 .output_color("MathAdd::Value");
1581 graph.finalize(scene);