Some more improvements/fixes to the VulkanViewer

* display GM name in title bar
* add ms timer for update loop
* add ms/frame meter
* fix vsync
* add some notes for later

GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1873453002

Review URL: https://codereview.chromium.org/1873453002
This commit is contained in:
jvanverth 2016-04-07 11:09:51 -07:00 committed by Commit bot
parent 312398159c
commit 3d6ed3ae75
10 changed files with 95 additions and 19 deletions

View File

@ -24,6 +24,7 @@
'../src/gpu', '../src/gpu',
'../src/images', '../src/images',
'../src/image', '../src/image',
'../tools/timer',
], ],
'sources': [ 'sources': [
'../gm/gm.cpp', '../gm/gm.cpp',

View File

@ -14,7 +14,7 @@ public:
virtual ~Application() {} virtual ~Application() {}
virtual void onIdle(float dt) = 0; virtual void onIdle(double ms) = 0;
}; };
#endif #endif

View File

@ -66,7 +66,7 @@ void VulkanTestContext::initializeContext(void* platformData) {
break; break;
} }
} }
SkASSERT(0 <= fPresentQueueIndex && fPresentQueueIndex < queueCount); SkASSERT(fPresentQueueIndex < queueCount);
VkBool32 supported; VkBool32 supported;
VkResult res = GR_VK_CALL(fBackendContext->fInterface, VkResult res = GR_VK_CALL(fBackendContext->fInterface,
@ -184,13 +184,14 @@ bool VulkanTestContext::createSwapchain(uint32_t width, uint32_t height)
VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR : VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR :
VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
// FIFO is the only mode universally supported // If mailbox mode is available, use it, as it is the lowest-latency non-
// tearing mode. If not, fall back to FIFO which is always available.
VkPresentModeKHR mode = VK_PRESENT_MODE_FIFO_KHR; VkPresentModeKHR mode = VK_PRESENT_MODE_FIFO_KHR;
bool vsync = false;
for (uint32_t i = 0; i < presentModeCount; ++i) { for (uint32_t i = 0; i < presentModeCount; ++i) {
if ((vsync && VK_PRESENT_MODE_MAILBOX_KHR == presentModes[i]) || // use mailbox
(!vsync && VK_PRESENT_MODE_IMMEDIATE_KHR == presentModes[i])) { if (VK_PRESENT_MODE_MAILBOX_KHR == presentModes[i]) {
mode = presentModes[i]; mode = presentModes[i];
break;
} }
} }
@ -447,9 +448,10 @@ SkSurface* VulkanTestContext::getBackbufferSurface() {
&backbuffer->fImageIndex)); &backbuffer->fImageIndex));
if (VK_ERROR_SURFACE_LOST_KHR == res) { if (VK_ERROR_SURFACE_LOST_KHR == res) {
// need to figure out how to create a new vkSurface without the platformData* // need to figure out how to create a new vkSurface without the platformData*
// maybe use attach somehow? but need a Window
return nullptr; return nullptr;
} }
if (VK_ERROR_OUT_OF_DATE_KHR == res || VK_ERROR_SURFACE_LOST_KHR == res) { if (VK_ERROR_OUT_OF_DATE_KHR == res) {
// tear swapchain down and try again // tear swapchain down and try again
if (!this->createSwapchain(0, 0)) { if (!this->createSwapchain(0, 0)) {
return nullptr; return nullptr;

View File

@ -61,6 +61,8 @@ void Window::onPaint() {
canvas->flush(); canvas->flush();
fTestContext->swapBuffers(); fTestContext->swapBuffers();
} else {
// try recreating testcontext
} }
} }

View File

@ -27,12 +27,12 @@ public:
int fStencilBits; int fStencilBits;
}; };
enum BackEndTypes { enum BackEndType {
kNativeGL_BackendType, kNativeGL_BackendType,
kVulkan_BackendType kVulkan_BackendType
}; };
virtual bool attach(BackEndTypes attachType, int msaaSampleCount, AttachmentInfo*) = 0; virtual bool attach(BackEndType attachType, int msaaSampleCount, AttachmentInfo*) = 0;
void detach(); void detach();
// input handling // input handling

