Restored render interruption
This commit is contained in:
parent
31b74c660e
commit
8f24d54568
15 changed files with 90 additions and 28 deletions
|
@ -31,6 +31,11 @@ int CanvasPixelShader::processParallelUnit(int unit)
|
||||||
{
|
{
|
||||||
for (int y = 0; y < limit_y; y += sub_chunk_size)
|
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)
|
if (sub_chunk_size == chunk_size or x % prev_sub_chunk_size != 0 or y % prev_sub_chunk_size != 0)
|
||||||
{
|
{
|
||||||
// Resolve the pixel color
|
// Resolve the pixel color
|
||||||
|
|
|
@ -20,7 +20,7 @@ class CanvasPixelShader: public ParallelWorker
|
||||||
public:
|
public:
|
||||||
CanvasPixelShader(const SoftwareCanvasRenderer &renderer, CanvasPortion *portion, int chunk_size, int sub_chunk_size, int chunks_x, int chunks_y);
|
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:
|
private:
|
||||||
const SoftwareCanvasRenderer &renderer;
|
const SoftwareCanvasRenderer &renderer;
|
||||||
|
|
|
@ -35,6 +35,8 @@ Rasterizer::Rasterizer(SoftwareRenderer* renderer, int client_id, const Color &c
|
||||||
renderer(renderer), client_id(client_id)
|
renderer(renderer), client_id(client_id)
|
||||||
{
|
{
|
||||||
this->color = new Color(color);
|
this->color = new Color(color);
|
||||||
|
|
||||||
|
interrupted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rasterizer::~Rasterizer()
|
Rasterizer::~Rasterizer()
|
||||||
|
@ -42,6 +44,11 @@ Rasterizer::~Rasterizer()
|
||||||
delete color;
|
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)
|
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;
|
ScanPoint point1, point2, point3;
|
||||||
|
|
|
@ -22,6 +22,7 @@ public:
|
||||||
|
|
||||||
virtual void rasterizeToCanvas(CanvasPortion* canvas) = 0;
|
virtual void rasterizeToCanvas(CanvasPortion* canvas) = 0;
|
||||||
virtual Color shadeFragment(const CanvasFragment &fragment) const = 0;
|
virtual Color shadeFragment(const CanvasFragment &fragment) const = 0;
|
||||||
|
virtual void interrupt();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void pushProjectedTriangle(CanvasPortion *canvas, const Vector3 &pixel1, const Vector3 &pixel2, const Vector3 &pixel3, const Vector3 &location1, const Vector3 &location2, const Vector3 &location3);
|
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;
|
Color* color;
|
||||||
SoftwareRenderer *renderer;
|
SoftwareRenderer *renderer;
|
||||||
int client_id;
|
int client_id;
|
||||||
|
bool interrupted;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void scanGetDiff(ScanPoint *v1, ScanPoint *v2, ScanPoint *result);
|
void scanGetDiff(ScanPoint *v1, ScanPoint *v2, ScanPoint *result);
|
||||||
|
|
|
@ -13,8 +13,8 @@ class SOFTWARESHARED_EXPORT SkyRasterizer: public Rasterizer
|
||||||
public:
|
public:
|
||||||
SkyRasterizer(SoftwareRenderer* renderer, int client_id);
|
SkyRasterizer(SoftwareRenderer* renderer, int client_id);
|
||||||
|
|
||||||
virtual void rasterizeToCanvas(CanvasPortion* canvas);
|
virtual void rasterizeToCanvas(CanvasPortion* canvas) override;
|
||||||
virtual Color shadeFragment(const CanvasFragment &fragment) const;
|
virtual Color shadeFragment(const CanvasFragment &fragment) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ SoftwareCanvasRenderer::SoftwareCanvasRenderer()
|
||||||
rasterizers.push_back(new SkyRasterizer(this, 0));
|
rasterizers.push_back(new SkyRasterizer(this, 0));
|
||||||
rasterizers.push_back(new WaterRasterizer(this, 1));
|
rasterizers.push_back(new WaterRasterizer(this, 1));
|
||||||
rasterizers.push_back(new TerrainRasterizer(this, 2));
|
rasterizers.push_back(new TerrainRasterizer(this, 2));
|
||||||
|
|
||||||
|
current_work = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SoftwareCanvasRenderer::~SoftwareCanvasRenderer()
|
SoftwareCanvasRenderer::~SoftwareCanvasRenderer()
|
||||||
|
@ -59,14 +61,33 @@ void SoftwareCanvasRenderer::render()
|
||||||
for (int x = 0; x < nx; x++)
|
for (int x = 0; x < nx; x++)
|
||||||
{
|
{
|
||||||
CanvasPortion *portion = canvas->at(x, y);
|
CanvasPortion *portion = canvas->at(x, y);
|
||||||
portion->preparePixels();
|
|
||||||
rasterize(portion, true);
|
if (not render_interrupt)
|
||||||
postProcess(portion, true);
|
{
|
||||||
|
portion->preparePixels();
|
||||||
|
rasterize(portion, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not render_interrupt)
|
||||||
|
{
|
||||||
|
applyPixelShader(portion, true);
|
||||||
|
}
|
||||||
|
|
||||||
portion->discardPixels();
|
portion->discardPixels();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SoftwareCanvasRenderer::interrupt()
|
||||||
|
{
|
||||||
|
SoftwareRenderer::interrupt();
|
||||||
|
|
||||||
|
if (current_work)
|
||||||
|
{
|
||||||
|
current_work->interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const std::vector<Rasterizer *> &SoftwareCanvasRenderer::getRasterizers() const
|
const std::vector<Rasterizer *> &SoftwareCanvasRenderer::getRasterizers() const
|
||||||
{
|
{
|
||||||
return rasterizers;
|
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
|
// Subdivide in chunks
|
||||||
int chunk_size = 64;
|
int chunk_size = 64;
|
||||||
|
@ -96,8 +117,16 @@ void SoftwareCanvasRenderer::postProcess(CanvasPortion *portion, bool threaded)
|
||||||
// Render chunks in parallel
|
// Render chunks in parallel
|
||||||
for (int sub_chunk_size = chunk_size; sub_chunk_size >= 1; sub_chunk_size /= 2)
|
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);
|
CanvasPixelShader shader(*this, portion, chunk_size, sub_chunk_size, chunks_x, chunks_y);
|
||||||
ParallelWork work(&shader, units);
|
ParallelWork work(&shader, units);
|
||||||
|
|
||||||
|
current_work = &work;
|
||||||
work.perform();
|
work.perform();
|
||||||
|
current_work = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,8 @@ public:
|
||||||
*/
|
*/
|
||||||
void render();
|
void render();
|
||||||
|
|
||||||
|
virtual void interrupt() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the list of objects that can be rasterized to polygons on a canvas.
|
* @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.
|
* 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:
|
private:
|
||||||
Canvas* canvas;
|
Canvas *canvas;
|
||||||
std::vector<Rasterizer*> rasterizers;
|
std::vector<Rasterizer*> rasterizers;
|
||||||
bool started;
|
bool started;
|
||||||
|
|
||||||
|
ParallelWork *current_work;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ public:
|
||||||
void disableAtmosphere();
|
void disableAtmosphere();
|
||||||
void disableAtmosphere(const std::vector<LightComponent> &lights);
|
void disableAtmosphere(const std::vector<LightComponent> &lights);
|
||||||
|
|
||||||
void interrupt();
|
virtual void interrupt();
|
||||||
|
|
||||||
inline Scenery* getScenery() const {return scenery;}
|
inline Scenery* getScenery() const {return scenery;}
|
||||||
|
|
||||||
|
|
|
@ -226,10 +226,6 @@ int TerrainRasterizer::processChunk(CanvasPortion* canvas, TerrainChunkInfo* chu
|
||||||
return !renderer->render_interrupt;
|
return !renderer->render_interrupt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainRasterizer::rasterize()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void TerrainRasterizer::rasterizeToCanvas(CanvasPortion *canvas)
|
void TerrainRasterizer::rasterizeToCanvas(CanvasPortion *canvas)
|
||||||
{
|
{
|
||||||
queue = new ParallelQueue();
|
queue = new ParallelQueue();
|
||||||
|
|
|
@ -43,15 +43,8 @@ public:
|
||||||
|
|
||||||
void renderQuad(CanvasPortion* canvas, double x, double z, double size, double water_height);
|
void renderQuad(CanvasPortion* canvas, double x, double z, double size, double water_height);
|
||||||
|
|
||||||
/**
|
virtual void rasterizeToCanvas(CanvasPortion* canvas) override;
|
||||||
* Start the final rasterization of terrain.
|
virtual Color shadeFragment(const CanvasFragment &fragment) const override;
|
||||||
*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ParallelQueue* queue;
|
ParallelQueue* queue;
|
||||||
|
|
|
@ -15,8 +15,8 @@ public:
|
||||||
|
|
||||||
void rasterizeQuad(CanvasPortion* canvas, double x, double z, double size);
|
void rasterizeQuad(CanvasPortion* canvas, double x, double z, double size);
|
||||||
|
|
||||||
virtual void rasterizeToCanvas(CanvasPortion* canvas);
|
virtual void rasterizeToCanvas(CanvasPortion* canvas) override;
|
||||||
virtual Color shadeFragment(const CanvasFragment &fragment) const;
|
virtual Color shadeFragment(const CanvasFragment &fragment) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,6 +172,11 @@ int ParallelWork::perform(int thread_count)
|
||||||
return done;
|
return done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ParallelWork::interrupt()
|
||||||
|
{
|
||||||
|
worker->interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
void ParallelWork::returnThread(ParallelWork::ParallelThread *thread)
|
void ParallelWork::returnThread(ParallelWork::ParallelThread *thread)
|
||||||
{
|
{
|
||||||
mutex->acquire();
|
mutex->acquire();
|
||||||
|
|
|
@ -48,6 +48,13 @@ public:
|
||||||
*/
|
*/
|
||||||
int perform(int thread_count=-1);
|
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:
|
private:
|
||||||
void returnThread(ParallelThread *thread);
|
void returnThread(ParallelThread *thread);
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,14 @@
|
||||||
|
|
||||||
ParallelWorker::ParallelWorker()
|
ParallelWorker::ParallelWorker()
|
||||||
{
|
{
|
||||||
|
interrupted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParallelWorker::~ParallelWorker()
|
ParallelWorker::~ParallelWorker()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ParallelWorker::interrupt()
|
||||||
|
{
|
||||||
|
interrupted = true;
|
||||||
|
}
|
||||||
|
|
|
@ -21,6 +21,14 @@ public:
|
||||||
* This method will be called from any thread in the thread pool used by the ParallelWork.
|
* This method will be called from any thread in the thread pool used by the ParallelWork.
|
||||||
*/
|
*/
|
||||||
virtual int processParallelUnit(int unit) = 0;
|
virtual int processParallelUnit(int unit) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to reimplement to know when to interrupt the processing of units.
|
||||||
|
*/
|
||||||
|
virtual void interrupt();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool interrupted;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue