Merge branch '1.5' into dotnet7
# Conflicts: # Source/Editor/Managed/ManagedEditor.Internal.cpp # Source/Engine/Core/Config/LayersAndTagsSettings.cs
This commit is contained in:
@@ -237,6 +237,41 @@ namespace Flax.Build.Bindings
|
||||
return $"({typeInfo}){value}";
|
||||
}
|
||||
|
||||
public static void GenerateCppVirtualWrapperCallBaseMethod(BuildData buildData, StringBuilder contents, VirtualClassInfo classInfo, FunctionInfo functionInfo, string scriptVTableBase, string scriptVTableOffset)
|
||||
{
|
||||
contents.AppendLine(" // Prevent stack overflow by calling native base method");
|
||||
if (buildData.Toolchain is Platforms.UnixToolchain)
|
||||
{
|
||||
// Clang compiler
|
||||
// TODO: secure VTableFunctionInjector with mutex (even at cost of performance)
|
||||
contents.AppendLine($" {functionInfo.UniqueName}_Signature funcPtr = &{classInfo.NativeName}::{functionInfo.Name};");
|
||||
contents.AppendLine($" VTableFunctionInjector vtableInjector(object, *(void**)&funcPtr, {scriptVTableBase}[{scriptVTableOffset} + 2]); // TODO: this is not thread-safe");
|
||||
if (classInfo is InterfaceInfo)
|
||||
{
|
||||
contents.Append($" return (({classInfo.NativeName}*)(void*)object)->{functionInfo.Name}(");
|
||||
}
|
||||
else
|
||||
{
|
||||
contents.Append(" return (object->*funcPtr)(");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// MSVC or other compiler
|
||||
contents.Append($" return (this->**({functionInfo.UniqueName}_Internal_Signature*)&{scriptVTableBase}[{scriptVTableOffset} + 2])(");
|
||||
}
|
||||
bool separator = false;
|
||||
for (var i = 0; i < functionInfo.Parameters.Count; i++)
|
||||
{
|
||||
var parameterInfo = functionInfo.Parameters[i];
|
||||
if (separator)
|
||||
contents.Append(", ");
|
||||
separator = true;
|
||||
contents.Append(parameterInfo.Name);
|
||||
}
|
||||
contents.AppendLine(");");
|
||||
}
|
||||
|
||||
private static string GenerateCppGetNativeClass(BuildData buildData, TypeInfo typeInfo, ApiTypeInfo caller, FunctionInfo functionInfo)
|
||||
{
|
||||
// Optimal path for in-build types
|
||||
@@ -1281,19 +1316,7 @@ namespace Flax.Build.Bindings
|
||||
|
||||
contents.AppendLine(" if (WrapperCallInstance == object)");
|
||||
contents.AppendLine(" {");
|
||||
contents.AppendLine(" // Prevent stack overflow by calling native base method");
|
||||
contents.AppendLine(" const auto scriptVTableBase = managedTypePtr->Script.ScriptVTableBase;");
|
||||
contents.Append($" return (this->**({functionInfo.UniqueName}_Internal_Signature*)&scriptVTableBase[{scriptVTableOffset} + 2])(");
|
||||
separator = false;
|
||||
for (var i = 0; i < functionInfo.Parameters.Count; i++)
|
||||
{
|
||||
var parameterInfo = functionInfo.Parameters[i];
|
||||
if (separator)
|
||||
contents.Append(", ");
|
||||
separator = true;
|
||||
contents.Append(parameterInfo.Name);
|
||||
}
|
||||
contents.AppendLine(");");
|
||||
GenerateCppVirtualWrapperCallBaseMethod(buildData, contents, classInfo, functionInfo, "managedTypePtr->Script.ScriptVTableBase", scriptVTableOffset);
|
||||
contents.AppendLine(" }");
|
||||
contents.AppendLine(" auto scriptVTable = (MMethod**)managedTypePtr->Script.ScriptVTable;");
|
||||
contents.AppendLine($" ASSERT(scriptVTable && scriptVTable[{scriptVTableOffset}]);");
|
||||
@@ -1410,7 +1433,11 @@ namespace Flax.Build.Bindings
|
||||
}
|
||||
var t = functionInfo.IsConst ? " const" : string.Empty;
|
||||
contents.AppendLine($" typedef {functionInfo.ReturnType} ({classInfo.NativeName}::*{functionInfo.UniqueName}_Signature)({thunkParams}){t};");
|
||||
contents.AppendLine($" typedef {functionInfo.ReturnType} ({classInfo.NativeName}Internal::*{functionInfo.UniqueName}_Internal_Signature)({thunkParams}){t};");
|
||||
if (!(buildData.Toolchain is Platforms.UnixToolchain))
|
||||
{
|
||||
// MSVC or other compiler
|
||||
contents.AppendLine($" typedef {functionInfo.ReturnType} ({classInfo.NativeName}Internal::*{functionInfo.UniqueName}_Internal_Signature)({thunkParams}){t};");
|
||||
}
|
||||
}
|
||||
contents.AppendLine("");
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Flax.Build.Graph;
|
||||
using Flax.Build.NativeCpp;
|
||||
|
||||
namespace Flax.Build
|
||||
{
|
||||
@@ -256,6 +257,11 @@ namespace Flax.Build
|
||||
if (targets.Length == 0)
|
||||
Log.Warning("No targets to build");
|
||||
|
||||
using (new ProfileEventScope("LoadIncludesCache"))
|
||||
{
|
||||
IncludesCache.LoadCache();
|
||||
}
|
||||
|
||||
// Create task graph for building all targets
|
||||
var graph = new TaskGraph(project.ProjectFolderPath);
|
||||
foreach (var target in targets)
|
||||
@@ -395,6 +401,11 @@ namespace Flax.Build
|
||||
}
|
||||
}
|
||||
|
||||
using (new ProfileEventScope("SaveIncludesCache"))
|
||||
{
|
||||
IncludesCache.SaveCache();
|
||||
}
|
||||
|
||||
foreach (var target in targets)
|
||||
{
|
||||
target.PostBuild();
|
||||
|
||||
@@ -13,9 +13,153 @@ namespace Flax.Build.NativeCpp
|
||||
/// </summary>
|
||||
public static class IncludesCache
|
||||
{
|
||||
private static readonly Dictionary<string, string[]> DirectIncludesCache = new Dictionary<string, string[]>();
|
||||
private static readonly Dictionary<string, string[]> AllIncludesCache = new Dictionary<string, string[]>();
|
||||
private static Dictionary<string, string[]> DirectIncludesCache = new Dictionary<string, string[]>();
|
||||
private static Dictionary<string, string[]> AllIncludesCache = new Dictionary<string, string[]>();
|
||||
private static Dictionary<string, DateTime> DirectIncludesTimestampCache = new Dictionary<string, DateTime>();
|
||||
private static Dictionary<string, DateTime> AllIncludesTimestampCache = new Dictionary<string, DateTime>();
|
||||
private static Dictionary<string, bool> FileExistsCache = new Dictionary<string, bool>();
|
||||
private static Dictionary<string, DateTime> FileTimestampCache = new Dictionary<string, DateTime>();
|
||||
private static readonly string IncludeToken = "include";
|
||||
private static string CachePath;
|
||||
|
||||
public static void LoadCache()
|
||||
{
|
||||
CachePath = Path.Combine(Globals.Root, Configuration.IntermediateFolder, "IncludesCache.cache");
|
||||
if (!File.Exists(CachePath))
|
||||
return;
|
||||
|
||||
using (var stream = new FileStream(CachePath, FileMode.Open))
|
||||
using (var reader = new BinaryReader(stream))
|
||||
{
|
||||
int version = reader.ReadInt32();
|
||||
if (version != 1)
|
||||
return;
|
||||
|
||||
// DirectIncludesCache
|
||||
{
|
||||
int count = reader.ReadInt32();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
string key = reader.ReadString();
|
||||
string[] values = new string[reader.ReadInt32()];
|
||||
for (int j = 0; j < values.Length; j++)
|
||||
values[j] = reader.ReadString();
|
||||
|
||||
DirectIncludesCache.Add(key, values);
|
||||
}
|
||||
}
|
||||
|
||||
// AllIncludesCache
|
||||
{
|
||||
int count = reader.ReadInt32();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
string key = reader.ReadString();
|
||||
string[] values = new string[reader.ReadInt32()];
|
||||
for (int j = 0; j < values.Length; j++)
|
||||
values[j] = reader.ReadString();
|
||||
|
||||
AllIncludesCache.Add(key, values);
|
||||
}
|
||||
}
|
||||
|
||||
// DirectIncludesTimestampCache
|
||||
{
|
||||
int count = reader.ReadInt32();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
string key = reader.ReadString();
|
||||
DateTime value = new DateTime(reader.ReadInt64());
|
||||
DirectIncludesTimestampCache.Add(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
// AllIncludesTimestampCache
|
||||
{
|
||||
int count = reader.ReadInt32();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
string key = reader.ReadString();
|
||||
DateTime value = new DateTime(reader.ReadInt64());
|
||||
AllIncludesTimestampCache.Add(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SaveCache()
|
||||
{
|
||||
using (var stream = new FileStream(CachePath, FileMode.Create))
|
||||
using (var writer = new BinaryWriter(stream))
|
||||
{
|
||||
// Version
|
||||
writer.Write(1);
|
||||
|
||||
// DirectIncludesCache
|
||||
{
|
||||
writer.Write(DirectIncludesCache.Count);
|
||||
foreach (KeyValuePair<string, string[]> kvp in DirectIncludesCache)
|
||||
{
|
||||
writer.Write(kvp.Key);
|
||||
writer.Write(kvp.Value.Length);
|
||||
foreach (var value in kvp.Value)
|
||||
writer.Write(value);
|
||||
}
|
||||
}
|
||||
|
||||
// AllIncludesCache
|
||||
{
|
||||
writer.Write(AllIncludesCache.Count);
|
||||
foreach (KeyValuePair<string, string[]> kvp in AllIncludesCache)
|
||||
{
|
||||
writer.Write(kvp.Key);
|
||||
writer.Write(kvp.Value.Length);
|
||||
foreach (var value in kvp.Value)
|
||||
writer.Write(value);
|
||||
}
|
||||
}
|
||||
|
||||
// DirectIncludesTimestampCache
|
||||
{
|
||||
writer.Write(DirectIncludesTimestampCache.Count);
|
||||
foreach (KeyValuePair<string, DateTime> kvp in DirectIncludesTimestampCache)
|
||||
{
|
||||
writer.Write(kvp.Key);
|
||||
writer.Write(kvp.Value.Ticks);
|
||||
}
|
||||
}
|
||||
|
||||
// AllIncludesTimestampCache
|
||||
{
|
||||
writer.Write(AllIncludesTimestampCache.Count);
|
||||
foreach (KeyValuePair<string, DateTime> kvp in AllIncludesTimestampCache)
|
||||
{
|
||||
writer.Write(kvp.Key);
|
||||
writer.Write(kvp.Value.Ticks);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool FileExists(string path)
|
||||
{
|
||||
if (FileExistsCache.TryGetValue(path, out bool result))
|
||||
return result;
|
||||
|
||||
result = File.Exists(path);
|
||||
FileExistsCache.Add(path, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static DateTime FileLastWriteTime(string path)
|
||||
{
|
||||
if (FileTimestampCache.TryGetValue(path, out DateTime result))
|
||||
return result;
|
||||
|
||||
result = File.GetLastWriteTime(path);
|
||||
FileTimestampCache.Add(path, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds all included files by the source file (including dependencies).
|
||||
@@ -24,12 +168,24 @@ namespace Flax.Build.NativeCpp
|
||||
/// <returns>The list of included files by this file. Not null nut may be empty.</returns>
|
||||
public static string[] FindAllIncludedFiles(string sourceFile)
|
||||
{
|
||||
DateTime? lastModified = null;
|
||||
|
||||
// Try hit the cache
|
||||
string[] result;
|
||||
if (AllIncludesCache.TryGetValue(sourceFile, out result))
|
||||
return result;
|
||||
{
|
||||
if (AllIncludesTimestampCache.TryGetValue(sourceFile, out var cachedTimestamp))
|
||||
{
|
||||
lastModified = FileLastWriteTime(sourceFile);
|
||||
if (lastModified == cachedTimestamp)
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!File.Exists(sourceFile))
|
||||
AllIncludesCache.Remove(sourceFile);
|
||||
AllIncludesTimestampCache.Remove(sourceFile);
|
||||
}
|
||||
|
||||
if (!FileExists(sourceFile))
|
||||
throw new Exception(string.Format("Cannot scan file \"{0}\" for includes because it does not exist.", sourceFile));
|
||||
|
||||
//using (new ProfileEventScope("FindAllIncludedFiles"))
|
||||
@@ -44,6 +200,9 @@ namespace Flax.Build.NativeCpp
|
||||
result = includedFiles.ToArray();
|
||||
AllIncludesCache.Add(sourceFile, result);
|
||||
|
||||
if (!AllIncludesTimestampCache.ContainsKey(sourceFile))
|
||||
AllIncludesTimestampCache.Add(sourceFile, lastModified ?? File.GetLastWriteTime(sourceFile));
|
||||
|
||||
/*Log.Info("File includes for " + sourceFile);
|
||||
foreach (var e in result)
|
||||
{
|
||||
@@ -72,10 +231,22 @@ namespace Flax.Build.NativeCpp
|
||||
|
||||
private static string[] GetDirectIncludes(string sourceFile)
|
||||
{
|
||||
DateTime? lastModified = null;
|
||||
|
||||
// Try hit the cache
|
||||
string[] result;
|
||||
if (DirectIncludesCache.TryGetValue(sourceFile, out result))
|
||||
return result;
|
||||
{
|
||||
if (DirectIncludesTimestampCache.TryGetValue(sourceFile, out var cachedTimestamp))
|
||||
{
|
||||
lastModified = FileLastWriteTime(sourceFile);
|
||||
if (lastModified == cachedTimestamp)
|
||||
return result;
|
||||
}
|
||||
|
||||
DirectIncludesCache.Remove(sourceFile);
|
||||
DirectIncludesTimestampCache.Remove(sourceFile);
|
||||
}
|
||||
|
||||
// Find all files included directly
|
||||
var includedFiles = new HashSet<string>();
|
||||
@@ -152,11 +323,11 @@ namespace Flax.Build.NativeCpp
|
||||
|
||||
// Relative to the workspace root
|
||||
var includedFilePath = Path.Combine(Globals.Root, "Source", includedFile);
|
||||
if (!File.Exists(includedFilePath))
|
||||
if (!FileExists(includedFilePath))
|
||||
{
|
||||
// Relative to the source file
|
||||
includedFilePath = Path.Combine(sourceFileFolder, includedFile);
|
||||
if (!File.Exists(includedFilePath))
|
||||
if (!FileExists(includedFilePath))
|
||||
{
|
||||
// Relative to any of the included project workspaces
|
||||
var project = Globals.Project;
|
||||
@@ -164,7 +335,7 @@ namespace Flax.Build.NativeCpp
|
||||
foreach (var reference in project.References)
|
||||
{
|
||||
includedFilePath = Path.Combine(reference.Project.ProjectFolderPath, "Source", includedFile);
|
||||
if (File.Exists(includedFilePath))
|
||||
if (FileExists(includedFilePath))
|
||||
{
|
||||
isValid = true;
|
||||
break;
|
||||
@@ -191,6 +362,8 @@ namespace Flax.Build.NativeCpp
|
||||
// Process result
|
||||
result = includedFiles.ToArray();
|
||||
DirectIncludesCache.Add(sourceFile, result);
|
||||
if (!DirectIncludesTimestampCache.ContainsKey(sourceFile))
|
||||
DirectIncludesTimestampCache.Add(sourceFile, lastModified ?? FileLastWriteTime(sourceFile));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,19 +67,7 @@ namespace Flax.Build.Plugins
|
||||
contents.AppendLine(" static THREADLOCAL void* WrapperCallInstance = nullptr;");
|
||||
contents.AppendLine(" if (WrapperCallInstance == object)");
|
||||
contents.AppendLine(" {");
|
||||
contents.AppendLine(" // Prevent stack overflow by calling base method");
|
||||
contents.AppendLine(" const auto scriptVTableBase = object->GetType().Script.ScriptVTableBase;");
|
||||
contents.Append($" return (this->**({functionInfo.UniqueName}_Internal_Signature*)&scriptVTableBase[{scriptVTableOffset} + 2])(");
|
||||
separator = false;
|
||||
for (var i = 0; i < functionInfo.Parameters.Count; i++)
|
||||
{
|
||||
var parameterInfo = functionInfo.Parameters[i];
|
||||
if (separator)
|
||||
contents.Append(", ");
|
||||
separator = true;
|
||||
contents.Append(parameterInfo.Name);
|
||||
}
|
||||
contents.AppendLine(");");
|
||||
BindingsGenerator.GenerateCppVirtualWrapperCallBaseMethod(buildData, contents, classInfo, functionInfo, "object->GetType().Script.ScriptVTableBase", scriptVTableOffset);
|
||||
contents.AppendLine(" }");
|
||||
contents.AppendLine(" auto scriptVTable = (VisualScript::Method**)object->GetType().Script.ScriptVTable;");
|
||||
contents.AppendLine($" ASSERT(scriptVTable && scriptVTable[{scriptVTableOffset}]);");
|
||||
|
||||
Reference in New Issue
Block a user