diff options
author | Greg Daniel <egdaniel@google.com> | 2017-07-13 15:07:54 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-07-13 21:29:33 +0000 |
commit | b76a72a659f53b8bf449c5ca2685045d08a21e43 (patch) | |
tree | cc2e1b3c997817f514438e79c248d3b890e65ef7 /tools/gpu/mtl | |
parent | ee3e0bacc8bedd1e3ebfb52fbc8b1cc3ccdad358 (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.h | 22 | ||||
-rw-r--r-- | tools/gpu/mtl/MtlTestContext.mm | 165 |
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 |