commit 10236cfaf42e46b3ec31ef93b7ee724d8753d01d
parent 4d91adfc1e42055ba3eea689c0cca3b1e5715578
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Fri, 28 Aug 2020 09:49:40 +0200
Add the sdis_green_function_create_from_stream function
Diffstat:
5 files changed, 262 insertions(+), 9 deletions(-)
diff --git a/src/sdis.h b/src/sdis.h
@@ -996,6 +996,12 @@ sdis_green_function_write
(struct sdis_green_function* green,
FILE* stream);
+SDIS_API res_T
+sdis_green_function_create_from_stream
+ (struct sdis_scene* scn, /* Scene from which the green was evaluated */
+ FILE* stream, /* Stream into which the green was serialized */
+ struct sdis_green_function** green);
+
/* Retrieve the number of valid paths used to estimate the green function. It
* is actually equal to the number of successful realisations. */
SDIS_API res_T
diff --git a/src/sdis_device_c.h b/src/sdis_device_c.h
@@ -27,7 +27,7 @@
struct ssp_rng;
struct ssp_rng_proxy;
-struct name { FITEM; };
+struct name { FITEM; void* mem; };
#define FITEM_TYPE name
#include <rsys/free_list.h>
diff --git a/src/sdis_green.c b/src/sdis_green.c
@@ -16,10 +16,11 @@
#include "sdis_device_c.h"
#include "sdis_estimator_c.h"
#include "sdis_green.h"
+#include "sdis_interface_c.h"
#include "sdis_log.h"
#include "sdis_medium_c.h"
#include "sdis_misc.h"
-#include "sdis_interface_c.h"
+#include "sdis_scene_c.h"
#include <star/ssp.h>
@@ -164,7 +165,7 @@ green_path_copy_and_release(struct green_path* dst, struct green_path* src)
return RES_OK;
}
-static INLINE res_T
+static res_T
green_path_write(const struct green_path* path, FILE* stream)
{
size_t sz = 0;
@@ -192,7 +193,7 @@ green_path_write(const struct green_path* path, FILE* stream)
WRITE(&path->limit, 1);
WRITE(&path->limit_type, 1);
- /* Write miscellaneous data */
+ /* Write miscellaneous data */
WRITE(&path->ilast_medium, 1);
WRITE(&path->ilast_interf, 1);
@@ -204,6 +205,54 @@ error:
goto exit;
}
+static res_T
+green_path_read(struct green_path* path, FILE* stream)
+{
+ size_t sz = 0;
+ res_T res = RES_OK;
+ ASSERT(path && stream);
+
+ #define READ(Var, N) { \
+ if(fread((Var), sizeof(*(Var)), (N), stream) != (N)) { \
+ if(feof(stream)) { \
+ res = RES_BAD_ARG; \
+ } else if(ferror(stream)) { \
+ res = RES_IO_ERR; \
+ } else { \
+ res = RES_UNKNOWN_ERR; \
+ } \
+ goto error; \
+ } \
+ } (void)0
+
+ /* Read the list of flux terms */
+ READ(&sz, 1);
+ res = darray_flux_term_resize(&path->flux_terms, sz);
+ if(res != RES_OK) goto error;
+ READ(darray_flux_term_data_get(&path->flux_terms), sz);
+
+ /* Read the list of power tems */
+ READ(&sz, 1);
+ res = darray_power_term_resize(&path->power_terms, sz);
+ if(res != RES_OK) goto error;
+ READ(darray_power_term_data_get(&path->power_terms), sz);
+
+ /* Read the limit point */
+ READ(&path->limit, 1);
+ READ(&path->limit_type, 1);
+
+ /* Read the miscellaneous data */
+ READ(&path->ilast_medium, 1);
+ READ(&path->ilast_interf, 1);
+
+ #undef READ
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
/* Generate the dynamic array of green paths */
#define DARRAY_NAME green_path
#define DARRAY_DATA struct green_path
@@ -431,9 +480,9 @@ write_media(struct sdis_green_function* green, FILE* stream)
htable_medium_begin(&green->media, &it);
htable_medium_end(&green->media, &it_end);
while(!htable_medium_iterator_eq(&it, &it_end)) {
- const unsigned id = *htable_medium_iterator_key_get(&it);
+ const struct sdis_medium* mdm = *htable_medium_iterator_data_get(&it);
htable_medium_iterator_next(&it);
- WRITE(&id);
+ WRITE(&mdm->id);
}
#undef WRITE
@@ -445,6 +494,53 @@ error:
}
static res_T
+read_media(struct sdis_green_function* green, FILE* stream)
+{
+ size_t nmedia = 0;
+ size_t imedium = 0;
+ res_T res = RES_OK;
+ ASSERT(green && stream);
+
+ #define READ(Var) { \
+ if(fread((Var), sizeof(*(Var)), 1, stream) != 1) { \
+ if(feof(stream)) { \
+ res = RES_BAD_ARG; \
+ } else if(ferror(stream)) { \
+ res = RES_IO_ERR; \
+ } else { \
+ res = RES_UNKNOWN_ERR; \
+ } \
+ goto error; \
+ } \
+ } (void)0
+
+ READ(&nmedia);
+ FOR_EACH(imedium, 0, nmedia) {
+ struct name* name = NULL;
+ struct fid id;
+ READ(&id);
+
+ name = flist_name_get(&green->dev->media_names, id);
+ if(!name) {
+ log_err(green->dev, "%s: a Stardis medium is missing.\n",
+ FUNC_NAME);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ res = ensure_medium_registration(green, name->mem);
+ if(res != RES_OK) goto error;
+ }
+
+ #undef READ
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
write_interfaces(struct sdis_green_function* green, FILE* stream)
{
struct htable_interf_iterator it, it_end;
@@ -464,9 +560,9 @@ write_interfaces(struct sdis_green_function* green, FILE* stream)
htable_interf_begin(&green->interfaces, &it);
htable_interf_end(&green->interfaces, &it_end);
while(!htable_interf_iterator_eq(&it, &it_end)) {
- const unsigned id = *htable_interf_iterator_key_get(&it);
+ const struct sdis_interface* interf = *htable_interf_iterator_data_get(&it);
htable_interf_iterator_next(&it);
- WRITE(&id);
+ WRITE(&interf->id);
}
#undef WRITE
@@ -477,6 +573,53 @@ error:
}
static res_T
+read_interfaces(struct sdis_green_function* green, FILE* stream)
+{
+ size_t ninterfs = 0;
+ size_t iinterf = 0;
+ res_T res = RES_OK;
+ ASSERT(green && stream);
+
+ #define READ(Var) { \
+ if(fread((Var), sizeof(*(Var)), 1, stream) != 1) { \
+ if(feof(stream)) { \
+ res = RES_BAD_ARG; \
+ } else if(ferror(stream)) { \
+ res = RES_IO_ERR; \
+ } else { \
+ res = RES_UNKNOWN_ERR; \
+ } \
+ goto error; \
+ } \
+ } (void)0
+
+ READ(&ninterfs);
+ FOR_EACH(iinterf, 0, ninterfs) {
+ struct name* name = NULL;
+ struct fid id;
+ READ(&id);
+
+ name = flist_name_get(&green->dev->interfaces_names, id);
+ if(!name) {
+ log_err(green->dev, "%s: a Stardis interface is missing.\n",
+ FUNC_NAME);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ res = ensure_interface_registration(green, name->mem);
+ if(res != RES_OK) goto error;
+ }
+
+ #undef READ
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
write_paths_list(struct sdis_green_function* green, FILE* stream)
{
size_t npaths = 0;
@@ -507,6 +650,45 @@ error:
goto exit;
}
+static res_T
+read_paths_list(struct sdis_green_function* green, FILE* stream)
+{
+ size_t npaths = 0;
+ size_t ipath = 0;
+ res_T res = RES_OK;
+
+ #define READ(Var) { \
+ if(fread((Var), sizeof(*(Var)), 1, stream) != 1) { \
+ if(feof(stream)) { \
+ res = RES_BAD_ARG; \
+ } else if(ferror(stream)) { \
+ res = RES_IO_ERR; \
+ } else { \
+ res = RES_UNKNOWN_ERR; \
+ } \
+ goto error; \
+ } \
+ } (void)0
+
+ READ(&npaths);
+ res = darray_green_path_resize(&green->paths, npaths);
+ if(res != RES_OK) goto error;
+
+ FOR_EACH(ipath, 0, npaths) {
+ struct green_path* path = NULL;
+ path = darray_green_path_data_get(&green->paths) + ipath;
+
+ res = green_path_read(path, stream);
+ if(res != RES_OK) goto error;
+ }
+ #undef READ
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
static void
green_function_clear(struct sdis_green_function* green)
{
@@ -650,7 +832,7 @@ sdis_green_function_write(struct sdis_green_function* green, FILE* stream)
struct ssp_rng* rng = NULL;
res_T res = RES_OK;
- if(!green && !stream) {
+ if(!green || !stream) {
res = RES_BAD_ARG;
goto error;
}
@@ -691,6 +873,69 @@ error:
}
res_T
+sdis_green_function_create_from_stream
+ (struct sdis_scene* scn,
+ FILE* stream,
+ struct sdis_green_function** out_green)
+{
+ struct sdis_green_function* green = NULL;
+ struct ssp_rng* rng = NULL;
+ res_T res = RES_OK;
+
+ if(!scn || !stream || !out_green) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ res = green_function_create(scn->dev, &green);
+ if(res != RES_OK) goto error;
+
+ res = read_media(green, stream);
+ if(res != RES_OK) goto error;
+ res = read_interfaces(green, stream);
+ if(res != RES_OK) goto error;
+ res = read_paths_list(green, stream);
+ if(res != RES_OK) goto error;
+
+ #define READ(Var) { \
+ if(fread((Var), sizeof(*(Var)), 1, stream) != 1) { \
+ if(feof(stream)) { \
+ res = RES_BAD_ARG; \
+ } else if(ferror(stream)) { \
+ res = RES_IO_ERR; \
+ } else { \
+ res = RES_UNKNOWN_ERR; \
+ } \
+ goto error; \
+ } \
+ } (void)0
+ READ(&green->npaths_valid);
+ READ(&green->npaths_invalid);
+ READ(&green->realisation_time);
+ READ(&green->rng_type);
+ #undef READ
+
+ /* Create a temporary RNG used to deserialise the RNG state */
+ res = ssp_rng_create(green->dev->allocator, &green->rng_type, &rng);
+ if(res != RES_OK) goto error;
+ res = ssp_rng_read(rng, stream);
+ if(res != RES_OK) goto error;
+ res = ssp_rng_write(rng, green->rng_state);
+ if(res != RES_OK) goto error;
+
+exit:
+ if(rng) SSP(rng_ref_put(rng));
+ if(out_green) *out_green = green;
+ return res;
+error:
+ if(green) {
+ SDIS(green_function_ref_put(green));
+ green = NULL;
+ }
+ goto exit;
+}
+
+res_T
sdis_green_function_get_paths_count
(const struct sdis_green_function* green, size_t* npaths)
{
diff --git a/src/sdis_interface.c b/src/sdis_interface.c
@@ -153,6 +153,7 @@ sdis_interface_create
interf->dev = dev;
interf->shader = *shader;
interf->id = flist_name_add(&dev->interfaces_names);
+ flist_name_get(&dev->interfaces_names, interf->id)->mem = interf;
if(data) {
SDIS(data_ref_get(data));
diff --git a/src/sdis_medium.c b/src/sdis_medium.c
@@ -68,6 +68,7 @@ medium_create
medium->dev = dev;
medium->type = type;
medium->id = flist_name_add(&dev->media_names);
+ flist_name_get(&dev->media_names, medium->id)->mem = medium;
exit:
if(out_medium) *out_medium = medium;