erebus
diff liberebus/src/erebus.cc @ 26:c8a6fb04fefa
multithreadededit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 01 Jun 2014 19:19:40 +0300 |
parents | 6204e4d3f445 |
children | 0ced900e15a7 |
line diff
1.1 --- a/liberebus/src/erebus.cc Sat May 31 06:21:09 2014 +0300 1.2 +++ b/liberebus/src/erebus.cc Sun Jun 01 19:19:40 2014 +0300 1.3 @@ -12,8 +12,7 @@ 1.4 1.5 using namespace std::chrono; 1.6 1.7 -#define INVALID_RECT Rect{0, 0, 0, 0} 1.8 - 1.9 +static void render_block(struct erebus *ctx, Block blk); 1.10 static void render_pixel(struct erebus *ctx, int x, int y, int sample); 1.11 1.12 static std::mt19937 rnd_gen; 1.13 @@ -34,7 +33,7 @@ 1.14 1.15 ctx->scn = 0; 1.16 ctx->cur_time = 0; 1.17 - ctx->cur_rect = INVALID_RECT; 1.18 + ctx->cur_frame = 0; 1.19 1.20 erb_setoptf(ctx, ERB_OPT_GAMMA, 2.2); 1.21 erb_setopti(ctx, ERB_OPT_MAX_ITER, 6); 1.22 @@ -125,16 +124,24 @@ 1.23 void erb_begin_frame(struct erebus *ctx, long ms) 1.24 { 1.25 printf("starting new frame...\n"); 1.26 + ++ctx->cur_frame; 1.27 + ctx->cur_sample = 0; 1.28 ctx->cur_time = ms; 1.29 1.30 int xsz = erb_getopti(ctx, ERB_OPT_WIDTH); 1.31 int ysz = erb_getopti(ctx, ERB_OPT_HEIGHT); 1.32 1.33 - ctx->fbimg.create(xsz, ysz); 1.34 - ctx->accum.create(xsz, ysz); 1.35 + if(!ctx->fbimg.get_pixels() || ctx->fbimg.get_width() != xsz || ctx->fbimg.get_height() < ysz) { 1.36 + ctx->fbimg.create(xsz, ysz); 1.37 + ctx->accum.create(xsz, ysz); 1.38 + } else { 1.39 + ctx->fbimg.clear(); 1.40 + ctx->accum.clear(); 1.41 + } 1.42 1.43 - ctx->cur_rect = INVALID_RECT; 1.44 ctx->inv_gamma = 1.0f / erb_getoptf(ctx, ERB_OPT_GAMMA); 1.45 + 1.46 + ctx->scn->update(ctx->cur_time); 1.47 } 1.48 1.49 int erb_render(struct erebus *ctx, long timeout) 1.50 @@ -142,56 +149,48 @@ 1.51 return erb_render_rect(ctx, 0, 0, ctx->fbimg.get_width(), ctx->fbimg.get_height(), timeout); 1.52 } 1.53 1.54 +#define BLKSZ 32 1.55 + 1.56 int erb_render_rect(struct erebus *ctx, int x, int y, int width, int height, long timeout) 1.57 { 1.58 + while(ctx->tpool.pending()) { 1.59 + if(timeout > 0) { 1.60 + long wait_interval = ctx->tpool.wait(timeout); 1.61 + timeout -= wait_interval; 1.62 + } else { 1.63 + return 1; 1.64 + } 1.65 + } 1.66 + 1.67 if(!width || !height) return -1; 1.68 1.69 - Rect rect{x, y, width, height}; 1.70 - if(ctx->cur_rect != rect) { 1.71 - // starting a new rendering apparently 1.72 - ctx->cur_rect = rect; 1.73 - ctx->cur_pixel_x = x; 1.74 - ctx->cur_pixel_y = y; 1.75 - ctx->cur_sample = 0; 1.76 + int startx = x; 1.77 + int endx = x + width; 1.78 + int endy = y + height; 1.79 + 1.80 + while(y < endy) { 1.81 + x = startx; 1.82 + while(x < endx) { 1.83 + Block blk; 1.84 + blk.x = x; 1.85 + blk.y = y; 1.86 + blk.width = std::min(BLKSZ, endx - x); 1.87 + blk.height = std::min(BLKSZ, endy - y); 1.88 + blk.sample = ctx->cur_sample; 1.89 + blk.frame = ctx->cur_frame; 1.90 + 1.91 + ctx->tpool.add_work(std::bind(render_block, ctx, blk)); 1.92 + 1.93 + x += BLKSZ; 1.94 + } 1.95 + y += BLKSZ; 1.96 } 1.97 1.98 - ctx->scn->update(); 1.99 + ++ctx->cur_sample; 1.100 + ctx->tpool.wait(timeout); // wait for completion 1.101 + return ctx->cur_sample > erb_getopti(ctx, ERB_OPT_MAX_SAMPLES) ? 0 : 1; 1.102 +} 1.103 1.104 - int max_samples = erb_getopti(ctx, ERB_OPT_MAX_SAMPLES); 1.105 - 1.106 - if(timeout > 0) { 1.107 - auto start_time = steady_clock::now(); 1.108 - while(duration_cast<milliseconds>(steady_clock::now() - start_time).count() < timeout) { 1.109 - render_pixel(ctx, ctx->cur_pixel_x, ctx->cur_pixel_y, ctx->cur_sample); 1.110 - 1.111 - if(++ctx->cur_pixel_x >= ctx->cur_rect.width) { 1.112 - ctx->cur_pixel_x = ctx->cur_rect.x; 1.113 - if(++ctx->cur_pixel_y >= ctx->cur_rect.height) { 1.114 - ctx->cur_pixel_y = ctx->cur_rect.y; 1.115 - if(++ctx->cur_sample >= max_samples) { 1.116 - ctx->cur_rect = INVALID_RECT; 1.117 - return 0; 1.118 - } 1.119 - } 1.120 - } 1.121 - } 1.122 - return 1; 1.123 - } 1.124 - 1.125 - if(max_samples == INF_SAMPLES) { 1.126 - // don't allow infinite samples when rendering non-progressively 1.127 - max_samples = 128; 1.128 - } 1.129 - 1.130 - for(int i=0; i<height; i++) { 1.131 - for(int j=0; j<width; j++) { 1.132 - for(int k=0; k<max_samples; k++) { 1.133 - render_pixel(ctx, j, i, k); 1.134 - } 1.135 - } 1.136 - } 1.137 - return 0; 1.138 -} 1.139 1.140 int erb_get_progress(struct erebus *ctx) 1.141 { 1.142 @@ -335,6 +334,19 @@ 1.143 return unirnd(rnd_gen); 1.144 } 1.145 1.146 +static void render_block(struct erebus *ctx, Block blk) 1.147 +{ 1.148 + if(blk.frame < ctx->cur_frame) { 1.149 + return; // skip stale blocks 1.150 + } 1.151 + 1.152 + for(int i=0; i<blk.height; i++) { 1.153 + for(int j=0; j<blk.width; j++) { 1.154 + render_pixel(ctx, blk.x + j, blk.y + i, blk.sample); 1.155 + } 1.156 + } 1.157 +} 1.158 + 1.159 static void render_pixel(struct erebus *ctx, int x, int y, int sample) 1.160 { 1.161 Camera *cam = ctx->scn->get_active_camera(); 1.162 @@ -360,14 +372,3 @@ 1.163 pix[2] = pow(accum[2] * inv_samples, ctx->inv_gamma); 1.164 pix[3] = accum[3] * inv_samples; 1.165 } 1.166 - 1.167 -bool Rect::operator ==(const Rect &r) const 1.168 -{ 1.169 - return memcmp(this, &r, sizeof r) == 0; 1.170 -} 1.171 - 1.172 -bool Rect::operator !=(const Rect &r) const 1.173 -{ 1.174 - return memcmp(this, &r, sizeof r) != 0; 1.175 -} 1.176 -