Commit a9affd1d authored by Peng Huang's avatar Peng Huang Committed by Commit Bot

vulkan: fix layout and queue family problems with ExternalVkImageBacking

1. For the first time GL access, the backing's queue family could be not
   VK_QUEUE_FAMILY_EXTERNAL. We need to transfer it to external for GL
   access.
2. SkiaOutputDeviceBufferQueue doesn't set backing's layout and queue
   family after Skia write access. Fix it by override
   PreGrContextSubmitz() to set the backing's layout and queue family.

Bug: 1101167
Change-Id: I2f2f527ffb6f4b56e0042c8762cdb93eea4b6942
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2286052Reviewed-by: default avatarVasiliy Telezhnikov <vasilyt@chromium.org>
Commit-Queue: Peng Huang <penghuang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#786453}
parent 540d207a
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "components/viz/service/display_embedder/output_presenter.h" #include "components/viz/service/display_embedder/output_presenter.h"
#include <utility>
#include "components/viz/service/display_embedder/skia_output_surface_dependency.h" #include "components/viz/service/display_embedder/skia_output_surface_dependency.h"
#include "gpu/command_buffer/service/shared_context_state.h" #include "gpu/command_buffer/service/shared_context_state.h"
#include "third_party/skia/include/gpu/GrBackendSemaphore.h" #include "third_party/skia/include/gpu/GrBackendSemaphore.h"
...@@ -99,6 +101,14 @@ void OutputPresenter::Image::EndWriteSkia() { ...@@ -99,6 +101,14 @@ void OutputPresenter::Image::EndWriteSkia() {
skia_representation_->SetCleared(); skia_representation_->SetCleared();
} }
void OutputPresenter::Image::PreGrContextSubmit() {
DCHECK(scoped_skia_write_access_);
if (scoped_skia_write_access_->end_state()) {
scoped_skia_write_access_->surface()->flush(
{}, scoped_skia_write_access_->end_state());
}
}
OutputPresenter::OverlayData::OverlayData( OutputPresenter::OverlayData::OverlayData(
std::unique_ptr<gpu::SharedImageRepresentationOverlay> representation, std::unique_ptr<gpu::SharedImageRepresentationOverlay> representation,
std::unique_ptr<gpu::SharedImageRepresentationOverlay::ScopedReadAccess> std::unique_ptr<gpu::SharedImageRepresentationOverlay::ScopedReadAccess>
......
...@@ -44,6 +44,7 @@ class VIZ_SERVICE_EXPORT OutputPresenter { ...@@ -44,6 +44,7 @@ class VIZ_SERVICE_EXPORT OutputPresenter {
SkSurface* sk_surface(); SkSurface* sk_surface();
std::vector<GrBackendSemaphore> TakeEndWriteSkiaSemaphores(); std::vector<GrBackendSemaphore> TakeEndWriteSkiaSemaphores();
void EndWriteSkia(); void EndWriteSkia();
void PreGrContextSubmit();
virtual void BeginPresent() = 0; virtual void BeginPresent() = 0;
virtual void EndPresent() = 0; virtual void EndPresent() = 0;
......
...@@ -120,6 +120,11 @@ void SkiaOutputDeviceBufferQueue::ScheduleOverlays( ...@@ -120,6 +120,11 @@ void SkiaOutputDeviceBufferQueue::ScheduleOverlays(
pending_overlays_ = presenter_->ScheduleOverlays(std::move(overlays)); pending_overlays_ = presenter_->ScheduleOverlays(std::move(overlays));
} }
void SkiaOutputDeviceBufferQueue::PreGrContextSubmit() {
DCHECK(current_image_);
current_image_->PreGrContextSubmit();
}
void SkiaOutputDeviceBufferQueue::SwapBuffers( void SkiaOutputDeviceBufferQueue::SwapBuffers(
BufferPresentedCallback feedback, BufferPresentedCallback feedback,
std::vector<ui::LatencyInfo> latency_info) { std::vector<ui::LatencyInfo> latency_info) {
......
...@@ -34,6 +34,7 @@ class VIZ_SERVICE_EXPORT SkiaOutputDeviceBufferQueue : public SkiaOutputDevice { ...@@ -34,6 +34,7 @@ class VIZ_SERVICE_EXPORT SkiaOutputDeviceBufferQueue : public SkiaOutputDevice {
delete; delete;
// SkiaOutputDevice overrides. // SkiaOutputDevice overrides.
void PreGrContextSubmit() override;
void SwapBuffers(BufferPresentedCallback feedback, void SwapBuffers(BufferPresentedCallback feedback,
std::vector<ui::LatencyInfo> latency_info) override; std::vector<ui::LatencyInfo> latency_info) override;
void PostSubBuffer(const gfx::Rect& rect, void PostSubBuffer(const gfx::Rect& rect,
......
...@@ -290,11 +290,7 @@ ExternalVkImageBacking::~ExternalVkImageBacking() { ...@@ -290,11 +290,7 @@ ExternalVkImageBacking::~ExternalVkImageBacking() {
bool result = backend_texture_.getVkImageInfo(&image_info); bool result = backend_texture_.getVkImageInfo(&image_info);
DCHECK(result); DCHECK(result);
auto* fence_helper = context_state() fence_helper()->EnqueueVulkanObjectCleanupForSubmittedWork(std::move(image_));
->vk_context_provider()
->GetDeviceQueue()
->GetFenceHelper();
fence_helper->EnqueueVulkanObjectCleanupForSubmittedWork(std::move(image_));
backend_texture_ = GrBackendTexture(); backend_texture_ = GrBackendTexture();
if (texture_) { if (texture_) {
...@@ -330,7 +326,7 @@ bool ExternalVkImageBacking::BeginAccess( ...@@ -330,7 +326,7 @@ bool ExternalVkImageBacking::BeginAccess(
if (readonly && !reads_in_progress_) { if (readonly && !reads_in_progress_) {
UpdateContent(kInVkImage); UpdateContent(kInVkImage);
if (texture_) if (texture_ || texture_passthrough_)
UpdateContent(kInGLTexture); UpdateContent(kInGLTexture);
} }
...@@ -340,11 +336,16 @@ bool ExternalVkImageBacking::BeginAccess( ...@@ -340,11 +336,16 @@ bool ExternalVkImageBacking::BeginAccess(
if (!is_gl) if (!is_gl)
return true; return true;
if (need_synchronization() && semaphore_handles->empty() && IsCleared()) { if (need_synchronization() && semaphore_handles->empty()) {
DLOG(ERROR) << "semaphore_handles is empty.";
// For the first time GL BeginAccess(), semaphore_handles could be empty, // For the first time GL BeginAccess(), semaphore_handles could be empty,
// since the Vulkan usage will not provide semaphore for EndAccess() call, // since the Vulkan usage will not provide semaphore for EndAccess() call,
// if ProduceGL*() is never called. // if ProduceGL*() is never called. In this case, image layout and queue
// family will not be ready for GL access as well.
auto* gr_context = context_state()->gr_context();
gr_context->setBackendTextureState(
backend_texture_,
GrBackendSurfaceMutableState(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_QUEUE_FAMILY_EXTERNAL));
VkSemaphore semaphore = VkSemaphore semaphore =
vulkan_implementation()->CreateExternalSemaphore(device()); vulkan_implementation()->CreateExternalSemaphore(device());
GrBackendSemaphore backend_semaphore; GrBackendSemaphore backend_semaphore;
...@@ -355,21 +356,16 @@ bool ExternalVkImageBacking::BeginAccess( ...@@ -355,21 +356,16 @@ bool ExternalVkImageBacking::BeginAccess(
}; };
gpu::AddVulkanCleanupTaskForSkiaFlush( gpu::AddVulkanCleanupTaskForSkiaFlush(
context_state()->vk_context_provider(), &flush_info); context_state()->vk_context_provider(), &flush_info);
auto* gr_context = context_state()->gr_context();
auto flush_result = gr_context->flush(flush_info); auto flush_result = gr_context->flush(flush_info);
DCHECK_EQ(flush_result, GrSemaphoresSubmitted::kYes); DCHECK_EQ(flush_result, GrSemaphoresSubmitted::kYes);
gr_context->submit(); gr_context->submit();
auto handle = auto handle =
vulkan_implementation()->GetSemaphoreHandle(device(), semaphore); vulkan_implementation()->GetSemaphoreHandle(device(), semaphore);
semaphore_handles->push_back(std::move(handle));
DCHECK(handle.is_valid()); DCHECK(handle.is_valid());
semaphore_handles->push_back(std::move(handle));
// We're done with the semaphore, enqueue deferred cleanup. // We're done with the semaphore, enqueue deferred cleanup.
context_state() fence_helper()->EnqueueSemaphoreCleanupForSubmittedWork(semaphore);
->vk_context_provider()
->GetDeviceQueue()
->GetFenceHelper()
->EnqueueSemaphoreCleanupForSubmittedWork(semaphore);
} }
if (readonly) { if (readonly) {
...@@ -722,13 +718,10 @@ bool ExternalVkImageBacking::WritePixelsWithCallback( ...@@ -722,13 +718,10 @@ bool ExternalVkImageBacking::WritePixelsWithCallback(
command_buffer->Submit(0, nullptr, 0, nullptr); command_buffer->Submit(0, nullptr, 0, nullptr);
EndAccessInternal(false /* readonly */, SemaphoreHandle()); EndAccessInternal(false /* readonly */, SemaphoreHandle());
auto* fence_helper = context_state_->vk_context_provider() fence_helper()->EnqueueVulkanObjectCleanupForSubmittedWork(
->GetDeviceQueue()
->GetFenceHelper();
fence_helper->EnqueueVulkanObjectCleanupForSubmittedWork(
std::move(command_buffer)); std::move(command_buffer));
fence_helper->EnqueueBufferCleanupForSubmittedWork(stage_buffer, fence_helper()->EnqueueBufferCleanupForSubmittedWork(stage_buffer,
stage_allocation); stage_allocation);
return true; return true;
} }
...@@ -752,15 +745,13 @@ bool ExternalVkImageBacking::WritePixelsWithCallback( ...@@ -752,15 +745,13 @@ bool ExternalVkImageBacking::WritePixelsWithCallback(
EndAccessInternal(false /* readonly */, EndAccessInternal(false /* readonly */,
std::move(end_access_semaphore_handle)); std::move(end_access_semaphore_handle));
auto* fence_helper = fence_helper()->EnqueueVulkanObjectCleanupForSubmittedWork(
context_state_->vk_context_provider()->GetDeviceQueue()->GetFenceHelper();
fence_helper->EnqueueVulkanObjectCleanupForSubmittedWork(
std::move(command_buffer)); std::move(command_buffer));
begin_access_semaphores.emplace_back(end_access_semaphore); begin_access_semaphores.emplace_back(end_access_semaphore);
fence_helper->EnqueueSemaphoresCleanupForSubmittedWork( fence_helper()->EnqueueSemaphoresCleanupForSubmittedWork(
begin_access_semaphores); begin_access_semaphores);
fence_helper->EnqueueBufferCleanupForSubmittedWork(stage_buffer, fence_helper()->EnqueueBufferCleanupForSubmittedWork(stage_buffer,
stage_allocation); stage_allocation);
return true; return true;
} }
......
...@@ -79,6 +79,12 @@ class ExternalVkImageBacking final : public ClearTrackingSharedImageBacking { ...@@ -79,6 +79,12 @@ class ExternalVkImageBacking final : public ClearTrackingSharedImageBacking {
VulkanImplementation* vulkan_implementation() const { VulkanImplementation* vulkan_implementation() const {
return context_state()->vk_context_provider()->GetVulkanImplementation(); return context_state()->vk_context_provider()->GetVulkanImplementation();
} }
VulkanFenceHelper* fence_helper() const {
return context_state()
->vk_context_provider()
->GetDeviceQueue()
->GetFenceHelper();
}
VkDevice device() const { VkDevice device() const {
return context_state() return context_state()
->vk_context_provider() ->vk_context_provider()
......
...@@ -92,6 +92,9 @@ bool ExternalVkImageGLRepresentationShared::BeginAccess(GLenum mode) { ...@@ -92,6 +92,9 @@ bool ExternalVkImageGLRepresentationShared::BeginAccess(GLenum mode) {
GrVkImageInfo info; GrVkImageInfo info;
auto result = backing_impl()->backend_texture().getVkImageInfo(&info); auto result = backing_impl()->backend_texture().getVkImageInfo(&info);
DCHECK(result); DCHECK(result);
DCHECK_EQ(info.fCurrentQueueFamily, VK_QUEUE_FAMILY_EXTERNAL);
DCHECK_NE(info.fImageLayout, VK_IMAGE_LAYOUT_UNDEFINED);
DCHECK_NE(info.fImageLayout, VK_IMAGE_LAYOUT_PREINITIALIZED);
GLenum src_layout = ToGLImageLayout(info.fImageLayout); GLenum src_layout = ToGLImageLayout(info.fImageLayout);
api()->glWaitSemaphoreEXTFn(gl_semaphore, 0, nullptr, 1, api()->glWaitSemaphoreEXTFn(gl_semaphore, 0, nullptr, 1,
&texture_service_id_, &src_layout); &texture_service_id_, &src_layout);
...@@ -160,6 +163,9 @@ void ExternalVkImageGLRepresentationShared::EndAccess() { ...@@ -160,6 +163,9 @@ void ExternalVkImageGLRepresentationShared::EndAccess() {
GrVkImageInfo info; GrVkImageInfo info;
auto result = backing_impl()->backend_texture().getVkImageInfo(&info); auto result = backing_impl()->backend_texture().getVkImageInfo(&info);
DCHECK(result); DCHECK(result);
DCHECK_EQ(info.fCurrentQueueFamily, VK_QUEUE_FAMILY_EXTERNAL);
DCHECK_NE(info.fImageLayout, VK_IMAGE_LAYOUT_UNDEFINED);
DCHECK_NE(info.fImageLayout, VK_IMAGE_LAYOUT_PREINITIALIZED);
GLenum dst_layout = ToGLImageLayout(info.fImageLayout); GLenum dst_layout = ToGLImageLayout(info.fImageLayout);
api()->glSignalSemaphoreEXTFn(gl_semaphore, 0, nullptr, 1, api()->glSignalSemaphoreEXTFn(gl_semaphore, 0, nullptr, 1,
&texture_service_id_, &dst_layout); &texture_service_id_, &dst_layout);
......
...@@ -81,10 +81,10 @@ sk_sp<SkSurface> ExternalVkImageSkiaRepresentation::BeginWriteAccess( ...@@ -81,10 +81,10 @@ sk_sp<SkSurface> ExternalVkImageSkiaRepresentation::BeginWriteAccess(
access_mode_ = kWrite; access_mode_ = kWrite;
// If Vulkan and GLSet share the same memory backing, we need set |end_state| // If Vulkan and GL (or Dawn) share the same memory backing, we need set
// VK_QUEUE_FAMILY_EXTERNAL, and then the caller will set the VkImage to // |end_state| VK_QUEUE_FAMILY_EXTERNAL, and then the caller will set the
// VK_QUEUE_FAMILY_EXTERNAL before calling EndAccess(). // VkImage to VK_QUEUE_FAMILY_EXTERNAL before calling EndAccess().
if (!backing_impl()->use_separate_gl_texture()) { if (backing_impl()->need_synchronization()) {
*end_state = std::make_unique<GrBackendSurfaceMutableState>( *end_state = std::make_unique<GrBackendSurfaceMutableState>(
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_QUEUE_FAMILY_EXTERNAL); VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_QUEUE_FAMILY_EXTERNAL);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment