From cbad0a7684e07a62159a6a550e9546c8b6a6720e Mon Sep 17 00:00:00 2001 From: Paul McCarthy <pauld.mccarthy@gmail.com> Date: Fri, 22 Jan 2016 11:37:18 +0000 Subject: [PATCH] GLSLShader.set keeps track of value changes, and returns True or False so caller can tell whether shader state was actually changed. GLVolume (for OpenGL 2.1) updated to use this feature. --- fsl/fsleyes/gl/gl14/glvolume_funcs.py | 2 ++ fsl/fsleyes/gl/gl21/glvolume_funcs.py | 32 +++++++++++++++----------- fsl/fsleyes/gl/glvolume.py | 5 ++-- fsl/fsleyes/gl/shaders/glsl/program.py | 20 +++++++++++++++- 4 files changed, 41 insertions(+), 18 deletions(-) diff --git a/fsl/fsleyes/gl/gl14/glvolume_funcs.py b/fsl/fsleyes/gl/gl14/glvolume_funcs.py index 3b1852abe..8fe4900c9 100644 --- a/fsl/fsleyes/gl/gl14/glvolume_funcs.py +++ b/fsl/fsleyes/gl/gl14/glvolume_funcs.py @@ -106,6 +106,8 @@ def updateShaderState(self): self.shader.unload() + return True + def preDraw(self): """Prepares to draw a slice from the given :class:`.GLVolume` instance. """ diff --git a/fsl/fsleyes/gl/gl21/glvolume_funcs.py b/fsl/fsleyes/gl/gl21/glvolume_funcs.py index 9fabd0001..0d437e29d 100644 --- a/fsl/fsleyes/gl/gl21/glvolume_funcs.py +++ b/fsl/fsleyes/gl/gl21/glvolume_funcs.py @@ -83,24 +83,28 @@ def updateShaderState(self): self.colourTexture.getCoordinateTransform()) shader.load() + + changed = False - shader.set('useSpline', opts.interpolation == 'spline') - shader.set('imageShape', self.image.shape[:3]) - shader.set('clipLow', clipLow) - shader.set('clipHigh', clipHigh) - shader.set('texZero', texZero) - shader.set('invertClip', opts.invertClipping) - shader.set('useNegCmap', opts.useNegativeCmap) - shader.set('imageIsClip', opts.clipImage is None) - shader.set('img2CmapXform', img2CmapXform) - - shader.set('imageTexture', 0) - shader.set('colourTexture', 1) - shader.set('negColourTexture', 2) - shader.set('clipTexture', 3) + changed |= shader.set('useSpline', opts.interpolation == 'spline') + changed |= shader.set('imageShape', self.image.shape[:3]) + changed |= shader.set('clipLow', clipLow) + changed |= shader.set('clipHigh', clipHigh) + changed |= shader.set('texZero', texZero) + changed |= shader.set('invertClip', opts.invertClipping) + changed |= shader.set('useNegCmap', opts.useNegativeCmap) + changed |= shader.set('imageIsClip', opts.clipImage is None) + changed |= shader.set('img2CmapXform', img2CmapXform) + + changed |= shader.set('imageTexture', 0) + changed |= shader.set('colourTexture', 1) + changed |= shader.set('negColourTexture', 2) + changed |= shader.set('clipTexture', 3) shader.unload() + return changed + def preDraw(self): """Sets up the GL state to draw a slice from the given :class:`.GLVolume` diff --git a/fsl/fsleyes/gl/glvolume.py b/fsl/fsleyes/gl/glvolume.py index 5e07775dc..261488e83 100644 --- a/fsl/fsleyes/gl/glvolume.py +++ b/fsl/fsleyes/gl/glvolume.py @@ -265,11 +265,10 @@ class GLVolume(globject.GLImageObject): def update(*a): self.notify() - def shaderUpdate(*a): if self.ready(): - fslgl.glvolume_funcs.updateShaderState(self) - self.notify() + if fslgl.glvolume_funcs.updateShaderState(self): + self.notify() def colourUpdate(*a): self.refreshColourTextures() diff --git a/fsl/fsleyes/gl/shaders/glsl/program.py b/fsl/fsleyes/gl/shaders/glsl/program.py index 49275d54e..9e3c381c7 100644 --- a/fsl/fsleyes/gl/shaders/glsl/program.py +++ b/fsl/fsleyes/gl/shaders/glsl/program.py @@ -149,6 +149,13 @@ class GLSLShader(object): self.vertUniforms, self.fragUniforms) + # We cache the most recent value for + # every uniform. When a call to set() + # is made, if the value is unchanged, + # we skip the GL call. + self.values = {n : None for n in self.positions.keys()} + + # Buffers for vertex attributes self.buffers = {} for att in self.vertAttributes: @@ -234,7 +241,16 @@ class GLSLShader(object): def set(self, name, value): - """Sets the value for the specified GLSL ``uniform`` variable. """ + """Sets the value for the specified GLSL ``uniform`` variable. + + The ``GLSLShader`` keeps a copy of the value of every uniform, to + avoid unnecessary GL calls. + + :returns: ``True`` if the value was changed, ``False`` otherwise. + """ + + if self.values[name] == value: + return False vPos = self.positions[name] vType = self.types[ name] @@ -250,6 +266,8 @@ class GLSLShader(object): setfunc(vPos, value) + return True + def setAtt(self, name, value, divisor=None): """Sets the value for the specified GLSL ``attribute`` variable. -- GitLab