* @brief Copies data from a GPU buffer to CPU memory. * @param[in] ctx Context instance to manage the operation * @param[in] tensor Tensor instance representing the GPU buffer to copy from * @param[out] data Pointer to the CPU memory to copy the data to * @param[in] bufferSize Size of the data buffer in bytes * @param[in] op StagingBuffer instance to manage the operation * * @code * toCPU(
| 995 | * @endcode |
| 996 | */ |
| 997 | inline void toCPU(Context &ctx, Tensor &tensor, void *data, size_t bufferSize, |
| 998 | CopyData &op) { |
| 999 | wgpuQueueSubmit(ctx.queue, 1, &op.commandBuffer); |
| 1000 | CallbackData callbackData = {op.readbackBuffer, bufferSize, data, &op.promise, |
| 1001 | &op.future}; |
| 1002 | wgpuQueueOnSubmittedWorkDone( |
| 1003 | ctx.queue, |
| 1004 | [](WGPUQueueWorkDoneStatus status, void *callbackData) { |
| 1005 | check(status == WGPUQueueWorkDoneStatus_Success, "Queue work done", |
| 1006 | __FILE__, __LINE__); |
| 1007 | const auto *data = static_cast<CallbackData *>(callbackData); |
| 1008 | wgpuBufferMapAsync( |
| 1009 | data->buffer, WGPUMapMode_Read, 0, data->bufferSize, |
| 1010 | [](WGPUBufferMapAsyncStatus status, void *captureData) { |
| 1011 | const auto *data = static_cast<CallbackData *>(captureData); |
| 1012 | check(status == WGPUBufferMapAsyncStatus_Success, |
| 1013 | "Map readbackBuffer", __FILE__, __LINE__); |
| 1014 | const void *mappedData = wgpuBufferGetConstMappedRange( |
| 1015 | data->buffer, /*offset=*/0, data->bufferSize); |
| 1016 | check(mappedData, "Get mapped range", __FILE__, __LINE__); |
| 1017 | memcpy(data->output, mappedData, data->bufferSize); |
| 1018 | wgpuBufferUnmap(data->buffer); |
| 1019 | data->promise->set_value(); |
| 1020 | }, |
| 1021 | callbackData); |
| 1022 | }, |
| 1023 | &callbackData); |
| 1024 | wait(ctx, op.future); |
| 1025 | } |
| 1026 | |
| 1027 | /** |
| 1028 | * @brief Overload of the toCPU function to copy data from a GPU buffer to CPU |