rngrd

Describe a surface and its physical properties
git clone git://git.meso-star.fr/rngrd.git
Log | Files | Refs | README | LICENSE

commit d16bb582620c075a9dfab21984e55c3e353fc9d5
parent c44a28638b5f67be4a4c4ca47f356f2fd195b2b8
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Fri, 30 Sep 2022 11:32:37 +0200

Pre-allocate the list of BSDF for each material

Diffstat:
Msrc/rngrd.c | 59++++++++++++++++++++++++++++++++++++++++++++++++++---------
Msrc/rngrd_c.h | 51++++++++++++++++++++++++++++++++++++++++++++-------
Msrc/rngrd_properties.c | 225+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
3 files changed, 234 insertions(+), 101 deletions(-)

diff --git a/src/rngrd.c b/src/rngrd.c @@ -26,6 +26,7 @@ #include <star/s3d.h> #include <star/sbuf.h> +#include <star/ssf.h> #include <rsys/cstr.h> #include <rsys/mem_allocator.h> @@ -194,35 +195,75 @@ error: * Local functions ******************************************************************************/ res_T -mtl_init(struct mem_allocator* allocator, struct mrumtl** mtl) +bsdf_init(struct mem_allocator* allocator, struct ssf_bsdf** bsdf) { + ASSERT(bsdf); (void)allocator; - *mtl = NULL; + *bsdf = NULL; return RES_OK; } void -mtl_release(struct mrumtl** mtl) +bsdf_release(struct ssf_bsdf** bsdf) { - if(*mtl) MRUMTL(ref_put(*mtl)); + ASSERT(bsdf); + if(*bsdf) SSF(bsdf_ref_put(*bsdf)); } res_T -mtl_copy(struct mrumtl** dst, struct mrumtl* const* src) +bsdf_copy(struct ssf_bsdf** dst, struct ssf_bsdf* const* src) { ASSERT(dst && src); - if(*dst) MRUMTL(ref_put(*dst)); + if(*dst) SSF(bsdf_ref_put(*dst)); *dst = *src; - if(*dst) MRUMTL(ref_get(*dst)); + if(*dst) SSF(bsdf_ref_get(*dst)); return RES_OK; } res_T -mtl_copy_and_release(struct mrumtl** dst, struct mrumtl** src) +bsdf_copy_and_release(struct ssf_bsdf** dst, struct ssf_bsdf** src) { ASSERT(dst && src); - if(*dst) MRUMTL(ref_put(*dst)); + if(*dst) SSF(bsdf_ref_put(*dst)); *dst = *src; *src = NULL; return RES_OK; } + + +res_T +mtl_init(struct mem_allocator* allocator, struct mtl* mtl) +{ + ASSERT(mtl); + mtl->mrumtl = NULL; + darray_bsdf_init(allocator, &mtl->bsdf_lst); + return RES_OK; +} + +void +mtl_release(struct mtl* mtl) +{ + ASSERT(mtl); + if(mtl->mrumtl) MRUMTL(ref_put(mtl->mrumtl)); + darray_bsdf_release(&mtl->bsdf_lst); +} + +res_T +mtl_copy(struct mtl* dst, const struct mtl* src) +{ + ASSERT(dst && src); + if(dst->mrumtl) MRUMTL(ref_put(dst->mrumtl)); + dst->mrumtl = src->mrumtl; + if(dst->mrumtl) MRUMTL(ref_get(dst->mrumtl)); + return darray_bsdf_copy(&dst->bsdf_lst, &src->bsdf_lst);; +} + +res_T +mtl_copy_and_release(struct mtl* dst, struct mtl* src) +{ + ASSERT(dst && src); + if(dst->mrumtl) MRUMTL(ref_put(dst->mrumtl)); + dst->mrumtl = src->mrumtl; + src->mrumtl = NULL; + return darray_bsdf_copy_and_release(&dst->bsdf_lst, &src->bsdf_lst); +} diff --git a/src/rngrd_c.h b/src/rngrd_c.h @@ -28,32 +28,69 @@ struct rngrd_create_args; struct mrumtl; +struct ssf_bsdf; + +/******************************************************************************* + * BSDF + ******************************************************************************/ +extern LOCAL_SYM res_T +bsdf_init + (struct mem_allocator* allocator, + struct ssf_bsdf** bsdf); + +extern LOCAL_SYM void +bsdf_release + (struct ssf_bsdf** bsdf); + +extern LOCAL_SYM res_T +bsdf_copy + (struct ssf_bsdf** dst, + struct ssf_bsdf* const* src); + +extern LOCAL_SYM res_T +bsdf_copy_and_release + (struct ssf_bsdf** dst, + struct ssf_bsdf** src); + +/* Generate the dynamic array of BSDFs */ +#define DARRAY_NAME bsdf +#define DARRAY_DATA struct ssf_bsdf* +#define DARRAY_FUNCTOR_INIT bsdf_init +#define DARRAY_FUNCTOR_RELEASE bsdf_release +#define DARRAY_FUNCTOR_COPY bsdf_copy +#define DARRAY_FUNCTOR_COPY_AND_RELEASE bsdf_copy_and_release +#include <rsys/dynamic_array.h> /******************************************************************************* * Material ******************************************************************************/ +struct mtl { + struct mrumtl* mrumtl; + struct darray_bsdf bsdf_lst; +}; + extern LOCAL_SYM res_T mtl_init (struct mem_allocator* allocator, - struct mrumtl** mtl); + struct mtl* mtl); extern LOCAL_SYM void mtl_release - (struct mrumtl** mtl); + (struct mtl* mtl); extern LOCAL_SYM res_T mtl_copy - (struct mrumtl** dst, - struct mrumtl* const* src); + (struct mtl* dst, + const struct mtl* src); extern LOCAL_SYM res_T mtl_copy_and_release - (struct mrumtl** dst, - struct mrumtl** src); + (struct mtl* dst, + struct mtl* src); /* Generate the dynamic array of materials */ #define DARRAY_NAME mtl -#define DARRAY_DATA struct mrumtl* +#define DARRAY_DATA struct mtl #define DARRAY_FUNCTOR_INIT mtl_init #define DARRAY_FUNCTOR_RELEASE mtl_release #define DARRAY_FUNCTOR_COPY mtl_copy diff --git a/src/rngrd_properties.c b/src/rngrd_properties.c @@ -91,6 +91,129 @@ check_sbuf_desc } static res_T +create_bsdf_diffuse + (struct rngrd* ground, + const struct mrumtl_brdf_lambertian* lambertian, + struct ssf_bsdf** out_bsdf) +{ + struct ssf_bsdf* bsdf = NULL; + struct mem_allocator* allocator = NULL; + res_T res = RES_OK; + ASSERT(ground && lambertian && out_bsdf); + + allocator = ground->allocator; + + res = ssf_bsdf_create(allocator, &ssf_lambertian_reflection, &bsdf); + if(res != RES_OK) goto error; + res = ssf_lambertian_reflection_setup(bsdf, lambertian->reflectivity); + if(res != RES_OK) goto error; + +exit: + *out_bsdf = bsdf; + return res; +error: + if(bsdf) { SSF(bsdf_ref_put(bsdf)); bsdf = NULL; } + goto exit; +} + +static res_T +create_bsdf_specular + (struct rngrd* ground, + const struct mrumtl_brdf_specular* specular, + struct ssf_bsdf** out_bsdf) +{ + struct ssf_bsdf* bsdf = NULL; + struct ssf_fresnel* fresnel = NULL; + struct mem_allocator* allocator = NULL; + res_T res = RES_OK; + ASSERT(ground && specular && out_bsdf); + + allocator = ground->allocator; + + res = ssf_bsdf_create(allocator, &ssf_specular_reflection, &bsdf); + if(res != RES_OK) goto error; + res = ssf_fresnel_create(allocator, &ssf_fresnel_constant, &fresnel); + if(res != RES_OK) goto error; + res = ssf_fresnel_constant_setup(fresnel, specular->reflectivity); + if(res != RES_OK) goto error; + res = ssf_specular_reflection_setup(bsdf, fresnel); + if(res != RES_OK) goto error; + +exit: + if(fresnel) SSF(fresnel_ref_put(fresnel)); + *out_bsdf = bsdf; + return res; +error: + if(bsdf) { SSF(bsdf_ref_put(bsdf)); bsdf = NULL; } + goto exit; +} + +static INLINE res_T +create_bsdf + (struct rngrd* ground, + const struct mrumtl_brdf* brdf, + struct ssf_bsdf** out_bsdf) +{ + struct mrumtl_brdf_lambertian lambertian; + struct mrumtl_brdf_specular specular; + res_T res = RES_OK; + ASSERT(ground && brdf && out_bsdf); + + switch(mrumtl_brdf_get_type(brdf)) { + case MRUMTL_BRDF_LAMBERTIAN: + MRUMTL(brdf_get_lambertian(brdf, &lambertian)); + res = create_bsdf_diffuse(ground, &lambertian, out_bsdf); + if(res != RES_OK) goto error; + break; + case MRUMTL_BRDF_SPECULAR: + MRUMTL(brdf_get_specular(brdf, &specular)); + res = create_bsdf_specular(ground, &specular, out_bsdf); + if(res != RES_OK) goto error; + break; + default: FATAL("Unreachable code.\n"); break; + } + +exit: + return res; +error: + goto exit; +} + +static res_T +mtl_create_bsdf_list + (struct rngrd* ground, + const char* filename, + struct mtl* mtl) +{ + size_t nbsdfs = 0; + size_t ibsdf = 0; + res_T res = RES_OK; + ASSERT(ground && filename && mtl); + + /* Reserve memory space for the list of BSDFs */ + nbsdfs = mrumtl_get_brdfs_count(mtl->mrumtl); + res = darray_bsdf_resize(&mtl->bsdf_lst, nbsdfs); + if(res != RES_OK) goto error; + + FOR_EACH(ibsdf, 0, nbsdfs) { + const struct mrumtl_brdf* brdf = mrumtl_get_brdf(mtl->mrumtl, ibsdf); + struct ssf_bsdf** bsdf = darray_bsdf_data_get(&mtl->bsdf_lst) + ibsdf; + + res = create_bsdf(ground, brdf, bsdf); + if(res != RES_OK) goto error; + } + +exit: + return res; + +error: + log_err(ground, "%s: error creating the list of BSDFs -- %s\n", + filename, res_to_cstr(res)); + darray_bsdf_clear(&mtl->bsdf_lst); + goto exit; +} + +static res_T load_mtl(struct rngrd* ground, const char* filename, struct mrumtl** out_mtl) { struct mrumtl_create_args args = MRUMTL_CREATE_ARGS_DEFAULT; @@ -126,6 +249,7 @@ load_mtllst(struct rngrd* ground, const struct rngrd_create_args* args) size_t imtl, nmtls; res_T res = RES_OK; + /* Create loader of material paths */ rnsl_args.logger = ground->logger; rnsl_args.allocator = ground->allocator; rnsl_args.verbose = ground->verbose; @@ -136,9 +260,11 @@ load_mtllst(struct rngrd* ground, const struct rngrd_create_args* args) goto error; } + /* Load the list of material paths */ res = rnsl_load(rnsl, args->mtllst_filename); if(res != RES_OK) goto error; + /* Reserve memory space for the list of materials */ nmtls = rnsl_get_strings_count(rnsl); res = darray_mtl_resize(&ground->mtls, nmtls); if(res != RES_OK) { @@ -147,10 +273,14 @@ load_mtllst(struct rngrd* ground, const struct rngrd_create_args* args) goto error; } + /* Load the list of materials and create their associated BSDFs */ FOR_EACH(imtl, 0, nmtls) { - struct mrumtl** mtl = darray_mtl_data_get(&ground->mtls)+imtl; + struct mtl* mtl = darray_mtl_data_get(&ground->mtls)+imtl; const char* filename = rnsl_get_string(rnsl, imtl); - res = load_mtl(ground, filename, mtl); + + res = load_mtl(ground, filename, &mtl->mrumtl); + if(res != RES_OK) goto error; + res = mtl_create_bsdf_list(ground, filename, mtl); if(res != RES_OK) goto error; } @@ -162,66 +292,6 @@ error: goto exit; } -static res_T -create_bsdf_diffuse - (struct rngrd* ground, - const struct mrumtl_brdf_lambertian* lambertian, - struct ssf_bsdf** out_bsdf) -{ - struct ssf_bsdf* bsdf = NULL; - struct mem_allocator* allocator = NULL; - res_T res = RES_OK; - ASSERT(ground && lambertian && out_bsdf); - - /* TODO speed up allocation by using a [per thread] fifo allocator */ - allocator = ground->allocator; - - res = ssf_bsdf_create(allocator, &ssf_lambertian_reflection, &bsdf); - if(res != RES_OK) goto error; - res = ssf_lambertian_reflection_setup(bsdf, lambertian->reflectivity); - if(res != RES_OK) goto error; - -exit: - *out_bsdf = bsdf; - return res; -error: - if(bsdf) { SSF(bsdf_ref_put(bsdf)); bsdf = NULL; } - goto exit; -} - -static res_T -create_bsdf_specular - (struct rngrd* ground, - const struct mrumtl_brdf_specular* specular, - struct ssf_bsdf** out_bsdf) -{ - struct ssf_bsdf* bsdf = NULL; - struct ssf_fresnel* fresnel = NULL; - struct mem_allocator* allocator = NULL; - res_T res = RES_OK; - ASSERT(ground && specular && out_bsdf); - - /* TODO speed up allocation by using a [per thread] fifo allocator */ - allocator = ground->allocator; - - res = ssf_bsdf_create(allocator, &ssf_specular_reflection, &bsdf); - if(res != RES_OK) goto error; - res = ssf_fresnel_create(allocator, &ssf_fresnel_constant, &fresnel); - if(res != RES_OK) goto error; - res = ssf_fresnel_constant_setup(fresnel, specular->reflectivity); - if(res != RES_OK) goto error; - res = ssf_specular_reflection_setup(bsdf, fresnel); - if(res != RES_OK) goto error; - -exit: - if(fresnel) SSF(fresnel_ref_put(fresnel)); - *out_bsdf = bsdf; - return res; -error: - if(bsdf) { SSF(bsdf_ref_put(bsdf)); bsdf = NULL; } - goto exit; -} - /******************************************************************************* * Exported functions ******************************************************************************/ @@ -231,13 +301,10 @@ rngrd_create_bsdf const struct rngrd_create_bsdf_args* args, struct ssf_bsdf** out_bsdf) { - struct mrumtl_brdf_lambertian lambertian; - struct mrumtl_brdf_specular specular; const struct ALIGN(8) { uint32_t mtl_id; float temperature; }* item = NULL; - const struct mrumtl_brdf* brdf = NULL; - const struct mrumtl* mtl = NULL; + struct mtl* mtl = NULL; struct ssf_bsdf* bsdf = NULL; - size_t ibrdf; + size_t ibsdf; struct sbuf_desc desc; res_T res = RES_OK; @@ -252,27 +319,15 @@ rngrd_create_bsdf /* Retrieve the spectrally varying material of the primitive */ ASSERT(item->mtl_id < darray_mtl_size_get(&ground->mtls)); - mtl = darray_mtl_cdata_get(&ground->mtls)[item->mtl_id]; + mtl = darray_mtl_data_get(&ground->mtls)+item->mtl_id; - /* Get the BRDF based on the input wavelength */ - res = mrumtl_fetch_brdf(mtl, args->wavelength, args->r, &ibrdf); + /* Get the BSDF based on the input wavelength */ + res = mrumtl_fetch_brdf(mtl->mrumtl, args->wavelength, args->r, &ibsdf); if(res != RES_OK) goto error; - brdf = mrumtl_get_brdf(mtl, ibrdf); - /* Create the scattering function */ - switch(mrumtl_brdf_get_type(brdf)) { - case MRUMTL_BRDF_LAMBERTIAN: - MRUMTL(brdf_get_lambertian(brdf, &lambertian)); - res = create_bsdf_diffuse(ground, &lambertian, &bsdf); - if(res != RES_OK) goto error; - break; - case MRUMTL_BRDF_SPECULAR: - MRUMTL(brdf_get_specular(brdf, &specular)); - res = create_bsdf_specular(ground, &specular, &bsdf); - if(res != RES_OK) goto error; - break; - default: FATAL("Unreachable code.\n"); break; - } + bsdf = darray_bsdf_data_get(&mtl->bsdf_lst)[ibsdf]; + ASSERT(bsdf); + SSF(bsdf_ref_get(bsdf)); exit: if(out_bsdf) *out_bsdf = bsdf;