1/* 2 * Copyright 2018 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 "src/gpu/vk/GrVkCommandPool.h" 9 10#include "src/core/SkTraceEvent.h" 11#include "src/gpu/GrDirectContextPriv.h" 12#include "src/gpu/vk/GrVkCommandBuffer.h" 13#include "src/gpu/vk/GrVkGpu.h" 14 15GrVkCommandPool* GrVkCommandPool::Create(GrVkGpu* gpu) { 16 VkCommandPoolCreateFlags cmdPoolCreateFlags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT; 17 if (gpu->protectedContext()) { 18 cmdPoolCreateFlags |= VK_COMMAND_POOL_CREATE_PROTECTED_BIT; 19 } 20 21 const VkCommandPoolCreateInfo cmdPoolInfo = { 22 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType 23 nullptr, // pNext 24 cmdPoolCreateFlags, // CmdPoolCreateFlags 25 gpu->queueIndex(), // queueFamilyIndex 26 }; 27 VkResult result; 28 VkCommandPool pool; 29 GR_VK_CALL_RESULT(gpu, result, CreateCommandPool(gpu->device(), &cmdPoolInfo, nullptr, &pool)); 30 if (result != VK_SUCCESS) { 31 return nullptr; 32 } 33 34 GrVkPrimaryCommandBuffer* primaryCmdBuffer = GrVkPrimaryCommandBuffer::Create(gpu, pool); 35 if (!primaryCmdBuffer) { 36 GR_VK_CALL(gpu->vkInterface(), DestroyCommandPool(gpu->device(), pool, nullptr)); 37 return nullptr; 38 } 39 40 return new GrVkCommandPool(gpu, pool, primaryCmdBuffer); 41} 42 43GrVkCommandPool::GrVkCommandPool(GrVkGpu* gpu, VkCommandPool commandPool, 44 GrVkPrimaryCommandBuffer* primaryCmdBuffer) 45 : GrVkManagedResource(gpu) 46 , fCommandPool(commandPool) 47 , fPrimaryCommandBuffer(primaryCmdBuffer) 48 , fMaxCachedSecondaryCommandBuffers( 49 gpu->vkCaps().maxPerPoolCachedSecondaryCommandBuffers()) { 50} 51 52std::unique_ptr<GrVkSecondaryCommandBuffer> GrVkCommandPool::findOrCreateSecondaryCommandBuffer( 53 GrVkGpu* gpu) { 54 std::unique_ptr<GrVkSecondaryCommandBuffer> result; 55 if (fAvailableSecondaryBuffers.count()) { 56 result = std::move(fAvailableSecondaryBuffers.back()); 57 fAvailableSecondaryBuffers.pop_back(); 58 } else{ 59 result.reset(GrVkSecondaryCommandBuffer::Create(gpu, this)); 60 } 61 return result; 62} 63 64void GrVkCommandPool::recycleSecondaryCommandBuffer(GrVkSecondaryCommandBuffer* buffer) { 65 std::unique_ptr<GrVkSecondaryCommandBuffer> scb(buffer); 66 if (fAvailableSecondaryBuffers.count() < fMaxCachedSecondaryCommandBuffers) { 67 fAvailableSecondaryBuffers.push_back(std::move(scb)); 68 } else { 69 VkCommandBuffer vkBuffer = buffer->vkCommandBuffer(); 70 GR_VK_CALL(fGpu->vkInterface(), 71 FreeCommandBuffers(fGpu->device(), fCommandPool, 1, &vkBuffer)); 72 } 73} 74 75void GrVkCommandPool::close() { 76 fOpen = false; 77} 78 79void GrVkCommandPool::reset(GrVkGpu* gpu) { 80 SkASSERT(!fOpen); 81 fOpen = true; 82 // We can't use the normal result macro calls here because we may call reset on a different 83 // thread and we can't be modifying the lost state on the GrVkGpu. We just call 84 // vkResetCommandPool and assume the "next" vulkan call will catch the lost device. 85 SkDEBUGCODE(VkResult result = )GR_VK_CALL(gpu->vkInterface(), 86 ResetCommandPool(gpu->device(), fCommandPool, 0)); 87 SkASSERT(result == VK_SUCCESS || result == VK_ERROR_DEVICE_LOST); 88} 89 90void GrVkCommandPool::releaseResources() { 91 TRACE_EVENT0("skia.gpu", TRACE_FUNC); 92 SkASSERT(!fOpen); 93 fPrimaryCommandBuffer->releaseResources(); 94 fPrimaryCommandBuffer->recycleSecondaryCommandBuffers(this); 95} 96 97void GrVkCommandPool::freeGPUData() const { 98 // TODO: having freeGPUData virtual on GrManagedResource be const seems like a bad restriction since 99 // we are changing the internal objects of these classes when it is called. We should go back a 100 // revisit how much of a headache it would be to make this function non-const 101 GrVkCommandPool* nonConstThis = const_cast<GrVkCommandPool*>(this); 102 nonConstThis->close(); 103 nonConstThis->releaseResources(); 104 fPrimaryCommandBuffer->freeGPUData(fGpu, fCommandPool); 105 for (const auto& buffer : fAvailableSecondaryBuffers) { 106 buffer->freeGPUData(fGpu, fCommandPool); 107 } 108 if (fCommandPool != VK_NULL_HANDLE) { 109 GR_VK_CALL(fGpu->vkInterface(), 110 DestroyCommandPool(fGpu->device(), fCommandPool, nullptr)); 111 } 112} 113