Merge "Macrobenchmark tweaks & gpu memory dumping" into sc-dev

This commit is contained in:
TreeHugger Robot
2021-05-12 03:21:29 +00:00
committed by Android (Google) Code Review
11 changed files with 72 additions and 44 deletions

View File

@@ -126,6 +126,12 @@ void SkiaMemoryTracer::dumpNumericValue(const char* dumpName, const char* valueN
mCurrentValues.insert({valueName, {units, value}});
}
bool SkiaMemoryTracer::hasOutput() {
// process any remaining elements
processElement();
return mResults.size() > 0;
}
void SkiaMemoryTracer::logOutput(String8& log) {
// process any remaining elements
processElement();

View File

@@ -34,6 +34,7 @@ public:
SkiaMemoryTracer(const char* categoryKey, bool itemizeType);
~SkiaMemoryTracer() override {}
bool hasOutput();
void logOutput(String8& log);
void logTotals(String8& log);

View File

@@ -140,7 +140,6 @@ void CacheManager::dumpMemoryUsage(String8& log, const RenderState* renderState)
log.appendFormat(" Size: %.2f kB \n", SkGraphics::GetFontCacheUsed() / 1024.0f);
log.appendFormat(" Glyph Count: %d \n", SkGraphics::GetFontCacheCountUsed());
log.appendFormat("CPU Caches:\n");
std::vector<skiapipeline::ResourcePair> cpuResourceMap = {
{"skia/sk_resource_cache/bitmap_", "Bitmaps"},
{"skia/sk_resource_cache/rrect-blur_", "Masks"},
@@ -149,20 +148,20 @@ void CacheManager::dumpMemoryUsage(String8& log, const RenderState* renderState)
};
skiapipeline::SkiaMemoryTracer cpuTracer(cpuResourceMap, false);
SkGraphics::DumpMemoryStatistics(&cpuTracer);
cpuTracer.logOutput(log);
if (cpuTracer.hasOutput()) {
log.appendFormat("CPU Caches:\n");
cpuTracer.logOutput(log);
}
log.appendFormat("GPU Caches:\n");
skiapipeline::SkiaMemoryTracer gpuTracer("category", true);
mGrContext->dumpMemoryStatistics(&gpuTracer);
gpuTracer.logOutput(log);
if (gpuTracer.hasOutput()) {
log.appendFormat("GPU Caches:\n");
gpuTracer.logOutput(log);
}
log.appendFormat("Other Caches:\n");
log.appendFormat(" Current / Maximum\n");
if (renderState) {
if (renderState->mActiveLayers.size() > 0) {
log.appendFormat(" Layer Info:\n");
}
if (renderState && renderState->mActiveLayers.size() > 0) {
log.appendFormat("Layer Info:\n");
const char* layerType = Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL
? "GlLayer"

View File

@@ -249,10 +249,10 @@ uint32_t RenderProxy::frameTimePercentile(int percentile) {
});
}
void RenderProxy::dumpGraphicsMemory(int fd) {
void RenderProxy::dumpGraphicsMemory(int fd, bool includeProfileData) {
if (RenderThread::hasInstance()) {
auto& thread = RenderThread::getInstance();
thread.queue().runSync([&]() { thread.dumpGraphicsMemory(fd); });
thread.queue().runSync([&]() { thread.dumpGraphicsMemory(fd, includeProfileData); });
}
}

View File

@@ -109,7 +109,7 @@ public:
// Not exported, only used for testing
void resetProfileInfo();
uint32_t frameTimePercentile(int p);
static void dumpGraphicsMemory(int fd);
static void dumpGraphicsMemory(int fd, bool includeProfileData = true);
static void rotateProcessStatsBuffer();
static void setProcessStatsBuffer(int fd);

View File

@@ -302,30 +302,25 @@ VulkanManager& RenderThread::vulkanManager() {
return *mVkManager.get();
}
void RenderThread::dumpGraphicsMemory(int fd) {
globalProfileData()->dump(fd);
String8 cachesOutput;
String8 pipeline;
auto renderType = Properties::getRenderPipelineType();
switch (renderType) {
case RenderPipelineType::SkiaGL: {
mCacheManager->dumpMemoryUsage(cachesOutput, mRenderState);
pipeline.appendFormat("Skia (OpenGL)");
break;
}
case RenderPipelineType::SkiaVulkan: {
mCacheManager->dumpMemoryUsage(cachesOutput, mRenderState);
pipeline.appendFormat("Skia (Vulkan)");
break;
}
static const char* pipelineToString() {
switch (auto renderType = Properties::getRenderPipelineType()) {
case RenderPipelineType::SkiaGL:
return "Skia (OpenGL)";
case RenderPipelineType::SkiaVulkan:
return "Skia (Vulkan)";
default:
LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
break;
}
}
void RenderThread::dumpGraphicsMemory(int fd, bool includeProfileData) {
if (includeProfileData) {
globalProfileData()->dump(fd);
}
dprintf(fd, "\n%s\n", cachesOutput.string());
dprintf(fd, "\nPipeline=%s\n", pipeline.string());
String8 cachesOutput;
mCacheManager->dumpMemoryUsage(cachesOutput, mRenderState);
dprintf(fd, "\nPipeline=%s\n%s\n", pipelineToString(), cachesOutput.string());
}
Readback& RenderThread::readback() {

View File

@@ -150,7 +150,7 @@ public:
VulkanManager& vulkanManager();
sk_sp<Bitmap> allocateHardwareBitmap(SkBitmap& skBitmap);
void dumpGraphicsMemory(int fd);
void dumpGraphicsMemory(int fd, bool includeProfileData);
void requireGlContext();
void requireVkContext();

View File

@@ -22,8 +22,9 @@ namespace test {
// Not a static global because we need to force the map to be constructed
// before we try to add things to it.
std::unordered_map<std::string, TestScene::Info>& TestScene::testMap() {
static std::unordered_map<std::string, TestScene::Info> testMap;
// std::map because tests sorted by name is a prettier output
std::map<std::string, TestScene::Info>& TestScene::testMap() {
static std::map<std::string, TestScene::Info> testMap;
return testMap;
}

View File

@@ -19,8 +19,8 @@
#include <gui/Surface.h>
#include <utils/StrongPointer.h>
#include <map>
#include <string>
#include <unordered_map>
namespace android {
@@ -39,6 +39,7 @@ public:
int repeatCount = 1;
int reportFrametimeWeight = 0;
bool renderOffscreen = true;
bool reportGpuMemoryUsage = false;
};
template <class T>
@@ -68,7 +69,7 @@ public:
virtual void createContent(int width, int height, Canvas& renderer) = 0;
virtual void doFrame(int frameNr) = 0;
static std::unordered_map<std::string, Info>& testMap();
static std::map<std::string, Info>& testMap();
static void registerScene(const Info& info);
sp<Surface> renderTarget;

View File

@@ -162,6 +162,11 @@ static void doRun(const TestScene::Info& info, const TestScene::Options& opts, i
void run(const TestScene::Info& info, const TestScene::Options& opts,
benchmark::BenchmarkReporter* reporter) {
if (opts.reportGpuMemoryUsage) {
// If we're reporting GPU memory usage we need to first start with a clean slate
// All repetitions of the same test will share a single memory usage report
RenderProxy::trimMemory(100);
}
BenchmarkResults results;
for (int i = 0; i < opts.repeatCount; i++) {
doRun(info, opts, i, reporter ? &results : nullptr);
@@ -172,4 +177,7 @@ void run(const TestScene::Info& info, const TestScene::Options& opts,
// TODO: Report summary
}
}
if (opts.reportGpuMemoryUsage) {
RenderProxy::dumpGraphicsMemory(STDOUT_FILENO, false);
}
}

View File

@@ -23,6 +23,7 @@
#include "renderthread/RenderProxy.h"
#include <benchmark/benchmark.h>
#include <fnmatch.h>
#include <getopt.h>
#include <pthread.h>
#include <stdio.h>
@@ -70,6 +71,7 @@ OPTIONS:
--benchmark_format Set output format. Possible values are tabular, json, csv
--renderer=TYPE Sets the render pipeline to use. May be skiagl or skiavk
--skip-leak-check Skips the memory leak check
--report-gpu-memory Dumps the GPU memory usage after each test run
)");
}
@@ -172,6 +174,7 @@ enum {
Offscreen,
Renderer,
SkipLeakCheck,
ReportGpuMemory,
};
}
@@ -188,6 +191,7 @@ static const struct option LONG_OPTIONS[] = {
{"offscreen", no_argument, nullptr, LongOpts::Offscreen},
{"renderer", required_argument, nullptr, LongOpts::Renderer},
{"skip-leak-check", no_argument, nullptr, LongOpts::SkipLeakCheck},
{"report-gpu-memory", no_argument, nullptr, LongOpts::ReportGpuMemory},
{0, 0, 0, 0}};
static const char* SHORT_OPTIONS = "c:r:h";
@@ -290,6 +294,10 @@ void parseOptions(int argc, char* argv[]) {
gRunLeakCheck = false;
break;
case LongOpts::ReportGpuMemory:
gOpts.reportGpuMemoryUsage = true;
break;
case 'h':
printHelp();
exit(EXIT_SUCCESS);
@@ -313,12 +321,21 @@ void parseOptions(int argc, char* argv[]) {
if (optind < argc) {
do {
const char* test = argv[optind++];
auto pos = TestScene::testMap().find(test);
if (pos == TestScene::testMap().end()) {
fprintf(stderr, "Unknown test '%s'\n", test);
exit(EXIT_FAILURE);
if (strchr(test, '*')) {
// Glob match
for (auto& iter : TestScene::testMap()) {
if (!fnmatch(test, iter.first.c_str(), 0)) {
gRunTests.push_back(iter.second);
}
}
} else {
gRunTests.push_back(pos->second);
auto pos = TestScene::testMap().find(test);
if (pos == TestScene::testMap().end()) {
fprintf(stderr, "Unknown test '%s'\n", test);
exit(EXIT_FAILURE);
} else {
gRunTests.push_back(pos->second);
}
}
} while (optind < argc);
} else {