View File

@ -31,8 +31,10 @@ static void on_paint_handler(SkCanvas* canvas, void* userData) {
return vv->onPaint(canvas); return vv->onPaint(canvas);
} }
VulkanViewer::VulkanViewer(int argc, char** argv, void* platformData) : VulkanViewer::VulkanViewer(int argc, char** argv, void* platformData)
fGMs(skiagm::GMRegistry::Head()){ : fGMs(skiagm::GMRegistry::Head())
, fCurrentMeasurement(0) {
memset(fMeasurements, 0, sizeof(fMeasurements));
fWindow = Window::CreateNativeWindow(platformData); fWindow = Window::CreateNativeWindow(platformData);
fWindow->attach(Window::kVulkan_BackendType, 0, nullptr); fWindow->attach(Window::kVulkan_BackendType, 0, nullptr);
@ -41,7 +43,10 @@ VulkanViewer::VulkanViewer(int argc, char** argv, void* platformData) :
fWindow->registerKeyFunc(on_key_handler, this); fWindow->registerKeyFunc(on_key_handler, this);
fWindow->registerPaintFunc(on_paint_handler, this); fWindow->registerPaintFunc(on_paint_handler, this);
fWindow->setTitle("VulkanViewer"); SkAutoTDelete<skiagm::GM> gm(fGMs->factory()(nullptr));
SkString title("VulkanViewer: ");
title.append(gm->getName());
fWindow->setTitle(title.c_str());
fWindow->show(); fWindow->show();
} }
@ -54,6 +59,10 @@ bool VulkanViewer::onKey(Window::Key key, Window::InputState state, uint32_t mod
if (Window::kDown_InputState == state && (modifiers & Window::kFirstPress_ModifierKey) && if (Window::kDown_InputState == state && (modifiers & Window::kFirstPress_ModifierKey) &&
key == Window::kRight_Key) { key == Window::kRight_Key) {
fGMs = fGMs->next(); fGMs = fGMs->next();
SkAutoTDelete<skiagm::GM> gm(fGMs->factory()(nullptr));
SkString title("VulkanViewer: ");
title.append(gm->getName());
fWindow->setTitle(title.c_str());
} }
return true; return true;
@ -63,12 +72,59 @@ void VulkanViewer::onPaint(SkCanvas* canvas) {
SkAutoTDelete<skiagm::GM> gm(fGMs->factory()(nullptr)); SkAutoTDelete<skiagm::GM> gm(fGMs->factory()(nullptr));
canvas->save(); canvas->save();
gm->draw(canvas); gm->draw(canvas);
canvas->restore();
drawStats(canvas);
}
void VulkanViewer::drawStats(SkCanvas* canvas) {
static const float kPixelPerMS = 2.0f;
static const int kDisplayWidth = 130;
static const int kDisplayHeight = 100;
static const int kDisplayPadding = 10;
static const int kGraphPadding = 3;
static const SkScalar kBaseMS = 1000.f / 60.f; // ms/frame to hit 60 fps
SkISize canvasSize = canvas->getDeviceSize();
SkRect rect = SkRect::MakeXYWH(SkIntToScalar(canvasSize.fWidth-kDisplayWidth-kDisplayPadding),
SkIntToScalar(kDisplayPadding),
SkIntToScalar(kDisplayWidth), SkIntToScalar(kDisplayHeight));
SkPaint paint;
canvas->save();
canvas->clipRect(rect);
paint.setColor(SK_ColorBLACK);
canvas->drawRect(rect, paint);
// draw the 16ms line
paint.setColor(SK_ColorLTGRAY);
canvas->drawLine(rect.fLeft, rect.fBottom - kBaseMS*kPixelPerMS,
rect.fRight, rect.fBottom - kBaseMS*kPixelPerMS, paint);
paint.setColor(SK_ColorRED);
paint.setStyle(SkPaint::kStroke_Style);
canvas->drawRect(rect, paint);
int x = SkScalarTruncToInt(rect.fLeft) + kGraphPadding;
const int xStep = 2;
const int startY = SkScalarTruncToInt(rect.fBottom);
int i = fCurrentMeasurement;
do {
int endY = startY - (int)(fMeasurements[i] * kPixelPerMS + 0.5); // round to nearest value
canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY),
SkIntToScalar(x), SkIntToScalar(endY), paint);
i++;
i &= (kMeasurementCount - 1); // fast mod
x += xStep;
} while (i != fCurrentMeasurement);
canvas->restore(); canvas->restore();
} }
void VulkanViewer::onIdle(float dt) { void VulkanViewer::onIdle(double ms) {
// Record measurements
fMeasurements[fCurrentMeasurement++] = ms;
fCurrentMeasurement &= (kMeasurementCount - 1); // fast mod
SkASSERT(fCurrentMeasurement < kMeasurementCount);
fWindow->onPaint(); fWindow->onPaint();
} }

