From 3a0e1f50ac44df49a8a69cf92deaaf2d1314862d Mon Sep 17 00:00:00 2001 From: "rem..om" Date: Thu, 12 Apr 2012 20:08:38 +0000 Subject: [PATCH] Shaders : The line number is now printed for each line of shader code in the standard error output when a shader fail to compile. git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9294 75d07b2b-3a1a-0410-a2c5-0572b91ccdca --- .../renderer/android/OGLESShaderRenderer.java | 5 +- .../jme3/renderer/lwjgl/LwjglRenderer.java | 144 +++++++++--------- .../tools/jme3tools/shader/ShaderDebug.java | 63 ++++++++ 3 files changed, 140 insertions(+), 72 deletions(-) create mode 100644 engine/src/tools/jme3tools/shader/ShaderDebug.java diff --git a/engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java b/engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java index 7e7af29c7..264e23aba 100644 --- a/engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java +++ b/engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java @@ -63,6 +63,7 @@ import java.util.EnumSet; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; +import jme3tools.shader.ShaderDebug; public class OGLESShaderRenderer implements Renderer { @@ -1049,8 +1050,8 @@ public class OGLESShaderRenderer implements Renderer { logger.log(Level.FINE, "compile success: " + source.getName()); } } else { - logger.log(Level.WARNING, "Bad compile of:\n{0}{1}", - new Object[]{source.getDefines(), source.getSource()}); + logger.log(Level.WARNING, "Bad compile of:\n{0}", + new Object[]{ShaderDebug.formatShaderSource(source.getDefines(), source.getSource())}); if (infoLog != null) { throw new RendererException("compile error in:" + source + " error:" + infoLog); } else { diff --git a/engine/src/lwjgl/com/jme3/renderer/lwjgl/LwjglRenderer.java b/engine/src/lwjgl/com/jme3/renderer/lwjgl/LwjglRenderer.java index 2c8707fce..e088cc2d8 100644 --- a/engine/src/lwjgl/com/jme3/renderer/lwjgl/LwjglRenderer.java +++ b/engine/src/lwjgl/com/jme3/renderer/lwjgl/LwjglRenderer.java @@ -65,6 +65,7 @@ import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import jme3tools.converters.MipMapGenerator; +import jme3tools.shader.ShaderDebug; import static org.lwjgl.opengl.ARBTextureMultisample.*; import static org.lwjgl.opengl.EXTFramebufferBlit.*; import static org.lwjgl.opengl.EXTFramebufferMultisample.*; @@ -505,8 +506,8 @@ public class LwjglRenderer implements Renderer { if (state.isPointSprite() && !context.pointSprite) { // Only enable/disable sprite - if (context.boundTextures[0] != null){ - if (context.boundTextureUnit != 0){ + if (context.boundTextures[0] != null) { + if (context.boundTextureUnit != 0) { glActiveTexture(GL_TEXTURE0); context.boundTextureUnit = 0; } @@ -515,8 +516,8 @@ public class LwjglRenderer implements Renderer { } context.pointSprite = true; } else if (!state.isPointSprite() && context.pointSprite) { - if (context.boundTextures[0] != null){ - if (context.boundTextureUnit != 0){ + if (context.boundTextures[0] != null) { + if (context.boundTextureUnit != 0) { glActiveTexture(GL_TEXTURE0); context.boundTextureUnit = 0; } @@ -771,7 +772,7 @@ public class LwjglRenderer implements Renderer { } } - protected void bindProgram(Shader shader){ + protected void bindProgram(Shader shader) { int shaderId = shader.getId(); if (context.boundShaderProgram != shaderId) { glUseProgram(shaderId); @@ -782,7 +783,7 @@ public class LwjglRenderer implements Renderer { statistics.onShaderUse(shader, false); } } - + protected void updateUniform(Shader shader, Uniform uniform) { int shaderId = shader.getId(); @@ -933,7 +934,7 @@ public class LwjglRenderer implements Renderer { } source.setId(id); - }else{ + } else { throw new RendererException("Cannot recompile shader source"); } @@ -995,9 +996,9 @@ public class LwjglRenderer implements Renderer { } else { logger.log(Level.FINE, "{0} compile success", source.getName()); } - } else { - logger.log(Level.WARNING, "Bad compile of:\n{0}{1}", - new Object[]{source.getDefines(), source.getSource()}); + } else { + logger.log(Level.WARNING, "Bad compile of:\n{0}", + new Object[]{ShaderDebug.formatShaderSource(source.getDefines(), source.getSource())}); if (infoLog != null) { throw new RendererException("compile error in:" + source + " error:" + infoLog); } else { @@ -1231,39 +1232,42 @@ public class LwjglRenderer implements Renderer { // TODO: support non-blit copies? } } - - private String getTargetBufferName(int buffer){ - switch (buffer){ - case GL_NONE: return "NONE"; - case GL_FRONT: return "GL_FRONT"; - case GL_BACK: return "GL_BACK"; + + private String getTargetBufferName(int buffer) { + switch (buffer) { + case GL_NONE: + return "NONE"; + case GL_FRONT: + return "GL_FRONT"; + case GL_BACK: + return "GL_BACK"; default: - if ( buffer >= GL_COLOR_ATTACHMENT0_EXT - && buffer <= GL_COLOR_ATTACHMENT15_EXT){ - return "GL_COLOR_ATTACHMENT" + - (buffer - GL_COLOR_ATTACHMENT0_EXT); - }else{ + if (buffer >= GL_COLOR_ATTACHMENT0_EXT + && buffer <= GL_COLOR_ATTACHMENT15_EXT) { + return "GL_COLOR_ATTACHMENT" + + (buffer - GL_COLOR_ATTACHMENT0_EXT); + } else { return "UNKNOWN? " + buffer; } } } - private void printRealRenderBufferInfo(FrameBuffer fb, RenderBuffer rb, String name){ + private void printRealRenderBufferInfo(FrameBuffer fb, RenderBuffer rb, String name) { System.out.println("== Renderbuffer " + name + " =="); System.out.println("RB ID: " + rb.getId()); System.out.println("Is proper? " + glIsRenderbufferEXT(rb.getId())); - + int attachment = convertAttachmentSlot(rb.getSlot()); - + int type = glGetFramebufferAttachmentParameterEXT(GL_DRAW_FRAMEBUFFER_EXT, - attachment, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT); - + attachment, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT); + int rbName = glGetFramebufferAttachmentParameterEXT(GL_DRAW_FRAMEBUFFER_EXT, - attachment, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT); - - switch (type){ + attachment, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT); + + switch (type) { case GL_NONE: System.out.println("Type: None"); return; // note: return from method as other queries will be invalid @@ -1275,20 +1279,20 @@ public class LwjglRenderer implements Renderer { System.out.println("RB ID: " + rbName); break; } - - - + + + } - + private void printRealFrameBufferInfo(FrameBuffer fb) { boolean doubleBuffer = glGetBoolean(GL_DOUBLEBUFFER); String drawBuf = getTargetBufferName(glGetInteger(GL_DRAW_BUFFER)); String readBuf = getTargetBufferName(glGetInteger(GL_READ_BUFFER)); - + int fbId = fb.getId(); int curDrawBinding = glGetInteger(ARBFramebufferObject.GL_DRAW_FRAMEBUFFER_BINDING); int curReadBinding = glGetInteger(ARBFramebufferObject.GL_READ_FRAMEBUFFER_BINDING); - + System.out.println("=== OpenGL FBO State ==="); System.out.println("Context doublebuffered? " + doubleBuffer); System.out.println("FBO ID: " + fbId); @@ -1297,20 +1301,20 @@ public class LwjglRenderer implements Renderer { System.out.println("Is bound to read? " + (fbId == curReadBinding)); System.out.println("Draw buffer: " + drawBuf); System.out.println("Read buffer: " + readBuf); - - if (context.boundFBO != fbId){ + + if (context.boundFBO != fbId) { glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fbId); context.boundFBO = fbId; } - - if (fb.getDepthBuffer() != null){ + + if (fb.getDepthBuffer() != null) { printRealRenderBufferInfo(fb, fb.getDepthBuffer(), "Depth"); } - for (int i = 0; i < fb.getNumColorBuffers(); i++){ + for (int i = 0; i < fb.getNumColorBuffers(); i++) { printRealRenderBufferInfo(fb, fb.getColorBuffer(i), "Color" + i); } } - + private void checkFrameBufferError() { int status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); switch (status) { @@ -1477,18 +1481,18 @@ public class LwjglRenderer implements Renderer { } return samplePositions; } - - public void setMainFrameBufferOverride(FrameBuffer fb){ + + public void setMainFrameBufferOverride(FrameBuffer fb) { mainFbOverride = fb; } public void setFrameBuffer(FrameBuffer fb) { - if (fb == null && mainFbOverride != null){ + if (fb == null && mainFbOverride != null) { fb = mainFbOverride; } - + if (lastFb == fb) { - if (fb == null || !fb.isUpdateNeeded()){ + if (fb == null || !fb.isUpdateNeeded()) { return; } } @@ -1530,11 +1534,11 @@ public class LwjglRenderer implements Renderer { lastFb = null; } else { - if (fb.getNumColorBuffers() == 0 && fb.getDepthBuffer() == null){ - throw new IllegalArgumentException("The framebuffer: " + fb + - "\nDoesn't have any color/depth buffers"); + if (fb.getNumColorBuffers() == 0 && fb.getDepthBuffer() == null) { + throw new IllegalArgumentException("The framebuffer: " + fb + + "\nDoesn't have any color/depth buffers"); } - + if (fb.isUpdateNeeded()) { updateFrameBuffer(fb); } @@ -1591,9 +1595,9 @@ public class LwjglRenderer implements Renderer { assert fb.getId() >= 0; assert context.boundFBO == fb.getId(); - + lastFb = fb; - + try { checkFrameBufferError(); } catch (IllegalStateException ex) { @@ -1998,7 +2002,7 @@ public class LwjglRenderer implements Renderer { objManager.registerForCleanup(vb); //statistics.onNewVertexBuffer(); - + created = true; } @@ -2010,7 +2014,7 @@ public class LwjglRenderer implements Renderer { glBindBuffer(target, bufId); context.boundElementArrayVBO = bufId; //statistics.onVertexBufferUse(vb, true); - }else{ + } else { //statistics.onVertexBufferUse(vb, false); } } else { @@ -2019,7 +2023,7 @@ public class LwjglRenderer implements Renderer { glBindBuffer(target, bufId); context.boundArrayVBO = bufId; //statistics.onVertexBufferUse(vb, true); - }else{ + } else { //statistics.onVertexBufferUse(vb, false); } } @@ -2128,7 +2132,7 @@ public class LwjglRenderer implements Renderer { intBuf1.position(0).limit(1); glDeleteBuffers(intBuf1); vb.resetObject(); - + //statistics.onDeleteVertexBuffer(); } } @@ -2170,11 +2174,11 @@ public class LwjglRenderer implements Renderer { attrib.setLocation(loc); } } - + if (vb.isUpdateNeeded() && idb == null) { updateBufferData(vb); } - + VertexBuffer[] attribs = context.boundAttribs; if (!context.attribIndexList.moveToNew(loc)) { glEnableVertexAttribArray(loc); @@ -2188,7 +2192,7 @@ public class LwjglRenderer implements Renderer { glBindBuffer(GL_ARRAY_BUFFER, bufId); context.boundArrayVBO = bufId; //statistics.onVertexBufferUse(vb, true); - }else{ + } else { //statistics.onVertexBufferUse(vb, false); } @@ -2235,7 +2239,7 @@ public class LwjglRenderer implements Renderer { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufId); context.boundElementArrayVBO = bufId; //statistics.onVertexBufferUse(indexBuf, true); - }else{ + } else { //statistics.onVertexBufferUse(indexBuf, true); } @@ -2360,9 +2364,9 @@ public class LwjglRenderer implements Renderer { } private void renderMeshVertexArray(Mesh mesh, int lod, int count) { - if (mesh.getId() == -1){ + if (mesh.getId() == -1) { updateVertexArray(mesh); - }else{ + } else { // TODO: Check if it was updated } @@ -2403,10 +2407,10 @@ public class LwjglRenderer implements Renderer { } else { indices = mesh.getBuffer(Type.Index); } - + // for (Entry entry : buffers) { // VertexBuffer vb = entry.getValue(); - for (VertexBuffer vb : mesh.getBufferList().getArray()){ + for (VertexBuffer vb : mesh.getBufferList().getArray()) { if (vb.getBufferType() == Type.InterleavedData || vb.getUsage() == Usage.CpuOnly // ignore cpu-only buffers || vb.getBufferType() == Type.Index) { @@ -2436,10 +2440,10 @@ public class LwjglRenderer implements Renderer { return; } - if (context.pointSprite && mesh.getMode() != Mode.Points){ + if (context.pointSprite && mesh.getMode() != Mode.Points) { // XXX: Hack, disable point sprite mode if mesh not in point mode - if (context.boundTextures[0] != null){ - if (context.boundTextureUnit != 0){ + if (context.boundTextures[0] != null) { + if (context.boundTextureUnit != 0) { glActiveTexture(GL_TEXTURE0); context.boundTextureUnit = 0; } @@ -2462,7 +2466,7 @@ public class LwjglRenderer implements Renderer { // if (GLContext.getCapabilities().GL_ARB_vertex_array_object){ // renderMeshVertexArray(mesh, lod, count); // }else{ - renderMeshDefault(mesh, lod, count); + renderMeshDefault(mesh, lod, count); // } } } diff --git a/engine/src/tools/jme3tools/shader/ShaderDebug.java b/engine/src/tools/jme3tools/shader/ShaderDebug.java new file mode 100644 index 000000000..5421accff --- /dev/null +++ b/engine/src/tools/jme3tools/shader/ShaderDebug.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2009-2010 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package jme3tools.shader; + +/** + * Static tool box class for convenient methods to help debug shaders + * @author Nehon + */ +public class ShaderDebug { + + /** + * Append the line numbers to the source code of a shader to output it + * @param defines the defines + * @param source the source + * @return the formated source code + */ + public static String formatShaderSource(String defines, String source) { + String[] lines = defines.split("\n"); + String[] lines2 = source.split("\n"); + int nblines = 0; + StringBuilder out = new StringBuilder(); + if (!defines.equals("")) { + for (String string : lines) { + nblines++; + out.append(nblines).append("\t").append(string).append("\n"); + } + } + for (String string : lines2) { + nblines++; + out.append(nblines).append("\t").append(string).append("\n"); + } + return out.toString(); + } +}