solstice-solver

Solver library of the solstice app
git clone git://git.meso-star.com/solstice-solver.git
Log | Files | Refs | README | LICENSE

ssol_draw.c (5222B)


      1 /* Copyright (C) 2018-2026 |Meso|Star> (contact@meso-star.com)
      2  * Copyright (C) 2016, 2018 CNRS
      3  *
      4  * This program is free software: you can redistribute it and/or modify
      5  * it under the terms of the GNU General Public License as published by
      6  * the Free Software Foundation, either version 3 of the License, or
      7  * (at your option) any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     12  * GNU General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU General Public License
     15  * along with this program. If not, see <http://www.gnu.org/licenses/>. */
     16 
     17 #include "ssol.h"
     18 #include "ssol_device_c.h"
     19 #include "ssol_draw.h"
     20 #include "ssol_scene_c.h"
     21 
     22 #include <star/s3d.h>
     23 
     24 #include <omp.h>
     25 #include <star/ssf.h>
     26 #include <star/ssp.h>
     27 
     28 #define TILE_SIZE 32 /* definition in X & Y of a tile */
     29 STATIC_ASSERT(IS_POW2(TILE_SIZE), TILE_SIZE_must_be_a_power_of_2);
     30 
     31 /*******************************************************************************
     32  * Helper function
     33  ******************************************************************************/
     34 static FINLINE uint16_t
     35 morton2D_decode(const uint32_t u32)
     36 {
     37   uint32_t x = u32 & 0x55555555;
     38   x = (x | (x >> 1)) & 0x33333333;
     39   x = (x | (x >> 2)) & 0x0F0F0F0F;
     40   x = (x | (x >> 4)) & 0x00FF00FF;
     41   x = (x | (x >> 8)) & 0x0000FFFF;
     42   return (uint16_t)x;
     43 }
     44 
     45 static void
     46 draw_tile
     47   (struct ssol_scene* scn,
     48    struct s3d_scene_view* view,
     49    const struct ssol_camera* cam,
     50    const int ithread,
     51    const size_t spp,
     52    const size_t origin[2], /* Tile origin */
     53    const size_t size[2], /* Tile definition */
     54    const float pix_sz[2], /* Normalized size of a pixel in the image plane */
     55    double* pixels,
     56    pixel_shader_T shader,
     57    void* shader_data)
     58 {
     59   size_t npixels;
     60   size_t mcode; /* Morton code of the tile pixel */
     61   ASSERT(scn && view && cam && spp && origin && size && pix_sz && pixels);
     62   ASSERT(shader);
     63 
     64   /* Adjust the #pixels to process them wrt a morton order */
     65   npixels = round_up_pow2(MMAX(size[0], size[1]));
     66   npixels *= npixels;
     67 
     68   FOR_EACH(mcode, 0, npixels) {
     69     size_t ipix[2];
     70     double* pixel;
     71 
     72     ipix[0] = morton2D_decode((uint32_t)(mcode>>0));
     73     if(ipix[0] >= size[0]) continue;
     74     ipix[1] = morton2D_decode((uint32_t)(mcode>>1));
     75     if(ipix[1] >= size[1]) continue;
     76 
     77     pixel = pixels + (ipix[1]*size[0] + ipix[0])*3/*#channels*/;
     78     ipix[0] = ipix[0] + origin[0];
     79     ipix[1] = ipix[1] + origin[1];
     80 
     81     shader(scn, cam, view, ithread, ipix, pix_sz, spp, pixel, shader_data);
     82   }
     83 }
     84 
     85 /*******************************************************************************
     86  * Local function
     87  ******************************************************************************/
     88 res_T
     89 draw
     90   (struct ssol_scene* scn,
     91    const struct ssol_camera* cam,
     92    const size_t width,
     93    const size_t height,
     94    const size_t spp, /* #samples per pixel */
     95    ssol_write_pixels_T writer,
     96    void* writer_data,
     97    pixel_shader_T pixel_shader,
     98    void* pixel_shader_data)
     99 {
    100   struct s3d_scene_view* view = NULL;
    101   struct darray_byte* tiles = NULL;
    102   int64_t mcode; /* Morton code of a tile */
    103   float pix_sz[2];
    104   size_t ntiles_x, ntiles_y, ntiles;
    105   size_t i;
    106   ATOMIC res = RES_OK;
    107 
    108   if(!scn || !cam || !width || !height || !spp || !writer || !pixel_shader)
    109     return RES_BAD_ARG;
    110 
    111   tiles = darray_tile_data_get(&scn->dev->tiles);
    112   ASSERT(darray_tile_size_get(&scn->dev->tiles) == scn->dev->nthreads);
    113   FOR_EACH(i, 0, scn->dev->nthreads) {
    114     const size_t sizeof_tile = TILE_SIZE * TILE_SIZE * sizeof(double[3]);
    115     res = darray_byte_resize(tiles+i, sizeof_tile);
    116     if(res != RES_OK) goto error;
    117   }
    118 
    119   ntiles_x = (width + (TILE_SIZE-1)/*ceil*/)/TILE_SIZE;
    120   ntiles_y = (height+ (TILE_SIZE-1)/*ceil*/)/TILE_SIZE;
    121   ntiles = round_up_pow2(MMAX(ntiles_x, ntiles_y));
    122   ntiles *= ntiles;
    123 
    124   pix_sz[0] = 1.f / (float)width;
    125   pix_sz[1] = 1.f / (float)height;
    126 
    127   res = s3d_scene_view_create(scn->scn_rt, S3D_TRACE, &view);
    128   if(res != RES_OK) goto error;
    129 
    130   #pragma omp parallel for schedule(dynamic, 1/*chunck size*/)
    131   for(mcode=0; mcode<(int64_t)ntiles; ++mcode) {
    132     size_t tile_org[2];
    133     size_t tile_sz[2];
    134     const int ithread = omp_get_thread_num();
    135     double* pixels;
    136     res_T res_local;
    137 
    138     if(ATOMIC_GET(&res) != RES_OK) continue;
    139 
    140     tile_org[0] = morton2D_decode((uint32_t)(mcode>>0));
    141     if(tile_org[0] >= ntiles_x) continue;
    142     tile_org[1] = morton2D_decode((uint32_t)(mcode>>1));
    143     if(tile_org[1] >= ntiles_y) continue;
    144 
    145     tile_org[0] *= TILE_SIZE;
    146     tile_org[1] *= TILE_SIZE;
    147     tile_sz[0] = MMIN(TILE_SIZE, width - tile_org[0]);
    148     tile_sz[1] = MMIN(TILE_SIZE, height- tile_org[1]);
    149 
    150     pixels = (double*)darray_byte_data_get(tiles+ithread);
    151 
    152     draw_tile(scn, view, cam, ithread, spp, tile_org, tile_sz, pix_sz, pixels,
    153       pixel_shader, pixel_shader_data);
    154 
    155     res_local = writer(writer_data, tile_org, tile_sz, SSOL_PIXEL_DOUBLE3, pixels);
    156     if(res_local != RES_OK) {
    157       ATOMIC_SET(&res, res_local);
    158       continue;
    159     }
    160   }
    161 
    162 exit:
    163   if(view) S3D(scene_view_ref_put(view));
    164   return (res_T)res;
    165 error:
    166   goto exit;
    167 }
    168 
    169