[Bf-blender-cvs] [7a029f4e00c] blender2.8: GPUViewport: Add a Texture Pool to reuse textures across engines.

Clément Foucault noreply at git.blender.org
Tue May 16 21:31:01 CEST 2017


Commit: 7a029f4e00cc9a9f6a938cf701e6ed4c91115264
Author: Clément Foucault
Date:   Tue May 16 02:59:25 2017 +0200
Branches: blender2.8
https://developer.blender.org/rB7a029f4e00cc9a9f6a938cf701e6ed4c91115264

GPUViewport: Add a Texture Pool to reuse textures across engines.

===================================================================

M	source/blender/gpu/GPU_texture.h
M	source/blender/gpu/GPU_viewport.h
M	source/blender/gpu/intern/gpu_texture.c
M	source/blender/gpu/intern/gpu_viewport.c

===================================================================

diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index 8cf9806ae36..b58cffd7214 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -191,6 +191,7 @@ void GPU_texture_framebuffer_set(GPUTexture *tex, struct GPUFrameBuffer *fb, int
 int GPU_texture_target(const GPUTexture *tex);
 int GPU_texture_width(const GPUTexture *tex);
 int GPU_texture_height(const GPUTexture *tex);
+int GPU_texture_format(const GPUTexture *tex);
 bool GPU_texture_depth(const GPUTexture *tex);
 bool GPU_texture_stencil(const GPUTexture *tex);
 int GPU_texture_opengl_bindcode(const GPUTexture *tex);
diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h
index e5acc024ff4..2b2a07f50b7 100644
--- a/source/blender/gpu/GPU_viewport.h
+++ b/source/blender/gpu/GPU_viewport.h
@@ -101,6 +101,9 @@ void *GPU_viewport_texture_list_get(GPUViewport *viewport);
 void  GPU_viewport_size_get(const GPUViewport *viewport, int size[2]);
 void  GPU_viewport_size_set(GPUViewport *viewport, const int size[2]);
 
+/* Texture pool */
+GPUTexture *GPU_viewport_texture_pool_query(GPUViewport *viewport, void *engine, int width, int height, int channels, int format);
+
 bool GPU_viewport_cache_validate(GPUViewport *viewport, unsigned int hash);
 
 /* debug */
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index 637cdff1262..4be425b7eb9 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -65,6 +65,7 @@ struct GPUTexture {
 	bool stencil;       /* is a stencil texture? */
 
 	unsigned int bytesize; /* number of byte for one pixel */
+	int format;         /* GPUTextureFormat */
 };
 
 /* ------ Memory Management ------- */
@@ -318,6 +319,7 @@ static GPUTexture *GPU_texture_create_nD(
 	tex->number = -1;
 	tex->refcount = 1;
 	tex->fb_attachment = -1;
+	tex->format = data_type;
 
 	if (n == 2) {
 		if (d == 0)
@@ -462,6 +464,7 @@ static GPUTexture *GPU_texture_cube_create(
 	tex->number = -1;
 	tex->refcount = 1;
 	tex->fb_attachment = -1;
+	tex->format = data_type;
 
 	if (d == 0) {
 		tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP;
@@ -551,6 +554,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget
 	tex->target = textarget;
 	tex->target_base = textarget;
 	tex->fromblender = 1;
+	tex->format = -1;
 
 	ima->gputexture[gputt] = tex;
 
@@ -611,6 +615,7 @@ GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
 	tex->refcount = 1;
 	tex->target = GL_TEXTURE_2D;
 	tex->target_base = GL_TEXTURE_2D;
+	tex->format = -1;
 	
 	prv->gputexture[0] = tex;
 	
@@ -944,6 +949,11 @@ int GPU_texture_height(const GPUTexture *tex)
 	return tex->h;
 }
 
+int GPU_texture_format(const GPUTexture *tex)
+{
+	return tex->format;
+}
+
 bool GPU_texture_depth(const GPUTexture *tex)
 {
 	return tex->depth;
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index c87b5099f0e..a965d4ef135 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -54,6 +54,17 @@
 static const int default_fbl_len = (sizeof(DefaultFramebufferList)) / sizeof(void *);
 static const int default_txl_len = (sizeof(DefaultTextureList)) / sizeof(void *);
 
+/* Maximum number of simultaneous engine enabled at the same time.
+ * Setting it lower than the real number will do lead to
+ * higher VRAM usage due to sub-efficient buffer reuse. */
+#define MAX_ENGINE_BUFFER_SHARING 5
+
+typedef struct ViewportTempTexture {
+	struct ViewportTempTexture *next, *prev;
+	void *user[MAX_ENGINE_BUFFER_SHARING];
+	GPUTexture *texture;
+} ViewportTempTexture;
+
 struct GPUViewport {
 	float pad[4];
 
@@ -66,11 +77,14 @@ struct GPUViewport {
 
 	DefaultFramebufferList *fbl;
 	DefaultTextureList *txl;
+
+	ListBase tex_pool;  /* ViewportTempTexture list : Temporary textures shared across draw engines */
 };
 
 static void gpu_viewport_buffers_free(FramebufferList *fbl, int fbl_len, TextureList *txl, int txl_len);
 static void gpu_viewport_storage_free(StorageList *stl, int stl_len);
 static void gpu_viewport_passes_free(PassList *psl, int psl_len);
+static void gpu_viewport_texture_pool_free(GPUViewport *viewport);
 
 GPUViewport *GPU_viewport_create(void)
 {
@@ -153,6 +167,8 @@ static void gpu_viewport_engines_data_free(GPUViewport *viewport)
 		BLI_remlink(&viewport->data, link);
 		MEM_freeN(link);
 	}
+
+	gpu_viewport_texture_pool_free(viewport);
 }
 
 void *GPU_viewport_engine_data_get(GPUViewport *viewport, void *engine_type)
@@ -192,6 +208,53 @@ void GPU_viewport_size_set(GPUViewport *viewport, const int size[2])
 	viewport->size[1] = size[1];
 }
 
+/**
+ * Try to find a texture coresponding to params into the texture pool.
+ * If no texture was found, create one and add it to the pool.
+ */
+GPUTexture *GPU_viewport_texture_pool_query(GPUViewport *viewport, void *engine, int width, int height, int channels, int format)
+{
+	GPUTexture *tex;
+
+	for (ViewportTempTexture *tmp_tex = viewport->tex_pool.first; tmp_tex; tmp_tex = tmp_tex->next) {
+		if ((GPU_texture_width(tmp_tex->texture) == width) &&
+			(GPU_texture_height(tmp_tex->texture) == height) &&
+			(GPU_texture_format(tmp_tex->texture) == format))
+		{
+			/* Search if the engine is not already using this texture */
+			for (int i = 0; i < MAX_ENGINE_BUFFER_SHARING; ++i) {
+				if (tmp_tex->user[i] == engine) {
+					break;
+				}
+
+				if (tmp_tex->user[i] == NULL) {
+					tmp_tex->user[i] = engine;
+					return tmp_tex->texture;
+				}
+			}
+		}
+	}
+
+	tex = GPU_texture_create_2D_custom(width, height, channels, format, NULL, NULL);
+
+	ViewportTempTexture *tmp_tex = MEM_callocN(sizeof(ViewportTempTexture), "ViewportTempTexture");
+	tmp_tex->texture = tex;
+	tmp_tex->user[0] = engine;
+
+	BLI_addtail(&viewport->tex_pool, tmp_tex);
+
+	return tex;
+}
+
+static void gpu_viewport_texture_pool_free(GPUViewport *viewport)
+{
+	for (ViewportTempTexture *tmp_tex = viewport->tex_pool.first; tmp_tex; tmp_tex = tmp_tex->next) {
+		GPU_texture_free(tmp_tex->texture);
+	}
+
+	BLI_freelistN(&viewport->tex_pool);
+}
+
 bool GPU_viewport_cache_validate(GPUViewport *viewport, unsigned int hash)
 {
 	bool dirty = false;
@@ -238,6 +301,8 @@ void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect)
 				DRW_engine_viewport_data_size_get(data->engine_type, &fbl_len, &txl_len, NULL, NULL);
 				gpu_viewport_buffers_free(data->fbl, fbl_len, data->txl, txl_len);
 			}
+
+			gpu_viewport_texture_pool_free(viewport);
 		}
 	}
 
@@ -408,6 +473,8 @@ void GPU_viewport_free(GPUViewport *viewport)
 	        (FramebufferList *)viewport->fbl, default_fbl_len,
 	        (TextureList *)viewport->txl, default_txl_len);
 
+	gpu_viewport_texture_pool_free(viewport);
+
 	MEM_freeN(viewport->fbl);
 	MEM_freeN(viewport->txl);




More information about the Bf-blender-cvs mailing list