Merge "Macrobenchmark tweaks & gpu memory dumping" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
f196d46fdf
@@ -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();
|
||||
|
||||
@@ -34,6 +34,7 @@ public:
|
||||
SkiaMemoryTracer(const char* categoryKey, bool itemizeType);
|
||||
~SkiaMemoryTracer() override {}
|
||||
|
||||
bool hasOutput();
|
||||
void logOutput(String8& log);
|
||||
void logTotals(String8& log);
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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); });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user