aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/gpu/mtl
diff options
context:
space:
mode:
authorGravatar Greg Daniel <egdaniel@google.com>2017-07-13 15:07:54 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-07-13 21:29:33 +0000
commitb76a72a659f53b8bf449c5ca2685045d08a21e43 (patch)
treecc2e1b3c997817f514438e79c248d3b890e65ef7 /tools/gpu/mtl
parentee3e0bacc8bedd1e3ebfb52fbc8b1cc3ccdad358 (diff)
Add support for creating a GrContext backed by Metal.
Also adds the support code to allow our TestContext to create a Metal backend. Bug: skia: Change-Id: Ia850687019d79b897bb16e2c151f4f8526721ad9 Reviewed-on: https://skia-review.googlesource.com/22644 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Greg Daniel <egdaniel@google.com>
Diffstat (limited to 'tools/gpu/mtl')
-rw-r--r--tools/gpu/mtl/MtlTestContext.h22
-rw-r--r--tools/gpu/mtl/MtlTestContext.mm165
2 files changed, 187 insertions, 0 deletions
diff --git a/tools/gpu/mtl/MtlTestContext.h b/tools/gpu/mtl/MtlTestContext.h
new file mode 100644
index 0000000000..f703238c41
--- /dev/null
+++ b/tools/gpu/mtl/MtlTestContext.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef MtlTestContext_h
+#define MtlTestContext_h
+
+#include "TestContext.h"
+
+#ifdef SK_METAL
+
+namespace sk_gpu_test {
+TestContext* CreatePlatformMtlTestContext(TestContext*);
+} // namespace sk_gpu_test
+
+#endif
+
+
+#endif /* MtlTestContext_h */
diff --git a/tools/gpu/mtl/MtlTestContext.mm b/tools/gpu/mtl/MtlTestContext.mm
new file mode 100644
index 0000000000..4014e2ba70
--- /dev/null
+++ b/tools/gpu/mtl/MtlTestContext.mm
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "MtlTestContext.h"
+
+#include "GrContext.h"
+#include "GrContextOptions.h"
+
+#import <Metal/Metal.h>
+
+#ifdef SK_METAL
+
+namespace {
+/**
+ * Implements sk_gpu_test::FenceSync for Metal.
+ */
+
+// TODO
+#if 0
+class MtlFenceSync : public sk_gpu_test::FenceSync {
+public:
+ MtlFenceSync(sk_sp<const GrVkInterface> vk, VkDevice device, VkQueue queue,
+ uint32_t queueFamilyIndex)
+ : fVk(std::move(vk))
+ , fDevice(device)
+ , fQueue(queue) {
+ SkDEBUGCODE(fUnfinishedSyncs = 0;)
+ VkCommandPoolCreateInfo createInfo;
+ createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+ createInfo.pNext = nullptr;
+ createInfo.flags = 0;
+ createInfo.queueFamilyIndex = queueFamilyIndex;
+ GR_VK_CALL_ERRCHECK(fVk, CreateCommandPool(fDevice, &createInfo, nullptr, &fCommandPool));
+
+ VkCommandBufferAllocateInfo allocateInfo;
+ allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ allocateInfo.pNext = nullptr;
+ allocateInfo.commandBufferCount = 1;
+ allocateInfo.commandPool = fCommandPool;
+ allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ GR_VK_CALL_ERRCHECK(fVk, AllocateCommandBuffers(fDevice, &allocateInfo, &fCommandBuffer));
+
+ VkCommandBufferBeginInfo beginInfo;
+ beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ beginInfo.pNext = nullptr;
+ beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
+ beginInfo.pInheritanceInfo = nullptr;
+ GR_VK_CALL_ERRCHECK(fVk, BeginCommandBuffer(fCommandBuffer, &beginInfo));
+ GR_VK_CALL_ERRCHECK(fVk, EndCommandBuffer(fCommandBuffer));
+ }
+
+ ~VkFenceSync() override {
+ SkASSERT(!fUnfinishedSyncs);
+ // If the above assertion is true then the command buffer should not be in flight.
+ GR_VK_CALL(fVk, FreeCommandBuffers(fDevice, fCommandPool, 1, &fCommandBuffer));
+ GR_VK_CALL(fVk, DestroyCommandPool(fDevice, fCommandPool, nullptr));
+ }
+
+ sk_gpu_test::PlatformFence SK_WARN_UNUSED_RESULT insertFence() const override {
+ VkFence fence;
+ VkFenceCreateInfo info;
+ info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+ info.pNext = nullptr;
+ info.flags = 0;
+ GR_VK_CALL_ERRCHECK(fVk, CreateFence(fDevice, &info, nullptr, &fence));
+ VkSubmitInfo submitInfo;
+ submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submitInfo.pNext = nullptr;
+ submitInfo.waitSemaphoreCount = 0;
+ submitInfo.pWaitSemaphores = nullptr;
+ submitInfo.pWaitDstStageMask = nullptr;
+ submitInfo.commandBufferCount = 1;
+ submitInfo.pCommandBuffers = &fCommandBuffer;
+ submitInfo.signalSemaphoreCount = 0;
+ submitInfo.pSignalSemaphores = nullptr;
+ GR_VK_CALL_ERRCHECK(fVk, QueueSubmit(fQueue, 1, &submitInfo, fence));
+ SkDEBUGCODE(++fUnfinishedSyncs;)
+ return (sk_gpu_test::PlatformFence)fence;
+ }
+
+ bool waitFence(sk_gpu_test::PlatformFence opaqueFence) const override {
+ VkFence fence = (VkFence)opaqueFence;
+ static constexpr uint64_t kForever = ~((uint64_t)0);
+ auto result = GR_VK_CALL(fVk, WaitForFences(fDevice, 1, &fence, true, kForever));
+ return result != VK_TIMEOUT;
+ }
+
+ void deleteFence(sk_gpu_test::PlatformFence opaqueFence) const override {
+ VkFence fence = (VkFence)opaqueFence;
+ GR_VK_CALL(fVk, DestroyFence(fDevice, fence, nullptr));
+ SkDEBUGCODE(--fUnfinishedSyncs;)
+ }
+
+private:
+ sk_sp<const GrVkInterface> fVk;
+ VkDevice fDevice;
+ VkQueue fQueue;
+ VkCommandPool fCommandPool;
+ VkCommandBuffer fCommandBuffer;
+ SkDEBUGCODE(mutable int fUnfinishedSyncs;)
+ typedef sk_gpu_test::FenceSync INHERITED;
+};
+
+GR_STATIC_ASSERT(sizeof(VkFence) <= sizeof(sk_gpu_test::PlatformFence));
+#endif
+
+class MtlTestContext : public sk_gpu_test::TestContext {
+public:
+ static MtlTestContext* Create(TestContext* sharedContext) {
+ SkASSERT(!sharedContext);
+ id<MTLDevice> device = MTLCreateSystemDefaultDevice();
+ id<MTLCommandQueue> queue = [device newCommandQueue];
+
+ return new MtlTestContext(device, queue);
+ }
+
+ ~MtlTestContext() override { this->teardown(); }
+
+ GrBackend backend() override { return kMetal_GrBackend; }
+
+ GrBackendContext backendContext() override { return 0; }
+
+ void testAbandon() override {}
+
+ // There is really nothing to here since we don't own any unqueued command buffers here.
+ void submit() override {}
+
+ void finish() override {}
+
+ sk_sp<GrContext> makeGrContext(const GrContextOptions& options) override {
+ return GrContext::MakeMetal((__bridge_retained void*)fDevice,
+ (__bridge_retained void*)fQueue,
+ options);
+ }
+
+private:
+ MtlTestContext(id<MTLDevice> device, id<MTLCommandQueue> queue)
+ : fDevice(device), fQueue(queue) {
+ fFenceSync.reset(nullptr);
+ }
+
+ void onPlatformMakeCurrent() const override {}
+ void onPlatformSwapBuffers() const override {}
+
+ id<MTLDevice> fDevice;
+ id<MTLCommandQueue> fQueue;
+
+ typedef sk_gpu_test::TestContext INHERITED;
+};
+
+} // anonymous namespace
+
+namespace sk_gpu_test {
+
+TestContext* CreatePlatformMtlTestContext(TestContext* sharedContext) {
+ return MtlTestContext::Create(sharedContext);
+}
+} // namespace sk_gpu_test
+
+
+#endif