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