| 170 | } |
| 171 | |
| 172 | std::vector<ComputeTaskDescriptorPtr> Softmax1x1(int id, ValueId input_id, |
| 173 | ValueId output_id, |
| 174 | int channels_count) { |
| 175 | auto desc = std::make_shared<ComputeTaskDescriptor>(); |
| 176 | desc->id = id; |
| 177 | desc->is_linkable = false; |
| 178 | desc->shader_source = GetSoftmax1x1Code(); |
| 179 | |
| 180 | desc->input_buffers = { |
| 181 | {input_id, "device FLT4* const src_buffer"}, |
| 182 | }; |
| 183 | |
| 184 | desc->output_buffer = {output_id, "device FLT4* dst_buffer", |
| 185 | [input_id](const std::map<ValueId, BHWC>& buffers) { |
| 186 | return buffers.find(input_id)->second; |
| 187 | }}; |
| 188 | |
| 189 | desc->uniform_buffers = { |
| 190 | {"constant uniforms& params", |
| 191 | [channels_count](const std::map<ValueId, BHWC>& buffers) { |
| 192 | const int src_depth = IntegralDivideRoundUp(channels_count, 4); |
| 193 | struct uniforms { |
| 194 | int4 size; |
| 195 | float4 mask; |
| 196 | }; |
| 197 | uniforms params; |
| 198 | params.size = {src_depth, IntegralDivideRoundUp(src_depth, 32), 1, 1}; |
| 199 | params.mask = {0.0f, 0.0f, 0.0f, 0.0f}; |
| 200 | const int reminder = channels_count % 4 == 0 ? 4 : channels_count % 4; |
| 201 | for (int i = 0; i < reminder; ++i) { |
| 202 | params.mask[i] = 1.0f; |
| 203 | } |
| 204 | const uint8_t* ptr = reinterpret_cast<const uint8_t*>(¶ms); |
| 205 | return std::vector<uint8_t>(ptr, ptr + sizeof(uniforms)); |
| 206 | }}, |
| 207 | }; |
| 208 | |
| 209 | desc->resize_function = [](const std::map<ValueId, BHWC>& buffers) { |
| 210 | return std::make_pair(uint3{32u, 1u, 1u}, uint3{1u, 1u, 1u}); |
| 211 | }; |
| 212 | |
| 213 | return {desc}; |
| 214 | } |
| 215 | |
| 216 | } // namespace metal |
| 217 | } // namespace gpu |
no test coverage detected