diff --git a/src/layer/vulkan/shader/softplus.comp b/src/layer/vulkan/shader/softplus.comp new file mode 100644 index 000000000000..9aebfaff7c9d --- /dev/null +++ b/src/layer/vulkan/shader/softplus.comp @@ -0,0 +1,27 @@ +// Copyright 2026 Futz12 +// SPDX-License-Identifier: BSD-3-Clause + +#version 450 + +layout(constant_id = 0) const uint n = 0; + +layout(binding = 0) buffer bottom_top_blob { sfpvec4 bottom_top_blob_data[]; }; + +layout(push_constant) uniform parameter +{ + uint n; +} p; + +void main() +{ + const uint gi = gl_GlobalInvocationID.x; + + if (gi >= psc(n)) + return; + + afpvec4 v = buffer_ld4(bottom_top_blob_data, gi); + + v = log(exp(v) + afpvec4(1.f)); + + buffer_st4(bottom_top_blob_data, gi, v); +} diff --git a/src/layer/vulkan/softplus_vulkan.cpp b/src/layer/vulkan/softplus_vulkan.cpp new file mode 100644 index 000000000000..2c43230eabea --- /dev/null +++ b/src/layer/vulkan/softplus_vulkan.cpp @@ -0,0 +1,84 @@ +// Copyright 2026 Futz12 +// SPDX-License-Identifier: BSD-3-Clause + +#include "softplus_vulkan.h" + +#include "layer_shader_type.h" + +namespace ncnn { + +Softplus_vulkan::Softplus_vulkan() +{ + support_vulkan = true; + support_vulkan_packing = true; + + pipeline_softplus = 0; +} + +int Softplus_vulkan::create_pipeline(const Option& opt) +{ + const Mat& shape = top_shapes.empty() ? Mat() : top_shapes[0]; + + const int dims = shape.dims; + + int elempack = 0; + if (dims == 1) elempack = shape.w % 4 == 0 ? 4 : 1; + if (dims == 2) elempack = shape.h % 4 == 0 ? 4 : 1; + if (dims == 3 || dims == 4) elempack = shape.c % 4 == 0 ? 4 : 1; + + size_t elemsize; + if (opt.use_fp16_storage || opt.use_fp16_packed) + { + elemsize = elempack * 2u; + } + else + { + elemsize = elempack * 4u; + } + + Mat shape_packed; + if (dims == 1) shape_packed = Mat(shape.w / elempack, (void*)0, elemsize, elempack); + if (dims == 2) shape_packed = Mat(shape.w, shape.h / elempack, (void*)0, elemsize, elempack); + if (dims == 3) shape_packed = Mat(shape.w, shape.h, shape.c / elempack, (void*)0, elemsize, elempack); + if (dims == 4) shape_packed = Mat(shape.w, shape.h, shape.d, shape.c / elempack, (void*)0, elemsize, elempack); + + std::vector specializations(1); + specializations[0].u32 = shape_packed.total() * elempack / 4; + + const int local_size_x = vkdev->info.subgroup_size(); + + pipeline_softplus = new Pipeline(vkdev); + pipeline_softplus->set_optimal_local_size_xyz(local_size_x, 1, 1); + pipeline_softplus->create(LayerShaderType::softplus, opt, specializations); + + return 0; +} + +int Softplus_vulkan::destroy_pipeline(const Option& /*opt*/) +{ + delete pipeline_softplus; + pipeline_softplus = 0; + + return 0; +} + +int Softplus_vulkan::forward_inplace(VkMat& bottom_top_blob, VkCompute& cmd, const Option& /*opt*/) const +{ + const size_t n = bottom_top_blob.total() * bottom_top_blob.elempack / 4; + + std::vector bindings(1); + bindings[0] = bottom_top_blob; + + std::vector constants(1); + constants[0].u32 = n; + + VkMat dispatcher; + dispatcher.w = n; + dispatcher.h = 1; + dispatcher.c = 1; + cmd.record_pipeline(pipeline_softplus, bindings, constants, dispatcher); + + return 0; +} + +} // namespace ncnn diff --git a/src/layer/vulkan/softplus_vulkan.h b/src/layer/vulkan/softplus_vulkan.h new file mode 100644 index 000000000000..0589d3e2e672 --- /dev/null +++ b/src/layer/vulkan/softplus_vulkan.h @@ -0,0 +1,28 @@ +// Copyright 2026 Futz12 +// SPDX-License-Identifier: BSD-3-Clause + +#ifndef LAYER_SOFTPLUS_VULKAN_H +#define LAYER_SOFTPLUS_VULKAN_H + +#include "softplus.h" + +namespace ncnn { + +class Softplus_vulkan : public Softplus +{ +public: + Softplus_vulkan(); + + virtual int create_pipeline(const Option& opt); + virtual int destroy_pipeline(const Option& opt); + + using Softplus::forward_inplace; + virtual int forward_inplace(VkMat& bottom_top_blob, VkCompute& cmd, const Option& opt) const; + +public: + Pipeline* pipeline_softplus; +}; + +} // namespace ncnn + +#endif // LAYER_SOFTPLUS_VULKAN_H