提交 0de82187 编写于 作者: C Craig Stout 提交者: craig stout

Transition render target images before submit.

Required by the spec; see '6.7.4. Queue Family Ownership Transfer'
of Vulkan 1.0.66.

Transitioning the image layout also fixes an image resolve failure
issue introduced by optimizations present in the intel mesa vulkan
driver v17.2.
上级 fb9782a5
......@@ -70,12 +70,6 @@ SkISize VulkanSurface::GetSize() const {
return SkISize::Make(sk_surface_->width(), sk_surface_->height());
}
GrBackendSemaphore VulkanSurface::GetAcquireSemaphore() const {
GrBackendSemaphore gr_semaphore;
gr_semaphore.initVulkan(acquire_semaphore_);
return gr_semaphore;
}
vulkan::VulkanHandle<VkSemaphore> VulkanSurface::SemaphoreFromEvent(
const zx::event& event) const {
VkResult result;
......@@ -136,6 +130,8 @@ bool VulkanSurface::CreateFences() {
return false;
}
command_buffer_fence_ = vulkan_provider_.CreateFence();
return true;
}
......@@ -375,6 +371,17 @@ void VulkanSurface::Reset() {
<< "Could not reset fences. The surface is no longer valid.";
}
VkFence fence = command_buffer_fence_;
if (command_buffer_) {
VK_CALL_LOG_ERROR(vulkan_provider_.vk().WaitForFences(
vulkan_provider_.vk_device(), 1, &fence, VK_TRUE, UINT64_MAX));
command_buffer_.reset();
}
VK_CALL_LOG_ERROR(vulkan_provider_.vk().ResetFences(
vulkan_provider_.vk_device(), 1, &fence));
// Need to make a new acquire semaphore every frame or else validation layers
// get confused about why no one is waiting on it in this VkInstance
acquire_semaphore_.Reset();
......
......@@ -6,6 +6,7 @@
#include <memory>
#include "flutter/flow/scene_update_context.h"
#include "flutter/vulkan/vulkan_command_buffer.h"
#include "flutter/vulkan/vulkan_handle.h"
#include "flutter/vulkan/vulkan_proc_table.h"
#include "flutter/vulkan/vulkan_provider.h"
......@@ -50,11 +51,23 @@ class VulkanSurface : public flow::SceneUpdateContext::SurfaceProducerSurface,
// |flow::SceneUpdateContext::SurfaceProducerSurface|
sk_sp<SkSurface> GetSkiaSurface() const override;
// This transfers ownership of the GrBackendSemaphore but not the underlying
// VkSemaphore (i.e. it is ok to let the returned GrBackendSemaphore go out of
// scope but it is not ok to call VkDestroySemaphore on the underlying
// VkSemaphore)
GrBackendSemaphore GetAcquireSemaphore() const;
const vulkan::VulkanHandle<VkImage>& GetVkImage() { return vk_image_; }
const vulkan::VulkanHandle<VkSemaphore>& GetAcquireVkSemaphore() {
return acquire_semaphore_;
}
vulkan::VulkanCommandBuffer* GetCommandBuffer(
const vulkan::VulkanHandle<VkCommandPool>& pool) {
if (!command_buffer_)
command_buffer_ = std::make_unique<vulkan::VulkanCommandBuffer>(
vulkan_provider_.vk(), vulkan_provider_.vk_device(), pool);
return command_buffer_.get();
}
const vulkan::VulkanHandle<VkFence>& GetCommandBufferFence() {
return command_buffer_fence_;
}
private:
vulkan::VulkanProvider& vulkan_provider_;
......@@ -62,10 +75,12 @@ class VulkanSurface : public flow::SceneUpdateContext::SurfaceProducerSurface,
scenic_lib::Session* session_;
vulkan::VulkanHandle<VkImage> vk_image_;
vulkan::VulkanHandle<VkDeviceMemory> vk_memory_;
vulkan::VulkanHandle<VkFence> command_buffer_fence_;
sk_sp<SkSurface> sk_surface_;
std::unique_ptr<scenic_lib::Image> session_image_;
zx::event acquire_event_;
vulkan::VulkanHandle<VkSemaphore> acquire_semaphore_;
std::unique_ptr<vulkan::VulkanCommandBuffer> command_buffer_;
zx::event release_event_;
fsl::MessageLoop::HandlerKey event_handler_key_ = 0;
std::function<void(void)> pending_on_writes_committed_;
......
......@@ -121,18 +121,16 @@ void VulkanSurfaceProducer::OnSurfacesPresented(
std::unique_ptr<flow::SceneUpdateContext::SurfaceProducerSurface>>
surfaces) {
TRACE_EVENT0("flutter", "VulkanSurfaceProducer::OnSurfacesPresented");
std::vector<GrBackendSemaphore> semaphores;
semaphores.reserve(surfaces.size());
for (auto& surface : surfaces) {
auto vk_surface = static_cast<VulkanSurface*>(surface.get());
semaphores.push_back(vk_surface->GetAcquireSemaphore());
}
// Do a single flush for all canvases derived from the context.
{
TRACE_EVENT0("flutter", "GrContext::flushAndSignalSemaphores");
context_->flushAndSignalSemaphores(semaphores.size(), semaphores.data());
context_->flush();
}
if (!TransitionSurfacesToExternal(surfaces))
FXL_LOG(ERROR) << "TransitionSurfacesToExternal failed";
// Submit surface
for (auto& surface : surfaces) {
SubmitSurface(std::move(surface));
......@@ -142,6 +140,57 @@ void VulkanSurfaceProducer::OnSurfacesPresented(
surface_pool_->AgeAndCollectOldBuffers();
}
bool VulkanSurfaceProducer::TransitionSurfacesToExternal(
const std::vector<
std::unique_ptr<flow::SceneUpdateContext::SurfaceProducerSurface>>&
surfaces) {
for (auto& surface : surfaces) {
auto vk_surface = static_cast<VulkanSurface*>(surface.get());
vulkan::VulkanCommandBuffer* command_buffer =
vk_surface->GetCommandBuffer(logical_device_->GetCommandPool());
if (!command_buffer->Begin())
return false;
GrVkImageInfo* imageInfo;
vk_surface->GetSkiaSurface()->getRenderTargetHandle(
reinterpret_cast<GrBackendObject*>(&imageInfo),
SkSurface::kFlushRead_BackendHandleAccess);
VkImageMemoryBarrier image_barrier = {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
.dstAccessMask = 0,
.oldLayout = imageInfo->fImageLayout,
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = 0,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL_KHR,
.image = vk_surface->GetVkImage(),
.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}};
if (!command_buffer->InsertPipelineBarrier(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
0, // dependencyFlags
0, nullptr, // memory barriers
0, nullptr, // buffer barriers
1, &image_barrier))
return false;
imageInfo->updateImageLayout(image_barrier.newLayout);
if (!command_buffer->End())
return false;
if (!logical_device_->QueueSubmit(
{}, {}, {vk_surface->GetAcquireVkSemaphore()},
{command_buffer->Handle()}, vk_surface->GetCommandBufferFence()))
return false;
}
return true;
}
std::unique_ptr<flow::SceneUpdateContext::SurfaceProducerSurface>
VulkanSurfaceProducer::ProduceSurface(const SkISize& size) {
FXL_DCHECK(valid_);
......
......@@ -50,6 +50,11 @@ class VulkanSurfaceProducer : public flow::SceneUpdateContext::SurfaceProducer,
return logical_device_->GetHandle();
}
bool TransitionSurfacesToExternal(
const std::vector<
std::unique_ptr<flow::SceneUpdateContext::SurfaceProducerSurface>>&
surfaces);
// Note: the order here is very important. The proctable must be destroyed
// last because it contains the function pointers for VkDestroyDevice and
// VkDestroyInstance. The backend context owns the VkDevice and the
......
// Copyright 2017 The Chromium 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 "flutter/vulkan/vulkan_provider.h"
namespace vulkan {
vulkan::VulkanHandle<VkFence> VulkanProvider::CreateFence() {
const VkFenceCreateInfo create_info = {
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
};
VkFence fence;
if (VK_CALL_LOG_ERROR(vk().CreateFence(vk_device(), &create_info, nullptr,
&fence)) != VK_SUCCESS)
return vulkan::VulkanHandle<VkFence>();
return {fence, [this](VkFence fence) {
vk().DestroyFence(vk_device(), fence, nullptr);
}};
}
} // namespace vulkan
......@@ -13,6 +13,22 @@ class VulkanProvider {
public:
virtual const vulkan::VulkanProcTable& vk() = 0;
virtual const vulkan::VulkanHandle<VkDevice>& vk_device() = 0;
vulkan::VulkanHandle<VkFence> CreateFence() {
const VkFenceCreateInfo create_info = {
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
};
VkFence fence;
if (VK_CALL_LOG_ERROR(vk().CreateFence(vk_device(), &create_info, nullptr,
&fence)) != VK_SUCCESS)
return vulkan::VulkanHandle<VkFence>();
return {fence, [this](VkFence fence) {
vk().DestroyFence(vk_device(), fence, nullptr);
}};
}
};
} // namespace vulkan
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册