Browse Source

Multithreaded the shader compilation using all available CPU cores.
Removed the const Replace() methods from String.

Lasse Öörni 14 years ago
parent
commit
118ed95315

+ 0 - 9
Bin/CoreData/Techniques/DiffVCol.xml

@@ -1,9 +0,0 @@
-<technique>
-    <pass name="deferred" vs="Deferred/GBuffer_VCol" ps="Deferred/GBuffer_DiffVCol" />
-    <pass name="prepass" vs="Prepass/GBuffer" ps="Prepass/GBuffer" />
-    <pass name="material" vs="Prepass/Material_VCol" ps="Prepass/Material_DiffVCol" depthwrite="false" depthtest="equal" />
-    <pass name="base" vs="Forward_VCol" ps="Forward_DiffVColAmbient" />
-    <pass name="litbase" vs="Forward_VCol" ps="Forward_DiffVColAmbient" />
-    <pass name="light" vs="Forward_VCol" ps="Forward_DiffVCol" depthwrite="false" depthtest="equal" blend="add" />
-    <pass name="shadow" vs="Shadow" ps="Shadow" />
-</technique>

+ 0 - 9
Bin/CoreData/Techniques/NoTextureVCol.xml

@@ -1,9 +0,0 @@
-<technique>
-    <pass name="deferred" vs="Deferred/GBuffer_VCol" ps="Deferred/GBuffer_VCol" />
-    <pass name="prepass" vs="Prepass/GBuffer" ps="Prepass/GBuffer" />
-    <pass name="material" vs="Prepass/Material_VCol" ps="Prepass/Material_VCol" depthwrite="false" depthtest="equal" />
-    <pass name="base" vs="Forward_VCol" ps="Forward_VColAmbient" />
-    <pass name="litbase" vs="Forward_VCol" ps="Forward_VColAmbient" />
-    <pass name="light" vs="Forward_VCol" ps="Forward_VCol" depthwrite="false" depthtest="equal" blend="add" />
-    <pass name="shadow" vs="Shadow" ps="Shadow" />
-</technique>

+ 1 - 1
Engine/Container/List.h

@@ -227,7 +227,7 @@ public:
     void Pop()
     void Pop()
     {
     {
         if (size_)
         if (size_)
-            Erase(End() - 1);
+            Erase(--End());
     }
     }
     
     
     /// Erase a node from the list. Return an iterator to the next element
     /// Erase a node from the list. Return an iterator to the next element

+ 12 - 36
Engine/Container/String.cpp

@@ -138,7 +138,7 @@ String& String::operator += (bool rhs)
     return *this += String(rhs);
     return *this += String(rhs);
 }
 }
 
 
-void String::ReplaceInPlace(char replaceThis, char replaceWith)
+void String::Replace(char replaceThis, char replaceWith)
 {
 {
     for (unsigned i = 0; i < length_; ++i)
     for (unsigned i = 0; i < length_; ++i)
     {
     {
@@ -147,7 +147,7 @@ void String::ReplaceInPlace(char replaceThis, char replaceWith)
     }
     }
 }
 }
 
 
-void String::ReplaceInPlace(const String& replaceThis, const String& replaceWith)
+void String::Replace(const String& replaceThis, const String& replaceWith)
 {
 {
     unsigned nextPos = 0;
     unsigned nextPos = 0;
     
     
@@ -156,27 +156,27 @@ void String::ReplaceInPlace(const String& replaceThis, const String& replaceWith
         unsigned pos = Find(replaceThis, nextPos);
         unsigned pos = Find(replaceThis, nextPos);
         if (pos == NPOS)
         if (pos == NPOS)
             break;
             break;
-        ReplaceInPlace(pos, replaceThis.length_, replaceWith);
+        Replace(pos, replaceThis.length_, replaceWith);
         nextPos = pos + replaceWith.length_;
         nextPos = pos + replaceWith.length_;
     }
     }
 }
 }
 
 
-void String::ReplaceInPlace(unsigned pos, unsigned length, const String& str)
+void String::Replace(unsigned pos, unsigned length, const String& str)
 {
 {
     // If substring is illegal, do nothing
     // If substring is illegal, do nothing
     if (pos + length > length_)
     if (pos + length > length_)
         return;
         return;
     
     
-    ReplaceInPlace(pos, length, str.buffer_, str.length_);
+    Replace(pos, length, str.buffer_, str.length_);
 }
 }
 
 
-String::Iterator String::ReplaceInPlace(const String::Iterator& start, const String::Iterator& end, const String& replaceWith)
+String::Iterator String::Replace(const String::Iterator& start, const String::Iterator& end, const String& replaceWith)
 {
 {
     unsigned pos = start - Begin();
     unsigned pos = start - Begin();
     if (pos >= length_)
     if (pos >= length_)
         return End();
         return End();
     unsigned length = end - start;
     unsigned length = end - start;
-    ReplaceInPlace(pos, length, replaceWith);
+    Replace(pos, length, replaceWith);
     
     
     return Begin() + pos;
     return Begin() + pos;
 }
 }
@@ -189,7 +189,7 @@ void String::Insert(unsigned pos, const String& str)
     if (pos == length_)
     if (pos == length_)
         (*this) += str;
         (*this) += str;
     else
     else
-        ReplaceInPlace(pos, 0, str);
+        Replace(pos, 0, str);
 }
 }
 
 
 void String::Insert(unsigned pos, char c)
 void String::Insert(unsigned pos, char c)
@@ -224,7 +224,7 @@ String::Iterator String::Insert(const String::Iterator& dest, const String::Iter
     if (pos > length_)
     if (pos > length_)
         pos = length_;
         pos = length_;
     unsigned length = end - start;
     unsigned length = end - start;
-    ReplaceInPlace(pos, 0, &(*start), length);
+    Replace(pos, 0, &(*start), length);
     
     
     return Begin() + pos;
     return Begin() + pos;
 }
 }
@@ -241,7 +241,7 @@ String::Iterator String::Insert(const String::Iterator& dest, char c)
 
 
 void String::Erase(unsigned pos, unsigned length)
 void String::Erase(unsigned pos, unsigned length)
 {
 {
-    ReplaceInPlace(pos, length, String());
+    Replace(pos, length, String());
 }
 }
 
 
 String::Iterator String::Erase(const String::Iterator& it)
 String::Iterator String::Erase(const String::Iterator& it)
@@ -333,30 +333,6 @@ void String::Swap(String& str)
     ::Swap(buffer_, str.buffer_);
     ::Swap(buffer_, str.buffer_);
 }
 }
 
 
-String String::Replace(char replaceThis, char replaceWith) const
-{
-    String ret(*this);
-    ret.ReplaceInPlace(replaceThis, replaceWith);
-    
-    return ret;
-}
-
-String String::Replace(const String& replaceThis, const String& replaceWith) const
-{
-    String ret(*this);
-    ret.ReplaceInPlace(replaceThis, replaceWith);
-    
-    return ret;
-}
-
-String String::Replace(unsigned pos, unsigned length, const String& str) const
-{
-    String ret(*this);
-    ret.ReplaceInPlace(pos, length, str);
-    
-    return ret;
-}
-
 String String::Substring(unsigned pos) const
 String String::Substring(unsigned pos) const
 {
 {
     if (pos < length_)
     if (pos < length_)
@@ -387,7 +363,7 @@ String String::Substring(unsigned pos, unsigned length) const
         return String();
         return String();
 }
 }
 
 
-String String::Trim() const
+String String::Trimmed() const
 {
 {
     unsigned trimStart = 0;
     unsigned trimStart = 0;
     unsigned trimEnd = length_;
     unsigned trimEnd = length_;
@@ -558,7 +534,7 @@ unsigned String::FindLast(const String& str, unsigned startPos) const
     return NPOS;
     return NPOS;
 }
 }
 
 
