2014-04-30 13:20:45 +00:00
|
|
|
#include "DMQuiltTask.h"
|
2013-11-26 23:36:51 +00:00
|
|
|
#include "DMUtil.h"
|
2014-04-30 13:20:45 +00:00
|
|
|
#include "DMWriteTask.h"
|
2013-11-26 23:36:51 +00:00
|
|
|
|
2014-07-09 20:10:58 +00:00
|
|
|
#include "SkBBHFactory.h"
|
2013-11-26 23:36:51 +00:00
|
|
|
#include "SkCommandLineFlags.h"
|
|
|
|
#include "SkPicture.h"
|
SkThreadPool ~~> SkTaskGroup
SkTaskGroup is like SkThreadPool except the threads stay in
one global pool. Each SkTaskGroup itself is tiny (4 bytes)
and its wait() method applies only to tasks add()ed to that
instance, not the whole thread pool.
This means we don't need to bring up new thread pools when
tests themselves want to use multithreading (e.g. pathops,
quilt). We just create a new SkTaskGroup and wait for that
to complete. This should be more efficient, and allow us
to expand where we use threads to really latency sensitive
places. E.g. we can probably now use these in nanobench
for CPU .skp rendering.
Now that all threads are sharing the same pool, I think we
can remove most of the custom mechanism pathops tests use
to control threading. They'll just ride on the global pool
with all other tests now.
This (temporarily?) removes the GPU multithreading feature
from DM, which we don't use.
On my desktop, DM runs a little faster (57s -> 55s) in
Debug, and a lot faster in Release (36s -> 24s). The bots
show speedups of similar proportions, cutting more than a
minute off the N4/Release and Win7/Debug runtimes.
BUG=skia:
Committed: https://skia.googlesource.com/skia/+/9c7207b5dc71dc5a96a2eb107d401133333d5b6f
R=caryclark@google.com, bsalomon@google.com, bungeman@google.com, mtklein@google.com, reed@google.com
Author: mtklein@chromium.org
Review URL: https://codereview.chromium.org/531653002
2014-09-03 22:34:37 +00:00
|
|
|
#include "SkTaskGroup.h"
|
2013-11-26 23:36:51 +00:00
|
|
|
|
2014-07-09 20:10:58 +00:00
|
|
|
DEFINE_bool(quilt, true, "If true, draw GM via a picture into a quilt of small tiles and compare.");
|
2014-07-07 17:41:04 +00:00
|
|
|
DEFINE_int32(quiltTile, 256, "Dimension of (square) quilt tile.");
|
2013-11-26 23:36:51 +00:00
|
|
|
|
|
|
|
namespace DM {
|
|
|
|
|
2014-08-11 15:08:43 +00:00
|
|
|
static SkString suffix(QuiltTask::Backend backend, QuiltTask::BBH bbh) {
|
|
|
|
static const char* kBackends[] = { "default", "skrecord" };
|
2014-08-26 21:07:04 +00:00
|
|
|
static const char* kBBHs[] = { "nobbh", "rtree", "tilegrid" };
|
2014-08-11 15:08:43 +00:00
|
|
|
return SkStringPrintf("%s-%s", kBackends[backend], kBBHs[bbh]);
|
|
|
|
}
|
|
|
|
|
|
|
|
QuiltTask::QuiltTask(const Task& parent, skiagm::GM* gm, SkBitmap reference,
|
|
|
|
QuiltTask::BBH bbh, QuiltTask::Backend backend)
|
2014-02-28 20:31:31 +00:00
|
|
|
: CpuTask(parent)
|
2014-08-11 15:08:43 +00:00
|
|
|
, fBBH(bbh)
|
|
|
|
, fBackend(backend)
|
|
|
|
, fName(UnderJoin(parent.name().c_str(), suffix(backend, bbh).c_str()))
|
2013-11-26 23:36:51 +00:00
|
|
|
, fGM(gm)
|
|
|
|
, fReference(reference)
|
|
|
|
{}
|
|
|
|
|
|
|
|
static int tiles_needed(int fullDimension, int tileDimension) {
|
|
|
|
return (fullDimension + tileDimension - 1) / tileDimension;
|
|
|
|
}
|
|
|
|
|
2014-07-01 14:46:50 +00:00
|
|
|
class Tile : public SkRunnable {
|
|
|
|
public:
|
2014-07-07 17:41:04 +00:00
|
|
|
Tile(int x, int y, const SkPicture& picture, SkBitmap* quilt)
|
|
|
|
: fX(x * FLAGS_quiltTile)
|
|
|
|
, fY(y * FLAGS_quiltTile)
|
2014-07-01 14:46:50 +00:00
|
|
|
, fPicture(picture)
|
2014-07-07 17:41:04 +00:00
|
|
|
, fQuilt(quilt) {}
|
2014-07-01 14:46:50 +00:00
|
|
|
|
|
|
|
virtual void run() SK_OVERRIDE {
|
|
|
|
SkBitmap tile;
|
2014-07-07 17:41:04 +00:00
|
|
|
fQuilt->extractSubset(&tile, SkIRect::MakeXYWH(fX, fY, FLAGS_quiltTile, FLAGS_quiltTile));
|
2014-07-01 14:46:50 +00:00
|
|
|
SkCanvas tileCanvas(tile);
|
|
|
|
|
2014-07-07 17:41:04 +00:00
|
|
|
tileCanvas.translate(SkIntToScalar(-fX), SkIntToScalar(-fY));
|
2014-09-04 15:42:50 +00:00
|
|
|
fPicture.playback(&tileCanvas);
|
2014-07-01 14:46:50 +00:00
|
|
|
tileCanvas.flush();
|
|
|
|
|
|
|
|
delete this;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
const int fX, fY;
|
|
|
|
const SkPicture& fPicture;
|
2014-07-07 17:41:04 +00:00
|
|
|
SkBitmap* fQuilt;
|
2014-07-01 14:46:50 +00:00
|
|
|
};
|
|
|
|
|
2014-04-30 13:20:45 +00:00
|
|
|
void QuiltTask::draw() {
|
2014-07-09 20:10:58 +00:00
|
|
|
SkAutoTDelete<SkBBHFactory> factory;
|
2014-08-11 15:08:43 +00:00
|
|
|
switch (fBBH) {
|
|
|
|
case kNone_BBH: break;
|
|
|
|
case kRTree_BBH:
|
2014-07-09 20:10:58 +00:00
|
|
|
factory.reset(SkNEW(SkRTreeFactory));
|
|
|
|
break;
|
2014-08-11 15:08:43 +00:00
|
|
|
case kTileGrid_BBH: {
|
2014-07-09 20:10:58 +00:00
|
|
|
const SkTileGridFactory::TileGridInfo tiles = {
|
|
|
|
{ FLAGS_quiltTile, FLAGS_quiltTile },
|
|
|
|
/*overlap: */{0, 0},
|
|
|
|
/*offset: */{0, 0},
|
|
|
|
};
|
|
|
|
factory.reset(SkNEW_ARGS(SkTileGridFactory, (tiles)));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2013-11-26 23:36:51 +00:00
|
|
|
|
2014-07-09 20:10:58 +00:00
|
|
|
// A couple GMs draw wrong when using a bounding box hierarchy.
|
|
|
|
// This almost certainly means we have a bug to fix, but for now
|
|
|
|
// just draw without a bounding box hierarchy.
|
|
|
|
if (fGM->getFlags() & skiagm::GM::kNoBBH_Flag) {
|
|
|
|
factory.reset(NULL);
|
2014-07-07 17:41:04 +00:00
|
|
|
}
|
2013-11-26 23:36:51 +00:00
|
|
|
|
2014-07-09 20:10:58 +00:00
|
|
|
SkAutoTUnref<const SkPicture> recorded(
|
2014-08-11 15:08:43 +00:00
|
|
|
RecordPicture(fGM.get(), factory.get(), kSkRecord_Backend == fBackend));
|
2014-07-09 20:10:58 +00:00
|
|
|
|
|
|
|
SkBitmap full;
|
|
|
|
AllocatePixels(fReference, &full);
|
|
|
|
|
|
|
|
if (fGM->getFlags() & skiagm::GM::kSkipTiled_Flag) {
|
|
|
|
// Some GMs don't draw exactly the same when tiled. Draw them in one go.
|
|
|
|
SkCanvas canvas(full);
|
2014-09-04 15:42:50 +00:00
|
|
|
recorded->playback(&canvas);
|
2014-07-09 20:10:58 +00:00
|
|
|
canvas.flush();
|
|
|
|
} else {
|
|
|
|
// Draw tiles in parallel into the same bitmap, simulating aggressive impl-side painting.
|
SkThreadPool ~~> SkTaskGroup
SkTaskGroup is like SkThreadPool except the threads stay in
one global pool. Each SkTaskGroup itself is tiny (4 bytes)
and its wait() method applies only to tasks add()ed to that
instance, not the whole thread pool.
This means we don't need to bring up new thread pools when
tests themselves want to use multithreading (e.g. pathops,
quilt). We just create a new SkTaskGroup and wait for that
to complete. This should be more efficient, and allow us
to expand where we use threads to really latency sensitive
places. E.g. we can probably now use these in nanobench
for CPU .skp rendering.
Now that all threads are sharing the same pool, I think we
can remove most of the custom mechanism pathops tests use
to control threading. They'll just ride on the global pool
with all other tests now.
This (temporarily?) removes the GPU multithreading feature
from DM, which we don't use.
On my desktop, DM runs a little faster (57s -> 55s) in
Debug, and a lot faster in Release (36s -> 24s). The bots
show speedups of similar proportions, cutting more than a
minute off the N4/Release and Win7/Debug runtimes.
BUG=skia:
Committed: https://skia.googlesource.com/skia/+/9c7207b5dc71dc5a96a2eb107d401133333d5b6f
R=caryclark@google.com, bsalomon@google.com, bungeman@google.com, mtklein@google.com, reed@google.com
Author: mtklein@chromium.org
Review URL: https://codereview.chromium.org/531653002
2014-09-03 22:34:37 +00:00
|
|
|
SkTaskGroup tg;
|
2014-07-09 20:10:58 +00:00
|
|
|
for (int y = 0; y < tiles_needed(full.height(), FLAGS_quiltTile); y++) {
|
|
|
|
for (int x = 0; x < tiles_needed(full.width(), FLAGS_quiltTile); x++) {
|
|
|
|
// Deletes itself when done.
|
SkThreadPool ~~> SkTaskGroup
SkTaskGroup is like SkThreadPool except the threads stay in
one global pool. Each SkTaskGroup itself is tiny (4 bytes)
and its wait() method applies only to tasks add()ed to that
instance, not the whole thread pool.
This means we don't need to bring up new thread pools when
tests themselves want to use multithreading (e.g. pathops,
quilt). We just create a new SkTaskGroup and wait for that
to complete. This should be more efficient, and allow us
to expand where we use threads to really latency sensitive
places. E.g. we can probably now use these in nanobench
for CPU .skp rendering.
Now that all threads are sharing the same pool, I think we
can remove most of the custom mechanism pathops tests use
to control threading. They'll just ride on the global pool
with all other tests now.
This (temporarily?) removes the GPU multithreading feature
from DM, which we don't use.
On my desktop, DM runs a little faster (57s -> 55s) in
Debug, and a lot faster in Release (36s -> 24s). The bots
show speedups of similar proportions, cutting more than a
minute off the N4/Release and Win7/Debug runtimes.
BUG=skia:
Committed: https://skia.googlesource.com/skia/+/9c7207b5dc71dc5a96a2eb107d401133333d5b6f
R=caryclark@google.com, bsalomon@google.com, bungeman@google.com, mtklein@google.com, reed@google.com
Author: mtklein@chromium.org
Review URL: https://codereview.chromium.org/531653002
2014-09-03 22:34:37 +00:00
|
|
|
tg.add(new Tile(x, y, *recorded, &full));
|
2014-07-09 20:10:58 +00:00
|
|
|
}
|
2013-11-26 23:36:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!BitmapsEqual(full, fReference)) {
|
|
|
|
this->fail();
|
Update DM JSON format.
Ex. dm --match patch -w bad --key arch x86 gpu nvidia model z620 --properties git_hash abcd build_number 20 ->
{
"build_number" : "20",
"git_hash" : "abcd",
"key" : {
"arch" : "x86",
"gpu" : "nvidia",
"model" : "z620"
},
"results" : [
{
"key" : {
"config" : "565",
"name" : "ninepatch-stretch"
},
"md5" : "f78cfafcbabaf815f3dfcf61fb59acc7",
"options" : {
"source_type" : "GM"
}
},
{
"key" : {
"config" : "8888",
"name" : "ninepatch-stretch"
},
"md5" : "3e8a42f35a1e76f00caa191e6310d789",
"options" : {
"source_type" : "GM"
}
},
...
This breaks -r, but that's okay. Going to follow up this CL with one that removes that entirely.
BUG=skia:
R=stephana@google.com, jcgregorio@google.com, mtklein@google.com
Author: mtklein@chromium.org
Review URL: https://codereview.chromium.org/551873003
2014-09-09 14:59:46 +00:00
|
|
|
this->spawnChild(SkNEW_ARGS(WriteTask, (*this, "GM", full)));
|
2013-11-26 23:36:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-30 13:20:45 +00:00
|
|
|
bool QuiltTask::shouldSkip() const {
|
2013-11-26 23:36:51 +00:00
|
|
|
if (fGM->getFlags() & skiagm::GM::kSkipPicture_Flag) {
|
|
|
|
return true;
|
|
|
|
}
|
2014-04-30 13:20:45 +00:00
|
|
|
return !FLAGS_quilt;
|
2013-11-26 23:36:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace DM
|