Restored render interruption

This commit is contained in:
Michaël Lemaire 2014-08-19 09:18:55 +02:00
parent 31b74c660e
commit 8f24d54568
15 changed files with 90 additions and 28 deletions

View file

@ -31,6 +31,11 @@ int CanvasPixelShader::processParallelUnit(int unit)
{
for (int y = 0; y < limit_y; y += sub_chunk_size)
{
if (interrupted)
{
return 0;
}
if (sub_chunk_size == chunk_size or x % prev_sub_chunk_size != 0 or y % prev_sub_chunk_size != 0)
{
// Resolve the pixel color

View file

@ -20,7 +20,7 @@ class CanvasPixelShader: public ParallelWorker
public:
CanvasPixelShader(const SoftwareCanvasRenderer &renderer, CanvasPortion *portion, int chunk_size, int sub_chunk_size, int chunks_x, int chunks_y);
virtual int processParallelUnit(int unit);
virtual int processParallelUnit(int unit) override;
private:
const SoftwareCanvasRenderer &renderer;

View file

@ -35,6 +35,8 @@ Rasterizer::Rasterizer(SoftwareRenderer* renderer, int client_id, const Color &c
renderer(renderer), client_id(client_id)
{
this->color = new Color(color);
interrupted = false;
}
Rasterizer::~Rasterizer()
@ -42,6 +44,11 @@ Rasterizer::~Rasterizer()
delete color;
}
void Rasterizer::interrupt()
{
interrupted = true;
}
void Rasterizer::pushProjectedTriangle(CanvasPortion *canvas, const Vector3 &pixel1, const Vector3 &pixel2, const Vector3 &pixel3, const Vector3 &location1, const Vector3 &location2, const Vector3 &location3)
{
ScanPoint point1, point2, point3;

View file

@ -22,6 +22,7 @@ public:
virtual void rasterizeToCanvas(CanvasPortion* canvas) = 0;
virtual Color shadeFragment(const CanvasFragment &fragment) const = 0;
virtual void interrupt();
protected:
void pushProjectedTriangle(CanvasPortion *canvas, const Vector3 &pixel1, const Vector3 &pixel2, const Vector3 &pixel3, const Vector3 &location1, const Vector3 &location2, const Vector3 &location3);
@ -34,6 +35,7 @@ protected:
Color* color;
SoftwareRenderer *renderer;
int client_id;
bool interrupted;
private:
void scanGetDiff(ScanPoint *v1, ScanPoint *v2, ScanPoint *result);

View file

@ -13,8 +13,8 @@ class SOFTWARESHARED_EXPORT SkyRasterizer: public Rasterizer
public:
SkyRasterizer(SoftwareRenderer* renderer, int client_id);
virtual void rasterizeToCanvas(CanvasPortion* canvas);
virtual Color shadeFragment(const CanvasFragment &fragment) const;
virtual void rasterizeToCanvas(CanvasPortion* canvas) override;
virtual Color shadeFragment(const CanvasFragment &fragment) const override;
};
}

View file

@ -19,6 +19,8 @@ SoftwareCanvasRenderer::SoftwareCanvasRenderer()
rasterizers.push_back(new SkyRasterizer(this, 0));
rasterizers.push_back(new WaterRasterizer(this, 1));
rasterizers.push_back(new TerrainRasterizer(this, 2));
current_work = NULL;
}
SoftwareCanvasRenderer::~SoftwareCanvasRenderer()
@ -59,14 +61,33 @@ void SoftwareCanvasRenderer::render()
for (int x = 0; x < nx; x++)
{
CanvasPortion *portion = canvas->at(x, y);
portion->preparePixels();
rasterize(portion, true);
postProcess(portion, true);
if (not render_interrupt)
{
portion->preparePixels();
rasterize(portion, true);
}
if (not render_interrupt)
{
applyPixelShader(portion, true);
}
portion->discardPixels();
}
}
}
void SoftwareCanvasRenderer::interrupt()
{
SoftwareRenderer::interrupt();
if (current_work)
{
current_work->interrupt();
}
}
const std::vector<Rasterizer *> &SoftwareCanvasRenderer::getRasterizers() const
{
return rasterizers;
@ -85,7 +106,7 @@ void SoftwareCanvasRenderer::rasterize(CanvasPortion *portion, bool threaded)
}
}
void SoftwareCanvasRenderer::postProcess(CanvasPortion *portion, bool threaded)
void SoftwareCanvasRenderer::applyPixelShader(CanvasPortion *portion, bool threaded)
{
// Subdivide in chunks
int chunk_size = 64;
@ -96,8 +117,16 @@ void SoftwareCanvasRenderer::postProcess(CanvasPortion *portion, bool threaded)
// Render chunks in parallel
for (int sub_chunk_size = chunk_size; sub_chunk_size >= 1; sub_chunk_size /= 2)
{
if (render_interrupt)
{
break;
}
CanvasPixelShader shader(*this, portion, chunk_size, sub_chunk_size, chunks_x, chunks_y);
ParallelWork work(&shader, units);
current_work = &work;
work.perform();
current_work = NULL;
}
}

