[Bf-blender-cvs] [1e6108e9724] blender2.8: OpenColorIO: cache multiple shaders instead of just one.

Brecht Van Lommel noreply at git.blender.org
Thu May 31 11:21:24 CEST 2018


Commit: 1e6108e97246fe544e39d5a6d9fb907847fd907b
Author: Brecht Van Lommel
Date:   Thu May 31 08:26:23 2018 +0200
Branches: blender2.8
https://developer.blender.org/rB1e6108e97246fe544e39d5a6d9fb907847fd907b

OpenColorIO: cache multiple shaders instead of just one.

Fixes constant shader and texture rebuilding when doing animation playback
with multiple editors that use different view transforms.

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

M	intern/opencolorio/ocio_impl_glsl.cc

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

diff --git a/intern/opencolorio/ocio_impl_glsl.cc b/intern/opencolorio/ocio_impl_glsl.cc
index e20d507b470..090422ff795 100644
--- a/intern/opencolorio/ocio_impl_glsl.cc
+++ b/intern/opencolorio/ocio_impl_glsl.cc
@@ -59,13 +59,19 @@ using namespace OCIO_NAMESPACE;
 #include "ocio_impl.h"
 
 static const int LUT3D_EDGE_SIZE = 64;
+static const int SHADER_CACHE_SIZE = 4;
 
 extern "C" char datatoc_gpu_shader_display_transform_glsl[];
 extern "C" char datatoc_gpu_shader_display_transform_vertex_glsl[];
 
 /* **** OpenGL drawing routines using GLSL for color space transform ***** */
 
