Skip to content

Commit

Permalink
aw: Multiple AwVulkanContextProvider
Browse files Browse the repository at this point in the history
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/+/2485778
Reviewed-by: Vasiliy Telezhnikov <vasilyt@chromium.org>
Commit-Queue: Bo <boliu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#820438}
  • Loading branch information
Bo Liu authored and Commit Bot committed Oct 23, 2020
1 parent 1d558f2 commit 4df06a5
Show file tree
Hide file tree
Showing 12 changed files with 155 additions and 110 deletions.
31 changes: 17 additions & 14 deletions android_webview/browser/gfx/aw_draw_fn_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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_);
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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()) {
Expand Down Expand Up @@ -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.
Expand Down
145 changes: 82 additions & 63 deletions android_webview/browser/gfx/aw_vulkan_context_provider.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand All @@ -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));

Expand All @@ -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);
Expand All @@ -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);
Expand Down
34 changes: 22 additions & 12 deletions android_webview/browser/gfx/aw_vulkan_context_provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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>;
Expand All @@ -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_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 3 additions & 2 deletions android_webview/browser/gfx/hardware_renderer_viz.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
5 changes: 4 additions & 1 deletion android_webview/browser/gfx/hardware_renderer_viz.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Loading

0 comments on commit 4df06a5

Please sign in to comment.