diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2017-05-16 03:59:25 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2017-05-16 21:27:52 +0300 |
commit | 7a029f4e00cc9a9f6a938cf701e6ed4c91115264 (patch) | |
tree | a315770fc2fbd5807ba262e9cbdcc179877d4125 /source/blender | |
parent | dc01586b4063142a3736993eb4a6e4fec893bed1 (diff) |
GPUViewport: Add a Texture Pool to reuse textures across engines.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/gpu/GPU_texture.h | 1 | ||||
-rw-r--r-- | source/blender/gpu/GPU_viewport.h | 3 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_texture.c | 10 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_viewport.c | 67 |
4 files changed, 81 insertions, 0 deletions
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); |