-typedef struct OCIO_GLSLDrawState {
+typedef struct OCIO_GLSLShader {
+	/* Cache ID */
+	std::string lut3dCacheID;
+	std::string shaderCacheID;
+
+	/* LUT */
 	bool lut3d_texture_allocated;  /* boolean flag indicating whether
 	                                * lut texture is allocated
 	                                */
@@ -75,25 +81,29 @@ typedef struct OCIO_GLSLDrawState {
 
 	float *lut3d;  /* 3D LUT table */
 
-	bool dither_used;
+	/* Dither */
+	bool use_dither;
 
-	bool curve_mapping_used;
+	/* Curve Mapping */
+	bool use_curve_mapping;
 	bool curve_mapping_texture_allocated;
 	bool curve_mapping_texture_valid;
 	GLuint curve_mapping_texture;
 	size_t curve_mapping_cache_id;
 
-	bool predivide_used;
-
-	/* Cache */
-	std::string lut3dcacheid;
-	std::string shadercacheid;
+	/* Alpha Predivide */
+	bool use_predivide;
 
 	/* GLSL stuff */
 	GLuint ocio_shader;
 	GLuint vert_shader;
 	GLuint program;
 	Gwn_ShaderInterface *shader_interface;
+} GLSLDrawState;
+
+typedef struct OCIO_GLSLDrawState {
+	/* Shader Cache */
+	OCIO_GLSLShader *shader_cache[SHADER_CACHE_SIZE];
 
 	/* Previous OpenGL state. */
 	GLint last_texture, last_texture_unit;
@@ -150,33 +160,24 @@ static GLuint linkShaders(GLuint ocio_shader, GLuint vert_shader)
 
 static OCIO_GLSLDrawState *allocateOpenGLState(void)
 {
-	OCIO_GLSLDrawState *state;
-
-	/* Allocate memory for state. */
-	state = (OCIO_GLSLDrawState *) MEM_callocN(sizeof(OCIO_GLSLDrawState),
-	                                           "OCIO OpenGL State struct");
-
-	/* Call constructors on new memory. */
-	new (&state->lut3dcacheid) std::string("");
-	new (&state->shadercacheid) std::string("");
-
-	return state;
+	return (OCIO_GLSLDrawState *) MEM_callocN(sizeof(OCIO_GLSLDrawState),
+	                                          "OCIO OpenGL State struct");
 }
 
 /* Ensure LUT texture and array are allocated */
-static bool ensureLUT3DAllocated(OCIO_GLSLDrawState *state)
+static bool ensureLUT3DAllocated(OCIO_GLSLShader *shader)
 {
 	int num_3d_entries = 3 * LUT3D_EDGE_SIZE * LUT3D_EDGE_SIZE * LUT3D_EDGE_SIZE;
 
-	if (state->lut3d_texture_allocated)
-		return state->lut3d_texture_valid;
+	if (shader->lut3d_texture_allocated)
+		return shader->lut3d_texture_valid;
 
-	glGenTextures(1, &state->lut3d_texture);
+	glGenTextures(1, &shader->lut3d_texture);
 
-	state->lut3d = (float *) MEM_callocN(sizeof(float) * num_3d_entries, "OCIO GPU 3D LUT");
+	shader->lut3d = (float *) MEM_callocN(sizeof(float) * num_3d_entries, "OCIO GPU 3D LUT");
 
 	glActiveTexture(GL_TEXTURE1);
-	glBindTexture(GL_TEXTURE_3D, state->lut3d_texture);
+	glBindTexture(GL_TEXTURE_3D, shader->lut3d_texture);
 	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -188,27 +189,27 @@ static bool ensureLUT3DAllocated(OCIO_GLSLDrawState *state)
 
 	glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB16F_ARB,
 	             LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE,
-	             0, GL_RGB, GL_FLOAT, state->lut3d);
+	             0, GL_RGB, GL_FLOAT, shader->lut3d);
 
-	state->lut3d_texture_allocated = true;
+	shader->lut3d_texture_allocated = true;
 
 	/* GL_RGB16F_ARB could be not supported at some drivers
 	 * in this case we could not use GLSL display
 	 */
-	state->lut3d_texture_valid = glGetError() == GL_NO_ERROR;
+	shader->lut3d_texture_valid = glGetError() == GL_NO_ERROR;
 
-	return state->lut3d_texture_valid;
+	return shader->lut3d_texture_valid;
 }
 
-static bool ensureCurveMappingAllocated(OCIO_GLSLDrawState *state, OCIO_CurveMappingSettings *curve_mapping_settings)
+static bool ensureCurveMappingAllocated(OCIO_GLSLShader *shader, OCIO_CurveMappingSettings *curve_mapping_settings)
 {
-	if (state->curve_mapping_texture_allocated)
-		return state->curve_mapping_texture_valid;
+	if (shader->curve_mapping_texture_allocated)
+		return shader->curve_mapping_texture_valid;
 
-	glGenTextures(1, &state->curve_mapping_texture);
+	glGenTextures(1, &shader->curve_mapping_texture);
 
 	glActiveTexture(GL_TEXTURE2);
-	glBindTexture(GL_TEXTURE_1D, state->curve_mapping_texture);
+	glBindTexture(GL_TEXTURE_1D, shader->curve_mapping_texture);
 	glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 	glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 	glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -221,16 +222,51 @@ static bool ensureCurveMappingAllocated(OCIO_GLSLDrawState *state, OCIO_CurveMap
 	glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA16F, curve_mapping_settings->lut_size,
 	             0, GL_RGBA, GL_FLOAT, curve_mapping_settings->lut);
 
-	state->curve_mapping_texture_allocated = true;
+	shader->curve_mapping_texture_allocated = true;
 
 	/* GL_RGB16F_ARB could be not supported at some drivers
 	 * in this case we could not use GLSL display
 	 */
-	state->curve_mapping_texture_valid = glGetError() == GL_NO_ERROR;
+	shader->curve_mapping_texture_valid = glGetError() == GL_NO_ERROR;
 
-	return state->curve_mapping_texture_valid;
+	return shader->curve_mapping_texture_valid;
 }
 
+static void freeGLSLShader(OCIO_GLSLShader *shader)
+{
+	if (shader->curve_mapping_texture_allocated) {
+		glDeleteTextures(1, &shader->curve_mapping_texture);
+	}
+
+	if (shader->lut3d_texture_allocated) {
+		glDeleteTextures(1, &shader->lut3d_texture);
+	}
+
+	if (shader->lut3d) {
+		MEM_freeN(shader->lut3d);
+	}
+
+	if (shader->program) {
+		glDeleteProgram(shader->program);
+	}
+
+	if (shader->shader_interface) {
+		GWN_shaderinterface_discard(shader->shader_interface);
+	}
+
+	if (shader->ocio_shader) {
+		glDeleteShader(shader->ocio_shader);
+	}
+
+	using std::string;
+	shader->lut3dCacheID.~string();
+	shader->shaderCacheID.~string();
+
+	MEM_freeN(shader);
+}
+
+
+
 /* Detect if we can support GLSL drawing */
 bool OCIOImpl::supportGLSLDraw()
 {
@@ -265,135 +301,154 @@ bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRc
 	glGetIntegerv(GL_TEXTURE_BINDING_2D, &state->last_texture);
 	glGetIntegerv(GL_ACTIVE_TEXTURE, &state->last_texture_unit);
 
-	if (!ensureLUT3DAllocated(state)) {
-		glActiveTexture(state->last_texture_unit);
-		glBindTexture(GL_TEXTURE_2D, state->last_texture);
+	/* Compute cache IDs. */
+	GpuShaderDesc shaderDesc;
+	shaderDesc.setLanguage(GPU_LANGUAGE_GLSL_1_3);
+	shaderDesc.setFunctionName("OCIODisplay");
+	shaderDesc.setLut3DEdgeLen(LUT3D_EDGE_SIZE);
 
-		return false;
-	}
+	std::string lut3dCacheID = ocio_processor->getGpuLut3DCacheID(shaderDesc);
+	std::string shaderCacheID = ocio_processor->getGpuShaderTextCacheID(shaderDesc);
 
-	if (use_curve_mapping) {
-		if (!ensureCurveMappingAllocated(state, curve_mapping_settings)) {
-			glActiveTexture(state->last_texture_unit);
-			glBindTexture(GL_TEXTURE_2D, state->last_texture);
+	/* Find matching cached shader. */
+	OCIO_GLSLShader *shader = NULL;
+	for (int i = 0; i < SHADER_CACHE_SIZE; i++) {
+		OCIO_GLSLShader *cached_shader = state->shader_cache[i];
+		if (cached_shader == NULL) {
+			continue;
+		}
+
+		if (cached_shader->lut3dCacheID == lut3dCacheID &&
+		    cached_shader->shaderCacheID == shaderCacheID &&
+		    cached_shader->use_predivide == use_predivide &&
+		    cached_shader->use_curve_mapping == use_curve_mapping &&
+		    cached_shader->use_dither == use_dither)
+		{
+			/* LRU cache, so move to front. */
+			for (int j = i; j > 0; j--) {
+				state->shader_cache[j] = state->shader_cache[j - 1];
+			}
+			state->shader_cache[0] = cached_shader;
 
-			return false;
+			shader = cached_shader;
+			break;
 		}
 	}
-	else {
-		if (state->curve_mapping_texture_allocated) {
-			glDeleteTextures(1, &state->curve_mapping_texture);
-			state->curve_mapping_texture_allocated = false;
+
+	if (shader == NULL) {
+		/* LRU cache, shift other items back so we can insert at the front. */
+		OCIO_GLSLShader *last_shader = state->shader_cache[SHADER_CACHE_SIZE - 1];
+		if (last_shader) {
+			freeGLSLShader(last_shader);
+		}
+		for (int j = SHADER_CACHE_SIZE - 1; j > 0; j--) {
+			state->shader_cache[j] = state->shader_cache[j - 1];
 		}
-	}
 
-	/* Step 1: Create a GPU Shader Description */
-	GpuShaderDesc shaderDesc;
-	shaderDesc.setLanguage(GPU_LANGUAGE_GLSL_1_3);
-	shaderDesc.setFunctionName("OCIODisplay");
-	shaderDesc.setLut3DEdgeLen(LUT3D_EDGE_SIZE);
+		/* Allocate memory for shader. */
+		shader = (OCIO_GLSLShader *) MEM_callocN(sizeof(OCIO_GLSLShader),
+		                                         "OCIO GLSL Shader");
+		state->shader_cache[0] = shader;
 
-	if (use_curve_mapping) {
-		if (state->curve_mapping_cache_id != curve_mapping_settings->cache_id) {
-			glActiveTexture(GL_TEXTURE2);
-			glBindTexture(GL_TEXTURE_1D, state->curve_mapping_texture);
-			glTexSubImage1D(GL_TEXTURE_1D, 0, 0, curve_mapping_settings->lut_size,
-			                GL_RGBA, GL_FLOAT, curve_mapping_settings->lut);
-		}
-	}
+		new (&shader->lut3dCacheID) std::string();
+		new (&shader->shaderCacheID) std::string();
 
-	/* Step 2: Compute the 3D LUT */
-	std::string lut3dCacheID = ocio_processor->getGpuLut3DCacheID(shaderDesc);
-	if (lut3dCacheID != state->lut3dcacheid) {
-		state->lut3dcacheid = lut3dCacheID;
-		ocio_processor->getGpuLut3D(state->lut3d, shaderDesc);
+        shader->lut3dCacheID = lut3dCacheID;
+        shader->shaderCacheID = shaderCacheID;
+		shader->use_curve_mapping = use_curve_mapping;
+		shader->use_dither = use_dither;
+		shader->use_predivide = use_predivide;
 
-		glActiveTexture(GL_TEXTURE1);
-		glBindTexture(GL_TEXTURE_3D, state->lut3d_texture);
-		glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0,

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list