Commit 19159489 authored by Peng Huang's avatar Peng Huang Committed by Commit Bot

Add a vulkan demo for testing and debugging gpu vulkan code with skia

Bug: 866914
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel
Change-Id: Ib5c6351cbad98221447e5218e54e4feeefb8e692
Reviewed-on: https://chromium-review.googlesource.com/1184968Reviewed-by: default avatarVictor Miura <vmiura@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Commit-Queue: Peng Huang <penghuang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#586109}
parent 811a4303
...@@ -25,6 +25,7 @@ import("//ui/webui/webui_features.gni") ...@@ -25,6 +25,7 @@ import("//ui/webui/webui_features.gni")
import("//ui/ozone/ozone.gni") import("//ui/ozone/ozone.gni")
import("//v8/gni/v8.gni") import("//v8/gni/v8.gni")
import("//v8/snapshot_toolchain.gni") import("//v8/snapshot_toolchain.gni")
import("//gpu/vulkan/features.gni")
if (is_android) { if (is_android) {
import("//build/config/android/config.gni") import("//build/config/android/config.gni")
...@@ -739,6 +740,10 @@ group("gn_all") { ...@@ -739,6 +740,10 @@ group("gn_all") {
"//webrunner:webrunner_unittests", "//webrunner:webrunner_unittests",
] ]
} }
if (enable_vulkan) {
deps += [ "//gpu/vulkan/demo" ]
}
} }
if (is_fuchsia) { if (is_fuchsia) {
......
# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//gpu/vulkan/features.gni")
import("//build/config/ui.gni")
import("//build/buildflag_header.gni")
assert(enable_vulkan)
# TODO(cblume): These tests should run on each platform -- crbug.com/858614
group("demo") {
if (use_x11) {
deps = [
":vulkan_demo",
]
}
}
if (use_x11) {
executable("vulkan_demo") {
sources = [
"main.cc",
"vulkan_demo.cc",
"vulkan_demo.h",
]
deps = [
"//base",
"//components/tracing:startup_tracing",
"//components/viz/common",
"//gpu/vulkan/init",
"//ui/display/types",
"//ui/events",
"//ui/events/platform",
"//ui/events/platform/x11",
"//ui/gfx:native_widget_types",
"//ui/gfx/geometry",
"//ui/platform_window:platform_window",
"//ui/platform_window/x11",
]
deps += [ "//ui/gfx/x" ]
configs += [ "//build/config/linux:x11" ]
}
}
include_rules = [
"+components/tracing",
"+components/viz",
"+third_party/skia",
"+ui",
]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <memory>
#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/debug/stack_trace.h"
#include "base/message_loop/message_loop.h"
#include "base/task/task_scheduler/task_scheduler.h"
#include "base/trace_event/trace_event.h"
#include "components/tracing/common/trace_to_console.h"
#include "components/tracing/common/tracing_switches.h"
#include "gpu/vulkan/demo/vulkan_demo.h"
int main(int argc, char** argv) {
base::CommandLine::Init(argc, argv);
base::AtExitManager exit_manager;
base::debug::EnableInProcessStackDumping();
// Initialize logging so we can enable VLOG messages.
logging::LoggingSettings settings;
logging::InitLogging(settings);
// Initialize tracing.
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kTraceToConsole)) {
base::trace_event::TraceConfig trace_config =
tracing::GetConfigForTraceToConsole();
base::trace_event::TraceLog::GetInstance()->SetEnabled(
trace_config, base::trace_event::TraceLog::RECORDING_MODE);
}
// Build UI thread message loop. This is used by platform
// implementations for event polling & running background tasks.
base::MessageLoopForUI message_loop;
base::TaskScheduler::CreateAndStartWithDefaultParams("VulkanDemo");
gpu::VulkanDemo vulkan_demo;
vulkan_demo.Initialize();
vulkan_demo.Run();
vulkan_demo.Destroy();
return 0;
}
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "gpu/vulkan/demo/vulkan_demo.h"
#include "base/bind.h"
#include "base/run_loop.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/viz/common/gpu/vulkan_in_process_context_provider.h"
#include "gpu/vulkan/init/vulkan_factory.h"
#include "gpu/vulkan/vulkan_implementation.h"
#include "gpu/vulkan/vulkan_surface.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
#include "third_party/skia/include/gpu/GrBackendSurface.h"
#include "third_party/skia/include/gpu/GrContext.h"
#include "ui/events/platform/platform_event_source.h"
#include "ui/platform_window/x11/x11_window.h"
namespace gpu {
VulkanDemo::VulkanDemo() = default;
VulkanDemo::~VulkanDemo() = default;
void VulkanDemo::Initialize() {
vulkan_implementation_ = gpu::CreateVulkanImplementation();
DCHECK(vulkan_implementation_) << ":Failed to create vulkan implementation.";
auto result = vulkan_implementation_->InitializeVulkanInstance();
DCHECK(result) << "Failed to initialize vulkan implementation.";
vulkan_context_provider_ =
viz::VulkanInProcessContextProvider::Create(vulkan_implementation_.get());
DCHECK(vulkan_context_provider_)
<< "Failed to create vulkan context provider.";
event_source_ = ui::PlatformEventSource::CreateDefault();
window_ = std::make_unique<ui::X11Window>(
this, gfx::Rect(gfx::Point(100, 100), size_));
window_->Show();
}
void VulkanDemo::Destroy() {
vulkan_surface_->Destroy();
}
void VulkanDemo::Run() {
DCHECK(!is_running_);
DCHECK(!run_loop_);
base::RunLoop run_loop;
is_running_ = true;
run_loop_ = &run_loop;
RenderFrame();
run_loop.Run();
run_loop_ = nullptr;
}
void VulkanDemo::OnBoundsChanged(const gfx::Rect& new_bounds) {
if (size_ == new_bounds.size())
return;
NOTIMPLEMENTED();
}
void VulkanDemo::OnCloseRequest() {
is_running_ = false;
if (run_loop_)
run_loop_->QuitWhenIdle();
}
void VulkanDemo::OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) {
DCHECK_EQ(accelerated_widget_, gfx::kNullAcceleratedWidget);
accelerated_widget_ = widget;
vulkan_surface_ =
vulkan_implementation_->CreateViewSurface(accelerated_widget_);
DCHECK(vulkan_surface_);
auto result =
vulkan_surface_->Initialize(vulkan_context_provider_->GetDeviceQueue(),
gpu::VulkanSurface::DEFAULT_SURFACE_FORMAT);
DCHECK(result) << "Failed to initialize vulkan surface.";
}
void VulkanDemo::CreateSkSurface() {
SkSurfaceProps surface_props =
SkSurfaceProps(0, SkSurfaceProps::kLegacyFontHost_InitType);
auto* swap_chain = vulkan_surface_->GetSwapChain();
VkImage vk_image = swap_chain->GetCurrentImage(swap_chain->current_image());
GrVkImageInfo vk_image_info;
vk_image_info.fImage = vk_image;
vk_image_info.fAlloc = {VK_NULL_HANDLE, 0, 0, 0};
vk_image_info.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
vk_image_info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
vk_image_info.fFormat = VK_FORMAT_B8G8R8A8_UNORM;
vk_image_info.fLevelCount = 1;
GrBackendRenderTarget render_target(size_.width(), size_.height(), 0, 0,
vk_image_info);
sk_surface_ = SkSurface::MakeFromBackendRenderTarget(
vulkan_context_provider_->GetGrContext(), render_target,
kTopLeft_GrSurfaceOrigin, kBGRA_8888_SkColorType, nullptr,
&surface_props);
}
void VulkanDemo::Draw(SkCanvas* canvas, float fraction) {
canvas->clear(SkColorSetARGB(255, 255 * fraction, 255 * (1 - fraction), 0));
SkPaint paint;
paint.setColor(SK_ColorRED);
// Draw a rectangle with red paint
SkRect rect = SkRect::MakeXYWH(10, 10, 128, 128);
canvas->drawRect(rect, paint);
// Set up a linear gradient and draw a circle
{
SkPoint linearPoints[] = {{0, 0}, {300, 300}};
SkColor linearColors[] = {SK_ColorGREEN, SK_ColorBLACK};
paint.setShader(SkGradientShader::MakeLinear(
linearPoints, linearColors, nullptr, 2, SkShader::kMirror_TileMode));
paint.setAntiAlias(true);
canvas->drawCircle(200, 200, 64, paint);
// Detach shader
paint.setShader(nullptr);
}
// Draw a message with a nice black paint
paint.setSubpixelText(true);
paint.setColor(SK_ColorBLACK);
paint.setTextSize(32);
canvas->save();
static const char message[] = "Hello Vulkan";
// Translate and rotate
canvas->translate(300, 300);
rotation_angle_ += 0.2f;
if (rotation_angle_ > 360) {
rotation_angle_ -= 360;
}
canvas->rotate(rotation_angle_);
// Draw the text
canvas->drawText(message, strlen(message), 0, 0, paint);
canvas->restore();
canvas->flush();
}
void VulkanDemo::RenderFrame() {
if (!is_running_)
return;
CreateSkSurface();
Draw(sk_surface_->getCanvas(), 0.7);
vulkan_surface_->SwapBuffers();
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&VulkanDemo::RenderFrame, base::Unretained(this)));
}
} // namespace gpu
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef GPU_VULKAN_DEMO_VULKAN_DEMO_H_
#define GPU_VULKAN_DEMO_VULKAN_DEMO_H_
#include <memory>
#include "base/memory/scoped_refptr.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "ui/gfx/geometry/size.h"
#include "ui/platform_window/platform_window_delegate.h"
class SkCanvas;
class SkSurface;
namespace base {
class RunLoop;
}
namespace viz {
class VulkanContextProvider;
}
namespace ui {
class PlatformEventSource;
class PlatformWindow;
} // namespace ui
namespace gpu {
class VulkanImplementation;
class VulkanSurface;
class VulkanDemo : public ui::PlatformWindowDelegate {
public:
VulkanDemo();
~VulkanDemo() override;
void Initialize();
void Destroy();
void Run();
private:
// ui::PlatformWindowDelegate:
void OnBoundsChanged(const gfx::Rect& new_bounds) override;
void OnDamageRect(const gfx::Rect& damaged_region) override {}
void DispatchEvent(ui::Event* event) override {}
void OnCloseRequest() override;
void OnClosed() override {}
void OnWindowStateChanged(ui::PlatformWindowState new_state) override {}
void OnLostCapture() override {}
void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) override;
void OnAcceleratedWidgetDestroyed() override {}
void OnActivationChanged(bool active) override {}
void CreateSkSurface();
void Draw(SkCanvas* canvas, float fraction);
void RenderFrame();
gfx::Size size_ = gfx::Size(800, 600);
std::unique_ptr<gpu::VulkanImplementation> vulkan_implementation_;
scoped_refptr<viz::VulkanContextProvider> vulkan_context_provider_;
gfx::AcceleratedWidget accelerated_widget_ = gfx::kNullAcceleratedWidget;
std::unique_ptr<ui::PlatformEventSource> event_source_;
std::unique_ptr<ui::PlatformWindow> window_;
std::unique_ptr<gpu::VulkanSurface> vulkan_surface_;
sk_sp<SkSurface> sk_surface_;
float rotation_angle_ = 0;
base::RunLoop* run_loop_ = nullptr;
bool is_running_ = false;
};
} // namespace gpu
#endif // GPU_VULKAN_DEMO_VULKAN_DEMO_H_
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