MtlTestContext.mm 3.8 KB

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