| 2666 | } |
| 2667 | |
| 2668 | static webgpu_encoded_op ggml_webgpu_argsort(webgpu_context & ctx, ggml_tensor * src, ggml_tensor * dst) { |
| 2669 | bool is_top_k = dst->op == GGML_OP_TOP_K; |
| 2670 | |
| 2671 | ggml_webgpu_shader_lib_context shader_lib_ctx = {}; |
| 2672 | shader_lib_ctx.src0 = src; |
| 2673 | shader_lib_ctx.src1 = nullptr; |
| 2674 | shader_lib_ctx.dst = dst; |
| 2675 | shader_lib_ctx.max_wg_size = ctx->global_ctx->capabilities.limits.maxComputeInvocationsPerWorkgroup; |
| 2676 | shader_lib_ctx.wg_mem_limit_bytes = ctx->global_ctx->capabilities.limits.maxComputeWorkgroupStorageSize; |
| 2677 | |
| 2678 | webgpu_pipeline argsort_pipeline = ctx->shader_lib->get_argsort_pipeline(shader_lib_ctx); |
| 2679 | auto * argsort_decisions = static_cast<ggml_webgpu_generic_shader_decisions *>(argsort_pipeline.context.get()); |
| 2680 | |
| 2681 | webgpu_pipeline argsort_merge_pipeline = ctx->shader_lib->get_argsort_merge_pipeline(shader_lib_ctx); |
| 2682 | |
| 2683 | const uint32_t src_ne0 = (uint32_t) src->ne[0]; |
| 2684 | const uint32_t nrows = (uint32_t) ggml_nrows(src); |
| 2685 | const uint32_t npr = CEIL_DIV(src_ne0, argsort_decisions->wg_size); |
| 2686 | const uint32_t block_size = |
| 2687 | is_top_k ? std::min(argsort_decisions->wg_size, (uint32_t) dst->ne[0]) : argsort_decisions->wg_size; |
| 2688 | uint32_t out_ne0 = src_ne0; |
| 2689 | if (is_top_k) { |
| 2690 | if (npr > 1) { |
| 2691 | const uint32_t last_tile = src_ne0 - (npr - 1) * argsort_decisions->wg_size; |
| 2692 | out_ne0 = (npr - 1) * block_size + std::min(last_tile, block_size); |
| 2693 | } else { |
| 2694 | out_ne0 = block_size; |
| 2695 | } |
| 2696 | } |
| 2697 | |
| 2698 | uint32_t merge_len = block_size; |
| 2699 | uint32_t merge_passes = 0; |
| 2700 | while (merge_len < out_ne0) { |
| 2701 | merge_len <<= 1; |
| 2702 | merge_passes++; |
| 2703 | } |
| 2704 | |
| 2705 | const bool start_in_tmp = (merge_passes % 2) == 1; |
| 2706 | |
| 2707 | const size_t dst_offset = ggml_webgpu_tensor_offset(dst); |
| 2708 | const size_t idx_nbytes = out_ne0 * ggml_nrows(dst) * sizeof(int32_t); |
| 2709 | const size_t tmp_offset = |
| 2710 | ROUNDUP_POW2(dst_offset + idx_nbytes, ctx->global_ctx->capabilities.limits.minStorageBufferOffsetAlignment); |
| 2711 | const size_t tmp_binding_size = ROUNDUP_POW2(idx_nbytes, WEBGPU_STORAGE_BUF_BINDING_MULT); |
| 2712 | const size_t dst_binding_size = |
| 2713 | ROUNDUP_POW2(idx_nbytes + ggml_webgpu_tensor_misalignment(ctx, dst), WEBGPU_STORAGE_BUF_BINDING_MULT); |
| 2714 | |
| 2715 | const uint32_t offset_src = (uint32_t) (ggml_webgpu_tensor_misalignment(ctx, src) / ggml_type_size(src->type)); |
| 2716 | const uint32_t offset_dst = (uint32_t) (ggml_webgpu_tensor_misalignment(ctx, dst) / ggml_type_size(dst->type)); |
| 2717 | const uint32_t offset_tmp = 0; |
| 2718 | const uint32_t stride_src1 = (uint32_t) (src->nb[1] / ggml_type_size(src->type)); |
| 2719 | const uint32_t stride_src2 = (uint32_t) (src->nb[2] / ggml_type_size(src->type)); |
| 2720 | const uint32_t stride_src3 = (uint32_t) (src->nb[3] / ggml_type_size(src->type)); |
| 2721 | const uint32_t stride_idx1 = out_ne0; |
| 2722 | const uint32_t stride_idx2 = out_ne0 * (uint32_t) dst->ne[1]; |
| 2723 | const uint32_t stride_idx3 = stride_idx2 * (uint32_t) dst->ne[2]; |
| 2724 | |
| 2725 | std::vector<webgpu_dispatch_desc> dispatches; |
no test coverage detected