1 /* 2 * Copyright 2016 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 "VkTestContext.h" 9 10 #ifdef SK_VULKAN 11 12 #include "vk/GrVkInterface.h" 13 #include "vk/GrVkUtil.h" 14 #include <vulkan/vulkan.h> 15 16 namespace { 17 /** 18 * Implements sk_gpu_test::FenceSync for Vulkan. It creates a single command 19 * buffer with USAGE_SIMULTANEOUS with no content . On every insertFence request 20 * it submits the command buffer with a new fence. 21 */ 22 class VkFenceSync : public sk_gpu_test::FenceSync { 23 public: 24 VkFenceSync(sk_sp<const GrVkInterface> vk, VkDevice device, VkQueue queue, 25 uint32_t queueFamilyIndex) 26 : fVk(std::move(vk)) 27 , fDevice(device) 28 , fQueue(queue) { 29 SkDEBUGCODE(fUnfinishedSyncs = 0;) 30 VkCommandPoolCreateInfo createInfo; 31 createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; 32 createInfo.pNext = nullptr; 33 createInfo.flags = 0; 34 createInfo.queueFamilyIndex = queueFamilyIndex; 35 GR_VK_CALL_ERRCHECK(fVk, CreateCommandPool(fDevice, &createInfo, nullptr, &fCommandPool)); 36 37 VkCommandBufferAllocateInfo allocateInfo; 38 allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; 39 allocateInfo.pNext = nullptr; 40 allocateInfo.commandBufferCount = 1; 41 allocateInfo.commandPool = fCommandPool; 42 allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; 43 GR_VK_CALL_ERRCHECK(fVk, AllocateCommandBuffers(fDevice, &allocateInfo, &fCommandBuffer)); 44 45 VkCommandBufferBeginInfo beginInfo; 46 beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 47 beginInfo.pNext = nullptr; 48 beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; 49 beginInfo.pInheritanceInfo = nullptr; 50 GR_VK_CALL_ERRCHECK(fVk, BeginCommandBuffer(fCommandBuffer, &beginInfo)); 51 GR_VK_CALL_ERRCHECK(fVk, EndCommandBuffer(fCommandBuffer)); 52 } 53 54 ~VkFenceSync() override { 55 SkASSERT(!fUnfinishedSyncs); 56 // If the above assertion is true then the command buffer should not be in flight. 57 GR_VK_CALL(fVk, FreeCommandBuffers(fDevice, fCommandPool, 1, &fCommandBuffer)); 58 GR_VK_CALL(fVk, DestroyCommandPool(fDevice, fCommandPool, nullptr)); 59 } 60 61 sk_gpu_test::PlatformFence SK_WARN_UNUSED_RESULT insertFence() const override { 62 VkFence fence; 63 VkFenceCreateInfo info; 64 info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; 65 info.pNext = nullptr; 66 info.flags = 0; 67 GR_VK_CALL_ERRCHECK(fVk, CreateFence(fDevice, &info, nullptr, &fence)); 68 VkSubmitInfo submitInfo; 69 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 70 submitInfo.pNext = nullptr; 71 submitInfo.waitSemaphoreCount = 0; 72 submitInfo.pWaitSemaphores = nullptr; 73 submitInfo.pWaitDstStageMask = nullptr; 74 submitInfo.commandBufferCount = 1; 75 submitInfo.pCommandBuffers = &fCommandBuffer; 76 submitInfo.signalSemaphoreCount = 0; 77 submitInfo.pSignalSemaphores = nullptr; 78 GR_VK_CALL_ERRCHECK(fVk, QueueSubmit(fQueue, 1, &submitInfo, fence)); 79 SkDEBUGCODE(++fUnfinishedSyncs;) 80 return (sk_gpu_test::PlatformFence)fence; 81 } 82 83 bool waitFence(sk_gpu_test::PlatformFence opaqueFence) const override { 84 VkFence fence = (VkFence)opaqueFence; 85 static constexpr uint64_t kForever = ~((uint64_t)0); 86 auto result = GR_VK_CALL(fVk, WaitForFences(fDevice, 1, &fence, true, kForever)); 87 return result != VK_TIMEOUT; 88 } 89 90 void deleteFence(sk_gpu_test::PlatformFence opaqueFence) const override { 91 VkFence fence = (VkFence)opaqueFence; 92 GR_VK_CALL(fVk, DestroyFence(fDevice, fence, nullptr)); 93 SkDEBUGCODE(--fUnfinishedSyncs;) 94 } 95 96 private: 97 sk_sp<const GrVkInterface> fVk; 98 VkDevice fDevice; 99 VkQueue fQueue; 100 VkCommandPool fCommandPool; 101 VkCommandBuffer fCommandBuffer; 102 SkDEBUGCODE(mutable int fUnfinishedSyncs;) 103 typedef sk_gpu_test::FenceSync INHERITED; 104 }; 105 106 GR_STATIC_ASSERT(sizeof(VkFence) <= sizeof(sk_gpu_test::PlatformFence)); 107 108 // TODO: Implement swap buffers and finish 109 class VkTestContextImpl : public sk_gpu_test::VkTestContext { 110 public: 111 static VkTestContext* Create() { 112 sk_sp<const GrVkBackendContext> backendContext(GrVkBackendContext::Create()); 113 if (!backendContext) { 114 return nullptr; 115 } 116 return new VkTestContextImpl(std::move(backendContext)); 117 } 118 119 ~VkTestContextImpl() override { this->teardown(); } 120 121 void testAbandon() override {} 122 123 // There is really nothing to here since we don't own any unqueued command buffers here. 124 void submit() override {} 125 126 void finish() override {} 127 128 protected: 129 void teardown() override { 130 INHERITED::teardown(); 131 fVk.reset(nullptr); 132 } 133 134 private: 135 VkTestContextImpl(sk_sp<const GrVkBackendContext> backendContext) 136 : VkTestContext(std::move(backendContext)) { 137 fFenceSync.reset(new VkFenceSync(fVk->fInterface, fVk->fDevice, fVk->fQueue, 138 fVk->fGraphicsQueueIndex)); 139 } 140 141 void onPlatformMakeCurrent() const override {} 142 void onPlatformSwapBuffers() const override {} 143 144 typedef sk_gpu_test::VkTestContext INHERITED; 145 }; 146 } // anonymous namespace 147 148 namespace sk_gpu_test { 149 VkTestContext* CreatePlatformVkTestContext() { return VkTestContextImpl::Create(); } 150 } // namespace sk_gpu_test 151 152 #endif 153