1/* 2 * Copyright 2021 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 "experimental/graphite/src/DrawBufferManager.h" 9 10#include "experimental/graphite/src/Buffer.h" 11#include "experimental/graphite/src/CommandBuffer.h" 12#include "experimental/graphite/src/ResourceProvider.h" 13 14namespace skgpu { 15 16// TODO: Tune these values on real world data 17static constexpr size_t kVertexBufferSize = 2 << 10; 18static constexpr size_t kIndexBufferSize = 2 << 10; 19static constexpr size_t kUniformBufferSize = 2 << 10; 20 21DrawBufferManager::DrawBufferManager(ResourceProvider* resourceProvider, 22 size_t uniformStartAlignment) 23 : fResourceProvider(resourceProvider) 24 , fUniformStartAlignment(uniformStartAlignment) {} 25 26DrawBufferManager::~DrawBufferManager() {} 27 28static bool can_fit(size_t requestedSize, 29 Buffer* buffer, 30 size_t currentOffset, 31 size_t alignment) { 32 size_t startOffset = SkAlignTo(currentOffset, alignment); 33 return requestedSize <= (buffer->size() - startOffset); 34} 35 36std::tuple<VertexWriter, BindBufferInfo> DrawBufferManager::getVertexWriter(size_t requiredBytes) { 37 if (!requiredBytes) { 38 BindBufferInfo bindInfo; 39 bindInfo.fBuffer = nullptr; 40 bindInfo.fOffset = 0; 41 return {VertexWriter(nullptr), bindInfo}; 42 } 43 if (fCurrentVertexBuffer && 44 !can_fit(requiredBytes, fCurrentVertexBuffer.get(), fVertexOffset, /*alignment=*/1)) { 45 fUsedBuffers.push_back(std::move(fCurrentVertexBuffer)); 46 } 47 48 if (!fCurrentVertexBuffer) { 49 SkASSERT(requiredBytes <= kVertexBufferSize); 50 fCurrentVertexBuffer = fResourceProvider->findOrCreateBuffer(kVertexBufferSize, 51 BufferType::kVertex, 52 PrioritizeGpuReads::kNo); 53 fVertexOffset = 0; 54 if (!fCurrentVertexBuffer) { 55 return {VertexWriter(), BindBufferInfo()}; 56 } 57 } 58 BindBufferInfo bindInfo; 59 bindInfo.fBuffer = fCurrentVertexBuffer.get(); 60 bindInfo.fOffset = fVertexOffset; 61 fVertexOffset += requiredBytes; 62 return {VertexWriter(fCurrentVertexBuffer->map()), bindInfo}; 63} 64 65std::tuple<IndexWriter, BindBufferInfo> DrawBufferManager::getIndexWriter(size_t requiredBytes) { 66 if (!requiredBytes) { 67 BindBufferInfo bindInfo; 68 bindInfo.fBuffer = nullptr; 69 bindInfo.fOffset = 0; 70 return {IndexWriter(nullptr), bindInfo}; 71 } 72 if (fCurrentIndexBuffer && 73 !can_fit(requiredBytes, fCurrentIndexBuffer.get(), fIndexOffset, /*alignment=*/1)) { 74 fUsedBuffers.push_back(std::move(fCurrentIndexBuffer)); 75 } 76 77 if (!fCurrentIndexBuffer) { 78 SkASSERT(requiredBytes <= kIndexBufferSize); 79 fCurrentIndexBuffer = fResourceProvider->findOrCreateBuffer(kIndexBufferSize, 80 BufferType::kIndex, 81 PrioritizeGpuReads::kNo); 82 fIndexOffset = 0; 83 if (!fCurrentIndexBuffer) { 84 return {IndexWriter(), BindBufferInfo()}; 85 } 86 } 87 BindBufferInfo bindInfo; 88 bindInfo.fBuffer = fCurrentIndexBuffer.get(); 89 bindInfo.fOffset = fIndexOffset; 90 fIndexOffset += requiredBytes; 91 return {IndexWriter(fCurrentIndexBuffer->map()), bindInfo}; 92} 93 94std::tuple<UniformWriter, BindBufferInfo> DrawBufferManager::getUniformWriter( 95 size_t requiredBytes) { 96 if (!requiredBytes) { 97 BindBufferInfo bindInfo; 98 bindInfo.fBuffer = nullptr; 99 bindInfo.fOffset = 0; 100 return {UniformWriter(nullptr), bindInfo}; 101 } 102 if (fCurrentUniformBuffer && 103 !can_fit(requiredBytes, 104 fCurrentUniformBuffer.get(), 105 fUniformOffset, 106 fUniformStartAlignment)) { 107 fUsedBuffers.push_back(std::move(fCurrentUniformBuffer)); 108 } 109 110 if (!fCurrentUniformBuffer) { 111 SkASSERT(requiredBytes <= kUniformBufferSize); 112 fCurrentUniformBuffer = fResourceProvider->findOrCreateBuffer(kUniformBufferSize, 113 BufferType::kUniform, 114 PrioritizeGpuReads::kNo); 115 fUniformOffset = 0; 116 if (!fCurrentUniformBuffer) { 117 return {UniformWriter(), BindBufferInfo()}; 118 } 119 } 120 fUniformOffset = SkAlignTo(fUniformOffset, fUniformStartAlignment); 121 BindBufferInfo bindInfo; 122 bindInfo.fBuffer = fCurrentUniformBuffer.get(); 123 bindInfo.fOffset = fUniformOffset; 124 fUniformOffset += requiredBytes; 125 return {UniformWriter(fCurrentUniformBuffer->map()), bindInfo}; 126} 127 128void DrawBufferManager::transferToCommandBuffer(CommandBuffer* commandBuffer) { 129 for (auto& buffer : fUsedBuffers) { 130 buffer->unmap(); 131 commandBuffer->trackResource(std::move(buffer)); 132 } 133 fUsedBuffers.clear(); 134} 135 136} // namespace skgpu 137 138