/** * Bind the {@link GLUniform} lifecycle to this ShaderState. * * <p>If a uniform location is cached it is promoted to the {@link GLUniformData} instance. * * <p>The attribute will be destroyed with {@link #destroy(GL2ES2)} and it's location will be * reset when switching shader with {@link #attachShaderProgram(GL2ES2, ShaderProgram)}. * * <p>The data will not be transfered to the GPU, use {@link #uniform(GL2ES2, GLUniformData)} * additionally. * * @param uniform the {@link GLUniformData} which lifecycle shall be managed * @see #getUniform(String) */ public void ownUniform(GLUniformData uniform) { final int location = getCachedUniformLocation(uniform.getName()); if (0 <= location) { uniform.setLocation(location); } activeUniformDataMap.put(uniform.getName(), uniform); managedUniforms.add(uniform); }
public StringBuilder toString(StringBuilder sb, boolean alsoUnlocated) { if (null == sb) { sb = new StringBuilder(); } sb.append("ShaderState[ "); sb.append(Platform.getNewline()).append(" "); if (null != shaderProgram) { shaderProgram.toString(sb); } else { sb.append("ShaderProgram: null"); } sb.append(Platform.getNewline()).append(" enabledAttributes ["); { Iterator<String> names = activedAttribEnabledMap.keySet().iterator(); Iterator<Boolean> values = activedAttribEnabledMap.values().iterator(); while (names.hasNext()) { sb.append(Platform.getNewline()) .append(" ") .append(names.next()) .append(": ") .append(values.next()); } } sb.append(Platform.getNewline()).append(" ],").append(" activeAttributes ["); for (Iterator<GLArrayData> iter = activeAttribDataMap.values().iterator(); iter.hasNext(); ) { final GLArrayData ad = iter.next(); if (alsoUnlocated || 0 <= ad.getLocation()) { sb.append(Platform.getNewline()).append(" ").append(ad); } } sb.append(Platform.getNewline()).append(" ],").append(" managedAttributes ["); for (Iterator<GLArrayData> iter = managedAttributes.iterator(); iter.hasNext(); ) { final GLArrayData ad = iter.next(); if (alsoUnlocated || 0 <= ad.getLocation()) { sb.append(Platform.getNewline()).append(" ").append(ad); } } sb.append(Platform.getNewline()).append(" ],").append(" activeUniforms ["); for (Iterator<GLUniformData> iter = activeUniformDataMap.values().iterator(); iter.hasNext(); ) { final GLUniformData ud = iter.next(); if (alsoUnlocated || 0 <= ud.getLocation()) { sb.append(Platform.getNewline()).append(" ").append(ud); } } sb.append(Platform.getNewline()).append(" ],").append(" managedUniforms ["); for (Iterator<GLUniformData> iter = managedUniforms.iterator(); iter.hasNext(); ) { final GLUniformData ud = iter.next(); if (alsoUnlocated || 0 <= ud.getLocation()) { sb.append(Platform.getNewline()).append(" ").append(ud); } } sb.append(Platform.getNewline()).append(" ]").append(Platform.getNewline()).append("]"); return sb; }
/** * Reset all previously mapped uniform data * * <p>Uniform data and location is bound to the program, hence both are updated here * * @throws GLException is the program is not in use * @see #attachShaderProgram(GL2ES2, ShaderProgram) */ private final void resetAllUniforms(GL2ES2 gl) { if (!shaderProgram.inUse()) throw new GLException("Program is not in use"); activeUniformLocationMap.clear(); for (Iterator<GLUniformData> iter = managedUniforms.iterator(); iter.hasNext(); ) { iter.next().setLocation(-1); } for (Iterator<GLUniformData> iter = activeUniformDataMap.values().iterator(); iter.hasNext(); ) { final GLUniformData uniform = iter.next(); uniform.setLocation(-1); uniform(gl, uniform); } }
private void draw(GL2ES2 gl) { // gl.glClearColor(0.5f, 0.1f, 0.1f, 1); // gl.glClear(GL2ES2.GL_COLOR_BUFFER_BIT); shaderState.useProgram(gl, true); time.setData((System.currentTimeMillis() - millisOffset) / 1000.0f); shaderState.uniform(gl, time); vertices.enableBuffer(gl, true); gl.glDrawArrays(GL2ES2.GL_TRIANGLE_STRIP, 0, 4); vertices.enableBuffer(gl, false); shaderState.useProgram(gl, false); // Compute current framerate and printout. frameCount++; fcount += 1; int m = (int) (System.currentTimeMillis() - millisOffset); if (m - lastm > 1000 * fint) { frameRate = (float) (fcount) / fint; fcount = 0; lastm = m; } if (frameCount % TARGET_FPS == 0) { System.out.println("FrameCount: " + frameCount + " - " + "FrameRate: " + frameRate); } }
/** * Validates and returns the location of a shader uniform.<br> * Uses either the cached value {@link #getCachedUniformLocation(String)} if valid, or the GLSL * queried via {@link GL2ES2#glGetUniformLocation(int, String)}.<br> * The location will be cached and set in the {@link GLUniformData} object. * * <p>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) { if (!shaderProgram.inUse()) throw new GLException("Program is not in use"); final String name = data.getName(); int location = getCachedUniformLocation(name); if (0 <= location) { data.setLocation(location); } else { if (!shaderProgram.linked()) throw new GLException("Program is not linked"); location = data.setLocation(gl, shaderProgram.program()); if (0 <= location) { Integer idx = new Integer(location); activeUniformLocationMap.put(name, idx); } else if (verbose) { System.err.println( "ShaderState: glUniform failed, no location for: " + name + ", index: " + location); if (DEBUG) { Thread.dumpStack(); } } } activeUniformDataMap.put(name, data); return location; }
/** * Set the uniform data. * * <p>Even if the uniform is not found in the current shader, it is stored in this state. * * @param data the GLUniforms's name must match the uniform one, it's index will be set with the * uniforms's location, if found. * @return false, if the name is not found, otherwise true * @throws GLException if the program is not in use * @see #glGetUniformLocation * @see javax.media.opengl.GL2ES2#glGetUniformLocation * @see javax.media.opengl.GL2ES2#glUniform * @see #getUniformLocation * @see ShaderProgram#glReplaceShader */ public boolean uniform(GL2ES2 gl, GLUniformData data) { if (!shaderProgram.inUse()) throw new GLException("Program is not in use"); int location = data.getLocation(); if (0 > location) { location = getUniformLocation(gl, data); } if (0 <= location) { // only pass the data, if the uniform exists in the current shader if (DEBUG) { System.err.println("ShaderState: glUniform: " + data); } gl.glUniform(data); } return true; }
protected void runOneSet( GLAutoDrawable drawable, String textBaseName, int numObjs, int numTextures, int loops) { GL2ES2 gl = drawable.getGL().getGL2ES2(); if (numTextures > MAX_TEXTURE_ENGINES) { throw new GLException("numTextures must be within 1.." + MAX_TEXTURE_ENGINES); } String textName = null; textDatas = new TextureData[numObjs]; textures = new Texture[numTextures]; try { for (int i = 0; i < numObjs; i++) { textName = "data/" + textBaseName + "." + (i + 1) + ".tga"; URL urlText = IOUtil.getResource(Perftst.class, textName); if (urlText == null) { throw new RuntimeException("couldn't fetch " + textName); } textDatas[i] = TextureIO.newTextureData(gl.getGLProfile(), urlText.openStream(), false, TextureIO.TGA); System.out.println(textBaseName + ": " + textDatas[i]); } for (int i = 0; i < numTextures; i++) { gl.glActiveTexture(i); textures[i] = new Texture(GL.GL_TEXTURE_2D); } } catch (IOException ioe) { System.err.println("couldn't fetch " + textName); throw new RuntimeException(ioe); } // // Vertices Data setup // st.useProgram(gl, true); GLArrayDataServer vertices = GLArrayDataServer.createGLSL("mgl_Vertex", 2, GL.GL_FLOAT, true, 4, GL.GL_STATIC_DRAW); { FloatBuffer vb = (FloatBuffer) vertices.getBuffer(); vb.put(0f); vb.put(0f); vb.put(1f); vb.put(0f); vb.put(0f); vb.put(1f); vb.put(1f); vb.put(1f); } vertices.seal(gl, true); GLArrayDataServer texCoords = GLArrayDataServer.createGLSL( "mgl_MultiTexCoord0", 2, GL.GL_FLOAT, true, 4, GL.GL_STATIC_DRAW); { FloatBuffer cb = (FloatBuffer) texCoords.getBuffer(); cb.put(0f); cb.put(0f); cb.put(1f); cb.put(0f); cb.put(0f); cb.put(1f); cb.put(1f); cb.put(1f); } texCoords.seal(gl, true); // // texture setup // long[] tU = new long[numObjs + 1]; tU[0] = System.currentTimeMillis(); for (int j = 0; j < numTextures; j++) { gl.glActiveTexture(j); textures[j].updateImage(gl, textDatas[0]); tU[j + 1] = System.currentTimeMillis(); } GLUniformData activeTexture = new GLUniformData("mgl_ActiveTexture", 0); st.uniform(gl, activeTexture); // // run loops // long dtC, dt, dt2, dt3, dtF, dtS, dtT; long[][] tC = new long[loops][numObjs]; long[][] t0 = new long[loops][numObjs]; long[][][] t1 = new long[loops][numObjs][numTextures]; long[][][] t2 = new long[loops][numObjs][numTextures]; long[][][] t3 = new long[loops][numObjs][numTextures]; long[][] tF = new long[loops][numObjs]; long[][] tS = new long[loops][numObjs]; for (int i = 0; i < loops; i++) { for (int j = 0; j < numObjs; j++) { tC[i][j] = System.currentTimeMillis(); gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT); t0[i][j] = System.currentTimeMillis(); for (int k = 0; k < numTextures; k++) { gl.glActiveTexture(GL.GL_TEXTURE0 + k); textures[k].enable(gl); textures[k].bind(gl); activeTexture.setData(k); st.uniform(gl, activeTexture); t1[i][j][k] = System.currentTimeMillis(); textures[k].updateSubImage(gl, textDatas[j], 0, 0, 0); t2[i][j][k] = System.currentTimeMillis(); gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, vertices.getElementCount()); t3[i][j][k] = System.currentTimeMillis(); } gl.glFinish(); tF[i][j] = System.currentTimeMillis(); drawable.swapBuffers(); tS[i][j] = System.currentTimeMillis(); /*try { Thread.sleep(100); } catch (Exception e) {} */ } } int textBytes = 0; for (int j = 0; j < numObjs; j++) { textBytes += textDatas[j].getEstimatedMemorySize(); } textBytes *= numTextures; dt = 0; for (int i = 1; i < loops; i++) { for (int j = 0; j < numObjs; j++) { dt += tS[i][j] - tC[i][j]; } } System.out.println(""); System.out.println( "Texture " + textBaseName + ", loops " + loops + ", textures " + numTextures + ", objects " + numObjs + ", total bytes " + textBytes + ", total time: " + dt + "ms, fps(-1): " + (((loops - 1) * numObjs * 1000) / dt) + ",\n text kB/s: " + (((double) (loops * textBytes) / 1024.0) / ((double) dt / 1000.0))); for (int i = 0; i < loops; i++) { dtC = 0; dtF = 0; dtS = 0; dtT = 0; for (int j = 0; j < numObjs; j++) { dtC += t0[i][j] - tC[i][j]; dtF += tF[i][j] - t3[i][j][numTextures - 1]; dtS += tS[i][j] - tF[i][j]; dtT += tS[i][j] - tC[i][j]; } if (dtT <= 0) dtT = 1; System.out.println( "\tloop " + i + ": clear " + dtC + "ms, finish " + dtF + ", swap " + dtS + "ms, total: " + dtT + "ms, fps " + (numObjs * 1000) / dtT); /* for(int j=0; j<dummyUni.length; j++) { dt = t1[i][j] - t0[i]; dt2= t2[i][j] - t1[i][j]; dt3= t3[i][j] - t2[i][j]; dtT= dt+dt2+dt3; System.out.println("\t\tobj "+j+": setup "+dt +"ms, update "+dt2 +"ms, draw "+dt3+"ms, total: "+ dtT); } */ } System.out.println("*****************************************************************"); st.useProgram(gl, false); for (int i = 0; i < numTextures; i++) { textures[i].disable(gl); textures[i].destroy(gl); textures[i] = null; } for (int i = 0; i < numObjs; i++) { textDatas[i] = null; } textures = null; textDatas = null; System.gc(); try { Thread.sleep(100); } catch (Exception e) { } System.gc(); }