solstice-solver

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

commit 8b7d952dda10c81f5ff50db0828e5b499848f92f
parent ec19567c234437e145aa5c18fe54cc35b6aca76c
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue,  5 Sep 2017 15:41:21 +0200

Use a per thread LIFO allocator to create the material BSDFs

This drastically improves the integration performances by reducing the
thread concurrency on the ssol_device allocator during the BSDF creation.

Diffstat:
Msrc/ssol_device.c | 24++++++++++++++++++++++--
Msrc/ssol_device_c.h | 1+
Msrc/ssol_material.c | 29++++++++++++++++++-----------
Msrc/test_ssol_by_receiver_integration.c | 16++++++++++++----
4 files changed, 53 insertions(+), 17 deletions(-)

diff --git a/src/ssol_device.c b/src/ssol_device.c @@ -18,6 +18,7 @@ #include <rsys/logger.h> #include <rsys/mem_allocator.h> +#include <rsys/mem_lifo_allocator.h> #include <star/s3d.h> #include <star/scpr.h> @@ -49,6 +50,13 @@ device_release(ref_T* ref) ASSERT(ref); dev = CONTAINER_OF(ref, struct ssol_device, ref); darray_tile_release(&dev->tiles); + if(dev->bsdf_allocators) { + unsigned i; + FOR_EACH(i, 0, dev->nthreads) { + mem_shutdown_lifo_allocator(&dev->bsdf_allocators[i]); + } + MEM_RM(dev->allocator, dev->bsdf_allocators); + } if(dev->s3d) S3D(device_ref_put(dev->s3d)); if(dev->scpr_mesh) SCPR(mesh_ref_put(dev->scpr_mesh)); MEM_RM(dev->allocator, dev); @@ -67,6 +75,7 @@ ssol_device_create { struct ssol_device* dev = NULL; struct mem_allocator* allocator; + unsigned i; res_T res = RES_OK; if(nthreads_hint == 0 || !out_dev) { @@ -88,12 +97,23 @@ ssol_device_create dev->nthreads = MMIN(nthreads_hint, (unsigned)omp_get_num_procs()); omp_set_num_threads((int)dev->nthreads); + dev->bsdf_allocators = MEM_CALLOC + (dev->allocator, dev->nthreads, sizeof(struct mem_allocator)); + if(!dev->bsdf_allocators) { + res = RES_MEM_ERR; + goto error; + } + + FOR_EACH(i, 0, dev->nthreads) { + res = mem_init_lifo_allocator + (&dev->bsdf_allocators[i], dev->allocator, 4096); + if(res != RES_OK) goto error; + } + res = darray_tile_resize(&dev->tiles, dev->nthreads); if(res != RES_OK) goto error; - res = s3d_device_create(logger, mem_allocator, 0, &dev->s3d); if(res != RES_OK) goto error; - res = scpr_mesh_create(mem_allocator, &dev->scpr_mesh); if(res != RES_OK) goto error; diff --git a/src/ssol_device_c.h b/src/ssol_device_c.h @@ -39,6 +39,7 @@ struct s3d_device; struct ssol_device { struct logger* logger; struct mem_allocator* allocator; + struct mem_allocator* bsdf_allocators; /* Per thread allocator */ unsigned nthreads; int verbose; diff --git a/src/ssol_material.c b/src/ssol_material.c @@ -32,6 +32,7 @@ #include <star/ssf.h> #include <math.h> +#include <omp.h> /******************************************************************************* * Helper functions @@ -96,6 +97,7 @@ create_dielectric_bsdf struct ssf_bsdf** bsdf) { double eta_i, eta_t; + const int ithread = omp_get_thread_num(); res_T res = RES_OK; ASSERT(mtl && fragment && mtl->type == SSOL_MATERIAL_DIELECTRIC); ASSERT(medium && bsdf); @@ -111,15 +113,15 @@ create_dielectric_bsdf eta_t = ssol_data_get_value(&mtl->in_medium.refractive_index, wavelength); #define CALL(Func) { res = Func; if(res != RES_OK) goto error; } (void)0 - CALL(ssf_bsdf_create - (mtl->dev->allocator, &ssf_specular_dielectric_dielectric_interface, bsdf)); + CALL(ssf_bsdf_create(&mtl->dev->bsdf_allocators[ithread], + &ssf_specular_dielectric_dielectric_interface, bsdf)); CALL(ssf_specular_dielectric_dielectric_interface_setup(*bsdf, eta_i, eta_t)); #undef CALL exit: return res; error: - if(bsdf) SSF(bsdf_ref_put(*bsdf)), bsdf = NULL; + if(*bsdf) SSF(bsdf_ref_put(*bsdf)), bsdf = NULL; goto exit; } @@ -131,6 +133,7 @@ create_matte_bsdf struct ssf_bsdf** bsdf) { double reflectivity; + const int ithread = omp_get_thread_num(); res_T res; ASSERT(mtl && fragment && mtl->type == SSOL_MATERIAL_MATTE); ASSERT(bsdf); @@ -140,7 +143,8 @@ create_matte_bsdf (mtl->dev, mtl->buf, wavelength, fragment, &reflectivity); /* Setup the BRDF */ - res = ssf_bsdf_create(mtl->dev->allocator, &ssf_lambertian_reflection, bsdf); + res = ssf_bsdf_create + (&mtl->dev->bsdf_allocators[ithread], &ssf_lambertian_reflection, bsdf); if(res != RES_OK) goto error; res = ssf_lambertian_reflection_setup(*bsdf, reflectivity); if(res != RES_OK) goto error; @@ -148,7 +152,7 @@ create_matte_bsdf exit: return res; error: - if(bsdf) SSF(bsdf_ref_put(*bsdf)), bsdf = NULL; + if(*bsdf) SSF(bsdf_ref_put(*bsdf)), bsdf = NULL; goto exit; } @@ -164,6 +168,7 @@ create_mirror_bsdf struct ssf_microfacet_distribution* distrib = NULL; double roughness; double reflectivity; + const int ithread = omp_get_thread_num(); res_T res; ASSERT(mtl && fragment && mtl->type == SSOL_MATERIAL_MIRROR); ASSERT(bsdf); @@ -182,7 +187,8 @@ create_mirror_bsdf /* Setup the BRDF */ if(roughness == 0) { /* Purely specular reflection */ - res = ssf_bsdf_create(mtl->dev->allocator, &ssf_specular_reflection, bsdf); + res = ssf_bsdf_create + (&mtl->dev->bsdf_allocators[ithread], &ssf_specular_reflection, bsdf); if(res != RES_OK) goto error; res = ssf_specular_reflection_setup(*bsdf, fresnel); if(res != RES_OK) goto error; @@ -198,10 +204,10 @@ create_mirror_bsdf * lighting. */ if(rendering) { res = ssf_bsdf_create - (mtl->dev->allocator, &ssf_microfacet_reflection, bsdf); + (&mtl->dev->bsdf_allocators[ithread], &ssf_microfacet_reflection, bsdf); } else { res = ssf_bsdf_create - (mtl->dev->allocator, &ssf_microfacet2_reflection, bsdf); + (&mtl->dev->bsdf_allocators[ithread], &ssf_microfacet2_reflection, bsdf); } if(res != RES_OK) goto error; res = ssf_microfacet_reflection_setup(*bsdf, fresnel, distrib); @@ -213,7 +219,7 @@ exit: if(distrib) SSF(microfacet_distribution_ref_put(distrib)); return res; error: - if(bsdf) SSF(bsdf_ref_put(*bsdf)), bsdf = NULL; + if(*bsdf) SSF(bsdf_ref_put(*bsdf)), bsdf = NULL; goto exit; } @@ -228,6 +234,7 @@ create_thin_dielectric_bsdf double absorption; double eta_i; double eta_t; + const int ithread = omp_get_thread_num(); res_T res = RES_OK; ASSERT(mtl && fragment && mtl->type == SSOL_MATERIAL_THIN_DIELECTRIC); ASSERT(bsdf); @@ -242,7 +249,7 @@ create_thin_dielectric_bsdf /* Setup the BxDF */ res = ssf_bsdf_create - (mtl->dev->allocator, &ssf_thin_specular_dielectric, bsdf); + (&mtl->dev->bsdf_allocators[ithread], &ssf_thin_specular_dielectric, bsdf); if(res != RES_OK) goto error; res = ssf_thin_specular_dielectric_setup (*bsdf, absorption, eta_i, eta_t, thickness); @@ -251,7 +258,7 @@ create_thin_dielectric_bsdf exit: return res; error: - if(bsdf) SSF(bsdf_ref_put(*bsdf)), bsdf = NULL; + if(*bsdf) SSF(bsdf_ref_put(*bsdf)), bsdf = NULL; goto exit; } diff --git a/src/test_ssol_by_receiver_integration.c b/src/test_ssol_by_receiver_integration.c @@ -139,22 +139,30 @@ main(int argc, char** argv) printf("Ir(target) = %g +/- %g\n", mc_rcv.integrated_irradiance.E, mc_rcv.integrated_irradiance.SE); CHECK(ssol_instance_set_receiver(heliostat, SSOL_FRONT, 0), RES_OK); - CHECK(eq_eps(mc_rcv.integrated_irradiance.E, S_DNI_cos, S_DNI_cos * 2e-1), 1); + CHECK(eq_eps + (mc_rcv.integrated_irradiance.E, S_DNI_cos, + mc_rcv.integrated_irradiance.SE*3), 1); CHECK(ssol_solve(scene, rng, 8 * N__, 0, NULL, &estimator2), RES_OK); CHECK(GET_MC_RCV(estimator2, target, SSOL_FRONT, &mc_rcv), RES_OK); printf("Ir(target) = %g +/- %g\n", mc_rcv.integrated_irradiance.E, mc_rcv.integrated_irradiance.SE); - CHECK(eq_eps(mc_rcv.integrated_irradiance.E, S_DNI_cos, S_DNI_cos * 5e-2), 1); + CHECK(eq_eps + (mc_rcv.integrated_irradiance.E, S_DNI_cos, + mc_rcv.integrated_irradiance.SE*3), 1); CHECK(ssol_estimator_ref_put(estimator1), RES_OK); CHECK(ssol_solve(scene, rng, 3 * N__, 0, NULL, &estimator1), RES_OK); CHECK(GET_MC_RCV(estimator1, target, SSOL_FRONT, &mc_rcv), RES_OK); printf("Ir(target) = %g +/- %g\n", mc_rcv.integrated_irradiance.E, mc_rcv.integrated_irradiance.SE); - CHECK(eq_eps(mc_rcv.integrated_irradiance.E, S_DNI_cos, S_DNI_cos * 1e-1), 1); + CHECK(eq_eps + (mc_rcv.integrated_irradiance.E, S_DNI_cos, + mc_rcv.integrated_irradiance.SE*3), 1); CHECK(GET_MC_SAMP_X_RCV(estimator1, heliostat, target, SSOL_FRONT, &mc_rcv), RES_OK); printf("Ir(heliostat=>target) = %g +/- %g\n", mc_rcv.integrated_irradiance.E, mc_rcv.integrated_irradiance.SE); - CHECK(eq_eps(mc_rcv.integrated_irradiance.E, S_DNI_cos, S_DNI_cos * 1e-1), 1); + CHECK(eq_eps + (mc_rcv.integrated_irradiance.E, S_DNI_cos, + mc_rcv.integrated_irradiance.SE*3), 1); /* Free data */ CHECK(ssol_instance_ref_put(heliostat), RES_OK);