• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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