GrMtlBuffer.mm 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /*
  2. * Copyright 2018 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/private/GrTypesPriv.h"
  8. #include "src/gpu/GrGpuResourcePriv.h"
  9. #include "src/gpu/mtl/GrMtlBuffer.h"
  10. #include "src/gpu/mtl/GrMtlCommandBuffer.h"
  11. #include "src/gpu/mtl/GrMtlGpu.h"
  12. #if !__has_feature(objc_arc)
  13. #error This file must be compiled with Arc. Use -fobjc-arc flag
  14. #endif
  15. #ifdef SK_DEBUG
  16. #define VALIDATE() this->validate()
  17. #else
  18. #define VALIDATE() do {} while(false)
  19. #endif
  20. sk_sp<GrMtlBuffer> GrMtlBuffer::Make(GrMtlGpu* gpu, size_t size, GrGpuBufferType intendedType,
  21. GrAccessPattern accessPattern, const void* data) {
  22. sk_sp<GrMtlBuffer> buffer(new GrMtlBuffer(gpu, size, intendedType, accessPattern));
  23. if (data && !buffer->onUpdateData(data, size)) {
  24. return nullptr;
  25. }
  26. return buffer;
  27. }
  28. GrMtlBuffer::GrMtlBuffer(GrMtlGpu* gpu, size_t size, GrGpuBufferType intendedType,
  29. GrAccessPattern accessPattern)
  30. : INHERITED(gpu, size, intendedType, accessPattern)
  31. , fIsDynamic(accessPattern != kStatic_GrAccessPattern)
  32. , fOffset(0) {
  33. // We'll allocate dynamic buffers when we map them, below.
  34. if (!fIsDynamic) {
  35. // TODO: newBufferWithBytes: used to work with StorageModePrivate buffers -- seems like
  36. // a bug that it no longer does. If that changes we could use that to pre-load the buffer.
  37. fMtlBuffer = size == 0 ? nil :
  38. [gpu->device() newBufferWithLength: size
  39. options: MTLResourceStorageModePrivate];
  40. }
  41. this->registerWithCache(SkBudgeted::kYes);
  42. VALIDATE();
  43. }
  44. GrMtlBuffer::~GrMtlBuffer() {
  45. SkASSERT(fMtlBuffer == nil);
  46. SkASSERT(fMappedBuffer == nil);
  47. SkASSERT(fMapPtr == nullptr);
  48. }
  49. bool GrMtlBuffer::onUpdateData(const void* src, size_t srcInBytes) {
  50. if (!fIsDynamic) {
  51. if (fMtlBuffer == nil) {
  52. return false;
  53. }
  54. if (srcInBytes > fMtlBuffer.length) {
  55. return false;
  56. }
  57. }
  58. VALIDATE();
  59. this->internalMap(srcInBytes);
  60. if (fMapPtr == nil) {
  61. return false;
  62. }
  63. SkASSERT(fMappedBuffer);
  64. if (!fIsDynamic) {
  65. SkASSERT(srcInBytes == fMappedBuffer.length);
  66. }
  67. memcpy(fMapPtr, src, srcInBytes);
  68. this->internalUnmap(srcInBytes);
  69. VALIDATE();
  70. return true;
  71. }
  72. inline GrMtlGpu* GrMtlBuffer::mtlGpu() const {
  73. SkASSERT(!this->wasDestroyed());
  74. return static_cast<GrMtlGpu*>(this->getGpu());
  75. }
  76. void GrMtlBuffer::onAbandon() {
  77. fMtlBuffer = nil;
  78. fMappedBuffer = nil;
  79. fMapPtr = nullptr;
  80. VALIDATE();
  81. INHERITED::onAbandon();
  82. }
  83. void GrMtlBuffer::onRelease() {
  84. if (!this->wasDestroyed()) {
  85. VALIDATE();
  86. fMtlBuffer = nil;
  87. fMappedBuffer = nil;
  88. fMapPtr = nullptr;
  89. VALIDATE();
  90. }
  91. INHERITED::onRelease();
  92. }
  93. void GrMtlBuffer::internalMap(size_t sizeInBytes) {
  94. if (this->wasDestroyed()) {
  95. return;
  96. }
  97. VALIDATE();
  98. SkASSERT(!this->isMapped());
  99. if (fIsDynamic) {
  100. fMtlBuffer = this->mtlGpu()->resourceProvider().getDynamicBuffer(sizeInBytes, &fOffset);
  101. fMappedBuffer = fMtlBuffer;
  102. fMapPtr = static_cast<char*>(fMtlBuffer.contents) + fOffset;
  103. } else {
  104. SkASSERT(fMtlBuffer);
  105. SkASSERT(fMappedBuffer == nil);
  106. fMappedBuffer =
  107. [this->mtlGpu()->device() newBufferWithLength: sizeInBytes
  108. options: MTLResourceStorageModeShared];
  109. fMapPtr = fMappedBuffer.contents;
  110. }
  111. VALIDATE();
  112. }
  113. void GrMtlBuffer::internalUnmap(size_t sizeInBytes) {
  114. SkASSERT(fMtlBuffer);
  115. if (this->wasDestroyed()) {
  116. return;
  117. }
  118. VALIDATE();
  119. SkASSERT(this->isMapped());
  120. if (fMtlBuffer == nil) {
  121. fMappedBuffer = nil;
  122. fMapPtr = nullptr;
  123. return;
  124. }
  125. if (fIsDynamic) {
  126. #ifdef SK_BUILD_FOR_MAC
  127. // TODO: need to make sure offset and size have valid alignments.
  128. [fMtlBuffer didModifyRange: NSMakeRange(fOffset, sizeInBytes)];
  129. #endif
  130. } else {
  131. GrMtlCommandBuffer* cmdBuffer = this->mtlGpu()->commandBuffer();
  132. id<MTLBlitCommandEncoder> blitCmdEncoder = cmdBuffer->getBlitCommandEncoder();
  133. [blitCmdEncoder copyFromBuffer: fMappedBuffer
  134. sourceOffset: 0
  135. toBuffer: fMtlBuffer
  136. destinationOffset: 0
  137. size: sizeInBytes];
  138. }
  139. fMappedBuffer = nil;
  140. fMapPtr = nullptr;
  141. }
  142. void GrMtlBuffer::onMap() {
  143. this->internalMap(this->size());
  144. }
  145. void GrMtlBuffer::onUnmap() {
  146. this->internalUnmap(this->size());
  147. }
  148. #ifdef SK_DEBUG
  149. void GrMtlBuffer::validate() const {
  150. SkASSERT(fMtlBuffer == nil ||
  151. this->intendedType() == GrGpuBufferType::kVertex ||
  152. this->intendedType() == GrGpuBufferType::kIndex ||
  153. this->intendedType() == GrGpuBufferType::kXferCpuToGpu ||
  154. this->intendedType() == GrGpuBufferType::kXferGpuToCpu);
  155. SkASSERT(fMappedBuffer == nil || fMtlBuffer == nil ||
  156. fMappedBuffer.length <= fMtlBuffer.length);
  157. }
  158. #endif