/* * Copyright 2022 Google LLC * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "src/gpu/graphite/UploadBufferManager.h" #include "include/gpu/graphite/Recording.h" #include "include/private/base/SkAlign.h" #include "src/gpu/graphite/Buffer.h" #include "src/gpu/graphite/Caps.h" #include "src/gpu/graphite/RecordingPriv.h" #include "src/gpu/graphite/ResourceProvider.h" namespace skgpu::graphite { static constexpr size_t kReusedBufferSize = 64 << 10; // 64 KB UploadBufferManager::UploadBufferManager(ResourceProvider* resourceProvider, const Caps* caps) : fResourceProvider(resourceProvider) , fMinAlignment(caps->requiredTransferBufferAlignment()) {} UploadBufferManager::~UploadBufferManager() {} std::tuple UploadBufferManager::getUploadWriter( size_t requiredBytes, size_t requiredAlignment) { if (!requiredBytes) { return {UploadWriter(), BindBufferInfo()}; } requiredAlignment = std::max(requiredAlignment, fMinAlignment); requiredBytes = SkAlignTo(requiredBytes, requiredAlignment); if (requiredBytes > kReusedBufferSize) { // Create a dedicated buffer for this request. sk_sp buffer = fResourceProvider->findOrCreateBuffer( requiredBytes, BufferType::kXferCpuToGpu, PrioritizeGpuReads::kNo); BindBufferInfo bindInfo; bindInfo.fBuffer = buffer.get(); bindInfo.fOffset = 0; void* bufferMapPtr = buffer->map(); fUsedBuffers.push_back(std::move(buffer)); return {UploadWriter(bufferMapPtr, requiredBytes), bindInfo}; } // Try to reuse an already-allocated buffer. fReusedBufferOffset = SkAlignTo(fReusedBufferOffset, requiredAlignment); if (fReusedBuffer && requiredBytes > fReusedBuffer->size() - fReusedBufferOffset) { fUsedBuffers.push_back(std::move(fReusedBuffer)); } if (!fReusedBuffer) { fReusedBuffer = fResourceProvider->findOrCreateBuffer( kReusedBufferSize, BufferType::kXferCpuToGpu, PrioritizeGpuReads::kNo); fReusedBufferOffset = 0; if (!fReusedBuffer) { return {UploadWriter(), BindBufferInfo()}; } } BindBufferInfo bindInfo; bindInfo.fBuffer = fReusedBuffer.get(); bindInfo.fOffset = fReusedBufferOffset; void* bufferMapPtr = fReusedBuffer->map(); bufferMapPtr = SkTAddOffset(bufferMapPtr, fReusedBufferOffset); fReusedBufferOffset += requiredBytes; return {UploadWriter(bufferMapPtr, requiredBytes), bindInfo}; } void UploadBufferManager::transferToRecording(Recording* recording) { for (sk_sp& buffer : fUsedBuffers) { buffer->unmap(); recording->priv().addResourceRef(std::move(buffer)); } fUsedBuffers.clear(); if (fReusedBuffer) { fReusedBuffer->unmap(); recording->priv().addResourceRef(std::move(fReusedBuffer)); } } } // namespace skgpu::graphite