You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

convolution_vulkan.cpp 76 kB

adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986
  1. // Tencent is pleased to support the open source community by making ncnn available.
  2. //
  3. // Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
  4. //
  5. // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
  6. // in compliance with the License. You may obtain a copy of the License at
  7. //
  8. // https://opensource.org/licenses/BSD-3-Clause
  9. //
  10. // Unless required by applicable law or agreed to in writing, software distributed
  11. // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  12. // CONDITIONS OF ANY KIND, either express or implied. See the License for the
  13. // specific language governing permissions and limitations under the License.
  14. #include "convolution_vulkan.h"
  15. #include <algorithm>
  16. #include "layer_type.h"
  17. #include "layer_shader_type.h"
  18. namespace ncnn {
  19. DEFINE_LAYER_CREATOR(Convolution_vulkan)
  20. Convolution_vulkan::Convolution_vulkan()
  21. {
  22. support_vulkan = true;
  23. support_image_storage = true;
  24. padding = 0;
  25. pipeline_convolution = 0;
  26. pipeline_convolution_1x1s1d1 = 0;
  27. pipeline_convolution_pack4 = 0;
  28. pipeline_convolution_pack4_1x1s1d1 = 0;
  29. pipeline_convolution_pack1to4 = 0;
  30. pipeline_convolution_pack4to1 = 0;
  31. pipeline_convolution_pack8 = 0;
  32. pipeline_convolution_pack8_1x1s1d1 = 0;
  33. pipeline_convolution_pack1to8 = 0;
  34. pipeline_convolution_pack4to8 = 0;
  35. pipeline_convolution_pack8to1 = 0;
  36. pipeline_convolution_pack8to4 = 0;
  37. winograd_padding = 0;
  38. winograd_crop = 0;
  39. pipeline_convolution_pack4_3x3s1d1_winograd23_transform_input = 0;
  40. pipeline_convolution_pack4_3x3s1d1_winograd23_gemm = 0;
  41. pipeline_convolution_pack4_3x3s1d1_winograd23_transform_output = 0;
  42. pipeline_convolution_pack8_3x3s1d1_winograd23_transform_input = 0;
  43. pipeline_convolution_pack8_3x3s1d1_winograd23_gemm = 0;
  44. pipeline_convolution_pack8_3x3s1d1_winograd23_transform_output = 0;
  45. innerproduct = 0;
  46. }
  47. int Convolution_vulkan::create_pipeline(const Option& opt)
  48. {
  49. const Mat& shape = bottom_shapes.empty() ? Mat() : bottom_shapes[0];
  50. const Mat& out_shape = top_shapes.empty() ? Mat() : top_shapes[0];
  51. const int maxk = kernel_w * kernel_h;
  52. int num_input = weight_data_size / maxk / num_output;
  53. // fc
  54. if (kernel_w == 1 && kernel_h == 1)
  55. {
  56. innerproduct = ncnn::create_layer(ncnn::LayerType::InnerProduct);
  57. innerproduct->vkdev = vkdev;
  58. innerproduct->bottom_shapes.resize(1);
  59. innerproduct->bottom_shapes[0] = shape;
  60. innerproduct->top_shapes.resize(1);
  61. innerproduct->top_shapes[0] = out_shape;
  62. ncnn::ParamDict pd;
  63. pd.set(0, num_output);
  64. pd.set(1, bias_term);
  65. pd.set(2, weight_data_size);// TODO int8
  66. innerproduct->load_param(pd);
  67. ncnn::Mat weights[2];
  68. weights[0] = weight_data;
  69. weights[1] = bias_data;
  70. ncnn::ModelBinFromMatArray mb(weights);
  71. innerproduct->load_model(mb);
  72. innerproduct->create_pipeline(opt);
  73. if (shape.dims == 1 && shape.w == num_input)
  74. {
  75. return 0;
  76. }
  77. }
  78. // the shape after padding
  79. Mat shape_bordered;
  80. if (shape.dims != 0)
  81. {
  82. if (pad_left > 0 || pad_right > 0 || pad_top > 0 || pad_bottom > 0)
  83. {
  84. shape_bordered = Mat(shape.w + pad_left + pad_right, shape.h + pad_top + pad_bottom, shape.c, (void*)0);
  85. }
  86. else if ((pad_left == -233 && pad_right == -233 && pad_top == -233 && pad_bottom == -233)
  87. || (pad_left == -234 && pad_right == -234 && pad_top == -234 && pad_bottom == -234))
  88. {
  89. const int kernel_extent_w = dilation_w * (kernel_w - 1) + 1;
  90. const int kernel_extent_h = dilation_h * (kernel_h - 1) + 1;
  91. int wpad = kernel_extent_w + (shape.w - 1) / stride_w * stride_w - shape.w;
  92. int hpad = kernel_extent_h + (shape.h - 1) / stride_h * stride_h - shape.h;
  93. if (wpad > 0 || hpad > 0)
  94. {
  95. shape_bordered = Mat(shape.w + wpad, shape.h + hpad, shape.c, (void*)0);
  96. }
  97. }
  98. else
  99. {
  100. shape_bordered = shape;
  101. }
  102. }
  103. {
  104. padding = ncnn::create_layer(ncnn::LayerType::Padding);
  105. padding->vkdev = vkdev;
  106. padding->bottom_shapes.resize(1);
  107. padding->bottom_shapes[0] = shape;
  108. padding->top_shapes.resize(1);
  109. padding->top_shapes[0] = shape_bordered;
  110. ncnn::ParamDict pd;
  111. pd.set(0, pad_top);
  112. pd.set(1, pad_bottom);
  113. pd.set(2, pad_left);
  114. pd.set(3, pad_right);
  115. pd.set(4, 0);
  116. pd.set(5, pad_value);
  117. padding->load_param(pd);
  118. padding->create_pipeline(opt);
  119. }
  120. int elempack = opt.use_shader_pack8 && num_input % 8 == 0 ? 8 : num_input % 4 == 0 ? 4 : 1;
  121. int out_elempack = opt.use_shader_pack8 && num_output % 8 == 0 ? 8 : num_output % 4 == 0 ? 4 : 1;
  122. size_t elemsize;
  123. size_t out_elemsize;
  124. if (opt.use_image_storage && opt.use_fp16_storage)
  125. {
  126. elemsize = elempack * 2u;
  127. out_elemsize = out_elempack * 2u;
  128. }
  129. else if (opt.use_image_storage && opt.use_fp16_packed)
  130. {
  131. elemsize = elempack == 1 ? 4u : elempack * 2u;
  132. out_elemsize = out_elempack == 1 ? 4u : out_elempack * 2u;
  133. }
  134. else if (opt.use_image_storage)
  135. {
  136. elemsize = elempack * 4u;
  137. out_elemsize = out_elempack * 4u;
  138. }
  139. else if (opt.use_fp16_storage)
  140. {
  141. elemsize = elempack * 2u;
  142. out_elemsize = out_elempack * 2u;
  143. }
  144. else if (opt.use_fp16_packed)
  145. {
  146. elemsize = elempack == 1 ? 4u : elempack * 2u;
  147. out_elemsize = out_elempack == 1 ? 4u : out_elempack * 2u;
  148. }
  149. else
  150. {
  151. elemsize = elempack * 4u;
  152. out_elemsize = out_elempack * 4u;
  153. }
  154. Mat shape_bordered_packed;
  155. if (shape_bordered.dims == 3) shape_bordered_packed = Mat(shape_bordered.w, shape_bordered.h, num_input / elempack, (void*)0, elemsize, elempack);
  156. Mat out_shape_packed;
  157. if (out_shape.dims == 3) out_shape_packed = Mat(out_shape.w, out_shape.h, num_output / out_elempack, (void*)0, out_elemsize, out_elempack);
  158. std::vector<vk_specialization_type> specializations(10 + 10);
  159. specializations[0].i = kernel_w;
  160. specializations[1].i = kernel_h;
  161. specializations[2].i = dilation_w;
  162. specializations[3].i = dilation_h;
  163. specializations[4].i = stride_w;
  164. specializations[5].i = stride_h;
  165. specializations[6].i = bias_term;
  166. specializations[7].i = activation_type;
  167. specializations[8].f = activation_params.w >= 1 ? activation_params[0] : 0.f;
  168. specializations[9].f = activation_params.w == 2 ? activation_params[1] : 0.f;
  169. specializations[10 + 0].i = shape_bordered_packed.dims;
  170. specializations[10 + 1].i = shape_bordered_packed.w;
  171. specializations[10 + 2].i = shape_bordered_packed.h;
  172. specializations[10 + 3].i = shape_bordered_packed.c;
  173. specializations[10 + 4].i = shape_bordered_packed.cstep;
  174. specializations[10 + 5].i = out_shape_packed.dims;
  175. specializations[10 + 6].i = out_shape_packed.w;
  176. specializations[10 + 7].i = out_shape_packed.h;
  177. specializations[10 + 8].i = out_shape_packed.c;
  178. specializations[10 + 9].i = out_shape_packed.cstep;
  179. Mat local_size_xyz(8, 8, std::min(4, num_output / out_elempack), (void*)0);
  180. if (out_shape_packed.dims != 0)
  181. {
  182. local_size_xyz.w = std::min(8, out_shape_packed.w);
  183. local_size_xyz.h = std::min(8, out_shape_packed.h);
  184. local_size_xyz.c = std::min(4, out_shape_packed.c);
  185. }
  186. bool is_conv1x1s1d1 = kernel_w == 1 && kernel_h == 1 && stride_w == 1 && stride_h == 1 && dilation_w == 1 && dilation_h == 1;
  187. bool is_conv3x3s1d1 = kernel_w == 3 && kernel_h == 3 && stride_w == 1 && stride_h == 1 && dilation_w == 1 && dilation_h == 1;
  188. // pack1
  189. if (elempack == 1 && out_elempack == 1)
  190. {
  191. if (is_conv1x1s1d1)
  192. {
  193. pipeline_convolution_1x1s1d1 = new Pipeline(vkdev);
  194. if (opt.use_image_storage)
  195. {
  196. Mat local_size_xyz_local(4, 4, std::min(4, num_output / out_elempack), (void*)0);
  197. if (out_shape_packed.dims != 0)
  198. {
  199. local_size_xyz_local.w = std::max(1, std::min(4, (out_shape_packed.w + 1) / 2));
  200. local_size_xyz_local.h = std::max(1, std::min(4, (out_shape_packed.h + 1) / 2));
  201. local_size_xyz_local.c = std::min(4, out_shape_packed.c);
  202. }
  203. pipeline_convolution_1x1s1d1->set_optimal_local_size_xyz(local_size_xyz_local);
  204. }
  205. else
  206. {
  207. pipeline_convolution_1x1s1d1->set_local_size_xyz(8, 1, std::min(8, num_output));
  208. }
  209. pipeline_convolution_1x1s1d1->create(LayerShaderType::convolution_1x1s1d1, opt, specializations);
  210. }
  211. else
  212. {
  213. pipeline_convolution = new Pipeline(vkdev);
  214. pipeline_convolution->set_optimal_local_size_xyz(local_size_xyz);
  215. pipeline_convolution->create(LayerShaderType::convolution, opt, specializations);
  216. }
  217. }
  218. // pack4
  219. if (elempack == 4 && out_elempack == 4)
  220. {
  221. if (is_conv1x1s1d1)
  222. {
  223. pipeline_convolution_pack4_1x1s1d1 = new Pipeline(vkdev);
  224. if (opt.use_image_storage)
  225. {
  226. Mat local_size_xyz_local(4, 4, std::min(4, num_output / out_elempack), (void*)0);
  227. if (out_shape_packed.dims != 0)
  228. {
  229. local_size_xyz_local.w = std::max(1, std::min(4, (out_shape_packed.w + 1) / 2));
  230. local_size_xyz_local.h = std::max(1, std::min(4, (out_shape_packed.h + 1) / 2));
  231. local_size_xyz_local.c = std::min(4, out_shape_packed.c);
  232. }
  233. pipeline_convolution_pack4_1x1s1d1->set_optimal_local_size_xyz(local_size_xyz_local);
  234. }
  235. else
  236. {
  237. pipeline_convolution_pack4_1x1s1d1->set_local_size_xyz(8, 1, std::min(8, num_output / 4));
  238. }
  239. pipeline_convolution_pack4_1x1s1d1->create(LayerShaderType::convolution_pack4_1x1s1d1, opt, specializations);
  240. }
  241. else if (is_conv3x3s1d1 && num_input >= 16 && num_output >= 16)
  242. {
  243. // winograd23
  244. int block_x = 0;
  245. int block_y = 0;
  246. Mat shape_winograd_bordered;
  247. Mat shape_winograd_input_transformed;
  248. Mat shape_winograd_gemm;
  249. Mat shape_winograd_out_bordered;
  250. if (out_shape.dims != 0)
  251. {
  252. int outw_bordered = (out_shape.w + 1) / 2 * 2;
  253. int outh_bordered = (out_shape.h + 1) / 2 * 2;
  254. int w_bordered = outw_bordered + 2;
  255. int h_bordered = outh_bordered + 2;
  256. block_x = outw_bordered / 2;
  257. block_y = outh_bordered / 2;
  258. shape_winograd_bordered = Mat(w_bordered, h_bordered, shape.c, (void*)0);
  259. shape_winograd_input_transformed = Mat(16, block_x * block_y, shape.c, (void*)0);
  260. shape_winograd_gemm = Mat(16, block_x * block_y, out_shape.c, (void*)0);
  261. shape_winograd_out_bordered = Mat(outw_bordered, outh_bordered, out_shape.c, (void*)0);
  262. }
  263. Mat shape_winograd_bordered_packed;
  264. if (shape_winograd_bordered.dims == 3) shape_winograd_bordered_packed = Mat(shape_winograd_bordered.w, shape_winograd_bordered.h, shape_winograd_bordered.c / elempack, (void*)0, elemsize, elempack);
  265. Mat shape_winograd_input_transformed_packed;
  266. if (shape_winograd_input_transformed.dims == 3) shape_winograd_input_transformed_packed = Mat(shape_winograd_input_transformed.w, shape_winograd_input_transformed.h, shape_winograd_input_transformed.c / elempack, (void*)0, elemsize, elempack);
  267. Mat shape_winograd_gemm_packed;
  268. if (shape_winograd_gemm.dims == 3) shape_winograd_gemm_packed = Mat(shape_winograd_gemm.w, shape_winograd_gemm.h, shape_winograd_gemm.c / out_elempack, (void*)0, out_elemsize, out_elempack);
  269. Mat shape_winograd_out_bordered_packed;
  270. if (shape_winograd_out_bordered.dims == 3) shape_winograd_out_bordered_packed = Mat(shape_winograd_out_bordered.w, shape_winograd_out_bordered.h, shape_winograd_out_bordered.c / out_elempack, (void*)0, out_elemsize, out_elempack);
  271. {
  272. winograd_padding = ncnn::create_layer(ncnn::LayerType::Padding);
  273. winograd_padding->vkdev = vkdev;
  274. winograd_padding->bottom_shapes.resize(1);
  275. winograd_padding->bottom_shapes[0] = shape_bordered;
  276. winograd_padding->top_shapes.resize(1);
  277. winograd_padding->top_shapes[0] = shape_winograd_bordered;
  278. ncnn::ParamDict pd;
  279. pd.set(0, -233);
  280. pd.set(1, -233);
  281. pd.set(2, -233);
  282. pd.set(3, -233);
  283. pd.set(4, 0);
  284. pd.set(5, 0.f);
  285. winograd_padding->load_param(pd);
  286. winograd_padding->create_pipeline(opt);
  287. }
  288. {
  289. winograd_crop = ncnn::create_layer(ncnn::LayerType::Crop);
  290. winograd_crop->vkdev = vkdev;
  291. winograd_crop->bottom_shapes.resize(1);
  292. winograd_crop->bottom_shapes[0] = shape_winograd_out_bordered;
  293. winograd_crop->top_shapes.resize(1);
  294. winograd_crop->top_shapes[0] = out_shape;
  295. ncnn::ParamDict pd;
  296. pd.set(0, -233);
  297. pd.set(1, -233);
  298. pd.set(2, -233);
  299. pd.set(3, 0);
  300. pd.set(4, 0);
  301. pd.set(5, 0);
  302. winograd_crop->load_param(pd);
  303. winograd_crop->create_pipeline(opt);
  304. }
  305. {
  306. std::vector<vk_specialization_type> specializations(0 + 7);
  307. specializations[0 + 0].i = shape_winograd_bordered_packed.w;
  308. specializations[0 + 1].i = shape_winograd_bordered_packed.h;
  309. specializations[0 + 2].i = shape_winograd_bordered_packed.c;
  310. specializations[0 + 3].i = shape_winograd_bordered_packed.cstep;
  311. specializations[0 + 4].i = shape_winograd_input_transformed_packed.cstep;
  312. specializations[0 + 5].i = block_x;
  313. specializations[0 + 6].i = block_y;
  314. pipeline_convolution_pack4_3x3s1d1_winograd23_transform_input = new Pipeline(vkdev);
  315. pipeline_convolution_pack4_3x3s1d1_winograd23_transform_input->set_local_size_xyz(8, 8, 1);
  316. pipeline_convolution_pack4_3x3s1d1_winograd23_transform_input->create(LayerShaderType::convolution_pack4_3x3s1d1_winograd23_transform_input, opt, specializations);
  317. }
  318. {
  319. std::vector<vk_specialization_type> specializations(0 + 5);
  320. specializations[0 + 0].i = shape_winograd_input_transformed_packed.c;
  321. specializations[0 + 1].i = shape_winograd_input_transformed_packed.cstep;
  322. specializations[0 + 2].i = shape_winograd_gemm_packed.h;
  323. specializations[0 + 3].i = shape_winograd_gemm_packed.c;
  324. specializations[0 + 4].i = shape_winograd_gemm_packed.cstep;
  325. pipeline_convolution_pack4_3x3s1d1_winograd23_gemm = new Pipeline(vkdev);
  326. pipeline_convolution_pack4_3x3s1d1_winograd23_gemm->set_local_size_xyz(4, 4, std::min(4, num_output / 4));
  327. pipeline_convolution_pack4_3x3s1d1_winograd23_gemm->create(LayerShaderType::convolution_pack4_3x3s1d1_winograd23_gemm, opt, specializations);
  328. }
  329. {
  330. std::vector<vk_specialization_type> specializations(4 + 7);
  331. specializations[0].i = bias_term;
  332. specializations[1].i = activation_type;
  333. specializations[2].f = activation_params.w >= 1 ? activation_params[0] : 0.f;
  334. specializations[3].f = activation_params.w == 2 ? activation_params[1] : 0.f;
  335. specializations[4 + 0].i = shape_winograd_gemm_packed.c;
  336. specializations[4 + 1].i = shape_winograd_gemm_packed.cstep;
  337. specializations[4 + 2].i = block_x;
  338. specializations[4 + 3].i = block_y;
  339. specializations[4 + 4].i = shape_winograd_out_bordered_packed.w;
  340. specializations[4 + 5].i = shape_winograd_out_bordered_packed.h;
  341. specializations[4 + 6].i = shape_winograd_out_bordered_packed.cstep;
  342. pipeline_convolution_pack4_3x3s1d1_winograd23_transform_output = new Pipeline(vkdev);
  343. pipeline_convolution_pack4_3x3s1d1_winograd23_transform_output->set_local_size_xyz(8, 8, 1);
  344. pipeline_convolution_pack4_3x3s1d1_winograd23_transform_output->create(LayerShaderType::convolution_pack4_3x3s1d1_winograd23_transform_output, opt, specializations);
  345. }
  346. }
  347. else
  348. {
  349. pipeline_convolution_pack4 = new Pipeline(vkdev);
  350. pipeline_convolution_pack4->set_optimal_local_size_xyz(local_size_xyz);
  351. pipeline_convolution_pack4->create(LayerShaderType::convolution_pack4, opt, specializations);
  352. }
  353. }
  354. // pack1to4
  355. if (elempack == 1 && out_elempack == 4)
  356. {
  357. pipeline_convolution_pack1to4 = new Pipeline(vkdev);
  358. pipeline_convolution_pack1to4->set_optimal_local_size_xyz(local_size_xyz);
  359. pipeline_convolution_pack1to4->create(LayerShaderType::convolution_pack1to4, opt, specializations);
  360. }
  361. // pack4to1
  362. if (elempack == 4 && out_elempack == 1)
  363. {
  364. pipeline_convolution_pack4to1 = new Pipeline(vkdev);
  365. pipeline_convolution_pack4to1->set_optimal_local_size_xyz(local_size_xyz);
  366. pipeline_convolution_pack4to1->create(LayerShaderType::convolution_pack4to1, opt, specializations);
  367. }
  368. // pack8
  369. if (elempack == 8 && out_elempack == 8)
  370. {
  371. if (is_conv1x1s1d1)
  372. {
  373. pipeline_convolution_pack8_1x1s1d1 = new Pipeline(vkdev);
  374. if (opt.use_image_storage)
  375. {
  376. Mat local_size_xyz_local(4, 4, std::min(4, num_output / out_elempack), (void*)0);
  377. if (out_shape_packed.dims != 0)
  378. {
  379. local_size_xyz_local.w = std::max(1, std::min(4, (out_shape_packed.w + 1) / 2));
  380. local_size_xyz_local.h = std::max(1, std::min(4, (out_shape_packed.h + 1) / 2));
  381. local_size_xyz_local.c = std::min(4, out_shape_packed.c);
  382. }
  383. pipeline_convolution_pack8_1x1s1d1->set_optimal_local_size_xyz(local_size_xyz_local);
  384. }
  385. else
  386. {
  387. pipeline_convolution_pack8_1x1s1d1->set_local_size_xyz(8, 1, std::min(8, num_output / 8));
  388. }
  389. pipeline_convolution_pack8_1x1s1d1->create(LayerShaderType::convolution_pack8_1x1s1d1, opt, specializations);
  390. }
  391. else if (is_conv3x3s1d1 && num_input >= 16 && num_output >= 16)
  392. {
  393. // winograd23
  394. int block_x = 0;
  395. int block_y = 0;
  396. Mat shape_winograd_bordered;
  397. Mat shape_winograd_input_transformed;
  398. Mat shape_winograd_gemm;
  399. Mat shape_winograd_out_bordered;
  400. if (out_shape.dims != 0)
  401. {
  402. int outw_bordered = (out_shape.w + 1) / 2 * 2;
  403. int outh_bordered = (out_shape.h + 1) / 2 * 2;
  404. int w_bordered = outw_bordered + 2;
  405. int h_bordered = outh_bordered + 2;
  406. block_x = outw_bordered / 2;
  407. block_y = outh_bordered / 2;
  408. shape_winograd_bordered = Mat(w_bordered, h_bordered, shape.c, (void*)0);
  409. shape_winograd_input_transformed = Mat(16, block_x * block_y, shape.c, (void*)0);
  410. shape_winograd_gemm = Mat(16, block_x * block_y, out_shape.c, (void*)0);
  411. shape_winograd_out_bordered = Mat(outw_bordered, outh_bordered, out_shape.c, (void*)0);
  412. }
  413. Mat shape_winograd_bordered_packed;
  414. if (shape_winograd_bordered.dims == 3) shape_winograd_bordered_packed = Mat(shape_winograd_bordered.w, shape_winograd_bordered.h, shape_winograd_bordered.c / elempack, (void*)0, elemsize, elempack);
  415. Mat shape_winograd_input_transformed_packed;
  416. if (shape_winograd_input_transformed.dims == 3) shape_winograd_input_transformed_packed = Mat(shape_winograd_input_transformed.w, shape_winograd_input_transformed.h, shape_winograd_input_transformed.c / elempack, (void*)0, elemsize, elempack);
  417. Mat shape_winograd_gemm_packed;
  418. if (shape_winograd_gemm.dims == 3) shape_winograd_gemm_packed = Mat(shape_winograd_gemm.w, shape_winograd_gemm.h, shape_winograd_gemm.c / out_elempack, (void*)0, out_elemsize, out_elempack);
  419. Mat shape_winograd_out_bordered_packed;
  420. if (shape_winograd_out_bordered.dims == 3) shape_winograd_out_bordered_packed = Mat(shape_winograd_out_bordered.w, shape_winograd_out_bordered.h, shape_winograd_out_bordered.c / out_elempack, (void*)0, out_elemsize, out_elempack);
  421. {
  422. winograd_padding = ncnn::create_layer(ncnn::LayerType::Padding);
  423. winograd_padding->vkdev = vkdev;
  424. winograd_padding->bottom_shapes.resize(1);
  425. winograd_padding->bottom_shapes[0] = shape_bordered;
  426. winograd_padding->top_shapes.resize(1);
  427. winograd_padding->top_shapes[0] = shape_winograd_bordered;
  428. ncnn::ParamDict pd;
  429. pd.set(0, -233);
  430. pd.set(1, -233);
  431. pd.set(2, -233);
  432. pd.set(3, -233);
  433. pd.set(4, 0);
  434. pd.set(5, 0.f);
  435. winograd_padding->load_param(pd);
  436. winograd_padding->create_pipeline(opt);
  437. }
  438. {
  439. winograd_crop = ncnn::create_layer(ncnn::LayerType::Crop);
  440. winograd_crop->vkdev = vkdev;
  441. winograd_crop->bottom_shapes.resize(1);
  442. winograd_crop->bottom_shapes[0] = shape_winograd_out_bordered;
  443. winograd_crop->top_shapes.resize(1);
  444. winograd_crop->top_shapes[0] = out_shape;
  445. ncnn::ParamDict pd;
  446. pd.set(0, -233);
  447. pd.set(1, -233);
  448. pd.set(2, -233);
  449. pd.set(3, 0);
  450. pd.set(4, 0);
  451. pd.set(5, 0);
  452. winograd_crop->load_param(pd);
  453. winograd_crop->create_pipeline(opt);
  454. }
  455. {
  456. std::vector<vk_specialization_type> specializations(0 + 7);
  457. specializations[0 + 0].i = shape_winograd_bordered_packed.w;
  458. specializations[0 + 1].i = shape_winograd_bordered_packed.h;
  459. specializations[0 + 2].i = shape_winograd_bordered_packed.c;
  460. specializations[0 + 3].i = shape_winograd_bordered_packed.cstep;
  461. specializations[0 + 4].i = shape_winograd_input_transformed_packed.cstep;
  462. specializations[0 + 5].i = block_x;
  463. specializations[0 + 6].i = block_y;
  464. pipeline_convolution_pack8_3x3s1d1_winograd23_transform_input = new Pipeline(vkdev);
  465. pipeline_convolution_pack8_3x3s1d1_winograd23_transform_input->set_local_size_xyz(8, 8, 1);
  466. pipeline_convolution_pack8_3x3s1d1_winograd23_transform_input->create(LayerShaderType::convolution_pack8_3x3s1d1_winograd23_transform_input, opt, specializations);
  467. }
  468. {
  469. std::vector<vk_specialization_type> specializations(0 + 5);
  470. specializations[0 + 0].i = shape_winograd_input_transformed_packed.c;
  471. specializations[0 + 1].i = shape_winograd_input_transformed_packed.cstep;
  472. specializations[0 + 2].i = shape_winograd_gemm_packed.h;
  473. specializations[0 + 3].i = shape_winograd_gemm_packed.c;
  474. specializations[0 + 4].i = shape_winograd_gemm_packed.cstep;
  475. pipeline_convolution_pack8_3x3s1d1_winograd23_gemm = new Pipeline(vkdev);
  476. pipeline_convolution_pack8_3x3s1d1_winograd23_gemm->set_local_size_xyz(4, 4, std::min(4, num_output / 8));
  477. pipeline_convolution_pack8_3x3s1d1_winograd23_gemm->create(LayerShaderType::convolution_pack8_3x3s1d1_winograd23_gemm, opt, specializations);
  478. }
  479. {
  480. std::vector<vk_specialization_type> specializations(4 + 7);
  481. specializations[0].i = bias_term;
  482. specializations[1].i = activation_type;
  483. specializations[2].f = activation_params.w >= 1 ? activation_params[0] : 0.f;
  484. specializations[3].f = activation_params.w == 2 ? activation_params[1] : 0.f;
  485. specializations[4 + 0].i = shape_winograd_gemm_packed.c;
  486. specializations[4 + 1].i = shape_winograd_gemm_packed.cstep;
  487. specializations[4 + 2].i = block_x;
  488. specializations[4 + 3].i = block_y;
  489. specializations[4 + 4].i = shape_winograd_out_bordered_packed.w;
  490. specializations[4 + 5].i = shape_winograd_out_bordered_packed.h;
  491. specializations[4 + 6].i = shape_winograd_out_bordered_packed.cstep;
  492. pipeline_convolution_pack8_3x3s1d1_winograd23_transform_output = new Pipeline(vkdev);
  493. pipeline_convolution_pack8_3x3s1d1_winograd23_transform_output->set_local_size_xyz(8, 8, 1);
  494. pipeline_convolution_pack8_3x3s1d1_winograd23_transform_output->create(LayerShaderType::convolution_pack8_3x3s1d1_winograd23_transform_output, opt, specializations);
  495. }
  496. }
  497. else
  498. {
  499. pipeline_convolution_pack8 = new Pipeline(vkdev);
  500. pipeline_convolution_pack8->set_optimal_local_size_xyz(local_size_xyz);
  501. pipeline_convolution_pack8->create(LayerShaderType::convolution_pack8, opt, specializations);
  502. }
  503. }
  504. // pack1to8
  505. if (elempack == 1 && out_elempack == 8)
  506. {
  507. pipeline_convolution_pack1to8 = new Pipeline(vkdev);
  508. pipeline_convolution_pack1to8->set_optimal_local_size_xyz(local_size_xyz);
  509. pipeline_convolution_pack1to8->create(LayerShaderType::convolution_pack1to8, opt, specializations);
  510. }
  511. // pack4to8
  512. if (elempack == 4 && out_elempack == 8)
  513. {
  514. pipeline_convolution_pack4to8 = new Pipeline(vkdev);
  515. pipeline_convolution_pack4to8->set_optimal_local_size_xyz(local_size_xyz);
  516. pipeline_convolution_pack4to8->create(LayerShaderType::convolution_pack4to8, opt, specializations);
  517. }
  518. // pack8to4
  519. if (elempack == 8 && out_elempack == 4)
  520. {
  521. pipeline_convolution_pack8to4 = new Pipeline(vkdev);
  522. pipeline_convolution_pack8to4->set_optimal_local_size_xyz(local_size_xyz);
  523. pipeline_convolution_pack8to4->create(LayerShaderType::convolution_pack8to4, opt, specializations);
  524. }
  525. // pack8to1
  526. if (elempack == 8 && out_elempack == 1)
  527. {
  528. pipeline_convolution_pack8to1 = new Pipeline(vkdev);
  529. pipeline_convolution_pack8to1->set_optimal_local_size_xyz(local_size_xyz);
  530. pipeline_convolution_pack8to1->create(LayerShaderType::convolution_pack8to1, opt, specializations);
  531. }
  532. return 0;
  533. }
  534. int Convolution_vulkan::destroy_pipeline(const Option& opt)
  535. {
  536. if (padding)
  537. {
  538. padding->destroy_pipeline(opt);
  539. delete padding;
  540. padding = 0;
  541. }
  542. delete pipeline_convolution;
  543. pipeline_convolution = 0;
  544. delete pipeline_convolution_1x1s1d1;
  545. pipeline_convolution_1x1s1d1 = 0;
  546. delete pipeline_convolution_pack4;
  547. pipeline_convolution_pack4 = 0;
  548. delete pipeline_convolution_pack4_1x1s1d1;
  549. pipeline_convolution_pack4_1x1s1d1 = 0;
  550. delete pipeline_convolution_pack1to4;
  551. pipeline_convolution_pack1to4 = 0;
  552. delete pipeline_convolution_pack4to1;
  553. pipeline_convolution_pack4to1 = 0;
  554. delete pipeline_convolution_pack8;
  555. pipeline_convolution_pack8 = 0;
  556. delete pipeline_convolution_pack8_1x1s1d1;
  557. pipeline_convolution_pack8_1x1s1d1 = 0;
  558. delete pipeline_convolution_pack1to8;
  559. pipeline_convolution_pack1to8 = 0;
  560. delete pipeline_convolution_pack4to8;
  561. pipeline_convolution_pack4to8 = 0;
  562. delete pipeline_convolution_pack8to4;
  563. pipeline_convolution_pack8to4 = 0;
  564. delete pipeline_convolution_pack8to1;
  565. pipeline_convolution_pack8to1 = 0;
  566. if (winograd_padding)
  567. {
  568. winograd_padding->destroy_pipeline(opt);
  569. delete winograd_padding;
  570. winograd_padding = 0;
  571. }
  572. if (winograd_crop)
  573. {
  574. winograd_crop->destroy_pipeline(opt);
  575. delete winograd_crop;
  576. winograd_crop = 0;
  577. }
  578. delete pipeline_convolution_pack4_3x3s1d1_winograd23_transform_input;
  579. delete pipeline_convolution_pack4_3x3s1d1_winograd23_gemm;
  580. delete pipeline_convolution_pack4_3x3s1d1_winograd23_transform_output;
  581. pipeline_convolution_pack4_3x3s1d1_winograd23_transform_input = 0;
  582. pipeline_convolution_pack4_3x3s1d1_winograd23_gemm = 0;
  583. pipeline_convolution_pack4_3x3s1d1_winograd23_transform_output = 0;
  584. delete pipeline_convolution_pack8_3x3s1d1_winograd23_transform_input;
  585. delete pipeline_convolution_pack8_3x3s1d1_winograd23_gemm;
  586. delete pipeline_convolution_pack8_3x3s1d1_winograd23_transform_output;
  587. pipeline_convolution_pack8_3x3s1d1_winograd23_transform_input = 0;
  588. pipeline_convolution_pack8_3x3s1d1_winograd23_gemm = 0;
  589. pipeline_convolution_pack8_3x3s1d1_winograd23_transform_output = 0;
  590. // fc
  591. if (innerproduct)
  592. {
  593. innerproduct->destroy_pipeline(opt);
  594. delete innerproduct;
  595. innerproduct = 0;
  596. }
  597. return 0;
  598. }
  599. int Convolution_vulkan::upload_model(VkTransfer& cmd, const Option& opt)
  600. {
  601. if (padding)
  602. {
  603. padding->upload_model(cmd, opt);
  604. }
  605. if (winograd_padding)
  606. {
  607. winograd_padding->upload_model(cmd, opt);
  608. }
  609. if (winograd_crop)
  610. {
  611. winograd_crop->upload_model(cmd, opt);
  612. }
  613. const int maxk = kernel_w * kernel_h;
  614. int num_input = weight_data_size / maxk / num_output;
  615. int elempack = opt.use_shader_pack8 && num_input % 8 == 0 ? 8 : num_input % 4 == 0 ? 4 : 1;
  616. int out_elempack = opt.use_shader_pack8 && num_output % 8 == 0 ? 8 : num_output % 4 == 0 ? 4 : 1;
  617. // src = kw-kh-inch-outch
  618. // dst = pa-pb-kw-kh-inch/pa-outch/pb
  619. Mat weight_data_packed;
  620. {
  621. Mat weight_data_r2 = weight_data.reshape(maxk, num_input, num_output);
  622. weight_data_packed.create(maxk, num_input/elempack, num_output/out_elempack, (size_t)4*elempack*out_elempack, elempack*out_elempack);
  623. for (int q=0; q+(out_elempack-1)<num_output; q+=out_elempack)
  624. {
  625. Mat g0 = weight_data_packed.channel(q/out_elempack);
  626. for (int p=0; p+(elempack-1)<num_input; p+=elempack)
  627. {
  628. float* g00 = g0.row(p/elempack);
  629. for (int k=0; k<maxk; k++)
  630. {
  631. for (int i=0; i<out_elempack; i++)
  632. {
  633. const Mat k0 = weight_data_r2.channel(q+i);
  634. for (int j=0; j<elempack; j++)
  635. {
  636. const float* k00 = k0.row(p+j);
  637. g00[0] = k00[k];
  638. g00++;
  639. }
  640. }
  641. }
  642. }
  643. }
  644. }
  645. if (opt.use_image_storage)
  646. {
  647. cmd.record_upload(weight_data_packed, weight_data_gpu_image, opt);
  648. }
  649. else
  650. {
  651. cmd.record_upload(weight_data_packed, weight_data_gpu, opt);
  652. }
  653. bool is_conv3x3s1d1 = kernel_w == 3 && kernel_h == 3 && stride_w == 1 && stride_h == 1 && dilation_w == 1 && dilation_h == 1;
  654. // pack4
  655. if (elempack == 4 && out_elempack == 4)
  656. {
  657. if (is_conv3x3s1d1 && num_input >= 16 && num_output >= 16)
  658. {
  659. // winograd23 transform kernel
  660. Mat weight_data_tm;
  661. weight_data_tm.create(4*4, num_input, num_output);
  662. // G
  663. const float ktm[4][3] = {
  664. { 1.0f, 0.0f, 0.0f},
  665. { 1.0f/2, 1.0f/2, 1.0f/2},
  666. { 1.0f/2, -1.0f/2, 1.0f/2},
  667. { 0.0f, 0.0f, 1.0f}
  668. };
  669. #pragma omp parallel for
  670. for (int p = 0; p<num_output; p++)
  671. {
  672. for (int q = 0; q<num_input; q++)
  673. {
  674. const float* kernel0 = (const float*)weight_data + p*num_input * 9 + q * 9;
  675. float* kernel_tm0 = weight_data_tm.channel(p).row(q);
  676. // transform kernel
  677. const float* k0 = kernel0;
  678. const float* k1 = kernel0 + 3;
  679. const float* k2 = kernel0 + 6;
  680. // h
  681. float tmp[4][3];
  682. for (int i=0; i<4; i++)
  683. {
  684. tmp[i][0] = k0[0] * ktm[i][0] + k0[1] * ktm[i][1] + k0[2] * ktm[i][2];
  685. tmp[i][1] = k1[0] * ktm[i][0] + k1[1] * ktm[i][1] + k1[2] * ktm[i][2];
  686. tmp[i][2] = k2[0] * ktm[i][0] + k2[1] * ktm[i][1] + k2[2] * ktm[i][2];
  687. }
  688. // U
  689. for (int j=0; j<4; j++)
  690. {
  691. float* tmpp = &tmp[j][0];
  692. for (int i=0; i<4; i++)
  693. {
  694. kernel_tm0[j*4 + i] = tmpp[0] * ktm[i][0] + tmpp[1] * ktm[i][1] + tmpp[2] * ktm[i][2];
  695. }
  696. }
  697. }
  698. }
  699. // src = 16-inch-outch
  700. // dst = 4a-4b-16-inch/4a-outch/4b
  701. Mat weight_data_pack4_tm;
  702. {
  703. weight_data_pack4_tm.create(16, num_input/4, num_output/4, (size_t)4*16, 16);
  704. for (int q=0; q+3<num_output; q+=4)
  705. {
  706. const Mat k0 = weight_data_tm.channel(q);
  707. const Mat k1 = weight_data_tm.channel(q+1);
  708. const Mat k2 = weight_data_tm.channel(q+2);
  709. const Mat k3 = weight_data_tm.channel(q+3);
  710. Mat g0 = weight_data_pack4_tm.channel(q/4);
  711. for (int p=0; p+3<num_input; p+=4)
  712. {
  713. const float* k00 = k0.row(p);
  714. const float* k01 = k0.row(p+1);
  715. const float* k02 = k0.row(p+2);
  716. const float* k03 = k0.row(p+3);
  717. const float* k10 = k1.row(p);
  718. const float* k11 = k1.row(p+1);
  719. const float* k12 = k1.row(p+2);
  720. const float* k13 = k1.row(p+3);
  721. const float* k20 = k2.row(p);
  722. const float* k21 = k2.row(p+1);
  723. const float* k22 = k2.row(p+2);
  724. const float* k23 = k2.row(p+3);
  725. const float* k30 = k3.row(p);
  726. const float* k31 = k3.row(p+1);
  727. const float* k32 = k3.row(p+2);
  728. const float* k33 = k3.row(p+3);
  729. float* g00 = g0.row(p/4);
  730. for (int k=0; k<16; k++)
  731. {
  732. g00[0] = k00[k];
  733. g00[1] = k01[k];
  734. g00[2] = k02[k];
  735. g00[3] = k03[k];
  736. g00[4] = k10[k];
  737. g00[5] = k11[k];
  738. g00[6] = k12[k];
  739. g00[7] = k13[k];
  740. g00[8] = k20[k];
  741. g00[9] = k21[k];
  742. g00[10] = k22[k];
  743. g00[11] = k23[k];
  744. g00[12] = k30[k];
  745. g00[13] = k31[k];
  746. g00[14] = k32[k];
  747. g00[15] = k33[k];
  748. g00 += 16;
  749. }
  750. }
  751. }
  752. }
  753. if (opt.use_image_storage)
  754. {
  755. cmd.record_upload(weight_data_pack4_tm, weight_data_gpu_pack4_tm_image, opt);
  756. }
  757. else
  758. {
  759. cmd.record_upload(weight_data_pack4_tm, weight_data_gpu_pack4_tm, opt);
  760. }
  761. }
  762. }
  763. // pack8
  764. if (elempack == 8 && out_elempack == 8)
  765. {
  766. if (is_conv3x3s1d1 && num_input >= 16 && num_output >= 16)
  767. {
  768. // winograd23 transform kernel
  769. Mat weight_data_tm;
  770. weight_data_tm.create(4*4, num_input, num_output);
  771. // G
  772. const float ktm[4][3] = {
  773. { 1.0f, 0.0f, 0.0f},
  774. { 1.0f/2, 1.0f/2, 1.0f/2},
  775. { 1.0f/2, -1.0f/2, 1.0f/2},
  776. { 0.0f, 0.0f, 1.0f}
  777. };
  778. #pragma omp parallel for
  779. for (int p = 0; p<num_output; p++)
  780. {
  781. for (int q = 0; q<num_input; q++)
  782. {
  783. const float* kernel0 = (const float*)weight_data + p*num_input * 9 + q * 9;
  784. float* kernel_tm0 = weight_data_tm.channel(p).row(q);
  785. // transform kernel
  786. const float* k0 = kernel0;
  787. const float* k1 = kernel0 + 3;
  788. const float* k2 = kernel0 + 6;
  789. // h
  790. float tmp[4][3];
  791. for (int i=0; i<4; i++)
  792. {
  793. tmp[i][0] = k0[0] * ktm[i][0] + k0[1] * ktm[i][1] + k0[2] * ktm[i][2];
  794. tmp[i][1] = k1[0] * ktm[i][0] + k1[1] * ktm[i][1] + k1[2] * ktm[i][2];
  795. tmp[i][2] = k2[0] * ktm[i][0] + k2[1] * ktm[i][1] + k2[2] * ktm[i][2];
  796. }
  797. // U
  798. for (int j=0; j<4; j++)
  799. {
  800. float* tmpp = &tmp[j][0];
  801. for (int i=0; i<4; i++)
  802. {
  803. kernel_tm0[j*4 + i] = tmpp[0] * ktm[i][0] + tmpp[1] * ktm[i][1] + tmpp[2] * ktm[i][2];
  804. }
  805. }
  806. }
  807. }
  808. // src = 64-inch-outch
  809. // dst = 8a-8b-16-inch/8a-outch/8b
  810. Mat weight_data_pack8_tm;
  811. {
  812. weight_data_pack8_tm.create(16, num_input/8, num_output/8, (size_t)4*64, 64);
  813. for (int q=0; q+7<num_output; q+=8)
  814. {
  815. Mat g0 = weight_data_pack8_tm.channel(q/8);
  816. for (int p=0; p+7<num_input; p+=8)
  817. {
  818. float* g00 = g0.row(p/8);
  819. for (int k=0; k<16; k++)
  820. {
  821. for (int i=0; i<8; i++)
  822. {
  823. const Mat k0 = weight_data_tm.channel(q+i);
  824. for (int j=0; j<8; j++)
  825. {
  826. const float* k00 = k0.row(p+j);
  827. g00[0] = k00[k];
  828. g00++;
  829. }
  830. }
  831. }
  832. }
  833. }
  834. }
  835. if (opt.use_image_storage)
  836. {
  837. cmd.record_upload(weight_data_pack8_tm, weight_data_gpu_pack8_tm_image, opt);
  838. }
  839. else
  840. {
  841. cmd.record_upload(weight_data_pack8_tm, weight_data_gpu_pack8_tm, opt);
  842. }
  843. }
  844. }
  845. if (bias_term)
  846. {
  847. Mat bias_data_packed;
  848. convert_packing(bias_data, bias_data_packed, out_elempack);
  849. if (opt.use_image_storage)
  850. {
  851. cmd.record_upload(bias_data_packed, bias_data_gpu_image, opt);
  852. }
  853. else
  854. {
  855. cmd.record_upload(bias_data_packed, bias_data_gpu, opt);
  856. }
  857. }
  858. if (innerproduct)
  859. {
  860. innerproduct->upload_model(cmd, opt);
  861. }
  862. return 0;
  863. }
  864. int Convolution_vulkan::forward(const VkMat& bottom_blob, VkMat& top_blob, VkCompute& cmd, const Option& opt) const
  865. {
  866. int w = bottom_blob.w;
  867. int h = bottom_blob.h;
  868. int channels = bottom_blob.c;
  869. size_t elemsize = bottom_blob.elemsize;
  870. int elempack = bottom_blob.elempack;
  871. // flattened blob, implement as InnerProduct
  872. if (bottom_blob.dims == 1 && kernel_w == 1 && kernel_h == 1)
  873. {
  874. int num_input = weight_data_size / num_output;
  875. if (bottom_blob.w * bottom_blob.elempack == num_input)
  876. {
  877. return innerproduct->forward(bottom_blob, top_blob, cmd, opt);
  878. }
  879. }
  880. const int kernel_extent_w = dilation_w * (kernel_w - 1) + 1;
  881. const int kernel_extent_h = dilation_h * (kernel_h - 1) + 1;
  882. VkMat bottom_blob_bordered = bottom_blob;
  883. if (pad_left > 0 || pad_right > 0 || pad_top > 0 || pad_bottom > 0)
  884. {
  885. Option opt_pad = opt;
  886. opt_pad.blob_vkallocator = opt.workspace_vkallocator;
  887. padding->forward(bottom_blob, bottom_blob_bordered, cmd, opt_pad);
  888. }
  889. else if (pad_left == -233 && pad_right == -233 && pad_top == -233 && pad_bottom == -233)
  890. {
  891. int wpad = kernel_extent_w + (w - 1) / stride_w * stride_w - w;
  892. int hpad = kernel_extent_h + (h - 1) / stride_h * stride_h - h;
  893. if (wpad > 0 || hpad > 0)
  894. {
  895. Option opt_pad = opt;
  896. opt_pad.blob_vkallocator = opt.workspace_vkallocator;
  897. VkMat padding_param_blob(4, (size_t)4u, 1, opt.staging_vkallocator);
  898. int* padding_params = padding_param_blob.mapped();
  899. padding_params[0] = hpad / 2;
  900. padding_params[1] = hpad - hpad / 2;
  901. padding_params[2] = wpad / 2;
  902. padding_params[3] = wpad - wpad / 2;
  903. std::vector<VkMat> padding_inputs(2);
  904. padding_inputs[0] = bottom_blob;
  905. padding_inputs[1] = padding_param_blob;
  906. std::vector<VkMat> padding_outputs(1);
  907. padding->forward(padding_inputs, padding_outputs, cmd, opt_pad);
  908. bottom_blob_bordered = padding_outputs[0];
  909. }
  910. }
  911. else if (pad_left == -234 && pad_right == -234 && pad_top == -234 && pad_bottom == -234)
  912. {
  913. int wpad = kernel_extent_w + (w - 1) / stride_w * stride_w - w;
  914. int hpad = kernel_extent_h + (h - 1) / stride_h * stride_h - h;
  915. if (wpad > 0 || hpad > 0)
  916. {
  917. Option opt_pad = opt;
  918. opt_pad.blob_vkallocator = opt.workspace_vkallocator;
  919. VkMat padding_param_blob(4, (size_t)4u, 1, opt.staging_vkallocator);
  920. int* padding_params = padding_param_blob.mapped();
  921. padding_params[0] = hpad - hpad / 2;
  922. padding_params[1] = hpad / 2;
  923. padding_params[2] = wpad - wpad / 2;
  924. padding_params[3] = wpad / 2;
  925. std::vector<VkMat> padding_inputs(2);
  926. padding_inputs[0] = bottom_blob;
  927. padding_inputs[1] = padding_param_blob;
  928. std::vector<VkMat> padding_outputs(1);
  929. padding->forward(padding_inputs, padding_outputs, cmd, opt_pad);
  930. bottom_blob_bordered = padding_outputs[0];
  931. }
  932. }
  933. w = bottom_blob_bordered.w;
  934. h = bottom_blob_bordered.h;
  935. int outw = (w - kernel_extent_w) / stride_w + 1;
  936. int outh = (h - kernel_extent_h) / stride_h + 1;
  937. int out_elempack = opt.use_shader_pack8 && num_output % 8 == 0 ? 8 : num_output % 4 == 0 ? 4 : 1;
  938. size_t out_elemsize = elemsize / elempack * out_elempack;
  939. if (opt.use_fp16_packed && !opt.use_fp16_storage)
  940. {
  941. if (out_elempack == 8) out_elemsize = 8*2u;
  942. if (out_elempack == 4) out_elemsize = 4*2u;
  943. if (out_elempack == 1) out_elemsize = 4u;
  944. }
  945. bool is_conv3x3s1d1 = kernel_w == 3 && kernel_h == 3 && stride_w == 1 && stride_h == 1 && dilation_w == 1 && dilation_h == 1;
  946. if (elempack == 4 && out_elempack == 4 && is_conv3x3s1d1 && channels * elempack >= 16 && num_output >= 16)
  947. {
  948. // winograd23
  949. int outw_bordered = (outw + 1) / 2 * 2;
  950. int outh_bordered = (outh + 1) / 2 * 2;
  951. int w_bordered = outw_bordered + 2;
  952. int h_bordered = outh_bordered + 2;
  953. int block_x = outw_bordered / 2;
  954. int block_y = outh_bordered / 2;
  955. // pad to 2n+2
  956. {
  957. Option opt_pad = opt;
  958. opt_pad.blob_vkallocator = opt.workspace_vkallocator;
  959. VkMat padding_param_blob(4, (size_t)4u, 1, opt.staging_vkallocator);
  960. int* padding_params = padding_param_blob.mapped();
  961. padding_params[0] = 0;
  962. padding_params[1] = h_bordered - bottom_blob_bordered.h;
  963. padding_params[2] = 0;
  964. padding_params[3] = w_bordered - bottom_blob_bordered.w;
  965. std::vector<VkMat> padding_inputs(2);
  966. padding_inputs[0] = bottom_blob_bordered;
  967. padding_inputs[1] = padding_param_blob;
  968. std::vector<VkMat> padding_outputs(1);
  969. winograd_padding->forward(padding_inputs, padding_outputs, cmd, opt_pad);
  970. bottom_blob_bordered = padding_outputs[0];
  971. }
  972. // transform input
  973. VkMat bottom_tm_blob;
  974. {
  975. bottom_tm_blob.create(16, block_x * block_y, channels, elemsize, elempack, opt.workspace_vkallocator);
  976. if (bottom_tm_blob.empty())
  977. return -100;
  978. std::vector<VkMat> bindings(2);
  979. bindings[0] = bottom_blob_bordered;
  980. bindings[1] = bottom_tm_blob;
  981. std::vector<vk_constant_type> constants(7);
  982. constants[0].i = bottom_blob_bordered.w;
  983. constants[1].i = bottom_blob_bordered.h;
  984. constants[2].i = bottom_blob_bordered.c;
  985. constants[3].i = bottom_blob_bordered.cstep;
  986. constants[4].i = bottom_tm_blob.cstep;
  987. constants[5].i = block_x;
  988. constants[6].i = block_y;
  989. VkMat dispatcher;
  990. dispatcher.w = block_x;
  991. dispatcher.h = block_y;
  992. dispatcher.c = bottom_tm_blob.c;
  993. cmd.record_pipeline(pipeline_convolution_pack4_3x3s1d1_winograd23_transform_input, bindings, constants, dispatcher);
  994. }
  995. // gemm
  996. VkMat top_tm_blob;
  997. {
  998. top_tm_blob.create(16, block_x * block_y, num_output / out_elempack, out_elemsize, out_elempack, opt.workspace_vkallocator);
  999. if (top_tm_blob.empty())
  1000. return -100;
  1001. std::vector<VkMat> bindings(3);
  1002. bindings[0] = bottom_tm_blob;
  1003. bindings[1] = top_tm_blob;
  1004. bindings[2] = weight_data_gpu_pack4_tm;
  1005. std::vector<vk_constant_type> constants(5);
  1006. constants[0].i = bottom_tm_blob.c;
  1007. constants[1].i = bottom_tm_blob.cstep;
  1008. constants[2].i = top_tm_blob.h;
  1009. constants[3].i = top_tm_blob.c;
  1010. constants[4].i = top_tm_blob.cstep;
  1011. VkMat dispatcher;
  1012. dispatcher.w = top_tm_blob.w;
  1013. dispatcher.h = (top_tm_blob.h + 3) / 4;
  1014. dispatcher.c = top_tm_blob.c;
  1015. cmd.record_pipeline(pipeline_convolution_pack4_3x3s1d1_winograd23_gemm, bindings, constants, dispatcher);
  1016. }
  1017. // transform output
  1018. VkMat top_blob_bordered;
  1019. {
  1020. top_blob_bordered.create(outw_bordered, outh_bordered, num_output / out_elempack, out_elemsize, out_elempack, opt.blob_vkallocator);
  1021. if (top_blob_bordered.empty())
  1022. return -100;
  1023. std::vector<VkMat> bindings(3);
  1024. bindings[0] = top_tm_blob;
  1025. bindings[1] = top_blob_bordered;
  1026. bindings[2] = bias_data_gpu;
  1027. std::vector<vk_constant_type> constants(7);
  1028. constants[0].i = top_tm_blob.c;
  1029. constants[1].i = top_tm_blob.cstep;
  1030. constants[2].i = block_x;
  1031. constants[3].i = block_y;
  1032. constants[4].i = top_blob_bordered.w;
  1033. constants[5].i = top_blob_bordered.h;
  1034. constants[6].i = top_blob_bordered.cstep;
  1035. VkMat dispatcher;
  1036. dispatcher.w = block_x;
  1037. dispatcher.h = block_y;
  1038. dispatcher.c = top_blob_bordered.c;
  1039. cmd.record_pipeline(pipeline_convolution_pack4_3x3s1d1_winograd23_transform_output, bindings, constants, dispatcher);
  1040. }
  1041. // crop top_blob
  1042. {
  1043. VkMat crop_param_blob(6, (size_t)4u, 1, opt.staging_vkallocator);
  1044. int* crop_params = crop_param_blob.mapped();
  1045. crop_params[0] = 0;
  1046. crop_params[1] = 0;
  1047. crop_params[2] = 0;
  1048. crop_params[3] = outw;
  1049. crop_params[4] = outh;
  1050. crop_params[5] = num_output;
  1051. std::vector<VkMat> crop_inputs(2);
  1052. crop_inputs[0] = top_blob_bordered;
  1053. crop_inputs[1] = crop_param_blob;
  1054. std::vector<VkMat> crop_outputs(1);
  1055. winograd_crop->forward(crop_inputs, crop_outputs, cmd, opt);
  1056. top_blob = crop_outputs[0];
  1057. }
  1058. return 0;
  1059. }
  1060. if (elempack == 8 && out_elempack == 8 && is_conv3x3s1d1 && channels * elempack >= 16 && num_output >= 16)
  1061. {
  1062. // winograd23
  1063. int outw_bordered = (outw + 1) / 2 * 2;
  1064. int outh_bordered = (outh + 1) / 2 * 2;
  1065. int w_bordered = outw_bordered + 2;
  1066. int h_bordered = outh_bordered + 2;
  1067. int block_x = outw_bordered / 2;
  1068. int block_y = outh_bordered / 2;
  1069. // pad to 2n+2
  1070. {
  1071. Option opt_pad = opt;
  1072. opt_pad.blob_vkallocator = opt.workspace_vkallocator;
  1073. VkMat padding_param_blob(4, (size_t)4u, 1, opt.staging_vkallocator);
  1074. int* padding_params = padding_param_blob.mapped();
  1075. padding_params[0] = 0;
  1076. padding_params[1] = h_bordered - bottom_blob_bordered.h;
  1077. padding_params[2] = 0;
  1078. padding_params[3] = w_bordered - bottom_blob_bordered.w;
  1079. std::vector<VkMat> padding_inputs(2);
  1080. padding_inputs[0] = bottom_blob_bordered;
  1081. padding_inputs[1] = padding_param_blob;
  1082. std::vector<VkMat> padding_outputs(1);
  1083. winograd_padding->forward(padding_inputs, padding_outputs, cmd, opt_pad);
  1084. bottom_blob_bordered = padding_outputs[0];
  1085. }
  1086. // transform input
  1087. VkMat bottom_tm_blob;
  1088. {
  1089. bottom_tm_blob.create(16, block_x * block_y, channels, elemsize, elempack, opt.workspace_vkallocator);
  1090. if (bottom_tm_blob.empty())
  1091. return -100;
  1092. std::vector<VkMat> bindings(2);
  1093. bindings[0] = bottom_blob_bordered;
  1094. bindings[1] = bottom_tm_blob;
  1095. std::vector<vk_constant_type> constants(7);
  1096. constants[0].i = bottom_blob_bordered.w;
  1097. constants[1].i = bottom_blob_bordered.h;
  1098. constants[2].i = bottom_blob_bordered.c;
  1099. constants[3].i = bottom_blob_bordered.cstep;
  1100. constants[4].i = bottom_tm_blob.cstep;
  1101. constants[5].i = block_x;
  1102. constants[6].i = block_y;
  1103. VkMat dispatcher;
  1104. dispatcher.w = block_x;
  1105. dispatcher.h = block_y;
  1106. dispatcher.c = bottom_tm_blob.c;
  1107. cmd.record_pipeline(pipeline_convolution_pack8_3x3s1d1_winograd23_transform_input, bindings, constants, dispatcher);
  1108. }
  1109. // gemm
  1110. VkMat top_tm_blob;
  1111. {
  1112. top_tm_blob.create(16, block_x * block_y, num_output / out_elempack, out_elemsize, out_elempack, opt.workspace_vkallocator);
  1113. if (top_tm_blob.empty())
  1114. return -100;
  1115. std::vector<VkMat> bindings(3);
  1116. bindings[0] = bottom_tm_blob;
  1117. bindings[1] = top_tm_blob;
  1118. bindings[2] = weight_data_gpu_pack8_tm;
  1119. std::vector<vk_constant_type> constants(5);
  1120. constants[0].i = bottom_tm_blob.c;
  1121. constants[1].i = bottom_tm_blob.cstep;
  1122. constants[2].i = top_tm_blob.h;
  1123. constants[3].i = top_tm_blob.c;
  1124. constants[4].i = top_tm_blob.cstep;
  1125. VkMat dispatcher;
  1126. dispatcher.w = top_tm_blob.w;
  1127. dispatcher.h = (top_tm_blob.h + 3) / 4;
  1128. dispatcher.c = top_tm_blob.c;
  1129. cmd.record_pipeline(pipeline_convolution_pack8_3x3s1d1_winograd23_gemm, bindings, constants, dispatcher);
  1130. }
  1131. // transform output
  1132. VkMat top_blob_bordered;
  1133. {
  1134. top_blob_bordered.create(outw_bordered, outh_bordered, num_output / out_elempack, out_elemsize, out_elempack, opt.blob_vkallocator);
  1135. if (top_blob_bordered.empty())
  1136. return -100;
  1137. std::vector<VkMat> bindings(3);
  1138. bindings[0] = top_tm_blob;
  1139. bindings[1] = top_blob_bordered;
  1140. bindings[2] = bias_data_gpu;
  1141. std::vector<vk_constant_type> constants(7);
  1142. constants[0].i = top_tm_blob.c;
  1143. constants[1].i = top_tm_blob.cstep;
  1144. constants[2].i = block_x;
  1145. constants[3].i = block_y;
  1146. constants[4].i = top_blob_bordered.w;
  1147. constants[5].i = top_blob_bordered.h;
  1148. constants[6].i = top_blob_bordered.cstep;
  1149. VkMat dispatcher;
  1150. dispatcher.w = block_x;
  1151. dispatcher.h = block_y;
  1152. dispatcher.c = top_blob_bordered.c;
  1153. cmd.record_pipeline(pipeline_convolution_pack8_3x3s1d1_winograd23_transform_output, bindings, constants, dispatcher);
  1154. }
  1155. // crop top_blob
  1156. {
  1157. VkMat crop_param_blob(6, (size_t)4u, 1, opt.staging_vkallocator);
  1158. int* crop_params = crop_param_blob.mapped();
  1159. crop_params[0] = 0;
  1160. crop_params[1] = 0;
  1161. crop_params[2] = 0;
  1162. crop_params[3] = outw;
  1163. crop_params[4] = outh;
  1164. crop_params[5] = num_output;
  1165. std::vector<VkMat> crop_inputs(2);
  1166. crop_inputs[0] = top_blob_bordered;
  1167. crop_inputs[1] = crop_param_blob;
  1168. std::vector<VkMat> crop_outputs(1);
  1169. winograd_crop->forward(crop_inputs, crop_outputs, cmd, opt);
  1170. top_blob = crop_outputs[0];
  1171. }
  1172. return 0;
  1173. }
  1174. top_blob.create(outw, outh, num_output / out_elempack, out_elemsize, out_elempack, opt.blob_vkallocator);
  1175. if (top_blob.empty())
  1176. return -100;
  1177. std::vector<VkMat> bindings(4);
  1178. bindings[0] = bottom_blob_bordered;
  1179. bindings[1] = top_blob;
  1180. bindings[2] = weight_data_gpu;
  1181. bindings[3] = bias_data_gpu;
  1182. std::vector<vk_constant_type> constants(10);
  1183. constants[0].i = bottom_blob_bordered.dims;
  1184. constants[1].i = bottom_blob_bordered.w;
  1185. constants[2].i = bottom_blob_bordered.h;
  1186. constants[3].i = bottom_blob_bordered.c;
  1187. constants[4].i = bottom_blob_bordered.cstep;
  1188. constants[5].i = top_blob.dims;
  1189. constants[6].i = top_blob.w;
  1190. constants[7].i = top_blob.h;
  1191. constants[8].i = top_blob.c;
  1192. constants[9].i = top_blob.cstep;
  1193. // record
  1194. if (elempack == 1 && out_elempack == 1 && kernel_w == 1 && kernel_h == 1 && stride_w == 1 && stride_h == 1 && dilation_w == 1 && dilation_h == 1)
  1195. {
  1196. VkMat dispatcher;
  1197. dispatcher.w = top_blob.cstep / 4;
  1198. dispatcher.h = 1;
  1199. dispatcher.c = top_blob.c;
  1200. cmd.record_pipeline(pipeline_convolution_1x1s1d1, bindings, constants, dispatcher);
  1201. }
  1202. else if (elempack == 4 && out_elempack == 4 && kernel_w == 1 && kernel_h == 1 && stride_w == 1 && stride_h == 1 && dilation_w == 1 && dilation_h == 1)
  1203. {
  1204. VkMat dispatcher;
  1205. dispatcher.w = (top_blob.w * top_blob.h + 3) / 4;
  1206. dispatcher.h = 1;
  1207. dispatcher.c = top_blob.c;
  1208. cmd.record_pipeline(pipeline_convolution_pack4_1x1s1d1, bindings, constants, dispatcher);
  1209. }
  1210. else if (elempack == 8 && out_elempack == 8 && kernel_w == 1 && kernel_h == 1 && stride_w == 1 && stride_h == 1 && dilation_w == 1 && dilation_h == 1)
  1211. {
  1212. VkMat dispatcher;
  1213. dispatcher.w = (top_blob.w * top_blob.h + 3) / 4;
  1214. dispatcher.h = 1;
  1215. dispatcher.c = top_blob.c;
  1216. cmd.record_pipeline(pipeline_convolution_pack8_1x1s1d1, bindings, constants, dispatcher);
  1217. }
  1218. else
  1219. {
  1220. const Pipeline* pipeline = 0;
  1221. if (elempack == 1 && out_elempack == 1)
  1222. {
  1223. pipeline = pipeline_convolution;
  1224. }
  1225. else if (elempack == 4 && out_elempack == 4)
  1226. {
  1227. pipeline = pipeline_convolution_pack4;
  1228. }
  1229. else if (elempack == 1 && out_elempack == 4)
  1230. {
  1231. pipeline = pipeline_convolution_pack1to4;
  1232. }
  1233. else if (elempack == 4 && out_elempack == 1)
  1234. {
  1235. pipeline = pipeline_convolution_pack4to1;
  1236. }
  1237. else if (elempack == 8 && out_elempack == 8)
  1238. {
  1239. pipeline = pipeline_convolution_pack8;
  1240. }
  1241. else if (elempack == 1 && out_elempack == 8)
  1242. {
  1243. pipeline = pipeline_convolution_pack1to8;
  1244. }
  1245. else if (elempack == 4 && out_elempack == 8)
  1246. {
  1247. pipeline = pipeline_convolution_pack4to8;
  1248. }
  1249. else if (elempack == 8 && out_elempack == 4)
  1250. {
  1251. pipeline = pipeline_convolution_pack8to4;
  1252. }
  1253. else if (elempack == 8 && out_elempack == 1)
  1254. {
  1255. pipeline = pipeline_convolution_pack8to1;
  1256. }
  1257. cmd.record_pipeline(pipeline, bindings, constants, top_blob);
  1258. }
  1259. return 0;
  1260. }
  1261. int Convolution_vulkan::forward(const VkImageMat& bottom_blob, VkImageMat& top_blob, VkCompute& cmd, const Option& opt) const
  1262. {
  1263. int w = bottom_blob.w;
  1264. int h = bottom_blob.h;
  1265. int channels = bottom_blob.c;
  1266. size_t elemsize = bottom_blob.elemsize;
  1267. int elempack = bottom_blob.elempack;
  1268. // flattened blob, implement as InnerProduct
  1269. if (bottom_blob.dims == 1 && kernel_w == 1 && kernel_h == 1)
  1270. {
  1271. int num_input = weight_data_size / num_output;
  1272. if (bottom_blob.w * bottom_blob.elempack == num_input)
  1273. {
  1274. return innerproduct->forward(bottom_blob, top_blob, cmd, opt);
  1275. }
  1276. }
  1277. const int kernel_extent_w = dilation_w * (kernel_w - 1) + 1;
  1278. const int kernel_extent_h = dilation_h * (kernel_h - 1) + 1;
  1279. VkImageMat bottom_blob_bordered = bottom_blob;
  1280. if (pad_left > 0 || pad_right > 0 || pad_top > 0 || pad_bottom > 0)
  1281. {
  1282. Option opt_pad = opt;
  1283. opt_pad.blob_vkallocator = opt.workspace_vkallocator;
  1284. padding->forward(bottom_blob, bottom_blob_bordered, cmd, opt_pad);
  1285. }
  1286. else if (pad_left == -233 && pad_right == -233 && pad_top == -233 && pad_bottom == -233)
  1287. {
  1288. int wpad = kernel_extent_w + (w - 1) / stride_w * stride_w - w;
  1289. int hpad = kernel_extent_h + (h - 1) / stride_h * stride_h - h;
  1290. if (wpad > 0 || hpad > 0)
  1291. {
  1292. Option opt_pad = opt;
  1293. opt_pad.blob_vkallocator = opt.workspace_vkallocator;
  1294. VkImageMat padding_param_blob(4, (size_t)4u, 1, opt.staging_vkallocator);
  1295. int* padding_params = padding_param_blob.mapped();
  1296. padding_params[0] = hpad / 2;
  1297. padding_params[1] = hpad - hpad / 2;
  1298. padding_params[2] = wpad / 2;
  1299. padding_params[3] = wpad - wpad / 2;
  1300. std::vector<VkImageMat> padding_inputs(2);
  1301. padding_inputs[0] = bottom_blob;
  1302. padding_inputs[1] = padding_param_blob;
  1303. std::vector<VkImageMat> padding_outputs(1);
  1304. padding->forward(padding_inputs, padding_outputs, cmd, opt_pad);
  1305. bottom_blob_bordered = padding_outputs[0];
  1306. }
  1307. }
  1308. else if (pad_left == -234 && pad_right == -234 && pad_top == -234 && pad_bottom == -234)
  1309. {
  1310. int wpad = kernel_extent_w + (w - 1) / stride_w * stride_w - w;
  1311. int hpad = kernel_extent_h + (h - 1) / stride_h * stride_h - h;
  1312. if (wpad > 0 || hpad > 0)
  1313. {
  1314. Option opt_pad = opt;
  1315. opt_pad.blob_vkallocator = opt.workspace_vkallocator;
  1316. VkImageMat padding_param_blob(4, (size_t)4u, 1, opt.staging_vkallocator);
  1317. int* padding_params = padding_param_blob.mapped();
  1318. padding_params[0] = hpad - hpad / 2;
  1319. padding_params[1] = hpad / 2;
  1320. padding_params[2] = wpad - wpad / 2;
  1321. padding_params[3] = wpad / 2;
  1322. std::vector<VkImageMat> padding_inputs(2);
  1323. padding_inputs[0] = bottom_blob;
  1324. padding_inputs[1] = padding_param_blob;
  1325. std::vector<VkImageMat> padding_outputs(1);
  1326. padding->forward(padding_inputs, padding_outputs, cmd, opt_pad);
  1327. bottom_blob_bordered = padding_outputs[0];
  1328. }
  1329. }
  1330. w = bottom_blob_bordered.w;
  1331. h = bottom_blob_bordered.h;
  1332. int outw = (w - kernel_extent_w) / stride_w + 1;
  1333. int outh = (h - kernel_extent_h) / stride_h + 1;
  1334. int out_elempack = opt.use_shader_pack8 && num_output % 8 == 0 ? 8 : num_output % 4 == 0 ? 4 : 1;
  1335. size_t out_elemsize = elemsize / elempack * out_elempack;
  1336. if (opt.use_fp16_packed && !opt.use_fp16_storage)
  1337. {
  1338. if (out_elempack == 8) out_elemsize = 8*2u;
  1339. if (out_elempack == 4) out_elemsize = 4*2u;
  1340. if (out_elempack == 1) out_elemsize = 4u;
  1341. }
  1342. bool is_conv3x3s1d1 = kernel_w == 3 && kernel_h == 3 && stride_w == 1 && stride_h == 1 && dilation_w == 1 && dilation_h == 1;
  1343. if (elempack == 4 && out_elempack == 4 && is_conv3x3s1d1 && channels * elempack >= 16 && num_output >= 16)
  1344. {
  1345. // winograd23
  1346. int outw_bordered = (outw + 1) / 2 * 2;
  1347. int outh_bordered = (outh + 1) / 2 * 2;
  1348. int w_bordered = outw_bordered + 2;
  1349. int h_bordered = outh_bordered + 2;
  1350. int block_x = outw_bordered / 2;
  1351. int block_y = outh_bordered / 2;
  1352. // pad to 2n+2
  1353. {
  1354. Option opt_pad = opt;
  1355. opt_pad.blob_vkallocator = opt.workspace_vkallocator;
  1356. VkImageMat padding_param_blob(4, (size_t)4u, 1, opt.staging_vkallocator);
  1357. int* padding_params = padding_param_blob.mapped();
  1358. padding_params[0] = 0;
  1359. padding_params[1] = h_bordered - bottom_blob_bordered.h;
  1360. padding_params[2] = 0;
  1361. padding_params[3] = w_bordered - bottom_blob_bordered.w;
  1362. std::vector<VkImageMat> padding_inputs(2);
  1363. padding_inputs[0] = bottom_blob_bordered;
  1364. padding_inputs[1] = padding_param_blob;
  1365. std::vector<VkImageMat> padding_outputs(1);
  1366. winograd_padding->forward(padding_inputs, padding_outputs, cmd, opt_pad);
  1367. bottom_blob_bordered = padding_outputs[0];
  1368. }
  1369. // transform input
  1370. VkImageMat bottom_tm_blob;
  1371. {
  1372. bottom_tm_blob.create(16, block_x * block_y, channels, elemsize, elempack, opt.workspace_vkallocator);
  1373. if (bottom_tm_blob.empty())
  1374. return -100;
  1375. std::vector<VkImageMat> bindings(2);
  1376. bindings[0] = bottom_blob_bordered;
  1377. bindings[1] = bottom_tm_blob;
  1378. std::vector<vk_constant_type> constants(7);
  1379. constants[0].i = bottom_blob_bordered.w;
  1380. constants[1].i = bottom_blob_bordered.h;
  1381. constants[2].i = bottom_blob_bordered.c;
  1382. constants[3].i = 0;//bottom_blob_bordered.cstep;
  1383. constants[4].i = 0;//bottom_tm_blob.cstep;
  1384. constants[5].i = block_x;
  1385. constants[6].i = block_y;
  1386. VkImageMat dispatcher;
  1387. dispatcher.w = block_x;
  1388. dispatcher.h = block_y;
  1389. dispatcher.c = bottom_tm_blob.c;
  1390. cmd.record_pipeline(pipeline_convolution_pack4_3x3s1d1_winograd23_transform_input, bindings, constants, dispatcher);
  1391. }
  1392. // gemm
  1393. VkImageMat top_tm_blob;
  1394. {
  1395. top_tm_blob.create(16, block_x * block_y, num_output / out_elempack, out_elemsize, out_elempack, opt.workspace_vkallocator);
  1396. if (top_tm_blob.empty())
  1397. return -100;
  1398. std::vector<VkImageMat> bindings(3);
  1399. bindings[0] = bottom_tm_blob;
  1400. bindings[1] = top_tm_blob;
  1401. bindings[2] = weight_data_gpu_pack4_tm_image;
  1402. std::vector<vk_constant_type> constants(5);
  1403. constants[0].i = bottom_tm_blob.c;
  1404. constants[1].i = 0;//bottom_tm_blob.cstep;
  1405. constants[2].i = top_tm_blob.h;
  1406. constants[3].i = top_tm_blob.c;
  1407. constants[4].i = 0;//top_tm_blob.cstep;
  1408. VkImageMat dispatcher;
  1409. dispatcher.w = top_tm_blob.w;
  1410. dispatcher.h = (top_tm_blob.h + 3) / 4;
  1411. dispatcher.c = top_tm_blob.c;
  1412. cmd.record_pipeline(pipeline_convolution_pack4_3x3s1d1_winograd23_gemm, bindings, constants, dispatcher);
  1413. }
  1414. // transform output
  1415. VkImageMat top_blob_bordered;
  1416. {
  1417. top_blob_bordered.create(outw_bordered, outh_bordered, num_output / out_elempack, out_elemsize, out_elempack, opt.blob_vkallocator);
  1418. if (top_blob_bordered.empty())
  1419. return -100;
  1420. std::vector<VkImageMat> bindings(3);
  1421. bindings[0] = top_tm_blob;
  1422. bindings[1] = top_blob_bordered;
  1423. bindings[2] = bias_data_gpu_image;
  1424. std::vector<vk_constant_type> constants(7);
  1425. constants[0].i = top_tm_blob.c;
  1426. constants[1].i = 0;//top_tm_blob.cstep;
  1427. constants[2].i = block_x;
  1428. constants[3].i = block_y;
  1429. constants[4].i = top_blob_bordered.w;
  1430. constants[5].i = top_blob_bordered.h;
  1431. constants[6].i = 0;//top_blob_bordered.cstep;
  1432. VkImageMat dispatcher;
  1433. dispatcher.w = block_x;
  1434. dispatcher.h = block_y;
  1435. dispatcher.c = top_blob_bordered.c;
  1436. cmd.record_pipeline(pipeline_convolution_pack4_3x3s1d1_winograd23_transform_output, bindings, constants, dispatcher);
  1437. }
  1438. // crop top_blob
  1439. {
  1440. VkImageMat crop_param_blob(6, (size_t)4u, 1, opt.staging_vkallocator);
  1441. int* crop_params = crop_param_blob.mapped();
  1442. crop_params[0] = 0;
  1443. crop_params[1] = 0;
  1444. crop_params[2] = 0;
  1445. crop_params[3] = outw;
  1446. crop_params[4] = outh;
  1447. crop_params[5] = num_output;
  1448. std::vector<VkImageMat> crop_inputs(2);
  1449. crop_inputs[0] = top_blob_bordered;
  1450. crop_inputs[1] = crop_param_blob;
  1451. std::vector<VkImageMat> crop_outputs(1);
  1452. winograd_crop->forward(crop_inputs, crop_outputs, cmd, opt);
  1453. top_blob = crop_outputs[0];
  1454. }
  1455. return 0;
  1456. }
  1457. if (elempack == 8 && out_elempack == 8 && is_conv3x3s1d1 && channels * elempack >= 16 && num_output >= 16)
  1458. {
  1459. // winograd23
  1460. int outw_bordered = (outw + 1) / 2 * 2;
  1461. int outh_bordered = (outh + 1) / 2 * 2;
  1462. int w_bordered = outw_bordered + 2;
  1463. int h_bordered = outh_bordered + 2;
  1464. int block_x = outw_bordered / 2;
  1465. int block_y = outh_bordered / 2;
  1466. // pad to 2n+2
  1467. {
  1468. Option opt_pad = opt;
  1469. opt_pad.blob_vkallocator = opt.workspace_vkallocator;
  1470. VkImageMat padding_param_blob(4, (size_t)4u, 1, opt.staging_vkallocator);
  1471. int* padding_params = padding_param_blob.mapped();
  1472. padding_params[0] = 0;
  1473. padding_params[1] = h_bordered - bottom_blob_bordered.h;
  1474. padding_params[2] = 0;
  1475. padding_params[3] = w_bordered - bottom_blob_bordered.w;
  1476. std::vector<VkImageMat> padding_inputs(2);
  1477. padding_inputs[0] = bottom_blob_bordered;
  1478. padding_inputs[1] = padding_param_blob;
  1479. std::vector<VkImageMat> padding_outputs(1);
  1480. winograd_padding->forward(padding_inputs, padding_outputs, cmd, opt_pad);
  1481. bottom_blob_bordered = padding_outputs[0];
  1482. }
  1483. // transform input
  1484. VkImageMat bottom_tm_blob;
  1485. {
  1486. bottom_tm_blob.create(16, block_x * block_y, channels, elemsize, elempack, opt.workspace_vkallocator);
  1487. if (bottom_tm_blob.empty())
  1488. return -100;
  1489. std::vector<VkImageMat> bindings(2);
  1490. bindings[0] = bottom_blob_bordered;
  1491. bindings[1] = bottom_tm_blob;
  1492. std::vector<vk_constant_type> constants(7);
  1493. constants[0].i = bottom_blob_bordered.w;
  1494. constants[1].i = bottom_blob_bordered.h;
  1495. constants[2].i = bottom_blob_bordered.c;
  1496. constants[3].i = 0;//bottom_blob_bordered.cstep;
  1497. constants[4].i = 0;//bottom_tm_blob.cstep;
  1498. constants[5].i = block_x;
  1499. constants[6].i = block_y;
  1500. VkImageMat dispatcher;
  1501. dispatcher.w = block_x;
  1502. dispatcher.h = block_y;
  1503. dispatcher.c = bottom_tm_blob.c;
  1504. cmd.record_pipeline(pipeline_convolution_pack8_3x3s1d1_winograd23_transform_input, bindings, constants, dispatcher);
  1505. }
  1506. // gemm
  1507. VkImageMat top_tm_blob;
  1508. {
  1509. top_tm_blob.create(16, block_x * block_y, num_output / out_elempack, out_elemsize, out_elempack, opt.workspace_vkallocator);
  1510. if (top_tm_blob.empty())
  1511. return -100;
  1512. std::vector<VkImageMat> bindings(3);
  1513. bindings[0] = bottom_tm_blob;
  1514. bindings[1] = top_tm_blob;
  1515. bindings[2] = weight_data_gpu_pack8_tm_image;
  1516. std::vector<vk_constant_type> constants(5);
  1517. constants[0].i = bottom_tm_blob.c;
  1518. constants[1].i = 0;//bottom_tm_blob.cstep;
  1519. constants[2].i = top_tm_blob.h;
  1520. constants[3].i = top_tm_blob.c;
  1521. constants[4].i = 0;//top_tm_blob.cstep;
  1522. VkImageMat dispatcher;
  1523. dispatcher.w = top_tm_blob.w;
  1524. dispatcher.h = (top_tm_blob.h + 3) / 4;
  1525. dispatcher.c = top_tm_blob.c;
  1526. cmd.record_pipeline(pipeline_convolution_pack8_3x3s1d1_winograd23_gemm, bindings, constants, dispatcher);
  1527. }
  1528. // transform output
  1529. VkImageMat top_blob_bordered;
  1530. {
  1531. top_blob_bordered.create(outw_bordered, outh_bordered, num_output / out_elempack, out_elemsize, out_elempack, opt.blob_vkallocator);
  1532. if (top_blob_bordered.empty())
  1533. return -100;
  1534. std::vector<VkImageMat> bindings(3);
  1535. bindings[0] = top_tm_blob;
  1536. bindings[1] = top_blob_bordered;
  1537. bindings[2] = bias_data_gpu_image;
  1538. std::vector<vk_constant_type> constants(7);
  1539. constants[0].i = top_tm_blob.c;
  1540. constants[1].i = 0;//top_tm_blob.cstep;
  1541. constants[2].i = block_x;
  1542. constants[3].i = block_y;
  1543. constants[4].i = top_blob_bordered.w;
  1544. constants[5].i = top_blob_bordered.h;
  1545. constants[6].i = 0;//top_blob_bordered.cstep;
  1546. VkImageMat dispatcher;
  1547. dispatcher.w = block_x;
  1548. dispatcher.h = block_y;
  1549. dispatcher.c = top_blob_bordered.c;
  1550. cmd.record_pipeline(pipeline_convolution_pack8_3x3s1d1_winograd23_transform_output, bindings, constants, dispatcher);
  1551. }
  1552. // crop top_blob
  1553. {
  1554. VkImageMat crop_param_blob(6, (size_t)4u, 1, opt.staging_vkallocator);
  1555. int* crop_params = crop_param_blob.mapped();
  1556. crop_params[0] = 0;
  1557. crop_params[1] = 0;
  1558. crop_params[2] = 0;
  1559. crop_params[3] = outw;
  1560. crop_params[4] = outh;
  1561. crop_params[5] = num_output;
  1562. std::vector<VkImageMat> crop_inputs(2);
  1563. crop_inputs[0] = top_blob_bordered;
  1564. crop_inputs[1] = crop_param_blob;
  1565. std::vector<VkImageMat> crop_outputs(1);
  1566. winograd_crop->forward(crop_inputs, crop_outputs, cmd, opt);
  1567. top_blob = crop_outputs[0];
  1568. }
  1569. return 0;
  1570. }
  1571. top_blob.create(outw, outh, num_output / out_elempack, out_elemsize, out_elempack, opt.blob_vkallocator);
  1572. if (top_blob.empty())
  1573. return -100;
  1574. std::vector<VkImageMat> bindings(4);
  1575. bindings[0] = bottom_blob_bordered;
  1576. bindings[1] = top_blob;
  1577. bindings[2] = weight_data_gpu_image;
  1578. bindings[3] = bias_data_gpu_image;
  1579. std::vector<vk_constant_type> constants(10);
  1580. constants[0].i = bottom_blob_bordered.dims;
  1581. constants[1].i = bottom_blob_bordered.w;
  1582. constants[2].i = bottom_blob_bordered.h;
  1583. constants[3].i = bottom_blob_bordered.c;
  1584. constants[4].i = 0;//bottom_blob_bordered.cstep;
  1585. constants[5].i = top_blob.dims;
  1586. constants[6].i = top_blob.w;
  1587. constants[7].i = top_blob.h;
  1588. constants[8].i = top_blob.c;
  1589. constants[9].i = 0;//top_blob.cstep;
  1590. // record
  1591. if (elempack == 1 && out_elempack == 1 && kernel_w == 1 && kernel_h == 1 && stride_w == 1 && stride_h == 1 && dilation_w == 1 && dilation_h == 1)
  1592. {
  1593. VkImageMat dispatcher;
  1594. dispatcher.w = (top_blob.w + 1) / 2;
  1595. dispatcher.h = (top_blob.h + 1) / 2;
  1596. dispatcher.c = top_blob.c;
  1597. cmd.record_pipeline(pipeline_convolution_1x1s1d1, bindings, constants, dispatcher);
  1598. }
  1599. else if (elempack == 4 && out_elempack == 4 && kernel_w == 1 && kernel_h == 1 && stride_w == 1 && stride_h == 1 && dilation_w == 1 && dilation_h == 1)
  1600. {
  1601. VkImageMat dispatcher;
  1602. dispatcher.w = (top_blob.w + 1) / 2;
  1603. dispatcher.h = (top_blob.h + 1) / 2;
  1604. dispatcher.c = top_blob.c;
  1605. cmd.record_pipeline(pipeline_convolution_pack4_1x1s1d1, bindings, constants, dispatcher);
  1606. }
  1607. else if (elempack == 8 && out_elempack == 8 && kernel_w == 1 && kernel_h == 1 && stride_w == 1 && stride_h == 1 && dilation_w == 1 && dilation_h == 1)
  1608. {
  1609. VkImageMat dispatcher;
  1610. dispatcher.w = (top_blob.w + 1) / 2;
  1611. dispatcher.h = (top_blob.h + 1) / 2;
  1612. dispatcher.c = top_blob.c;
  1613. cmd.record_pipeline(pipeline_convolution_pack8_1x1s1d1, bindings, constants, dispatcher);
  1614. }
  1615. else
  1616. {
  1617. const Pipeline* pipeline = 0;
  1618. if (elempack == 1 && out_elempack == 1)
  1619. {
  1620. pipeline = pipeline_convolution;
  1621. }
  1622. else if (elempack == 4 && out_elempack == 4)
  1623. {
  1624. pipeline = pipeline_convolution_pack4;
  1625. }
  1626. else if (elempack == 1 && out_elempack == 4)
  1627. {
  1628. pipeline = pipeline_convolution_pack1to4;
  1629. }
  1630. else if (elempack == 4 && out_elempack == 1)
  1631. {
  1632. pipeline = pipeline_convolution_pack4to1;
  1633. }
  1634. else if (elempack == 8 && out_elempack == 8)
  1635. {
  1636. pipeline = pipeline_convolution_pack8;
  1637. }
  1638. else if (elempack == 1 && out_elempack == 8)
  1639. {
  1640. pipeline = pipeline_convolution_pack1to8;
  1641. }
  1642. else if (elempack == 4 && out_elempack == 8)
  1643. {
  1644. pipeline = pipeline_convolution_pack4to8;
  1645. }
  1646. else if (elempack == 8 && out_elempack == 4)
  1647. {
  1648. pipeline = pipeline_convolution_pack8to4;
  1649. }
  1650. else if (elempack == 8 && out_elempack == 1)
  1651. {
  1652. pipeline = pipeline_convolution_pack8to1;
  1653. }
  1654. cmd.record_pipeline(pipeline, bindings, constants, top_blob);
  1655. }
  1656. return 0;
  1657. }
  1658. } // namespace ncnn