aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools
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
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')
-rw-r--r--tools/gpu/GrContextFactory.cpp18
-rw-r--r--tools/gpu/TestContext.cpp6
-rw-r--r--tools/gpu/TestContext.h8
-rw-r--r--tools/gpu/gl/GLTestContext.h2
-rw-r--r--tools/gpu/mock/MockTestContext.cpp1
-rw-r--r--tools/gpu/mtl/MtlTestContext.h22
-rw-r--r--tools/gpu/mtl/MtlTestContext.mm165
-rw-r--r--tools/gpu/vk/VkTestContext.h2
8 files changed, 217 insertions, 7 deletions
diff --git a/tools/gpu/GrContextFactory.cpp b/tools/gpu/GrContextFactory.cpp
index d614b0643e..0686b79902 100644
--- a/tools/gpu/GrContextFactory.cpp
+++ b/tools/gpu/GrContextFactory.cpp
@@ -20,6 +20,9 @@
#ifdef SK_VULKAN
#include "vk/VkTestContext.h"
#endif
+#ifdef SK_METAL
+#include "mtl/MtlTestContext.h"
+#endif
#include "gl/null/NullGLTestContext.h"
#include "gl/GrGLGpu.h"
#include "mock/MockTestContext.h"
@@ -221,6 +224,16 @@ ContextInfo GrContextFactory::getContextInfoInternal(ContextType type, ContextOv
break;
}
#endif
+#ifdef SK_METAL
+ case kMetal_GrBackend: {
+ SkASSERT(!masterContext);
+ testCtx.reset(CreatePlatformMtlTestContext(nullptr));
+ if (!testCtx) {
+ return ContextInfo();
+ }
+ break;
+ }
+#endif
case kMock_GrBackend: {
TestContext* sharedContext = masterContext ? masterContext->fTestContext : nullptr;
SkASSERT(kMock_ContextType == type);
@@ -252,7 +265,10 @@ ContextInfo GrContextFactory::getContextInfoInternal(ContextType type, ContextOv
if (ContextOverrides::kAvoidStencilBuffers & overrides) {
grOptions.fAvoidStencilBuffers = true;
}
- sk_sp<GrContext> grCtx(GrContext::Create(backend, backendContext, grOptions));
+ sk_sp<GrContext> grCtx = testCtx->makeGrContext(grOptions);
+ if (!grCtx.get() && kMetal_GrBackend != backend) {
+ grCtx.reset(GrContext::Create(backend, backendContext, grOptions));
+ }
if (!grCtx.get()) {
return ContextInfo();
}
diff --git a/tools/gpu/TestContext.cpp b/tools/gpu/TestContext.cpp
index 90aba43880..c80c4ea4df 100644
--- a/tools/gpu/TestContext.cpp
+++ b/tools/gpu/TestContext.cpp
@@ -10,6 +10,8 @@
#include "GpuTimer.h"
+#include "GrContext.h"
+
namespace sk_gpu_test {
TestContext::TestContext()
: fFenceSync(nullptr)
@@ -29,6 +31,10 @@ TestContext::~TestContext() {
SkASSERT(!fGpuTimer);
}
+sk_sp<GrContext> TestContext::makeGrContext(const GrContextOptions&) {
+ return nullptr;
+}
+
void TestContext::makeCurrent() const { this->onPlatformMakeCurrent(); }
void TestContext::swapBuffers() { this->onPlatformSwapBuffers(); }
diff --git a/tools/gpu/TestContext.h b/tools/gpu/TestContext.h
index ecb61e3b2a..84794f3c34 100644
--- a/tools/gpu/TestContext.h
+++ b/tools/gpu/TestContext.h
@@ -11,8 +11,12 @@
#include "FenceSync.h"
#include "GrTypes.h"
+#include "SkRefCnt.h"
#include "../private/SkTemplates.h"
+class GrContext;
+struct GrContextOptions;
+
namespace sk_gpu_test {
class GpuTimer;
@@ -25,8 +29,6 @@ class TestContext : public SkNoncopyable {
public:
virtual ~TestContext();
- virtual bool isValid() const = 0;
-
bool fenceSyncSupport() const { return fFenceSync != nullptr; }
FenceSync* fenceSync() { SkASSERT(fFenceSync); return fFenceSync.get(); }
@@ -46,6 +48,8 @@ public:
virtual GrBackend backend() = 0;
virtual GrBackendContext backendContext() = 0;
+ virtual sk_sp<GrContext> makeGrContext(const GrContextOptions&);
+
/** Swaps front and back buffer (if the context has such buffers) */
void swapBuffers();
diff --git a/tools/gpu/gl/GLTestContext.h b/tools/gpu/gl/GLTestContext.h
index 9bd10395f7..f5afa31a7f 100644
--- a/tools/gpu/gl/GLTestContext.h
+++ b/tools/gpu/gl/GLTestContext.h
@@ -25,7 +25,7 @@ public:
return reinterpret_cast<GrBackendContext>(fGL.get());
}
- bool isValid() const override { return SkToBool(this->gl()); }
+ bool isValid() const { return SkToBool(this->gl()); }
const GrGLInterface *gl() const { return fGL.get(); }
diff --git a/tools/gpu/mock/MockTestContext.cpp b/tools/gpu/mock/MockTestContext.cpp
index c47fff5de3..56cd68cb59 100644
--- a/tools/gpu/mock/MockTestContext.cpp
+++ b/tools/gpu/mock/MockTestContext.cpp
@@ -21,7 +21,6 @@ public:
virtual GrBackendContext backendContext() override {
return reinterpret_cast<GrBackendContext>(nullptr);
}
- bool isValid() const override { return true; }
void testAbandon() override {}
void submit() override {}
void finish() override {}
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
diff --git a/tools/gpu/vk/VkTestContext.h b/tools/gpu/vk/VkTestContext.h
index 85acb0e716..5090f556b4 100644
--- a/tools/gpu/vk/VkTestContext.h
+++ b/tools/gpu/vk/VkTestContext.h
@@ -26,8 +26,6 @@ public:
return fVk;
}
- bool isValid() const override { return NULL != this->vk(); }
-
const GrVkInterface* vk() const { return fVk->fInterface.get(); }
protected: