         int num_act_out_real = std::get<1>(pair_res);
 
         tv::Tensor out_features =
-            tv::empty({is_subm ? real_num_act_in : out_inds_num_limit, 64},
+            tv::empty({is_subm ? static_num_act_in : out_inds_num_limit, 64},
                       tv::float16, 0);
         auto out_features_real =
             out_features.slice_first_axis(0, num_act_out_real);

        // dynamic allocator, in c++ (inference engine) we need to use
        // fixed-size workspace and create a static allocator.
        auto ws_tensors = SpconvOps::get_indice_gen_tensors_from_workspace(
            workspace.raw_data(), KV, real_num_act_in,
            is_subm ? real_num_act_in : out_inds_num_limit, max_act_out_theory,
            is_subm, use_int64_hash_k, use_direct_table);
        // pair can also have a upper bound.
        // !!!!!IMPORTANT!!!!!!! if you provide a static (padded) pair_fwd and
        // other indice data, the output layout is tight pair_fwd_correct =

        // only regular conv need direct table.
        bool use_direct_table = direct_table && !is_subm;
        auto max_act_out_theory = SpconvOps::get_handcrafted_max_act_out(
            static_num_act_in, ksize, stride, padding, dilation);
        // query workspace size.
        int workspace_size = SpconvOps::get_indice_gen_workspace_size(
            KV, static_num_act_in, out_inds_num_limit, max_act_out_theory,
            is_subm, use_int64_hash_k, use_direct_table);
        // you should return workspace size in tensorrt plugin method.
        tv::Tensor workspace = tv::empty({workspace_size}, tv::uint8, 0);