View File

@ -22,11 +22,17 @@ public:
bool onKey(Window::Key key, Window::InputState state, uint32_t modifiers); bool onKey(Window::Key key, Window::InputState state, uint32_t modifiers);
void onPaint(SkCanvas* canvas); void onPaint(SkCanvas* canvas);
void onIdle(float dt) override; void onIdle(double ms) override;
private: private:
void drawStats(SkCanvas* canvas);
Window* fWindow; Window* fWindow;
static const int kMeasurementCount = 64; // should be power of 2 for fast mod
double fMeasurements[kMeasurementCount];
int fCurrentMeasurement;
const skiagm::GMRegistry* fGMs; const skiagm::GMRegistry* fGMs;
}; };

View File

@ -262,7 +262,7 @@ void Window_win::show() {
} }
bool Window_win::attach(BackEndTypes attachType, int msaaSampleCount, AttachmentInfo*) { bool Window_win::attach(BackEndType attachType, int msaaSampleCount, AttachmentInfo*) {
if (kVulkan_BackendType != attachType) { if (kVulkan_BackendType != attachType) {
return false; return false;
} }

View File

@ -21,7 +21,7 @@ public:
void setTitle(const char*) override; void setTitle(const char*) override;
void show() override; void show() override;
bool attach(BackEndTypes attachType, int msaaSampleCount, AttachmentInfo*) override; bool attach(BackEndType attachType, int msaaSampleCount, AttachmentInfo*) override;
private: private:
HINSTANCE fHInstance; HINSTANCE fHInstance;

View File

@ -9,6 +9,7 @@
#include <tchar.h> #include <tchar.h>
#include "SkTypes.h" #include "SkTypes.h"
#include "Timer.h"
#include "Window_win.h" #include "Window_win.h"
#include "../Application.h" #include "../Application.h"
@ -24,6 +25,8 @@ static char* tchar_to_utf8(const TCHAR* str) {
#endif #endif
} }
static double now_ms() { return SkTime::GetNSecs() * 1e-6; }
// This file can work with GUI or CONSOLE subsystem types since we define _tWinMain and main(). // This file can work with GUI or CONSOLE subsystem types since we define _tWinMain and main().
static int main_common(HINSTANCE hInstance, int show, int argc, char**argv); static int main_common(HINSTANCE hInstance, int show, int argc, char**argv);
@ -60,6 +63,10 @@ static int main_common(HINSTANCE hInstance, int show, int argc, char**argv) {
Application* app = Application::Create(argc, argv, (void*)hInstance); Application* app = Application::Create(argc, argv, (void*)hInstance);
MSG msg = { 0 }; MSG msg = { 0 };
double currentTime = 0.0;
double previousTime = 0.0;
// Main message loop // Main message loop
while (WM_QUIT != msg.message) { while (WM_QUIT != msg.message) {
if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
@ -67,7 +74,9 @@ static int main_common(HINSTANCE hInstance, int show, int argc, char**argv) {
DispatchMessage(&msg); DispatchMessage(&msg);
} }
app->onIdle(0.0f); previousTime = currentTime;
currentTime = now_ms();
app->onIdle(currentTime - previousTime);
} }
delete app; delete app;