Use task dispatcher provided by user.

This commit is contained in:
castano 2010-12-10 10:29:04 +00:00
parent 66c9729097
commit a2f0e566c7
13 changed files with 109 additions and 80 deletions

View File

@ -30,11 +30,11 @@
namespace nv namespace nv
{ {
struct CompressorInterface struct CompressorInterface
{ {
virtual ~CompressorInterface() {} virtual ~CompressorInterface() {}
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * rgba, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions) = 0; virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * rgba, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions) = 0;
}; };
} // nv namespace } // nv namespace

View File

@ -126,7 +126,7 @@ struct CompressorContext
}; };
// Each task compresses one row. // Each task compresses one row.
void CompressorTask(void * data, size_t i) void CompressorTask(void * data, int i)
{ {
CompressorContext * d = (CompressorContext *) data; CompressorContext * d = (CompressorContext *) data;
@ -143,7 +143,7 @@ void CompressorTask(void * data, size_t i)
} }
} }
void FixedBlockCompressor::compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions) void FixedBlockCompressor::compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * data, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
{ {
CompressorContext context; CompressorContext context;
context.alphaMode = alphaMode; context.alphaMode = alphaMode;
@ -158,12 +158,7 @@ void FixedBlockCompressor::compress(nvtt::AlphaMode alphaMode, uint w, uint h, c
context.compressor = this; context.compressor = this;
static SequentialTaskDispatcher sequential; SequentialTaskDispatcher sequential;
//static AppleTaskDispatcher concurrent;
static OpenMPTaskDispatcher concurrent;
//TaskDispatcher * dispatcher = &sequential;
TaskDispatcher * dispatcher = &concurrent;
// Use a single thread to compress small textures. // Use a single thread to compress small textures.
if (context.bh < 4) dispatcher = &sequential; if (context.bh < 4) dispatcher = &sequential;
@ -182,7 +177,7 @@ void FixedBlockCompressor::compress(nvtt::AlphaMode alphaMode, uint w, uint h, c
void ColorSetCompressor::compress(AlphaMode alphaMode, uint w, uint h, const float * data, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) void ColorSetCompressor::compress(AlphaMode alphaMode, uint w, uint h, const float * data, nvtt::TaskDispatcher * dispatcher, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions)
{ {
const uint bs = blockSize(); const uint bs = blockSize();
const uint bw = (w + 3) / 4; const uint bw = (w + 3) / 4;

View File

@ -35,7 +35,7 @@ namespace nv
struct FixedBlockCompressor : public CompressorInterface struct FixedBlockCompressor : public CompressorInterface
{ {
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * rgba, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions); virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * rgba, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
virtual void compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) = 0; virtual void compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) = 0;
virtual uint blockSize() const = 0; virtual uint blockSize() const = 0;
@ -43,7 +43,7 @@ namespace nv
struct ColorSetCompressor : public CompressorInterface struct ColorSetCompressor : public CompressorInterface
{ {
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * rgba, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions); virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * rgba, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
virtual void compressBlock(ColorSet & set, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) = 0; virtual void compressBlock(ColorSet & set, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) = 0;
virtual uint blockSize() const = 0; virtual uint blockSize() const = 0;

View File

@ -122,7 +122,7 @@ namespace
void PixelFormatConverter::compress(nvtt::AlphaMode /*alphaMode*/, uint w, uint h, const float * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions) void PixelFormatConverter::compress(nvtt::AlphaMode /*alphaMode*/, uint w, uint h, const float * data, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
{ {
nvDebugCheck (compressionOptions.format == nvtt::Format_RGBA); nvDebugCheck (compressionOptions.format == nvtt::Format_RGBA);

View File

@ -31,7 +31,7 @@ namespace nv
{ {
struct PixelFormatConverter : public CompressorInterface struct PixelFormatConverter : public CompressorInterface
{ {
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions); virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * data, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
}; };
} // nv namespace } // nv namespace

View File

@ -56,7 +56,7 @@ static Color32 toRgbe8(float r, float g, float b)
} }
void CompressorRGBE::compress(nvtt::AlphaMode /*alphaMode*/, uint w, uint h, const float * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions) void CompressorRGBE::compress(nvtt::AlphaMode /*alphaMode*/, uint w, uint h, const float * data, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
{ {
nvDebugCheck (compressionOptions.format == nvtt::Format_RGBE); nvDebugCheck (compressionOptions.format == nvtt::Format_RGBE);

View File

@ -30,7 +30,7 @@ namespace nv
{ {
struct CompressorRGBE : public CompressorInterface struct CompressorRGBE : public CompressorInterface
{ {
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions); virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * data, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
}; };
} // nv namespace } // nv namespace

View File

@ -64,6 +64,8 @@ Compressor::Compressor() : m(*new Compressor::Private())
m.cuda = NULL; m.cuda = NULL;
enableCudaAcceleration(m.cudaSupported); enableCudaAcceleration(m.cudaSupported);
m.dispatcher = &m.defaultDispatcher;
} }
Compressor::~Compressor() Compressor::~Compressor()
@ -96,6 +98,16 @@ bool Compressor::isCudaAccelerationEnabled() const
return m.cudaEnabled; return m.cudaEnabled;
} }
void Compressor::setTaskDispatcher(TaskDispatcher * disp)
{
if (disp == NULL) {
m.dispatcher = &m.defaultDispatcher;
}
else {
m.dispatcher = disp;
}
}
// Input Options API. // Input Options API.
bool Compressor::process(const InputOptions & inputOptions, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const bool Compressor::process(const InputOptions & inputOptions, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const
@ -318,7 +330,7 @@ bool Compressor::Private::compress(AlphaMode alphaMode, int w, int h, int d, int
} }
else else
{ {
compressor->compress(alphaMode, w, h, rgba, compressionOptions, outputOptions); compressor->compress(alphaMode, w, h, rgba, dispatcher, compressionOptions, outputOptions);
} }
return true; return true;

View File

@ -30,6 +30,7 @@
#include "nvtt/Compressor.h" #include "nvtt/Compressor.h"
#include "nvtt/cuda/CudaCompressorDXT.h" #include "nvtt/cuda/CudaCompressorDXT.h"
#include "nvtt.h" #include "nvtt.h"
#include "TaskDispatcher.h"
namespace nv namespace nv
{ {
@ -51,18 +52,19 @@ namespace nvtt
void quantize(TexImage & tex, const CompressionOptions::Private & compressionOptions) const; void quantize(TexImage & tex, const CompressionOptions::Private & compressionOptions) const;
bool outputHeader(nvtt::TextureType textureType, int w, int h, int d, int mipmapCount, bool isNormalMap, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const; bool outputHeader(nvtt::TextureType textureType, int w, int h, int d, int mipmapCount, bool isNormalMap, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const;
//bool outputHeader(const InputOptions::Private & inputOptions, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const;
nv::CompressorInterface * chooseCpuCompressor(const CompressionOptions::Private & compressionOptions) const; nv::CompressorInterface * chooseCpuCompressor(const CompressionOptions::Private & compressionOptions) const;
nv::CompressorInterface * chooseGpuCompressor(const CompressionOptions::Private & compressionOptions) const; nv::CompressorInterface * chooseGpuCompressor(const CompressionOptions::Private & compressionOptions) const;
bool cudaSupported;
bool cudaEnabled;
bool cudaSupported; nv::AutoPtr<nv::CudaContext> cuda;
bool cudaEnabled;
nv::AutoPtr<nv::CudaContext> cuda;
TaskDispatcher * dispatcher;
//SequentialTaskDispatcher defaultDispatcher;
ConcurrentTaskDispatcher defaultDispatcher;
}; };
} // nvtt namespace } // nvtt namespace

View File

@ -10,16 +10,14 @@
// Gran Central Dispatch (GCD/libdispatch) // Gran Central Dispatch (GCD/libdispatch)
// http://developer.apple.com/mac/library/documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html // http://developer.apple.com/mac/library/documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html
#if NV_OS_DARWIN && defined(HAVE_DISPATCH_H) #if NV_OS_DARWIN && defined(HAVE_DISPATCH_H)
#define HAVE_GCD 1
#include <dispatch/dispatch.h> #include <dispatch/dispatch.h>
#endif #endif
#if NV_OS_WIN32 && _MSC_VER >= 1600
#define HAVE_PPL 1
#endif
// Parallel Patterns Library (PPL) is part of Microsoft's concurrency runtime: // Parallel Patterns Library (PPL) is part of Microsoft's concurrency runtime:
// http://msdn.microsoft.com/en-us/library/dd504870.aspx // http://msdn.microsoft.com/en-us/library/dd504870.aspx
#if defined(HAVE_PPL) #if NV_OS_WIN32 && _MSC_VER >= 1600
#define HAVE_PPL 1
#include <array> #include <array>
//#include <ppl.h> //#include <ppl.h>
#endif #endif
@ -35,8 +33,8 @@ namespace nvtt {
struct SequentialTaskDispatcher : public TaskDispatcher struct SequentialTaskDispatcher : public TaskDispatcher
{ {
virtual void dispatch(Task * task, void * context, size_t count) { virtual void dispatch(Task * task, void * context, int count) {
for (size_t i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
task(context, i); task(context, i);
} }
} }
@ -46,9 +44,9 @@ namespace nvtt {
struct OpenMPTaskDispatcher : public TaskDispatcher struct OpenMPTaskDispatcher : public TaskDispatcher
{ {
virtual void dispatch(Task * task, void * context, size_t count) { virtual void dispatch(Task * task, void * context, int count) {
#pragma omp parallel for #pragma omp parallel for
for (int i = 0; i < int(count); i++) { for (int i = 0; i < count; i++) {
task(context, i); task(context, i);
} }
} }
@ -61,9 +59,21 @@ namespace nvtt {
// Task dispatcher using Apple's Grand Central Dispatch. // Task dispatcher using Apple's Grand Central Dispatch.
struct AppleTaskDispatcher : public TaskDispatcher struct AppleTaskDispatcher : public TaskDispatcher
{ {
virtual void dispatch(Task * task, void * context, size_t count) { // @@ This is really lame, but I refuse to use size_t in the public API.
dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0); struct BlockContext {
dispatch_apply_f(count, q, context, task); Task * task;
void * context;
};
static void block(void * context, size_t id) {
BlockContext * ctx = (BlockContext *)context;
ctx->task(ctx->context, int(id));
}
virtual void dispatch(Task * task, void * context, int count) {
dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
BlockContext blockCtx = { task, context };
dispatch_apply_f(count, q, &blockCtx, block);
} }
}; };
@ -71,42 +81,41 @@ namespace nvtt {
#if defined(HAVE_PPL) #if defined(HAVE_PPL)
class CountingIterator class CountingIterator
{ {
public: public:
CountingIterator() : i(0) {} CountingIterator() : i(0) {}
CountingIterator(const CountingIterator & rhs) : i(0) {} CountingIterator(const CountingIterator & rhs) : i(0) {}
explicit CountingIterator(int x) : i(x) {} explicit CountingIterator(int x) : i(x) {}
//const int & base() const; const int & operator*() const { return i; }
const int & operator*() const { return i; } CountingIterator & operator++() { i++; return *this; }
CountingIterator & operator++() { i++; return *this; } CountingIterator & operator--() { i--; return *this; }
CountingIterator & operator--() { i--; return *this; }
private:
private: int i;
int i;
}; };
struct TaskFunctor { struct TaskFunctor {
TaskFunctor(Task * task, void * context) : task(task), context(context) {} TaskFunctor(Task * task, void * context) : task(task), context(context) {}
void operator()(int & n) const { void operator()(int & n) const {
task(context, n); task(context, n);
} }
Task * task; Task * task;
void * context; void * context;
}; };
// Using Microsoft's concurrency runtime. // Task dispatcher using Microsoft's concurrency runtime.
struct MicrosoftTaskDispatcher : public TaskDispatcher struct MicrosoftTaskDispatcher : public TaskDispatcher
{ {
virtual void dispatch(Task * task, void * context, size_t count) virtual void dispatch(Task * task, void * context, int count)
{ {
CountingIterator begin(0); CountingIterator begin(0);
CountingIterator end((int)count); CountingIterator end((int)count);
TaskFunctor func(task, context); TaskFunctor func(task, context);
std::for_each(begin, end, func); std::for_each(begin, end, func);
//std::parallel_for_each(begin, end, func); //parallel_for_each(begin, end, func);
} }
}; };
@ -114,22 +123,35 @@ namespace nvtt {
#if defined(HAVE_TBB) #if defined(HAVE_TBB)
struct TaskFunctor { struct TaskFunctor {
TaskFunctor(Task * task, void * context) : task(task), context(context) {} TaskFunctor(Task * task, void * context) : task(task), context(context) {}
void operator()(int & n) const { void operator()(int & n) const {
task(context, n); task(context, n);
} }
Task * task; Task * task;
void * context; void * context;
}; };
// Task dispatcher using Inte's Thread Building Blocks.
struct IntelTaskDispatcher : public TaskDispatcher struct IntelTaskDispatcher : public TaskDispatcher
{ {
virtual void dispatch(Task * task, void * context, size_t count) { virtual void dispatch(Task * task, void * context, int count) {
parallel_for(blocked_range<size_t>(0, count, 1), TaskFunctor(task, context)); parallel_for(blocked_range<int>(0, count, 1), TaskFunctor(task, context));
} }
}; };
#endif #endif
#if defined(HAVE_OPENMP)
typedef OpenMPTaskDispatcher ConcurrentTaskDispatcher;
#elif defined(HAVE_TBB)
typedef IntelTaskDispatcher ConcurrentTaskDispatcher;
#elif defined(HAVE_PPL)
typedef MicrosoftTaskDispatcher ConcurrentTaskDispatcher;
#elif defined(HAVE_GCD)
typedef AppleTaskDispatcher ConcurrentTaskDispatcher;
#else
typedef SequentialTaskDispatcher ConcurrentTaskDispatcher;
#endif
} // namespace nvtt } // namespace nvtt

View File

@ -125,7 +125,7 @@ CudaCompressor::CudaCompressor(CudaContext & ctx) : m_ctx(ctx)
} }
void CudaCompressor::compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions) void CudaCompressor::compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * data, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
{ {
nvDebugCheck(cuda::isHardwarePresent()); nvDebugCheck(cuda::isHardwarePresent());

View File

@ -54,7 +54,7 @@ namespace nv
{ {
CudaCompressor(CudaContext & ctx); CudaCompressor(CudaContext & ctx);
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions); virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * data, nvtt::TaskDispatcher * dispatcher, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
virtual void setup(cudaArray * image, const nvtt::CompressionOptions::Private & compressionOptions) = 0; virtual void setup(cudaArray * image, const nvtt::CompressionOptions::Private & compressionOptions) = 0;
virtual void compressBlocks(uint first, uint count, uint w, uint h, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) = 0; virtual void compressBlocks(uint first, uint count, uint w, uint h, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) = 0;

View File

@ -26,8 +26,6 @@
#ifndef NVTT_H #ifndef NVTT_H
#define NVTT_H #define NVTT_H
#include <stddef.h> // size_t @@ Use or own define?
// Function linkage // Function linkage
#if NVTT_SHARED #if NVTT_SHARED
@ -333,11 +331,11 @@ namespace nvtt
NVTT_API void setUserVersion(int version); NVTT_API void setUserVersion(int version);
}; };
typedef void Task(void * context, size_t id); typedef void Task(void * context, int id);
struct TaskDispatcher struct TaskDispatcher
{ {
virtual void dispatch(Task * task, void * context, size_t count) = 0; virtual void dispatch(Task * task, void * context, int count) = 0;
}; };
/// Context. /// Context.