-void String::ReplaceInPlace(unsigned pos, unsigned length, const char* srcStart, unsigned srcLength)
+void String::Replace(unsigned pos, unsigned length, const char* srcStart, unsigned srcLength)
 {
 {
     int delta = (int)srcLength - (int)length;
     int delta = (int)srcLength - (int)length;
     
     

+ 10 - 12
Engine/Container/StringBase.h

@@ -272,13 +272,13 @@ public:
     const char& At(unsigned index) const { return buffer_[index]; }
     const char& At(unsigned index) const { return buffer_[index]; }
     
     
     /// Replace all occurrences of a character
     /// Replace all occurrences of a character
-    void ReplaceInPlace(char replaceThis, char replaceWith);
+    void Replace(char replaceThis, char replaceWith);
     /// Replace all occurrences of a string
     /// Replace all occurrences of a string
-    void ReplaceInPlace(const String& replaceThis, const String& replaceWith);
+    void Replace(const String& replaceThis, const String& replaceWith);
     /// Replace a substring
     /// Replace a substring
-    void ReplaceInPlace(unsigned pos, unsigned length, const String& replaceWith);
+    void Replace(unsigned pos, unsigned length, const String& replaceWith);
     /// Replace a substring using iterators
     /// Replace a substring using iterators
-    Iterator ReplaceInPlace(const Iterator& start, const Iterator& end, const String& replaceWith);
+    Iterator Replace(const Iterator& start, const Iterator& end, const String& replaceWith);
     /// Insert a string
     /// Insert a string
     void Insert(unsigned pos, const String& str);
     void Insert(unsigned pos, const String& str);
     /// Insert a character
     /// Insert a character
@@ -314,18 +314,16 @@ public:
     Iterator End() { return Iterator(buffer_ + length_); }
     Iterator End() { return Iterator(buffer_ + length_); }
     /// Return const iterator to the end
     /// Return const iterator to the end
     ConstIterator End() const { return ConstIterator(buffer_ + length_); }
     ConstIterator End() const { return ConstIterator(buffer_ + length_); }
-    /// Return string with all occurrences of a character replaced
-    String Replace(char replaceThis, char replaceWith) const;
-    /// Return string with all occurrences of a string replaced
-    String Replace(const String& replaceThis, const String& replaceWith) const;
-    /// Return string with a substring replaced
-    String Replace(unsigned pos, unsigned length, const String& replaceWith) const;
+    /// Return first char, or 0 if empty
+    char Front() const { return buffer_[0]; }
+    /// Return last char, or 0 if empty
+    char Back() const { return length_ ? buffer_[length_ - 1] : buffer_[0]; }
     /// Return a substring from position to end
     /// Return a substring from position to end
     String Substring(unsigned pos) const;
     String Substring(unsigned pos) const;
     /// Return a substring with length from position
     /// Return a substring with length from position
     String Substring(unsigned pos, unsigned length) const;
     String Substring(unsigned pos, unsigned length) const;
     /// Return string with whitespace trimmed from the beginning and the end
     /// Return string with whitespace trimmed from the beginning and the end
-    String Trim() const;
+    String Trimmed() const;
     /// Return string in uppercase
     /// Return string in uppercase
     String ToUpper() const;
     String ToUpper() const;
     /// Return string in lowercase
     /// Return string in lowercase
@@ -395,7 +393,7 @@ private:
     }
     }
     
     
     /// Replace a substring with another substring
     /// Replace a substring with another substring
-    void ReplaceInPlace(unsigned pos, unsigned length, const char* srcStart, unsigned srcLength);
+    void Replace(unsigned pos, unsigned length, const char* srcStart, unsigned srcLength);
     
     
     /// String length
     /// String length
     unsigned length_;
     unsigned length_;

+ 4 - 4
Engine/Core/MiniDump.cpp

@@ -60,10 +60,10 @@ int WriteMiniDump(const char* applicationName, void* exceptionPointers)
     time(&sysTime);
     time(&sysTime);
     const char* dateTime = ctime(&sysTime);
     const char* dateTime = ctime(&sysTime);
     String dateTimeStr = String(dateTime);
     String dateTimeStr = String(dateTime);
-    dateTimeStr.ReplaceInPlace("\n", "");
-    dateTimeStr.ReplaceInPlace(":", "");
-    dateTimeStr.ReplaceInPlace("/", "");
-    dateTimeStr.ReplaceInPlace(' ', '_');
+    dateTimeStr.Replace("\n", "");
+    dateTimeStr.Replace(":", "");
+    dateTimeStr.Replace("/", "");
+    dateTimeStr.Replace(' ', '_');
     
     
     char pathName[MAX_PATH];
     char pathName[MAX_PATH];
     pathName[0] = 0;
     pathName[0] = 0;

+ 1 - 1
Engine/Engine/Console.cpp

@@ -239,7 +239,7 @@ void Console::HandleScreenMode(StringHash eventType, VariantMap& eventData)
 void Console::HandleLogMessage(StringHash eventType, VariantMap& eventData)
 void Console::HandleLogMessage(StringHash eventType, VariantMap& eventData)
 {
 {
     // If the rows are not fully initialized yet, or we are recursing here, do not write the message
     // If the rows are not fully initialized yet, or we are recursing here, do not write the message
-    if ((inLogMessage_) || (!rows_.Size()) || (!rows_[rows_.Size() - 1]))
+    if ((inLogMessage_) || (rows_.Empty()) || (!rows_.Back()))
         return;
         return;
     
     
     inLogMessage_ = true;
     inLogMessage_ = true;

+ 1 - 0
Engine/Engine/IOAPI.cpp

@@ -288,6 +288,7 @@ void RegisterFileSystem(asIScriptEngine* engine)
     engine->RegisterGlobalFunction("String AddTrailingSlash(const String&in)", asFUNCTION(AddTrailingSlash), asCALL_CDECL);
     engine->RegisterGlobalFunction("String AddTrailingSlash(const String&in)", asFUNCTION(AddTrailingSlash), asCALL_CDECL);
     engine->RegisterGlobalFunction("String RemoveTrailingSlash(const String&in)", asFUNCTION(RemoveTrailingSlash), asCALL_CDECL);
     engine->RegisterGlobalFunction("String RemoveTrailingSlash(const String&in)", asFUNCTION(RemoveTrailingSlash), asCALL_CDECL);
     engine->RegisterGlobalFunction("String GetParentPath(const String&in)", asFUNCTION(GetParentPath), asCALL_CDECL);
     engine->RegisterGlobalFunction("String GetParentPath(const String&in)", asFUNCTION(GetParentPath), asCALL_CDECL);
+    engine->RegisterGlobalFunction("String GetInternalPath(const String&in)", asFUNCTION(GetInternalPath), asCALL_CDECL);
 }
 }
 
 
 static PackageFile* ConstructPackageFile()
 static PackageFile* ConstructPackageFile()

+ 4 - 2
Engine/Graphics/Renderer.cpp

