| /* | |
| * 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<UploadWriter, BindBufferInfo> 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> 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<void>(bufferMapPtr, fReusedBufferOffset); | |
| fReusedBufferOffset += requiredBytes; | |
| return {UploadWriter(bufferMapPtr, requiredBytes), bindInfo}; | |
| } | |
| void UploadBufferManager::transferToRecording(Recording* recording) { | |
| for (sk_sp<Buffer>& 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 |