blob: 68e0e9785f06a9a50e809f246c009019a06f7b20 [file] [log] [blame]
/*
* Copyright 2019 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/dawn/GrDawnStagingManager.h"
#include "src/core/SkMathPriv.h"
GrDawnStagingManager::GrDawnStagingManager(dawn::Device device) : fDevice(device) {
}
GrDawnStagingManager::~GrDawnStagingManager() {
// Clean up any pending callbacks before destroying the StagingBuffers.
while (fWaitingCount > 0) {
fDevice.Tick();
}
}
GrDawnStagingBuffer* GrDawnStagingManager::findOrCreateStagingBuffer(size_t size) {
size_t sizePow2 = GrNextPow2(size);
GrDawnStagingBuffer* stagingBuffer;
auto i = fReadyPool.find(sizePow2);
if (i != fReadyPool.end()) {
stagingBuffer = i->second;
fReadyPool.erase(i);
} else {
dawn::BufferDescriptor desc;
desc.usage = dawn::BufferUsage::MapWrite | dawn::BufferUsage::CopySrc;
desc.size = sizePow2;
dawn::CreateBufferMappedResult result = fDevice.CreateBufferMapped(&desc);
std::unique_ptr<GrDawnStagingBuffer> b(new GrDawnStagingBuffer(
this, result.buffer, sizePow2, result.data));
stagingBuffer = b.get();
fBuffers.push_back(std::move(b));
}
fBusyList.push_back(stagingBuffer);
return stagingBuffer;
}
static void callback(DawnBufferMapAsyncStatus status, void* data, uint64_t dataLength,
void* userData) {
GrDawnStagingBuffer* buffer = static_cast<GrDawnStagingBuffer*>(userData);
buffer->fData = data;
if (buffer->fManager) {
buffer->fManager->addToReadyPool(buffer);
}
}
void GrDawnStagingManager::mapBusyList() {
// Map all buffers on the busy list for writing. When they're no longer in flight on the GPU,
// their callback will be called and they'll be moved to the ready pool.
for (GrDawnStagingBuffer* buffer : fBusyList) {
buffer->fBuffer.MapWriteAsync(callback, buffer);
fWaitingCount++;
}
fBusyList.clear();
}
void GrDawnStagingManager::addToReadyPool(GrDawnStagingBuffer* buffer) {
fWaitingCount--;
fReadyPool.insert(std::pair<size_t, GrDawnStagingBuffer*>(buffer->fSize, buffer));
}