• 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#include "tools/gpu/mtl/MtlTestContext.h"
9
10#include "include/gpu/GrContext.h"
11#include "include/gpu/GrContextOptions.h"
12
13#include "src/gpu/mtl/GrMtlUtil.h"
14
15#ifdef SK_METAL
16
17#import <Metal/Metal.h>
18
19namespace {
20/**
21 * Implements sk_gpu_test::FenceSync for Metal.
22 *
23 * Fences as MTLSharedEvents are not supported across all Metal platforms, so we do
24 * the next best thing and submit an empty MTLCommandBuffer and track when it's complete.
25 */
26class MtlFenceSync : public sk_gpu_test::FenceSync {
27public:
28    MtlFenceSync(id<MTLCommandQueue> queue)
29            : fQueue(queue) {
30        SkDEBUGCODE(fUnfinishedSyncs = 0;)
31    }
32
33    ~MtlFenceSync() override {
34        SkASSERT(!fUnfinishedSyncs);
35    }
36
37    sk_gpu_test::PlatformFence SK_WARN_UNUSED_RESULT insertFence() const override {
38        id<MTLCommandBuffer> cmdBuffer = [fQueue commandBuffer];
39        cmdBuffer.label = @"Fence";
40        [cmdBuffer commit];
41
42        SkDEBUGCODE(++fUnfinishedSyncs;)
43
44        void* cfCmdBuffer = (__bridge_retained void*)cmdBuffer;
45        return (sk_gpu_test::PlatformFence)cfCmdBuffer;
46    }
47
48    bool waitFence(sk_gpu_test::PlatformFence opaqueFence) const override {
49        void* cfCmdBuffer = (void*) opaqueFence;
50        id<MTLCommandBuffer> cmdBuffer = (__bridge id<MTLCommandBuffer>) cfCmdBuffer;
51
52        [cmdBuffer waitUntilCompleted];
53
54        return (MTLCommandBufferStatusError != cmdBuffer.status);
55    }
56
57    void deleteFence(sk_gpu_test::PlatformFence opaqueFence) const override {
58        CFRelease((void*) opaqueFence);
59        SkDEBUGCODE(--fUnfinishedSyncs;)
60    }
61
62private:
63    id<MTLCommandQueue>         fQueue;
64    SkDEBUGCODE(mutable int     fUnfinishedSyncs;)
65    typedef sk_gpu_test::FenceSync INHERITED;
66};
67
68GR_STATIC_ASSERT(sizeof(uint64_t) <= sizeof(sk_gpu_test::PlatformFence));
69
70class MtlTestContextImpl : public sk_gpu_test::MtlTestContext {
71public:
72    static MtlTestContext* Create(MtlTestContext* sharedContext) {
73        id<MTLDevice> device;
74        id<MTLCommandQueue> queue;
75        if (sharedContext) {
76            MtlTestContextImpl* sharedContextImpl = (MtlTestContextImpl*) sharedContext;
77            device = sharedContextImpl->device();
78            queue = sharedContextImpl->queue();
79        } else {
80            device = MTLCreateSystemDefaultDevice();
81            queue = [device newCommandQueue];
82        }
83
84        return new MtlTestContextImpl(device, queue);
85    }
86
87    ~MtlTestContextImpl() override { this->teardown(); }
88
89    void testAbandon() override {}
90
91    // There is really nothing to do here since we don't own any unqueued command buffers here.
92    void submit() override {}
93
94    void finish() override {}
95
96    sk_sp<GrContext> makeGrContext(const GrContextOptions& options) override {
97        return GrContext::MakeMetal((__bridge void*)fDevice,
98                                    (__bridge void*)fQueue,
99                                    options);
100    }
101
102    id<MTLDevice> device() { return fDevice; }
103    id<MTLCommandQueue> queue() { return fQueue; }
104
105private:
106    MtlTestContextImpl(id<MTLDevice> device, id<MTLCommandQueue> queue)
107            : INHERITED(), fDevice(device), fQueue(queue) {
108        fFenceSync.reset(new MtlFenceSync(queue));
109    }
110
111    void onPlatformMakeCurrent() const override {}
112    std::function<void()> onPlatformGetAutoContextRestore() const override { return nullptr; }
113    void onPlatformSwapBuffers() const override {}
114
115    id<MTLDevice>        fDevice;
116    id<MTLCommandQueue>  fQueue;
117
118    typedef sk_gpu_test::MtlTestContext INHERITED;
119};
120
121}  // anonymous namespace
122
123namespace sk_gpu_test {
124
125MtlTestContext* CreatePlatformMtlTestContext(MtlTestContext* sharedContext) {
126    return MtlTestContextImpl::Create(sharedContext);
127}
128
129}  // namespace sk_gpu_test
130
131
132#endif
133