From 87ff90fb03216737df70ff83246664b7fba2663e Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Mon, 22 Aug 2011 16:38:45 +0200 Subject: Fix regression of commit 6c346d98f04e2355210960fe9ffde47432f04d62, where VBO/attribute binding wasn't updated (VBO data written, shader change/switch attribute on same location) ; Optimized interleaved GLSL VBO binding, hence split up GLArrayHandler syncData/enableState --- .../com/jogamp/opengl/util/GLArrayDataClient.java | 8 +- .../com/jogamp/opengl/util/GLArrayHandler.java | 14 ++- .../com/jogamp/opengl/util/glsl/ShaderState.java | 103 ++++++++++++++------- .../jogamp/opengl/util/GLDataArrayHandler.java | 9 +- .../jogamp/opengl/util/GLFixedArrayHandler.java | 54 +++++------ .../opengl/util/GLFixedArrayHandlerFlat.java | 40 ++++---- .../util/GLFixedArrayHandlerInterleaved.java | 18 ++-- .../jogamp/opengl/util/glsl/GLSLArrayHandler.java | 38 ++++++-- .../opengl/util/glsl/GLSLArrayHandlerFlat.java | 14 ++- .../util/glsl/GLSLArrayHandlerInterleaved.java | 46 +++++++-- .../test/junit/jogl/glsl/GLSLMiscHelper.java | 2 +- 11 files changed, 230 insertions(+), 116 deletions(-) (limited to 'src') diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java index 13c61766e..3600081bc 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java @@ -162,7 +162,13 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData // init/generate VBO name if not done yet init_vbo(gl); } - glArrayHandler.enableBuffer(gl, enable); + if(enable) { + glArrayHandler.syncData(gl, true); + glArrayHandler.enableState(gl, true); + } else { + glArrayHandler.enableState(gl, false); + glArrayHandler.syncData(gl, false); + } bufferEnabled = enable; } } diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayHandler.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayHandler.java index ee80c4299..b30e220bd 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayHandler.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayHandler.java @@ -11,13 +11,21 @@ import javax.media.opengl.*; public interface GLArrayHandler { /** - * Implementation shall ensure the buffers data is synchronized to the GPU - * and the array state is enabled. + * Implementation shall associate the data with the array + * and synchronize the data with the GPU. + * + * @param gl current GL object + * @param enable true if array data shall be valid, otherwise false. + */ + public void syncData(GL gl, boolean enable); + + /** + * Implementation shall enable or disable the array state. * * @param gl current GL object * @param enable true if array shall be enabled, otherwise false. */ - public void enableBuffer(GL gl, boolean enable); + public void enableState(GL gl, boolean enable); /** * Supporting interleaved arrays, where sub handlers may handle diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java index e8a547057..a2a012e08 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java @@ -303,7 +303,7 @@ public class ShaderState { * @see #getAttribLocation(GL2ES2, String) * @see GL2ES2#glGetAttribLocation(int, String) */ - public int getAttribLocation(String name) { + public int getCachedAttribLocation(String name) { Integer idx = (Integer) activeAttribLocationMap.get(name); return (null!=idx)?idx.intValue():-1; } @@ -346,7 +346,7 @@ public class ShaderState { */ public void ownAttribute(GLArrayData attribute, boolean own) { if(own) { - final int location = getAttribLocation(attribute.getName()); + final int location = getCachedAttribLocation(attribute.getName()); if(0<=location) { attribute.setLocation(location); } @@ -363,7 +363,7 @@ public class ShaderState { /** * Binds a shader attribute to a location. * Multiple names can be bound to one location. - * The value will be cached and can be retrieved via {@link #getAttribLocation(String)} + * The value will be cached and can be retrieved via {@link #getCachedAttribLocation(String)} * before or after linking. * * @throws GLException if no program is attached @@ -371,7 +371,7 @@ public class ShaderState { * * @see javax.media.opengl.GL2ES2#glBindAttribLocation(int, int, String) * @see #getAttribLocation(GL2ES2, String) - * @see #getAttribLocation(String) + * @see #getCachedAttribLocation(String) */ public void bindAttribLocation(GL2ES2 gl, int location, String name) { if(null==shaderProgram) throw new GLException("No program is attached"); @@ -384,7 +384,7 @@ public class ShaderState { /** * Binds a shader {@link GLArrayData} attribute to a location. * Multiple names can be bound to one location. - * The value will be cached and can be retrieved via {@link #getAttribLocation(String)} + * The value will be cached and can be retrieved via {@link #getCachedAttribLocation(String)} * and {@link #getAttribute(String)}before or after linking. * The {@link GLArrayData}'s location will be set as well. * @@ -393,7 +393,7 @@ public class ShaderState { * * @see javax.media.opengl.GL2ES2#glBindAttribLocation(int, int, String) * @see #getAttribLocation(GL2ES2, String) - * @see #getAttribLocation(String) + * @see #getCachedAttribLocation(String) * @see #getAttribute(String) */ public void bindAttribLocation(GL2ES2 gl, int location, GLArrayData data) { @@ -403,24 +403,24 @@ public class ShaderState { } /** - * Gets the location of a shader attribute, - * either the cached value {@link #getAttribLocation(String)} if valid or - * the retrieved one {@link GL2ES2#glGetAttribLocation(int, String)}. - * In the latter case the value will be cached. + * Gets the location of a shader attribute.
+ * Uses either the cached value {@link #getCachedAttribLocation(String)} if valid, + * or the GLSL queried via {@link GL2ES2#glGetAttribLocation(int, String)}.
+ * The location will be cached. * * @return -1 if there is no such attribute available, * otherwise >= 0 * @throws GLException if no program is attached * @throws GLException if the program is not linked and no location was cached. * - * @see #getAttribLocation(String) + * @see #getCachedAttribLocation(String) * @see #bindAttribLocation(GL2ES2, int, GLArrayData) * @see #bindAttribLocation(GL2ES2, int, String) * @see GL2ES2#glGetAttribLocation(int, String) */ public int getAttribLocation(GL2ES2 gl, String name) { if(null==shaderProgram) throw new GLException("No program is attached"); - int location = getAttribLocation(name); + int location = getCachedAttribLocation(name); if(0>location) { if(!shaderProgram.linked()) throw new GLException("Program is not linked"); location = gl.glGetAttribLocation(shaderProgram.program(), name); @@ -439,11 +439,11 @@ public class ShaderState { } /** - * Gets the location of a shader attribute, - * either the cached value {@link #getAttribLocation(String)} if valid or - * the retrieved one {@link GL2ES2#glGetAttribLocation(int, String)}. - * In the latter case the value will be cached. - * The {@link GLArrayData}'s location will be set as well. + * Validates and returns the location of a shader attribute.
+ * Uses either the cached value {@link #getCachedAttribLocation(String)} if valid, + * or the GLSL queried via {@link GL2ES2#glGetAttribLocation(int, String)}.
+ * The location will be cached and set in the + * {@link GLArrayData} object. * * @return -1 if there is no such attribute available, * otherwise >= 0 @@ -451,7 +451,7 @@ public class ShaderState { * @throws GLException if no program is attached * @throws GLException if the program is not linked and no location was cached. * - * @see #getAttribLocation(String) + * @see #getCachedAttribLocation(String) * @see #bindAttribLocation(GL2ES2, int, GLArrayData) * @see #bindAttribLocation(GL2ES2, int, String) * @see GL2ES2#glGetAttribLocation(int, String) @@ -646,11 +646,7 @@ public class ShaderState { int location = data.getLocation(); if(0 > location) { location = getAttribLocation(gl, data); - } /* else { - done via enable .. - // ensure data is the current bound one - activeAttribDataMap.put(data.getName(), data); - } */ + } if(0 <= location) { // only pass the data, if the attribute exists in the current shader if(DEBUG) { @@ -804,6 +800,17 @@ public class ShaderState { // Shader Uniform handling // + /** + * Gets the cached location of the shader uniform. + * + * @return -1 if there is no such uniform available, + * otherwise >= 0 + */ + public final int getCachedUniformLocation(String name) { + Integer idx = (Integer) activeUniformLocationMap.get(name); + return (null!=idx)?idx.intValue():-1; + } + /** * Bind the {@link GLUniform} lifecycle to this ShaderState. * @@ -819,7 +826,7 @@ public class ShaderState { * @see #getUniform(String) */ public void ownUniform(GLUniformData uniform) { - final int location = getUniformLocation(uniform.getName()); + final int location = getCachedUniformLocation(uniform.getName()); if(0<=location) { uniform.setLocation(location); } @@ -832,8 +839,13 @@ public class ShaderState { } /** - * Gets the index of a shader uniform. - * This must be done when the program is in use ! + * Gets the location of a shader uniform.
+ * Uses either the cached value {@link #getCachedUniformLocation(String)} if valid, + * or the GLSL queried via {@link GL2ES2#glGetUniformLocation(int, String)}.
+ * The location will be cached. + *

+ * The current shader program ({@link #attachShaderProgram(GL2ES2, ShaderProgram)}) + * must be in use ({@link #useProgram(GL2ES2, boolean) }) !

* * @return -1 if there is no such attribute available, * otherwise >= 0 @@ -845,9 +857,9 @@ public class ShaderState { * @see #getUniformLocation * @see ShaderProgram#glReplaceShader */ - protected final int getUniformLocation(GL2ES2 gl, String name) { + public final int getUniformLocation(GL2ES2 gl, String name) { if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); - int location = getUniformLocation(name); + int location = getCachedUniformLocation(name); if(0>location) { location = gl.glGetUniformLocation(shaderProgram.program(), name); if(0<=location) { @@ -861,11 +873,33 @@ public class ShaderState { return location; } - protected final int getUniformLocation(String name) { - Integer idx = (Integer) activeUniformLocationMap.get(name); - return (null!=idx)?idx.intValue():-1; - } + /** + * Validates and returns the location of a shader uniform.
+ * Uses either the cached value {@link #getCachedUniformLocation(String)} if valid, + * or the GLSL queried via {@link GL2ES2#glGetUniformLocation(int, String)}.
+ * The location will be cached and set in the + * {@link GLUniformData} object. + *

+ * The current shader program ({@link #attachShaderProgram(GL2ES2, ShaderProgram)}) + * must be in use ({@link #useProgram(GL2ES2, boolean) }) !

+ * + * @return -1 if there is no such attribute available, + * otherwise >= 0 + * @throws GLException is the program is not linked + * + * @see #glGetUniformLocation + * @see javax.media.opengl.GL2ES2#glGetUniformLocation + * @see #getUniformLocation + * @see ShaderProgram#glReplaceShader + */ + public int getUniformLocation(GL2ES2 gl, GLUniformData data) { + int location = getUniformLocation(gl, data.getName()); + data.setLocation(location); + activeUniformDataMap.put(data.getName(), data); + return location; + } + /** * Set the uniform data. * @@ -883,6 +917,7 @@ public class ShaderState { * * @see #glGetUniformLocation * @see javax.media.opengl.GL2ES2#glGetUniformLocation + * @see javax.media.opengl.GL2ES2#glUniform * @see #getUniformLocation * @see ShaderProgram#glReplaceShader */ @@ -890,10 +925,8 @@ public class ShaderState { if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); int location = data.getLocation(); if(0>location) { - location = getUniformLocation(gl, data.getName()); - data.setLocation(location); + location = getUniformLocation(gl, data); } - activeUniformDataMap.put(data.getName(), data); if(0<=location) { // only pass the data, if the uniform exists in the current shader if(DEBUG) { diff --git a/src/jogl/classes/jogamp/opengl/util/GLDataArrayHandler.java b/src/jogl/classes/jogamp/opengl/util/GLDataArrayHandler.java index 718b63822..259b8ae23 100644 --- a/src/jogl/classes/jogamp/opengl/util/GLDataArrayHandler.java +++ b/src/jogl/classes/jogamp/opengl/util/GLDataArrayHandler.java @@ -29,6 +29,7 @@ package jogamp.opengl.util; import javax.media.opengl.*; + import com.jogamp.opengl.util.*; import java.nio.*; @@ -52,7 +53,7 @@ public class GLDataArrayHandler implements GLArrayHandler { throw new UnsupportedOperationException(); } - public final void enableBuffer(GL gl, boolean enable) { + public final void syncData(GL gl, boolean enable) { if(enable) { Buffer buffer = ad.getBuffer(); @@ -67,7 +68,11 @@ public class GLDataArrayHandler implements GLArrayHandler { } } else { gl.glBindBuffer(ad.getVBOTarget(), 0); - } + } + } + + public final void enableState(GL gl, boolean enable) { + // no array association } } diff --git a/src/jogl/classes/jogamp/opengl/util/GLFixedArrayHandler.java b/src/jogl/classes/jogamp/opengl/util/GLFixedArrayHandler.java index e365f0f4b..2cce72ff4 100644 --- a/src/jogl/classes/jogamp/opengl/util/GLFixedArrayHandler.java +++ b/src/jogl/classes/jogamp/opengl/util/GLFixedArrayHandler.java @@ -51,30 +51,9 @@ public class GLFixedArrayHandler implements GLArrayHandler { throw new UnsupportedOperationException(); } - private final void passArrayPointer(GLPointerFunc gl) { - switch(ad.getIndex()) { - case GLPointerFunc.GL_VERTEX_ARRAY: - gl.glVertexPointer(ad); - break; - case GLPointerFunc.GL_NORMAL_ARRAY: - gl.glNormalPointer(ad); - break; - case GLPointerFunc.GL_COLOR_ARRAY: - gl.glColorPointer(ad); - break; - case GLPointerFunc.GL_TEXTURE_COORD_ARRAY: - gl.glTexCoordPointer(ad); - break; - default: - throw new GLException("invalid glArrayIndex: "+ad.getIndex()+":\n\t"+ad); - } - } - - public final void enableBuffer(GL gl, boolean enable) { - GLPointerFunc glp = gl.getGL2ES1(); + public final void syncData(GL gl, boolean enable) { if(enable) { - Buffer buffer = ad.getBuffer(); - + final Buffer buffer = ad.getBuffer(); if(ad.isVBO()) { // always bind and refresh the VBO mgr, // in case more than one gl*Pointer objects are in use @@ -86,13 +65,34 @@ public class GLFixedArrayHandler implements GLArrayHandler { ad.setVBOWritten(true); } } - passArrayPointer(glp); + final GLPointerFunc glp = gl.getGL2ES1(); + switch(ad.getIndex()) { + case GLPointerFunc.GL_VERTEX_ARRAY: + glp.glVertexPointer(ad); + break; + case GLPointerFunc.GL_NORMAL_ARRAY: + glp.glNormalPointer(ad); + break; + case GLPointerFunc.GL_COLOR_ARRAY: + glp.glColorPointer(ad); + break; + case GLPointerFunc.GL_TEXTURE_COORD_ARRAY: + glp.glTexCoordPointer(ad); + break; + default: + throw new GLException("invalid glArrayIndex: "+ad.getIndex()+":\n\t"+ad); + } + } else if(ad.isVBO()) { + gl.glBindBuffer(ad.getVBOTarget(), 0); + } + } + + public final void enableState(GL gl, boolean enable) { + final GLPointerFunc glp = gl.getGL2ES1(); + if(enable) { glp.glEnableClientState(ad.getIndex()); } else { glp.glDisableClientState(ad.getIndex()); - if(ad.isVBO()) { - gl.glBindBuffer(ad.getVBOTarget(), 0); - } } } } diff --git a/src/jogl/classes/jogamp/opengl/util/GLFixedArrayHandlerFlat.java b/src/jogl/classes/jogamp/opengl/util/GLFixedArrayHandlerFlat.java index e1cf5d572..4dda9c6a1 100644 --- a/src/jogl/classes/jogamp/opengl/util/GLFixedArrayHandlerFlat.java +++ b/src/jogl/classes/jogamp/opengl/util/GLFixedArrayHandlerFlat.java @@ -50,29 +50,31 @@ public class GLFixedArrayHandlerFlat implements GLArrayHandler { throw new UnsupportedOperationException(); } - private final void passArrayPointer(GLPointerFunc gl) { - switch(ad.getIndex()) { - case GLPointerFunc.GL_VERTEX_ARRAY: - gl.glVertexPointer(ad); - break; - case GLPointerFunc.GL_NORMAL_ARRAY: - gl.glNormalPointer(ad); - break; - case GLPointerFunc.GL_COLOR_ARRAY: - gl.glColorPointer(ad); - break; - case GLPointerFunc.GL_TEXTURE_COORD_ARRAY: - gl.glTexCoordPointer(ad); - break; - default: - throw new GLException("invalid glArrayIndex: "+ad.getIndex()+":\n\t"+ad); + public final void syncData(GL gl, boolean enable) { + if(enable) { + final GLPointerFunc glp = gl.getGL2ES1(); + switch(ad.getIndex()) { + case GLPointerFunc.GL_VERTEX_ARRAY: + glp.glVertexPointer(ad); + break; + case GLPointerFunc.GL_NORMAL_ARRAY: + glp.glNormalPointer(ad); + break; + case GLPointerFunc.GL_COLOR_ARRAY: + glp.glColorPointer(ad); + break; + case GLPointerFunc.GL_TEXTURE_COORD_ARRAY: + glp.glTexCoordPointer(ad); + break; + default: + throw new GLException("invalid glArrayIndex: "+ad.getIndex()+":\n\t"+ad); + } } } - public final void enableBuffer(GL gl, boolean enable) { - GLPointerFunc glp = gl.getGL2ES1(); + public final void enableState(GL gl, boolean enable) { + final GLPointerFunc glp = gl.getGL2ES1(); if(enable) { - passArrayPointer(glp); glp.glEnableClientState(ad.getIndex()); } else { glp.glDisableClientState(ad.getIndex()); diff --git a/src/jogl/classes/jogamp/opengl/util/GLFixedArrayHandlerInterleaved.java b/src/jogl/classes/jogamp/opengl/util/GLFixedArrayHandlerInterleaved.java index 838032646..4bac20217 100644 --- a/src/jogl/classes/jogamp/opengl/util/GLFixedArrayHandlerInterleaved.java +++ b/src/jogl/classes/jogamp/opengl/util/GLFixedArrayHandlerInterleaved.java @@ -54,15 +54,15 @@ public class GLFixedArrayHandlerInterleaved implements GLArrayHandler { subArrays.add(handler); } - private final void enableSubBuffer(GL gl, boolean enable) { + private final void syncSubData(GL gl, boolean enable) { for(int i=0; i= 0) { + } else if(st.getAttribLocation(glsl, ad) >= 0) { // didn't experience a performance hit on this query .. + // (using ShaderState's location query above to validate the location) final int[] qi = new int[1]; glsl.glGetVertexAttribiv(ad.getLocation(), GL2ES2.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, qi, 0); if(ad.getVBOName() != qi[0]) { @@ -81,12 +95,18 @@ public class GLSLArrayHandler implements GLArrayHandler { } else if(null!=buffer) { st.vertexAttribPointer(glsl, ad); } + } else if(ad.isVBO()) { + glsl.glBindBuffer(ad.getVBOTarget(), 0); + } + } + + public final void enableState(GL gl, boolean enable) { + final GL2ES2 glsl = gl.getGL2ES2(); + + if(enable) { st.enableVertexAttribArray(glsl, ad); } else { st.disableVertexAttribArray(glsl, ad); - if(ad.isVBO()) { - glsl.glBindBuffer(ad.getVBOTarget(), 0); - } } } diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java index 38379877f..5c4aa718c 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java +++ b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java @@ -51,16 +51,20 @@ public class GLSLArrayHandlerFlat implements GLArrayHandler { throw new UnsupportedOperationException(); } - public final void enableBuffer(GL gl, boolean enable) { - GL2ES2 glsl = gl.getGL2ES2(); + public final void syncData(GL gl, boolean enable) { + if(enable) { + st.vertexAttribPointer(gl.getGL2ES2(), ad); + } + } + + public final void enableState(GL gl, boolean enable) { + final GL2ES2 glsl = gl.getGL2ES2(); if(enable) { - st.vertexAttribPointer(glsl, ad); st.enableVertexAttribArray(glsl, ad); } else { st.disableVertexAttribArray(glsl, ad); } - } - + } } diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerInterleaved.java b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerInterleaved.java index ba5814a09..c662c13d2 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerInterleaved.java +++ b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerInterleaved.java @@ -60,21 +60,22 @@ public class GLSLArrayHandlerInterleaved implements GLArrayHandler { subArrays.add(handler); } - private final void enableSubBuffer(GL gl, boolean enable) { + private final void syncSubData(GL gl, boolean enable) { for(int i=0; i= 0) { + // didn't experience a performance hit on this query .. + // (using ShaderState's location query above to validate the location) + final int[] qi = new int[1]; + glsl.glGetVertexAttribiv(ad.getLocation(), GL2ES2.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, qi, 0); + if(ad.getVBOName() != qi[0]) { + glsl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName()); + syncSubData(gl, true); + } + } + } else if(null!=buffer) { + syncSubData(gl, true); + } } else { - enableSubBuffer(gl, false); + syncSubData(gl, false); if(ad.isVBO()) { glsl.glBindBuffer(ad.getVBOTarget(), 0); } - } + } + } + + public final void enableState(GL gl, boolean enable) { + for(int i=0; i