Browse Source

* Some optimizations for defines and shader key. Computing "compiled" define list isn't necessary to execute a lookup against asset manager. Allows faster changes in defines.

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9771 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
Sha..rd 13 years ago
parent
commit
8efd28da76

+ 52 - 15
engine/src/core/com/jme3/shader/DefineList.java

@@ -35,13 +35,15 @@ package com.jme3.shader;
 import com.jme3.export.*;
 import java.io.IOException;
 import java.util.Map;
-import java.util.SortedMap;
 import java.util.TreeMap;
 
-public class DefineList implements Savable {
+public class DefineList implements Savable, Cloneable {
 
-    private final SortedMap<String, String> defines = new TreeMap<String, String>();
+    private static final String ONE = "1";
+    
+    private TreeMap<String, String> defines = new TreeMap<String, String>();
     private String compiled = null;
+    private int cachedHashCode = 0;
 
     public void write(JmeExporter ex) throws IOException{
         OutputCapsule oc = ex.getCapsule(this);
@@ -73,46 +75,66 @@ public class DefineList implements Savable {
     public void clear() {
         defines.clear();
         compiled = "";
+        cachedHashCode = 0;
     }
 
     public String get(String key){
         return defines.get(key);
     }
+    
+    @Override
+    public DefineList clone() {
+        try {
+            DefineList clone = (DefineList) super.clone();
+            clone.cachedHashCode = 0;
+            clone.compiled = null;
+            clone.defines = (TreeMap<String, String>) defines.clone();
+            return clone;
+        } catch (CloneNotSupportedException ex) {
+            throw new AssertionError();
+        }
+    }
 
     public boolean set(String key, VarType type, Object val){    
         if (val == null){
             defines.remove(key);
             compiled = null;
+            cachedHashCode = 0;
             return true;
         }
 
         switch (type){
             case Boolean:
-                if ( ((Boolean) val).booleanValue() ) {
-                    // same literal, != should work
-                    if (defines.put(key, "1") != "1") {
+                if (((Boolean) val).booleanValue()) {
+                    // same literal, != will work
+                    if (defines.put(key, ONE) != ONE) {
                         compiled = null;
+                        cachedHashCode = 0;
                         return true;
                     }
                 } else if (defines.containsKey(key)) {
                     defines.remove(key);
                     compiled = null;
+                    cachedHashCode = 0;
                     return true;
                 }
                 
                 break;
             case Float:
             case Int:
-                String original = defines.put(key, val.toString());
+                String newValue = val.toString();
+                String original = defines.put(key, newValue);
                 if (!val.equals(original)) {
                     compiled = null;
+                    cachedHashCode = 0;
                     return true;            
                 }
                 break;
             default:
-                // same literal, != should work
-                if (defines.put(key, "1") != "1") {  
+                // same literal, != will work
+                if (defines.put(key, ONE) != ONE) {  
                     compiled = null;
+                    cachedHashCode = 0;
                     return true;            
                 }
                 break;
@@ -124,17 +146,18 @@ public class DefineList implements Savable {
     public boolean remove(String key){   
         if (defines.remove(key) != null) {
             compiled = null;
+            cachedHashCode = 0;
             return true;
         }
-        
         return false;
     }
 
     public void addFrom(DefineList other){    
-        if (other == null)
+        if (other == null) {
             return;
-        
+        }
         compiled = null;
+        cachedHashCode = 0;
         defines.putAll(other.defines);
     }
 
@@ -150,15 +173,29 @@ public class DefineList implements Savable {
         return compiled;
     }
 
+    @Override
+    public boolean equals(Object obj) {
+        final DefineList other = (DefineList) obj;
+        return defines.equals(other.defines);
+    }
+    
+    @Override
+    public int hashCode() {
+        if (cachedHashCode == 0) {
+            cachedHashCode = defines.hashCode();
+        }
+        return cachedHashCode;
+    }
+
     @Override
     public String toString(){
         StringBuilder sb = new StringBuilder();
         int i = 0;
         for (Map.Entry<String, String> entry : defines.entrySet()) {
-            sb.append(entry.getKey());
-            if (i != defines.size() - 1)
+            sb.append(entry.getKey()).append("=").append(entry.getValue());
+            if (i != defines.size() - 1) {
                 sb.append(", ");
-
+            }
             i++;
         }
         return sb.toString();

+ 24 - 16
engine/src/core/com/jme3/shader/ShaderKey.java

@@ -45,6 +45,7 @@ public class ShaderKey extends AssetKey<Shader> {
     protected DefineList defines;
     protected String vertLanguage;
     protected String fragLanguage;
+    protected int cachedHashedCode = 0;
 
     public ShaderKey(){
     }
@@ -57,6 +58,14 @@ public class ShaderKey extends AssetKey<Shader> {
         this.fragLanguage = fragLanguage;
     }
 
+    @Override
+    public ShaderKey clone() {
+        ShaderKey clone = (ShaderKey) super.clone();
+        clone.cachedHashedCode = 0;
+        clone.defines = defines.clone();
+        return clone;
+    }
+    
     @Override
     public String toString(){
         return "V="+name + " F=" + fragName + (defines != null ? defines : "");
@@ -64,32 +73,29 @@ public class ShaderKey extends AssetKey<Shader> {
 
     @Override
     public boolean equals(Object obj) {
-        if (obj == null){
-            return false;
-        }
-        if (getClass() != obj.getClass()){
-            return false;
-        }
-
         final ShaderKey other = (ShaderKey) obj;
         if (name.equals(other.name) && fragName.equals(other.fragName)){
-            if (defines != null && other.defines != null)
-                return defines.getCompiled().equals(other.defines.getCompiled());
-            else if (defines != null || other.defines != null)
+            if (defines != null && other.defines != null) {
+                return defines.equals(other.defines);
+            } else if (defines != null || other.defines != null) {
                 return false;
-            else
+            } else {
                 return true;
+            }
         }
         return false;
     }
 
     @Override
     public int hashCode() {
-        int hash = 7;
-        hash = 41 * hash + name.hashCode();
-        hash = 41 * hash + fragName.hashCode();
-        hash = 41 * hash + (defines != null ? defines.getCompiled().hashCode() : 0);
-        return hash;
+        if (cachedHashedCode == 0) {
+            int hash = 7;
+            hash = 41 * hash + name.hashCode();
+            hash = 41 * hash + fragName.hashCode();
+            hash = 41 * hash + (defines != null ? defines.hashCode() : 0);
+            cachedHashedCode = hash;
+        }
+        return cachedHashedCode;
     }
 
     public DefineList getDefines() {
@@ -126,6 +132,7 @@ public class ShaderKey extends AssetKey<Shader> {
         OutputCapsule oc = ex.getCapsule(this);
         oc.write(fragName, "fragment_name", null);
         oc.write(vertLanguage, "language", null);
+        oc.write(fragLanguage, "frag_language", null);
     }
 
     @Override
@@ -134,6 +141,7 @@ public class ShaderKey extends AssetKey<Shader> {
         InputCapsule ic = im.getCapsule(this);
         fragName = ic.readString("fragment_name", null);
         vertLanguage = ic.readString("language", null);
+        fragLanguage = ic.readString("frag_language", null);
     }
 
 }