Adding new benchmark to test image decoding performance.
BUG=skia: Review URL: https://codereview.chromium.org/918673002
This commit is contained in:
parent
a8fcea0cd0
commit
95f192d199
@ -1,50 +0,0 @@
|
||||
|
||||
/*
|
||||
* Copyright 2011 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#include "Benchmark.h"
|
||||
#include "SkBitmap.h"
|
||||
#include "SkCommandLineFlags.h"
|
||||
#include "SkImageDecoder.h"
|
||||
#include "SkOSFile.h"
|
||||
#include "SkString.h"
|
||||
#include "sk_tool_utils.h"
|
||||
|
||||
DEFINE_string(decodeBenchFilename, "resources/CMYK.jpeg", "Path to image for DecodeBench.");
|
||||
|
||||
class DecodeBench : public Benchmark {
|
||||
const SkColorType fPrefColorType;
|
||||
SkString fName;
|
||||
public:
|
||||
DecodeBench(SkColorType ct) : fPrefColorType(ct) {
|
||||
SkString fname = SkOSPath::Basename(FLAGS_decodeBenchFilename[0]);
|
||||
fName.printf("decode_%s_%s", sk_tool_utils::colortype_name(ct), fname.c_str());
|
||||
}
|
||||
|
||||
bool isSuitableFor(Backend backend) SK_OVERRIDE {
|
||||
return backend == kNonRendering_Backend;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual const char* onGetName() {
|
||||
return fName.c_str();
|
||||
}
|
||||
|
||||
virtual void onDraw(const int loops, SkCanvas*) {
|
||||
for (int i = 0; i < loops; i++) {
|
||||
SkBitmap bm;
|
||||
SkImageDecoder::DecodeFile(FLAGS_decodeBenchFilename[0], &bm, fPrefColorType,
|
||||
SkImageDecoder::kDecodePixels_Mode);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
typedef Benchmark INHERITED;
|
||||
};
|
||||
|
||||
DEF_BENCH( return new DecodeBench(kN32_SkColorType); )
|
||||
DEF_BENCH( return new DecodeBench(kRGB_565_SkColorType); )
|
||||
DEF_BENCH( return new DecodeBench(kARGB_4444_SkColorType); )
|
62
bench/DecodingBench.cpp
Normal file
62
bench/DecodingBench.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2015 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "DecodingBench.h"
|
||||
#include "SkData.h"
|
||||
#include "SkImageDecoder.h"
|
||||
#include "SkOSFile.h"
|
||||
#include "SkStream.h"
|
||||
|
||||
/*
|
||||
*
|
||||
* This benchmark is designed to test the performance of image decoding.
|
||||
* It is invoked from the nanobench.cpp file.
|
||||
*
|
||||
*/
|
||||
DecodingBench::DecodingBench(SkString path, SkColorType colorType)
|
||||
: fColorType(colorType)
|
||||
{
|
||||
// Parse filename and the color type to give the benchmark a useful name
|
||||
SkString baseName = SkOSPath::Basename(path.c_str());
|
||||
const char* colorName;
|
||||
switch(colorType) {
|
||||
case kN32_SkColorType:
|
||||
colorName = "N32";
|
||||
break;
|
||||
case kRGB_565_SkColorType:
|
||||
colorName = "565";
|
||||
break;
|
||||
case kAlpha_8_SkColorType:
|
||||
colorName = "Alpha8";
|
||||
break;
|
||||
default:
|
||||
colorName = "Unknown";
|
||||
}
|
||||
fName.printf("Decode_%s_%s", baseName.c_str(), colorName);
|
||||
|
||||
// Perform setup for the decode
|
||||
SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str()));
|
||||
fStream.reset(new SkMemoryStream(encoded));
|
||||
fDecoder.reset(SkImageDecoder::Factory(fStream.get()));
|
||||
}
|
||||
|
||||
const char* DecodingBench::onGetName() {
|
||||
return fName.c_str();
|
||||
}
|
||||
|
||||
bool DecodingBench::isSuitableFor(Backend backend) {
|
||||
return kNonRendering_Backend == backend;
|
||||
}
|
||||
|
||||
void DecodingBench::onDraw(const int n, SkCanvas* canvas) {
|
||||
SkBitmap bitmap;
|
||||
for (int i = 0; i < n; i++) {
|
||||
fStream->rewind();
|
||||
fDecoder->decode(fStream, &bitmap, fColorType,
|
||||
SkImageDecoder::kDecodePixels_Mode);
|
||||
}
|
||||
}
|
35
bench/DecodingBench.h
Normal file
35
bench/DecodingBench.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2015 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "Benchmark.h"
|
||||
#include "SkImageDecoder.h"
|
||||
#include "SkImageInfo.h"
|
||||
#include "SkStream.h"
|
||||
#include "SkString.h"
|
||||
|
||||
/*
|
||||
*
|
||||
* This benchmark is designed to test the performance of image decoding.
|
||||
* It is invoked from the nanobench.cpp file.
|
||||
*
|
||||
*/
|
||||
class DecodingBench : public Benchmark {
|
||||
public:
|
||||
DecodingBench(SkString path, SkColorType colorType);
|
||||
|
||||
protected:
|
||||
const char* onGetName() SK_OVERRIDE;
|
||||
bool isSuitableFor(Backend backend) SK_OVERRIDE;
|
||||
void onDraw(const int n, SkCanvas* canvas) SK_OVERRIDE;
|
||||
|
||||
private:
|
||||
SkString fName;
|
||||
SkColorType fColorType;
|
||||
SkAutoTDelete<SkMemoryStream> fStream;
|
||||
SkAutoTDelete<SkImageDecoder> fDecoder;
|
||||
typedef Benchmark INHERITED;
|
||||
};
|
73
bench/DecodingSubsetBench.cpp
Normal file
73
bench/DecodingSubsetBench.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2015 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "DecodingSubsetBench.h"
|
||||
#include "SkData.h"
|
||||
#include "SkImageDecoder.h"
|
||||
#include "SkOSFile.h"
|
||||
#include "SkStream.h"
|
||||
|
||||
/*
|
||||
*
|
||||
* This benchmark is designed to test the performance of image subset decoding.
|
||||
* It is invoked from the nanobench.cpp file.
|
||||
*
|
||||
*/
|
||||
DecodingSubsetBench::DecodingSubsetBench(SkString path, SkColorType colorType,
|
||||
const int divisor)
|
||||
: fColorType(colorType)
|
||||
, fDivisor(divisor)
|
||||
{
|
||||
// Parse filename and the color type to give the benchmark a useful name
|
||||
SkString baseName = SkOSPath::Basename(path.c_str());
|
||||
const char* colorName;
|
||||
switch(colorType) {
|
||||
case kN32_SkColorType:
|
||||
colorName = "N32";
|
||||
break;
|
||||
case kRGB_565_SkColorType:
|
||||
colorName = "565";
|
||||
break;
|
||||
case kAlpha_8_SkColorType:
|
||||
colorName = "Alpha8";
|
||||
break;
|
||||
default:
|
||||
colorName = "Unknown";
|
||||
}
|
||||
fName.printf("DecodeSubset_%dx%d_%s_%s", fDivisor, fDivisor,
|
||||
baseName.c_str(), colorName);
|
||||
|
||||
// Perform the decode setup
|
||||
SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str()));
|
||||
fStream.reset(new SkMemoryStream(encoded));
|
||||
fDecoder.reset(SkImageDecoder::Factory(fStream));
|
||||
}
|
||||
|
||||
const char* DecodingSubsetBench::onGetName() {
|
||||
return fName.c_str();
|
||||
}
|
||||
|
||||
bool DecodingSubsetBench::isSuitableFor(Backend backend) {
|
||||
return kNonRendering_Backend == backend;
|
||||
}
|
||||
|
||||
void DecodingSubsetBench::onDraw(const int n, SkCanvas* canvas) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
int w, h;
|
||||
fDecoder->buildTileIndex(fStream->duplicate(), &w, &h);
|
||||
// Divide the image into subsets and decode each subset
|
||||
const int sW = w / fDivisor;
|
||||
const int sH = h / fDivisor;
|
||||
for (int y = 0; y < h; y += sH) {
|
||||
for (int x = 0; x < w; x += sW) {
|
||||
SkBitmap bitmap;
|
||||
SkIRect rect = SkIRect::MakeXYWH(x, y, sW, sH);
|
||||
fDecoder->decodeSubset(&bitmap, rect, fColorType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
37
bench/DecodingSubsetBench.h
Normal file
37
bench/DecodingSubsetBench.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2015 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "Benchmark.h"
|
||||
#include "SkImageDecoder.h"
|
||||
#include "SkImageInfo.h"
|
||||
#include "SkStream.h"
|
||||
#include "SkString.h"
|
||||
|
||||
/*
|
||||
*
|
||||
* This benchmark is designed to test the performance of image subset decoding.
|
||||
* It is invoked from the nanobench.cpp file.
|
||||
*
|
||||
*/
|
||||
class DecodingSubsetBench : public Benchmark {
|
||||
public:
|
||||
DecodingSubsetBench(SkString path, SkColorType colorType,
|
||||
const int divisor);
|
||||
|
||||
protected:
|
||||
const char* onGetName() SK_OVERRIDE;
|
||||
bool isSuitableFor(Backend backend) SK_OVERRIDE;
|
||||
void onDraw(const int n, SkCanvas* canvas) SK_OVERRIDE;
|
||||
|
||||
private:
|
||||
SkString fName;
|
||||
SkColorType fColorType;
|
||||
const int fDivisor;
|
||||
SkAutoTDelete<SkMemoryStream> fStream;
|
||||
SkAutoTDelete<SkImageDecoder> fDecoder;
|
||||
typedef Benchmark INHERITED;
|
||||
};
|
@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "Benchmark.h"
|
||||
#include "SkBitmap.h"
|
||||
#include "SkData.h"
|
||||
#include "SkForceLinking.h"
|
||||
#include "SkImageDecoder.h"
|
||||
#include "SkOSFile.h"
|
||||
#include "SkStream.h"
|
||||
#include "SkString.h"
|
||||
|
||||
__SK_FORCE_IMAGE_DECODER_LINKING;
|
||||
|
||||
class SkCanvas;
|
||||
|
||||
class ImageDecodeBench : public Benchmark {
|
||||
public:
|
||||
ImageDecodeBench(void* p, const char* filename)
|
||||
: fName("image_decode_")
|
||||
, fFilename(filename)
|
||||
, fStream()
|
||||
, fValid(false) {
|
||||
fName.append(SkOSPath::Basename(filename));
|
||||
}
|
||||
|
||||
bool isSuitableFor(Backend backend) SK_OVERRIDE {
|
||||
return backend == kNonRendering_Backend;
|
||||
}
|
||||
|
||||
protected:
|
||||
const char* onGetName() SK_OVERRIDE {
|
||||
return fName.c_str();
|
||||
}
|
||||
|
||||
void onPreDraw() SK_OVERRIDE {
|
||||
SkFILEStream fileStream(fFilename.c_str());
|
||||
fValid = fileStream.isValid() && fileStream.getLength() > 0;
|
||||
if (fValid) {
|
||||
const size_t size = fileStream.getLength();
|
||||
void* data = sk_malloc_throw(size);
|
||||
if (fileStream.read(data, size) < size) {
|
||||
fValid = false;
|
||||
} else {
|
||||
SkAutoTUnref<SkData> skdata(SkData::NewFromMalloc(data, size));
|
||||
fStream.setData(skdata.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
|
||||
#ifdef SK_DEBUG
|
||||
if (!fValid) {
|
||||
SkDebugf("stream was invalid: %s\n", fName.c_str());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
// Decode a bunch of times
|
||||
SkBitmap bm;
|
||||
for (int i = 0; i < loops; ++i) {
|
||||
SkDEBUGCODE(bool success =) SkImageDecoder::DecodeStream(&fStream, &bm);
|
||||
#ifdef SK_DEBUG
|
||||
if (!success) {
|
||||
SkDebugf("failed to decode %s\n", fName.c_str());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
SkDEBUGCODE(success =) fStream.rewind();
|
||||
#ifdef SK_DEBUG
|
||||
if (!success) {
|
||||
SkDebugf("failed to rewind %s\n", fName.c_str());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
SkString fName;
|
||||
const SkString fFilename;
|
||||
SkMemoryStream fStream;
|
||||
bool fValid;
|
||||
|
||||
typedef Benchmark INHERITED;
|
||||
};
|
||||
|
||||
// These are files which call decodePalette
|
||||
//DEF_BENCH( return SkNEW_ARGS(ImageDecodeBench, ("/usr/local/google/home/scroggo/Downloads/images/hal_163x90.png")); )
|
||||
//DEF_BENCH( return SkNEW_ARGS(ImageDecodeBench, ("/usr/local/google/home/scroggo/Downloads/images/box_19_top-left.png")); )
|
@ -9,6 +9,8 @@
|
||||
|
||||
#include "Benchmark.h"
|
||||
#include "CrashHandler.h"
|
||||
#include "DecodingBench.h"
|
||||
#include "DecodingSubsetBench.h"
|
||||
#include "GMBench.h"
|
||||
#include "ProcStats.h"
|
||||
#include "ResultsWriter.h"
|
||||
@ -20,6 +22,7 @@
|
||||
#include "SkBBoxHierarchy.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkCommonFlags.h"
|
||||
#include "SkData.h"
|
||||
#include "SkForceLinking.h"
|
||||
#include "SkGraphics.h"
|
||||
#include "SkOSFile.h"
|
||||
@ -439,7 +442,11 @@ public:
|
||||
, fCurrentRecording(0)
|
||||
, fCurrentScale(0)
|
||||
, fCurrentSKP(0)
|
||||
, fCurrentUseMPD(0) {
|
||||
, fCurrentUseMPD(0)
|
||||
, fCurrentImage(0)
|
||||
, fCurrentSubsetImage(0)
|
||||
, fCurrentColorType(0)
|
||||
, fDivisor(2) {
|
||||
for (int i = 0; i < FLAGS_skps.count(); i++) {
|
||||
if (SkStrEndsWith(FLAGS_skps[i], ".skp")) {
|
||||
fSKPs.push_back() = FLAGS_skps[i];
|
||||
@ -469,6 +476,27 @@ public:
|
||||
if (FLAGS_mpd) {
|
||||
fUseMPDs.push_back() = true;
|
||||
}
|
||||
|
||||
// Prepare the images for decoding
|
||||
for (int i = 0; i < FLAGS_images.count(); i++) {
|
||||
const char* flag = FLAGS_images[i];
|
||||
if (sk_isdir(flag)) {
|
||||
// If the value passed in is a directory, add all the images
|
||||
SkOSFile::Iter it(flag);
|
||||
SkString file;
|
||||
while (it.next(&file)) {
|
||||
fImages.push_back() = SkOSPath::Join(flag, file.c_str());
|
||||
}
|
||||
} else if (sk_exists(flag)) {
|
||||
// Also add the value if it is a single image
|
||||
fImages.push_back() = flag;
|
||||
}
|
||||
}
|
||||
|
||||
// Choose the candidate color types for image decoding
|
||||
const SkColorType colorTypes[] =
|
||||
{ kN32_SkColorType, kRGB_565_SkColorType, kAlpha_8_SkColorType };
|
||||
fColorTypes.push_back_n(SK_ARRAY_COUNT(colorTypes), colorTypes);
|
||||
}
|
||||
|
||||
static bool ReadPicture(const char* path, SkAutoTUnref<SkPicture>* pic) {
|
||||
@ -562,6 +590,75 @@ public:
|
||||
fCurrentScale++;
|
||||
}
|
||||
|
||||
// Run the DecodingBenches
|
||||
while (fCurrentImage < fImages.count()) {
|
||||
while (fCurrentColorType < fColorTypes.count()) {
|
||||
const SkString& path = fImages[fCurrentImage];
|
||||
SkColorType colorType = fColorTypes[fCurrentColorType];
|
||||
fCurrentColorType++;
|
||||
// Check if the image decodes before creating the benchmark
|
||||
SkBitmap bitmap;
|
||||
if (SkImageDecoder::DecodeFile(path.c_str(), &bitmap,
|
||||
colorType, SkImageDecoder::kDecodePixels_Mode)) {
|
||||
return new DecodingBench(path, colorType);
|
||||
}
|
||||
}
|
||||
fCurrentColorType = 0;
|
||||
fCurrentImage++;
|
||||
}
|
||||
|
||||
// Run the DecodingSubsetBenches
|
||||
while (fCurrentSubsetImage < fImages.count()) {
|
||||
while (fCurrentColorType < fColorTypes.count()) {
|
||||
const SkString& path = fImages[fCurrentSubsetImage];
|
||||
SkColorType colorType = fColorTypes[fCurrentColorType];
|
||||
fCurrentColorType++;
|
||||
// Check if the image decodes before creating the benchmark
|
||||
SkAutoTUnref<SkData> encoded(
|
||||
SkData::NewFromFileName(path.c_str()));
|
||||
SkAutoTDelete<SkMemoryStream> stream(
|
||||
new SkMemoryStream(encoded));
|
||||
SkAutoTDelete<SkImageDecoder>
|
||||
decoder(SkImageDecoder::Factory(stream.get()));
|
||||
if (!decoder) {
|
||||
SkDebugf("Cannot find decoder for %s\n", path.c_str());
|
||||
} else {
|
||||
stream->rewind();
|
||||
int w, h;
|
||||
bool success;
|
||||
if (!decoder->buildTileIndex(stream.detach(), &w, &h)
|
||||
|| w*h == 1) {
|
||||
// This is not an error, but in this case we still
|
||||
// do not want to run the benchmark.
|
||||
success = false;
|
||||
} else if (fDivisor > w || fDivisor > h) {
|
||||
SkDebugf("Divisor %d is too big for %s %dx%d\n",
|
||||
fDivisor, path.c_str(), w, h);
|
||||
success = false;
|
||||
} else {
|
||||
const int sW = w / fDivisor;
|
||||
const int sH = h / fDivisor;
|
||||
SkBitmap bitmap;
|
||||
success = true;
|
||||
for (int y = 0; y < h; y += sH) {
|
||||
for (int x = 0; x < w; x += sW) {
|
||||
SkIRect rect = SkIRect::MakeXYWH(x, y, sW, sH);
|
||||
success &= decoder->decodeSubset(&bitmap, rect,
|
||||
colorType);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Create the benchmark if successful
|
||||
if (success) {
|
||||
return new DecodingSubsetBench(path, colorType,
|
||||
fDivisor);
|
||||
}
|
||||
}
|
||||
}
|
||||
fCurrentColorType = 0;
|
||||
fCurrentSubsetImage++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -591,6 +688,8 @@ private:
|
||||
SkTArray<SkScalar> fScales;
|
||||
SkTArray<SkString> fSKPs;
|
||||
SkTArray<bool> fUseMPDs;
|
||||
SkTArray<SkString> fImages;
|
||||
SkTArray<SkColorType> fColorTypes;
|
||||
|
||||
double fSKPBytes, fSKPOps;
|
||||
|
||||
@ -600,6 +699,10 @@ private:
|
||||
int fCurrentScale;
|
||||
int fCurrentSKP;
|
||||
int fCurrentUseMPD;
|
||||
int fCurrentImage;
|
||||
int fCurrentSubsetImage;
|
||||
int fCurrentColorType;
|
||||
const int fDivisor;
|
||||
};
|
||||
|
||||
int nanobench_main();
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "Test.h"
|
||||
#include "Timer.h"
|
||||
|
||||
DEFINE_string(images, "resources", "Images to decode.");
|
||||
DEFINE_string(src, "tests gm skp image subset", "Source types to test.");
|
||||
DEFINE_bool(nameByHash, false,
|
||||
"If true, write to FLAGS_writePath[0]/<hash>.png instead of "
|
||||
|
@ -10,6 +10,8 @@
|
||||
'type': 'executable',
|
||||
'sources': [
|
||||
'../gm/gm.cpp',
|
||||
'../bench/DecodingBench.cpp',
|
||||
'../bench/DecodingSubsetBench.cpp',
|
||||
'../bench/GMBench.cpp',
|
||||
'../bench/RecordingBench.cpp',
|
||||
'../bench/SKPBench.cpp',
|
||||
|
@ -43,7 +43,6 @@
|
||||
'../bench/ColorPrivBench.cpp',
|
||||
'../bench/CoverageBench.cpp',
|
||||
'../bench/DashBench.cpp',
|
||||
'../bench/DecodeBench.cpp',
|
||||
'../bench/DeferredSurfaceCopyBench.cpp',
|
||||
'../bench/DisplacementBench.cpp',
|
||||
'../bench/ETCBitmapBench.cpp',
|
||||
@ -58,7 +57,6 @@
|
||||
'../bench/GradientBench.cpp',
|
||||
'../bench/HairlinePathBench.cpp',
|
||||
'../bench/ImageCacheBench.cpp',
|
||||
'../bench/ImageDecodeBench.cpp',
|
||||
'../bench/ImageFilterDAGBench.cpp',
|
||||
'../bench/ImageFilterCollapse.cpp',
|
||||
'../bench/InterpBench.cpp',
|
||||
|
@ -18,6 +18,8 @@
|
||||
'xml.gyp:xml',
|
||||
],
|
||||
'sources': [
|
||||
'../bench/DecodingBench.cpp',
|
||||
'../bench/DecodingSubsetBench.cpp',
|
||||
'../bench/GMBench.cpp',
|
||||
'../bench/RecordingBench.cpp',
|
||||
'../bench/SKPBench.cpp',
|
||||
|
@ -23,6 +23,8 @@ DEFINE_string(gpuAPI, "", "Force use of specific gpu API. Using \"gl\" "
|
||||
"Defaults to empty string, which selects the API native to the "
|
||||
"system.");
|
||||
|
||||
DEFINE_string(images, "resources", "Directory of images to decode.");
|
||||
|
||||
DEFINE_bool2(leaks, l, false, "show leaked ref cnt'd objects.");
|
||||
|
||||
DEFINE_string2(match, m, NULL,
|
||||
|
@ -15,6 +15,7 @@ DECLARE_bool(cpu);
|
||||
DECLARE_bool(dryRun);
|
||||
DECLARE_bool(gpu);
|
||||
DECLARE_string(gpuAPI);
|
||||
DECLARE_string(images);
|
||||
DECLARE_bool(leaks);
|
||||
DECLARE_string(match);
|
||||
DECLARE_bool(quiet);
|
||||
|
Loading…
Reference in New Issue
Block a user