From b5ee4c432fa8434db03aa0401d163bd09542ec5f Mon Sep 17 00:00:00 2001 From: Michael Lemaire Date: Mon, 18 Aug 2014 16:04:46 +0200 Subject: [PATCH] Added parallel pixel shader for second-pass rendering --- src/render/software/CanvasPixelShader.cpp | 41 +++++++++++++------ src/render/software/CanvasPixelShader.h | 3 +- src/render/software/Rasterizer.cpp | 2 +- src/render/software/SkyRasterizer.cpp | 2 +- .../software/SoftwareCanvasRenderer.cpp | 11 +++-- src/render/software/TerrainRasterizer.cpp | 2 +- src/render/software/WaterRasterizer.cpp | 2 +- 7 files changed, 41 insertions(+), 22 deletions(-) diff --git a/src/render/software/CanvasPixelShader.cpp b/src/render/software/CanvasPixelShader.cpp index 6af6479..43f1940 100644 --- a/src/render/software/CanvasPixelShader.cpp +++ b/src/render/software/CanvasPixelShader.cpp @@ -7,30 +7,45 @@ #include "CanvasFragment.h" #include "Rasterizer.h" -CanvasPixelShader::CanvasPixelShader(const SoftwareCanvasRenderer &renderer, CanvasPortion *portion, int chunk_size, int chunks_x, int chunks_y): - renderer(renderer), portion(portion), chunk_size(chunk_size), chunks_x(chunks_x), chunks_y(chunks_y) +CanvasPixelShader::CanvasPixelShader(const SoftwareCanvasRenderer &renderer, CanvasPortion *portion, int chunk_size, int sub_chunk_size, int chunks_x, int chunks_y): + renderer(renderer), portion(portion), chunk_size(chunk_size), sub_chunk_size(sub_chunk_size), chunks_x(chunks_x), chunks_y(chunks_y) { } int CanvasPixelShader::processParallelUnit(int unit) { // Locate the chunk we work on + int prev_sub_chunk_size = chunk_size * 2; int chunk_x = unit % chunks_x; int chunk_y = unit / chunks_x; + int base_x = chunk_x * chunk_size; + int base_y = chunk_y * chunk_size; + int limit_x = portion->getWidth() - base_x; + int limit_y = portion->getHeight() - base_y; - // Resolve the pixel color - int x = chunk_x * chunk_size; - int y = chunk_y * chunk_size; - const CanvasPixel &pixel = portion->at(x, y); - int n = pixel.getFragmentCount(); - Color composite = COLOR_BLACK; - for (int i = 0; i < n; i++) + limit_x = (limit_x > chunk_size) ? chunk_size : limit_x; + limit_y = (limit_y > chunk_size) ? chunk_size : limit_y; + + for (int x = 0; x < limit_x; x += sub_chunk_size) { - const CanvasFragment &fragment = pixel.getFragment(i); - const Rasterizer &rasterizer = renderer.getRasterizer(fragment.getClient()); - composite.mask(rasterizer.shadeFragment(fragment)); + for (int y = 0; y < limit_y; y += sub_chunk_size) + { + if (x % prev_sub_chunk_size != 0 or y % prev_sub_chunk_size != 0) + { + // Resolve the pixel color + const CanvasPixel &pixel = portion->at(base_x + x, base_y + y); + int n = pixel.getFragmentCount(); + Color composite = COLOR_BLACK; + for (int i = 0; i < n; i++) + { + const CanvasFragment &fragment = pixel.getFragment(i); + const Rasterizer &rasterizer = renderer.getRasterizer(fragment.getClient()); + composite.mask(rasterizer.shadeFragment(fragment)); + } + portion->setColor(base_x + x, base_y + y, composite); + } + } } - portion->setColor(x, y, composite); return 0; } diff --git a/src/render/software/CanvasPixelShader.h b/src/render/software/CanvasPixelShader.h index 700bdd9..ce321c1 100644 --- a/src/render/software/CanvasPixelShader.h +++ b/src/render/software/CanvasPixelShader.h @@ -18,7 +18,7 @@ namespace software { class CanvasPixelShader: public ParallelWorker { public: - CanvasPixelShader(const SoftwareCanvasRenderer &renderer, CanvasPortion *portion, int 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); @@ -26,6 +26,7 @@ private: const SoftwareCanvasRenderer &renderer; CanvasPortion *portion; int chunk_size; + int sub_chunk_size; int chunks_x; int chunks_y; }; diff --git a/src/render/software/Rasterizer.cpp b/src/render/software/Rasterizer.cpp index 009d984..43e4b57 100644 --- a/src/render/software/Rasterizer.cpp +++ b/src/render/software/Rasterizer.cpp @@ -339,7 +339,7 @@ void Rasterizer::renderScanLines(CanvasPortion *canvas, RenderScanlines* scanlin Color frag_color = *color; if (cury == starty || cury == endy) { - frag_color.mask(Color(0.0, 0.0, 0.0, 0.3)); + frag_color.mask(Color(0.0, 0.0, 0.0, 0.1)); } fragment.setColor(frag_color); diff --git a/src/render/software/SkyRasterizer.cpp b/src/render/software/SkyRasterizer.cpp index dedff67..b8251c7 100644 --- a/src/render/software/SkyRasterizer.cpp +++ b/src/render/software/SkyRasterizer.cpp @@ -12,7 +12,7 @@ #define SPHERE_SIZE 20000.0 SkyRasterizer::SkyRasterizer(SoftwareRenderer* renderer, int client_id): - Rasterizer(renderer, client_id, Color(0.3, 0.7, 1.0)) + Rasterizer(renderer, client_id, Color(0.9, 0.9, 1.0)) { } diff --git a/src/render/software/SoftwareCanvasRenderer.cpp b/src/render/software/SoftwareCanvasRenderer.cpp index 4106ffd..a70ba88 100644 --- a/src/render/software/SoftwareCanvasRenderer.cpp +++ b/src/render/software/SoftwareCanvasRenderer.cpp @@ -77,13 +77,16 @@ void SoftwareCanvasRenderer::rasterize(CanvasPortion *portion, bool threaded) void SoftwareCanvasRenderer::postProcess(CanvasPortion *portion, bool threaded) { // Subdivide in chunks - int chunk_size = 32; + int chunk_size = 64; int chunks_x = (portion->getWidth() - 1) / chunk_size + 1; int chunks_y = (portion->getHeight() - 1) / chunk_size + 1; int units = chunks_x * chunks_y; // Render chunks in parallel - CanvasPixelShader shader(*this, portion, chunk_size, chunks_x, chunks_y); - ParallelWork work(&shader, units); - work.perform(); + for (int sub_chunk_size = chunk_size; sub_chunk_size >= 1; sub_chunk_size /= 2) + { + CanvasPixelShader shader(*this, portion, chunk_size, sub_chunk_size, chunks_x, chunks_y); + ParallelWork work(&shader, units); + work.perform(); + } } diff --git a/src/render/software/TerrainRasterizer.cpp b/src/render/software/TerrainRasterizer.cpp index b677b81..ac0afdf 100644 --- a/src/render/software/TerrainRasterizer.cpp +++ b/src/render/software/TerrainRasterizer.cpp @@ -12,7 +12,7 @@ #include "CanvasFragment.h" TerrainRasterizer::TerrainRasterizer(SoftwareRenderer* renderer, int client_id): - Rasterizer(renderer, client_id, Color(0.5, 0.3, 0.3)) + Rasterizer(renderer, client_id, Color(1.0, 0.9, 0.9)) { } diff --git a/src/render/software/WaterRasterizer.cpp b/src/render/software/WaterRasterizer.cpp index 92face3..ee9d681 100644 --- a/src/render/software/WaterRasterizer.cpp +++ b/src/render/software/WaterRasterizer.cpp @@ -6,7 +6,7 @@ #include "CanvasFragment.h" WaterRasterizer::WaterRasterizer(SoftwareRenderer* renderer, int client_id): - Rasterizer(renderer, client_id, Color(0.1, 0.3, 0.6)) + Rasterizer(renderer, client_id, Color(0.9, 0.95, 1.0)) { }