diff --git a/jme3-android/src/main/java/com/jme3/renderer/android/AndroidGL.java b/jme3-android/src/main/java/com/jme3/renderer/android/AndroidGL.java index 12e743810..3541eaa63 100644 --- a/jme3-android/src/main/java/com/jme3/renderer/android/AndroidGL.java +++ b/jme3-android/src/main/java/com/jme3/renderer/android/AndroidGL.java @@ -31,11 +31,10 @@ */ package com.jme3.renderer.android; -import android.opengl.GLES20; +import android.opengl.*; import com.jme3.renderer.RendererException; -import com.jme3.renderer.opengl.GL; -import com.jme3.renderer.opengl.GLExt; -import com.jme3.renderer.opengl.GLFbo; +import com.jme3.renderer.opengl.*; + import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.FloatBuffer; @@ -92,6 +91,11 @@ public class AndroidGL implements GL, GLExt, GLFbo { GLES20.glAttachShader(program, shader); } + @Override + public void glBeginQuery(int target, int query) { + GLES30.glBeginQuery(target, query); + } + public void glBindBuffer(int target, int buffer) { GLES20.glBindBuffer(target, buffer); } @@ -234,6 +238,11 @@ public class AndroidGL implements GL, GLExt, GLFbo { GLES20.glEnableVertexAttribArray(index); } + @Override + public void glEndQuery(int target) { + GLES30.glEndQuery(target); + } + public void glGenBuffers(IntBuffer buffers) { checkLimit(buffers); GLES20.glGenBuffers(buffers.limit(), buffers); @@ -244,6 +253,11 @@ public class AndroidGL implements GL, GLExt, GLFbo { GLES20.glGenTextures(textures.limit(), textures); } + @Override + public void glGenQueries(int num, IntBuffer buff) { + GLES30.glGenQueries(num, buff); + } + public int glGetAttribLocation(int program, String name) { return GLES20.glGetAttribLocation(program, name); } @@ -271,6 +285,21 @@ public class AndroidGL implements GL, GLExt, GLFbo { return GLES20.glGetProgramInfoLog(program); } + @Override + public long glGetQueryObjectui64(int query, int pname) { + IntBuffer buff = IntBuffer.allocate(1); + //FIXME This is wrong IMO should be glGetQueryObjectui64v with a LongBuffer but it seems the API doesn't provide it. + GLES30.glGetQueryObjectuiv(query, pname, buff); + return buff.get(0); + } + + @Override + public int glGetQueryObjectiv(int query, int pname) { + IntBuffer buff = IntBuffer.allocate(1); + GLES30.glGetQueryiv(query, pname, buff); + return buff.get(0); + } + public void glGetShader(int shader, int pname, IntBuffer params) { checkLimit(params); GLES20.glGetShaderiv(shader, pname, params); diff --git a/jme3-core/src/main/java/com/jme3/renderer/Renderer.java b/jme3-core/src/main/java/com/jme3/renderer/Renderer.java index d6645d24d..9a4e5bcc2 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/Renderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/Renderer.java @@ -387,4 +387,46 @@ public interface Renderer { */ public void setLinearizeSrgbImages(boolean linearize); + + /** + * Generates a pool of gpu queries meant to use as profiling tasks + * + * @param numTasks the number of task ids to generate + * @return an array of tasks ids. + */ + public int[] generateProfilingTasks(int numTasks); + + /** + * Starts a time profiling task on the GPU. + * This will profile all operations called between startProfiling and stopProfiling + * + * @param taskId the id of the task to start profiling. + */ + public void startProfiling(int taskId); + + /** + * Will stop the last profiling task started with startProfiling + */ + public void stopProfiling(); + + /** + * Returns the time in nano seconds elapsed for the task with the given id. + * Note that the result may not be available right after stopProfiling has been called. + * You need to check if the result is available with isTaskResultAvailable. + * Also note that it's guaranteed that the result will be available on next frame. + * If you use getProfilingTime on the next frame you called stopProfiling, you don't need to check the result availability with isTaskResultAvailable + * + * @param taskId the id of the task given by startProfiling. + * @return the time in nano second of the profiling task with the given id. + */ + public long getProfilingTime(int taskId); + + /** + * Check if the profiling results are available + * + * @param taskId the id of the task provided by startProfiling + * @return true if the resulst of the task with the given task id are available. + */ + public boolean isTaskResultAvailable(int taskId); + } diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java index 136442f77..5aa2cdb83 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java @@ -126,6 +126,8 @@ public interface GL { public static final int GL_OUT_OF_MEMORY = 0x505; public static final int GL_POINTS = 0x0; public static final int GL_POLYGON_OFFSET_FILL = 0x8037; + public static final int GL_QUERY_RESULT = 0x8866; + public static final int GL_QUERY_RESULT_AVAILABLE = 0x8867; public static final int GL_RED = 0x1903; public static final int GL_RENDERER = 0x1F01; public static final int GL_REPEAT = 0x2901; @@ -177,6 +179,7 @@ public interface GL { public static final int GL_TEXTURE_MIN_FILTER = 0x2801; public static final int GL_TEXTURE_WRAP_S = 0x2802; public static final int GL_TEXTURE_WRAP_T = 0x2803; + public static final int GL_TIME_ELAPSED = 0x88BF; public static final int GL_TRIANGLES = 0x4; public static final int GL_TRIANGLE_FAN = 0x6; public static final int GL_TRIANGLE_STRIP = 0x5; @@ -196,6 +199,7 @@ public interface GL { public void glActiveTexture(int texture); public void glAttachShader(int program, int shader); + public void glBeginQuery(int target, int query); public void glBindBuffer(int target, int buffer); public void glBindTexture(int target, int texture); public void glBlendEquationSeparate(int colorMode, int alphaMode); @@ -232,8 +236,10 @@ public interface GL { public void glDrawRangeElements(int mode, int start, int end, int count, int type, long indices); /// GL2+ public void glEnable(int cap); public void glEnableVertexAttribArray(int index); + public void glEndQuery(int target); public void glGenBuffers(IntBuffer buffers); public void glGenTextures(IntBuffer textures); + public void glGenQueries(int number, IntBuffer ids); public int glGetAttribLocation(int program, String name); public void glGetBoolean(int pname, ByteBuffer params); public void glGetBufferSubData(int target, long offset, ByteBuffer data); @@ -241,7 +247,9 @@ public interface GL { public void glGetInteger(int pname, IntBuffer params); public void glGetProgram(int program, int pname, IntBuffer params); public String glGetProgramInfoLog(int program, int maxSize); - public void glGetShader(int shader, int pname, IntBuffer params); + public long glGetQueryObjectui64(int query, int pname); + public int glGetQueryObjectiv(int query, int pname); + public void glGetShader(int shader, int pname, IntBuffer params); public String glGetShaderInfoLog(int shader, int maxSize); public String glGetString(int name); public int glGetUniformLocation(int program, String name); diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugES.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugES.java index 6b15bb967..412d738f5 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugES.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugES.java @@ -30,6 +30,12 @@ public class GLDebugES extends GLDebug implements GL, GLFbo, GLExt { checkError(); } + @Override + public void glBeginQuery(int target, int query) { + gl.glBeginQuery(target, query); + checkError(); + } + public void glBindBuffer(int target, int buffer) { gl.glBindBuffer(target, buffer); checkError(); @@ -198,6 +204,11 @@ public class GLDebugES extends GLDebug implements GL, GLFbo, GLExt { checkError(); } + @Override + public void glEndQuery(int target) { + checkError(); + } + public void glGenBuffers(IntBuffer buffers) { gl.glGenBuffers(buffers); checkError(); @@ -208,6 +219,12 @@ public class GLDebugES extends GLDebug implements GL, GLFbo, GLExt { checkError(); } + @Override + public void glGenQueries(int num, IntBuffer ids) { + glGenQueries(num, ids); + checkError(); + } + public int glGetAttribLocation(int program, String name) { int location = gl.glGetAttribLocation(program, name); checkError(); @@ -240,6 +257,20 @@ public class GLDebugES extends GLDebug implements GL, GLFbo, GLExt { return infoLog; } + @Override + public long glGetQueryObjectui64(int query, int pname) { + long res = gl.glGetQueryObjectui64(query, pname); + checkError(); + return res; + } + + @Override + public int glGetQueryObjectiv(int query, int pname) { + int res = gl.glGetQueryObjectiv(query, pname); + checkError(); + return res; + } + public void glGetShader(int shader, int pname, IntBuffer params) { gl.glGetShader(shader, pname, params); checkError(); diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java index 943d3ab40..2eedf2c50 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java @@ -2851,4 +2851,31 @@ public final class GLRenderer implements Renderer { linearizeSrgbImages = linearize; } } + + @Override + public int[] generateProfilingTasks(int numTasks) { + IntBuffer ids = BufferUtils.createIntBuffer(numTasks); + gl.glGenQueries(numTasks, ids); + return BufferUtils.getIntArray(ids); + } + + @Override + public void startProfiling(int taskId) { + gl.glBeginQuery(GL.GL_TIME_ELAPSED, taskId); + } + + @Override + public void stopProfiling() { + gl.glEndQuery(GL.GL_TIME_ELAPSED); + } + + @Override + public long getProfilingTime(int taskId) { + return gl.glGetQueryObjectui64(taskId, GL.GL_QUERY_RESULT); + } + + @Override + public boolean isTaskResultAvailable(int taskId) { + return gl.glGetQueryObjectiv(taskId, GL.GL_QUERY_RESULT_AVAILABLE) == 1; + } } diff --git a/jme3-core/src/main/java/com/jme3/system/NullRenderer.java b/jme3-core/src/main/java/com/jme3/system/NullRenderer.java index 293c5e2c7..1eb2b1533 100644 --- a/jme3-core/src/main/java/com/jme3/system/NullRenderer.java +++ b/jme3-core/src/main/java/com/jme3/system/NullRenderer.java @@ -172,6 +172,31 @@ public class NullRenderer implements Renderer { public void setLinearizeSrgbImages(boolean linearize) { } + @Override + public int[] generateProfilingTasks(int numTasks) { + return new int[0]; + } + + @Override + public void startProfiling(int id) { + + } + + @Override + public void stopProfiling() { + + } + + @Override + public long getProfilingTime(int taskId) { + return 0; + } + + @Override + public boolean isTaskResultAvailable(int taskId) { + return false; + } + public void readFrameBufferWithFormat(FrameBuffer fb, ByteBuffer byteBuf, Image.Format format) { } diff --git a/jme3-ios/src/main/java/com/jme3/renderer/ios/IosGL.java b/jme3-ios/src/main/java/com/jme3/renderer/ios/IosGL.java index d73c5158a..95e8a213b 100644 --- a/jme3-ios/src/main/java/com/jme3/renderer/ios/IosGL.java +++ b/jme3-ios/src/main/java/com/jme3/renderer/ios/IosGL.java @@ -124,6 +124,11 @@ public class IosGL implements GL, GLExt, GLFbo { JmeIosGLES.glAttachShader(program, shader); } + @Override + public void glBeginQuery(int target, int query) { + throw new UnsupportedOperationException("Today is not a good day for this"); + } + public void glBindBuffer(int target, int buffer) { JmeIosGLES.glBindBuffer(target, buffer); } @@ -269,6 +274,11 @@ public class IosGL implements GL, GLExt, GLFbo { JmeIosGLES.glEnableVertexAttribArray(index); } + @Override + public void glEndQuery(int target) { + throw new UnsupportedOperationException("Today is not a good day for this"); + } + public void glGenBuffers(IntBuffer buffers) { checkLimit(buffers); JmeIosGLES.glGenBuffers(buffers.remaining(), temp_array, 0); @@ -281,6 +291,11 @@ public class IosGL implements GL, GLExt, GLFbo { fromArray(textures.remaining(), temp_array, textures); } + @Override + public void glGenQueries(int num, IntBuffer buff) { + throw new UnsupportedOperationException("Today is not a good day for this"); + } + public int glGetAttribLocation(int program, String name) { return JmeIosGLES.glGetAttribLocation(program, name); } @@ -311,6 +326,16 @@ public class IosGL implements GL, GLExt, GLFbo { return JmeIosGLES.glGetProgramInfoLog(program); } + @Override + public long glGetQueryObjectui64(int query, int pname) { + throw new UnsupportedOperationException("Today is not a good day for this"); + } + + @Override + public int glGetQueryObjectiv(int query, int pname) { + throw new UnsupportedOperationException("Today is not a good day for this"); + } + public void glGetShader(int shader, int pname, IntBuffer params) { checkLimit(params); JmeIosGLES.glGetShaderiv(shader, pname, temp_array, 0); diff --git a/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGL.java b/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGL.java index bbd1b24f9..e927b4bb7 100644 --- a/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGL.java +++ b/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGL.java @@ -5,12 +5,7 @@ import com.jme3.renderer.opengl.GL; import com.jme3.renderer.opengl.GL2; import com.jme3.renderer.opengl.GL3; -import java.nio.Buffer; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.FloatBuffer; -import java.nio.IntBuffer; -import java.nio.ShortBuffer; +import java.nio.*; import com.jme3.renderer.opengl.GL4; import com.jogamp.opengl.GLContext; @@ -69,7 +64,12 @@ public class JoglGL implements GL, GL2, GL3, GL4 { } @Override - public void glBindBuffer(int param1, int param2) { + public void glBeginQuery(int target, int query) { + GLContext.getCurrentGL().getGL2ES2().glBeginQuery(target, query); + } + + @Override + public void glBindBuffer(int param1, int param2) { GLContext.getCurrentGL().glBindBuffer(param1, param2); } @@ -271,13 +271,23 @@ public class JoglGL implements GL, GL2, GL3, GL4 { } @Override - public void glGenBuffers(IntBuffer param1) { + public void glEndQuery(int target) { + GLContext.getCurrentGL().getGL2ES2().glEndQuery(target); + } + + @Override + public void glGenBuffers(IntBuffer param1) { checkLimit(param1); GLContext.getCurrentGL().glGenBuffers(param1.limit(), param1); } @Override - public void glGenTextures(IntBuffer param1) { + public void glGenQueries(int num, IntBuffer buff) { + GLContext.getCurrentGL().getGL2ES2().glGenQueries(num, buff); + } + + @Override + public void glGenTextures(IntBuffer param1) { checkLimit(param1); GLContext.getCurrentGL().glGenTextures(param1.limit(), param1); } @@ -569,6 +579,20 @@ public class JoglGL implements GL, GL2, GL3, GL4 { return new String(bytes); } + @Override + public long glGetQueryObjectui64(int query, int target) { + LongBuffer buff = LongBuffer.allocate(1); + GLContext.getCurrentGL().getGL2ES2().glGetQueryObjectui64v(query, target, buff); + return buff.get(0); + } + + @Override + public int glGetQueryObjectiv(int query, int pname) { + IntBuffer buff = IntBuffer.allocate(1); + GLContext.getCurrentGL().getGL2ES2().glGetQueryObjectiv(query, pname, buff); + return buff.get(0); + } + @Override public String glGetShaderInfoLog(int shader, int maxSize) { ByteBuffer buffer = ByteBuffer.allocateDirect(maxSize); diff --git a/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java b/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java index 59e50e3f7..c2694988c 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java +++ b/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java @@ -11,9 +11,12 @@ import java.nio.IntBuffer; import java.nio.ShortBuffer; import com.jme3.renderer.opengl.GL4; +import com.jme3.util.BufferUtils; import org.lwjgl.opengl.*; public final class LwjglGL implements GL, GL2, GL3, GL4 { + + IntBuffer tmpBuff = BufferUtils.createIntBuffer(1); private static void checkLimit(Buffer buffer) { if (buffer == null) { @@ -42,6 +45,11 @@ public final class LwjglGL implements GL, GL2, GL3, GL4 { GL20.glAttachShader(param1, param2); } + @Override + public void glBeginQuery(int target, int query) { + GL15.glBeginQuery(target, query); + } + public void glBindBuffer(int param1, int param2) { GL15.glBindBuffer(param1, param2); } @@ -206,11 +214,21 @@ public final class LwjglGL implements GL, GL2, GL3, GL4 { GL20.glEnableVertexAttribArray(param1); } + @Override + public void glEndQuery(int target) { + GL15.glEndQuery(target); + } + public void glGenBuffers(IntBuffer param1) { checkLimit(param1); GL15.glGenBuffers(param1); } + @Override + public void glGenQueries(int num, IntBuffer ids) { + GL15.glGenQueries(ids); + } + public void glGenTextures(IntBuffer param1) { checkLimit(param1); GL11.glGenTextures(param1); @@ -435,6 +453,16 @@ public final class LwjglGL implements GL, GL2, GL3, GL4 { return GL20.glGetProgramInfoLog(program, maxSize); } + @Override + public long glGetQueryObjectui64(int query, int target) { + return ARBTimerQuery.glGetQueryObjectui64(query, target); + } + + @Override + public int glGetQueryObjectiv(int query, int pname) { + return GL15.glGetQueryObjecti(query, pname); + } + public String glGetShaderInfoLog(int shader, int maxSize) { return GL20.glGetShaderInfoLog(shader, maxSize); } diff --git a/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java b/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java index f5f6a7b1a..a905c9f01 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java @@ -71,6 +71,11 @@ public class LwjglGL implements GL, GL2, GL3, GL4 { GL20.glAttachShader(param1, param2); } + @Override + public void glBeginQuery(int target, int query) { + GL15.glBeginQuery(target, query); + } + public void glBindBuffer(int param1, int param2) { GL15.glBindBuffer(param1, param2); } @@ -235,6 +240,11 @@ public class LwjglGL implements GL, GL2, GL3, GL4 { GL20.glEnableVertexAttribArray(param1); } + @Override + public void glEndQuery(int target) { + GL15.glEndQuery(target); + } + public void glGenBuffers(IntBuffer param1) { checkLimit(param1); GL15.glGenBuffers(param1); @@ -245,6 +255,11 @@ public class LwjglGL implements GL, GL2, GL3, GL4 { GL11.glGenTextures(param1); } + @Override + public void glGenQueries(int num, IntBuffer ids) { + GL15.glGenQueries(ids); + } + public void glGetBoolean(int param1, ByteBuffer param2) { checkLimit(param2); GL11.glGetBooleanv(param1, param2); @@ -464,6 +479,16 @@ public class LwjglGL implements GL, GL2, GL3, GL4 { return GL20.glGetProgramInfoLog(program, maxSize); } + @Override + public long glGetQueryObjectui64(int query, int target) { + return ARBTimerQuery.glGetQueryObjectui64(query, target); + } + + @Override + public int glGetQueryObjectiv(int query, int pname) { + return GL15.glGetQueryObjecti(query, pname); + } + public String glGetShaderInfoLog(int shader, int maxSize) { return GL20.glGetShaderInfoLog(shader, maxSize); }