| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2010 Google Inc. | 3 * Copyright 2010 Google Inc. |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 | 9 |
| 10 #include "GrBufferAllocPool.h" | 10 #include "GrBufferAllocPool.h" |
| 11 #include "GrBuffer.h" |
| 11 #include "GrCaps.h" | 12 #include "GrCaps.h" |
| 12 #include "GrContext.h" | 13 #include "GrContext.h" |
| 13 #include "GrGpu.h" | 14 #include "GrGpu.h" |
| 14 #include "GrIndexBuffer.h" | |
| 15 #include "GrResourceProvider.h" | 15 #include "GrResourceProvider.h" |
| 16 #include "GrTypes.h" | 16 #include "GrTypes.h" |
| 17 #include "GrVertexBuffer.h" | |
| 18 | 17 |
| 19 #include "SkTraceEvent.h" | 18 #include "SkTraceEvent.h" |
| 20 | 19 |
| 21 #ifdef SK_DEBUG | 20 #ifdef SK_DEBUG |
| 22 #define VALIDATE validate | 21 #define VALIDATE validate |
| 23 #else | 22 #else |
| 24 static void VALIDATE(bool = false) {} | 23 static void VALIDATE(bool = false) {} |
| 25 #endif | 24 #endif |
| 26 | 25 |
| 27 static const size_t MIN_VERTEX_BUFFER_SIZE = 1 << 15; | 26 static const size_t MIN_VERTEX_BUFFER_SIZE = 1 << 15; |
| 28 static const size_t MIN_INDEX_BUFFER_SIZE = 1 << 12; | 27 static const size_t MIN_INDEX_BUFFER_SIZE = 1 << 12; |
| 29 | 28 |
| 30 // page size | 29 // page size |
| 31 #define GrBufferAllocPool_MIN_BLOCK_SIZE ((size_t)1 << 15) | 30 #define GrBufferAllocPool_MIN_BLOCK_SIZE ((size_t)1 << 15) |
| 32 | 31 |
| 33 #define UNMAP_BUFFER(block)
\ | 32 #define UNMAP_BUFFER(block)
\ |
| 34 do {
\ | 33 do {
\ |
| 35 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("skia.gpu"),
\ | 34 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("skia.gpu"),
\ |
| 36 "GrBufferAllocPool Unmapping Buffer",
\ | 35 "GrBufferAllocPool Unmapping Buffer",
\ |
| 37 TRACE_EVENT_SCOPE_THREAD,
\ | 36 TRACE_EVENT_SCOPE_THREAD,
\ |
| 38 "percent_unwritten",
\ | 37 "percent_unwritten",
\ |
| 39 (float)((block).fBytesFree) / (block).fBuffer->gpuMemor
ySize()); \ | 38 (float)((block).fBytesFree) / (block).fBuffer->gpuMemor
ySize()); \ |
| 40 (block).fBuffer->unmap();
\ | 39 (block).fBuffer->unmap();
\ |
| 41 } while (false) | 40 } while (false) |
| 42 | 41 |
| 43 GrBufferAllocPool::GrBufferAllocPool(GrGpu* gpu, | 42 GrBufferAllocPool::GrBufferAllocPool(GrGpu* gpu, |
| 44 BufferType bufferType, | 43 GrBufferType bufferType, |
| 45 size_t blockSize) | 44 size_t blockSize) |
| 46 : fBlocks(8) { | 45 : fBlocks(8) { |
| 47 | 46 |
| 48 fGpu = SkRef(gpu); | 47 fGpu = SkRef(gpu); |
| 49 fCpuData = nullptr; | 48 fCpuData = nullptr; |
| 50 fBufferType = bufferType; | 49 fBufferType = bufferType; |
| 51 fBufferPtr = nullptr; | 50 fBufferPtr = nullptr; |
| 52 fMinBlockSize = SkTMax(GrBufferAllocPool_MIN_BLOCK_SIZE, blockSize); | 51 fMinBlockSize = SkTMax(GrBufferAllocPool_MIN_BLOCK_SIZE, blockSize); |
| 53 | 52 |
| 54 fBytesInUse = 0; | 53 fBytesInUse = 0; |
| 55 | 54 |
| 56 fGeometryBufferMapThreshold = gpu->caps()->geometryBufferMapThreshold(); | 55 fBufferMapThreshold = gpu->caps()->bufferMapThreshold(); |
| 57 } | 56 } |
| 58 | 57 |
| 59 void GrBufferAllocPool::deleteBlocks() { | 58 void GrBufferAllocPool::deleteBlocks() { |
| 60 if (fBlocks.count()) { | 59 if (fBlocks.count()) { |
| 61 GrGeometryBuffer* buffer = fBlocks.back().fBuffer; | 60 GrBuffer* buffer = fBlocks.back().fBuffer; |
| 62 if (buffer->isMapped()) { | 61 if (buffer->isMapped()) { |
| 63 UNMAP_BUFFER(fBlocks.back()); | 62 UNMAP_BUFFER(fBlocks.back()); |
| 64 } | 63 } |
| 65 } | 64 } |
| 66 while (!fBlocks.empty()) { | 65 while (!fBlocks.empty()) { |
| 67 this->destroyBlock(); | 66 this->destroyBlock(); |
| 68 } | 67 } |
| 69 SkASSERT(!fBufferPtr); | 68 SkASSERT(!fBufferPtr); |
| 70 } | 69 } |
| 71 | 70 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 102 } | 101 } |
| 103 VALIDATE(); | 102 VALIDATE(); |
| 104 } | 103 } |
| 105 | 104 |
| 106 #ifdef SK_DEBUG | 105 #ifdef SK_DEBUG |
| 107 void GrBufferAllocPool::validate(bool unusedBlockAllowed) const { | 106 void GrBufferAllocPool::validate(bool unusedBlockAllowed) const { |
| 108 bool wasDestroyed = false; | 107 bool wasDestroyed = false; |
| 109 if (fBufferPtr) { | 108 if (fBufferPtr) { |
| 110 SkASSERT(!fBlocks.empty()); | 109 SkASSERT(!fBlocks.empty()); |
| 111 if (fBlocks.back().fBuffer->isMapped()) { | 110 if (fBlocks.back().fBuffer->isMapped()) { |
| 112 GrGeometryBuffer* buf = fBlocks.back().fBuffer; | 111 GrBuffer* buf = fBlocks.back().fBuffer; |
| 113 SkASSERT(buf->mapPtr() == fBufferPtr); | 112 SkASSERT(buf->mapPtr() == fBufferPtr); |
| 114 } else { | 113 } else { |
| 115 SkASSERT(fCpuData == fBufferPtr); | 114 SkASSERT(fCpuData == fBufferPtr); |
| 116 } | 115 } |
| 117 } else { | 116 } else { |
| 118 SkASSERT(fBlocks.empty() || !fBlocks.back().fBuffer->isMapped()); | 117 SkASSERT(fBlocks.empty() || !fBlocks.back().fBuffer->isMapped()); |
| 119 } | 118 } |
| 120 size_t bytesInUse = 0; | 119 size_t bytesInUse = 0; |
| 121 for (int i = 0; i < fBlocks.count() - 1; ++i) { | 120 for (int i = 0; i < fBlocks.count() - 1; ++i) { |
| 122 SkASSERT(!fBlocks[i].fBuffer->isMapped()); | 121 SkASSERT(!fBlocks[i].fBuffer->isMapped()); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 138 (!fBytesInUse && (fBlocks.count() < 2))); | 137 (!fBytesInUse && (fBlocks.count() < 2))); |
| 139 } else { | 138 } else { |
| 140 SkASSERT((0 == fBytesInUse) == fBlocks.empty()); | 139 SkASSERT((0 == fBytesInUse) == fBlocks.empty()); |
| 141 } | 140 } |
| 142 } | 141 } |
| 143 } | 142 } |
| 144 #endif | 143 #endif |
| 145 | 144 |
| 146 void* GrBufferAllocPool::makeSpace(size_t size, | 145 void* GrBufferAllocPool::makeSpace(size_t size, |
| 147 size_t alignment, | 146 size_t alignment, |
| 148 const GrGeometryBuffer** buffer, | 147 const GrBuffer** buffer, |
| 149 size_t* offset) { | 148 size_t* offset) { |
| 150 VALIDATE(); | 149 VALIDATE(); |
| 151 | 150 |
| 152 SkASSERT(buffer); | 151 SkASSERT(buffer); |
| 153 SkASSERT(offset); | 152 SkASSERT(offset); |
| 154 | 153 |
| 155 if (fBufferPtr) { | 154 if (fBufferPtr) { |
| 156 BufferBlock& back = fBlocks.back(); | 155 BufferBlock& back = fBlocks.back(); |
| 157 size_t usedBytes = back.fBuffer->gpuMemorySize() - back.fBytesFree; | 156 size_t usedBytes = back.fBuffer->gpuMemorySize() - back.fBytesFree; |
| 158 size_t pad = GrSizeAlignUpPad(usedBytes, alignment); | 157 size_t pad = GrSizeAlignUpPad(usedBytes, alignment); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 fBufferPtr = nullptr; | 244 fBufferPtr = nullptr; |
| 246 } | 245 } |
| 247 | 246 |
| 248 SkASSERT(!fBufferPtr); | 247 SkASSERT(!fBufferPtr); |
| 249 | 248 |
| 250 // If the buffer is CPU-backed we map it because it is free to do so and sav
es a copy. | 249 // If the buffer is CPU-backed we map it because it is free to do so and sav
es a copy. |
| 251 // Otherwise when buffer mapping is supported we map if the buffer size is g
reater than the | 250 // Otherwise when buffer mapping is supported we map if the buffer size is g
reater than the |
| 252 // threshold. | 251 // threshold. |
| 253 bool attemptMap = block.fBuffer->isCPUBacked(); | 252 bool attemptMap = block.fBuffer->isCPUBacked(); |
| 254 if (!attemptMap && GrCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags())
{ | 253 if (!attemptMap && GrCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags())
{ |
| 255 attemptMap = size > fGeometryBufferMapThreshold; | 254 attemptMap = size > fBufferMapThreshold; |
| 256 } | 255 } |
| 257 | 256 |
| 258 if (attemptMap) { | 257 if (attemptMap) { |
| 259 fBufferPtr = block.fBuffer->map(); | 258 fBufferPtr = block.fBuffer->map(); |
| 260 } | 259 } |
| 261 | 260 |
| 262 if (!fBufferPtr) { | 261 if (!fBufferPtr) { |
| 263 fBufferPtr = this->resetCpuData(block.fBytesFree); | 262 fBufferPtr = this->resetCpuData(block.fBytesFree); |
| 264 } | 263 } |
| 265 | 264 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 288 fCpuData = sk_malloc_throw(newSize); | 287 fCpuData = sk_malloc_throw(newSize); |
| 289 } | 288 } |
| 290 } else { | 289 } else { |
| 291 fCpuData = nullptr; | 290 fCpuData = nullptr; |
| 292 } | 291 } |
| 293 return fCpuData; | 292 return fCpuData; |
| 294 } | 293 } |
| 295 | 294 |
| 296 | 295 |
| 297 void GrBufferAllocPool::flushCpuData(const BufferBlock& block, size_t flushSize)
{ | 296 void GrBufferAllocPool::flushCpuData(const BufferBlock& block, size_t flushSize)
{ |
| 298 GrGeometryBuffer* buffer = block.fBuffer; | 297 GrBuffer* buffer = block.fBuffer; |
| 299 SkASSERT(buffer); | 298 SkASSERT(buffer); |
| 300 SkASSERT(!buffer->isMapped()); | 299 SkASSERT(!buffer->isMapped()); |
| 301 SkASSERT(fCpuData == fBufferPtr); | 300 SkASSERT(fCpuData == fBufferPtr); |
| 302 SkASSERT(flushSize <= buffer->gpuMemorySize()); | 301 SkASSERT(flushSize <= buffer->gpuMemorySize()); |
| 303 VALIDATE(true); | 302 VALIDATE(true); |
| 304 | 303 |
| 305 if (GrCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags() && | 304 if (GrCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags() && |
| 306 flushSize > fGeometryBufferMapThreshold) { | 305 flushSize > fBufferMapThreshold) { |
| 307 void* data = buffer->map(); | 306 void* data = buffer->map(); |
| 308 if (data) { | 307 if (data) { |
| 309 memcpy(data, fBufferPtr, flushSize); | 308 memcpy(data, fBufferPtr, flushSize); |
| 310 UNMAP_BUFFER(block); | 309 UNMAP_BUFFER(block); |
| 311 return; | 310 return; |
| 312 } | 311 } |
| 313 } | 312 } |
| 314 buffer->updateData(fBufferPtr, flushSize); | 313 buffer->updateData(fBufferPtr, flushSize); |
| 315 VALIDATE(true); | 314 VALIDATE(true); |
| 316 } | 315 } |
| 317 | 316 |
| 318 GrGeometryBuffer* GrBufferAllocPool::getBuffer(size_t size) { | 317 GrBuffer* GrBufferAllocPool::getBuffer(size_t size) { |
| 319 | 318 |
| 320 GrResourceProvider* rp = fGpu->getContext()->resourceProvider(); | 319 GrResourceProvider* rp = fGpu->getContext()->resourceProvider(); |
| 321 | 320 |
| 322 static const GrResourceProvider::BufferUsage kUsage = GrResourceProvider::kD
ynamic_BufferUsage; | |
| 323 // Shouldn't have to use this flag (https://bug.skia.org/4156) | 321 // Shouldn't have to use this flag (https://bug.skia.org/4156) |
| 324 static const uint32_t kFlags = GrResourceProvider::kNoPendingIO_Flag; | 322 static const uint32_t kFlags = GrResourceProvider::kNoPendingIO_Flag; |
| 325 if (kIndex_BufferType == fBufferType) { | 323 return rp->createBuffer(fBufferType, size, kDynamic_GrAccessPattern, kFlags)
; |
| 326 return rp->createIndexBuffer(size, kUsage, kFlags); | |
| 327 } else { | |
| 328 SkASSERT(kVertex_BufferType == fBufferType); | |
| 329 return rp->createVertexBuffer(size, kUsage, kFlags); | |
| 330 } | |
| 331 } | 324 } |
| 332 | 325 |
| 333 //////////////////////////////////////////////////////////////////////////////// | 326 //////////////////////////////////////////////////////////////////////////////// |
| 334 | 327 |
| 335 GrVertexBufferAllocPool::GrVertexBufferAllocPool(GrGpu* gpu) | 328 GrVertexBufferAllocPool::GrVertexBufferAllocPool(GrGpu* gpu) |
| 336 : GrBufferAllocPool(gpu, kVertex_BufferType, MIN_VERTEX_BUFFER_SIZE) { | 329 : GrBufferAllocPool(gpu, kVertex_GrBufferType, MIN_VERTEX_BUFFER_SIZE) { |
| 337 } | 330 } |
| 338 | 331 |
| 339 void* GrVertexBufferAllocPool::makeSpace(size_t vertexSize, | 332 void* GrVertexBufferAllocPool::makeSpace(size_t vertexSize, |
| 340 int vertexCount, | 333 int vertexCount, |
| 341 const GrVertexBuffer** buffer, | 334 const GrBuffer** buffer, |
| 342 int* startVertex) { | 335 int* startVertex) { |
| 343 | 336 |
| 344 SkASSERT(vertexCount >= 0); | 337 SkASSERT(vertexCount >= 0); |
| 345 SkASSERT(buffer); | 338 SkASSERT(buffer); |
| 346 SkASSERT(startVertex); | 339 SkASSERT(startVertex); |
| 347 | 340 |
| 348 size_t offset = 0; // assign to suppress warning | 341 size_t offset = 0; // assign to suppress warning |
| 349 const GrGeometryBuffer* geomBuffer = nullptr; // assign to suppress warning | |
| 350 void* ptr = INHERITED::makeSpace(vertexSize * vertexCount, | 342 void* ptr = INHERITED::makeSpace(vertexSize * vertexCount, |
| 351 vertexSize, | 343 vertexSize, |
| 352 &geomBuffer, | 344 buffer, |
| 353 &offset); | 345 &offset); |
| 354 | 346 |
| 355 *buffer = (const GrVertexBuffer*) geomBuffer; | |
| 356 SkASSERT(0 == offset % vertexSize); | 347 SkASSERT(0 == offset % vertexSize); |
| 357 *startVertex = static_cast<int>(offset / vertexSize); | 348 *startVertex = static_cast<int>(offset / vertexSize); |
| 358 return ptr; | 349 return ptr; |
| 359 } | 350 } |
| 360 | 351 |
| 361 //////////////////////////////////////////////////////////////////////////////// | 352 //////////////////////////////////////////////////////////////////////////////// |
| 362 | 353 |
| 363 GrIndexBufferAllocPool::GrIndexBufferAllocPool(GrGpu* gpu) | 354 GrIndexBufferAllocPool::GrIndexBufferAllocPool(GrGpu* gpu) |
| 364 : GrBufferAllocPool(gpu, kIndex_BufferType, MIN_INDEX_BUFFER_SIZE) { | 355 : GrBufferAllocPool(gpu, kIndex_GrBufferType, MIN_INDEX_BUFFER_SIZE) { |
| 365 } | 356 } |
| 366 | 357 |
| 367 void* GrIndexBufferAllocPool::makeSpace(int indexCount, | 358 void* GrIndexBufferAllocPool::makeSpace(int indexCount, |
| 368 const GrIndexBuffer** buffer, | 359 const GrBuffer** buffer, |
| 369 int* startIndex) { | 360 int* startIndex) { |
| 370 | 361 |
| 371 SkASSERT(indexCount >= 0); | 362 SkASSERT(indexCount >= 0); |
| 372 SkASSERT(buffer); | 363 SkASSERT(buffer); |
| 373 SkASSERT(startIndex); | 364 SkASSERT(startIndex); |
| 374 | 365 |
| 375 size_t offset = 0; // assign to suppress warning | 366 size_t offset = 0; // assign to suppress warning |
| 376 const GrGeometryBuffer* geomBuffer = nullptr; // assign to suppress warning | |
| 377 void* ptr = INHERITED::makeSpace(indexCount * sizeof(uint16_t), | 367 void* ptr = INHERITED::makeSpace(indexCount * sizeof(uint16_t), |
| 378 sizeof(uint16_t), | 368 sizeof(uint16_t), |
| 379 &geomBuffer, | 369 buffer, |
| 380 &offset); | 370 &offset); |
| 381 | 371 |
| 382 *buffer = (const GrIndexBuffer*) geomBuffer; | |
| 383 SkASSERT(0 == offset % sizeof(uint16_t)); | 372 SkASSERT(0 == offset % sizeof(uint16_t)); |
| 384 *startIndex = static_cast<int>(offset / sizeof(uint16_t)); | 373 *startIndex = static_cast<int>(offset / sizeof(uint16_t)); |
| 385 return ptr; | 374 return ptr; |
| 386 } | 375 } |
| OLD | NEW |