1 /* 2 * Copyright 2017 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 #ifndef GrMtlGpu_DEFINED 9 #define GrMtlGpu_DEFINED 10 11 #include "include/gpu/GrTexture.h" 12 #include "src/gpu/GrGpu.h" 13 #include "src/gpu/GrRenderTarget.h" 14 #include "src/gpu/GrSemaphore.h" 15 16 #include "src/gpu/mtl/GrMtlCaps.h" 17 #include "src/gpu/mtl/GrMtlResourceProvider.h" 18 #include "src/gpu/mtl/GrMtlStencilAttachment.h" 19 20 #import <Metal/Metal.h> 21 22 class GrMtlGpuRTCommandBuffer; 23 class GrMtlTexture; 24 class GrSemaphore; 25 struct GrMtlBackendContext; 26 class GrMtlCommandBuffer; 27 28 namespace SkSL { 29 class Compiler; 30 } 31 32 class GrMtlGpu : public GrGpu { 33 public: 34 static sk_sp<GrGpu> Make(GrContext* context, const GrContextOptions& options, 35 id<MTLDevice> device, id<MTLCommandQueue> queue); 36 ~GrMtlGpu() override; 37 38 void disconnect(DisconnectType) override; 39 mtlCaps()40 const GrMtlCaps& mtlCaps() const { return *fMtlCaps.get(); } 41 device()42 id<MTLDevice> device() const { return fDevice; } 43 resourceProvider()44 GrMtlResourceProvider& resourceProvider() { return fResourceProvider; } 45 46 GrMtlCommandBuffer* commandBuffer(); 47 48 enum SyncQueue { 49 kForce_SyncQueue, 50 kSkip_SyncQueue 51 }; 52 53 // Commits the current command buffer to the queue and then creates a new command buffer. If 54 // sync is set to kForce_SyncQueue, the function will wait for all work in the committed 55 // command buffer to finish before creating a new buffer and returning. 56 void submitCommandBuffer(SyncQueue sync); 57 58 GrBackendTexture createBackendTexture(int w, int h, const GrBackendFormat&, 59 GrMipMapped, GrRenderable, 60 const void* pixels, size_t rowBytes, 61 const SkColor4f* color, 62 GrProtected isProtected) override; 63 64 void deleteBackendTexture(const GrBackendTexture&) override; 65 66 #if GR_TEST_UTILS 67 bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override; 68 69 GrBackendRenderTarget createTestingOnlyBackendRenderTarget(int w, int h, GrColorType) override; 70 void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override; 71 72 void testingOnly_flushGpuAndSync() override; 73 #endif 74 75 void copySurfaceAsResolve(GrSurface* dst, GrSurface* src); 76 77 void copySurfaceAsBlit(GrSurface* dst, GrSurface* src, const SkIRect& srcRect, 78 const SkIPoint& dstPoint); 79 80 bool onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect, 81 const SkIPoint& dstPoint, bool canDiscardOutsideDstRect) override; 82 83 GrGpuRTCommandBuffer* getCommandBuffer( 84 GrRenderTarget*, GrSurfaceOrigin, const SkRect& bounds, 85 const GrGpuRTCommandBuffer::LoadAndStoreInfo&, 86 const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo&) override; 87 88 GrGpuTextureCommandBuffer* getCommandBuffer(GrTexture*, GrSurfaceOrigin) override; 89 shaderCompiler()90 SkSL::Compiler* shaderCompiler() const { return fCompiler.get(); } 91 92 void submit(GrGpuCommandBuffer* buffer) override; 93 insertFence()94 GrFence SK_WARN_UNUSED_RESULT insertFence() override { return 0; } waitFence(GrFence,uint64_t)95 bool waitFence(GrFence, uint64_t) override { return true; } deleteFence(GrFence)96 void deleteFence(GrFence) const override {} 97 makeSemaphore(bool isOwned)98 sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT makeSemaphore(bool isOwned) override { 99 return nullptr; 100 } wrapBackendSemaphore(const GrBackendSemaphore & semaphore,GrResourceProvider::SemaphoreWrapType wrapType,GrWrapOwnership ownership)101 sk_sp<GrSemaphore> wrapBackendSemaphore(const GrBackendSemaphore& semaphore, 102 GrResourceProvider::SemaphoreWrapType wrapType, 103 GrWrapOwnership ownership) override { return nullptr; } insertSemaphore(sk_sp<GrSemaphore> semaphore)104 void insertSemaphore(sk_sp<GrSemaphore> semaphore) override {} waitSemaphore(sk_sp<GrSemaphore> semaphore)105 void waitSemaphore(sk_sp<GrSemaphore> semaphore) override {} 106 // We currently call finish procs immediately in onFinishFlush(). checkFinishProcs()107 void checkFinishProcs() override {} prepareTextureForCrossContextUsage(GrTexture *)108 sk_sp<GrSemaphore> prepareTextureForCrossContextUsage(GrTexture*) override { return nullptr; } 109 110 // When the Metal backend actually uses indirect command buffers, this function will actually do 111 // what it says. For now, every command is encoded directly into the primary command buffer, so 112 // this function is pretty useless, except for indicating that a render target has been drawn 113 // to. submitIndirectCommandBuffer(GrSurface * surface,GrSurfaceOrigin origin,const SkIRect * bounds)114 void submitIndirectCommandBuffer(GrSurface* surface, GrSurfaceOrigin origin, 115 const SkIRect* bounds) { 116 this->didWriteToSurface(surface, origin, bounds); 117 } 118 resolveRenderTargetNoFlush(GrRenderTarget * target)119 void resolveRenderTargetNoFlush(GrRenderTarget* target) { 120 this->internalResolveRenderTarget(target, false); 121 } 122 123 private: 124 GrMtlGpu(GrContext* context, const GrContextOptions& options, 125 id<MTLDevice> device, id<MTLCommandQueue> queue, MTLFeatureSet featureSet); 126 127 void destroyResources(); 128 onResetContext(uint32_t resetBits)129 void onResetContext(uint32_t resetBits) override {} 130 querySampleLocations(GrRenderTarget *,SkTArray<SkPoint> *)131 void querySampleLocations(GrRenderTarget*, SkTArray<SkPoint>*) override { 132 SkASSERT(!this->caps()->sampleLocationsSupport()); 133 SK_ABORT("Sample locations not yet implemented for Metal."); 134 } 135 xferBarrier(GrRenderTarget *,GrXferBarrierType)136 void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {} 137 138 sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc& desc, 139 const GrBackendFormat& format, 140 GrRenderable, 141 int renderTargetSampleCnt, 142 SkBudgeted budgeted, 143 GrProtected, 144 const GrMipLevel texels[], 145 int mipLevelCount) override; onCreateCompressedTexture(int width,int height,const GrBackendFormat &,SkImage::CompressionType,SkBudgeted,const void * data)146 sk_sp<GrTexture> onCreateCompressedTexture(int width, int height, const GrBackendFormat&, 147 SkImage::CompressionType, SkBudgeted, 148 const void* data) override { 149 return nullptr; 150 } 151 152 sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrColorType, 153 GrWrapOwnership, GrWrapCacheable, GrIOType) override; 154 155 sk_sp<GrTexture> onWrapRenderableBackendTexture(const GrBackendTexture&, int sampleCnt, 156 GrColorType, GrWrapOwnership, 157 GrWrapCacheable) override; 158 159 sk_sp<GrRenderTarget> onWrapBackendRenderTarget(const GrBackendRenderTarget&, 160 GrColorType) override; 161 162 sk_sp<GrRenderTarget> onWrapBackendTextureAsRenderTarget(const GrBackendTexture&, 163 int sampleCnt, 164 GrColorType) override; 165 166 sk_sp<GrGpuBuffer> onCreateBuffer(size_t, GrGpuBufferType, GrAccessPattern, 167 const void*) override; 168 169 bool onReadPixels(GrSurface* surface, int left, int top, int width, int height, 170 GrColorType surfaceColorType, GrColorType bufferColorType, void* buffer, 171 size_t rowBytes) override; 172 173 bool onWritePixels(GrSurface*, int left, int top, int width, int height, 174 GrColorType surfaceColorType, GrColorType bufferColorType, 175 const GrMipLevel[], int mipLevelCount) override; 176 onTransferPixelsTo(GrTexture *,int left,int top,int width,int height,GrColorType textureColorType,GrColorType bufferColorType,GrGpuBuffer *,size_t offset,size_t rowBytes)177 bool onTransferPixelsTo(GrTexture*, int left, int top, int width, int height, 178 GrColorType textureColorType, GrColorType bufferColorType, GrGpuBuffer*, 179 size_t offset, size_t rowBytes) override { 180 // TODO: not sure this is worth the work since nobody uses it 181 return false; 182 } onTransferPixelsFrom(GrSurface *,int left,int top,int width,int height,GrColorType surfaceColorType,GrColorType bufferColorType,GrGpuBuffer *,size_t offset)183 bool onTransferPixelsFrom(GrSurface*, int left, int top, int width, int height, 184 GrColorType surfaceColorType, GrColorType bufferColorType, 185 GrGpuBuffer*, size_t offset) override { 186 // TODO: Will need to implement this to support async read backs. 187 return false; 188 } 189 190 bool onRegenerateMipMapLevels(GrTexture*) override; 191 onResolveRenderTarget(GrRenderTarget * target)192 void onResolveRenderTarget(GrRenderTarget* target) override { 193 // This resolve is called when we are preparing an msaa surface for external I/O. It is 194 // called after flushing, so we need to make sure we submit the command buffer after doing 195 // the resolve so that the resolve actually happens. 196 this->internalResolveRenderTarget(target, true); 197 } 198 199 void internalResolveRenderTarget(GrRenderTarget* target, bool requiresSubmit); 200 void resolveTexture(id<MTLTexture> colorTexture, id<MTLTexture> resolveTexture); 201 onFinishFlush(GrSurfaceProxy * [],int n,SkSurface::BackendSurfaceAccess access,const GrFlushInfo & info,const GrPrepareForExternalIORequests &)202 void onFinishFlush(GrSurfaceProxy*[], int n, SkSurface::BackendSurfaceAccess access, 203 const GrFlushInfo& info, const GrPrepareForExternalIORequests&) override { 204 if (info.fFlags & kSyncCpu_GrFlushFlag) { 205 this->submitCommandBuffer(kForce_SyncQueue); 206 if (info.fFinishedProc) { 207 info.fFinishedProc(info.fFinishedContext); 208 } 209 } else { 210 this->submitCommandBuffer(kSkip_SyncQueue); 211 // TODO: support finishedProc to actually be called when the GPU is done with the work 212 // and not immediately. 213 if (info.fFinishedProc) { 214 info.fFinishedProc(info.fFinishedContext); 215 } 216 } 217 } 218 219 // Function that uploads data onto textures with private storage mode (GPU access only). 220 bool uploadToTexture(GrMtlTexture* tex, int left, int top, int width, int height, 221 GrColorType dataColorType, const GrMipLevel texels[], int mipLevels); 222 // Function that fills texture levels with transparent black based on levelMask. 223 bool clearTexture(GrMtlTexture*, GrColorType, uint32_t levelMask); 224 225 GrStencilAttachment* createStencilAttachmentForRenderTarget( 226 const GrRenderTarget*, int width, int height, int numStencilSamples) override; 227 228 bool createTestingOnlyMtlTextureInfo(MTLPixelFormat, 229 int w, int h, bool texturable, 230 bool renderable, GrMipMapped mipMapped, 231 const void* srcData, size_t srcRowBytes, 232 const SkColor4f* color, GrMtlTextureInfo* info); 233 234 sk_sp<GrMtlCaps> fMtlCaps; 235 236 id<MTLDevice> fDevice; 237 id<MTLCommandQueue> fQueue; 238 239 GrMtlCommandBuffer* fCmdBuffer; 240 241 std::unique_ptr<SkSL::Compiler> fCompiler; 242 243 GrMtlResourceProvider fResourceProvider; 244 245 bool fDisconnected; 246 247 typedef GrGpu INHERITED; 248 }; 249 250 #endif 251 252