Commit 0c9696bf authored by Peng Huang's avatar Peng Huang Committed by Commit Bot

ExternalVkImageBacking: fix concurrent read problem

Concurrent read access from both GL and Vulkan is not allowed.
Get rid of the concurrent read problem by releasing the texture
from GL temporarily, when a Vulkan read is requested. And resume
GL read access, when the Vulkan read access is over.
Current chrome GL and Vulkan concurrent read pattern is - Blink holds
and caches read access for a backing shared image for a WebGL or
2D canvas. SkiaOutputSurfaceImplOnGpu only requests read access just
before playing back DDL and releases the read access after playing back
DDL and before SwapBuffers. The GPU will not schedule other tasks
between playing back DDL and SwapBuffers. So it should be safe to
temporarily pause GL read access.

Bug: 1104231
Change-Id: I729eeebd5196bc5387ac148133b5926358bb4b53
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2311330Reviewed-by: default avatarVasiliy Telezhnikov <vasilyt@chromium.org>
Commit-Queue: Peng Huang <penghuang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#791022}
parent 630ebb7f
......@@ -388,6 +388,32 @@ bool ExternalVkImageBacking::BeginAccess(
UpdateContent(kInGLTexture);
}
if (gl_reads_in_progress_ && need_synchronization()) {
// To avoid concurrent read access from both GL and vulkan, if there is
// unfinished GL read access, we will release the GL texture temporarily.
// And when this vulkan access is over, we will acquire the GL texture to
// resume the GL access.
DCHECK(!is_gl);
DCHECK(readonly);
DCHECK(texture_passthrough_ || texture_);
GLuint texture_id = texture_passthrough_
? texture_passthrough_->service_id()
: texture_->service_id();
context_state()->MakeCurrent(/*gl_surface=*/nullptr, /*needs_gl=*/true);
GrVkImageInfo info;
auto result = backend_texture_.getVkImageInfo(&info);
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);
auto release_semaphore =
ExternalVkImageGLRepresentationShared::ReleaseTexture(
external_semaphore_pool(), texture_id, info.fImageLayout);
EndAccessInternal(readonly, std::move(release_semaphore));
}
if (!BeginAccessInternal(readonly, external_semaphores))
return false;
......@@ -452,6 +478,32 @@ void ExternalVkImageBacking::EndAccess(bool readonly,
latest_content_ = kInVkImage | kInGLTexture;
}
}
if (gl_reads_in_progress_ && need_synchronization()) {
// When vulkan read access is finished, if there is unfinished GL read
// access, we need to resume GL read access.
DCHECK(!is_gl);
DCHECK(readonly);
DCHECK(texture_passthrough_ || texture_);
GLuint texture_id = texture_passthrough_
? texture_passthrough_->service_id()
: texture_->service_id();
context_state()->MakeCurrent(/*gl_surface=*/nullptr, /*needs_gl=*/true);
std::vector<ExternalSemaphore> external_semaphores;
BeginAccessInternal(true, &external_semaphores);
DCHECK_LE(external_semaphores.size(), 1u);
for (auto& semaphore : external_semaphores) {
GrVkImageInfo info;
auto result = backend_texture_.getVkImageInfo(&info);
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);
ExternalVkImageGLRepresentationShared::AcquireTexture(
&semaphore, texture_id, info.fImageLayout);
}
}
}
void ExternalVkImageBacking::Update(std::unique_ptr<gfx::GpuFence> in_fence) {
......
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