Commit 9127573b authored by Bo Liu's avatar Bo Liu Committed by Chromium LUCI CQ

aw: Vulkan instrumentation test

Implement vulkan instrumentation shell. This requires dependency on
gpu/vulkan for vulkan bindings and initialization, and skia for
setting up pipeline and secondary command buffer to be passed to
webview. The skia dependency is largely the same as hwui's
implementation vulkan draw functor implementation.

This requires one fix to VulkanSwapChain to not try to get the
current TaskRunner on initialization. Webview's render thread does
not have a TaskRunner.

Also needed to plumb an explicit resize event to native
ContextManager to resize the vulkan surface.

Make sure to install draw_fn function table before calling
AwBrowserProcess.start everywhere, so it can call query_render_mode
on initialization.

Add plumbing to allow test to choose to use vulkan, and add a test
rendering test using vulkan. The test is limited to P+ and a hard
coded list of supported devices. Verified the android-pie-arm64-rel
bot can successfully run the test.

Bug: 1141687
Change-Id: Id49b770728d993c7764d7dc044a3d990df5bef3a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2620539
Commit-Queue: Bo <boliu@chromium.org>
Reviewed-by: default avatarPeng Huang <penghuang@chromium.org>
Reviewed-by: default avatarVasiliy Telezhnikov <vasilyt@chromium.org>
Cr-Commit-Position: refs/heads/master@{#843260}
parent b30dd7ae
...@@ -195,11 +195,22 @@ public class AwActivityTestRule extends BaseActivityTestRule<AwTestRunnerActivit ...@@ -195,11 +195,22 @@ public class AwActivityTestRule extends BaseActivityTestRule<AwTestRunnerActivit
} }
public void startBrowserProcess() { public void startBrowserProcess() {
doStartBrowserProcess(false);
}
public void startBrowserProcessWithVulkan() {
doStartBrowserProcess(true);
}
private void doStartBrowserProcess(boolean useVulkan) {
// The Activity must be launched in order for proper webview statics to be setup. // The Activity must be launched in order for proper webview statics to be setup.
launchActivity(); launchActivity();
if (!sBrowserProcessStarted) { if (!sBrowserProcessStarted) {
sBrowserProcessStarted = true; sBrowserProcessStarted = true;
TestThreadUtils.runOnUiThreadBlocking(() -> AwBrowserProcess.start()); TestThreadUtils.runOnUiThreadBlocking(() -> {
AwTestContainerView.installDrawFnFunctionTable(useVulkan);
AwBrowserProcess.start();
});
} }
if (mBrowserContext != null) { if (mBrowserContext != null) {
TestThreadUtils.runOnUiThreadBlocking( TestThreadUtils.runOnUiThreadBlocking(
......
...@@ -129,6 +129,7 @@ public class AwSecondBrowserProcessTest { ...@@ -129,6 +129,7 @@ public class AwSecondBrowserProcessTest {
// runOnMainSync does not catch RuntimeExceptions, they just terminate the test. // runOnMainSync does not catch RuntimeExceptions, they just terminate the test.
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
try { try {
AwTestContainerView.installDrawFnFunctionTable(/*useVulkan=*/false);
AwBrowserProcess.start(); AwBrowserProcess.start();
success[0] = true; success[0] = true;
} catch (RuntimeException e) { } catch (RuntimeException e) {
......
...@@ -165,7 +165,9 @@ shared_library("libstandalonelibwebviewchromium") { ...@@ -165,7 +165,9 @@ shared_library("libstandalonelibwebviewchromium") {
"//components/autofill/android/provider/test_support:component_autofill_provider_native_test_support", "//components/autofill/android/provider/test_support:component_autofill_provider_native_test_support",
"//components/heap_profiling/multi_process:test_support", "//components/heap_profiling/multi_process:test_support",
"//content/public/test/android:content_native_test_support", "//content/public/test/android:content_native_test_support",
"//ui/gl", "//gpu/vulkan",
"//gpu/vulkan/init",
"//gpu/vulkan/init:skia",
] ]
libs = [ "android" ] libs = [ "android" ]
configs -= [ "//build/config/android:hide_all_but_jni_onload" ] configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
......
...@@ -12,8 +12,11 @@ namespace draw_fn { ...@@ -12,8 +12,11 @@ namespace draw_fn {
namespace { namespace {
bool g_use_vulkan = false;
AwDrawFnRenderMode QueryRenderMode() { AwDrawFnRenderMode QueryRenderMode() {
return AW_DRAW_FN_RENDER_MODE_OPENGL_ES; return g_use_vulkan ? AW_DRAW_FN_RENDER_MODE_VULKAN
: AW_DRAW_FN_RENDER_MODE_OPENGL_ES;
} }
int CreateFunctor(void* data, AwDrawFnFunctorCallbacks* functor_callbacks) { int CreateFunctor(void* data, AwDrawFnFunctorCallbacks* functor_callbacks) {
...@@ -34,6 +37,10 @@ void ReleaseFunctor(int functor) { ...@@ -34,6 +37,10 @@ void ReleaseFunctor(int functor) {
} // namespace } // namespace
void SetDrawFnUseVulkan(bool use_vulkan) {
g_use_vulkan = use_vulkan;
}
AwDrawFnFunctionTable* GetDrawFnFunctionTable() { AwDrawFnFunctionTable* GetDrawFnFunctionTable() {
static AwDrawFnFunctionTable table{kAwDrawFnVersion, &QueryRenderMode, static AwDrawFnFunctionTable table{kAwDrawFnVersion, &QueryRenderMode,
&CreateFunctor, &ReleaseFunctor, &CreateFunctor, &ReleaseFunctor,
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
namespace draw_fn { namespace draw_fn {
void SetDrawFnUseVulkan(bool use_vulkan);
AwDrawFnFunctionTable* GetDrawFnFunctionTable(); AwDrawFnFunctionTable* GetDrawFnFunctionTable();
struct FunctorData { struct FunctorData {
......
...@@ -7,42 +7,45 @@ ...@@ -7,42 +7,45 @@
#include <android/native_window.h> #include <android/native_window.h>
#include <jni.h> #include <jni.h>
#include <memory>
#include "android_webview/test/shell/src/draw_fn/overlays_manager.h" #include "android_webview/test/shell/src/draw_fn/overlays_manager.h"
#include "base/android/scoped_java_ref.h" #include "base/android/scoped_java_ref.h"
typedef void* EGLContext;
typedef void* EGLSurface;
namespace draw_fn { namespace draw_fn {
class ContextManager { class ContextManager {
public: public:
ContextManager(); ContextManager();
~ContextManager(); virtual ~ContextManager();
void SetSurface(JNIEnv* env, const base::android::JavaRef<jobject>& surface); void SetSurface(JNIEnv* env,
const base::android::JavaRef<jobject>& surface,
int width,
int height);
virtual void ResizeSurface(JNIEnv* env, int width, int height) = 0;
void SetOverlaysSurface(JNIEnv* env, void SetOverlaysSurface(JNIEnv* env,
const base::android::JavaRef<jobject>& surface); const base::android::JavaRef<jobject>& surface);
void Sync(JNIEnv* env, int functor, bool apply_force_dark); void Sync(JNIEnv* env, int functor, bool apply_force_dark);
base::android::ScopedJavaLocalRef<jintArray> Draw( virtual base::android::ScopedJavaLocalRef<jintArray> Draw(
JNIEnv* env, JNIEnv* env,
int width, int width,
int height, int height,
int scroll_x, int scroll_x,
int scroll_y, int scroll_y,
jboolean readback_quadrants); jboolean readback_quadrants) = 0;
private: protected:
void CreateContext(JNIEnv* env, void CreateContext(JNIEnv* env,
const base::android::JavaRef<jobject>& surface); const base::android::JavaRef<jobject>& surface,
void DestroyContext(); int width,
void MakeCurrent(); int height);
virtual void DoCreateContext(JNIEnv* env, int width, int height) = 0;
virtual void DestroyContext() = 0;
virtual void CurrentFunctorChanged() = 0;
base::android::ScopedJavaGlobalRef<jobject> java_surface_; base::android::ScopedJavaGlobalRef<jobject> java_surface_;
ANativeWindow* native_window_ = nullptr; ANativeWindow* native_window_ = nullptr;
EGLSurface surface_ = nullptr;
EGLContext context_ = nullptr;
int current_functor_ = 0; int current_functor_ = 0;
......
...@@ -20,6 +20,7 @@ bool AreOverlaysSupported() { ...@@ -20,6 +20,7 @@ bool AreOverlaysSupported() {
} }
OverlaysManager::ScopedCurrentFunctorCall* g_current_functor_call = nullptr; OverlaysManager::ScopedCurrentFunctorCall* g_current_functor_call = nullptr;
} // namespace } // namespace
class OverlaysManager::ScopedCurrentFunctorCall { class OverlaysManager::ScopedCurrentFunctorCall {
...@@ -67,17 +68,33 @@ class OverlaysManager::ScopedCurrentFunctorCall { ...@@ -67,17 +68,33 @@ class OverlaysManager::ScopedCurrentFunctorCall {
ANativeWindow* native_window_; ANativeWindow* native_window_;
}; };
template <typename T>
void SetDrawParams(T& params, bool has_window) {
params.overlays_mode = (AreOverlaysSupported() && has_window)
? AW_DRAW_FN_OVERLAYS_MODE_ENABLED
: AW_DRAW_FN_OVERLAYS_MODE_DISABLED;
params.get_surface_control =
OverlaysManager::ScopedCurrentFunctorCall::GetSurfaceControlFn;
params.merge_transaction =
OverlaysManager::ScopedCurrentFunctorCall::MergeTransactionFn;
}
OverlaysManager::ScopedDraw::ScopedDraw(OverlaysManager& manager, OverlaysManager::ScopedDraw::ScopedDraw(OverlaysManager& manager,
FunctorData& functor, FunctorData& functor,
AwDrawFn_DrawGLParams& params) AwDrawFn_DrawGLParams& params)
: scoped_functor_call_( : scoped_functor_call_(
std::make_unique<ScopedCurrentFunctorCall>(functor, std::make_unique<ScopedCurrentFunctorCall>(functor,
manager.native_window_)) { manager.native_window_)) {
params.overlays_mode = (AreOverlaysSupported() && manager.native_window_) SetDrawParams(params, !!manager.native_window_);
? AW_DRAW_FN_OVERLAYS_MODE_ENABLED }
: AW_DRAW_FN_OVERLAYS_MODE_DISABLED;
params.get_surface_control = ScopedCurrentFunctorCall::GetSurfaceControlFn; OverlaysManager::ScopedDraw::ScopedDraw(OverlaysManager& manager,
params.merge_transaction = ScopedCurrentFunctorCall::MergeTransactionFn; FunctorData& functor,
AwDrawFn_DrawVkParams& params)
: scoped_functor_call_(
std::make_unique<ScopedCurrentFunctorCall>(functor,
manager.native_window_)) {
SetDrawParams(params, !!manager.native_window_);
} }
OverlaysManager::ScopedDraw::~ScopedDraw() = default; OverlaysManager::ScopedDraw::~ScopedDraw() = default;
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "ui/gfx/android/android_surface_control_compat.h" #include "ui/gfx/android/android_surface_control_compat.h"
struct AwDrawFn_DrawGLParams; struct AwDrawFn_DrawGLParams;
struct AwDrawFn_DrawVkParams;
namespace draw_fn { namespace draw_fn {
...@@ -25,6 +26,9 @@ class OverlaysManager { ...@@ -25,6 +26,9 @@ class OverlaysManager {
ScopedDraw(OverlaysManager& manager, ScopedDraw(OverlaysManager& manager,
FunctorData& functor, FunctorData& functor,
AwDrawFn_DrawGLParams& params); AwDrawFn_DrawGLParams& params);
ScopedDraw(OverlaysManager& manager,
FunctorData& functor,
AwDrawFn_DrawVkParams& params);
~ScopedDraw(); ~ScopedDraw();
private: private:
......
...@@ -113,6 +113,7 @@ public class AwShellActivity extends Activity { ...@@ -113,6 +113,7 @@ public class AwShellActivity extends Activity {
} }
private AwTestContainerView createAwTestContainerView() { private AwTestContainerView createAwTestContainerView() {
AwTestContainerView.installDrawFnFunctionTable(/*useVulkan=*/false);
AwBrowserProcess.start(); AwBrowserProcess.start();
AwTestContainerView testContainerView = new AwTestContainerView(this, true); AwTestContainerView testContainerView = new AwTestContainerView(this, true);
AwContentsClient awContentsClient = new NullContentsClient() { AwContentsClient awContentsClient = new NullContentsClient() {
......
...@@ -11,22 +11,27 @@ import org.chromium.base.annotations.JNINamespace; ...@@ -11,22 +11,27 @@ import org.chromium.base.annotations.JNINamespace;
/** draw_fn framework side implementation for tests. */ /** draw_fn framework side implementation for tests. */
@JNINamespace("draw_fn") @JNINamespace("draw_fn")
public class ContextManager { public class ContextManager {
private static boolean sUseVulkan;
private Surface mCurrentSurface; private Surface mCurrentSurface;
public static long getDrawFnFunctionTable() { public static long getDrawFnFunctionTable(boolean useVulkan) {
return nativeGetDrawFnFunctionTable(); sUseVulkan = useVulkan;
return nativeGetDrawFnFunctionTable(useVulkan);
} }
private final long mNativeContextManager; private final long mNativeContextManager;
public ContextManager() { public ContextManager() {
mNativeContextManager = nativeInit(); mNativeContextManager = nativeInit(sUseVulkan);
} }
public void setSurface(Surface surface) { public void setSurface(Surface surface, int width, int height) {
if (mCurrentSurface == surface) return; if (mCurrentSurface == surface) {
if (surface != null) nativeResizeSurface(mNativeContextManager, width, height);
return;
}
mCurrentSurface = surface; mCurrentSurface = surface;
nativeSetSurface(mNativeContextManager, surface); nativeSetSurface(mNativeContextManager, surface, width, height);
} }
public void setOverlaysSurface(Surface surface) { public void setOverlaysSurface(Surface surface) {
...@@ -43,9 +48,12 @@ public class ContextManager { ...@@ -43,9 +48,12 @@ public class ContextManager {
mNativeContextManager, width, height, scrollX, scrollY, readbackQuadrants); mNativeContextManager, width, height, scrollX, scrollY, readbackQuadrants);
} }
private static native long nativeGetDrawFnFunctionTable(); private static native long nativeGetDrawFnFunctionTable(boolean useVulkan);
private static native long nativeInit(); private static native long nativeInit(boolean useVulkan);
private static native void nativeSetSurface(long nativeContextManager, Surface surface); private static native void nativeSetSurface(
long nativeContextManager, Surface surface, int width, int height);
private static native void nativeResizeSurface(
long nativeContextManager, int width, int height);
private static native void nativeSetOverlaysSurface(long nativeContextManager, Surface surface); private static native void nativeSetOverlaysSurface(long nativeContextManager, Surface surface);
private static native void nativeSync( private static native void nativeSync(
long nativeContextManager, int functor, boolean applyForceDark); long nativeContextManager, int functor, boolean applyForceDark);
......
...@@ -75,6 +75,10 @@ public class AwTestContainerView extends FrameLayout { ...@@ -75,6 +75,10 @@ public class AwTestContainerView extends FrameLayout {
} }
} }
public static void installDrawFnFunctionTable(boolean useVulkan) {
AwDrawFnImpl.setDrawFnFunctionTable(ContextManager.getDrawFnFunctionTable(useVulkan));
}
private class HardwareView extends SurfaceView implements SurfaceHolder.Callback { private class HardwareView extends SurfaceView implements SurfaceHolder.Callback {
// Only accessed on UI thread. // Only accessed on UI thread.
private int mWidth; private int mWidth;
...@@ -145,7 +149,8 @@ public class AwTestContainerView extends FrameLayout { ...@@ -145,7 +149,8 @@ public class AwTestContainerView extends FrameLayout {
mHaveSurface = true; mHaveSurface = true;
Surface surface = holder.getSurface(); Surface surface = holder.getSurface();
sRenderThreadHandler.post(() -> { mContextManager.setSurface(surface); }); sRenderThreadHandler.post(
() -> { mContextManager.setSurface(surface, width, height); });
if (mReadyToRenderCallback != null) { if (mReadyToRenderCallback != null) {
mReadyToRenderCallback.run(); mReadyToRenderCallback.run();
...@@ -168,7 +173,7 @@ public class AwTestContainerView extends FrameLayout { ...@@ -168,7 +173,7 @@ public class AwTestContainerView extends FrameLayout {
mHaveSurface = false; mHaveSurface = false;
WaitableEvent event = new WaitableEvent(); WaitableEvent event = new WaitableEvent();
sRenderThreadHandler.post(() -> { sRenderThreadHandler.post(() -> {
mContextManager.setSurface(null); mContextManager.setSurface(null, 0, 0);
event.signal(); event.signal();
}); });
event.waitForEvent(); event.waitForEvent();
...@@ -230,9 +235,6 @@ public class AwTestContainerView extends FrameLayout { ...@@ -230,9 +235,6 @@ public class AwTestContainerView extends FrameLayout {
public void initialize(AwContents awContents) { public void initialize(AwContents awContents) {
mAwContents = awContents; mAwContents = awContents;
if (isBackedByHardwareView()) {
AwDrawFnImpl.setDrawFnFunctionTable(ContextManager.getDrawFnFunctionTable());
}
} }
public void setWindowVisibleDisplayFrameOverride(Rect rect) { public void setWindowVisibleDisplayFrameOverride(Rect rect) {
......
...@@ -52,6 +52,7 @@ public class SecondBrowserProcess extends Service { ...@@ -52,6 +52,7 @@ public class SecondBrowserProcess extends Service {
private void startBrowserProcess() { private void startBrowserProcess() {
AwResource.setResources(this.getResources()); AwResource.setResources(this.getResources());
AwResource.setConfigKeySystemUuidMapping(R.array.config_key_system_uuid_mapping); AwResource.setConfigKeySystemUuidMapping(R.array.config_key_system_uuid_mapping);
AwTestContainerView.installDrawFnFunctionTable(/*useVulkan=*/false);
AwBrowserProcess.loadLibrary(null); AwBrowserProcess.loadLibrary(null);
AwBrowserProcess.start(); AwBrowserProcess.start();
} }
......
...@@ -68,7 +68,6 @@ bool VulkanSwapChain::Initialize( ...@@ -68,7 +68,6 @@ bool VulkanSwapChain::Initialize(
DCHECK(device_queue); DCHECK(device_queue);
DCHECK(!use_protected_memory || device_queue->allow_protected_memory()); DCHECK(!use_protected_memory || device_queue->allow_protected_memory());
task_runner_ = base::ThreadTaskRunnerHandle::Get();
use_protected_memory_ = use_protected_memory; use_protected_memory_ = use_protected_memory;
device_queue_ = device_queue; device_queue_ = device_queue;
is_incremental_present_supported_ = is_incremental_present_supported_ =
...@@ -146,7 +145,7 @@ void VulkanSwapChain::PostSubBufferAsync( ...@@ -146,7 +145,7 @@ void VulkanSwapChain::PostSubBufferAsync(
DCHECK(!has_pending_post_sub_buffer_); DCHECK(!has_pending_post_sub_buffer_);
if (UNLIKELY(!PresentBuffer(rect))) { if (UNLIKELY(!PresentBuffer(rect))) {
task_runner_->PostTask( base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, FROM_HERE,
base::BindOnce(std::move(callback), gfx::SwapResult::SWAP_FAILED)); base::BindOnce(std::move(callback), gfx::SwapResult::SWAP_FAILED));
return; return;
...@@ -158,18 +157,21 @@ void VulkanSwapChain::PostSubBufferAsync( ...@@ -158,18 +157,21 @@ void VulkanSwapChain::PostSubBufferAsync(
post_sub_buffer_task_runner_->PostTask( post_sub_buffer_task_runner_->PostTask(
FROM_HERE, FROM_HERE,
base::BindOnce( base::BindOnce(
[](VulkanSwapChain* self, PostSubBufferCompletionCallback callback) { [](VulkanSwapChain* self,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
PostSubBufferCompletionCallback callback) {
base::AutoLock auto_lock(self->lock_); base::AutoLock auto_lock(self->lock_);
DCHECK(self->has_pending_post_sub_buffer_); DCHECK(self->has_pending_post_sub_buffer_);
auto swap_result = self->AcquireNextImage() auto swap_result = self->AcquireNextImage()
? gfx::SwapResult::SWAP_ACK ? gfx::SwapResult::SWAP_ACK
: gfx::SwapResult::SWAP_FAILED; : gfx::SwapResult::SWAP_FAILED;
self->task_runner_->PostTask( task_runner->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), swap_result)); FROM_HERE, base::BindOnce(std::move(callback), swap_result));
self->has_pending_post_sub_buffer_ = false; self->has_pending_post_sub_buffer_ = false;
self->condition_variable_.Signal(); self->condition_variable_.Signal();
}, },
base::Unretained(this), std::move(callback))); base::Unretained(this), base::ThreadTaskRunnerHandle::Get(),
std::move(callback)));
} }
bool VulkanSwapChain::InitializeSwapChain( bool VulkanSwapChain::InitializeSwapChain(
......
...@@ -23,10 +23,6 @@ ...@@ -23,10 +23,6 @@
#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size.h"
#include "ui/gfx/swap_result.h" #include "ui/gfx/swap_result.h"
namespace base {
class SingleThreadTaskRunner;
}
namespace gpu { namespace gpu {
class VulkanDeviceQueue; class VulkanDeviceQueue;
...@@ -190,9 +186,6 @@ class COMPONENT_EXPORT(VULKAN) VulkanSwapChain { ...@@ -190,9 +186,6 @@ class COMPONENT_EXPORT(VULKAN) VulkanSwapChain {
bool destroy_swapchain_will_hang_ = false; bool destroy_swapchain_will_hang_ = false;
// For executing task on GPU main thread.
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
// For executing PosSubBufferAsync tasks off the GPU main thread. // For executing PosSubBufferAsync tasks off the GPU main thread.
scoped_refptr<base::SequencedTaskRunner> post_sub_buffer_task_runner_; scoped_refptr<base::SequencedTaskRunner> post_sub_buffer_task_runner_;
......
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