* @brief A factory function to create a kernel on the GPU. The kernel is * created with the given WGSL code, input tensors, output tensor, and * optional parameters. * * Note that the values of the input tensors are not used here, only the * reference handles to the underlying buffers as well as the size of the * buffers. * * @param[in] ctx Context instance to manage the kernel * @param[i
| 1213 | * output, nThreads, params, paramsSize); |
| 1214 | */ |
| 1215 | inline Kernel createKernel(Context &ctx, const KernelCode &code, |
| 1216 | const Tensor *dataBindings, size_t numTensors, |
| 1217 | const size_t *viewOffsets, const Shape &totalWorkgroups, |
| 1218 | const void *params = nullptr, |
| 1219 | size_t paramsSize = 0, |
| 1220 | CompilationInfo* compilationInfo = nullptr) { |
| 1221 | assert(totalWorkgroups.rank == 3); |
| 1222 | WGPUDevice device = ctx.device; |
| 1223 | WGPUQueue queue = ctx.queue; |
| 1224 | Kernel op; |
| 1225 | // paramIndex is the index into bgLayoutEntries for the parameters buffer If |
| 1226 | // there are no parameters for the kernel, paramsSize == 0 and paramIndex is |
| 1227 | // effectively undefined (== -1) |
| 1228 | size_t paramIndex = -1; |
| 1229 | // Note: paramIndex is undefined unless paramsSize > 0 |
| 1230 | size_t numBindings = numTensors; |
| 1231 | if (paramsSize > 0) { |
| 1232 | numBindings++; // parameters buffer |
| 1233 | paramIndex = numBindings - 1; // index of the parameters buffer within |
| 1234 | // op.buffers, op.bufferSizes and |
| 1235 | // bgLayoutEntries |
| 1236 | } |
| 1237 | op.buffers = std::make_unique<WGPUBuffer[]>(numBindings); |
| 1238 | op.bufferSizes = std::make_unique<size_t[]>(numBindings); |
| 1239 | op.numBindings = numBindings; |
| 1240 | std::vector<WGPUBindGroupLayoutEntry> bgLayoutEntries(numBindings); |
| 1241 | // Create layout entries for input buffers |
| 1242 | for (size_t i = 0; i < numTensors; ++i) { |
| 1243 | bgLayoutEntries[i] = WGPUBindGroupLayoutEntry{ |
| 1244 | .binding = static_cast<uint32_t>(i), |
| 1245 | .visibility = WGPUShaderStage_Compute, |
| 1246 | .buffer = |
| 1247 | WGPUBufferBindingLayout{ |
| 1248 | .type = WGPUBufferBindingType_Storage, |
| 1249 | .minBindingSize = dataBindings[i].data.size, |
| 1250 | }, |
| 1251 | }; |
| 1252 | } |
| 1253 | if (paramsSize > 0) { |
| 1254 | LOG(kDefLog, kInfo, "Create layout entry for the params buffer"); |
| 1255 | // Create layout entry for the params buffer |
| 1256 | bgLayoutEntries[paramIndex] = WGPUBindGroupLayoutEntry{ |
| 1257 | .binding = static_cast<uint32_t>(paramIndex), |
| 1258 | .visibility = WGPUShaderStage_Compute, |
| 1259 | .buffer = |
| 1260 | WGPUBufferBindingLayout{ |
| 1261 | .type = WGPUBufferBindingType_Uniform, |
| 1262 | .minBindingSize = paramsSize, |
| 1263 | }, |
| 1264 | }; |
| 1265 | } |
| 1266 | WGPUBindGroupLayoutDescriptor bgLayoutDesc = { |
| 1267 | .entryCount = static_cast<uint32_t>(bgLayoutEntries.size()), |
| 1268 | .entries = bgLayoutEntries.data(), |
| 1269 | }; |
| 1270 | WGPUBindGroupLayout bgLayout = |
| 1271 | wgpuDeviceCreateBindGroupLayout(device, &bgLayoutDesc); |
| 1272 | for (size_t i = 0; i < numTensors; ++i) { |