1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* 2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2016 Google Inc. 3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be 5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file. 6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GpuTimer.h" 9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrContextFactory.h" 10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkGr.h" 11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkCanvas.h" 13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkCommonFlags.h" 14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkCommonFlagsGpu.h" 15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkOSFile.h" 16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkOSPath.h" 17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPerlinNoiseShader.h" 18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPicture.h" 19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPictureRecorder.h" 20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkStream.h" 21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkSurface.h" 22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkSurfaceProps.h" 23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "picture_utils.h" 24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "sk_tool_utils.h" 25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "flags/SkCommandLineFlags.h" 26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "flags/SkCommonFlagsConfig.h" 27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <stdlib.h> 28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <algorithm> 29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <array> 30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <chrono> 31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <cmath> 32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <vector> 33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/** 35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * This is a minimalist program whose sole purpose is to open an skp file, benchmark it on a single 36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * config, and exit. It is intended to be used through skpbench.py rather than invoked directly. 37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Limiting the entire process to a single config/skp pair helps to keep the results repeatable. 38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * No tiling, looping, or other fanciness is used; it just draws the skp whole into a size-matched 40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * render target and syncs the GPU after each draw. 41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Currently, only GPU configs are supported. 43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEFINE_int32(duration, 5000, "number of milliseconds to run the benchmark"); 46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEFINE_int32(sampleMs, 50, "minimum duration of a sample"); 47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEFINE_bool(gpuClock, false, "time on the gpu clock (gpu work only)"); 48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEFINE_bool(fps, false, "use fps instead of ms"); 49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEFINE_string(skp, "", "path to a single .skp file, or 'warmup' for a builtin warmup run"); 50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEFINE_string(png, "", "if set, save a .png proof to disk at this file location"); 51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEFINE_int32(verbosity, 4, "level of verbosity (0=none to 5=debug)"); 52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEFINE_bool(suppressHeader, false, "don't print a header row before the results"); 53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic const char* header = 55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot" accum median max min stddev samples sample_ms clock metric config bench"; 56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic const char* resultFormat = 58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot"%8.4g %8.4g %8.4g %8.4g %6.3g%% %7li %9i %-5s %-6s %-9s %s"; 59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstruct Sample { 61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot using duration = std::chrono::nanoseconds; 62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Sample() : fFrames(0), fDuration(0) {} 64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double seconds() const { return std::chrono::duration<double>(fDuration).count(); } 65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double ms() const { return std::chrono::duration<double, std::milli>(fDuration).count(); } 66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double value() const { return FLAGS_fps ? fFrames / this->seconds() : this->ms() / fFrames; } 67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static const char* metric() { return FLAGS_fps ? "fps" : "ms"; } 68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int fFrames; 70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot duration fDuration; 71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass GpuSync { 74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic: 75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GpuSync(const sk_gpu_test::FenceSync* fenceSync); 76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ~GpuSync(); 77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void syncToPreviousFrame(); 79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate: 81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void updateFence(); 82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const sk_gpu_test::FenceSync* const fFenceSync; 84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_gpu_test::PlatformFence fFence; 85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotenum class ExitErr { 88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kOk = 0, 89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kUsage = 64, 90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kData = 65, 91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kUnavailable = 69, 92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kIO = 74, 93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kSoftware = 70 94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void draw_skp_and_flush(SkCanvas*, const SkPicture*); 97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic sk_sp<SkPicture> create_warmup_skp(); 98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool mkdir_p(const SkString& name); 99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic SkString join(const SkCommandLineFlags::StringArray&); 100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void exitf(ExitErr, const char* format, ...); 101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void run_benchmark(const sk_gpu_test::FenceSync* fenceSync, SkCanvas* canvas, 103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPicture* skp, std::vector<Sample>* samples) { 104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot using clock = std::chrono::high_resolution_clock; 105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const Sample::duration sampleDuration = std::chrono::milliseconds(FLAGS_sampleMs); 106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const clock::duration benchDuration = std::chrono::milliseconds(FLAGS_duration); 107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot draw_skp_and_flush(canvas, skp); 109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GpuSync gpuSync(fenceSync); 110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot draw_skp_and_flush(canvas, skp); 112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gpuSync.syncToPreviousFrame(); 113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot clock::time_point now = clock::now(); 115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const clock::time_point endTime = now + benchDuration; 116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot clock::time_point sampleStart = now; 119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot samples->emplace_back(); 120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Sample& sample = samples->back(); 121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot draw_skp_and_flush(canvas, skp); 124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gpuSync.syncToPreviousFrame(); 125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot now = clock::now(); 127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sample.fDuration = now - sampleStart; 128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++sample.fFrames; 129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (sample.fDuration < sampleDuration); 130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (now < endTime || 0 == samples->size() % 2); 131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void run_gpu_time_benchmark(sk_gpu_test::GpuTimer* gpuTimer, 134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const sk_gpu_test::FenceSync* fenceSync, SkCanvas* canvas, 135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPicture* skp, std::vector<Sample>* samples) { 136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot using sk_gpu_test::PlatformTimerQuery; 137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot using clock = std::chrono::steady_clock; 138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const clock::duration sampleDuration = std::chrono::milliseconds(FLAGS_sampleMs); 139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const clock::duration benchDuration = std::chrono::milliseconds(FLAGS_duration); 140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!gpuTimer->disjointSupport()) { 142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fprintf(stderr, "WARNING: GPU timer cannot detect disjoint operations; " 143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "results may be unreliable\n"); 144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot draw_skp_and_flush(canvas, skp); 147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GpuSync gpuSync(fenceSync); 148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gpuTimer->queueStart(); 150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot draw_skp_and_flush(canvas, skp); 151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot PlatformTimerQuery previousTime = gpuTimer->queueStop(); 152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gpuSync.syncToPreviousFrame(); 153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot clock::time_point now = clock::now(); 155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const clock::time_point endTime = now + benchDuration; 156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const clock::time_point sampleEndTime = now + sampleDuration; 159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot samples->emplace_back(); 160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Sample& sample = samples->back(); 161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gpuTimer->queueStart(); 164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot draw_skp_and_flush(canvas, skp); 165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot PlatformTimerQuery time = gpuTimer->queueStop(); 166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gpuSync.syncToPreviousFrame(); 167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (gpuTimer->checkQueryStatus(previousTime)) { 169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot using QueryStatus = sk_gpu_test::GpuTimer::QueryStatus; 170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case QueryStatus::kInvalid: 171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot exitf(ExitErr::kUnavailable, "GPU timer failed"); 172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case QueryStatus::kPending: 173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot exitf(ExitErr::kUnavailable, "timer query still not ready after fence sync"); 174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case QueryStatus::kDisjoint: 175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (FLAGS_verbosity >= 4) { 176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fprintf(stderr, "discarding timer query due to disjoint operations.\n"); 177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case QueryStatus::kAccurate: 180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sample.fDuration += gpuTimer->getTimeElapsed(previousTime); 181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++sample.fFrames; 182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gpuTimer->deleteQuery(previousTime); 185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot previousTime = time; 186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot now = clock::now(); 187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (now < sampleEndTime || 0 == sample.fFrames); 188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (now < endTime || 0 == samples->size() % 2); 189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gpuTimer->deleteQuery(previousTime); 191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid print_result(const std::vector<Sample>& samples, const char* config, const char* bench) { 194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (0 == (samples.size() % 2)) { 195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot exitf(ExitErr::kSoftware, "attempted to gather stats on even number of samples"); 196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Sample accum = Sample(); 199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::vector<double> values; 200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot values.reserve(samples.size()); 201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (const Sample& sample : samples) { 202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot accum.fFrames += sample.fFrames; 203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot accum.fDuration += sample.fDuration; 204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot values.push_back(sample.value()); 205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::sort(values.begin(), values.end()); 207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const double accumValue = accum.value(); 209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double variance = 0; 210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (double value : values) { 211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const double delta = value - accumValue; 212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot variance += delta * delta; 213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot variance /= values.size(); 215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Technically, this is the relative standard deviation. 216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const double stddev = 100/*%*/ * sqrt(variance) / accumValue; 217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot printf(resultFormat, accumValue, values[values.size() / 2], values.back(), values.front(), 219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot stddev, values.size(), FLAGS_sampleMs, FLAGS_gpuClock ? "gpu" : "cpu", Sample::metric(), 220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot config, bench); 221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot printf("\n"); 222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fflush(stdout); 223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotint main(int argc, char** argv) { 226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCommandLineFlags::SetUsage("Use skpbench.py instead. " 227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "You usually don't want to use this program directly."); 228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCommandLineFlags::Parse(argc, argv); 229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!FLAGS_suppressHeader) { 231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot printf("%s\n", header); 232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (FLAGS_duration <= 0) { 234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot exit(0); // This can be used to print the header and quit. 235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Parse the config. 238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkCommandLineConfigGpu* config = nullptr; // Initialize for spurious warning. 239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCommandLineConfigArray configs; 240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ParseConfigs(FLAGS_config, &configs); 241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (configs.count() != 1 || !(config = configs[0]->asConfigGpu())) { 242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot exitf(ExitErr::kUsage, "invalid config '%s': must specify one (and only one) GPU config", 243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot join(FLAGS_config).c_str()); 244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Parse the skp. 247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (FLAGS_skp.count() != 1) { 248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot exitf(ExitErr::kUsage, "invalid skp '%s': must specify a single skp file, or 'warmup'", 249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot join(FLAGS_skp).c_str()); 250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<SkPicture> skp; 252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkString skpname; 253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (0 == strcmp(FLAGS_skp[0], "warmup")) { 254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot skp = create_warmup_skp(); 255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot skpname = "warmup"; 256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* skpfile = FLAGS_skp[0]; 258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkStream> skpstream(SkStream::MakeFromFile(skpfile)); 259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!skpstream) { 260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot exitf(ExitErr::kIO, "failed to open skp file %s", skpfile); 261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot skp = SkPicture::MakeFromStream(skpstream.get()); 263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!skp) { 264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot exitf(ExitErr::kData, "failed to parse skp file %s", skpfile); 265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot skpname = SkOSPath::Basename(skpfile); 267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int width = SkTMin(SkScalarCeilToInt(skp->cullRect().width()), 2048), 269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot height = SkTMin(SkScalarCeilToInt(skp->cullRect().height()), 2048); 270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (FLAGS_verbosity >= 3 && 271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (width != skp->cullRect().width() || height != skp->cullRect().height())) { 272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fprintf(stderr, "%s is too large (%ix%i), cropping to %ix%i.\n", 273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot skpname.c_str(), SkScalarCeilToInt(skp->cullRect().width()), 274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalarCeilToInt(skp->cullRect().height()), width, height); 275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Create a context. 278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrContextOptions ctxOptions; 279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SetCtxOptionsFromCommonFlags(&ctxOptions); 280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_gpu_test::GrContextFactory factory(ctxOptions); 281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_gpu_test::ContextInfo ctxInfo = 282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot factory.getContextInfo(config->getContextType(), config->getContextOverrides()); 283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrContext* ctx = ctxInfo.grContext(); 284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!ctx) { 285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot exitf(ExitErr::kUnavailable, "failed to create context for config %s", 286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot config->getTag().c_str()); 287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (ctx->caps()->maxRenderTargetSize() < SkTMax(width, height)) { 289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot exitf(ExitErr::kUnavailable, "render target size %ix%i not supported by platform (max: %i)", 290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot width, height, ctx->caps()->maxRenderTargetSize()); 291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrPixelConfig grPixConfig = SkImageInfo2GrPixelConfig(config->getColorType(), 293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot config->getColorSpace(), 294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *ctx->caps()); 295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int supportedSampleCount = ctx->caps()->getSampleCount(config->getSamples(), grPixConfig); 296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (supportedSampleCount != config->getSamples()) { 297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot exitf(ExitErr::kUnavailable, "sample count %i not supported by platform", 298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot config->getSamples()); 299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_gpu_test::TestContext* testCtx = ctxInfo.testContext(); 301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!testCtx) { 302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot exitf(ExitErr::kSoftware, "testContext is null"); 303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!testCtx->fenceSyncSupport()) { 305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot exitf(ExitErr::kUnavailable, "GPU does not support fence sync"); 306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Create a render target. 309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkImageInfo info = 310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkImageInfo::Make(width, height, config->getColorType(), config->getAlphaType(), 311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_ref_sp(config->getColorSpace())); 312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t flags = config->getUseDIText() ? SkSurfaceProps::kUseDeviceIndependentFonts_Flag : 0; 313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType); 314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<SkSurface> surface = 315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info, config->getSamples(), &props); 316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!surface) { 317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot exitf(ExitErr::kUnavailable, "failed to create %ix%i render target for config %s", 318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot width, height, config->getTag().c_str()); 319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Run the benchmark. 322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::vector<Sample> samples; 323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (FLAGS_sampleMs > 0) { 324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // +1 because we might take one more sample in order to have an odd number. 325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot samples.reserve(1 + (FLAGS_duration + FLAGS_sampleMs - 1) / FLAGS_sampleMs); 326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot samples.reserve(2 * FLAGS_duration); 328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCanvas* canvas = surface->getCanvas(); 330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->translate(-skp->cullRect().x(), -skp->cullRect().y()); 331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!FLAGS_gpuClock) { 332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot run_benchmark(testCtx->fenceSync(), canvas, skp.get(), &samples); 333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!testCtx->gpuTimingSupport()) { 335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot exitf(ExitErr::kUnavailable, "GPU does not support timing"); 336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot run_gpu_time_benchmark(testCtx->gpuTimer(), testCtx->fenceSync(), canvas, skp.get(), 338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot &samples); 339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot print_result(samples, config->getTag().c_str(), skpname.c_str()); 341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Save a proof (if one was requested). 343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!FLAGS_png.isEmpty()) { 344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap bmp; 345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bmp.allocPixels(info); 346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!surface->getCanvas()->readPixels(bmp, 0, 0)) { 347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot exitf(ExitErr::kUnavailable, "failed to read canvas pixels for png"); 348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkString &dirname = SkOSPath::Dirname(FLAGS_png[0]), 350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot &basename = SkOSPath::Basename(FLAGS_png[0]); 351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!mkdir_p(dirname)) { 352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot exitf(ExitErr::kIO, "failed to create directory \"%s\" for png", dirname.c_str()); 353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!sk_tools::write_bitmap_to_disk(bmp, dirname, nullptr, basename)) { 355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot exitf(ExitErr::kIO, "failed to save png to \"%s\"", FLAGS_png[0]); 356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot exit(0); 360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void draw_skp_and_flush(SkCanvas* canvas, const SkPicture* skp) { 363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->drawPicture(skp); 364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->flush(); 365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic sk_sp<SkPicture> create_warmup_skp() { 368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static constexpr SkRect bounds{0, 0, 500, 500}; 369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPictureRecorder recorder; 370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCanvas* recording = recorder.beginRecording(bounds); 371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot recording->clear(SK_ColorWHITE); 373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint stroke; 375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot stroke.setStyle(SkPaint::kStroke_Style); 376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot stroke.setStrokeWidth(2); 377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Use a big path to (theoretically) warmup the CPU. 379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPath bigPath; 380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_tool_utils::make_big_path(bigPath); 381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot recording->drawPath(bigPath, stroke); 382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Use a perlin shader to warmup the GPU. 384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint perlin; 385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot perlin.setShader(SkPerlinNoiseShader::MakeTurbulence(0.1f, 0.1f, 1, 0, nullptr)); 386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot recording->drawRect(bounds, perlin); 387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return recorder.finishRecordingAsPicture(); 389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool mkdir_p(const SkString& dirname) { 392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (dirname.isEmpty()) { 393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return mkdir_p(SkOSPath::Dirname(dirname.c_str())) && sk_mkdir(dirname.c_str()); 396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic SkString join(const SkCommandLineFlags::StringArray& stringArray) { 399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkString joined; 400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < stringArray.count(); ++i) { 401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot joined.appendf(i ? " %s" : "%s", stringArray[i]); 402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return joined; 404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void exitf(ExitErr err, const char* format, ...) { 407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fprintf(stderr, ExitErr::kSoftware == err ? "INTERNAL ERROR: " : "ERROR: "); 408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot va_list args; 409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot va_start(args, format); 410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot vfprintf(stderr, format, args); 411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot va_end(args); 412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fprintf(stderr, ExitErr::kSoftware == err ? "; this should never happen.\n": ".\n"); 413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot exit((int)err); 414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGpuSync::GpuSync(const sk_gpu_test::FenceSync* fenceSync) 417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : fFenceSync(fenceSync) { 418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->updateFence(); 419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGpuSync::~GpuSync() { 422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFenceSync->deleteFence(fFence); 423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GpuSync::syncToPreviousFrame() { 426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (sk_gpu_test::kInvalidFence == fFence) { 427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot exitf(ExitErr::kSoftware, "attempted to sync with invalid fence"); 428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!fFenceSync->waitFence(fFence)) { 430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot exitf(ExitErr::kUnavailable, "failed to wait for fence"); 431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFenceSync->deleteFence(fFence); 433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->updateFence(); 434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GpuSync::updateFence() { 437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFence = fFenceSync->insertFence(); 438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (sk_gpu_test::kInvalidFence == fFence) { 439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot exitf(ExitErr::kUnavailable, "failed to insert fence"); 440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 442