| 617 | } |
| 618 | |
| 619 | std::optional<ValueRefList> warp_affine_grad_rule( |
| 620 | const OpDef& op, Span<ValueRef> inputs, Span<bool> inputs_require_grad, |
| 621 | CustomBackward& backward) { |
| 622 | auto&& warp_affine = op.cast_final_safe<WarpAffine>(); |
| 623 | auto&& param = warp_affine.param(); |
| 624 | mgb_assert(inputs.size() == 3); |
| 625 | SmallVector<ValueRef> inps; |
| 626 | if (inputs_require_grad[0] || inputs_require_grad[1]) { |
| 627 | for (size_t i = 0; i < inputs.size(); ++i) { |
| 628 | inps.push_back(inputs[i]); |
| 629 | } |
| 630 | } |
| 631 | auto maker = CustomGradMaker(backward, inputs.size()); |
| 632 | maker.output_size(1).output_captured(0, false); |
| 633 | maker.backward([inputs = std::move(inps), &warp_affine, |
| 634 | param](Span<ValueRef> grads) { |
| 635 | mgb_assert(grads.size() == 1); |
| 636 | ValueRef grad = grads[0]; |
| 637 | SmallVector<ValueRef> ret(2); |
| 638 | if (!grad) { |
| 639 | return ret; |
| 640 | } |
| 641 | |
| 642 | CompNodeValue::ref_t device = inputs[0].device(); |
| 643 | DTypeValue::ref_t dtype = inputs[0].dtype(); |
| 644 | HostTensorStorage storage(*device); |
| 645 | storage.ensure_size(3 * (dtype->size())); |
| 646 | |
| 647 | auto* ptr = reinterpret_cast<dt_float32*>(storage.ptr()); |
| 648 | ptr[0] = 0; |
| 649 | ptr[1] = 0; |
| 650 | ptr[2] = 1; |
| 651 | auto t = imperative::apply( |
| 652 | CreateTensor( |
| 653 | CreateTensor::Unique, *device, dtype::Float32(), |
| 654 | ValueShape({1, 1, 3})), |
| 655 | HostStorage::make(storage))[0]; |
| 656 | auto mat = inputs[1]; |
| 657 | auto&& concat = Concat::make(); |
| 658 | concat->axis = 1; |
| 659 | mat = imperative::apply(*concat, inputs[1], t)[0]; |
| 660 | if (inputs[0]) { |
| 661 | auto&& grad_op = WarpPerspectiveBackwardData::make( |
| 662 | param.imode, param.border_mode, param.format, param.border_val); |
| 663 | ValueRefList args_(inputs.size()); |
| 664 | args_[0] = mat; |
| 665 | args_[1] = grads[0]; |
| 666 | args_[2] = inputs[0]; |
| 667 | ret[0] = imperative::apply(*grad_op, args_)[0]; |
| 668 | } |
| 669 | if (inputs[1]) { |
| 670 | auto&& grad_op = WarpPerspectiveBackwardMat::make( |
| 671 | param.imode, param.border_mode, param.format, param.border_val); |
| 672 | ValueRefList args_(inputs.size()); |
| 673 | args_[0] = inputs[0]; |
| 674 | args_[1] = mat; |
| 675 | args_[2] = grads[0]; |
| 676 | ret[1] = imperative::apply(*grad_op, args_)[0]; |
nothing calls this directly
no test coverage detected