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
3.0
rem..om 12 years ago
parent 77a3cba69e
commit 4f3319f049
  1. 2
      engine/src/core-plugins/com/jme3/material/plugins/J3MLoader.java
  2. 7
      engine/src/core/com/jme3/asset/DesktopAssetManager.java
  3. 9
      engine/src/core/com/jme3/material/Technique.java
  4. 12
      engine/src/core/com/jme3/shader/ShaderGenerator.java
  5. 9
      engine/src/core/com/jme3/shader/ShaderKey.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){

@ -398,6 +398,12 @@ public class DesktopAssetManager implements AssetManager {
AssetCache cache = handler.getCache(SimpleAssetCache.class);
Shader shader = (Shader) cache.getFromCache(key);
if (shader == null){
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();
@ -408,6 +414,7 @@ public class DesktopAssetManager implements AssetManager {
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);
}

@ -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(),
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) {

@ -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
@ -62,13 +64,20 @@ public abstract class ShaderGenerator {
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();
@ -82,6 +91,7 @@ public abstract class ShaderGenerator {
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;
}

@ -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(){
}
@ -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);

Loading…
Cancel
Save