Commit 4df06a5a authored by Bo Liu's avatar Bo Liu Committed by Commit Bot

aw: Multiple AwVulkanContextProvider

VulkanContextProvider currently owns things such as
GrVkSecondaryCBDrawContext that is per-webview rather than (assumed)
global. Factor out a AwVulkanContextProvider::Global that provides of
sharing things that are (assumed) global, and create new instances of
AwVulkanContextProvider for each draw functor instance.

Need to pass the right instance of AwVulkanContextProvider into viz.
Only hook this up for the viz code path.

Bug: 1141683
Change-Id: Ia98a2e9edb74ccdda56f75944a3257e64efc79fa
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2485778Reviewed-by: default avatarVasiliy Telezhnikov <vasilyt@chromium.org>
Commit-Queue: Bo <boliu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#820438}
parent 1d558f24
......@@ -280,8 +280,9 @@ void AwDrawFnImpl::InitVk(AwDrawFn_InitVkParams* params) {
// We should never have a |vulkan_context_provider_| if we are calling VkInit.
// This means context destroyed was not correctly called.
DCHECK(!vulkan_context_provider_);
vulkan_context_provider_ =
AwVulkanContextProvider::GetOrCreateInstance(params);
vulkan_context_provider_ = AwVulkanContextProvider::Create(params);
render_thread_manager_.SetVulkanContextProviderOnRT(
vulkan_context_provider_.get());
// Make sure we have a GL context.
DCHECK(!gl_context_);
......@@ -316,8 +317,8 @@ void AwDrawFnImpl::DrawVkDirect(AwDrawFn_DrawVkParams* params) {
LOG(ERROR) << "Received invalid colorspace.";
color_space = SkColorSpace::MakeSRGB();
}
auto draw_context = CreateDrawContext(vulkan_context_provider_->gr_context(),
params, color_space);
auto draw_context = CreateDrawContext(
vulkan_context_provider_->GetGrContext(), params, color_space);
// Set the draw contexct in |vulkan_context_provider_|, so the SkiaRenderer
// and SkiaOutputSurface* will use it as frame render target.
......@@ -437,16 +438,18 @@ void AwDrawFnImpl::DrawVkInterop(AwDrawFn_DrawVkParams* params) {
}
pending_draw->draw_context = CreateDrawContext(
vulkan_context_provider_->gr_context(), params, color_space);
vulkan_context_provider_->GetGrContext(), params, color_space);
// If we have a |gl_done_fd|, create a Skia GrBackendSemaphore from
// |gl_done_fd| and wait.
if (gl_done_fd.is_valid()) {
VkSemaphore gl_done_semaphore =
vulkan_context_provider_->implementation()->ImportSemaphoreHandle(
vulkan_context_provider_->device(),
gpu::SemaphoreHandle(VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
std::move(gl_done_fd)));
vulkan_context_provider_->GetVulkanImplementation()
->ImportSemaphoreHandle(
vulkan_context_provider_->device(),
gpu::SemaphoreHandle(
VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
std::move(gl_done_fd)));
if (gl_done_semaphore == VK_NULL_HANDLE) {
LOG(ERROR) << "Could not create Vulkan semaphore for GL completion.";
return;
......@@ -485,7 +488,7 @@ void AwDrawFnImpl::DrawVkInterop(AwDrawFn_DrawVkParams* params) {
GrBackendTexture backend_texture(params->width, params->height,
pending_draw->image_info);
pending_draw->ahb_skimage = SkImage::MakeFromTexture(
vulkan_context_provider_->gr_context(), backend_texture,
vulkan_context_provider_->GetGrContext(), backend_texture,
kBottomLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType, kPremul_SkAlphaType,
color_space);
if (!pending_draw->ahb_skimage) {
......@@ -555,14 +558,14 @@ void AwDrawFnImpl::PostDrawVkInterop(AwDrawFn_PostDrawVkParams* params) {
flushInfo.fNumSemaphores = 1;
flushInfo.fSignalSemaphores = &gr_post_draw_semaphore;
GrSemaphoresSubmitted submitted =
vulkan_context_provider_->gr_context()->flush(flushInfo);
vulkan_context_provider_->gr_context()->submit();
vulkan_context_provider_->GetGrContext()->flush(flushInfo);
vulkan_context_provider_->GetGrContext()->submit();
if (submitted != GrSemaphoresSubmitted::kYes) {
LOG(ERROR) << "Skia could not submit GrSemaphore.";
return;
}
gpu::SemaphoreHandle semaphore_handle =
vulkan_context_provider_->implementation()->GetSemaphoreHandle(
vulkan_context_provider_->GetVulkanImplementation()->GetSemaphoreHandle(
vulkan_context_provider_->device(),
pending_draw->post_draw_semaphore);
if (!semaphore_handle.is_valid()) {
......@@ -625,7 +628,7 @@ AwDrawFnImpl::InFlightInteropDraw::~InFlightInteropDraw() {
// to flush before the vkQueueWaitIdle below.
if (ahb_skimage) {
ahb_skimage.reset();
vk_context_provider->gr_context()->flushAndSubmit();
vk_context_provider->GetGrContext()->flushAndSubmit();
}
// We encountered an error and are not sure when our Vk objects are safe to
// delete. VkQueueWaitIdle to ensure safety.
......
......@@ -24,9 +24,9 @@
namespace android_webview {
namespace {
AwVulkanContextProvider::Globals* AwVulkanContextProvider::g_globals = nullptr;
AwVulkanContextProvider* g_vulkan_context_provider = nullptr;
namespace {
bool InitVulkanForWebView(VkInstance instance,
VkPhysicalDevice physical_device,
......@@ -69,72 +69,39 @@ bool InitVulkanForWebView(VkInstance instance,
} // namespace
// static
scoped_refptr<AwVulkanContextProvider>
AwVulkanContextProvider::GetOrCreateInstance(AwDrawFn_InitVkParams* params) {
if (g_vulkan_context_provider) {
DCHECK(!params || params->device == g_vulkan_context_provider->device());
DCHECK(!params || params->queue == g_vulkan_context_provider->queue());
return base::WrapRefCounted(g_vulkan_context_provider);
scoped_refptr<AwVulkanContextProvider::Globals>
AwVulkanContextProvider::Globals::GetOrCreateInstance(
AwDrawFn_InitVkParams* params) {
if (g_globals) {
DCHECK(params->device == g_globals->device_queue->GetVulkanDevice());
DCHECK(params->queue == g_globals->device_queue->GetVulkanQueue());
return base::WrapRefCounted(g_globals);
}
auto provider = base::WrapRefCounted(new AwVulkanContextProvider);
if (!provider->Initialize(params))
auto globals = base::MakeRefCounted<AwVulkanContextProvider::Globals>();
if (!globals->Initialize(params))
return nullptr;
return provider;
}
AwVulkanContextProvider::AwVulkanContextProvider() {
DCHECK_EQ(nullptr, g_vulkan_context_provider);
g_vulkan_context_provider = this;
}
AwVulkanContextProvider::~AwVulkanContextProvider() {
DCHECK_EQ(g_vulkan_context_provider, this);
g_vulkan_context_provider = nullptr;
draw_context_.reset();
gr_context_.reset();
device_queue_->Destroy();
device_queue_ = nullptr;
}
gpu::VulkanImplementation* AwVulkanContextProvider::GetVulkanImplementation() {
return implementation_.get();
}
gpu::VulkanDeviceQueue* AwVulkanContextProvider::GetDeviceQueue() {
return device_queue_.get();
return globals;
}
GrDirectContext* AwVulkanContextProvider::GetGrContext() {
return gr_context_.get();
AwVulkanContextProvider::Globals::Globals() {
DCHECK_EQ(nullptr, g_globals);
g_globals = this;
}
GrVkSecondaryCBDrawContext*
AwVulkanContextProvider::GetGrSecondaryCBDrawContext() {
return draw_context_.get();
}
AwVulkanContextProvider::Globals::~Globals() {
DCHECK_EQ(g_globals, this);
g_globals = nullptr;
void AwVulkanContextProvider::EnqueueSecondaryCBSemaphores(
std::vector<VkSemaphore> semaphores) {
post_submit_semaphores_.reserve(post_submit_semaphores_.size() +
semaphores.size());
std::copy(semaphores.begin(), semaphores.end(),
std::back_inserter(post_submit_semaphores_));
gr_context.reset();
device_queue->Destroy();
device_queue = nullptr;
}
void AwVulkanContextProvider::EnqueueSecondaryCBPostSubmitTask(
base::OnceClosure closure) {
post_submit_tasks_.push_back(std::move(closure));
}
bool AwVulkanContextProvider::Initialize(AwDrawFn_InitVkParams* params) {
DCHECK(params);
bool AwVulkanContextProvider::Globals::Initialize(
AwDrawFn_InitVkParams* params) {
// Don't call init on implementation. Instead call InitVulkanForWebView,
// which avoids creating a new instance.
implementation_ = gpu::CreateVulkanImplementation();
implementation = gpu::CreateVulkanImplementation();
gfx::ExtensionSet instance_extensions;
for (uint32_t i = 0; i < params->enabled_instance_extension_names_length; ++i)
......@@ -151,8 +118,8 @@ bool AwVulkanContextProvider::Initialize(AwDrawFn_InitVkParams* params) {
return false;
}
device_queue_ = std::make_unique<gpu::VulkanDeviceQueue>(params->instance);
device_queue_->InitializeForWebView(
device_queue = std::make_unique<gpu::VulkanDeviceQueue>(params->instance);
device_queue->InitializeForWebView(
params->physical_device, params->device, params->queue,
params->graphics_queue_index, std::move(device_extensions));
......@@ -178,18 +145,70 @@ bool AwVulkanContextProvider::Initialize(AwDrawFn_InitVkParams* params) {
.fVkExtensions = &vk_extensions,
.fDeviceFeatures = params->device_features,
.fDeviceFeatures2 = params->device_features_2,
.fMemoryAllocator = gpu::CreateGrVkMemoryAllocator(device_queue_.get()),
.fMemoryAllocator = gpu::CreateGrVkMemoryAllocator(device_queue.get()),
.fGetProc = get_proc,
.fOwnsInstanceAndDevice = false,
};
gr_context_ = GrDirectContext::MakeVulkan(backend_context);
if (!gr_context_) {
gr_context = GrDirectContext::MakeVulkan(backend_context);
if (!gr_context) {
LOG(ERROR) << "Unable to initialize GrContext.";
return false;
}
return true;
}
// static
scoped_refptr<AwVulkanContextProvider> AwVulkanContextProvider::Create(
AwDrawFn_InitVkParams* params) {
auto provider = base::WrapRefCounted(new AwVulkanContextProvider);
if (!provider->Initialize(params))
return nullptr;
return provider;
}
AwVulkanContextProvider::AwVulkanContextProvider() = default;
AwVulkanContextProvider::~AwVulkanContextProvider() {
draw_context_.reset();
}
gpu::VulkanImplementation* AwVulkanContextProvider::GetVulkanImplementation() {
return globals_->implementation.get();
}
gpu::VulkanDeviceQueue* AwVulkanContextProvider::GetDeviceQueue() {
return globals_->device_queue.get();
}
GrDirectContext* AwVulkanContextProvider::GetGrContext() {
return globals_->gr_context.get();
}
GrVkSecondaryCBDrawContext*
AwVulkanContextProvider::GetGrSecondaryCBDrawContext() {
return draw_context_.get();
}
void AwVulkanContextProvider::EnqueueSecondaryCBSemaphores(
std::vector<VkSemaphore> semaphores) {
post_submit_semaphores_.reserve(post_submit_semaphores_.size() +
semaphores.size());
std::copy(semaphores.begin(), semaphores.end(),
std::back_inserter(post_submit_semaphores_));
}
void AwVulkanContextProvider::EnqueueSecondaryCBPostSubmitTask(
base::OnceClosure closure) {
post_submit_tasks_.push_back(std::move(closure));
}
bool AwVulkanContextProvider::Initialize(AwDrawFn_InitVkParams* params) {
DCHECK(params);
globals_ = Globals::GetOrCreateInstance(params);
return !!globals_;
}
void AwVulkanContextProvider::SecondaryCBDrawBegin(
sk_sp<GrVkSecondaryCBDrawContext> draw_context) {
DCHECK(draw_context);
......@@ -202,7 +221,7 @@ void AwVulkanContextProvider::SecondaryCMBDrawSubmitted() {
DCHECK(draw_context_);
auto draw_context = std::move(draw_context_);
auto* fence_helper = device_queue_->GetFenceHelper();
auto* fence_helper = globals_->device_queue->GetFenceHelper();
VkFence vk_fence = VK_NULL_HANDLE;
auto result = fence_helper->GetFence(&vk_fence);
DCHECK(result == VK_SUCCESS);
......
......@@ -42,8 +42,8 @@ class AwVulkanContextProvider final : public viz::VulkanContextProvider {
DISALLOW_COPY_AND_ASSIGN(ScopedSecondaryCBDraw);
};
static scoped_refptr<AwVulkanContextProvider> GetOrCreateInstance(
AwDrawFn_InitVkParams* params = nullptr);
static scoped_refptr<AwVulkanContextProvider> Create(
AwDrawFn_InitVkParams* params);
// viz::VulkanContextProvider implementation:
gpu::VulkanImplementation* GetVulkanImplementation() override;
......@@ -54,13 +54,8 @@ class AwVulkanContextProvider final : public viz::VulkanContextProvider {
std::vector<VkSemaphore> semaphores) override;
void EnqueueSecondaryCBPostSubmitTask(base::OnceClosure closure) override;
VkPhysicalDevice physical_device() {
return device_queue_->GetVulkanPhysicalDevice();
}
VkDevice device() { return device_queue_->GetVulkanDevice(); }
VkQueue queue() { return device_queue_->GetVulkanQueue(); }
gpu::VulkanImplementation* implementation() { return implementation_.get(); }
GrDirectContext* gr_context() { return gr_context_.get(); }
VkDevice device() { return globals_->device_queue->GetVulkanDevice(); }
VkQueue queue() { return globals_->device_queue->GetVulkanQueue(); }
private:
friend class base::RefCounted<AwVulkanContextProvider>;
......@@ -72,9 +67,24 @@ class AwVulkanContextProvider final : public viz::VulkanContextProvider {
void SecondaryCBDrawBegin(sk_sp<GrVkSecondaryCBDrawContext> draw_context);
void SecondaryCMBDrawSubmitted();
std::unique_ptr<gpu::VulkanImplementation> implementation_;
std::unique_ptr<gpu::VulkanDeviceQueue> device_queue_;
sk_sp<GrDirectContext> gr_context_;
struct Globals : base::RefCountedThreadSafe<Globals> {
static scoped_refptr<Globals> GetOrCreateInstance(
AwDrawFn_InitVkParams* params);
Globals();
bool Initialize(AwDrawFn_InitVkParams* params);
std::unique_ptr<gpu::VulkanImplementation> implementation;
std::unique_ptr<gpu::VulkanDeviceQueue> device_queue;
sk_sp<GrDirectContext> gr_context;
private:
friend base::RefCountedThreadSafe<Globals>;
~Globals();
};
static Globals* g_globals;
scoped_refptr<Globals> globals_;
sk_sp<GrVkSecondaryCBDrawContext> draw_context_;
std::vector<base::OnceClosure> post_submit_tasks_;
std::vector<VkSemaphore> post_submit_semaphores_;
......
......@@ -51,8 +51,7 @@ HardwareRendererSingleThread::~HardwareRendererSingleThread() {
void HardwareRendererSingleThread::DrawAndSwap(
HardwareRendererDrawParams* params) {
TRACE_EVENT1("android_webview", "HardwareRendererSingleThread::DrawAndSwap",
"vulkan", surfaces_->is_using_vulkan());
TRACE_EVENT0("android_webview", "HardwareRendererSingleThread::DrawAndSwap");
bool submitted_new_frame = false;
uint32_t frame_token = 0u;
......
......@@ -271,8 +271,9 @@ HardwareRendererViz::OnViz::GetPreferredFrameIntervalForFrameSinkId(
HardwareRendererViz::HardwareRendererViz(
RenderThreadManager* state,
RootFrameSinkGetter root_frame_sink_getter)
: HardwareRenderer(state) {
RootFrameSinkGetter root_frame_sink_getter,
AwVulkanContextProvider* context_provider)
: HardwareRenderer(state), output_surface_provider_(context_provider) {
DCHECK_CALLED_ON_VALID_THREAD(render_thread_checker_);
DCHECK(output_surface_provider_.renderer_settings().use_skia_renderer);
......
......@@ -16,10 +16,13 @@
namespace android_webview {
class AwVulkanContextProvider;
class HardwareRendererViz : public HardwareRenderer {
public:
HardwareRendererViz(RenderThreadManager* state,
RootFrameSinkGetter root_frame_sink_getter);
RootFrameSinkGetter root_frame_sink_getter,
AwVulkanContextProvider* context_provider);
~HardwareRendererViz() override;
// HardwareRenderer overrides.
......
......@@ -40,7 +40,9 @@ void OnContextLost(bool synthetic_loss) {
} // namespace
OutputSurfaceProviderWebview::OutputSurfaceProviderWebview() {
OutputSurfaceProviderWebview::OutputSurfaceProviderWebview(
AwVulkanContextProvider* vulkan_context_provider)
: vulkan_context_provider_(vulkan_context_provider) {
// Should be kept in sync with compositor_impl_android.cc.
renderer_settings_.allow_antialiasing = false;
renderer_settings_.highp_threshold_min = 2048;
......@@ -52,6 +54,8 @@ OutputSurfaceProviderWebview::OutputSurfaceProviderWebview() {
auto* command_line = base::CommandLine::ForCurrentProcess();
enable_vulkan_ = command_line->HasSwitch(switches::kWebViewEnableVulkan);
DCHECK(!enable_vulkan_ || vulkan_context_provider_);
enable_shared_image_ =
base::FeatureList::IsEnabled(features::kEnableSharedImageForWebview);
LOG_IF(FATAL, enable_vulkan_ && !enable_shared_image_)
......@@ -90,15 +94,11 @@ void OutputSurfaceProviderWebview::InitializeContext() {
share_group.get(), gl_surface_.get(), gl::GLContextAttribs());
gl_context->MakeCurrent(gl_surface_.get());
auto vulkan_context_provider =
enable_vulkan_ ? AwVulkanContextProvider::GetOrCreateInstance()
: nullptr;
shared_context_state_ = base::MakeRefCounted<gpu::SharedContextState>(
share_group, gl_surface_, std::move(gl_context),
false /* use_virtualized_gl_contexts */, base::BindOnce(&OnContextLost),
GpuServiceWebView::GetInstance()->gpu_preferences().gr_context_type,
vulkan_context_provider.get());
vulkan_context_provider_);
if (!enable_vulkan_) {
auto feature_info = base::MakeRefCounted<gpu::gles2::FeatureInfo>(
workarounds, GpuServiceWebView::GetInstance()->gpu_feature_info());
......
......@@ -23,9 +23,13 @@ class OutputSurface;
namespace android_webview {
class AwVulkanContextProvider;
// Effectively a data struct to pass pointers from render thread to viz thread.
class OutputSurfaceProviderWebview {
public:
OutputSurfaceProviderWebview();
explicit OutputSurfaceProviderWebview(
AwVulkanContextProvider* vulkan_context_provider);
~OutputSurfaceProviderWebview();
std::unique_ptr<viz::OutputSurface> CreateOutputSurface();
......@@ -45,8 +49,9 @@ class OutputSurfaceProviderWebview {
private:
void InitializeContext();
AwVulkanContextProvider* const vulkan_context_provider_;
// The member variables are effectively const after constructor, so it's safe
// to call accessors on different threads
// to call accessors on different threads.
viz::RendererSettings renderer_settings_;
viz::DebugRendererSettings debug_settings_;
scoped_refptr<AwGLSurface> gl_surface_;
......
......@@ -172,6 +172,12 @@ void RenderThreadManager::CommitFrameOnRT() {
hardware_renderer_->CommitFrame();
}
void RenderThreadManager::SetVulkanContextProviderOnRT(
AwVulkanContextProvider* context_provider) {
DCHECK(!hardware_renderer_);
vulkan_context_provider_ = context_provider;
}
void RenderThreadManager::UpdateViewTreeForceDarkStateOnRT(
bool view_tree_force_dark_state) {
if (view_tree_force_dark_state_ == view_tree_force_dark_state)
......@@ -199,8 +205,8 @@ void RenderThreadManager::DrawOnRT(bool save_restore,
getter = root_frame_sink_getter_;
}
DCHECK(getter);
hardware_renderer_.reset(
new HardwareRendererViz(this, std::move(getter)));
hardware_renderer_.reset(new HardwareRendererViz(
this, std::move(getter), vulkan_context_provider_));
} else {
hardware_renderer_.reset(new HardwareRendererSingleThread(this));
}
......
......@@ -21,6 +21,7 @@
namespace android_webview {
class AwVulkanContextProvider;
class ChildFrame;
class CompositorFrameProducer;
......@@ -60,6 +61,7 @@ class RenderThreadManager : public CompositorFrameConsumer {
uint32_t layer_tree_frame_sink_id);
void CommitFrameOnRT();
void SetVulkanContextProviderOnRT(AwVulkanContextProvider* context_provider);
void UpdateViewTreeForceDarkStateOnRT(bool view_tree_force_dark_state);
void DrawOnRT(bool save_restore, HardwareRendererDrawParams* params);
void DestroyHardwareRendererOnRT(bool save_restore);
......@@ -108,6 +110,7 @@ class RenderThreadManager : public CompositorFrameConsumer {
// Accessed by RT thread.
std::unique_ptr<HardwareRenderer> hardware_renderer_;
bool view_tree_force_dark_state_ = false;
AwVulkanContextProvider* vulkan_context_provider_ = nullptr;
// Accessed by both UI and RT thread.
mutable base::Lock lock_;
......
......@@ -9,7 +9,6 @@
#include <utility>
#include "android_webview/browser/gfx/aw_render_thread_context_provider.h"
#include "android_webview/browser/gfx/aw_vulkan_context_provider.h"
#include "android_webview/browser/gfx/deferred_gpu_command_service.h"
#include "android_webview/browser/gfx/gpu_service_web_view.h"
#include "android_webview/browser/gfx/output_surface_provider_webview.h"
......@@ -61,7 +60,8 @@ scoped_refptr<SurfacesInstance> SurfacesInstance::GetOrCreateInstance() {
SurfacesInstance::SurfacesInstance()
: frame_sink_id_allocator_(kDefaultClientId),
frame_sink_id_(AllocateFrameSinkId()) {
frame_sink_id_(AllocateFrameSinkId()),
output_surface_provider_(nullptr) {
// The SharedBitmapManager is null as we do not support or use software
// compositing on Android.
frame_sink_manager_ = std::make_unique<viz::FrameSinkManagerImpl>(
......
......@@ -55,10 +55,6 @@ class SurfacesInstance : public base::RefCounted<SurfacesInstance>,
void AddChildId(const viz::SurfaceId& child_id);
void RemoveChildId(const viz::SurfaceId& child_id);
bool is_using_vulkan() const {
return output_surface_provider_.shared_context_state() &&
output_surface_provider_.shared_context_state()->GrContextIsVulkan();
}
private:
friend class base::RefCounted<SurfacesInstance>;
......
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