Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/draw/CMakeLists.txt2
-rw-r--r--source/blender/draw/DRW_engine.h3
-rw-r--r--source/blender/draw/intern/draw_instance_data.c226
-rw-r--r--source/blender/draw/intern/draw_instance_data.h41
-rw-r--r--source/blender/gpu/GPU_viewport.h1
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c10
6 files changed, 283 insertions, 0 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 03ab9cf9435..c45af4c3807 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -62,6 +62,7 @@ set(SRC
intern/draw_cache_impl_metaball.c
intern/draw_cache_impl_particles.c
intern/draw_common.c
+ intern/draw_instance_data.c
intern/draw_manager.c
intern/draw_manager_text.c
intern/draw_manager_profiling.c
@@ -104,6 +105,7 @@ set(SRC
intern/draw_cache.h
intern/draw_cache_impl.h
intern/draw_common.h
+ intern/draw_instance_data.h
intern/draw_manager_text.h
intern/draw_manager_profiling.h
intern/draw_view.h
diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h
index 3f09f38147e..7fa640683e1 100644
--- a/source/blender/draw/DRW_engine.h
+++ b/source/blender/draw/DRW_engine.h
@@ -30,6 +30,7 @@ struct ARegion;
struct CollectionEngineSettings;
struct Depsgraph;
struct DRWPass;
+struct DRWInstanceDataList;
struct Main;
struct Material;
struct Scene;
@@ -109,6 +110,8 @@ void DRW_draw_depth_loop(
/* This is here because GPUViewport needs it */
void DRW_pass_free(struct DRWPass *pass);
+struct DRWInstanceDataList *DRW_instance_data_list_create(void);
+void DRW_instance_data_list_free(struct DRWInstanceDataList *idatalist);
/* Mode engines initialization */
void OBJECT_collection_settings_create(struct IDProperty *properties);
diff --git a/source/blender/draw/intern/draw_instance_data.c b/source/blender/draw/intern/draw_instance_data.c
new file mode 100644
index 00000000000..5cfd4991f38
--- /dev/null
+++ b/source/blender/draw/intern/draw_instance_data.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * 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 2
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/intern/draw_instance_data.c
+ * \ingroup draw
+ */
+
+/**
+ * DRW Instance Data Manager
+ * This is a special memory manager that keeps memory blocks ready to send as vbo data in one continuous allocation.
+ * This way we avoid feeding gawain each instance data one by one and unecessary memcpy.
+ * Since we loose which memory block was used each DRWShadingGroup we need to redistribute them in the same order/size
+ * to avoid to realloc each frame.
+ * This is why DRWInstanceDatas are sorted in a list for each different data size.
+ **/
+
+#include "draw_instance_data.h"
+#include "DRW_engine.h"
+
+#include "MEM_guardedalloc.h"
+#include "BLI_utildefines.h"
+
+#define MAX_INSTANCE_DATA_SIZE 28 /* Can be adjusted for more */
+
+struct DRWInstanceData {
+ struct DRWInstanceData *next;
+ bool used; /* If this data is used or not. */
+ size_t chunk_size; /* Current size of the whole chunk. */
+ size_t data_size; /* Size of one instance data. */
+ size_t instance_group; /* How many instance to allocate at a time. */
+ size_t offset; /* Offset to the next instance data. */
+ float *memchunk; /* Should be float no matter what. */
+};
+
+struct DRWInstanceDataList {
+ /* Linked lists for all possible data pool size */
+ /* Not entirely sure if we should separate them in the first place.
+ * This is done to minimize the reattribution misses. */
+ DRWInstanceData *idata_head[MAX_INSTANCE_DATA_SIZE];
+ DRWInstanceData *idata_tail[MAX_INSTANCE_DATA_SIZE];
+};
+
+/* -------------------------------------------------------------------- */
+
+/** \name Instance Data (DRWInstanceData)
+ * \{ */
+
+static DRWInstanceData *drw_instance_data_create(
+ DRWInstanceDataList *idatalist, unsigned int attrib_size, unsigned int instance_group)
+{
+ DRWInstanceData *idata = MEM_mallocN(sizeof(DRWInstanceData), "DRWInstanceData");
+ idata->next = NULL;
+ idata->used = true;
+ idata->data_size = attrib_size;
+ idata->instance_group = instance_group;
+ idata->chunk_size = idata->data_size * instance_group;
+ idata->offset = 0;
+ idata->memchunk = MEM_mallocN(idata->chunk_size * sizeof(float), "DRWInstanceData memchunk");
+
+ BLI_assert(attrib_size > 0);
+
+ /* Push to linked list. */
+ if (idatalist->idata_head[attrib_size-1] == NULL) {
+ idatalist->idata_head[attrib_size-1] = idata;
+ }
+ else {
+ idatalist->idata_tail[attrib_size-1]->next = idata;
+ }
+ idatalist->idata_tail[attrib_size-1] = idata;
+
+ return idata;
+}
+
+static void DRW_instance_data_free(DRWInstanceData *idata)
+{
+ MEM_freeN(idata->memchunk);
+}
+
+/**
+ * Return a pointer to the next instance data space.
+ * DO NOT SAVE/REUSE THIS POINTER after the next call
+ * to this function since the chunk may have been
+ * reallocated.
+ **/
+void *DRW_instance_data_next(DRWInstanceData *idata)
+{
+ idata->offset += idata->data_size;
+
+ /* Check if chunk is large enough. realloc otherwise. */
+ if (idata->offset > idata->chunk_size) {
+ idata->chunk_size += idata->data_size * idata->instance_group;
+ idata->memchunk = MEM_reallocN(idata->memchunk, idata->chunk_size * sizeof(float));
+ }
+
+ return idata->memchunk + (idata->offset - idata->data_size);
+}
+
+void *DRW_instance_data_get(DRWInstanceData *idata)
+{
+ return (void *)idata->memchunk;
+}
+
+DRWInstanceData *DRW_instance_data_request(
+ DRWInstanceDataList *idatalist, unsigned int attrib_size, unsigned int instance_group)
+{
+ BLI_assert(attrib_size > 0 && attrib_size <= MAX_INSTANCE_DATA_SIZE);
+
+ DRWInstanceData *idata = idatalist->idata_head[attrib_size - 1];
+
+ /* Search for an unused data chunk. */
+ for (; idata; idata = idata->next) {
+ if (idata->used == false) {
+ idata->used = true;
+ return idata;
+ }
+ }
+
+ return drw_instance_data_create(idatalist, attrib_size, instance_group);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Instance Data List (DRWInstanceDataList)
+ * \{ */
+
+DRWInstanceDataList *DRW_instance_data_list_create(void)
+{
+ return MEM_callocN(sizeof(DRWInstanceDataList), "DRWInstanceDataList");
+}
+
+void DRW_instance_data_list_free(DRWInstanceDataList *idatalist)
+{
+ DRWInstanceData *idata, *next_idata;
+
+ for (int i = 0; i < MAX_INSTANCE_DATA_SIZE; ++i) {
+ for (idata = idatalist->idata_head[i]; idata; idata = next_idata) {
+ next_idata = idata->next;
+ DRW_instance_data_free(idata);
+ MEM_freeN(idata);
+ }
+ idatalist->idata_head[i] = NULL;
+ idatalist->idata_tail[i] = NULL;
+ }
+}
+
+void DRW_instance_data_list_reset(DRWInstanceDataList *idatalist)
+{
+ DRWInstanceData *idata;
+
+ for (int i = 0; i < MAX_INSTANCE_DATA_SIZE; ++i) {
+ for (idata = idatalist->idata_head[i]; idata; idata = idata->next) {
+ idata->used = false;
+ idata->offset = 0;
+ }
+ }
+}
+
+void DRW_instance_data_list_free_unused(DRWInstanceDataList *idatalist)
+{
+ DRWInstanceData *idata, *next_idata;
+
+ /* Remove unused data blocks and sanitize each list. */
+ for (int i = 0; i < MAX_INSTANCE_DATA_SIZE; ++i) {
+ idatalist->idata_tail[i] = NULL;
+ for (idata = idatalist->idata_head[i]; idata; idata = next_idata) {
+ next_idata = idata->next;
+ if (idata->used == false) {
+ if (idatalist->idata_head[i] == idata) {
+ idatalist->idata_head[i] = next_idata;
+ }
+ else {
+ /* idatalist->idata_tail[i] is garanteed not to be null in this case. */
+ idatalist->idata_tail[i]->next = next_idata;
+ }
+ DRW_instance_data_free(idata);
+ MEM_freeN(idata);
+ }
+ else {
+ if (idatalist->idata_tail[i] != NULL) {
+ idatalist->idata_tail[i]->next = idata;
+ }
+ idatalist->idata_tail[i] = idata;
+ }
+ }
+ }
+}
+
+void DRW_instance_data_list_resize(DRWInstanceDataList *idatalist)
+{
+ DRWInstanceData *idata;
+
+ for (int i = 0; i < MAX_INSTANCE_DATA_SIZE; ++i) {
+ for (idata = idatalist->idata_head[i]; idata; idata = idata->next) {
+ /* Rounding up to nearest chunk size to compare. */
+ size_t fac = idata->data_size * idata->instance_group;
+ size_t tmp = idata->offset + fac - 1;
+ size_t rounded_offset = tmp - tmp % fac;
+ if (rounded_offset < idata->chunk_size) {
+ idata->chunk_size = rounded_offset;
+ idata->memchunk = MEM_reallocN(idata->memchunk, idata->chunk_size * sizeof(float));
+ }
+ }
+ }
+}
+
+/** \} */
diff --git a/source/blender/draw/intern/draw_instance_data.h b/source/blender/draw/intern/draw_instance_data.h
new file mode 100644
index 00000000000..637c0e3cc24
--- /dev/null
+++ b/source/blender/draw/intern/draw_instance_data.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * 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 2
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file draw_instance_data.h
+ * \ingroup draw
+ */
+
+#ifndef __DRAW_INSTANCE_DATA_H__
+#define __DRAW_INSTANCE_DATA_H__
+
+typedef struct DRWInstanceData DRWInstanceData;
+typedef struct DRWInstanceDataList DRWInstanceDataList;
+
+void *DRW_instance_data_next(DRWInstanceData *idata);
+void *DRW_instance_data_get(DRWInstanceData *idata);
+DRWInstanceData *DRW_instance_data_request(
+ DRWInstanceDataList *idatalist, unsigned int attrib_size, unsigned int instance_group);
+
+void DRW_instance_data_list_reset(DRWInstanceDataList *idatalist);
+void DRW_instance_data_list_free_unused(DRWInstanceDataList *idatalist);
+void DRW_instance_data_list_resize(DRWInstanceDataList *idatalist);
+
+#endif /* __DRAW_INSTANCE_DATA_H__ */
diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h
index f2bb05a6d1e..a34a901ac63 100644
--- a/source/blender/gpu/GPU_viewport.h
+++ b/source/blender/gpu/GPU_viewport.h
@@ -106,6 +106,7 @@ GPUViewport *GPU_viewport_create_from_offscreen(struct GPUOffScreen *ofs);
void GPU_viewport_clear_from_offscreen(GPUViewport *viewport);
ViewportMemoryPool *GPU_viewport_mempool_get(GPUViewport *viewport);
+struct DRWInstanceDataList *GPU_viewport_instance_data_list_get(GPUViewport *viewport);
void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type);
void *GPU_viewport_engine_data_get(GPUViewport *viewport, void *engine_type);
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index bd563a36f57..c97822dcc2a 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -84,6 +84,7 @@ struct GPUViewport {
DefaultTextureList *txl;
ViewportMemoryPool vmempool; /* Used for rendering data structure. */
+ struct DRWInstanceDataList *idatalist; /* Used for rendering data structure. */
ListBase tex_pool; /* ViewportTempTexture list : Temporary textures shared across draw engines */
};
@@ -114,6 +115,7 @@ GPUViewport *GPU_viewport_create(void)
GPUViewport *viewport = MEM_callocN(sizeof(GPUViewport), "GPUViewport");
viewport->fbl = MEM_callocN(sizeof(DefaultFramebufferList), "FramebufferList");
viewport->txl = MEM_callocN(sizeof(DefaultTextureList), "TextureList");
+ viewport->idatalist = DRW_instance_data_list_create();
viewport->size[0] = viewport->size[1] = -1;
@@ -210,6 +212,11 @@ ViewportMemoryPool *GPU_viewport_mempool_get(GPUViewport *viewport)
return &viewport->vmempool;
}
+struct DRWInstanceDataList *GPU_viewport_instance_data_list_get(GPUViewport *viewport)
+{
+ return viewport->idatalist;
+}
+
void *GPU_viewport_framebuffer_list_get(GPUViewport *viewport)
{
return viewport->fbl;
@@ -599,6 +606,9 @@ void GPU_viewport_free(GPUViewport *viewport)
BLI_mempool_destroy(viewport->vmempool.passes);
}
+ DRW_instance_data_list_free(viewport->idatalist);
+ MEM_freeN(viewport->idatalist);
+
GPU_viewport_debug_depth_free(viewport);
}