* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/ganesh/vk/GrVkCommandPool.h"
#include "include/private/base/SkAssert.h"
#include "src/core/SkTraceEvent.h"
#include "src/gpu/ganesh/vk/GrVkCaps.h"
#include "src/gpu/ganesh/vk/GrVkCommandBuffer.h"
#include "src/gpu/ganesh/vk/GrVkGpu.h"
#include "src/gpu/ganesh/vk/GrVkUtil.h"
#include <utility>
GrVkCommandPool* GrVkCommandPool::Create(GrVkGpu* gpu) {
VkCommandPoolCreateFlags cmdPoolCreateFlags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
if (gpu->protectedContext()) {
cmdPoolCreateFlags |= VK_COMMAND_POOL_CREATE_PROTECTED_BIT;
}
const VkCommandPoolCreateInfo cmdPoolInfo = {
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
nullptr,
cmdPoolCreateFlags,
gpu->queueIndex(),
};
VkResult result;
VkCommandPool pool;
GR_VK_CALL_RESULT(gpu, result, CreateCommandPool(gpu->device(), &cmdPoolInfo, nullptr, &pool));
if (result != VK_SUCCESS) {
return nullptr;
}
GrVkPrimaryCommandBuffer* primaryCmdBuffer = GrVkPrimaryCommandBuffer::Create(gpu, pool);
if (!primaryCmdBuffer) {
GR_VK_CALL(gpu->vkInterface(), DestroyCommandPool(gpu->device(), pool, nullptr));
return nullptr;
}
return new GrVkCommandPool(gpu, pool, primaryCmdBuffer);
}
GrVkCommandPool::GrVkCommandPool(GrVkGpu* gpu, VkCommandPool commandPool,
GrVkPrimaryCommandBuffer* primaryCmdBuffer)
: GrVkManagedResource(gpu)
, fCommandPool(commandPool)
, fPrimaryCommandBuffer(primaryCmdBuffer)
, fMaxCachedSecondaryCommandBuffers(
gpu->vkCaps().maxPerPoolCachedSecondaryCommandBuffers()) {
}
std::unique_ptr<GrVkSecondaryCommandBuffer> GrVkCommandPool::findOrCreateSecondaryCommandBuffer(
GrVkGpu* gpu) {
std::unique_ptr<GrVkSecondaryCommandBuffer> result;
if (!fAvailableSecondaryBuffers.empty()) {
result = std::move(fAvailableSecondaryBuffers.back());
fAvailableSecondaryBuffers.pop_back();
} else{
result.reset(GrVkSecondaryCommandBuffer::Create(gpu, this));
}
return result;
}
void GrVkCommandPool::recycleSecondaryCommandBuffer(GrVkSecondaryCommandBuffer* buffer) {
std::unique_ptr<GrVkSecondaryCommandBuffer> scb(buffer);
if (fAvailableSecondaryBuffers.size() < fMaxCachedSecondaryCommandBuffers) {
fAvailableSecondaryBuffers.push_back(std::move(scb));
} else {
VkCommandBuffer vkBuffer = buffer->vkCommandBuffer();
GR_VK_CALL(fGpu->vkInterface(),
FreeCommandBuffers(fGpu->device(), fCommandPool, 1, &vkBuffer));
}
}
void GrVkCommandPool::close() {
fOpen = false;
}
void GrVkCommandPool::reset(GrVkGpu* gpu) {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
SkASSERT(!fOpen);
SkDEBUGCODE(VkResult result = )GR_VK_CALL(gpu->vkInterface(),
ResetCommandPool(gpu->device(), fCommandPool, 0));
SkASSERT(result == VK_SUCCESS || result == VK_ERROR_DEVICE_LOST);
this->releaseResources();
fOpen = true;
}
void GrVkCommandPool::releaseResources() {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
SkASSERT(!fOpen);
fPrimaryCommandBuffer->releaseResources();
fPrimaryCommandBuffer->recycleSecondaryCommandBuffers(this);
}
void GrVkCommandPool::freeGPUData() const {
GrVkCommandPool* nonConstThis = const_cast<GrVkCommandPool*>(this);
nonConstThis->close();
nonConstThis->releaseResources();
fPrimaryCommandBuffer->freeGPUData(fGpu, fCommandPool);
for (const auto& buffer : fAvailableSecondaryBuffers) {
buffer->freeGPUData(fGpu, fCommandPool);
}
if (fCommandPool != VK_NULL_HANDLE) {
GR_VK_CALL(fGpu->vkInterface(),
DestroyCommandPool(fGpu->device(), fCommandPool, nullptr));
}
}