blob: 4fb51fa2491c7fb49fa1374e0cbb87b7d46f2b6c [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 <string>
#include "flutter/fml/closure.h"
#include "fml/status.h"
#include "fml/status_or.h"
#include "impeller/renderer/backend/vulkan/context_vk.h"
#include "impeller/renderer/backend/vulkan/fence_waiter_vk.h"
#include "impeller/renderer/backend/vulkan/gpu_tracer_vk.h"
#include "impeller/renderer/backend/vulkan/texture_vk.h"
#include "impeller/renderer/backend/vulkan/tracked_objects_vk.h"
namespace impeller {
CommandEncoderFactoryVK::CommandEncoderFactoryVK(
const std::weak_ptr<const ContextVK>& context)
: context_(context) {}
void CommandEncoderFactoryVK::SetLabel(const std::string& label) {
label_ = label;
}
std::shared_ptr<CommandEncoderVK> CommandEncoderFactoryVK::Create() {
auto context = context_.lock();
if (!context) {
return nullptr;
}
auto recycler = context->GetCommandPoolRecycler();
if (!recycler) {
return nullptr;
}
auto tls_pool = recycler->Get();
if (!tls_pool) {
return nullptr;
}
auto tracked_objects = std::make_shared<TrackedObjectsVK>(
context, tls_pool, context->GetGPUTracer()->CreateGPUProbe());
auto queue = context->GetGraphicsQueue();
if (!tracked_objects || !tracked_objects->IsValid() || !queue) {
return nullptr;
}
vk::CommandBufferBeginInfo begin_info;
begin_info.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
if (tracked_objects->GetCommandBuffer().begin(begin_info) !=
vk::Result::eSuccess) {
VALIDATION_LOG << "Could not begin command buffer.";
return nullptr;
}
if (label_.has_value()) {
context->SetDebugName(tracked_objects->GetCommandBuffer(), label_.value());
}
tracked_objects->GetGPUProbe().RecordCmdBufferStart(
tracked_objects->GetCommandBuffer());
return std::make_shared<CommandEncoderVK>(context->GetDeviceHolder(),
tracked_objects, queue,
context->GetFenceWaiter());
}
CommandEncoderVK::CommandEncoderVK(
std::weak_ptr<const DeviceHolderVK> device_holder,
std::shared_ptr<TrackedObjectsVK> tracked_objects,
const std::shared_ptr<QueueVK>& queue,
std::shared_ptr<FenceWaiterVK> fence_waiter)
: device_holder_(std::move(device_holder)),
tracked_objects_(std::move(tracked_objects)),
queue_(queue),
fence_waiter_(std::move(fence_waiter)) {}
CommandEncoderVK::~CommandEncoderVK() = default;
bool CommandEncoderVK::IsValid() const {
return is_valid_;
}
bool CommandEncoderVK::EndCommandBuffer() const {
InsertDebugMarker("QueueSubmit");
auto command_buffer = GetCommandBuffer();
tracked_objects_->GetGPUProbe().RecordCmdBufferEnd(command_buffer);
auto status = command_buffer.end();
if (status != vk::Result::eSuccess) {
VALIDATION_LOG << "Failed to end command buffer: " << vk::to_string(status);
return false;
}
return true;
}
vk::CommandBuffer CommandEncoderVK::GetCommandBuffer() const {
if (tracked_objects_) {
return tracked_objects_->GetCommandBuffer();
}
return {};
}
void CommandEncoderVK::Reset() {
tracked_objects_.reset();
queue_ = nullptr;
is_valid_ = false;
}
bool CommandEncoderVK::Track(std::shared_ptr<SharedObjectVK> object) {
if (!IsValid()) {
return false;
}
tracked_objects_->Track(std::move(object));
return true;
}
bool CommandEncoderVK::Track(std::shared_ptr<const DeviceBuffer> buffer) {
if (!IsValid()) {
return false;
}
tracked_objects_->Track(std::move(buffer));
return true;
}
bool CommandEncoderVK::IsTracking(
const std::shared_ptr<const DeviceBuffer>& buffer) const {
if (!IsValid()) {
return false;
}
return tracked_objects_->IsTracking(buffer);
}
bool CommandEncoderVK::Track(std::shared_ptr<const TextureSourceVK> texture) {
if (!IsValid()) {
return false;
}
tracked_objects_->Track(std::move(texture));
return true;
}
bool CommandEncoderVK::Track(const std::shared_ptr<const Texture>& texture) {
if (!IsValid()) {
return false;
}
if (!texture) {
return true;
}
return Track(TextureVK::Cast(*texture).GetTextureSource());
}
bool CommandEncoderVK::IsTracking(
const std::shared_ptr<const Texture>& texture) const {
if (!IsValid()) {
return false;
}
std::shared_ptr<const TextureSourceVK> source =
TextureVK::Cast(*texture).GetTextureSource();
return tracked_objects_->IsTracking(source);
}
fml::StatusOr<vk::DescriptorSet> CommandEncoderVK::AllocateDescriptorSets(
const vk::DescriptorSetLayout& layout,
const ContextVK& context) {
if (!IsValid()) {
return fml::Status(fml::StatusCode::kUnknown, "command encoder invalid");
}
return tracked_objects_->GetDescriptorPool().AllocateDescriptorSets(layout,
context);
}
void CommandEncoderVK::PushDebugGroup(std::string_view label) const {
if (!HasValidationLayers()) {
return;
}
vk::DebugUtilsLabelEXT label_info;
label_info.pLabelName = label.data();
if (auto command_buffer = GetCommandBuffer()) {
command_buffer.beginDebugUtilsLabelEXT(label_info);
}
}
void CommandEncoderVK::PopDebugGroup() const {
if (!HasValidationLayers()) {
return;
}
if (auto command_buffer = GetCommandBuffer()) {
command_buffer.endDebugUtilsLabelEXT();
}
}
void CommandEncoderVK::InsertDebugMarker(std::string_view label) const {
if (!HasValidationLayers()) {
return;
}
vk::DebugUtilsLabelEXT label_info;
label_info.pLabelName = label.data();
if (auto command_buffer = GetCommandBuffer()) {
command_buffer.insertDebugUtilsLabelEXT(label_info);
}
if (queue_) {
queue_->InsertDebugMarker(label);
}
}
} // namespace impeller