Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(66)

Unified Diff: src/codec/SkRawCodec.cpp

Issue 1634763002: Multithreaded dng host implementation (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Addressed comment from adaubert. Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/codec/SkRawCodec.cpp
diff --git a/src/codec/SkRawCodec.cpp b/src/codec/SkRawCodec.cpp
index 05f18ac635918d448149fe112374ebd57636789c..451efd2d90c8ab71ce30503faa1149174d859957 100644
--- a/src/codec/SkRawCodec.cpp
+++ b/src/codec/SkRawCodec.cpp
@@ -17,9 +17,11 @@
#include "SkStream.h"
#include "SkStreamPriv.h"
#include "SkSwizzler.h"
+#include "SkTaskGroup.h"
#include "SkTemplates.h"
#include "SkTypes.h"
+#include "dng_area_task.h"
#include "dng_color_space.h"
#include "dng_exceptions.h"
#include "dng_host.h"
@@ -35,6 +37,82 @@
namespace {
+// Caluclates the number of tiles of tile_size that fit into the area in vertical and horizontal
+// directions.
+dng_point num_tiles_in_area(const dng_point &areaSize,
+ const dng_point_real64 &tileSize) {
+ return dng_point((areaSize.v + tileSize.v - 1) / tileSize.v,
msarett 2016/01/26 21:34:03 nit: This is non-critical, but can we use a ceil_
ebrauer 2016/01/26 22:50:59 Would it be Ok to add a Fixit?
ebrauer 2016/01/27 15:54:37 Done.
+ (areaSize.h + tileSize.h - 1) / tileSize.h);
+}
+
+int num_threads_required(const dng_point& tilesInThread,
+ const dng_point& tilesInArea) {
+ return ((tilesInArea.v + tilesInThread.v - 1) / tilesInThread.v) *
+ ((tilesInArea.h + tilesInThread.h - 1) / tilesInThread.h);
+}
+
+// Calculate the number of tiles to process per thread, taking into account the maximum number of
+// threads.
+dng_point num_tiles_per_thread(const int maxThreads,
+ const dng_point &tilesInArea) {
+ dng_point tilesInThread = {1, 1};
+ while (num_threads_required(tilesInThread, tilesInArea) > maxThreads) {
+ if (tilesInThread.h < tilesInArea.h) {
msarett 2016/01/26 21:34:03 So, when possible, we will always split into tiles
ebrauer 2016/01/26 22:50:58 I think it's preferable to make them as wide as po
msarett 2016/01/27 15:34:42 Great! Can you add a comment explaining this?
ebrauer 2016/01/27 15:54:37 Done.
+ ++tilesInThread.h;
+ } else if (tilesInThread.v < tilesInArea.v) {
+ ++tilesInThread.v;
+ } else {
+ ThrowProgramError("num_tiles_per_thread calculation is wrong.");
msarett 2016/01/26 21:34:03 Can we signal an error here without throwing an ex
ebrauer 2016/01/26 22:50:59 It might be reached on program errors or invalid d
msarett 2016/01/27 15:34:42 Sorry for being unclear here. If reaching this co
ebrauer 2016/01/27 15:54:37 Discussed this with Anton and we agreed that it is
+ }
+ }
+ return tilesInThread;
+}
+
+class SkDngHost : public dng_host {
+public:
+ using dng_host::dng_host;
+
+ void PerformAreaTask(dng_area_task& task, const dng_rect& area) override {
+ const int maxThreads = static_cast<int>(kMaxMPThreads);
msarett 2016/01/26 21:34:03 So this is 32 on 64-bit systems and 8 on 32-bit sy
ebrauer 2016/01/26 22:50:59 I think we should usetask.MaxThreads(), because th
msarett 2016/01/27 15:34:42 sgtm. Thanks for the comment.
ebrauer 2016/01/27 15:54:37 Done.
+ SkTaskGroup taskGroup;
+
+ const dng_point tileSize(task.FindTileSize(area));
msarett 2016/01/26 21:34:03 Can you add a comment explaining how the dng_sdk d
ebrauer 2016/01/26 22:50:58 area is typically something like (4000, 3000) whil
msarett 2016/01/27 15:34:42 Can you add a comment that is something like this?
ebrauer 2016/01/27 15:54:37 Done.
+ const dng_point tilesInArea = num_tiles_in_area(area.Size(), tileSize);
+
+ const dng_point tilesInThread = num_tiles_per_thread(maxThreads, tilesInArea);
+ const dng_point threadAreaSize(tilesInThread.v * tileSize.v, tilesInThread.h * tileSize.h);
+ dng_rect threadArea = dng_rect(threadAreaSize) + area.TL();
+
+ const int numThreads = num_threads_required(tilesInThread, tilesInArea);
+
+ task.Start(numThreads, tileSize, &Allocator(), Sniffer());
+ int taskIndex = 0;
+ for (int v = 0; v < tilesInArea.v; v += tilesInThread.v) {
+ for (int h = 0; h < tilesInArea.h; h += tilesInThread.h) {
+ threadArea.l = area.l + h * tileSize.h;
+ threadArea.t = area.t + v * tileSize.v;
+ threadArea.r = Min_int32(threadArea.l + threadAreaSize.h, area.r);
+ threadArea.b = Min_int32(threadArea.t + threadAreaSize.v, area.b);
+
+ taskGroup.add([&task, this, taskIndex, threadArea, tileSize] {
+ task.ProcessOnThread(taskIndex, threadArea, tileSize, this->Sniffer());
+ });
+ ++taskIndex;
+ }
+ }
+
+ taskGroup.wait();
+ task.Finish(numThreads);
+ }
+
+ uint32 PerformAreaTaskThreads() override {
msarett 2016/01/26 21:34:03 I'm not sure how this is used, but the comments in
ebrauer 2016/01/26 22:50:58 The documentation for PerformAreaTaskThreads() isn
msarett 2016/01/27 15:34:42 Yeah I noticed that they mostly compare it to 1, s
ebrauer 2016/01/27 15:54:37 Acknowledged.
+ return kMaxMPThreads;
+ }
+
+private:
+ typedef dng_host INHERITED;
+};
+
// T must be unsigned type.
template <class T>
bool safe_add_to_size_t(T arg1, T arg2, size_t* result) {
@@ -288,7 +366,7 @@ public:
private:
bool readDng() {
// Due to the limit of DNG SDK, we need to reset host and info.
- fHost.reset(new dng_host(&fAllocator));
+ fHost.reset(new SkDngHost(&fAllocator));
fInfo.reset(new dng_info);
fDngStream.reset(new SkDngStream(fStream));
try {
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698