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
This commit is contained in:
parent
77a3cba69e
commit
4f3319f049
@ -448,6 +448,8 @@ public class J3MLoader implements AssetLoader {
|
|||||||
|
|
||||||
if(isUseNodes){
|
if(isUseNodes){
|
||||||
nodesLoaderDelegate.computeConditions();
|
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){
|
if (vertName != null && fragName != null){
|
||||||
|
@ -398,16 +398,23 @@ public class DesktopAssetManager implements AssetManager {
|
|||||||
AssetCache cache = handler.getCache(SimpleAssetCache.class);
|
AssetCache cache = handler.getCache(SimpleAssetCache.class);
|
||||||
Shader shader = (Shader) cache.getFromCache(key);
|
Shader shader = (Shader) cache.getFromCache(key);
|
||||||
if (shader == null){
|
if (shader == null){
|
||||||
String vertName = key.getVertName();
|
if (key.isUsesShaderNodes()) {
|
||||||
String fragName = key.getFragName();
|
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 vertSource = (String) loadAsset(new AssetKey(vertName));
|
||||||
String fragSource = (String) loadAsset(new AssetKey(fragName));
|
String fragSource = (String) loadAsset(new AssetKey(fragName));
|
||||||
|
|
||||||
shader = new Shader();
|
shader = new Shader();
|
||||||
shader.initialize();
|
shader.initialize();
|
||||||
shader.addSource(Shader.ShaderType.Vertex, vertName, vertSource, key.getDefines().getCompiled(), key.getVertexShaderLanguage());
|
shader.addSource(Shader.ShaderType.Vertex, vertName, vertSource, key.getDefines().getCompiled(), key.getVertexShaderLanguage());
|
||||||
shader.addSource(Shader.ShaderType.Fragment, fragName, fragSource, key.getDefines().getCompiled(), key.getFragmentShaderLanguage());
|
shader.addSource(Shader.ShaderType.Fragment, fragName, fragSource, key.getDefines().getCompiled(), key.getFragmentShaderLanguage());
|
||||||
|
}
|
||||||
|
|
||||||
cache.addToCache(key, shader);
|
cache.addToCache(key, shader);
|
||||||
}
|
}
|
||||||
|
@ -204,17 +204,18 @@ public class Technique /* implements Savable */ {
|
|||||||
|
|
||||||
private void loadShader(AssetManager manager,EnumSet<Caps> rendererCaps) {
|
private void loadShader(AssetManager manager,EnumSet<Caps> rendererCaps) {
|
||||||
|
|
||||||
if (getDef().isUsingShaderNodes()) {
|
ShaderKey key = new ShaderKey(def.getVertexShaderName(),
|
||||||
shader = manager.getShaderGenerator(rendererCaps).generateShader(this);
|
|
||||||
} else {
|
|
||||||
ShaderKey key = new ShaderKey(def.getVertexShaderName(),
|
|
||||||
def.getFragmentShaderName(),
|
def.getFragmentShaderName(),
|
||||||
getAllDefines(),
|
getAllDefines(),
|
||||||
def.getVertexShaderLanguage(),
|
def.getVertexShaderLanguage(),
|
||||||
def.getFragmentShaderLanguage());
|
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
|
// register the world bound uniforms
|
||||||
worldBindUniforms.clear();
|
worldBindUniforms.clear();
|
||||||
if (def.getWorldBindings() != null) {
|
if (def.getWorldBindings() != null) {
|
||||||
|
@ -52,6 +52,8 @@ public abstract class ShaderGenerator {
|
|||||||
protected AssetManager assetManager;
|
protected AssetManager assetManager;
|
||||||
//indentation value for generation
|
//indentation value for generation
|
||||||
protected int indent;
|
protected int indent;
|
||||||
|
//the technique to use for the shader generation
|
||||||
|
protected Technique technique = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a shaderGenerator
|
* Build a shaderGenerator
|
||||||
@ -62,13 +64,20 @@ public abstract class ShaderGenerator {
|
|||||||
this.assetManager = assetManager;
|
this.assetManager = assetManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void initialize(Technique technique){
|
||||||
|
this.technique = technique;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate vertex and fragment shaders for the given technique
|
* Generate vertex and fragment shaders for the given technique
|
||||||
*
|
*
|
||||||
* @param technique the technique to use to generate the shaders
|
* @param technique the technique to use to generate the shaders
|
||||||
* @return a Shader program
|
* @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();
|
DefineList defines = technique.getAllDefines();
|
||||||
TechniqueDef def = technique.getDef();
|
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.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));
|
shader.addSource(Shader.ShaderType.Fragment, technique.getDef().getName() + ".frag", fragmentSource, defines.getCompiled(), getLanguageAndVersion(ShaderType.Fragment));
|
||||||
|
|
||||||
|
technique = null;
|
||||||
return shader;
|
return shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@ public class ShaderKey extends AssetKey<Shader> {
|
|||||||
protected String vertLanguage;
|
protected String vertLanguage;
|
||||||
protected String fragLanguage;
|
protected String fragLanguage;
|
||||||
protected int cachedHashedCode = 0;
|
protected int cachedHashedCode = 0;
|
||||||
|
protected boolean usesShaderNodes = false;
|
||||||
|
|
||||||
public ShaderKey(){
|
public ShaderKey(){
|
||||||
}
|
}
|
||||||
@ -125,6 +126,14 @@ public class ShaderKey extends AssetKey<Shader> {
|
|||||||
return fragLanguage;
|
return fragLanguage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isUsesShaderNodes() {
|
||||||
|
return usesShaderNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsesShaderNodes(boolean usesShaderNodes) {
|
||||||
|
this.usesShaderNodes = usesShaderNodes;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(JmeExporter ex) throws IOException{
|
public void write(JmeExporter ex) throws IOException{
|
||||||
super.write(ex);
|
super.write(ex);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user