1 /*
2  * Copyright 2019 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "src/gpu/dawn/GrDawnStagingManager.h"
9 
10 #include "src/core/SkMathPriv.h"
11 
GrDawnStagingManager(wgpu::Device device)12 GrDawnStagingManager::GrDawnStagingManager(wgpu::Device device) : fDevice(device) {
13 }
14 
~GrDawnStagingManager()15 GrDawnStagingManager::~GrDawnStagingManager() {
16     // Clean up any pending callbacks before destroying the StagingBuffers.
17     while (fWaitingCount > 0) {
18         fDevice.Tick();
19     }
20 }
21 
findOrCreateStagingBuffer(size_t size)22 GrDawnStagingBuffer* GrDawnStagingManager::findOrCreateStagingBuffer(size_t size) {
23     size_t sizePow2 = GrNextPow2(size);
24     GrDawnStagingBuffer* stagingBuffer;
25     auto i = fReadyPool.find(sizePow2);
26     if (i != fReadyPool.end()) {
27         stagingBuffer = i->second;
28         fReadyPool.erase(i);
29     } else {
30         wgpu::BufferDescriptor desc;
31         desc.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc;
32         desc.size = sizePow2;
33         wgpu::CreateBufferMappedResult result = fDevice.CreateBufferMapped(&desc);
34         std::unique_ptr<GrDawnStagingBuffer> b(new GrDawnStagingBuffer(
35             this, result.buffer, sizePow2, result.data));
36         stagingBuffer = b.get();
37         fBuffers.push_back(std::move(b));
38     }
39     fBusyList.push_back(stagingBuffer);
40     return stagingBuffer;
41 }
42 
callback(WGPUBufferMapAsyncStatus status,void * data,uint64_t dataLength,void * userData)43 static void callback(WGPUBufferMapAsyncStatus status, void* data, uint64_t dataLength,
44                      void* userData) {
45     GrDawnStagingBuffer* buffer = static_cast<GrDawnStagingBuffer*>(userData);
46     buffer->fData = data;
47     if (buffer->fManager) {
48         buffer->fManager->addToReadyPool(buffer);
49     }
50 }
51 
mapBusyList()52 void GrDawnStagingManager::mapBusyList() {
53     // Map all buffers on the busy list for writing. When they're no longer in flight on the GPU,
54     // their callback will be called and they'll be moved to the ready pool.
55     for (GrDawnStagingBuffer* buffer : fBusyList) {
56         buffer->fBuffer.MapWriteAsync(callback, buffer);
57         fWaitingCount++;
58     }
59     fBusyList.clear();
60 }
61 
addToReadyPool(GrDawnStagingBuffer * buffer)62 void GrDawnStagingManager::addToReadyPool(GrDawnStagingBuffer* buffer) {
63     fWaitingCount--;
64     fReadyPool.insert(std::pair<size_t, GrDawnStagingBuffer*>(buffer->fSize, buffer));
65 }
66