GrGLBuffer.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /*
  2. * Copyright 2016 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. #include "include/core/SkTraceMemoryDump.h"
  8. #include "src/gpu/GrGpuResourcePriv.h"
  9. #include "src/gpu/gl/GrGLBuffer.h"
  10. #include "src/gpu/gl/GrGLGpu.h"
  11. #define GL_CALL(X) GR_GL_CALL(this->glGpu()->glInterface(), X)
  12. #define GL_CALL_RET(RET, X) GR_GL_CALL_RET(this->glGpu()->glInterface(), RET, X)
  13. #if GR_GL_CHECK_ALLOC_WITH_GET_ERROR
  14. #define CLEAR_ERROR_BEFORE_ALLOC(iface) GrGLClearErr(iface)
  15. #define GL_ALLOC_CALL(iface, call) GR_GL_CALL_NOERRCHECK(iface, call)
  16. #define CHECK_ALLOC_ERROR(iface) GR_GL_GET_ERROR(iface)
  17. #else
  18. #define CLEAR_ERROR_BEFORE_ALLOC(iface)
  19. #define GL_ALLOC_CALL(iface, call) GR_GL_CALL(iface, call)
  20. #define CHECK_ALLOC_ERROR(iface) GR_GL_NO_ERROR
  21. #endif
  22. #ifdef SK_DEBUG
  23. #define VALIDATE() this->validate()
  24. #else
  25. #define VALIDATE() do {} while(false)
  26. #endif
  27. sk_sp<GrGLBuffer> GrGLBuffer::Make(GrGLGpu* gpu, size_t size, GrGpuBufferType intendedType,
  28. GrAccessPattern accessPattern, const void* data) {
  29. if (gpu->glCaps().transferBufferType() == GrGLCaps::kNone_TransferBufferType &&
  30. (GrGpuBufferType::kXferCpuToGpu == intendedType ||
  31. GrGpuBufferType::kXferGpuToCpu == intendedType)) {
  32. return nullptr;
  33. }
  34. sk_sp<GrGLBuffer> buffer(new GrGLBuffer(gpu, size, intendedType, accessPattern, data));
  35. if (0 == buffer->bufferID()) {
  36. return nullptr;
  37. }
  38. return buffer;
  39. }
  40. // GL_STREAM_DRAW triggers an optimization in Chromium's GPU process where a client's vertex buffer
  41. // objects are implemented as client-side-arrays on tile-deferred architectures.
  42. #define DYNAMIC_DRAW_PARAM GR_GL_STREAM_DRAW
  43. inline static GrGLenum gr_to_gl_access_pattern(GrGpuBufferType bufferType,
  44. GrAccessPattern accessPattern) {
  45. auto drawUsage = [](GrAccessPattern pattern) {
  46. switch (pattern) {
  47. case kDynamic_GrAccessPattern:
  48. // TODO: Do we really want to use STREAM_DRAW here on non-Chromium?
  49. return DYNAMIC_DRAW_PARAM;
  50. case kStatic_GrAccessPattern:
  51. return GR_GL_STATIC_DRAW;
  52. case kStream_GrAccessPattern:
  53. return GR_GL_STREAM_DRAW;
  54. }
  55. SK_ABORT("Unexpected access pattern");
  56. return GR_GL_STATIC_DRAW;
  57. };
  58. auto readUsage = [](GrAccessPattern pattern) {
  59. switch (pattern) {
  60. case kDynamic_GrAccessPattern:
  61. return GR_GL_DYNAMIC_READ;
  62. case kStatic_GrAccessPattern:
  63. return GR_GL_STATIC_READ;
  64. case kStream_GrAccessPattern:
  65. return GR_GL_STREAM_READ;
  66. }
  67. SK_ABORT("Unexpected access pattern");
  68. return GR_GL_STATIC_READ;
  69. };
  70. auto usageType = [&drawUsage, &readUsage](GrGpuBufferType type, GrAccessPattern pattern) {
  71. switch (type) {
  72. case GrGpuBufferType::kVertex:
  73. case GrGpuBufferType::kIndex:
  74. case GrGpuBufferType::kXferCpuToGpu:
  75. return drawUsage(pattern);
  76. case GrGpuBufferType::kXferGpuToCpu:
  77. return readUsage(pattern);
  78. }
  79. SK_ABORT("Unexpected gpu buffer type.");
  80. return GR_GL_STATIC_DRAW;
  81. };
  82. return usageType(bufferType, accessPattern);
  83. }
  84. GrGLBuffer::GrGLBuffer(GrGLGpu* gpu, size_t size, GrGpuBufferType intendedType,
  85. GrAccessPattern accessPattern, const void* data)
  86. : INHERITED(gpu, size, intendedType, accessPattern)
  87. , fIntendedType(intendedType)
  88. , fBufferID(0)
  89. , fUsage(gr_to_gl_access_pattern(intendedType, accessPattern))
  90. , fGLSizeInBytes(0)
  91. , fHasAttachedToTexture(false) {
  92. GL_CALL(GenBuffers(1, &fBufferID));
  93. if (fBufferID) {
  94. GrGLenum target = gpu->bindBuffer(fIntendedType, this);
  95. CLEAR_ERROR_BEFORE_ALLOC(gpu->glInterface());
  96. // make sure driver can allocate memory for this buffer
  97. GL_ALLOC_CALL(gpu->glInterface(), BufferData(target,
  98. (GrGLsizeiptr) size,
  99. data,
  100. fUsage));
  101. if (CHECK_ALLOC_ERROR(gpu->glInterface()) != GR_GL_NO_ERROR) {
  102. GL_CALL(DeleteBuffers(1, &fBufferID));
  103. fBufferID = 0;
  104. } else {
  105. fGLSizeInBytes = size;
  106. }
  107. }
  108. VALIDATE();
  109. this->registerWithCache(SkBudgeted::kYes);
  110. if (!fBufferID) {
  111. this->resourcePriv().removeScratchKey();
  112. }
  113. }
  114. inline GrGLGpu* GrGLBuffer::glGpu() const {
  115. SkASSERT(!this->wasDestroyed());
  116. return static_cast<GrGLGpu*>(this->getGpu());
  117. }
  118. inline const GrGLCaps& GrGLBuffer::glCaps() const {
  119. return this->glGpu()->glCaps();
  120. }
  121. void GrGLBuffer::onRelease() {
  122. TRACE_EVENT0("skia.gpu", TRACE_FUNC);
  123. if (!this->wasDestroyed()) {
  124. VALIDATE();
  125. // make sure we've not been abandoned or already released
  126. if (fBufferID) {
  127. GL_CALL(DeleteBuffers(1, &fBufferID));
  128. fBufferID = 0;
  129. fGLSizeInBytes = 0;
  130. }
  131. fMapPtr = nullptr;
  132. VALIDATE();
  133. }
  134. INHERITED::onRelease();
  135. }
  136. void GrGLBuffer::onAbandon() {
  137. fBufferID = 0;
  138. fGLSizeInBytes = 0;
  139. fMapPtr = nullptr;
  140. VALIDATE();
  141. INHERITED::onAbandon();
  142. }
  143. void GrGLBuffer::onMap() {
  144. SkASSERT(fBufferID);
  145. SkASSERT(!this->wasDestroyed());
  146. VALIDATE();
  147. SkASSERT(!this->isMapped());
  148. // TODO: Make this a function parameter.
  149. bool readOnly = (GrGpuBufferType::kXferGpuToCpu == fIntendedType);
  150. // Handling dirty context is done in the bindBuffer call
  151. switch (this->glCaps().mapBufferType()) {
  152. case GrGLCaps::kNone_MapBufferType:
  153. return;
  154. case GrGLCaps::kMapBuffer_MapBufferType: {
  155. GrGLenum target = this->glGpu()->bindBuffer(fIntendedType, this);
  156. if (!readOnly) {
  157. // Let driver know it can discard the old data
  158. if (this->glCaps().useBufferDataNullHint() || fGLSizeInBytes != this->size()) {
  159. GL_CALL(BufferData(target, this->size(), nullptr, fUsage));
  160. }
  161. }
  162. GL_CALL_RET(fMapPtr, MapBuffer(target, readOnly ? GR_GL_READ_ONLY : GR_GL_WRITE_ONLY));
  163. break;
  164. }
  165. case GrGLCaps::kMapBufferRange_MapBufferType: {
  166. GrGLenum target = this->glGpu()->bindBuffer(fIntendedType, this);
  167. // Make sure the GL buffer size agrees with fDesc before mapping.
  168. if (fGLSizeInBytes != this->size()) {
  169. GL_CALL(BufferData(target, this->size(), nullptr, fUsage));
  170. }
  171. GrGLbitfield access;
  172. if (readOnly) {
  173. access = GR_GL_MAP_READ_BIT;
  174. } else {
  175. access = GR_GL_MAP_WRITE_BIT;
  176. if (GrGpuBufferType::kXferCpuToGpu != fIntendedType) {
  177. // TODO: Make this a function parameter.
  178. access |= GR_GL_MAP_INVALIDATE_BUFFER_BIT;
  179. }
  180. }
  181. GL_CALL_RET(fMapPtr, MapBufferRange(target, 0, this->size(), access));
  182. break;
  183. }
  184. case GrGLCaps::kChromium_MapBufferType: {
  185. GrGLenum target = this->glGpu()->bindBuffer(fIntendedType, this);
  186. // Make sure the GL buffer size agrees with fDesc before mapping.
  187. if (fGLSizeInBytes != this->size()) {
  188. GL_CALL(BufferData(target, this->size(), nullptr, fUsage));
  189. }
  190. GL_CALL_RET(fMapPtr, MapBufferSubData(target, 0, this->size(),
  191. readOnly ? GR_GL_READ_ONLY : GR_GL_WRITE_ONLY));
  192. break;
  193. }
  194. }
  195. fGLSizeInBytes = this->size();
  196. VALIDATE();
  197. }
  198. void GrGLBuffer::onUnmap() {
  199. SkASSERT(fBufferID);
  200. VALIDATE();
  201. SkASSERT(this->isMapped());
  202. if (0 == fBufferID) {
  203. fMapPtr = nullptr;
  204. return;
  205. }
  206. // bind buffer handles the dirty context
  207. switch (this->glCaps().mapBufferType()) {
  208. case GrGLCaps::kNone_MapBufferType:
  209. SkDEBUGFAIL("Shouldn't get here.");
  210. return;
  211. case GrGLCaps::kMapBuffer_MapBufferType: // fall through
  212. case GrGLCaps::kMapBufferRange_MapBufferType: {
  213. GrGLenum target = this->glGpu()->bindBuffer(fIntendedType, this);
  214. GL_CALL(UnmapBuffer(target));
  215. break;
  216. }
  217. case GrGLCaps::kChromium_MapBufferType:
  218. this->glGpu()->bindBuffer(fIntendedType, this); // TODO: Is this needed?
  219. GL_CALL(UnmapBufferSubData(fMapPtr));
  220. break;
  221. }
  222. fMapPtr = nullptr;
  223. }
  224. bool GrGLBuffer::onUpdateData(const void* src, size_t srcSizeInBytes) {
  225. SkASSERT(fBufferID);
  226. if (this->wasDestroyed()) {
  227. return false;
  228. }
  229. SkASSERT(!this->isMapped());
  230. VALIDATE();
  231. if (srcSizeInBytes > this->size()) {
  232. return false;
  233. }
  234. SkASSERT(srcSizeInBytes <= this->size());
  235. // bindbuffer handles dirty context
  236. GrGLenum target = this->glGpu()->bindBuffer(fIntendedType, this);
  237. if (this->glCaps().useBufferDataNullHint()) {
  238. if (this->size() == srcSizeInBytes) {
  239. GL_CALL(BufferData(target, (GrGLsizeiptr) srcSizeInBytes, src, fUsage));
  240. } else {
  241. // Before we call glBufferSubData we give the driver a hint using
  242. // glBufferData with nullptr. This makes the old buffer contents
  243. // inaccessible to future draws. The GPU may still be processing
  244. // draws that reference the old contents. With this hint it can
  245. // assign a different allocation for the new contents to avoid
  246. // flushing the gpu past draws consuming the old contents.
  247. // TODO I think we actually want to try calling bufferData here
  248. GL_CALL(BufferData(target, this->size(), nullptr, fUsage));
  249. GL_CALL(BufferSubData(target, 0, (GrGLsizeiptr) srcSizeInBytes, src));
  250. }
  251. fGLSizeInBytes = this->size();
  252. } else {
  253. // Note that we're cheating on the size here. Currently no methods
  254. // allow a partial update that preserves contents of non-updated
  255. // portions of the buffer (map() does a glBufferData(..size, nullptr..))
  256. GL_CALL(BufferData(target, srcSizeInBytes, src, fUsage));
  257. fGLSizeInBytes = srcSizeInBytes;
  258. }
  259. VALIDATE();
  260. return true;
  261. }
  262. void GrGLBuffer::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump,
  263. const SkString& dumpName) const {
  264. SkString buffer_id;
  265. buffer_id.appendU32(this->bufferID());
  266. traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_buffer",
  267. buffer_id.c_str());
  268. }
  269. #ifdef SK_DEBUG
  270. void GrGLBuffer::validate() const {
  271. SkASSERT(0 != fBufferID || 0 == fGLSizeInBytes);
  272. SkASSERT(nullptr == fMapPtr || fGLSizeInBytes <= this->size());
  273. }
  274. #endif