+void DepthwiseConvolutionLayer::convQ8iHybridPerChannel()
+{
+ if (!_prepared)
+ {
+ prepareQ8iHybridPerChannel();
+ _prepared = true;
+ }
+
+ float output_activation_min = 0, output_activation_max = 0;
+ CalculateActivationRange(_activation, &output_activation_min, &output_activation_max);
+
+ auto input_shape = getShape(_input);
+ const int batch_size = input_shape.Dims(0);
+ const int input_size = input_shape.FlatSize() / batch_size;
+
+ auto scaling_factors_ptr = _input_scaling_factors.data();
+ auto input_offsets_ptr = _input_offsets.data();
+
+ for (int b = 0; b < batch_size; ++b)
+ {
+ const int offset = b * input_size;
+ nnfw::cker::PortableAsymmetricQuantizeFloats(getBuffer<float>(_input) + offset, input_size,
+ _input_quantized.data() + offset,
+ &scaling_factors_ptr[b], &input_offsets_ptr[b]);
+ }
+
+ nnfw::cker::DepthwiseConvParams op_params;
+ op_params.padding_values.width = _paddingLeft;
+ op_params.padding_values.height = _paddingTop;
+ op_params.depth_multiplier = _multiplier;
+ op_params.stride_width = _strideWidth;
+ op_params.stride_height = _strideHeight;
+ op_params.dilation_width_factor = _dilationWidth;
+ op_params.dilation_height_factor = _dilationHeight;
+ op_params.float_activation_min = output_activation_min;
+ op_params.float_activation_max = output_activation_max;
+
+ nnfw::cker::reference_integer_ops::DepthwiseConvHybridPerChannel(
+ op_params, _input_scaling_factors.data(), getShape(_input), _input_quantized.data(),
+ getShape(_kernel), getBuffer<int8_t>(_kernel), getShape(_bias), getBuffer<float>(_bias),
+ getShape(_output), getBuffer<float>(_output), _kernel->data_scales().data(),
+ _input_offsets.data());
+}
+