1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2018 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/private/GrTypesPriv.h" 9cb93a386Sopenharmony_ci#include "src/gpu/GrGpuResourcePriv.h" 10cb93a386Sopenharmony_ci#include "src/gpu/GrStagingBufferManager.h" 11cb93a386Sopenharmony_ci#include "src/gpu/mtl/GrMtlBuffer.h" 12cb93a386Sopenharmony_ci#include "src/gpu/mtl/GrMtlCommandBuffer.h" 13cb93a386Sopenharmony_ci#include "src/gpu/mtl/GrMtlGpu.h" 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ci#if !__has_feature(objc_arc) 16cb93a386Sopenharmony_ci#error This file must be compiled with Arc. Use -fobjc-arc flag 17cb93a386Sopenharmony_ci#endif 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_ci#ifdef SK_DEBUG 20cb93a386Sopenharmony_ci#define VALIDATE() this->validate() 21cb93a386Sopenharmony_ci#else 22cb93a386Sopenharmony_ci#define VALIDATE() do {} while(false) 23cb93a386Sopenharmony_ci#endif 24cb93a386Sopenharmony_ci 25cb93a386Sopenharmony_ciGR_NORETAIN_BEGIN 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_ci#ifdef SK_ENABLE_MTL_DEBUG_INFO 28cb93a386Sopenharmony_ciNSString* kBufferTypeNames[kGrGpuBufferTypeCount] = { 29cb93a386Sopenharmony_ci @"Vertex", 30cb93a386Sopenharmony_ci @"Index", 31cb93a386Sopenharmony_ci @"Indirect", 32cb93a386Sopenharmony_ci @"Xfer CPU to GPU", 33cb93a386Sopenharmony_ci @"Xfer GPU to CPU", 34cb93a386Sopenharmony_ci @"Uniform", 35cb93a386Sopenharmony_ci}; 36cb93a386Sopenharmony_ci#endif 37cb93a386Sopenharmony_ci 38cb93a386Sopenharmony_cisk_sp<GrMtlBuffer> GrMtlBuffer::Make(GrMtlGpu* gpu, size_t size, GrGpuBufferType intendedType, 39cb93a386Sopenharmony_ci GrAccessPattern accessPattern, const void* data) { 40cb93a386Sopenharmony_ci sk_sp<GrMtlBuffer> buffer(new GrMtlBuffer(gpu, size, intendedType, accessPattern)); 41cb93a386Sopenharmony_ci if (data && !buffer->onUpdateData(data, size)) { 42cb93a386Sopenharmony_ci return nullptr; 43cb93a386Sopenharmony_ci } 44cb93a386Sopenharmony_ci return buffer; 45cb93a386Sopenharmony_ci} 46cb93a386Sopenharmony_ci 47cb93a386Sopenharmony_ciGrMtlBuffer::GrMtlBuffer(GrMtlGpu* gpu, size_t size, GrGpuBufferType intendedType, 48cb93a386Sopenharmony_ci GrAccessPattern accessPattern) 49cb93a386Sopenharmony_ci : INHERITED(gpu, size, intendedType, accessPattern) 50cb93a386Sopenharmony_ci , fIsDynamic(accessPattern != kStatic_GrAccessPattern) { 51cb93a386Sopenharmony_ci NSUInteger options = 0; 52cb93a386Sopenharmony_ci if (@available(macOS 10.11, iOS 9.0, *)) { 53cb93a386Sopenharmony_ci if (fIsDynamic) { 54cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_MAC 55cb93a386Sopenharmony_ci if (gpu->mtlCaps().isMac()) { 56cb93a386Sopenharmony_ci options |= MTLResourceStorageModeManaged; 57cb93a386Sopenharmony_ci } else { 58cb93a386Sopenharmony_ci options |= MTLResourceStorageModeShared; 59cb93a386Sopenharmony_ci } 60cb93a386Sopenharmony_ci#else 61cb93a386Sopenharmony_ci options |= MTLResourceStorageModeShared; 62cb93a386Sopenharmony_ci#endif 63cb93a386Sopenharmony_ci } else { 64cb93a386Sopenharmony_ci options |= MTLResourceStorageModePrivate; 65cb93a386Sopenharmony_ci } 66cb93a386Sopenharmony_ci } 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_ci size = SkAlignTo(size, gpu->mtlCaps().getMinBufferAlignment()); 69cb93a386Sopenharmony_ci fMtlBuffer = size == 0 ? nil : 70cb93a386Sopenharmony_ci [gpu->device() newBufferWithLength: size 71cb93a386Sopenharmony_ci options: options]; 72cb93a386Sopenharmony_ci#ifdef SK_ENABLE_MTL_DEBUG_INFO 73cb93a386Sopenharmony_ci fMtlBuffer.label = kBufferTypeNames[(int)intendedType]; 74cb93a386Sopenharmony_ci#endif 75cb93a386Sopenharmony_ci this->registerWithCache(SkBudgeted::kYes); 76cb93a386Sopenharmony_ci VALIDATE(); 77cb93a386Sopenharmony_ci} 78cb93a386Sopenharmony_ci 79cb93a386Sopenharmony_ciGrMtlBuffer::~GrMtlBuffer() { 80cb93a386Sopenharmony_ci SkASSERT(!fMtlBuffer); 81cb93a386Sopenharmony_ci SkASSERT(!fMapPtr); 82cb93a386Sopenharmony_ci} 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_cibool GrMtlBuffer::onUpdateData(const void* src, size_t sizeInBytes) { 85cb93a386Sopenharmony_ci if (this->wasDestroyed()) { 86cb93a386Sopenharmony_ci return false; 87cb93a386Sopenharmony_ci } 88cb93a386Sopenharmony_ci 89cb93a386Sopenharmony_ci if (sizeInBytes > this->size()) { 90cb93a386Sopenharmony_ci return false; 91cb93a386Sopenharmony_ci } 92cb93a386Sopenharmony_ci 93cb93a386Sopenharmony_ci if (fIsDynamic) { 94cb93a386Sopenharmony_ci this->internalMap(sizeInBytes); 95cb93a386Sopenharmony_ci if (!fMapPtr) { 96cb93a386Sopenharmony_ci return false; 97cb93a386Sopenharmony_ci } 98cb93a386Sopenharmony_ci memcpy(fMapPtr, src, sizeInBytes); 99cb93a386Sopenharmony_ci this->internalUnmap(sizeInBytes); 100cb93a386Sopenharmony_ci } else { 101cb93a386Sopenharmony_ci // copy data to gpu buffer 102cb93a386Sopenharmony_ci GrStagingBufferManager::Slice slice; 103cb93a386Sopenharmony_ci slice = this->mtlGpu()->stagingBufferManager()->allocateStagingBufferSlice( 104cb93a386Sopenharmony_ci sizeInBytes, this->mtlGpu()->mtlCaps().getMinBufferAlignment()); 105cb93a386Sopenharmony_ci if (!slice.fBuffer) { 106cb93a386Sopenharmony_ci return false; 107cb93a386Sopenharmony_ci } 108cb93a386Sopenharmony_ci memcpy(slice.fOffsetMapPtr, src, sizeInBytes); 109cb93a386Sopenharmony_ci 110cb93a386Sopenharmony_ci GrMtlCommandBuffer* cmdBuffer = this->mtlGpu()->commandBuffer(); 111cb93a386Sopenharmony_ci id<MTLBlitCommandEncoder> GR_NORETAIN blitCmdEncoder = cmdBuffer->getBlitCommandEncoder(); 112cb93a386Sopenharmony_ci if (!blitCmdEncoder) { 113cb93a386Sopenharmony_ci return false; 114cb93a386Sopenharmony_ci } 115cb93a386Sopenharmony_ci GrMtlBuffer* mtlBuffer = static_cast<GrMtlBuffer*>(slice.fBuffer); 116cb93a386Sopenharmony_ci id<MTLBuffer> transferBuffer = mtlBuffer->mtlBuffer(); 117cb93a386Sopenharmony_ci [blitCmdEncoder copyFromBuffer: transferBuffer 118cb93a386Sopenharmony_ci sourceOffset: slice.fOffset 119cb93a386Sopenharmony_ci toBuffer: fMtlBuffer 120cb93a386Sopenharmony_ci destinationOffset: 0 121cb93a386Sopenharmony_ci size: sizeInBytes]; 122cb93a386Sopenharmony_ci } 123cb93a386Sopenharmony_ci 124cb93a386Sopenharmony_ci return true; 125cb93a386Sopenharmony_ci} 126cb93a386Sopenharmony_ci 127cb93a386Sopenharmony_ciinline GrMtlGpu* GrMtlBuffer::mtlGpu() const { 128cb93a386Sopenharmony_ci SkASSERT(!this->wasDestroyed()); 129cb93a386Sopenharmony_ci return static_cast<GrMtlGpu*>(this->getGpu()); 130cb93a386Sopenharmony_ci} 131cb93a386Sopenharmony_ci 132cb93a386Sopenharmony_civoid GrMtlBuffer::onAbandon() { 133cb93a386Sopenharmony_ci fMtlBuffer = nil; 134cb93a386Sopenharmony_ci fMapPtr = nullptr; 135cb93a386Sopenharmony_ci VALIDATE(); 136cb93a386Sopenharmony_ci INHERITED::onAbandon(); 137cb93a386Sopenharmony_ci} 138cb93a386Sopenharmony_ci 139cb93a386Sopenharmony_civoid GrMtlBuffer::onRelease() { 140cb93a386Sopenharmony_ci if (!this->wasDestroyed()) { 141cb93a386Sopenharmony_ci VALIDATE(); 142cb93a386Sopenharmony_ci fMtlBuffer = nil; 143cb93a386Sopenharmony_ci fMapPtr = nullptr; 144cb93a386Sopenharmony_ci VALIDATE(); 145cb93a386Sopenharmony_ci } 146cb93a386Sopenharmony_ci INHERITED::onRelease(); 147cb93a386Sopenharmony_ci} 148cb93a386Sopenharmony_ci 149cb93a386Sopenharmony_civoid GrMtlBuffer::internalMap(size_t sizeInBytes) { 150cb93a386Sopenharmony_ci if (fIsDynamic) { 151cb93a386Sopenharmony_ci VALIDATE(); 152cb93a386Sopenharmony_ci SkASSERT(sizeInBytes <= this->size()); 153cb93a386Sopenharmony_ci SkASSERT(!this->isMapped()); 154cb93a386Sopenharmony_ci fMapPtr = static_cast<char*>(fMtlBuffer.contents); 155cb93a386Sopenharmony_ci VALIDATE(); 156cb93a386Sopenharmony_ci } 157cb93a386Sopenharmony_ci} 158cb93a386Sopenharmony_ci 159cb93a386Sopenharmony_civoid GrMtlBuffer::internalUnmap(size_t sizeInBytes) { 160cb93a386Sopenharmony_ci SkASSERT(fMtlBuffer); 161cb93a386Sopenharmony_ci if (fIsDynamic) { 162cb93a386Sopenharmony_ci VALIDATE(); 163cb93a386Sopenharmony_ci SkASSERT(sizeInBytes <= this->size()); 164cb93a386Sopenharmony_ci SkASSERT(this->isMapped()); 165cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_MAC 166cb93a386Sopenharmony_ci if (this->mtlGpu()->mtlCaps().isMac()) { 167cb93a386Sopenharmony_ci [fMtlBuffer didModifyRange: NSMakeRange(0, sizeInBytes)]; 168cb93a386Sopenharmony_ci } 169cb93a386Sopenharmony_ci#endif 170cb93a386Sopenharmony_ci fMapPtr = nullptr; 171cb93a386Sopenharmony_ci } 172cb93a386Sopenharmony_ci} 173cb93a386Sopenharmony_ci 174cb93a386Sopenharmony_civoid GrMtlBuffer::onMap() { 175cb93a386Sopenharmony_ci if (!this->wasDestroyed()) { 176cb93a386Sopenharmony_ci this->internalMap(this->size()); 177cb93a386Sopenharmony_ci } 178cb93a386Sopenharmony_ci} 179cb93a386Sopenharmony_ci 180cb93a386Sopenharmony_civoid GrMtlBuffer::onUnmap() { 181cb93a386Sopenharmony_ci if (!this->wasDestroyed()) { 182cb93a386Sopenharmony_ci this->internalUnmap(this->size()); 183cb93a386Sopenharmony_ci } 184cb93a386Sopenharmony_ci} 185cb93a386Sopenharmony_ci 186cb93a386Sopenharmony_ci#ifdef SK_DEBUG 187cb93a386Sopenharmony_civoid GrMtlBuffer::validate() const { 188cb93a386Sopenharmony_ci SkASSERT(fMtlBuffer == nil || 189cb93a386Sopenharmony_ci this->intendedType() == GrGpuBufferType::kVertex || 190cb93a386Sopenharmony_ci this->intendedType() == GrGpuBufferType::kIndex || 191cb93a386Sopenharmony_ci this->intendedType() == GrGpuBufferType::kXferCpuToGpu || 192cb93a386Sopenharmony_ci this->intendedType() == GrGpuBufferType::kXferGpuToCpu || 193cb93a386Sopenharmony_ci this->intendedType() == GrGpuBufferType::kDrawIndirect || 194cb93a386Sopenharmony_ci this->intendedType() == GrGpuBufferType::kUniform); 195cb93a386Sopenharmony_ci SkASSERT((fMapPtr && fMtlBuffer) || !fMapPtr); 196cb93a386Sopenharmony_ci} 197cb93a386Sopenharmony_ci#endif 198cb93a386Sopenharmony_ci 199cb93a386Sopenharmony_ciGR_NORETAIN_END 200