Browse Source

ShaderNodes : generated shaders are now cached by the assetManager to avoid generating a new shader for already loaded materials. This saves memory and avoids a lot of shader switches at render time.

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10575 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
rem..om 12 years ago
parent
commit
4f3319f049

+ 2 - 0
engine/src/core-plugins/com/jme3/material/plugins/J3MLoader.java

@@ -448,6 +448,8 @@ public class J3MLoader implements AssetLoader {
         
         if(isUseNodes){
             nodesLoaderDelegate.computeConditions();
+            //used for caching later, the shader here is not a file.
+            technique.setShaderFile(technique.hashCode() + "", technique.hashCode() + "", "GLSL100", "GLSL100");
         }
 
         if (vertName != null && fragName != null){

+ 17 - 10
engine/src/core/com/jme3/asset/DesktopAssetManager.java

@@ -398,16 +398,23 @@ public class DesktopAssetManager implements AssetManager {
         AssetCache cache = handler.getCache(SimpleAssetCache.class);
         Shader shader = (Shader) cache.getFromCache(key);
         if (shader == null){
-            String vertName = key.getVertName();
-            String fragName = key.getFragName();
-
-            String vertSource = (String) loadAsset(new AssetKey(vertName));
-            String fragSource = (String) loadAsset(new AssetKey(fragName));
-
-            shader = new Shader();
-            shader.initialize();
-            shader.addSource(Shader.ShaderType.Vertex,   vertName, vertSource, key.getDefines().getCompiled(), key.getVertexShaderLanguage());
-            shader.addSource(Shader.ShaderType.Fragment, fragName, fragSource, key.getDefines().getCompiled(), key.getFragmentShaderLanguage());
+            if (key.isUsesShaderNodes()) {
+                if(shaderGenerator == null){
+                    throw new UnsupportedOperationException("ShaderGenerator was not initialized, make sure assetManager.getGenerator(caps) has been called");
+                }
+                shader = shaderGenerator.generateShader();
+            } else {
+                String vertName = key.getVertName();
+                String fragName = key.getFragName();
+
+                String vertSource = (String) loadAsset(new AssetKey(vertName));
+                String fragSource = (String) loadAsset(new AssetKey(fragName));
+
+                shader = new Shader();
+                shader.initialize();
+                shader.addSource(Shader.ShaderType.Vertex, vertName, vertSource, key.getDefines().getCompiled(), key.getVertexShaderLanguage());
+                shader.addSource(Shader.ShaderType.Fragment, fragName, fragSource, key.getDefines().getCompiled(), key.getFragmentShaderLanguage());
+            }
 
             cache.addToCache(key, shader);
         }

+ 7 - 6
engine/src/core/com/jme3/material/Technique.java

@@ -204,17 +204,18 @@ public class Technique /* implements Savable */ {
 
     private void loadShader(AssetManager manager,EnumSet<Caps> rendererCaps) {
         
-        if (getDef().isUsingShaderNodes()) {
-            shader = manager.getShaderGenerator(rendererCaps).generateShader(this);
-        } else {
-            ShaderKey key = new ShaderKey(def.getVertexShaderName(),
+        ShaderKey key = new ShaderKey(def.getVertexShaderName(),
                     def.getFragmentShaderName(),
                     getAllDefines(),
                     def.getVertexShaderLanguage(),
                     def.getFragmentShaderLanguage());
-            shader = manager.loadShader(key);
         
-        }
+        if (getDef().isUsingShaderNodes()) {                 
+           manager.getShaderGenerator(rendererCaps).initialize(this);           
+           key.setUsesShaderNodes(true);
+        }   
+        shader = manager.loadShader(key);
+
         // register the world bound uniforms
         worldBindUniforms.clear();
         if (def.getWorldBindings() != null) {

+ 15 - 5
engine/src/core/com/jme3/shader/ShaderGenerator.java

@@ -52,6 +52,8 @@ public abstract class ShaderGenerator {
     protected AssetManager assetManager;
     //indentation value for generation
     protected int indent;
+    //the technique to use for the shader generation
+    protected Technique technique = null;    
 
     /**
      * Build a shaderGenerator
@@ -59,16 +61,23 @@ public abstract class ShaderGenerator {
      * @param assetManager
      */
     protected ShaderGenerator(AssetManager assetManager) {
-        this.assetManager = assetManager;
+        this.assetManager = assetManager;        
     }
-
+    
+    public void initialize(Technique technique){
+        this.technique = technique;
+    }
+    
     /**
      * Generate vertex and fragment shaders for the given technique
      *
      * @param technique the technique to use to generate the shaders
      * @return a Shader program
      */
-    public Shader generateShader(Technique technique) {
+    public Shader generateShader() {
+        if(technique == null){
+            throw new UnsupportedOperationException("The shaderGenerator was not properly initialized, call initialize(Technique) before any generation");
+        }
 
         DefineList defines = technique.getAllDefines();
         TechniqueDef def = technique.getDef();
@@ -81,7 +90,8 @@ public abstract class ShaderGenerator {
         shader.initialize();
         shader.addSource(Shader.ShaderType.Vertex, technique.getDef().getName() + ".vert", vertexSource, defines.getCompiled(), getLanguageAndVersion(ShaderType.Vertex));
         shader.addSource(Shader.ShaderType.Fragment, technique.getDef().getName() + ".frag", fragmentSource, defines.getCompiled(), getLanguageAndVersion(ShaderType.Fragment));
-
+        
+        technique = null;
         return shader;
     }
 
@@ -286,5 +296,5 @@ public abstract class ShaderGenerator {
             }
         }
         return index;
-    }
+    }    
 }

+ 10 - 1
engine/src/core/com/jme3/shader/ShaderKey.java

@@ -45,6 +45,7 @@ public class ShaderKey extends AssetKey<Shader> {
     protected String vertLanguage;
     protected String fragLanguage;
     protected int cachedHashedCode = 0;
+    protected boolean usesShaderNodes = false;
 
     public ShaderKey(){
     }
@@ -56,7 +57,7 @@ public class ShaderKey extends AssetKey<Shader> {
         this.vertLanguage = vertLanguage;
         this.fragLanguage = fragLanguage;
     }
-
+    
     @Override
     public ShaderKey clone() {
         ShaderKey clone = (ShaderKey) super.clone();
@@ -125,6 +126,14 @@ public class ShaderKey extends AssetKey<Shader> {
         return fragLanguage;
     }
 
+    public boolean isUsesShaderNodes() {
+        return usesShaderNodes;
+    }
+
+    public void setUsesShaderNodes(boolean usesShaderNodes) {
+        this.usesShaderNodes = usesShaderNodes;
+    }
+
     @Override
     public void write(JmeExporter ex) throws IOException{
         super.write(ex);