2 // Copyright (c) 2018 Intel Corporation
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 ///////////////////////////////////////////////////////////////////////////////////////////////////
19 #include "pass_manager.h"
20 #include "border_inst.h"
21 #include "convolution_inst.h"
22 #include "error_handler.h"
24 using namespace cldnn;
26 //Some primitives support padding for input.
27 //There are 2 types of padding: symmetric and asymettric.
28 //Symmetric padding can be done using input_offset parameter for primitives.
29 //Asymmetric padding can be done by adding border primitive before them. It's safe way without modyfing optimized kernels.
30 void handle_input_padding::run(program_impl& p)
32 auto processing_order = p.get_processing_order();
34 for (auto& node : processing_order)
36 if (node->is_type<convolution>()
37 && (node->as<convolution>().get_primitive()->padding_above.spatial[0] != 0 || node->as<convolution>().get_primitive()->padding_above.spatial[1] != 0
38 || node->as<convolution>().get_primitive()->padding_below.spatial[0] != 0 || node->as<convolution>().get_primitive()->padding_below.spatial[1] != 0))
40 auto conv = node->as<convolution>().get_primitive();
41 auto conv_primitive = const_cast<convolution*>(&(*conv));
44 if (node->as<convolution>().get_primitive()->padding_above.spatial[0] != node->as<convolution>().get_primitive()->padding_below.spatial[0]
45 || node->as<convolution>().get_primitive()->padding_above.spatial[1] != node->as<convolution>().get_primitive()->padding_below.spatial[1])
47 primitive_id conv_id = conv_primitive->id;
48 primitive_id input_id = conv_primitive->input[0];
50 auto padding_above = conv_primitive->padding_above;
51 auto padding_below = conv_primitive->padding_below;
53 CLDNN_ERROR_NOT_EQUAL(node->as<convolution>().id(), "Padding above feature", padding_above.feature[0], "", 0, "Padding above in feature is not supported");
54 CLDNN_ERROR_NOT_EQUAL(node->as<convolution>().id(), "Padding above batch", padding_above.batch[0], "", 0, "Padding above in batch is not supported");
55 CLDNN_ERROR_NOT_EQUAL(node->as<convolution>().id(), "Padding below feature", padding_below.feature[0], "", 0, "Padding below in feature is not supported");
56 CLDNN_ERROR_NOT_EQUAL(node->as<convolution>().id(), "Padding below batch", padding_below.batch[0], "", 0, "Padding below in batch is not supported");
58 CLDNN_ERROR_LESS_THAN(node->as<convolution>().id(), "Padding above X", padding_above.spatial[0], "", 0, "Padding above in X cannot be negative");
59 CLDNN_ERROR_LESS_THAN(node->as<convolution>().id(), "Padding above Y", padding_above.spatial[1], "", 0, "Padding above in Y cannot be negative");
60 CLDNN_ERROR_LESS_THAN(node->as<convolution>().id(), "Padding below X", padding_below.spatial[0], "", 0, "Padding below in X cannot be negative");
61 CLDNN_ERROR_LESS_THAN(node->as<convolution>().id(), "Padding below Y", padding_below.spatial[1], "", 0, "Padding below in Y cannot be negative");
63 //set padding_above/padding_below to zeros - border primitive do the job
64 conv_primitive->padding_above = tensor(0, 0, 0, 0);
65 conv_primitive->padding_below = tensor(0, 0, 0, 0);
67 //create border primitive
68 primitive_id border_id = input_id + "_border_" + conv_id;
69 auto b_prim = std::make_shared<border>(border_id, input_id,
72 border_type::constant, 0.0f);
74 auto& b_prim_node = p.get_or_create(b_prim);
76 p.add_intermediate(b_prim_node, *node, 0, true);
84 conv_primitive->input_offset = conv_primitive->padding_above.negate().add(conv_primitive->input_offset);
86 //set padding_above/padding_below to zeros - input_offset do the job
87 conv_primitive->padding_above = tensor(0, 0, 0, 0);
88 conv_primitive->padding_below = tensor(0, 0, 0, 0);
90 node->as<convolution>().recalc_output_layout(true);