commit 52a3ec66c4ab6a1e421d6b6b314d171a77ae50ed
parent 700871661b21ccafa3e929a5a4f7da348ffa02dd
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Wed, 30 Nov 2016 16:33:24 +0100
Implement of the param_buffer API
Diffstat:
3 files changed, 233 insertions(+), 0 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -60,6 +60,7 @@ set(SSOL_FILES_SRC
ssol_material.c
ssol_object.c
ssol_instance.c
+ ssol_param_buffer.c
ssol_ranst_sun_dir.c
ssol_ranst_sun_wl.c
ssol_scene.c
diff --git a/src/ssol.h b/src/ssol.h
@@ -52,6 +52,7 @@ struct ssol_image;
struct ssol_material;
struct ssol_object;
struct ssol_instance;
+struct ssol_param_buffer;
struct ssol_scene;
struct ssol_shape;
struct ssol_spectrum;
@@ -506,6 +507,40 @@ ssol_instance_get_id
uint32_t* id);
/*******************************************************************************
+ * Param buffer API
+ ******************************************************************************/
+SSOL_API res_T
+ssol_param_buffer_create
+ (struct ssol_device* dev,
+ struct ssol_param_buffer** buf);
+
+SSOL_API res_T
+ssol_param_buffer_ref_get
+ (struct ssol_param_buffer* buf);
+
+SSOL_API res_T
+ssol_param_buffer_ref_put
+ (struct ssol_param_buffer* buf);
+
+SSOL_API res_T
+ssol_param_buffer_set
+ (struct ssol_param_buffer* buf,
+ const char* name,
+ const size_t size, /* In Bytes */
+ const size_t alignment, /* Must be a power of 2 in [1, 64] */
+ const void* parameter);
+
+SSOL_API res_T
+ssol_param_buffer_get
+ (struct ssol_param_buffer* buf,
+ const char* name,
+ const void** parameter);
+
+SSOL_API res_T
+ssol_param_buffer_clear
+ (struct ssol_param_buffer* buf);
+
+/*******************************************************************************
* Spectrum API - Collection of wavelengths with their associated data.
******************************************************************************/
SSOL_API res_T
diff --git a/src/ssol_param_buffer.c b/src/ssol_param_buffer.c
@@ -0,0 +1,197 @@
+/* Copyright (C) CNRS 2016
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "ssol.h"
+#include "ssol_device_c.h"
+
+#include <rsys/dynamic_array.h>
+#include <rsys/hash_table.h>
+#include <rsys/str.h>
+
+#define DEFAULT_ALIGNMENT 64
+
+struct param {
+ size_t size; /* In Bytes */
+ size_t offset; /* In Bytes */
+};
+
+/* Define the hash table that maps the name of a parameter to its offset in the
+ * raw parameter buffer */
+#define HTABLE_NAME param
+#define HTABLE_KEY struct str
+#define HTABLE_DATA struct param
+#define HTABLE_KEY_FUNCTOR_INIT str_init
+#define HTABLE_KEY_FUNCTOR_RELEASE str_release
+#define HTABLE_KEY_FUNCTOR_COPY str_copy
+#define HTABLE_KEY_FUNCTOR_COPY_AND_RELEASE str_copy_and_release
+#define HTABLE_KEY_FUNCTOR_HASH str_hash
+#define HTABLE_KEY_FUNCTOR_EQ str_eq
+#include <rsys/hash_table.h>
+
+struct ssol_param_buffer {
+ /* TODO ensure that the buffer array is aligned on DEFAULT_ALIGNMENT, i.e.
+ * provide a DARRAY_ALIGNMENT attribute on the dynamic array generic API */
+ struct darray_char buffer;
+ struct htable_param params;
+
+ ref_T ref;
+ struct ssol_device* dev;
+};
+
+/*******************************************************************************
+ * Helper functions
+ ******************************************************************************/
+static void
+param_buffer_release(ref_T* ref)
+{
+ struct ssol_param_buffer* buf;
+ struct ssol_device* dev;
+ ASSERT(ref);
+ buf = CONTAINER_OF(ref, struct ssol_param_buffer, ref);
+ darray_char_release(&buf->buffer);
+ htable_param_release(&buf->params);
+ dev = buf->dev;
+ MEM_RM(dev->allocator, buf);
+ SSOL(device_ref_put(dev));
+}
+
+/*******************************************************************************
+ * Exported functions
+ ******************************************************************************/
+res_T
+ssol_param_buffer_create
+ (struct ssol_device* dev, struct ssol_param_buffer** out_buf)
+{
+ struct ssol_param_buffer* buf = NULL;
+ res_T res = RES_OK;
+
+ if(!dev || !out_buf) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ buf = MEM_CALLOC(dev->allocator, 1, sizeof(struct ssol_param_buffer));
+ if(!buf) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ SSOL(device_ref_get(dev));
+ buf->dev = dev;
+ ref_init(&buf->ref);
+ htable_param_init(dev->allocator, &buf->params);
+ darray_char_init(dev->allocator, &buf->buffer);
+
+exit:
+ return res;
+error:
+ if(buf) {
+ SSOL(param_buffer_ref_put(buf));
+ buf = NULL;
+ }
+ goto exit;
+}
+
+res_T
+ssol_param_buffer_ref_get(struct ssol_param_buffer* buf)
+{
+ if(!buf) return RES_BAD_ARG;
+ ref_get(&buf->ref);
+ return RES_OK;
+}
+
+res_T
+ssol_param_buffer_ref_put(struct ssol_param_buffer* buf)
+{
+ if(!buf) return RES_BAD_ARG;
+ ref_put(&buf->ref, param_buffer_release);
+ return RES_OK;
+}
+
+res_T
+ssol_param_buffer_set
+ (struct ssol_param_buffer* buf,
+ const char* name,
+ const size_t size, /* In Bytes */
+ const size_t alignment, /* Must be a power of 2 in [1, 64] */
+ const void* parameter)
+{
+ struct param* pparam;
+ char* dst;
+ size_t bufsz = SIZE_MAX;
+ struct str key;
+ res_T res = RES_OK;
+
+ str_init(buf->dev->allocator, &key);
+
+ if(!buf || !name || name[0] == '\0' || !size || !IS_POW2(alignment)
+ || alignment > DEFAULT_ALIGNMENT || !parameter) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ bufsz = darray_char_size_get(&buf->buffer);
+
+ res = str_set(&key, name);
+ if(res != RES_OK) goto error;
+
+ pparam = htable_param_find(&buf->params, &key);
+
+ if(pparam) { /* Update a previously set parameter */
+ char* dst = darray_char_data_get(&buf->buffer) + pparam->offset;
+ if(pparam->size < size || !IS_ALIGNED(dst, alignment)) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ if(MEM_AREA_OVERLAP(parameter, size, dst, size)) {
+ memmove(dst, parameter, size);
+ } else {
+ memcpy(dst, parameter, size);
+ }
+ } else { /* Setup a new parameter */
+ struct param param;
+
+ param.offset = ALIGN_SIZE(bufsz, alignment);
+ param.size = size;
+
+ res = darray_char_resize(&buf->buffer, param.offset + param.size);
+ if(res != RES_OK) goto error;
+
+ dst = darray_char_data_get(&buf->buffer) + param.offset;
+ ASSERT(IS_ALIGNED(dst, alignment));
+ memcpy(dst, parameter, param.size);
+
+ res = htable_param_set(&buf->params, &key, ¶m);
+ if(res != RES_OK) goto error;
+ }
+
+exit:
+ str_release(&key);
+ return res;
+error:
+ if(bufsz != SIZE_MAX) {
+ CHECK(darray_char_resize(&buf->buffer, bufsz), RES_OK);
+ }
+ goto exit;
+}
+
+res_T
+ssol_param_buffer_clear(struct ssol_param_buffer* buf)
+{
+ if(!buf) return RES_BAD_ARG;
+ darray_char_clear(&buf->buffer);
+ htable_param_clear(&buf->params);
+ return RES_OK;
+}
+