View file

@ -36,6 +36,8 @@ public:
*/
void render();
virtual void interrupt() override;
/**
* @brief Get the list of objects that can be rasterized to polygons on a canvas.
*/
@ -52,19 +54,21 @@ protected:
*
* If 'threaded' is true, the rasterization will take advantage of multiple CPU cores.
*/
void rasterize(CanvasPortion* portion, bool threaded);
void rasterize(CanvasPortion *portion, bool threaded=false);
/**
* @brief Apply post-processing to fragments stored in the CanvasPortion.
* @brief Apply pixel shader to fragments stored in the CanvasPortion.
*
* If 'threaded' is true, the post-processing will take advantage of multiple CPU cores.
* If 'threaded' is true, the shader will take advantage of multiple CPU cores.
*/
void postProcess(CanvasPortion* portion, bool threaded=true);
void applyPixelShader(CanvasPortion *portion, bool threaded=true);
private:
Canvas* canvas;
Canvas *canvas;
std::vector<Rasterizer*> rasterizers;
bool started;
ParallelWork *current_work;
};
}

View file

@ -67,7 +67,7 @@ public:
void disableAtmosphere();
void disableAtmosphere(const std::vector<LightComponent> &lights);
void interrupt();
virtual void interrupt();
inline Scenery* getScenery() const {return scenery;}

View file

@ -226,10 +226,6 @@ int TerrainRasterizer::processChunk(CanvasPortion* canvas, TerrainChunkInfo* chu
return !renderer->render_interrupt;
}
void TerrainRasterizer::rasterize()
{
}
void TerrainRasterizer::rasterizeToCanvas(CanvasPortion *canvas)
{
queue = new ParallelQueue();

View file

@ -43,15 +43,8 @@ public:
void renderQuad(CanvasPortion* canvas, double x, double z, double size, double water_height);
/**
* Start the final rasterization of terrain.
*
* This will push the rasterized quads in the render area, waiting for post process.
*/
virtual void rasterize();
virtual void rasterizeToCanvas(CanvasPortion* canvas);
virtual Color shadeFragment(const CanvasFragment &fragment) const;
virtual void rasterizeToCanvas(CanvasPortion* canvas) override;
virtual Color shadeFragment(const CanvasFragment &fragment) const override;
private:
ParallelQueue* queue;

View file

@ -15,8 +15,8 @@ public:
void rasterizeQuad(CanvasPortion* canvas, double x, double z, double size);
virtual void rasterizeToCanvas(CanvasPortion* canvas);
virtual Color shadeFragment(const CanvasFragment &fragment) const;
virtual void rasterizeToCanvas(CanvasPortion* canvas) override;
virtual Color shadeFragment(const CanvasFragment &fragment) const override;
};
}

View file

@ -172,6 +172,11 @@ int ParallelWork::perform(int thread_count)
return done;
}
void ParallelWork::interrupt()
{
worker->interrupt();
}
void ParallelWork::returnThread(ParallelWork::ParallelThread *thread)
{
mutex->acquire();

View file

@ -48,6 +48,13 @@ public:
*/
int perform(int thread_count=-1);
/**
* Tell the threads to interrupt what they are doing.
*
* This will also call interrupt() on the worker.
*/
void interrupt();
private:
void returnThread(ParallelThread *thread);

View file

@ -2,8 +2,14 @@
ParallelWorker::ParallelWorker()
{
interrupted = false;
}
ParallelWorker::~ParallelWorker()
{
}
void ParallelWorker::interrupt()
{
interrupted = true;
}

View file

@ -21,6 +21,14 @@ public:
* This method will be called from any thread in the thread pool used by the ParallelWork.
*/
virtual int processParallelUnit(int unit) = 0;
/**
* Method to reimplement to know when to interrupt the processing of units.
*/
virtual void interrupt();
protected:
bool interrupted;
};
}