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