blob: 6fbf12950f49b95d4ee99d6678e84befd2ccd1cd [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/renderer/backend/vulkan/command_encoder_vk.h"
#include "flutter/fml/closure.h"
#include "impeller/renderer/backend/vulkan/context_vk.h"
namespace impeller {
CommandEncoderVK::CommandEncoderVK(vk::Device device,
vk::Queue queue,
vk::CommandPool pool) {
vk::CommandBufferAllocateInfo alloc_info;
alloc_info.commandPool = pool;
alloc_info.commandBufferCount = 1u;
alloc_info.level = vk::CommandBufferLevel::ePrimary;
auto [result, buffers] = device.allocateCommandBuffersUnique(alloc_info);
if (result != vk::Result::eSuccess) {
VALIDATION_LOG << "Could not create command buffer.";
return;
}
vk::CommandBufferBeginInfo begin_info;
begin_info.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
if (buffers[0]->begin(begin_info) != vk::Result::eSuccess) {
VALIDATION_LOG << "Could not begin command buffer.";
return;
}
device_ = device;
queue_ = queue;
command_buffer_ = std::move(buffers[0]);
is_valid_ = true;
}
CommandEncoderVK::~CommandEncoderVK() = default;
bool CommandEncoderVK::IsValid() const {
return is_valid_;
}
bool CommandEncoderVK::Submit() {
if (!IsValid()) {
return false;
}
// Success or failure, you only get to submit once.
fml::ScopedCleanupClosure reset([&]() { Reset(); });
if (command_buffer_->end() != vk::Result::eSuccess) {
return false;
}
auto [fence_result, fence] = device_.createFenceUnique({});
if (fence_result != vk::Result::eSuccess) {
return false;
}
vk::SubmitInfo submit_info;
submit_info.setCommandBuffers(*command_buffer_);
if (queue_.submit(submit_info, *fence) != vk::Result::eSuccess) {
return false;
}
if (device_.waitForFences(
*fence, // fences
true, // wait all
std::numeric_limits<uint64_t>::max() // timeout (ns)
) != vk::Result::eSuccess) {
return false;
}
return true;
}
const vk::CommandBuffer& CommandEncoderVK::GetCommandBuffer() const {
return *command_buffer_;
}
void CommandEncoderVK::Reset() {
command_buffer_.reset();
tracked_objects_.clear();
tracked_buffers_.clear();
tracked_textures_.clear();
queue_ = nullptr;
device_ = nullptr;
is_valid_ = false;
}
bool CommandEncoderVK::Track(std::shared_ptr<SharedObjectVK> object) {
tracked_objects_.push_back(std::move(object));
return true;
}
bool CommandEncoderVK::Track(std::shared_ptr<const DeviceBuffer> buffer) {
tracked_buffers_.emplace_back(std::move(buffer));
return true;
}
bool CommandEncoderVK::Track(std::shared_ptr<const Texture> texture) {
tracked_textures_.emplace_back(std::move(texture));
return true;
}
void CommandEncoderVK::PushDebugGroup(const char* label) const {
if (!vk::HasValidationLayers() || !command_buffer_) {
return;
}
vk::DebugUtilsLabelEXT label_info;
label_info.pLabelName = label;
command_buffer_->beginDebugUtilsLabelEXT(label_info);
}
void CommandEncoderVK::PopDebugGroup() const {
if (!vk::HasValidationLayers() || !command_buffer_) {
return;
}
command_buffer_->endDebugUtilsLabelEXT();
}
} // namespace impeller