star-schiff

Library for estimating radiative properties
git clone git://git.meso-star.com/star-schiff.git
Log | Files | Refs | README | LICENSE

sschiff_device.c (5206B)


      1 /* Copyright (C) 2015, 2016, 2026 Centre National de la Recherche Scientifique
      2  * Copyright (C) 2026 Clermont Auvergne INP
      3  * Copyright (C) 2026 Institut Mines Télécom Albi-Carmaux
      4  * Copyright (C) 2020, 2021, 2023, 2026 |Méso|Star> (contact@meso-star.com)
      5  * Copyright (C) 2026 Université de Lorraine
      6  * Copyright (C) 2026 Université de Toulouse
      7  *
      8  * This program is free software: you can redistribute it and/or modify
      9  * it under the terms of the GNU General Public License as published by
     10  * the Free Software Foundation, either version 3 of the License, or
     11  * (at your option) any later version.
     12  *
     13  * This program is distributed in the hope that it will be useful,
     14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     16  * GNU General Public License for more details.
     17  *
     18  * You should have received a copy of the GNU General Public License
     19  * along with this program. If not, see <http://www.gnu.org/licenses/>. */
     20 
     21 #include "sschiff.h"
     22 #include "sschiff_device.h"
     23 
     24 #include <rsys/logger.h>
     25 #include <rsys/mem_allocator.h>
     26 #include <rsys/stretchy_array.h>
     27 
     28 #include <star/s3d.h>
     29 
     30 #include <stdarg.h>
     31 
     32 #include <omp.h>
     33 
     34 /*******************************************************************************
     35  * Helper function
     36  ******************************************************************************/
     37 static void
     38 device_release(ref_T* ref)
     39 {
     40   struct sschiff_device* dev;
     41   ASSERT(ref);
     42   dev = CONTAINER_OF(ref, struct sschiff_device, ref);
     43   if(dev->s3d) {
     44     size_t i;
     45     FOR_EACH(i, 0, dev->nthreads) {
     46       if(dev->s3d[i]) S3D(device_ref_put(dev->s3d[i]));
     47     }
     48     sa_release(dev->s3d);
     49   }
     50   MEM_RM(dev->allocator, dev);
     51 }
     52 
     53 /*******************************************************************************
     54  * Local functions
     55  ******************************************************************************/
     56 void
     57 log_error(struct sschiff_device* dev, const char* msg, ...)
     58 {
     59   va_list vargs_list;
     60   ASSERT(dev && msg);
     61   if(dev->verbose) {
     62     res_T res; (void)res;
     63     va_start(vargs_list, msg);
     64     res = logger_vprint(dev->logger, LOG_ERROR, msg, vargs_list);
     65     ASSERT(res == RES_OK);
     66     va_end(vargs_list);
     67   }
     68 }
     69 
     70 void
     71 log_warning(struct sschiff_device* dev, const char* msg, ...)
     72 {
     73   va_list vargs_list;
     74   ASSERT(dev && msg);
     75   if(dev->verbose) {
     76     res_T res; (void)res;
     77     va_start(vargs_list, msg);
     78     res = logger_vprint(dev->logger, LOG_WARNING, msg, vargs_list);
     79     ASSERT(res == RES_OK);
     80     va_end(vargs_list);
     81   }
     82 }
     83 
     84 /*******************************************************************************
     85  * API functions
     86  ******************************************************************************/
     87 res_T
     88 sschiff_device_create
     89   (struct logger* log,
     90    struct mem_allocator* allocator,
     91    const unsigned nthreads_hint,
     92    const int verbose,
     93    struct s3d_device* s3d,
     94    struct sschiff_device** out_dev)
     95 {
     96   struct mem_allocator* mem_allocator;
     97   struct sschiff_device* dev = NULL;
     98   struct logger* logger = NULL;
     99   size_t i;
    100   res_T res = RES_OK;
    101 
    102   if(!out_dev || !nthreads_hint) {
    103     res = RES_BAD_ARG;
    104     goto error;
    105   }
    106 
    107   mem_allocator = allocator ? allocator : &mem_default_allocator;
    108   logger = log ? log : LOGGER_DEFAULT;
    109 
    110   dev = MEM_CALLOC(mem_allocator, 1, sizeof(struct sschiff_device));
    111   if(!dev) {
    112     log_error(dev, "Couldn't allocate the Star-Schiff device.\n");
    113     res = RES_MEM_ERR;
    114     goto error;
    115   }
    116   ref_init(&dev->ref);
    117   dev->allocator = mem_allocator;
    118   dev->logger = logger;
    119   dev->verbose = verbose;
    120   dev->nthreads = MMIN(nthreads_hint, (unsigned)omp_get_num_procs());
    121 
    122   if(!sa_add(dev->s3d, dev->nthreads)) {
    123     log_error(dev,
    124       "Not enough memory: couldn't allocate the list of S3D devices.\n");
    125     res = RES_MEM_ERR;
    126     goto error;
    127   }
    128   memset(dev->s3d, 0, sizeof(struct s3d_device*)*dev->nthreads);
    129 
    130   FOR_EACH(i, 0, dev->nthreads) {
    131     if(s3d) {
    132       S3D(device_ref_get(s3d));
    133       dev->s3d[i] = s3d;
    134     } else {
    135       /* Create as many Star-3D devices as threads since this is actually more
    136        * efficient. It seems that the Star-3D back-end (i.e. embree) shared
    137        * some ressources - and thus perform some synchronisations leading to
    138        * performance loss - if several acceleration data structures are build
    139        * on the same device. */
    140       res = s3d_device_create(dev->logger, dev->allocator, 0, &dev->s3d[i]);
    141       if(res != RES_OK) {
    142         log_error
    143           (dev, "Couldn't create the internal Star-3D device of Star-Schiff.\n");
    144         goto error;
    145       }
    146     }
    147   }
    148 
    149   omp_set_num_threads((int)dev->nthreads);
    150 
    151 exit:
    152   if(out_dev) *out_dev = dev;
    153   return res;
    154 error:
    155   if(dev) {
    156     SSCHIFF(device_ref_put(dev));
    157     dev = NULL;
    158   }
    159   goto exit;
    160 }
    161 
    162 res_T
    163 sschiff_device_get_threads_count(struct sschiff_device* dev, unsigned* nthreads)
    164 {
    165   if(!dev || !nthreads) return RES_BAD_ARG;
    166   *nthreads = dev->nthreads;
    167   return RES_OK;
    168 }
    169 
    170 res_T
    171 sschiff_device_ref_get(struct sschiff_device* dev)
    172 {
    173   if(!dev) return RES_BAD_ARG;
    174   ref_get(&dev->ref);
    175   return RES_OK;
    176 }
    177 
    178 res_T
    179 sschiff_device_ref_put(struct sschiff_device* dev)
    180 {
    181   if(!dev) return RES_BAD_ARG;
    182   ref_put(&dev->ref, device_release);
    183   return RES_OK;
    184 }
    185