Commit 182fe54a authored by Peng Huang's avatar Peng Huang Committed by Commit Bot

ExternalVkImage: using GrContext::setBackendTextureState() to change

VkImage layout and queue family.

Right now, ExternalVkImageBacking uses vulkan API to change VkImage
layout and queue family for external usage (GL). It needs an extra
vulkan queue submission. Remove this submission by using the new added
GrContext::setBackendTextureState().

Bug: 1087063
Change-Id: If0885d166dd917132b81a111bd10be6863cc991d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2273601Reviewed-by: default avatarVasiliy Telezhnikov <vasilyt@chromium.org>
Commit-Queue: Peng Huang <penghuang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#783748}
parent f2637281
......@@ -6,6 +6,7 @@
#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_IMAGE_CONTEXT_IMPL_H_
#include <memory>
#include <utility>
#include <vector>
#include "base/macros.h"
......@@ -71,6 +72,11 @@ class ImageContextImpl final : public ExternalUseClient::ImageContext {
SkPromiseImageTexture* promise_image_texture() const {
return promise_image_texture_;
}
GrBackendSurfaceMutableState* end_access_state() const {
return representation_scoped_read_access_
? representation_scoped_read_access_->end_state()
: nullptr;
}
void BeginAccessIfNecessary(
gpu::SharedContextState* context_state,
......
......@@ -1021,6 +1021,7 @@ void SkiaOutputSurfaceImplOnGpu::SwapBuffers(
}
DCHECK(output_device_);
ResetStateOfImages();
gr_context()->submit();
promise_image_access_helper_.EndAccess();
scoped_output_device_paint_.reset();
......@@ -1066,6 +1067,7 @@ void SkiaOutputSurfaceImplOnGpu::SwapBuffersSkipped(
base::OnceCallback<bool()> deferred_framebuffer_draw_closure) {
if (deferred_framebuffer_draw_closure)
std::move(deferred_framebuffer_draw_closure).Run();
ResetStateOfImages();
gr_context()->submit();
promise_image_access_helper_.EndAccess();
// Perform cleanup that would have otherwise happened in SwapBuffers().
......@@ -1409,14 +1411,29 @@ void SkiaOutputSurfaceImplOnGpu::BeginAccessImages(
context->BeginAccessIfNecessary(
context_state_.get(), shared_image_representation_factory_.get(),
dependency_->GetMailboxManager(), begin_semaphores, end_semaphores);
if (context->end_access_state())
image_contexts_with_end_access_state_.emplace(context);
}
}
}
void SkiaOutputSurfaceImplOnGpu::ResetStateOfImages() {
for (auto* context : image_contexts_with_end_access_state_) {
DCHECK(context->end_access_state());
if (!gr_context()->setBackendTextureState(
context->promise_image_texture()->backendTexture(),
*context->end_access_state())) {
DLOG(ERROR) << "setBackendTextureState() failed.";
}
}
image_contexts_with_end_access_state_.clear();
}
void SkiaOutputSurfaceImplOnGpu::EndAccessImages(
const base::flat_set<ImageContextImpl*>& image_contexts) {
TRACE_EVENT0("viz", "SkiaOutputSurfaceImplOnGpu::EndAccessImages");
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(image_contexts_with_end_access_state_.empty());
for (auto* context : image_contexts)
context->EndAccessIfNecessary();
}
......
......@@ -159,6 +159,7 @@ class SkiaOutputSurfaceImplOnGpu : public gpu::ImageTransportSurfaceDelegate {
void BeginAccessImages(const std::vector<ImageContextImpl*>& image_contexts,
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores);
void ResetStateOfImages();
void EndAccessImages(const base::flat_set<ImageContextImpl*>& image_contexts);
sk_sp<GrContextThreadSafeProxy> GetGrContextThreadSafeProxy();
......@@ -328,6 +329,7 @@ class SkiaOutputSurfaceImplOnGpu : public gpu::ImageTransportSurfaceDelegate {
DISALLOW_COPY_AND_ASSIGN(PromiseImageAccessHelper);
};
PromiseImageAccessHelper promise_image_access_helper_{this};
base::flat_set<ImageContextImpl*> image_contexts_with_end_access_state_;
std::unique_ptr<SkiaOutputDevice> output_device_;
base::Optional<SkiaOutputDevice::ScopedPaint> scoped_output_device_paint_;
......
......@@ -346,65 +346,6 @@ bool ExternalVkImageBacking::BeginAccess(
DCHECK(!gl_reads_in_progress_);
gl_reads_in_progress_ = 1;
}
if (use_separate_gl_texture())
return true;
DCHECK(need_synchronization());
DCHECK(is_gl);
auto command_buffer = command_pool_->CreatePrimaryCommandBuffer();
{
ScopedSingleUseCommandBufferRecorder recorder(*command_buffer);
GrVkImageInfo image_info;
bool success = backend_texture_.getVkImageInfo(&image_info);
DCHECK(success);
auto image_layout = image_info.fImageLayout;
if (image_layout == VK_IMAGE_LAYOUT_UNDEFINED) {
// dst_image_layout cannot be VK_IMAGE_LAYOUT_UNDEFINED, so we set it to
// VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL.
image_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
command_buffer->TransitionImageLayout(
image_info.fImage, image_info.fImageLayout, image_layout);
// Update backend_texture_ image layout.
backend_texture_.setVkImageLayout(image_layout);
}
uint32_t vulkan_queue_index = context_state_->vk_context_provider()
->GetDeviceQueue()
->GetVulkanQueueIndex();
// Transfer image queue family ownership to external, so the image can be
// used by GL.
command_buffer->TransitionImageLayout(image_info.fImage, image_layout,
image_layout, vulkan_queue_index,
VK_QUEUE_FAMILY_EXTERNAL);
}
std::vector<VkSemaphore> wait_semaphores;
wait_semaphores.reserve(semaphore_handles->size());
for (auto& handle : *semaphore_handles) {
VkSemaphore semaphore = vulkan_implementation()->ImportSemaphoreHandle(
device(), std::move(handle));
wait_semaphores.emplace_back(semaphore);
}
semaphore_handles->clear();
VkSemaphore signal_semaphore =
vulkan_implementation()->CreateExternalSemaphore(device());
// TODO(penghuang): ask skia to do it for us to avoid this queue submission.
command_buffer->Submit(wait_semaphores.size(), wait_semaphores.data(), 1,
&signal_semaphore);
auto end_access_semaphore_handle =
vulkan_implementation()->GetSemaphoreHandle(device(), signal_semaphore);
semaphore_handles->push_back(std::move(end_access_semaphore_handle));
auto* fence_helper =
context_state_->vk_context_provider()->GetDeviceQueue()->GetFenceHelper();
fence_helper->EnqueueVulkanObjectCleanupForSubmittedWork(
std::move(command_buffer));
wait_semaphores.emplace_back(signal_semaphore);
fence_helper->EnqueueSemaphoresCleanupForSubmittedWork(
std::move(wait_semaphores));
return true;
}
......@@ -419,43 +360,6 @@ void ExternalVkImageBacking::EndAccess(bool readonly,
}
}
// Only transite image layout and queue back when it is the last gl access.
if (is_gl && !use_separate_gl_texture()) {
DCHECK(semaphore_handle.is_valid());
auto command_buffer = command_pool_->CreatePrimaryCommandBuffer();
{
ScopedSingleUseCommandBufferRecorder recorder(*command_buffer);
GrVkImageInfo image_info;
bool success = backend_texture_.getVkImageInfo(&image_info);
DCHECK(success);
uint32_t vulkan_queue_index = context_state_->vk_context_provider()
->GetDeviceQueue()
->GetVulkanQueueIndex();
// After GL accessing, transfer image queue family ownership back, so it
// can be used by vulkan.
command_buffer->TransitionImageLayout(
image_info.fImage, image_info.fImageLayout, image_info.fImageLayout,
VK_QUEUE_FAMILY_EXTERNAL, vulkan_queue_index);
}
VkSemaphore semaphore = vulkan_implementation()->ImportSemaphoreHandle(
device(), std::move(semaphore_handle));
VkSemaphore end_access_semaphore =
vulkan_implementation()->CreateExternalSemaphore(device());
// TODO(penghuang): ask skia to do it for us to avoid this queue submission.
command_buffer->Submit(1, &semaphore, 1, &end_access_semaphore);
semaphore_handle = vulkan_implementation()->GetSemaphoreHandle(
device(), end_access_semaphore);
auto* fence_helper = context_state_->vk_context_provider()
->GetDeviceQueue()
->GetFenceHelper();
fence_helper->EnqueueVulkanObjectCleanupForSubmittedWork(
std::move(command_buffer));
fence_helper->EnqueueSemaphoresCleanupForSubmittedWork(
{semaphore, end_access_semaphore});
}
EndAccessInternal(readonly, std::move(semaphore_handle));
if (!readonly) {
if (use_separate_gl_texture()) {
......@@ -879,6 +783,10 @@ bool ExternalVkImageBacking::WritePixels() {
};
gr_context->flush(flush_info);
gr_context->setBackendTextureState(
backend_texture_,
GrBackendSurfaceMutableState(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_QUEUE_FAMILY_EXTERNAL));
// Submit so the |end_access_semaphore| is ready for waiting.
gr_context->submit();
......
......@@ -34,7 +34,8 @@ sk_sp<SkSurface> ExternalVkImageSkiaRepresentation::BeginWriteAccess(
int final_msaa_count,
const SkSurfaceProps& surface_props,
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores) {
std::vector<GrBackendSemaphore>* end_semaphores,
std::unique_ptr<GrBackendSurfaceMutableState>* end_state) {
auto* gr_context = backing_impl()->context_state()->gr_context();
if (gr_context->abandoned()) {
LOG(ERROR) << "GrContext is abandonded.";
......@@ -79,6 +80,15 @@ sk_sp<SkSurface> ExternalVkImageSkiaRepresentation::BeginWriteAccess(
ALLOW_UNUSED_LOCAL(count);
access_mode_ = kWrite;
// If Vulkan and GLSet share the same memory backing, we need set |end_state|
// VK_QUEUE_FAMILY_EXTERNAL, and then the caller will set the VkImage to
// VK_QUEUE_FAMILY_EXTERNAL before calling EndAccess().
if (!backing_impl()->use_separate_gl_texture()) {
*end_state = std::make_unique<GrBackendSurfaceMutableState>(
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_QUEUE_FAMILY_EXTERNAL);
}
return surface;
}
......@@ -97,7 +107,8 @@ void ExternalVkImageSkiaRepresentation::EndWriteAccess(
sk_sp<SkPromiseImageTexture> ExternalVkImageSkiaRepresentation::BeginReadAccess(
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores) {
std::vector<GrBackendSemaphore>* end_semaphores,
std::unique_ptr<GrBackendSurfaceMutableState>* end_state) {
if (access_mode_ != kNone) {
LOG(DFATAL) << "Previous access is not finished. mode=" << access_mode_;
return nullptr;
......@@ -109,6 +120,15 @@ sk_sp<SkPromiseImageTexture> ExternalVkImageSkiaRepresentation::BeginReadAccess(
LOG(ERROR) << "BeginAccess failed";
return nullptr;
}
// If Vulkan and GLSet share the same memory backing, we need set |end_state|
// VK_QUEUE_FAMILY_EXTERNAL, and then the caller will set the VkImage to
// VK_QUEUE_FAMILY_EXTERNAL before calling EndAccess().
if (!backing_impl()->use_separate_gl_texture()) {
*end_state = std::make_unique<GrBackendSurfaceMutableState>(
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_QUEUE_FAMILY_EXTERNAL);
}
access_mode_ = kRead;
return promise_texture;
}
......
......@@ -28,11 +28,13 @@ class ExternalVkImageSkiaRepresentation : public SharedImageRepresentationSkia {
int final_msaa_count,
const SkSurfaceProps& surface_props,
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores) override;
std::vector<GrBackendSemaphore>* end_semaphores,
std::unique_ptr<GrBackendSurfaceMutableState>* end_state) override;
void EndWriteAccess(sk_sp<SkSurface> surface) override;
sk_sp<SkPromiseImageTexture> BeginReadAccess(
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores) override;
std::vector<GrBackendSemaphore>* end_semaphores,
std::unique_ptr<GrBackendSurfaceMutableState>* end_state) override;
void EndReadAccess() override;
private:
......
......@@ -93,8 +93,11 @@ bool SharedImageRepresentationSkia::SupportsMultipleConcurrentReadAccess() {
SharedImageRepresentationSkia::ScopedWriteAccess::ScopedWriteAccess(
util::PassKey<SharedImageRepresentationSkia> /* pass_key */,
SharedImageRepresentationSkia* representation,
sk_sp<SkSurface> surface)
: ScopedAccessBase(representation), surface_(std::move(surface)) {}
sk_sp<SkSurface> surface,
std::unique_ptr<GrBackendSurfaceMutableState> end_state)
: ScopedAccessBase(representation),
surface_(std::move(surface)),
end_state_(std::move(end_state)) {}
SharedImageRepresentationSkia::ScopedWriteAccess::~ScopedWriteAccess() {
representation()->EndWriteAccess(std::move(surface_));
......@@ -112,15 +115,18 @@ SharedImageRepresentationSkia::BeginScopedWriteAccess(
return nullptr;
}
sk_sp<SkSurface> surface = BeginWriteAccess(final_msaa_count, surface_props,
begin_semaphores, end_semaphores);
std::unique_ptr<GrBackendSurfaceMutableState> end_state;
sk_sp<SkSurface> surface =
BeginWriteAccess(final_msaa_count, surface_props, begin_semaphores,
end_semaphores, &end_state);
if (!surface)
return nullptr;
backing()->OnWriteSucceeded();
return std::make_unique<ScopedWriteAccess>(
util::PassKey<SharedImageRepresentationSkia>(), this, std::move(surface));
util::PassKey<SharedImageRepresentationSkia>(), this, std::move(surface),
std::move(end_state));
}
std::unique_ptr<SharedImageRepresentationSkia::ScopedWriteAccess>
......@@ -137,9 +143,11 @@ SharedImageRepresentationSkia::BeginScopedWriteAccess(
SharedImageRepresentationSkia::ScopedReadAccess::ScopedReadAccess(
util::PassKey<SharedImageRepresentationSkia> /* pass_key */,
SharedImageRepresentationSkia* representation,
sk_sp<SkPromiseImageTexture> promise_image_texture)
sk_sp<SkPromiseImageTexture> promise_image_texture,
std::unique_ptr<GrBackendSurfaceMutableState> end_state)
: ScopedAccessBase(representation),
promise_image_texture_(std::move(promise_image_texture)) {}
promise_image_texture_(std::move(promise_image_texture)),
end_state_(std::move(end_state)) {}
SharedImageRepresentationSkia::ScopedReadAccess::~ScopedReadAccess() {
representation()->EndReadAccess();
......@@ -154,8 +162,9 @@ SharedImageRepresentationSkia::BeginScopedReadAccess(
return nullptr;
}
std::unique_ptr<GrBackendSurfaceMutableState> end_state;
sk_sp<SkPromiseImageTexture> promise_image_texture =
BeginReadAccess(begin_semaphores, end_semaphores);
BeginReadAccess(begin_semaphores, end_semaphores, &end_state);
if (!promise_image_texture)
return nullptr;
......@@ -163,7 +172,38 @@ SharedImageRepresentationSkia::BeginScopedReadAccess(
return std::make_unique<ScopedReadAccess>(
util::PassKey<SharedImageRepresentationSkia>(), this,
std::move(promise_image_texture));
std::move(promise_image_texture), std::move(end_state));
}
sk_sp<SkSurface> SharedImageRepresentationSkia::BeginWriteAccess(
int final_msaa_count,
const SkSurfaceProps& surface_props,
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores,
std::unique_ptr<GrBackendSurfaceMutableState>* end_state) {
return BeginWriteAccess(final_msaa_count, surface_props, begin_semaphores,
end_semaphores);
}
sk_sp<SkSurface> SharedImageRepresentationSkia::BeginWriteAccess(
int final_msaa_count,
const SkSurfaceProps& surface_props,
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores) {
return nullptr;
}
sk_sp<SkPromiseImageTexture> SharedImageRepresentationSkia::BeginReadAccess(
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores,
std::unique_ptr<GrBackendSurfaceMutableState>* end_state) {
return BeginReadAccess(begin_semaphores, end_semaphores);
}
sk_sp<SkPromiseImageTexture> SharedImageRepresentationSkia::BeginReadAccess(
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores) {
return nullptr;
}
SharedImageRepresentationOverlay::ScopedReadAccess::ScopedReadAccess(
......
......@@ -18,6 +18,7 @@
#include "gpu/command_buffer/service/shared_image_manager.h"
#include "gpu/gpu_gles2_export.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/gpu/GrBackendSurfaceMutableState.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
......@@ -227,13 +228,16 @@ class GPU_GLES2_EXPORT SharedImageRepresentationSkia
public:
ScopedWriteAccess(util::PassKey<SharedImageRepresentationSkia> pass_key,
SharedImageRepresentationSkia* representation,
sk_sp<SkSurface> surface);
sk_sp<SkSurface> surface,
std::unique_ptr<GrBackendSurfaceMutableState> end_state);
~ScopedWriteAccess();
SkSurface* surface() const { return surface_.get(); }
GrBackendSurfaceMutableState* end_state() const { return end_state_.get(); }
private:
sk_sp<SkSurface> surface_;
std::unique_ptr<GrBackendSurfaceMutableState> end_state_;
};
class GPU_GLES2_EXPORT ScopedReadAccess
......@@ -241,15 +245,18 @@ class GPU_GLES2_EXPORT SharedImageRepresentationSkia
public:
ScopedReadAccess(util::PassKey<SharedImageRepresentationSkia> pass_key,
SharedImageRepresentationSkia* representation,
sk_sp<SkPromiseImageTexture> promise_image_texture);
sk_sp<SkPromiseImageTexture> promise_image_texture,
std::unique_ptr<GrBackendSurfaceMutableState> end_state);
~ScopedReadAccess();
SkPromiseImageTexture* promise_image_texture() const {
return promise_image_texture_.get();
}
GrBackendSurfaceMutableState* end_state() const { return end_state_.get(); }
private:
sk_sp<SkPromiseImageTexture> promise_image_texture_;
std::unique_ptr<GrBackendSurfaceMutableState> end_state_;
};
SharedImageRepresentationSkia(SharedImageManager* manager,
......@@ -287,11 +294,19 @@ class GPU_GLES2_EXPORT SharedImageRepresentationSkia
// client must submit them with drawing operations which use the backing.
// The ownership of end_semaphores are not passed to client. And client must
// submit the end_semaphores before calling EndWriteAccess().
// The backing can assign end_state, and the caller must reset backing's state
// to the end_state before calling EndWriteAccess().
virtual sk_sp<SkSurface> BeginWriteAccess(
int final_msaa_count,
const SkSurfaceProps& surface_props,
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores) = 0;
std::vector<GrBackendSemaphore>* end_semaphores,
std::unique_ptr<GrBackendSurfaceMutableState>* end_state);
virtual sk_sp<SkSurface> BeginWriteAccess(
int final_msaa_count,
const SkSurfaceProps& surface_props,
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores);
virtual void EndWriteAccess(sk_sp<SkSurface> surface) = 0;
// Begin the read access. The implementations should insert semaphores into
......@@ -301,9 +316,15 @@ class GPU_GLES2_EXPORT SharedImageRepresentationSkia
// client must submit them with drawing operations which use the backing.
// The ownership of end_semaphores are not passed to client. And client must
// submit the end_semaphores before calling EndReadAccess().
// The backing can assign end_state, and the caller must reset backing's state
// to the end_state before calling EndReadAccess().
virtual sk_sp<SkPromiseImageTexture> BeginReadAccess(
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores) = 0;
std::vector<GrBackendSemaphore>* end_semaphores,
std::unique_ptr<GrBackendSurfaceMutableState>* end_state);
virtual sk_sp<SkPromiseImageTexture> BeginReadAccess(
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores);
virtual void EndReadAccess() = 0;
};
......
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