Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -327,6 +327,18 @@ public:
|
||||
bool operator!=(const String& other) const;
|
||||
|
||||
public:
|
||||
using StringViewBase::StartsWith;
|
||||
FORCE_INLINE bool StartsWith(const StringView& prefix, StringSearchCase searchCase = StringSearchCase::IgnoreCase) const
|
||||
{
|
||||
return StringViewBase::StartsWith(prefix, searchCase);
|
||||
}
|
||||
|
||||
using StringViewBase::EndsWith;
|
||||
FORCE_INLINE bool EndsWith(const StringView& suffix, StringSearchCase searchCase = StringSearchCase::IgnoreCase) const
|
||||
{
|
||||
return StringViewBase::EndsWith(suffix, searchCase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the left most given number of characters.
|
||||
/// </summary>
|
||||
@@ -511,6 +523,18 @@ public:
|
||||
bool operator!=(const StringAnsi& other) const;
|
||||
|
||||
public:
|
||||
using StringViewBase::StartsWith;
|
||||
FORCE_INLINE bool StartsWith(const StringAnsiView& prefix, StringSearchCase searchCase = StringSearchCase::IgnoreCase) const
|
||||
{
|
||||
return StringViewBase::StartsWith(prefix, searchCase);
|
||||
}
|
||||
|
||||
using StringViewBase::EndsWith;
|
||||
FORCE_INLINE bool EndsWith(const StringAnsiView& suffix, StringSearchCase searchCase = StringSearchCase::IgnoreCase) const
|
||||
{
|
||||
return StringViewBase::EndsWith(suffix, searchCase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves substring created from characters starting from startIndex to the String end.
|
||||
/// </summary>
|
||||
|
||||
@@ -30,6 +30,20 @@ typedef struct
|
||||
} MonoCultureInfo;
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
const CultureInfoEntry* FindEntry(const StringAnsiView& name)
|
||||
{
|
||||
for (int32 i = 0; i < NUM_CULTURE_ENTRIES; i++)
|
||||
{
|
||||
const CultureInfoEntry& e = culture_entries[i];
|
||||
if (name == idx2string(e.name))
|
||||
return &e;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
CultureInfo::CultureInfo(int32 lcid)
|
||||
{
|
||||
_lcid = lcid;
|
||||
@@ -80,23 +94,24 @@ CultureInfo::CultureInfo(const StringAnsiView& name)
|
||||
_englishName = TEXT("Invariant Culture");
|
||||
return;
|
||||
}
|
||||
for (int32 i = 0; i < NUM_CULTURE_ENTRIES; i++)
|
||||
const CultureInfoEntry* e = FindEntry(name);
|
||||
if (!e && name.Find('-') != -1)
|
||||
{
|
||||
auto& e = culture_entries[i];
|
||||
if (name == idx2string(e.name))
|
||||
{
|
||||
_data = (void*)&e;
|
||||
_lcid = (int32)e.lcid;
|
||||
_lcidParent = (int32)e.parent_lcid;
|
||||
_name.SetUTF8(name.Get(), name.Length());
|
||||
const char* nativename = idx2string(e.nativename);
|
||||
_nativeName.SetUTF8(nativename, StringUtils::Length(nativename));
|
||||
const char* englishname = idx2string(e.englishname);
|
||||
_englishName.SetUTF8(englishname, StringUtils::Length(englishname));
|
||||
break;
|
||||
}
|
||||
e = FindEntry(name.Substring(0, name.Find('-')));
|
||||
}
|
||||
if (!_data)
|
||||
if (e)
|
||||
{
|
||||
_data = (void*)e;
|
||||
_lcid = (int32)e->lcid;
|
||||
_lcidParent = (int32)e->parent_lcid;
|
||||
const char* ename = idx2string(e->name);
|
||||
_name.SetUTF8(ename, StringUtils::Length(ename));
|
||||
const char* nativename = idx2string(e->nativename);
|
||||
_nativeName.SetUTF8(nativename, StringUtils::Length(nativename));
|
||||
const char* englishname = idx2string(e->englishname);
|
||||
_englishName.SetUTF8(englishname, StringUtils::Length(englishname));
|
||||
}
|
||||
else
|
||||
{
|
||||
_lcid = 127;
|
||||
_lcidParent = 0;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "Engine/Platform/StringUtils.h"
|
||||
#include "Engine/Platform/WindowsManager.h"
|
||||
#include "Engine/Platform/Clipboard.h"
|
||||
#include "Engine/Platform/Thread.h"
|
||||
#include "Engine/Platform/IGuiData.h"
|
||||
#include "Engine/Platform/Base/PlatformUtils.h"
|
||||
#include "Engine/Utilities/StringConverter.h"
|
||||
@@ -176,12 +177,19 @@ uint64 ApplePlatform::GetCurrentThreadID()
|
||||
|
||||
void ApplePlatform::SetThreadPriority(ThreadPriority priority)
|
||||
{
|
||||
// TODO: impl this
|
||||
struct sched_param sched;
|
||||
Platform::MemoryClear(&sched, sizeof(struct sched_param));
|
||||
int32 policy = SCHED_RR;
|
||||
pthread_getschedparam(pthread_self(), &policy, &sched);
|
||||
sched.sched_priority = AppleThread::GetAppleThreadPriority(priority);
|
||||
pthread_setschedparam(pthread_self(), policy, &sched);
|
||||
}
|
||||
|
||||
void ApplePlatform::SetThreadAffinityMask(uint64 affinityMask)
|
||||
{
|
||||
// TODO: impl this
|
||||
thread_affinity_policy policy;
|
||||
policy.affinity_tag = affinityMask;
|
||||
thread_policy_set(pthread_mach_thread_np(pthread_self()), THREAD_AFFINITY_POLICY, (integer_t*)&policy, THREAD_AFFINITY_POLICY_COUNT);
|
||||
}
|
||||
|
||||
void ApplePlatform::Sleep(int32 milliseconds)
|
||||
|
||||
@@ -40,10 +40,7 @@ public:
|
||||
return (AppleThread*)Setup(New<AppleThread>(runnable, name, priority), stackSize);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// [UnixThread]
|
||||
int32 GetThreadPriority(ThreadPriority priority) override
|
||||
static int32 GetAppleThreadPriority(ThreadPriority priority)
|
||||
{
|
||||
switch (priority)
|
||||
{
|
||||
@@ -60,6 +57,14 @@ protected:
|
||||
}
|
||||
return 31;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// [UnixThread]
|
||||
int32 GetThreadPriority(ThreadPriority priority) override
|
||||
{
|
||||
return GetAppleThreadPriority(priority);
|
||||
}
|
||||
int32 Start(pthread_attr_t& attr) override
|
||||
{
|
||||
return pthread_create(&_thread, &attr, ThreadProc, this);
|
||||
|
||||
@@ -26,6 +26,12 @@ int32 UnixThread::Start(pthread_attr_t& attr)
|
||||
void* UnixThread::ThreadProc(void* pThis)
|
||||
{
|
||||
auto thread = (UnixThread*)pThis;
|
||||
#if PLATFORM_APPLE_FAMILY
|
||||
// Apple doesn't support creating named thread so assign name here
|
||||
{
|
||||
pthread_setname_np(StringAnsi(thread->GetName()).Get());
|
||||
}
|
||||
#endif
|
||||
const int32 exitCode = thread->Run();
|
||||
return (void*)(uintptr)exitCode;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#if COMPILE_WITH_SHADER_COMPILER
|
||||
|
||||
#include "ShaderCompiler.h"
|
||||
#include "ShadersCompilation.h"
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Core/Collections/Dictionary.h"
|
||||
#include "Engine/Engine/Globals.h"
|
||||
@@ -14,10 +15,6 @@
|
||||
#include "Engine/Profiler/ProfilerCPU.h"
|
||||
#include "Engine/Serialization/MemoryWriteStream.h"
|
||||
#include "Engine/Utilities/StringConverter.h"
|
||||
#if USE_EDITOR
|
||||
#include "Editor/Editor.h"
|
||||
#include "Editor/ProjectInfo.h"
|
||||
#endif
|
||||
|
||||
namespace IncludedFiles
|
||||
{
|
||||
@@ -30,31 +27,6 @@ namespace IncludedFiles
|
||||
|
||||
CriticalSection Locker;
|
||||
Dictionary<String, File*> Files;
|
||||
|
||||
#if USE_EDITOR
|
||||
bool FindProject(const ProjectInfo* project, HashSet<const ProjectInfo*>& projects, const StringView& projectName, String& path)
|
||||
{
|
||||
if (!project || projects.Contains(project))
|
||||
return false;
|
||||
projects.Add(project);
|
||||
|
||||
// Check the project name
|
||||
if (project->Name == projectName)
|
||||
{
|
||||
path = project->ProjectFolderPath;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Initialize referenced projects
|
||||
for (const auto& reference : project->References)
|
||||
{
|
||||
if (reference.Project && FindProject(reference.Project, projects, projectName, path))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ShaderCompiler::Compile(ShaderCompilationContext* context)
|
||||
@@ -124,7 +96,8 @@ bool ShaderCompiler::Compile(ShaderCompilationContext* context)
|
||||
output->WriteInt32(context->Includes.Count());
|
||||
for (auto& include : context->Includes)
|
||||
{
|
||||
output->WriteString(include.Item, 11);
|
||||
String compactPath = ShadersCompilation::CompactShaderPath(include.Item);
|
||||
output->WriteString(compactPath, 11);
|
||||
const auto date = FileSystem::GetFileLastEditTime(include.Item);
|
||||
output->Write(date);
|
||||
}
|
||||
@@ -138,75 +111,17 @@ bool ShaderCompiler::GetIncludedFileSource(ShaderCompilationContext* context, co
|
||||
source = nullptr;
|
||||
sourceLength = 0;
|
||||
|
||||
// Skip to the last root start './' but preserve the leading one
|
||||
const int32 includedFileLength = StringUtils::Length(includedFile);
|
||||
for (int32 i = includedFileLength - 2; i >= 2; i--)
|
||||
// Get actual file path
|
||||
const String includedFileName(includedFile);
|
||||
String path = ShadersCompilation::ResolveShaderPath(includedFileName);
|
||||
if (!FileSystem::FileExists(path))
|
||||
{
|
||||
if (StringUtils::Compare(includedFile + i, "./", 2) == 0)
|
||||
{
|
||||
includedFile = includedFile + i;
|
||||
break;
|
||||
}
|
||||
LOG(Error, "Unknown shader source file '{0}' included in '{1}'.{2}", includedFileName, String(sourceFile), String::Empty);
|
||||
return true;
|
||||
}
|
||||
|
||||
ScopeLock lock(IncludedFiles::Locker);
|
||||
|
||||
// Find the included file path
|
||||
String path;
|
||||
#if USE_EDITOR
|
||||
if (StringUtils::Compare(includedFile, "./", 2) == 0)
|
||||
{
|
||||
int32 projectNameEnd = -1;
|
||||
for (int32 i = 2; i < includedFileLength; i++)
|
||||
{
|
||||
if (includedFile[i] == '/')
|
||||
{
|
||||
projectNameEnd = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (projectNameEnd == -1)
|
||||
{
|
||||
LOG(Error, "Unknown shader source file '{0}' included in '{1}'.{2}", String(includedFile), String(sourceFile), TEXT("Missing project name after root path."));
|
||||
return true;
|
||||
}
|
||||
const StringAsUTF16<120> projectName(includedFile + 2, projectNameEnd - 2);
|
||||
if (StringUtils::Compare(projectName.Get(), TEXT("FlaxPlatforms")) == 0)
|
||||
{
|
||||
// Hard-coded redirect to platform-specific includes
|
||||
path /= Globals::StartupFolder / TEXT("Source/Platforms");
|
||||
}
|
||||
else
|
||||
{
|
||||
HashSet<const ProjectInfo*> projects;
|
||||
if (!IncludedFiles::FindProject(Editor::Project, projects, StringView(projectName.Get(), projectNameEnd - 2), path))
|
||||
{
|
||||
LOG(Error, "Unknown shader source file '{0}' included in '{1}'.{2}", String(includedFile), String(sourceFile), TEXT("Failed to find the project of the given name."));
|
||||
return true;
|
||||
}
|
||||
path /= TEXT("Source/Shaders/");
|
||||
}
|
||||
const StringAsUTF16<250> localPath(includedFile + projectNameEnd + 1, includedFileLength - projectNameEnd - 1);
|
||||
path /= localPath.Get();
|
||||
}
|
||||
#else
|
||||
if (StringUtils::Compare(includedFile, "./Flax/", 7) == 0)
|
||||
{
|
||||
// Engine project relative shader path
|
||||
const auto includedFileStr = String(includedFile + 6);
|
||||
path = Globals::StartupFolder / TEXT("Source/Shaders") / includedFileStr;
|
||||
}
|
||||
#endif
|
||||
else if (FileSystem::FileExists(path = String(includedFile)))
|
||||
{
|
||||
// Absolute shader path
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(Error, "Unknown shader source file '{0}' included in '{1}'.{2}", String(includedFile), String(sourceFile), String::Empty);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to reuse file
|
||||
IncludedFiles::File* result = nullptr;
|
||||
if (!IncludedFiles::Files.TryGet(path, result) || FileSystem::GetFileLastEditTime(path) > result->LastEditTime)
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#include "Editor/Editor.h"
|
||||
#include "Editor/ProjectInfo.h"
|
||||
#endif
|
||||
|
||||
#if COMPILE_WITH_D3D_SHADER_COMPILER
|
||||
#include "DirectX/ShaderCompilerD3D.h"
|
||||
#endif
|
||||
@@ -55,6 +54,49 @@ namespace ShadersCompilationImpl
|
||||
CriticalSection Locker;
|
||||
Array<ShaderCompiler*> Compilers;
|
||||
Array<ShaderCompiler*> ReadyCompilers;
|
||||
|
||||
#if USE_EDITOR
|
||||
const ProjectInfo* FindProjectByName(const ProjectInfo* project, HashSet<const ProjectInfo*>& projects, const StringView& projectName)
|
||||
{
|
||||
if (!project || projects.Contains(project))
|
||||
return nullptr;
|
||||
projects.Add(project);
|
||||
|
||||
// Check the project name
|
||||
if (project->Name == projectName)
|
||||
return project;
|
||||
|
||||
// Search referenced projects
|
||||
for (const auto& reference : project->References)
|
||||
{
|
||||
const ProjectInfo* result = FindProjectByName(reference.Project, projects, projectName);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ProjectInfo* FindProjectByPath(const ProjectInfo* project, HashSet<const ProjectInfo*>& projects, const StringView& projectPath)
|
||||
{
|
||||
if (!project || projects.Contains(project))
|
||||
return nullptr;
|
||||
projects.Add(project);
|
||||
|
||||
// Search referenced projects (depth first to handle plugin projects first)
|
||||
for (const auto& reference : project->References)
|
||||
{
|
||||
const ProjectInfo* result = FindProjectByPath(reference.Project, projects, projectPath);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check the project path
|
||||
if (projectPath.StartsWith(project->ProjectFolderPath))
|
||||
return project;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
using namespace ShadersCompilationImpl;
|
||||
@@ -361,11 +403,89 @@ void ShadersCompilation::ExtractShaderIncludes(byte* shaderCache, int32 shaderCa
|
||||
{
|
||||
String& include = includes.AddOne();
|
||||
stream.ReadString(&include, 11);
|
||||
include = ShadersCompilation::ResolveShaderPath(include);
|
||||
DateTime lastEditTime;
|
||||
stream.Read(lastEditTime);
|
||||
}
|
||||
}
|
||||
|
||||
String ShadersCompilation::ResolveShaderPath(StringView path)
|
||||
{
|
||||
// Skip to the last root start './' but preserve the leading one
|
||||
for (int32 i = path.Length() - 2; i >= 2; i--)
|
||||
{
|
||||
if (StringUtils::Compare(path.Get() + i, TEXT("./"), 2) == 0)
|
||||
{
|
||||
path = path.Substring(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the included file path
|
||||
String result;
|
||||
#if USE_EDITOR
|
||||
if (path.StartsWith(StringView(TEXT("./"), 2)))
|
||||
{
|
||||
int32 projectNameEnd = -1;
|
||||
for (int32 i = 2; i < path.Length(); i++)
|
||||
{
|
||||
if (path[i] == '/')
|
||||
{
|
||||
projectNameEnd = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (projectNameEnd == -1)
|
||||
return String::Empty; // Invalid project path
|
||||
StringView projectName = path.Substring(2, projectNameEnd - 2);
|
||||
if (projectName.StartsWith(StringView(TEXT("FlaxPlatforms"))))
|
||||
{
|
||||
// Hard-coded redirect to platform-specific includes
|
||||
result = Globals::StartupFolder / TEXT("Source/Platforms");
|
||||
}
|
||||
else
|
||||
{
|
||||
HashSet<const ProjectInfo*> projects;
|
||||
const ProjectInfo* project = FindProjectByName(Editor::Project, projects, StringView(projectName.Get(), projectNameEnd - 2));
|
||||
if (project)
|
||||
result = project->ProjectFolderPath / TEXT("/Source/Shaders/");
|
||||
else
|
||||
return String::Empty;
|
||||
}
|
||||
result /= path.Substring(projectNameEnd + 1);
|
||||
}
|
||||
#else
|
||||
if (path.StartsWith(StringView(TEXT("./Flax/"), 7)))
|
||||
{
|
||||
// Engine project relative shader path
|
||||
result = Globals::StartupFolder / TEXT("Source/Shaders") / path.Substring(6);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
// Absolute shader path
|
||||
result = path;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
String ShadersCompilation::CompactShaderPath(StringView path)
|
||||
{
|
||||
#if USE_EDITOR
|
||||
// Try to use file path relative to the project shader sources folder
|
||||
HashSet<const ProjectInfo*> projects;
|
||||
const ProjectInfo* project = FindProjectByPath(Editor::Project, projects, path);
|
||||
if (project)
|
||||
{
|
||||
String projectSourcesPath = project->ProjectFolderPath / TEXT("/Source/Shaders/");
|
||||
if (path.StartsWith(projectSourcesPath))
|
||||
return String::Format(TEXT("./{}/{}"), project->Name, path.Substring(projectSourcesPath.Length()));
|
||||
}
|
||||
#endif
|
||||
return String(path);
|
||||
}
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
namespace
|
||||
|
||||
@@ -14,7 +14,6 @@ class Asset;
|
||||
class FLAXENGINE_API ShadersCompilation
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Compiles the shader.
|
||||
/// </summary>
|
||||
@@ -43,6 +42,11 @@ public:
|
||||
/// <param name="includes">The output included.</param>
|
||||
static void ExtractShaderIncludes(byte* shaderCache, int32 shaderCacheLength, Array<String>& includes);
|
||||
|
||||
// Resolves shader path name into absolute file path. Resolves './<ProjectName>/ShaderFile.hlsl' cases into a full path.
|
||||
static String ResolveShaderPath(StringView path);
|
||||
// Compacts the full shader file path into portable format with project name prefix such as './<ProjectName>/ShaderFile.hlsl'.
|
||||
static String CompactShaderPath(StringView path);
|
||||
|
||||
private:
|
||||
|
||||
static ShaderCompiler* CreateCompiler(ShaderProfile profile);
|
||||
|
||||
Reference in New Issue
Block a user