@@ -442,7 +442,8 @@ const Viewport& Renderer::GetViewport(unsigned index) const
 VertexShader* Renderer::GetVertexShader(const String& name, bool checkExists) const
 VertexShader* Renderer::GetVertexShader(const String& name, bool checkExists) const
 {
 {
     // Check for extra underscore with no variations and remove
     // Check for extra underscore with no variations and remove
-    String fullName = (shaderPath_ + name + vsFormat_).Replace("_.", ".");
+    String fullName = (shaderPath_ + name + vsFormat_);
+    fullName.Replace("_.", ".");
     if (checkExists)
     if (checkExists)
     {
     {
         if (!cache_->Exists(fullName))
         if (!cache_->Exists(fullName))
@@ -454,7 +455,8 @@ VertexShader* Renderer::GetVertexShader(const String& name, bool checkExists) co
 PixelShader* Renderer::GetPixelShader(const String& name, bool checkExists) const
 PixelShader* Renderer::GetPixelShader(const String& name, bool checkExists) const
 {
 {
     // Check for extra underscore with no variations and remove
     // Check for extra underscore with no variations and remove
-    String fullName = (shaderPath_ + name + psFormat_).Replace("_.", ".");
+    String fullName = (shaderPath_ + name + psFormat_);
+    fullName.Replace("_.", ".");
     if (checkExists)
     if (checkExists)
     {
     {
         if (!cache_->Exists(fullName))
         if (!cache_->Exists(fullName))

+ 2 - 2
Engine/Graphics/View.cpp

@@ -1868,7 +1868,7 @@ Technique* View::GetTechnique(Drawable* drawable, Material*& material)
     
     
     float lodDistance = drawable->GetLodDistance();
     float lodDistance = drawable->GetLodDistance();
     const Vector<TechniqueEntry>& techniques = material->GetTechniques();
     const Vector<TechniqueEntry>& techniques = material->GetTechniques();
-    if (!techniques.Size())
+    if (techniques.Empty())
         return 0;
         return 0;
     
     
     // Check for suitable technique. Techniques should be ordered like this:
     // Check for suitable technique. Techniques should be ordered like this:
@@ -1887,7 +1887,7 @@ Technique* View::GetTechnique(Drawable* drawable, Material*& material)
     }
     }
     
     
     // If no suitable technique found, fallback to the last
     // If no suitable technique found, fallback to the last
-    return techniques[techniques.Size() - 1].technique_;
+    return techniques.Back().technique_;
 }
 }
 
 
 void View::CheckMaterialForAuxView(Material* material)
 void View::CheckMaterialForAuxView(Material* material)

+ 3 - 3
Engine/IO/File.h

@@ -45,18 +45,18 @@ class File : public Object, public Deserializer, public Serializer
 public:
 public:
     /// Construct
     /// Construct
     File(Context* context);
     File(Context* context);
-    /// Construct and open
+    /// Construct and open a filesystem file
     File(Context* context, const String& fileName, FileMode mode = FILE_READ);
     File(Context* context, const String& fileName, FileMode mode = FILE_READ);
     /// Construct and open from a package file
     /// Construct and open from a package file
     File(Context* context, PackageFile* package, const String& fileName);
     File(Context* context, PackageFile* package, const String& fileName);
     /// Destruct. Close the file if open
     /// Destruct. Close the file if open
     virtual ~File();
     virtual ~File();
     
     
-    /// Read bytes from the file
+    /// Read bytes from the file. Return number of bytes actually read
     virtual unsigned Read(void* dest, unsigned size);
     virtual unsigned Read(void* dest, unsigned size);
     /// Set position from the beginning of the file
     /// Set position from the beginning of the file
     virtual unsigned Seek(unsigned position);
     virtual unsigned Seek(unsigned position);
-    /// Write bytes to the file
+    /// Write bytes to the file. Return number of bytes actually written
     virtual unsigned Write(const void* data, unsigned size);
     virtual unsigned Write(const void* data, unsigned size);
     /// Return the file name
     /// Return the file name
     virtual const String& GetName() const { return fileName_; }
     virtual const String& GetName() const { return fileName_; }

+ 27 - 22
Engine/IO/FileSystem.cpp

@@ -77,7 +77,8 @@ bool FileSystem::CreateDir(const String& pathName)
         return false;
         return false;
     }
     }
     
     
-    bool success = (CreateDirectory(GetNativePath(RemoveTrailingSlash(pathName), true).CString(), 0) == TRUE) || (GetLastError() == ERROR_ALREADY_EXISTS);
+    bool success = (CreateDirectory(GetNativePath(RemoveTrailingSlash(pathName), true).CString(), 0) == TRUE) ||
+        (GetLastError() == ERROR_ALREADY_EXISTS);
     if (success)
     if (success)
         LOGDEBUG("Created directory " + pathName);
         LOGDEBUG("Created directory " + pathName);
     else
     else
@@ -334,7 +335,7 @@ void FileSystem::ScanDirInternal(Vector<String>& result, String path, const Stri
 
 
 void SplitPath(const String& fullPath, String& pathName, String& fileName, String& extension)
 void SplitPath(const String& fullPath, String& pathName, String& fileName, String& extension)
 {
 {
-    String fullPathCopy = fullPath.Replace('\\', '/');
+    String fullPathCopy = GetInternalPath(fullPath);
     
     
     unsigned extPos = fullPathCopy.FindLast('.');
     unsigned extPos = fullPathCopy.FindLast('.');
     if (extPos != String::NPOS)
     if (extPos != String::NPOS)
@@ -386,32 +387,24 @@ String GetFileNameAndExtension(const String& fileName)
     return file + extension;
     return file + extension;
 }
 }
 
 
-String AddTrailingSlash(const String& path)
+String AddTrailingSlash(const String& pathName)
 {
 {
-    String ret;
+    String ret = pathName;
+    ret.Replace('\\', '/');
+    if ((!ret.Empty()) && (ret.Back() != '/'))
+        ret += '/';
     
     
-    if (!path.Empty())
-    {
-        ret = path;
-        char last = path[path.Length() - 1];
-        if ((last != '/') && (last != '\\'))
-            ret += '/';
-    }
-    
-    ret.ReplaceInPlace('\\', '/');
     return ret;
     return ret;
 }
 }
 
 
-String RemoveTrailingSlash(const String& path)
+String RemoveTrailingSlash(const String& pathName)
 {
 {
-    if (!path.Empty())
-    {
-        char last = path[path.Length() - 1];
-        if ((last == '/') || (last == '\\'))
-            return path.Substring(0, path.Length() - 1);
-    }
+    String ret = pathName;
+    ret.Replace('\\', '/');
+    if ((!ret.Empty()) && (ret.Back() == '/'))
+        ret.Resize(ret.Length() - 1);
     
     
-    return path;
+    return ret;
 }
 }
 
 
 String GetParentPath(const String& path)
 String GetParentPath(const String& path)
@@ -423,6 +416,14 @@ String GetParentPath(const String& path)
         return path;
         return path;
 }
 }
 
 
+String GetInternalPath(const String& pathName)
+{
+    String ret = pathName;
+    ret.Replace('\\', '/');
+    
+    return ret;
+}
+
 String GetNativePath(const String& pathName, bool forNativeApi)
 String GetNativePath(const String& pathName, bool forNativeApi)
 {
 {
     // On MSVC, replace slash always with backslash. On MinGW only if going to do Win32 native calls
     // On MSVC, replace slash always with backslash. On MinGW only if going to do Win32 native calls
@@ -431,7 +432,11 @@ String GetNativePath(const String& pathName, bool forNativeApi)
 #endif
 #endif
     
     
     if (forNativeApi)
     if (forNativeApi)
-        return pathName.Replace('/', '\\');
+    {
+        String ret = pathName;
+        ret.Replace('/', '\\');
+        return ret;
+    }
     else
     else
         return pathName;
         return pathName;
 }
 }

+ 4 - 2
Engine/IO/FileSystem.h

@@ -99,11 +99,13 @@ String GetFileName(const String& fullPath);
 String GetExtension(const String& fullPath);
 String GetExtension(const String& fullPath);
 /// Return the filename and extension from a full path. The extension will be converted to lowercase
 /// Return the filename and extension from a full path. The extension will be converted to lowercase
 String GetFileNameAndExtension(const String& fullPath);
 String GetFileNameAndExtension(const String& fullPath);
-/// Fix a path so that it contains a slash in the end, and convert backslashes to slashes
+/// Add a slash in the end of the path if missing, and convert backslashes to slashes
 String AddTrailingSlash(const String& pathName);
 String AddTrailingSlash(const String& pathName);
-/// Remove the slash or backslash from the end of a path if exists
+/// Remove the slash from the end of a path if exists, and convert backslashes to slashes
 String RemoveTrailingSlash(const String& pathName);
 String RemoveTrailingSlash(const String& pathName);
 /// Return the parent path, or the path itself if not available
 /// Return the parent path, or the path itself if not available
 String GetParentPath(const String& pathName);
 String GetParentPath(const String& pathName);
+/// Convert a path to internal format (use slashes)
+String GetInternalPath(const String& pathName);
 /// Convert a path to the format required by the operating system
 /// Convert a path to the format required by the operating system
 String GetNativePath(const String& pathName, bool forNativeApi = false);
 String GetNativePath(const String& pathName, bool forNativeApi = false);

+ 2 - 1
Engine/IO/Log.cpp

@@ -89,7 +89,8 @@ void Log::Write(int level, const String& message)
     time_t sysTime;
     time_t sysTime;
     time(&sysTime);
     time(&sysTime);
     const char* dateTime = ctime(&sysTime);
     const char* dateTime = ctime(&sysTime);
-    String dateTimeString = String(dateTime).Replace("\n", "");
+    String dateTimeString = String(dateTime);
+    dateTimeString.Replace("\n", "");
     String formattedMessage = "[" + dateTimeString + "] " + levelPrefixes[level] + ": " + message;
     String formattedMessage = "[" + dateTimeString + "] " + levelPrefixes[level] + ": " + message;
     
     
     printf("%s\n", formattedMessage.CString());
     printf("%s\n", formattedMessage.CString());

+ 3 - 3
Engine/Script/Addons.cpp

@@ -741,18 +741,18 @@ void RegisterString(asIScriptEngine *engine)
     engine->RegisterObjectMethod("String", "String opAdd(const String& in) const", asMETHODPR(String, operator +, (const String&) const, String), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "String opAdd(const String& in) const", asMETHODPR(String, operator +, (const String&) const, String), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "uint8 &opIndex(uint)", asFUNCTION(StringCharAt), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("String", "uint8 &opIndex(uint)", asFUNCTION(StringCharAt), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("String", "const uint8 &opIndex(uint) const", asFUNCTION(StringCharAt), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("String", "const uint8 &opIndex(uint) const", asFUNCTION(StringCharAt), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod("String", "void Replace(uint8, uint8)", asMETHODPR(String, Replace, (char, char), void), asCALL_THISCALL);
+    engine->RegisterObjectMethod("String", "void Replace(const String&in, const String&in)", asMETHODPR(String, Replace, (const String&, const String&), void), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "void Resize(uint)", asFUNCTION(StringResize), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("String", "void Resize(uint)", asFUNCTION(StringResize), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("String", "int Find(const String& in, uint start = 0) const", asMETHODPR(String, Find, (const String&, unsigned) const, unsigned), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "int Find(const String& in, uint start = 0) const", asMETHODPR(String, Find, (const String&, unsigned) const, unsigned), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "int Find(uint8, uint start = 0) const", asMETHODPR(String, Find, (char, unsigned) const, unsigned), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "int Find(uint8, uint start = 0) const", asMETHODPR(String, Find, (char, unsigned) const, unsigned), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "int FindLast(const String& in, uint start = 0xffffffff) const", asMETHODPR(String, FindLast, (const String&, unsigned) const, unsigned), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "int FindLast(const String& in, uint start = 0xffffffff) const", asMETHODPR(String, FindLast, (const String&, unsigned) const, unsigned), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "int FindLast(uint8, uint start = 0xffffffff) const", asMETHODPR(String, FindLast, (char, unsigned) const, unsigned), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "int FindLast(uint8, uint start = 0xffffffff) const", asMETHODPR(String, FindLast, (char, unsigned) const, unsigned), asCALL_THISCALL);
-    engine->RegisterObjectMethod("String", "String Replace(uint8, uint8) const", asMETHODPR(String, Replace, (char, char) const, String), asCALL_THISCALL);
-    engine->RegisterObjectMethod("String", "String Replace(const String&in, const String&in) const", asMETHODPR(String, Replace, (const String&, const String&) const, String), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "String Substring(uint) const", asMETHODPR(String, Substring, (unsigned) const, String), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "String Substring(uint) const", asMETHODPR(String, Substring, (unsigned) const, String), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "String Substring(uint, uint) const", asMETHODPR(String, Substring, (unsigned, unsigned) const, String), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "String Substring(uint, uint) const", asMETHODPR(String, Substring, (unsigned, unsigned) const, String), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "String ToUpper() const", asMETHOD(String, ToUpper), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "String ToUpper() const", asMETHOD(String, ToUpper), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "String ToLower() const", asMETHOD(String, ToLower), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "String ToLower() const", asMETHOD(String, ToLower), asCALL_THISCALL);
-    engine->RegisterObjectMethod("String", "String Trim() const", asMETHOD(String, Trim), asCALL_THISCALL);
+    engine->RegisterObjectMethod("String", "String Trimmed() const", asMETHOD(String, Trimmed), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "uint get_length() const", asMETHOD(String, Length), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "uint get_length() const", asMETHOD(String, Length), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "bool get_empty() const", asMETHOD(String, Empty), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "bool get_empty() const", asMETHOD(String, Empty), asCALL_THISCALL);
     
     

+ 7 - 6
Engine/Script/Script.cpp

@@ -64,7 +64,7 @@ void ExtractPropertyInfo(const String& functionName, const String& declaration,
     if (!info)
     if (!info)
     {
     {
         propertyInfos.Resize(propertyInfos.Size() + 1);
         propertyInfos.Resize(propertyInfos.Size() + 1);
-        info = &propertyInfos[propertyInfos.Size() - 1];
+        info = &propertyInfos.Back();
         info->name_ = propertyName;
         info->name_ = propertyName;
     }
     }
     if (functionName.Find("get_") != String::NPOS)
     if (functionName.Find("get_") != String::NPOS)
@@ -292,7 +292,8 @@ void Script::DumpAPI()
                     if (declaration.Find("::op") == String::NPOS)
                     if (declaration.Find("::op") == String::NPOS)
                     {
                     {
                         String prefix(typeName + "::");
                         String prefix(typeName + "::");
-                        methodDeclarations.Push(declaration.Replace(prefix, ""));
+                        declaration.Replace(prefix, "");
+                        methodDeclarations.Push(declaration);
                     }
                     }
                 }
                 }
                 else
                 else
@@ -420,11 +421,11 @@ asIObjectType* Script::GetObjectType(const char* declaration)
 void Script::OutputAPIRow(const String& row, bool removeReference)
 void Script::OutputAPIRow(const String& row, bool removeReference)
 {
 {
     String out = row;
     String out = row;
-    out.ReplaceInPlace("double", "float");
-    out.ReplaceInPlace("&in", "&");
-    out.ReplaceInPlace("&out", "&");
+    out.Replace("double", "float");
+    out.Replace("&in", "&");
+    out.Replace("&out", "&");
     if (removeReference)
     if (removeReference)
-        out.ReplaceInPlace("&", "");
+        out.Replace("&", "");
     
     
     LOGRAW(out + "\n");
     LOGRAW(out + "\n");
 }
 }

+ 2 - 1
Engine/UI/Text.cpp

@@ -106,7 +106,8 @@ void Text::SetStyle(const XMLElement& element)
     }
     }
     if (element.HasChildElement("text"))
     if (element.HasChildElement("text"))
     {
     {
-        String text = element.GetChildElement("text").GetString("value").Replace("\\n", "\n");
+        String text = element.GetChildElement("text").GetString("value");
+        text.Replace("\\n", "\n");
         text_ = text;
         text_ = text;
         changed = true;
         changed = true;
     }
     }

+ 1 - 3
SourceAssets/Shaders/Deferred/GBuffer.xml

@@ -1,7 +1,6 @@
 <shaders>
 <shaders>
     <shader name="GBuffer" type="vs">
     <shader name="GBuffer" type="vs">
         <option name="Normal" define="NORMALMAP" />
         <option name="Normal" define="NORMALMAP" />
-        <option name="VCol" define="VERTEXCOLOR" />
         <variation name="" />
         <variation name="" />
         <variation name="Skinned" define="SKINNED" />
         <variation name="Skinned" define="SKINNED" />
         <variation name="Instanced" define="INSTANCED" />
         <variation name="Instanced" define="INSTANCED" />
@@ -9,8 +8,7 @@
     <shader name="GBuffer" type="ps">
     <shader name="GBuffer" type="ps">
         <option name="Diff" define="DIFFMAP" />
         <option name="Diff" define="DIFFMAP" />
         <option name="Normal" define="NORMALMAP" />
         <option name="Normal" define="NORMALMAP" />
-        <option name="Spec" define="SPECMAP" />
-        <option name="VCol" define="VERTEXCOLOR" />        
+        <option name="Spec" define="SPECMAP" />      
         <option name="Mask" define="ALPHAMASK" include="Diff" />
         <option name="Mask" define="ALPHAMASK" include="Diff" />
     </shader>
     </shader>
 </shaders>
 </shaders>

+ 11 - 2
SourceAssets/Shaders/Forward.xml

@@ -1,7 +1,10 @@
 <shaders>
 <shaders>
     <shader name="Forward" type="vs">
     <shader name="Forward" type="vs">
         <option name="Normal" define="NORMALMAP" />
         <option name="Normal" define="NORMALMAP" />
-        <option name="VCol" define="VERTEXCOLOR" />
+        <option name="VCol" define="VERTEXCOLOR">
+            <exclude name="Normal" />
+            <exclude name="Shadow" />
+        </option>
         <option name="Spot" define="SPOTLIGHT" />
         <option name="Spot" define="SPOTLIGHT" />
         <option name="Shadow" define="SHADOW" />
         <option name="Shadow" define="SHADOW" />
         <variation name="" />
         <variation name="" />
@@ -15,12 +18,18 @@
         <option name="Diff" define="DIFFMAP" />
         <option name="Diff" define="DIFFMAP" />
         <option name="Normal" define="NORMALMAP" />
         <option name="Normal" define="NORMALMAP" />
         <option name="SpecMap" define="SPECMAP" include="Spec" />
         <option name="SpecMap" define="SPECMAP" include="Spec" />
-        <option name="VCol" define="VERTEXCOLOR" />
+        <option name="VCol" define="VERTEXCOLOR">
+            <exclude name="Normal" />
+            <exclude name="Shadow" />
+            <exclude name="Spec" />
+            <exclude name="SpecMap" />
+        </option>
         <option name="Volume" define="VOLUMETRIC">
         <option name="Volume" define="VOLUMETRIC">
             <exclude name="Additive" />
             <exclude name="Additive" />
             <exclude name="Ambient" />
             <exclude name="Ambient" />
             <exclude name="Normal" />
             <exclude name="Normal" />
             <exclude name="Shadow" />
             <exclude name="Shadow" />
+            <exclude name="Spec" />
             <exclude name="SpecMap" />
             <exclude name="SpecMap" />
             <exclude name="Unlit" />
             <exclude name="Unlit" />
         </option>
         </option>

+ 1 - 3
SourceAssets/Shaders/Prepass/Material.xml

@@ -1,14 +1,12 @@
 <shaders>
 <shaders>
     <shader name="Material" type="vs">
     <shader name="Material" type="vs">
-        <option name="VCol" define="VERTEXCOLOR" />
         <variation name="" />
         <variation name="" />
         <variation name="Skinned" define="SKINNED" />
         <variation name="Skinned" define="SKINNED" />
         <variation name="Instanced" define="INSTANCED" />
         <variation name="Instanced" define="INSTANCED" />
     </shader>
     </shader>
     <shader name="Material" type="ps">
     <shader name="Material" type="ps">
         <option name="Diff" define="DIFFMAP" />
         <option name="Diff" define="DIFFMAP" />
-        <option name="Spec" define="SPECMAP" />
-        <option name="VCol" define="VERTEXCOLOR" />        
+        <option name="Spec" define="SPECMAP" />    
         <option name="Mask" define="ALPHAMASK" include="Diff" />
         <option name="Mask" define="ALPHAMASK" include="Diff" />
     </shader>
     </shader>
 </shaders>
 </shaders>

+ 13 - 13
Tools/AssetImporter/AssetImporter.cpp

@@ -241,7 +241,7 @@ void Run(const Vector<String>& arguments)
                 break;
                 break;
                 
                 
             case 'm':
             case 'm':
-                materialListName_ = parameter.Replace('\\', '/');
+                materialListName_ = GetInternalPath(parameter);
                 break;
                 break;
                 
                 
             case 'p':
             case 'p':
@@ -299,7 +299,7 @@ void Run(const Vector<String>& arguments)
         String inFile = arguments[1];
         String inFile = arguments[1];
         String outFile;
         String outFile;
         if ((arguments.Size() > 2) && (arguments[2][0] != '-'))
         if ((arguments.Size() > 2) && (arguments[2][0] != '-'))
-            outFile = arguments[2].Replace('\\', '/');
+            outFile = GetInternalPath(arguments[2]);
         
         
         if (resourcePath_.Empty())
         if (resourcePath_.Empty())
         {
         {
@@ -374,13 +374,13 @@ void Run(const Vector<String>& arguments)
         for (unsigned i = 1; i < numLodArguments + 1; ++i)
         for (unsigned i = 1; i < numLodArguments + 1; ++i)
         {
         {
             if (i == numLodArguments)
             if (i == numLodArguments)
-                outFile = arguments[i].Replace('\\', '/');
+                outFile = GetInternalPath(arguments[i]);
             else
             else
             {
             {
                 if (i & 1)
                 if (i & 1)
                     lodDistances.Push(Max(ToFloat(arguments[i]), 0.0f));
                     lodDistances.Push(Max(ToFloat(arguments[i]), 0.0f));
                 else
                 else
-                    modelNames.Push(arguments[i].Replace('\\', '/'));
+                    modelNames.Push(GetInternalPath(arguments[i]));
             }
             }
         }
         }
         
         
@@ -1652,15 +1652,15 @@ Quaternion ToQuaternion(const aiQuaternion& quat)
 String SanitateAssetName(const String& name)
 String SanitateAssetName(const String& name)
 {
 {
     String fixedName = name;
     String fixedName = name;
-    fixedName.ReplaceInPlace("<", "");
-    fixedName.ReplaceInPlace(">", "");
-    fixedName.ReplaceInPlace("?", "");
-    fixedName.ReplaceInPlace("*", "");
-    fixedName.ReplaceInPlace(":", "");
-    fixedName.ReplaceInPlace("\"", "");
-    fixedName.ReplaceInPlace("/", "");
-    fixedName.ReplaceInPlace("\\", "");
-    fixedName.ReplaceInPlace("|", "");
+    fixedName.Replace("<", "");
+    fixedName.Replace(">", "");
+    fixedName.Replace("?", "");
+    fixedName.Replace("*", "");
+    fixedName.Replace(":", "");
+    fixedName.Replace("\"", "");
+    fixedName.Replace("/", "");
+    fixedName.Replace("\\", "");
+    fixedName.Replace("|", "");
     
     
     return fixedName;
     return fixedName;
 }
 }

+ 5 - 1
Tools/OgreImporter/OgreImporter.cpp

@@ -1019,10 +1019,14 @@ void WriteOutput(const String& outputFileName, bool exportAnimations, bool rotat
                 }
                 }
                 
                 
                 // Write each animation into a separate file
                 // Write each animation into a separate file
-                String animationFileName = outputFileName.Replace(".mdl", "") + "_" + newAnimation.name_ + ".ani";
+                String animationFileName = outputFileName;
+                animationFileName.Replace(".mdl", "");
+                animationFileName += "_" + newAnimation.name_ + ".ani";
+                
                 File dest(context_);
                 File dest(context_);
                 if (!dest.Open(animationFileName, FILE_WRITE))
                 if (!dest.Open(animationFileName, FILE_WRITE))
                     ErrorExit("Could not open output file " + animationFileName);
                     ErrorExit("Could not open output file " + animationFileName);
+                
                 dest.WriteID("UANI");
                 dest.WriteID("UANI");
                 dest.WriteString(newAnimation.name_);
                 dest.WriteString(newAnimation.name_);
                 dest.WriteFloat(newAnimation.length_);
                 dest.WriteFloat(newAnimation.length_);

+ 11 - 7
Tools/PackageTool/PackageTool.cpp

@@ -149,21 +149,25 @@ void WritePackageFile(const String& fileName, const String& rootDir)
     for (unsigned i = 0; i < entries_.Size(); ++i)
     for (unsigned i = 0; i < entries_.Size(); ++i)
     {
     {
         entries_[i].offset_ = dest.GetSize();
         entries_[i].offset_ = dest.GetSize();
-        String fileFullPath = GetNativePath(rootDir + "/" + entries_[i].name_);
-        FILE* handle = fopen(fileFullPath.CString(), "rb");
-        if (!handle)
+        String fileFullPath = rootDir + "/" + entries_[i].name_;
+        
+        File srcFile(context_, fileFullPath);
+        if (!srcFile.IsOpen())
             ErrorExit("Could not open file " + fileFullPath);
             ErrorExit("Could not open file " + fileFullPath);
-        SharedArrayPtr<unsigned char> buffer(new unsigned char[entries_[i].size_]);
-        if (fread(&buffer[0], entries_[i].size_, 1, handle) != 1)
+        
+        unsigned dataSize = entries_[i].size_;
+        SharedArrayPtr<unsigned char> buffer(new unsigned char[dataSize]);
+        
+        if (srcFile.Read(&buffer[0], dataSize) != dataSize)
             ErrorExit("Could not read file " + fileFullPath);
             ErrorExit("Could not read file " + fileFullPath);
+        srcFile.Close();
         
         
-        for (unsigned j = 0; j < entries_[i].size_; ++j)
+        for (unsigned j = 0; j < dataSize; ++j)
         {
         {
             checksum_ = SDBMHash(checksum_, buffer[j]);
             checksum_ = SDBMHash(checksum_, buffer[j]);
             entries_[i].checksum_ = SDBMHash(entries_[i].checksum_, buffer[j]);
             entries_[i].checksum_ = SDBMHash(entries_[i].checksum_, buffer[j]);
         }
         }
         
         
-        fclose(handle);
         dest.Write(&buffer[0], entries_[i].size_);
         dest.Write(&buffer[0], entries_[i].size_);
     }
     }
     
     

+ 197 - 165
Tools/ShaderCompiler/ShaderCompiler.cpp

@@ -24,8 +24,11 @@
 #include "Context.h"
 #include "Context.h"
 #include "File.h"
 #include "File.h"
 #include "FileSystem.h"
 #include "FileSystem.h"
+#include "List.h"
+#include "Mutex.h"
 #include "ProcessUtils.h"
 #include "ProcessUtils.h"
 #include "StringUtils.h"
 #include "StringUtils.h"
+#include "Thread.h"
 #include "XMLFile.h"
 #include "XMLFile.h"
 
 
 #include <cstdio>
 #include <cstdio>
@@ -44,36 +47,40 @@ enum ShaderType
     Both
     Both
 };
 };
 
 
-struct Variation
+
+struct Parameter
 {
 {
-    Variation()
+    Parameter()
     {
     {
     }
     }
     
     
-    Variation(const String& name, bool isOption) :
+    Parameter(const String& name, unsigned index) :
         name_(name),
         name_(name),
-        option_(isOption)
-    {
-    }
-    
-    void AddDefine(const String& def)
-    {
-        defines_.Push(def);
-    }
-    
-    void AddExclude(const String& excl)
+        index_(index)
     {
     {
-        excludes_.Push(excl);
     }
     }
     
     
-    void AddInclude(const String& incl)
+    String name_;
+    unsigned index_;
+};
+
+struct Parameters
+{
+    Vector<Parameter> vsParams_;
+    Vector<Parameter> psParams_;
+    Vector<Parameter> textureUnits_;
+};
+
+struct Variation
+{
+    Variation()
     {
     {
-        includes_.Push(incl);
     }
     }
     
     
-    void AddRequire(const String& req)
+    Variation(const String& name, bool isOption) :
+        name_(name),
+        option_(isOption)
     {
     {
-        requires_.Push(req);
     }
     }
     
     
     String name_;
     String name_;
@@ -84,6 +91,16 @@ struct Variation
     bool option_;
     bool option_;
 };
 };
 
 
+struct CompiledVariation
+{
+    ShaderType type_;
+    String name_;
+    Vector<String> defines_;
+    PODVector<unsigned char> byteCode_;
+    Parameters parameters_;
+    String errorMsg_;
+};
+
 struct Shader
 struct Shader
 {
 {
     Shader(const String& name, ShaderType type) :
     Shader(const String& name, ShaderType type) :
@@ -92,55 +109,11 @@ struct Shader
     {
     {
     }
     }
     
     
-    void AddVariation(const Variation& var)
-    {
-        variations_.Push(var);
-    }
-    
     String name_;
     String name_;
     ShaderType type_;
     ShaderType type_;
     Vector<Variation> variations_;
     Vector<Variation> variations_;
 };
 };
 
 
-struct Parameter
-{
-    String name_;
-    unsigned index_;
-};
-
-struct Parameters
-{
-    void AddVSParam(const String& name, unsigned index)
-    {
-        Parameter newParam;
-        newParam.name_ = name;
-        newParam.index_ = index;
-        
-        vsParams_.Push(newParam);
-    }
-    
-    void AddPSParam(const String& name, unsigned index)
-    {
-        Parameter newParam;
-        newParam.name_ = name;
-        newParam.index_ = index;
-        
-        psParams_.Push(newParam);
-    }
-    
-    void AddTextureUnit(const String& name, unsigned index)
-    {
-        Parameter newParam;
-        newParam.name_ = name;
-        newParam.index_ = index;
-        
-        textureUnits_.Push(newParam);
-    }
-    
-    Vector<Parameter> vsParams_;
-    Vector<Parameter> psParams_;
-    Vector<Parameter> textureUnits_;
-};
 
 
 SharedPtr<Context> context_(new Context());
 SharedPtr<Context> context_(new Context());
 SharedPtr<FileSystem> fileSystem_(new FileSystem(context_));
 SharedPtr<FileSystem> fileSystem_(new FileSystem(context_));
@@ -152,11 +125,44 @@ Map<String, unsigned> psParams_;
 Map<String, unsigned> textureUnits_;
 Map<String, unsigned> textureUnits_;
 Vector<String> defines_;
 Vector<String> defines_;
 bool useSM3_ = false;
 bool useSM3_ = false;
+volatile bool compileFailed_ = false;
+
+List<CompiledVariation*> workList_;
+Mutex workMutex_;
+Mutex globalParamMutex_;
+String hlslCode_;
 
 
 int main(int argc, char** argv);
 int main(int argc, char** argv);
 void Run(const Vector<String>& arguments);
 void Run(const Vector<String>& arguments);
 void CompileVariations(const Shader& baseShader, XMLElement& shaders);
 void CompileVariations(const Shader& baseShader, XMLElement& shaders);
-bool Compile(ShaderType type, const String& hlslCode, const String& output, const Vector<String>& defines, Parameters& params);
+void Compile(CompiledVariation* variation);
+
+class WorkerThread : public RefCounted, public Thread
+{
+public:
+    void ThreadFunction()
+    {
+        for (;;)
+        {
+            CompiledVariation* workItem = 0;
+            {
+                MutexLock lock(workMutex_);
+                if (!workList_.Empty())
+                {
+                    workItem = workList_.Front();
+                    workList_.Erase(workList_.Begin());
+                    PrintLine("Compiling shader " + workItem->name_);
+                }
+            }
+            if (!workItem)
+                return;
+            
+            // If compile(s) failed, just empty the list, but do not compile more
+            if (!compileFailed_)
+                Compile(workItem);
+        }
+    }
+};
 
 
 class IncludeHandler : public ID3DXInclude
 class IncludeHandler : public ID3DXInclude
 {
 {
@@ -164,15 +170,15 @@ public:
     STDMETHOD(Open)(D3DXINCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes)
     STDMETHOD(Open)(D3DXINCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes)
     {
     {
         String fileName = inDir_ + String((const char*)pFileName);
         String fileName = inDir_ + String((const char*)pFileName);
-        SharedPtr<File> file(new File(context_, fileName));
-        if (!file->IsOpen())
+        File file(context_, fileName);
+        if (!file.IsOpen())
             return E_FAIL;
             return E_FAIL;
         
         
-        unsigned fileSize = file->GetSize();
+        unsigned fileSize = file.GetSize();
         void* fileData = new unsigned char[fileSize];
         void* fileData = new unsigned char[fileSize];
         *pBytes = fileSize;
         *pBytes = fileSize;
         *ppData = fileData;
         *ppData = fileData;
-        file->Read(fileData, fileSize);
+        file.Read(fileData, fileSize);
         
         
         return S_OK;
         return S_OK;
     }
     }
@@ -191,7 +197,7 @@ int main(int argc, char** argv)
     for (int i = 1; i < argc; ++i)
     for (int i = 1; i < argc; ++i)
     {
     {
         String argument(argv[i]);
         String argument(argv[i]);
-        arguments.Push(argument.Replace('/', '\\'));
+        arguments.Push(GetInternalPath(argument));
     }
     }
     
     
     Run(arguments);
     Run(arguments);
@@ -209,7 +215,7 @@ void Run(const Vector<String>& arguments)
         );
         );
     }
     }
     
     
-    unsigned pos = arguments[0].FindLast('\\');
+    unsigned pos = arguments[0].FindLast('/');
     if (pos != String::NPOS)
     if (pos != String::NPOS)
     {
     {
         inDir_ = arguments[0].Substring(0, pos);
         inDir_ = arguments[0].Substring(0, pos);
@@ -253,7 +259,7 @@ void Run(const Vector<String>& arguments)
     XMLElement shader = shaders.GetChildElement("shader");
     XMLElement shader = shaders.GetChildElement("shader");
     while (shader)
     while (shader)
     {
     {
-        bool WriteOutput = false;
+        bool writeOutput = false;
         
         
         String source = shader.GetString("name");
         String source = shader.GetString("name");
         
         
@@ -263,8 +269,10 @@ void Run(const Vector<String>& arguments)
             compileType = VS;
             compileType = VS;
         if ((type == "PS") || (type == "ps"))
         if ((type == "PS") || (type == "ps"))
             compileType = PS;
             compileType = PS;
-        if ((compileType == Both) || (compileType == PS))
-            WriteOutput = true;
+        
+        // If both VS & PS are defined separately, we should only write output once both have been compiled
+        if (compileType != VS)
+            writeOutput = true;
         
         
         Shader baseShader(source, compileType);
         Shader baseShader(source, compileType);
         
         
@@ -280,57 +288,49 @@ void Run(const Vector<String>& arguments)
                 
                 
                 String simpleDefine = variation.GetString("define");
                 String simpleDefine = variation.GetString("define");
                 if (!simpleDefine.Empty())
                 if (!simpleDefine.Empty())
-                    newVar.AddDefine(simpleDefine);
+                    newVar.defines_.Push(simpleDefine);
                     
                     
                 String simpleExclude = variation.GetString("exclude");
                 String simpleExclude = variation.GetString("exclude");
                 if (!simpleExclude.Empty())
                 if (!simpleExclude.Empty())
-                    newVar.AddExclude(simpleExclude);
+                    newVar.excludes_.Push(simpleExclude);
                 
                 
                 String simpleInclude = variation.GetString("include");
                 String simpleInclude = variation.GetString("include");
                 if (!simpleInclude.Empty())
                 if (!simpleInclude.Empty())
-                    newVar.AddInclude(simpleInclude);
+                    newVar.includes_.Push(simpleInclude);
                 
                 
                 String simpleRequire = variation.GetString("require");
                 String simpleRequire = variation.GetString("require");
                 if (!simpleRequire.Empty())
                 if (!simpleRequire.Empty())
-                    newVar.AddRequire(simpleRequire);
+                    newVar.requires_.Push(simpleRequire);
                 
                 
                 XMLElement define = variation.GetChildElement("define");
                 XMLElement define = variation.GetChildElement("define");
                 while (define)
                 while (define)
                 {
                 {
-                    String name = define.GetString("name");
-                    newVar.AddDefine(name);
-                    
+                    newVar.defines_.Push(define.GetString("name"));
                     define = define.GetNextElement("define");
                     define = define.GetNextElement("define");
                 }
                 }
                 
                 
                 XMLElement exclude = variation.GetChildElement("exclude");
                 XMLElement exclude = variation.GetChildElement("exclude");
                 while (exclude)
                 while (exclude)
                 {
                 {
-                    String name = exclude.GetString("name");
-                    newVar.AddExclude(name);
-                    
+                    newVar.excludes_.Push(exclude.GetString("name"));
                     exclude = exclude.GetNextElement("exclude");
                     exclude = exclude.GetNextElement("exclude");
                 }
                 }
                 
                 
                 XMLElement include = variation.GetChildElement("include");
                 XMLElement include = variation.GetChildElement("include");
                 while (include)
                 while (include)
                 {
                 {
-                    String name = include.GetString("name");
-                    newVar.AddInclude(name);
-                    
+                    newVar.includes_.Push(include.GetString("name"));
                     include = include.GetNextElement("include");
                     include = include.GetNextElement("include");
                 }
                 }
                 
                 
                 XMLElement require = variation.GetChildElement("require");
                 XMLElement require = variation.GetChildElement("require");
                 while (require)
                 while (require)
                 {
                 {
-                    String name = require.GetString("name");
-                    newVar.AddRequire(name);
-                    
+                    newVar.requires_.Push(require.GetString("name"));
                     require = require.GetNextElement("require");
                     require = require.GetNextElement("require");
                 }
                 }
                 
                 
-                baseShader.AddVariation(newVar);
+                baseShader.variations_.Push(newVar);
             }
             }
             
             
             variation = variation.GetNextElement();
             variation = variation.GetNextElement();
@@ -346,10 +346,9 @@ void Run(const Vector<String>& arguments)
             CompileVariations(baseShader, outShaders);
             CompileVariations(baseShader, outShaders);
         }
         }
         
         
-        if (WriteOutput)
+        if (writeOutput)
         {
         {
             String outFileName = outDir_ + inDir_ + source + ".xml";
             String outFileName = outDir_ + inDir_ + source + ".xml";
-            remove(outFileName.CString());
             
             
             // Add global parameter & texture sampler definitions
             // Add global parameter & texture sampler definitions
             {
             {
@@ -416,10 +415,10 @@ void Run(const Vector<String>& arguments)
 void CompileVariations(const Shader& baseShader, XMLElement& shaders)
 void CompileVariations(const Shader& baseShader, XMLElement& shaders)
 {
 {
     unsigned combinations = 1;
     unsigned combinations = 1;
-    PODVector<unsigned> compiled;
+    PODVector<unsigned> usedCombinations;
     bool hasVariations = false;
     bool hasVariations = false;
     Map<String, unsigned> nameToIndex;
     Map<String, unsigned> nameToIndex;
-    String hlslCode;
+    Vector<CompiledVariation> compiledVariations;
     
     
     const Vector<Variation>& variations = baseShader.variations_;
     const Vector<Variation>& variations = baseShader.variations_;
     
     
@@ -427,14 +426,16 @@ void CompileVariations(const Shader& baseShader, XMLElement& shaders)
         ErrorExit("Maximum amount of variations exceeded");
         ErrorExit("Maximum amount of variations exceeded");
     
     
     // Load the shader source code
     // Load the shader source code
-    String inputFileName = inDir_ + baseShader.name_ + ".hlsl";
-    SharedPtr<File> hlslFile(new File(context_, inputFileName));
-    if (!hlslFile->IsOpen())
-        ErrorExit("Could not open input file " + inputFileName);
-    
-    while (!hlslFile->IsEof())
-        hlslCode += hlslFile->ReadLine() + "\n";
-    hlslFile->Close();
+    {
+        String inputFileName = inDir_ + baseShader.name_ + ".hlsl";
+        File hlslFile(context_, inputFileName);
+        if (!hlslFile.IsOpen())
+            ErrorExit("Could not open input file " + inputFileName);
+        
+        hlslCode_.Clear();
+        while (!hlslFile.IsEof())
+            hlslCode_ += hlslFile.ReadLine() + "\n";
+    }
     
     
     for (unsigned i = 0; i < variations.Size(); ++i)
     for (unsigned i = 0; i < variations.Size(); ++i)
     {
     {
@@ -529,9 +530,9 @@ void CompileVariations(const Shader& baseShader, XMLElement& shaders)
         
         
         // Check that this combination is unique
         // Check that this combination is unique
         bool unique = true;
         bool unique = true;
-        for (unsigned j = 0; j < compiled.Size(); ++j)
+        for (unsigned j = 0; j < usedCombinations.Size(); ++j)
         {
         {
-            if (compiled[j] == active)
+            if (usedCombinations[j] == active)
             {
             {
                 unique = false;
                 unique = false;
                 break;
                 break;
@@ -564,69 +565,89 @@ void CompileVariations(const Shader& baseShader, XMLElement& shaders)
                 }
                 }
             }
             }
             
             
-            Parameters params;
+            CompiledVariation compile;
+            compile.type_ = baseShader.type_;
+            compile.name_ = outName;
+            compile.defines_ = defines;
             
             
-            bool ok = Compile(baseShader.type_, hlslCode, outName, defines, params);
+            compiledVariations.Push(compile);
+            usedCombinations.Push(active);
+        }
+    }
+    
+    // Prepare the work list
+    // (all variations must be created first, so that vector resize does not change pointers)
+    for (unsigned i = 0; i < compiledVariations.Size(); ++i)
+        workList_.Push(&compiledVariations[i]);
+    
+    // Create and start worker threads
+    Vector<SharedPtr<WorkerThread> > workerThreads;
+    workerThreads.Resize(GetNumCPUCores());
+    for (unsigned i = 0; i < workerThreads.Size(); ++i)
+    {
+        workerThreads[i] = new WorkerThread();
+        workerThreads[i]->Start();
+    }
+    // This will wait until the thread functions have stopped
+    for (unsigned i = 0; i < workerThreads.Size(); ++i)
+        workerThreads[i]->Stop();
+    
+    // Build the XML output
+    for (unsigned i = 0; i < compiledVariations.Size(); ++i)
+    {
+        if (!compiledVariations[i].errorMsg_.Empty())
+            ErrorExit("Failed to compile shader " + compiledVariations[i].name_ + ": " + compiledVariations[i].errorMsg_);
+        
+        Parameters& params = compiledVariations[i].parameters_;
+        
+        XMLElement shader = shaders.CreateChildElement("shader");
+        shader.SetString("name", compiledVariations[i].name_);
+        switch (baseShader.type_)
+        {
+        case VS:
+            shader.SetString("type", "vs");
+            for (unsigned j = 0; j < params.vsParams_.Size(); ++j)
+            {
+                XMLElement vsParam = shader.CreateChildElement("parameter");
+                vsParam.SetString("name", params.vsParams_[j].name_);
+            }
+            break;
             
             
-            // If shader was unnecessary (for example SM2 does not support HQ variations)
-            // no output may have been produced. Skip in that case.
-            if (ok)
+        case PS:
+            shader.SetString("type", "ps");
+            for (unsigned j = 0; j < params.psParams_.Size(); ++j)
             {
             {
-                XMLElement shader = shaders.CreateChildElement("shader");
-                shader.SetString("name", outName);
-                switch (baseShader.type_)
-                {
-                case VS:
-                    shader.SetString("type", "vs");
-                    for (unsigned j = 0; j < params.vsParams_.Size(); ++j)
-                    {
-                        XMLElement vsParam = shader.CreateChildElement("parameter");
-                        vsParam.SetString("name", params.vsParams_[j].name_);
-                    }
-                    break;
-                    
-                case PS:
-                    shader.SetString("type", "ps");
-                    for (unsigned j = 0; j < params.psParams_.Size(); ++j)
-                    {
-                        XMLElement psParam = shader.CreateChildElement("parameter");
-                        psParam.SetString("name", params.psParams_[j].name_);
-                    }
-                    for (unsigned j = 0; j < params.textureUnits_.Size(); ++j)
-                    {
-                        XMLElement texture = shader.CreateChildElement("textureunit");
-                        texture.SetString("name", params.textureUnits_[j].name_);
-                    }
-                    break;
-                }
-                
-                compiled.Push(active);
+                XMLElement psParam = shader.CreateChildElement("parameter");
+                psParam.SetString("name", params.psParams_[j].name_);
+            }
+            for (unsigned j = 0; j < params.textureUnits_.Size(); ++j)
+            {
+                XMLElement texture = shader.CreateChildElement("textureunit");
+                texture.SetString("name", params.textureUnits_[j].name_);
             }
             }
+            break;
         }
         }
     }
     }
 }
 }
 
 
-bool Compile(ShaderType type, const String& hlslCode, const String& output, const Vector<String>& defines,
-    Parameters& params)
+void Compile(CompiledVariation* variation)
 {
 {
     IncludeHandler includeHandler;
     IncludeHandler includeHandler;
     PODVector<D3DXMACRO> macros;
     PODVector<D3DXMACRO> macros;
     
     
-    String value = "1";
-    
     // Insert variation-specific and global defines
     // Insert variation-specific and global defines
-    for (unsigned i = 0; i < defines.Size(); ++i)
+    for (unsigned i = 0; i < variation->defines_.Size(); ++i)
     {
     {
         D3DXMACRO macro;
         D3DXMACRO macro;
-        macro.Name = defines[i].CString();
-        macro.Definition = value.CString();
+        macro.Name = variation->defines_[i].CString();
+        macro.Definition = "1";
         macros.Push(macro);
         macros.Push(macro);
     }
     }
     for (unsigned i = 0; i < defines_.Size(); ++i)
     for (unsigned i = 0; i < defines_.Size(); ++i)
     {
     {
         D3DXMACRO macro;
         D3DXMACRO macro;
         macro.Name = defines_[i].CString();
         macro.Name = defines_[i].CString();
-        macro.Definition = value.CString();
+        macro.Definition = "1";
         macros.Push(macro);
         macros.Push(macro);
     }
     }
     
     
@@ -645,7 +666,7 @@ bool Compile(ShaderType type, const String& hlslCode, const String& output, cons
     String entryPoint;
     String entryPoint;
     unsigned flags = 0;
     unsigned flags = 0;
     
     
-    if (type == VS)
+    if (variation->type_ == VS)
     {
     {
         entryPoint = "VS";
         entryPoint = "VS";
         if (!useSM3_)
         if (!useSM3_)
@@ -675,25 +696,34 @@ bool Compile(ShaderType type, const String& hlslCode, const String& output, cons
         }
         }
     }
     }
     
     
-    String outFileName = outDir_ + inDir_ + output + extension;
+    String outFileName = outDir_ + inDir_ + variation->name_ + extension;
     
     
     // Compile using D3DX
     // Compile using D3DX
-    PrintLine("Compiling shader " + outFileName);
-    HRESULT hr = D3DXCompileShader(hlslCode.CString(), hlslCode.Length(), &macros.Front(), &includeHandler, 
+    HRESULT hr = D3DXCompileShader(hlslCode_.CString(), hlslCode_.Length(), &macros.Front(), &includeHandler, 
         entryPoint.CString(), profile.CString(), flags, &shaderCode, &errorMsgs, &constantTable);
         entryPoint.CString(), profile.CString(), flags, &shaderCode, &errorMsgs, &constantTable);
     if (FAILED(hr))
     if (FAILED(hr))
     {
     {
-        String error((const char*)errorMsgs->GetBufferPointer(), errorMsgs->GetBufferSize());
-        errorMsgs->Release();
-        ErrorExit("Failed to compile shader " + outFileName + ": " + error);
+        variation->errorMsg_ = String((const char*)errorMsgs->GetBufferPointer(), errorMsgs->GetBufferSize());
+        compileFailed_ = true;
     }
     }
-    
-    // Write the shader bytecode
-    SharedPtr<File> outFile(new File(context_, outFileName, FILE_WRITE));
-    if (outFile->IsOpen())
-        outFile->Write(shaderCode->GetBufferPointer(), shaderCode->GetBufferSize());
     else
     else
-        ErrorExit("Failed to write output file " + outFileName);
+    {
+        unsigned dataSize = shaderCode->GetBufferSize();
+        if (dataSize)
+        {
+            variation->byteCode_.Resize(dataSize);
+            memcpy(&variation->byteCode_[0], shaderCode->GetBufferPointer(), dataSize);
+        }
+        
+        File outFile(context_, outFileName, FILE_WRITE);
+        if (outFile.IsOpen())
+            outFile.Write(shaderCode->GetBufferPointer(), dataSize);
+        else
+        {
+            variation->errorMsg_ = "Failed to write output file " + outFileName;
+            compileFailed_ = true;
+        }
+    }
     
     
     // Parse the constant table for constants and texture units
     // Parse the constant table for constants and texture units
     D3DXCONSTANTTABLE_DESC desc;
     D3DXCONSTANTTABLE_DESC desc;
@@ -711,13 +741,15 @@ bool Compile(ShaderType type, const String& hlslCode, const String& output, cons
         // Check if the parameter is a constant or a texture sampler
         // Check if the parameter is a constant or a texture sampler
         bool isSampler = (name[0] == 's');
         bool isSampler = (name[0] == 's');
         name = name.Substring(1);
         name = name.Substring(1);
-    
+        
+        MutexLock lock(globalParamMutex_);
+        
         if (isSampler)
         if (isSampler)
         {
         {
             // Skip if it's a G-buffer sampler
             // Skip if it's a G-buffer sampler
             if (name.Find("Buffer") == String::NPOS)
             if (name.Find("Buffer") == String::NPOS)
             {
             {
-                params.AddTextureUnit(name, index);
+                variation->parameters_.textureUnits_.Push(Parameter(name, index));
                 
                 
                 if (textureUnits_.Find(name) != textureUnits_.End())
                 if (textureUnits_.Find(name) != textureUnits_.End())
                 {
                 {
@@ -730,9 +762,9 @@ bool Compile(ShaderType type, const String& hlslCode, const String& output, cons
         }
         }
         else
         else
         {
         {
-            if (type == VS)
+            if (variation->type_ == VS)
             {
             {
-                params.AddVSParam(name, index);
+                variation->parameters_.vsParams_.Push(Parameter(name, index));
                 
                 
                 if (vsParams_.Find(name) != vsParams_.End())
                 if (vsParams_.Find(name) != vsParams_.End())
                 {
                 {
@@ -744,7 +776,7 @@ bool Compile(ShaderType type, const String& hlslCode, const String& output, cons
             }
             }
             else
             else
             {
             {
-                params.AddPSParam(name, index);
+                variation->parameters_.psParams_.Push(Parameter(name, index));
                 
                 
                 if (psParams_.Find(name) != psParams_.End())
                 if (psParams_.Find(name) != psParams_.End())
                 {
                 {
@@ -761,6 +793,6 @@ bool Compile(ShaderType type, const String& hlslCode, const String& output, cons
         shaderCode->Release();
         shaderCode->Release();
     if (constantTable)
     if (constantTable)
         constantTable->Release();
         constantTable->Release();
-    
-    return true;
+    if (errorMsgs)
+        errorMsgs->Release();
 }
 }