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)
|
||||
{
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
if (not render_interrupt)
|
||||
{
|
||||
portion->preparePixels();
|
||||
rasterize(portion, true);
|
||||
postProcess(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
std::vector<Rasterizer*> rasterizers;
|
||||
bool started;
|
||||
|
||||
ParallelWork *current_work;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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;}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -2,8 +2,14 @@
|
|||
|
||||
ParallelWorker::ParallelWorker()
|
||||
{
|
||||
interrupted = false;
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
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