From c92d4ae9631135d37231faba827f60c3ad479e99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20S=C5=82uszniak?= Date: Sat, 22 Aug 2026 19:20:04 +0200 Subject: [PATCH] Vulkan: classify conv2d method by weight shape in conv2d_local_wg_size conv2d_local_wg_size() picked the convolution method from the shader name alone, and the condition it used matched every conv2d shader: if (kernel_name.find("conv2d_pw") != npos || (kernel_name.find("conv2d") != npos && kernel_name.find("conv_transpose2d") == npos)) { method = Conv2dMethod::Pointwise; } else { method = Conv2dMethod::SlidingWindow; } The sliding window shader is itself named "conv2d", so it matched and was labelled Pointwise, which made the SlidingWindow branch unreachable for every conv2d variant. Only conv_transpose2d reached the else. The sibling conv2d_global_wg_size() directly above uses the identical outer name test but then disambiguates by inspecting the weight's spatial extent, so the two functions could disagree about the same dispatch: the global size computed as sliding window while the local size was computed as pointwise. That second step arrived with #13173, which introduced the tuned {64 / y, y, 1} local size for pointwise convolutions. Before it, conv2d used create_local_wg_size() for every method. The name test swept sliding window convolutions into the new pointwise size along with it, so this restores what they had before that commit. Factors the classification into one function used by both, so they cannot drift apart again. Depthwise is routed to conv2d_dw_impl() before this dispatch and never reaches either function, and transposed convolutions resolve to the same branch as before, so sliding window is the only behavior that changes. Both local sizes are always 64 threads per group; only the group shape differs, for instance {8, 8, 1} to {8, 4, 2} for a 128x128x64 output. Fixes #21942 --- .../runtime/graph/ops/impl/Convolution.cpp | 58 ++++++++++--------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/backends/vulkan/runtime/graph/ops/impl/Convolution.cpp b/backends/vulkan/runtime/graph/ops/impl/Convolution.cpp index 5df73556ab6..5f201463aa1 100644 --- a/backends/vulkan/runtime/graph/ops/impl/Convolution.cpp +++ b/backends/vulkan/runtime/graph/ops/impl/Convolution.cpp @@ -349,32 +349,43 @@ utils::uvec3 create_conv2d_global_wg_size( } } -// Custom global workgroup size function for conv2d -utils::uvec3 conv2d_global_wg_size( +// Determines which convolution method a dispatch uses. +// +// The shader name alone is not enough: the sliding window and depthwise +// shaders are also named "conv2d", so a name test that accepts "conv2d" +// matches all of them. The pointwise case is therefore confirmed against the +// weight's spatial extent. Shared by the global and local workgroup size +// functions below so that the two cannot disagree about the same dispatch. +Conv2dMethod conv2d_method_from_dispatch( ComputeGraph* graph, const vkapi::ShaderInfo& shader, - const std::vector& args, - const std::vector& resize_args) { - const ValueRef out = args.at(0).refs.at(0); - const ValueRef weight_data = resize_args.at(0); - - // Determine method from shader name - Conv2dMethod method; + const ValueRef weight_data) { if (shader.kernel_name.find("conv2d_pw") != std::string::npos || (shader.kernel_name.find("conv2d") != std::string::npos && shader.kernel_name.find("conv_transpose2d") == std::string::npos)) { - // Check if it's pointwise by examining weight sizes const auto& weight_sizes = graph->get_tref(weight_data)->sizes; if (weight_sizes.at(2) == 1 && weight_sizes.at(3) == 1) { - method = Conv2dMethod::Pointwise; - } else { - method = Conv2dMethod::SlidingWindow; + return Conv2dMethod::Pointwise; } - } else if (shader.kernel_name.find("conv_transpose2d") != std::string::npos) { - method = Conv2dMethod::Transposed; - } else { - method = Conv2dMethod::SlidingWindow; + return Conv2dMethod::SlidingWindow; + } + if (shader.kernel_name.find("conv_transpose2d") != std::string::npos) { + return Conv2dMethod::Transposed; } + return Conv2dMethod::SlidingWindow; +} + +// Custom global workgroup size function for conv2d +utils::uvec3 conv2d_global_wg_size( + ComputeGraph* graph, + const vkapi::ShaderInfo& shader, + const std::vector& args, + const std::vector& resize_args) { + const ValueRef out = args.at(0).refs.at(0); + const ValueRef weight_data = resize_args.at(0); + + const Conv2dMethod method = + conv2d_method_from_dispatch(graph, shader, weight_data); // Determine stride_equals_dilation from shader name bool stride_equals_dilation = @@ -402,17 +413,10 @@ utils::uvec3 conv2d_local_wg_size( const std::vector& args, const std::vector& resize_args) { (void)args; - (void)resize_args; - // Determine method from shader name - Conv2dMethod method; - if (shader.kernel_name.find("conv2d_pw") != std::string::npos || - (shader.kernel_name.find("conv2d") != std::string::npos && - shader.kernel_name.find("conv_transpose2d") == std::string::npos)) { - method = Conv2dMethod::Pointwise; - } else { - method = Conv2dMethod::SlidingWindow; - } + const ValueRef weight_data = resize_args.at(0); + const Conv2dMethod method = + conv2d_method_from_dispatch(graph, shader, weight_data); if (method == Conv2dMethod::Pointwise) { uint32_t local_wg_size_y = 1;