10 Commits

Author SHA1 Message Date
max
546b7feca7 project and solution generation 2024-07-21 22:31:04 +02:00
max
36a134170a editor project
yes
2024-07-21 14:03:40 +02:00
max
6e41c2579c started working on compiler project
the idea of the compiler project is to have a tool that generates and compiles the solution + csproj files for the project. This is then used by the editor or via the command line.
2024-07-21 04:38:31 +02:00
max
2afbd9defe Generate solution file 2024-07-20 00:46:08 +02:00
max
f978c49532 start working on project generation 2024-07-19 15:24:50 +02:00
92cf24fe9f - Added resource manager
- Shader building now inspects the spir-v for descriptor sets and writes the info to the output binary
2024-07-13 13:45:12 +02:00
cce6e00960 - Merge 2024-07-12 23:11:47 +02:00
1096597161 - Fixed bug in builder when no content files exist 2024-07-12 23:10:44 +02:00
d45f7c3b8c - Fixed bug in builder when no content files exist 2024-07-12 23:08:52 +02:00
max
7a81026ca5 Merge remote-tracking branch 'origin/ImGui' 2024-07-12 19:51:41 +02:00
37 changed files with 1093 additions and 1050 deletions

View File

@ -3,6 +3,7 @@
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$/Nerfed.Runtime/Libraries/FAudio" vcs="Git" />
<mapping directory="$PROJECT_DIR$/Nerfed.Runtime/Libraries/ImGui.NET" vcs="Git" />
<mapping directory="$PROJECT_DIR$/Nerfed.Runtime/Libraries/RefreshCS" vcs="Git" />
<mapping directory="$PROJECT_DIR$/Nerfed.Runtime/Libraries/SDL2CS" vcs="Git" />
<mapping directory="$PROJECT_DIR$/Nerfed.Runtime/Libraries/WellspringCS" vcs="Git" />

View File

@ -5,12 +5,15 @@ public class BuildArgs
[Argument("-build")]
public bool Build { get; set; }
[Argument("-projectPath")]
public string ProjectPath { get; set; }
[Argument("-resourcePath")]
public string ResourcePath { get; set; }
[Argument("-resourceOutPath")]
public string ResourceOutPath { get; set; }
[Argument("-platform")]
public string Platform { get; set; }
[Argument("-content")]
public List<string> ContentFiles { get; set; }
[Argument("-resourceFiles")]
public List<string> ResourceFiles { get; set; }
}

View File

@ -11,13 +11,12 @@ public class Builder : IDisposable
{
rawFileImporter = new RawFileImporter();
ShaderImporter shaderImporter = new ShaderImporter();
importers.Add(".vert", shaderImporter); // Vertex shader
importers.Add(".frag", shaderImporter); // Fragment shader
importers.Add(".tesc", shaderImporter); // Tessellation control shader
importers.Add(".tese", shaderImporter); // Tessellation evaluation shader
importers.Add(".geom", shaderImporter); // Geometry shader
importers.Add(".comp", shaderImporter); // Compute shader
importers.Add(".vert", new ShaderImporter(ShaderStage.Vertex)); // Vertex shader
importers.Add(".frag", new ShaderImporter(ShaderStage.Fragment)); // Fragment shader
//importers.Add(".tesc", shaderImporter); // Tessellation control shader
//importers.Add(".tese", shaderImporter); // Tessellation evaluation shader
//importers.Add(".geom", shaderImporter); // Geometry shader
//importers.Add(".comp", shaderImporter); // Compute shader
}
public void Run(BuildArgs args)
@ -25,77 +24,78 @@ public class Builder : IDisposable
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
CopyLibs(args.ProjectPath);
//CopyLibs(args.ResourcePath);
List<string> contentFiles = args.ContentFiles;
string absContentPath = $"{args.ProjectPath}/{PathUtil.ContentFolderName}";
List<string> contentFiles = args.ResourceFiles;
// If no files are provided, build all content.
if (args.ContentFiles == null)
if (args.ResourceFiles == null)
{
contentFiles = [];
CollectAssetFiles(absContentPath, absContentPath, ref contentFiles);
CollectAssetFiles(args.ResourcePath, args.ResourcePath, ref contentFiles);
}
string importPath = $"{args.ProjectPath}/{PathUtil.ImportFolderName}";
ParallelOptions parallelOptions = new ParallelOptions
if (contentFiles.Count > 0)
{
MaxDegreeOfParallelism = contentFiles.Count
};
Parallel.ForEach(contentFiles, parallelOptions, relativeFile =>
{
try
ParallelOptions parallelOptions = new ParallelOptions
{
string inFile = $"{args.ProjectPath}/{PathUtil.ContentFolderName}/{relativeFile}";
MaxDegreeOfParallelism = contentFiles.Count
};
if (!File.Exists(inFile))
{
Console.Error.WriteLine($"Asset file '{relativeFile}' not found");
return;
}
string outFile = $"{importPath}/{relativeFile}{PathUtil.ImportedFileExtension}";
FileInfo inFileInfo = new FileInfo(inFile);
FileInfo outFileInfo = new FileInfo(outFile);
if (!FileUtil.IsNewer(inFileInfo, outFileInfo))
{
// File has not changed since last build, no need to build this one.
return;
}
string outDir = Path.GetDirectoryName(outFile);
if (!Directory.Exists(outDir))
{
Directory.CreateDirectory(outDir);
}
string ext = Path.GetExtension(inFile).ToLower();
if (importers.TryGetValue(ext, out IImporter importer))
{
importer.Import(inFile, outFile);
}
else
{
rawFileImporter.Import(inFile, outFile);
}
Console.WriteLine(relativeFile);
}
catch (Exception e)
Parallel.ForEach(contentFiles, parallelOptions, relativeFile =>
{
Console.Error.WriteLine($"Import error on asset '{relativeFile}': {e.Message}");
}
});
try
{
string inFile = $"{args.ResourcePath}/{relativeFile}";
if (!File.Exists(inFile))
{
Console.Error.WriteLine($"Asset file '{relativeFile}' not found");
return;
}
string outFile = $"{args.ResourceOutPath}/{relativeFile}{PathUtil.ImportedFileExtension}";
FileInfo inFileInfo = new FileInfo(inFile);
FileInfo outFileInfo = new FileInfo(outFile);
if (!FileUtil.IsNewer(inFileInfo, outFileInfo))
{
// File has not changed since last build, no need to build this one.
return;
}
string outDir = Path.GetDirectoryName(outFile);
if (!Directory.Exists(outDir))
{
Directory.CreateDirectory(outDir);
}
string ext = Path.GetExtension(inFile).ToLower();
if (importers.TryGetValue(ext, out IImporter importer))
{
importer.Import(inFile, outFile);
}
else
{
rawFileImporter.Import(inFile, outFile);
}
Console.WriteLine(relativeFile);
}
catch (Exception e)
{
Console.Error.WriteLine($"Import error on asset '{relativeFile}': {e.Message}");
}
});
}
Console.WriteLine($"Build content completed in {stopwatch.Elapsed.TotalSeconds:F2} seconds");
}
private void CopyLibs(string projectPath)
/*private void CopyLibs(string projectPath)
{
string libDir = $"{Directory.GetCurrentDirectory()}/../../Native/";
string libDir = $"{AppDomain.CurrentDomain.BaseDirectory}/../../Native/";
if (OperatingSystem.IsWindows())
{
libDir += "x64";
@ -119,17 +119,12 @@ public class Builder : IDisposable
FileUtil.Copy(srcFileInfo, dstFileInfo);
}
}
}
}*/
private void CollectAssetFiles(string assetDir, string dir, ref List<string> files)
{
foreach (string file in Directory.EnumerateFiles(dir))
{
if (Path.GetExtension(file).Equals(PathUtil.ImportFileExtension, StringComparison.CurrentCultureIgnoreCase))
{
continue;
}
string relativeFile = file.Substring(assetDir.Length, file.Length - assetDir.Length);
if (relativeFile[0] == Path.DirectorySeparatorChar || relativeFile[0] == Path.AltDirectorySeparatorChar)
{

View File

@ -1,33 +1,157 @@
using System.Diagnostics;
using Vortice.ShaderCompiler;
using Vortice.SPIRV.Reflect;
namespace Nerfed.Builder;
// Values should match the ShaderStage enum in the runtime.
public enum ShaderStage
{
Vertex,
Fragment
}
// Values should match the ShaderFormat enum in the runtime.
public enum ShaderFormat
{
Invalid,
SPIRV,
HLSL,
DXBC,
DXIL,
MSL,
METALLIB,
SECRET
}
public class ShaderImporter : IImporter
{
public void Import(string inFile, string outFile)
private readonly ShaderStage shaderStage;
public ShaderImporter(ShaderStage shaderStage)
{
using (Process proc = new Process())
this.shaderStage = shaderStage;
}
public unsafe void Import(string inFile, string outFile)
{
string name = Path.GetFileNameWithoutExtension(inFile);
string nameWithExt = Path.GetFileName(inFile);
// Compile the shader.
Result compileResult;
using (Compiler compiler = new Compiler())
{
string glslc;
if (OperatingSystem.IsWindows())
string shaderSource = File.ReadAllText(inFile);
compileResult = compiler.Compile(shaderSource, nameWithExt, ToShaderKind(shaderStage));
}
if (compileResult.Status != CompilationStatus.Success)
{
Console.Error.WriteLine($"Failed to compile {nameWithExt}\n{compileResult.ErrorMessage}");
return;
}
if (compileResult.ErrorsCount > 0 || compileResult.WarningsCount > 0)
{
Console.Error.WriteLine(compileResult.ErrorMessage);
}
Span<byte> byteCode = compileResult.GetBytecode();
// Inspect SPIR-V bytecode for information which the runtime requires to create a shader resource.
SpvReflectShaderModule module = new SpvReflectShaderModule();
if (!CheckReflectResult(SPIRVReflectApi.spvReflectCreateShaderModule(byteCode, &module), name))
{
return;
}
uint descriptorSetCount = 0;
if (!CheckReflectResult(SPIRVReflectApi.spvReflectEnumerateDescriptorSets(&module, &descriptorSetCount, null), name))
{
return;
}
int uniformBufferCount = 0;
int storageBufferCount = 0;
int storageTextureCount = 0;
int samplerCount = 0;
if (descriptorSetCount > 0)
{
SpvReflectDescriptorSet* descriptorSets = stackalloc SpvReflectDescriptorSet[(int)descriptorSetCount];
if (!CheckReflectResult(
SPIRVReflectApi.spvReflectEnumerateDescriptorSets(&module, &descriptorSetCount, &descriptorSets),
name
))
{
glslc = "Win64/glslc.exe";
}
else if (OperatingSystem.IsLinux())
{
glslc = "Linux/glslc";
}
else
{
throw new PlatformNotSupportedException("No shader compiler found for current platform");
return;
}
proc.StartInfo.FileName = glslc;
proc.StartInfo.Arguments = @$"""{inFile}"" -o ""{outFile}"" -c";
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.UseShellExecute = false;
proc.Start();
proc.WaitForExit();
for (int i = 0; i < descriptorSetCount; i++)
{
SpvReflectDescriptorSet set = descriptorSets[i];
for (int j = 0; j < set.binding_count; j++)
{
SpvReflectDescriptorBinding binding = *set.bindings[j];
if (binding.descriptor_type == SpvReflectDescriptorType.UniformBuffer)
{
uniformBufferCount++;
}
else if (binding.descriptor_type == SpvReflectDescriptorType.StorageBuffer)
{
storageBufferCount++;
}
else if (binding.descriptor_type == SpvReflectDescriptorType.StorageTexelBuffer)
{
storageTextureCount++;
}
else if (binding.descriptor_type == SpvReflectDescriptorType.Sampler ||
binding.descriptor_type == SpvReflectDescriptorType.CombinedImageSampler)
{
samplerCount++;
}
}
}
}
//TODO: Convert SPIR-V to other bytecode formats here (DX/Consoles).
ShaderFormat format = ShaderFormat.SPIRV;
// Write shader meta-data and bytecode to the output file.
using (FileStream stream = new FileStream(outFile, FileMode.Create, FileAccess.Write))
{
using (BinaryWriter writer = new BinaryWriter(stream))
{
writer.Write((int)format);
writer.Write((int)shaderStage);
writer.Write(uniformBufferCount);
writer.Write(storageBufferCount);
writer.Write(storageTextureCount);
writer.Write(samplerCount);
writer.Write(byteCode.Length);
writer.Write(byteCode);
}
}
}
private bool CheckReflectResult(SpvReflectResult result, string name)
{
if (result != SpvReflectResult.Success)
{
Console.Error.WriteLine($"SpirV-Reflect failure for '{name}': {result}");
return false;
}
return true;
}
private ShaderKind ToShaderKind(ShaderStage shaderStage)
{
switch (shaderStage)
{
case ShaderStage.Vertex: return ShaderKind.VertexShader;
case ShaderStage.Fragment: return ShaderKind.FragmentShader;
default: throw new ArgumentOutOfRangeException(nameof(shaderStage));
}
}
}

View File

@ -12,14 +12,22 @@
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Test|x64' ">
<Optimize>true</Optimize>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
<Optimize>true</Optimize>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Vortice.ShaderCompiler" Version="1.7.3" />
<PackageReference Include="Vortice.SPIRV.Reflect" Version="1.0.3" />
</ItemGroup>
</Project>

View File

@ -3,8 +3,4 @@ namespace Nerfed.Builder;
public static class PathUtil
{
public const string ImportedFileExtension = ".bin";
public const string BuildFolderName = ".build";
public const string ImportFileExtension = ".import";
public const string ImportFolderName = $"{BuildFolderName}/Import";
public const string ContentFolderName = "Content";
}

View File

@ -0,0 +1,64 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Nerfed.Compiler;
public class CSProject
{
public string Name { get; set; }
public string Guid { get; set; }
//public bool IsEditor { get; set; }
// Add platform stuff here..?
// Add dll's here..?
// Add dependencies here..?
public static bool Create(string projectFilePath, string name, out CSProject project)
{
project = null;
if (File.Exists(projectFilePath))
{
Console.WriteLine($"ERROR: File already exists!");
return false;
}
// Create project file.
project = new CSProject
{
Name = name,
Guid = System.Guid.NewGuid().ToString("B").ToUpper(),
};
Save(project, projectFilePath);
return true;
}
public static bool Save(CSProject project, string projectFilePath)
{
string jsonString = JsonSerializer.Serialize(project, CSProjectContext.Default.CSProject);
File.WriteAllText(projectFilePath, jsonString);
return true;
}
public static bool Open(string projectFilePath, out CSProject project)
{
string jsonString = File.ReadAllText(projectFilePath);
project = JsonSerializer.Deserialize(jsonString, CSProjectContext.Default.CSProject);
if (project == null)
{
Console.WriteLine($"ERROR: Could not open {typeof(CSProject)}.");
return false;
}
return true;
}
}
[JsonSerializable(typeof(CSProject))]
public partial class CSProjectContext : JsonSerializerContext
{
}

231
Nerfed.Compiler/Compiler.cs Normal file
View File

@ -0,0 +1,231 @@
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.Json;
namespace Nerfed.Compiler;
public static class Compiler
{
public const string CSProjectFileName = ".csproject";
public const string CSProjFileName = ".csproj";
public static bool Compile(string projectFilePath, string configuration = "Debug")
{
string projectPath = Path.GetDirectoryName(projectFilePath);
if (!File.Exists(projectFilePath))
{
Console.WriteLine($"ERROR: Project file not found at {projectPath}.");
return false;
}
if (!Project.Open(projectFilePath, out Project project))
{
return false;
}
// TODO: Check project version, to make sure we can compile it or something...
// Generate solution.
GenerateSolution(projectPath, project, out string solutionFilePath);
// Compile solution.
ProcessStartInfo processInfo = new()
{
WorkingDirectory = Path.GetDirectoryName(solutionFilePath),
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true,
};
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
processInfo.FileName = "/bin/bash";
processInfo.Arguments = $"-c \"dotnet build '{Path.GetFileName(solutionFilePath)}'\"" + (string.IsNullOrWhiteSpace(configuration) ? $" --configuration {configuration}" : "");
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
processInfo.FileName = "cmd.exe";
processInfo.Arguments = $"/c dotnet build \"{Path.GetFileName(solutionFilePath)}\"" + (string.IsNullOrWhiteSpace(configuration) ? $" --configuration {configuration}" : "");
}
else
{
Console.WriteLine($"ERROR: Platform not supported!");
return false;
}
Process process = Process.Start(processInfo) ?? throw new Exception();
process.OutputDataReceived += (sender, dataArgs) => {
string data = dataArgs.Data;
if (data is null)
{
return;
}
Console.WriteLine(data);
};
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.ErrorDataReceived += (sender, dataArgs) => {
if (dataArgs.Data is not null)
{
Console.WriteLine(dataArgs.Data);
}
};
process.WaitForExit();
int exitCode = process.ExitCode;
process.Close();
return true;
}
public static void GenerateSolution(string projectPath, Project project, out string solutionPath)
{
// Clear files.
string[] csProjectFiles = Directory.GetFiles(projectPath, $"*{CSProjFileName}", SearchOption.TopDirectoryOnly);
foreach (string csProjFile in csProjectFiles)
{
File.Delete(csProjFile);
}
// Generate projects.
string[] csProjectFilePaths = Directory.GetFiles(projectPath, CSProjectFileName, SearchOption.AllDirectories);
foreach (string csProjectFilePath in csProjectFilePaths)
{
GenerateCSProject(csProjectFilePath, projectPath);
}
// Generate solution.
string[] csProjPaths = Directory.GetFiles(projectPath, $"*{CSProjFileName}", SearchOption.TopDirectoryOnly);
string[] csProjGuids = new string[csProjPaths.Length];
for (int i = 0; i < csProjPaths.Length; i++)
{
csProjGuids[i] = Guid.NewGuid().ToString("B").ToUpper();
}
StringBuilder solutionContent = new StringBuilder();
// Write the solution file header
solutionContent.AppendLine("Microsoft Visual Studio Solution File, Format Version 12.00");
solutionContent.AppendLine("# Visual Studio Version 17");
solutionContent.AppendLine("VisualStudioVersion = 17.10.35013.160");
solutionContent.AppendLine("MinimumVisualStudioVersion = 10.0.40219.1");
// Add each project to the solution file
for (int i = 0; i < csProjPaths.Length; i++)
{
string csProjPath = csProjPaths[i];
string projectGuid = csProjGuids[i];
string projectName = Path.GetFileNameWithoutExtension(csProjPath);
string projectRelativePath = Path.GetRelativePath(projectPath, csProjPath);
// FAE04EC0-301F-11D3-BF4B-00C04F79EFBC for C# projects.
solutionContent.AppendLine($"Project(\"{{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}}\") = \"{projectName}\", \"{projectRelativePath}\", \"{projectGuid}\"");
solutionContent.AppendLine("EndProject");
}
// Add global sections (these can be extended as needed)
solutionContent.AppendLine("Global");
solutionContent.AppendLine(" GlobalSection(SolutionConfigurationPlatforms) = preSolution");
solutionContent.AppendLine(" Test|x64 = Test|x64");
solutionContent.AppendLine(" Release|x64 = Release|x64");
solutionContent.AppendLine(" Debug|x64 = Debug|x64");
solutionContent.AppendLine(" EndGlobalSection");
solutionContent.AppendLine(" GlobalSection(ProjectConfigurationPlatforms) = postSolution");
for (int i = 0; i < csProjPaths.Length; i++)
{
string projectGuid = csProjGuids[i];
solutionContent.AppendLine($" {projectGuid}.Test|x64.ActiveCfg = Test|x64");
solutionContent.AppendLine($" {projectGuid}.Test|x64.Build.0 = Test|x64");
solutionContent.AppendLine($" {projectGuid}.Release|x64.ActiveCfg = Release|x64");
solutionContent.AppendLine($" {projectGuid}.Release|x64.Build.0 = Release|x64");
solutionContent.AppendLine($" {projectGuid}.Debug|x64.ActiveCfg = Debug|x64");
solutionContent.AppendLine($" {projectGuid}.Debug|x64.Build.0 = Debug|x64");
}
solutionContent.AppendLine(" EndGlobalSection");
solutionContent.AppendLine(" GlobalSection(SolutionProperties) = preSolution");
solutionContent.AppendLine(" HideSolutionNode = FALSE");
solutionContent.AppendLine(" EndGlobalSection");
solutionContent.AppendLine("EndGlobal");
// Write the solution file content to disk
string solutionName = project.Name + ".sln";
string filePath = Path.Combine(projectPath, solutionName);
File.WriteAllText(filePath, solutionContent.ToString());
solutionPath = filePath;
}
private static void GenerateCSProject(string csProjectFilePath, string projectPath)
{
if (!File.Exists(csProjectFilePath))
{
return;
}
string jsonString = File.ReadAllText(csProjectFilePath);
CSProject csProject = JsonSerializer.Deserialize(jsonString, CSProjectContext.Default.CSProject);
Assembly[] loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
Assembly runtimeAssembly = loadedAssemblies.FirstOrDefault(assembly => assembly.GetName().Name == "Nerfed.Runtime") ?? throw new Exception("Failed to find Runtime Assembly!");
// TODO: get all dependencies.
// TODO: properly get assemblies.
StringBuilder projectContent = new StringBuilder();
projectContent.AppendLine("<Project Sdk=\"Microsoft.NET.Sdk\">");
projectContent.AppendLine(" <PropertyGroup>");
projectContent.AppendLine(" <TargetFramework>net8.0</TargetFramework>");
projectContent.AppendLine(" <ImplicitUsings>enable</ImplicitUsings>");
projectContent.AppendLine(" <Nullable>disable</Nullable>");
projectContent.AppendLine(" <PublishAot>true</PublishAot>");
projectContent.AppendLine(" <InvariantGlobalization>true</InvariantGlobalization>");
projectContent.AppendLine(" <AllowUnsafeBlocks>true</AllowUnsafeBlocks>");
projectContent.AppendLine(" <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>");
projectContent.AppendLine(" <IsPackable>false</IsPackable>");
projectContent.AppendLine(" <Configurations>Debug;Test;Release</Configurations>");
projectContent.AppendLine(" <Platforms>x64</Platforms>");
projectContent.AppendLine(" </PropertyGroup>");
projectContent.AppendLine(" <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Debug|x64' \">");
projectContent.AppendLine(" <DefineConstants>TRACE;LOG_INFO;PROFILING</DefineConstants>");
projectContent.AppendLine(" </PropertyGroup>");
projectContent.AppendLine(" <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Test|x64' \">");
projectContent.AppendLine(" <DefineConstants>TRACE;LOG_ERROR;PROFILING</DefineConstants>");
projectContent.AppendLine(" <Optimize>true</Optimize>");
projectContent.AppendLine(" </PropertyGroup>");
projectContent.AppendLine(" <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Release|x64' \">");
projectContent.AppendLine(" <DefineConstants>TRACE;LOG_ERROR</DefineConstants>");
projectContent.AppendLine(" <Optimize>true</Optimize>");
projectContent.AppendLine(" </PropertyGroup>");
projectContent.AppendLine(" <ItemGroup>");
projectContent.AppendLine($" <Compile Include=\"{csProjectFilePath}/**/*.cs\"/>");
projectContent.AppendLine(" </ItemGroup>");
projectContent.AppendLine(" <ItemGroup>");
projectContent.AppendLine(" <Reference Include=\"Nerfed.Runtime\">");
projectContent.AppendLine($" <HintPath>{runtimeAssembly.Location}</HintPath>");
projectContent.AppendLine(" <Private>false</Private>");
projectContent.AppendLine(" </Reference>");
projectContent.AppendLine(" </ItemGroup>");
projectContent.AppendLine("</Project>");
string projectName = csProject.Name + ".csproj";
string filePath = Path.Combine(projectPath, projectName);
File.WriteAllText(filePath, projectContent.ToString());
}
}

View File

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>disable</Nullable>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<IsPackable>false</IsPackable>
<Configurations>Debug;Test;Release</Configurations>
<Platforms>x64</Platforms>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
<Optimize>false</Optimize>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Test|x64' ">
<Optimize>true</Optimize>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
<Optimize>true</Optimize>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,10 @@
namespace Nerfed.Compiler
{
public class Program
{
internal static void Main(string[] args)
{
Compiler.Compile(args[0], args[1]);
}
}
}

View File

@ -0,0 +1,50 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Nerfed.Compiler;
public class Project
{
public string Name { get; set; }
public static bool Create(string path, string name, out Project project)
{
// Create project file.
project = new Project
{
Name = name,
};
Save(project, path);
return true;
}
public static bool Save(Project project, string projectFilePath)
{
string jsonString = JsonSerializer.Serialize(project, ProjectContext.Default.Project);
File.WriteAllText(projectFilePath, jsonString);
return true;
}
public static bool Open(string path, out Project project)
{
string jsonString = File.ReadAllText(path);
project = JsonSerializer.Deserialize(jsonString, ProjectContext.Default.Project);
if (project == null)
{
Console.WriteLine($"ERROR: Could not open {typeof(Project)}.");
return false;
}
return true;
}
}
[JsonSerializable(typeof(Project))]
public partial class ProjectContext : JsonSerializerContext
{
}

View File

@ -1,4 +1,5 @@
using ImGuiNET;
using Nerfed.Editor.Project;
using Nerfed.Runtime;
using Nerfed.Runtime.Graphics;
using Nerfed.Runtime.Gui;
@ -56,6 +57,7 @@ namespace Nerfed.Editor
}
ImGui.EndMenu();
}
ImGui.EndMainMenuBar();
}
}
@ -66,6 +68,8 @@ namespace Nerfed.Editor
UpdateDock();
ImGui.ShowDemoWindow();
ProjectGui.OnGui();
}
}
}

View File

@ -23,8 +23,13 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Nerfed.Compiler\Nerfed.Compiler.csproj" />
<ProjectReference Include="..\Nerfed.Runtime\Nerfed.Runtime.csproj" />
</ItemGroup>
<Import Project=".\CopyLibs.targets" />
</Project>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="&quot;$(ProjectDir)../Bin/Nerfed.Builder/Nerfed.Builder&quot; -build -resourcePath &quot;$(ProjectDir)Resources&quot; -resourceOutPath &quot;$(TargetDir)Resources&quot; " />
</Target>
</Project>

View File

@ -0,0 +1,135 @@
using Nerfed.Runtime;
namespace Nerfed.Editor.Project;
internal static class EditorProject
{
internal static Compiler.Project Project { get; private set; }
internal static string ProjectFilePath { get; private set; }
internal static string ProjectSolutionFilePath { get; private set; }
internal static string ProjectPath { get; private set; }
internal static string ProjectContentPath { get; private set; }
internal static string ProjectTempPath { get; private set; }
internal static bool Create(string projectFilePath, string projectName)
{
Close();
if (!Compiler.Project.Create(projectFilePath, projectName, out Compiler.Project project))
{
return false;
}
Open(projectFilePath);
Log.Info($"Succesfully created project.");
return true;
}
internal static bool Open(string path)
{
Close();
if(!Compiler.Project.Open(path, out Compiler.Project project))
{
return false;
}
Project = project;
ProjectFilePath = path;
ProjectPath = Path.GetDirectoryName(path);
string projectSolutionFilePath = Path.Combine(ProjectPath, Project.Name + ".sln");
if (File.Exists(projectSolutionFilePath))
{
ProjectSolutionFilePath = projectSolutionFilePath;
}
SetupDefaultFolders();
Compile();
Log.Info($"Opened project: {project.Name}");
return true;
}
internal static void Close()
{
Project = null;
ProjectFilePath = string.Empty;
ProjectSolutionFilePath = string.Empty;
ProjectPath = string.Empty;
ProjectContentPath = string.Empty;
ProjectTempPath = string.Empty;
}
internal static bool Save()
{
if(Project == null)
{
return false;
}
return Compiler.Project.Save(Project, ProjectFilePath);
}
internal static void Compile()
{
if(Project == null)
{
return;
}
Nerfed.Compiler.Compiler.Compile(ProjectFilePath, "Debug");
}
internal static void GenerateSolution()
{
if(Project == null)
{
return;
}
Nerfed.Compiler.Compiler.GenerateSolution(ProjectPath, Project, out string solutionFilePath);
ProjectSolutionFilePath = solutionFilePath;
}
private static void SetupDefaultFolders()
{
if (Project == null || ProjectPath == null)
{
return;
}
string contentPath = Path.Combine(ProjectPath, "Content");
if (!Directory.Exists(contentPath))
{
Directory.CreateDirectory(contentPath);
}
ProjectContentPath = contentPath;
string scriptsPath = Path.Combine(ProjectContentPath, "Scripts");
if (!Directory.Exists(scriptsPath))
{
Directory.CreateDirectory(scriptsPath);
}
string scriptsRuntimePath = Path.Combine(scriptsPath, "Runtime");
if (!Directory.Exists(scriptsRuntimePath))
{
Directory.CreateDirectory(scriptsRuntimePath);
}
// Test create csproject.
string gameplayRuntimePath = Path.Combine(scriptsRuntimePath, ".csproject");
if (!File.Exists(gameplayRuntimePath))
{
Compiler.CSProject.Create(gameplayRuntimePath, "Gameplay", out Compiler.CSProject project);
}
string tempPath = Path.Combine(ProjectPath, "Temp");
if (!Directory.Exists(tempPath))
{
Directory.CreateDirectory(tempPath);
}
ProjectTempPath = tempPath;
}
}

View File

@ -0,0 +1,68 @@
using ImGuiNET;
namespace Nerfed.Editor.Project
{
internal static class ProjectGui
{
private static string projectPath = string.Empty;
private static string projectName = string.Empty;
private static string projectFilePath = string.Empty;
internal static void OnGui()
{
ImGui.Begin("Project");
ImGui.BeginGroup();
ImGui.InputText("Project Path", ref projectPath, 512);
ImGui.InputText("Project Name", ref projectName, 512);
string newProjectFilePath = Path.Combine(projectPath, ".project");
ImGui.Text(newProjectFilePath);
if (ImGui.Button("Create Project"))
{
EditorProject.Create(newProjectFilePath, projectName);
}
ImGui.EndGroup();
ImGui.BeginGroup();
ImGui.InputText("Project File Path", ref projectFilePath, 512);
if (ImGui.Button("Open Project"))
{
EditorProject.Open(projectFilePath);
}
ImGui.Text("Loaded project: ");
if(EditorProject.Project != null)
{
ImGui.Text(EditorProject.Project.Name);
ImGui.Text(EditorProject.ProjectFilePath);
ImGui.Text(EditorProject.ProjectSolutionFilePath);
ImGui.Text(EditorProject.ProjectPath);
ImGui.Text(EditorProject.ProjectContentPath);
ImGui.Text(EditorProject.ProjectTempPath);
}
else
{
ImGui.Text("None");
}
ImGui.EndGroup();
ImGui.BeginGroup();
if (ImGui.Button("Generate Solution"))
{
EditorProject.GenerateSolution();
}
if (ImGui.Button("Compile"))
{
EditorProject.Compile();
}
ImGui.EndGroup();
ImGui.End();
}
}
}

View File

@ -0,0 +1,9 @@
#version 450
layout(location = 0) out vec2 outTexCoord;
void main()
{
outTexCoord = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
gl_Position = vec4(outTexCoord * vec2(2.0, -2.0) + vec2(-1.0, 1.0), 0.0, 1.0);
}

View File

@ -0,0 +1,34 @@
#version 450
layout(location = 0) in vec2 inTexCoord;
layout(location = 1) in vec4 inColor;
layout(location = 0) out vec4 outColor;
layout(set = 2, binding = 0) uniform sampler2D msdf;
layout(set = 3, binding = 0) uniform UBO
{
float pxRange;
} ubo;
float median(float r, float g, float b)
{
return max(min(r, g), min(max(r, g), b));
}
float screenPxRange()
{
vec2 unitRange = vec2(ubo.pxRange)/vec2(textureSize(msdf, 0));
vec2 screenTexSize = vec2(1.0)/fwidth(inTexCoord);
return max(0.5*dot(unitRange, screenTexSize), 1.0);
}
void main()
{
vec3 msd = texture(msdf, inTexCoord).rgb;
float sd = median(msd.r, msd.g, msd.b);
float screenPxDistance = screenPxRange() * (sd - 0.5);
float opacity = clamp(screenPxDistance + 0.5, 0.0, 1.0);
outColor = mix(vec4(0.0, 0.0, 0.0, 0.0), inColor, opacity);
}

View File

@ -0,0 +1,20 @@
#version 450
layout(location = 0) in vec3 inPos;
layout(location = 1) in vec2 inTexCoord;
layout(location = 2) in vec4 inColor;
layout(location = 0) out vec2 outTexCoord;
layout(location = 1) out vec4 outColor;
layout(set = 1, binding = 0) uniform UBO
{
mat4 ViewProjection;
} ubo;
void main()
{
gl_Position = ubo.ViewProjection * vec4(inPos, 1.0);
outTexCoord = inTexCoord;
outColor = inColor;
}

View File

@ -0,0 +1,38 @@
/*
* This effect is based on the YUV-to-RGBA GLSL shader found in SDL.
* Thus, it also released under the zlib license:
* http://libsdl.org/license.php
*/
#version 450
layout(location = 0) in vec2 TexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 2, binding = 0) uniform sampler2D YSampler;
layout(set = 2, binding = 1) uniform sampler2D USampler;
layout(set = 2, binding = 2) uniform sampler2D VSampler;
/* More info about colorspace conversion:
* http://www.equasys.de/colorconversion.html
* http://www.equasys.de/colorformat.html
*/
const vec3 offset = vec3(-0.0625, -0.5, -0.5);
const vec3 Rcoeff = vec3(1.164, 0.000, 1.793);
const vec3 Gcoeff = vec3(1.164, -0.213, -0.533);
const vec3 Bcoeff = vec3(1.164, 2.112, 0.000);
void main()
{
vec3 yuv;
yuv.x = texture(YSampler, TexCoord).r;
yuv.y = texture(USampler, TexCoord).r;
yuv.z = texture(VSampler, TexCoord).r;
yuv += offset;
FragColor.r = dot(yuv, Rcoeff);
FragColor.g = dot(yuv, Gcoeff);
FragColor.b = dot(yuv, Bcoeff);
FragColor.a = 1.0;
}

View File

@ -1,2 +0,0 @@
glslangvalidator -V imgui-vertex.glsl -o imgui-vertex.spv -S vert
glslangvalidator -V imgui-frag.glsl -o imgui-frag.spv -S frag

View File

@ -61,6 +61,7 @@ public static class Engine
}
GraphicsDevice = new GraphicsDevice(BackendFlags.All);
GraphicsDevice.LoadDefaultPipelines();
MainWindow = new Window(GraphicsDevice, new WindowCreateInfo(WindowTitle, WindowWidth, WindowHeight, ScreenMode.Windowed));
if (!GraphicsDevice.ClaimWindow(MainWindow, SwapchainComposition.SDR, VSync ? PresentMode.VSync : PresentMode.Mailbox))

View File

@ -1,716 +0,0 @@
namespace Nerfed.Runtime.Graphics;
internal class EmbeddedShadersSpirV : IEmbeddedShaders
{
public ShaderFormat ShaderFormat => ShaderFormat.SPIRV;
public byte[] FullscreenVert { get; } =
[
0x3, 0x2, 0x23, 0x7, 0x0, 0x0, 0x1, 0x0, 0xB, 0x0,
0x8, 0x0, 0x2E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x11, 0x0, 0x2, 0x0, 0x1, 0x0, 0x0, 0x0, 0xB, 0x0,
0x6, 0x0, 0x1, 0x0, 0x0, 0x0, 0x47, 0x4C, 0x53, 0x4C,
0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, 0x0, 0x0,
0x0, 0x0, 0xE, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0,
0x1, 0x0, 0x0, 0x0, 0xF, 0x0, 0x8, 0x0, 0x0, 0x0,
0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x6D, 0x61, 0x69, 0x6E,
0x0, 0x0, 0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0xC, 0x0,
0x0, 0x0, 0x1D, 0x0, 0x0, 0x0, 0x3, 0x0, 0x3, 0x0,
0x2, 0x0, 0x0, 0x0, 0xC2, 0x1, 0x0, 0x0, 0x5, 0x0,
0x4, 0x0, 0x4, 0x0, 0x0, 0x0, 0x6D, 0x61, 0x69, 0x6E,
0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x5, 0x0, 0x9, 0x0,
0x0, 0x0, 0x6F, 0x75, 0x74, 0x54, 0x65, 0x78, 0x43, 0x6F,
0x6F, 0x72, 0x64, 0x0, 0x5, 0x0, 0x6, 0x0, 0xC, 0x0,
0x0, 0x0, 0x67, 0x6C, 0x5F, 0x56, 0x65, 0x72, 0x74, 0x65,
0x78, 0x49, 0x6E, 0x64, 0x65, 0x78, 0x0, 0x0, 0x5, 0x0,
0x6, 0x0, 0x1B, 0x0, 0x0, 0x0, 0x67, 0x6C, 0x5F, 0x50,
0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x0, 0x0,
0x0, 0x0, 0x6, 0x0, 0x6, 0x0, 0x1B, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x67, 0x6C, 0x5F, 0x50, 0x6F, 0x73,
0x69, 0x74, 0x69, 0x6F, 0x6E, 0x0, 0x6, 0x0, 0x7, 0x0,
0x1B, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x67, 0x6C,
0x5F, 0x50, 0x6F, 0x69, 0x6E, 0x74, 0x53, 0x69, 0x7A, 0x65,
0x0, 0x0, 0x0, 0x0, 0x6, 0x0, 0x7, 0x0, 0x1B, 0x0,
0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x67, 0x6C, 0x5F, 0x43,
0x6C, 0x69, 0x70, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6E, 0x63,
0x65, 0x0, 0x6, 0x0, 0x7, 0x0, 0x1B, 0x0, 0x0, 0x0,
0x3, 0x0, 0x0, 0x0, 0x67, 0x6C, 0x5F, 0x43, 0x75, 0x6C,
0x6C, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x0,
0x5, 0x0, 0x3, 0x0, 0x1D, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x47, 0x0, 0x4, 0x0, 0x9, 0x0, 0x0, 0x0,
0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x47, 0x0,
0x4, 0x0, 0xC, 0x0, 0x0, 0x0, 0xB, 0x0, 0x0, 0x0,
0x2A, 0x0, 0x0, 0x0, 0x48, 0x0, 0x5, 0x0, 0x1B, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x48, 0x0, 0x5, 0x0, 0x1B, 0x0,
0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xB, 0x0, 0x0, 0x0,
0x1, 0x0, 0x0, 0x0, 0x48, 0x0, 0x5, 0x0, 0x1B, 0x0,
0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0xB, 0x0, 0x0, 0x0,
0x3, 0x0, 0x0, 0x0, 0x48, 0x0, 0x5, 0x0, 0x1B, 0x0,
0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0xB, 0x0, 0x0, 0x0,
0x4, 0x0, 0x0, 0x0, 0x47, 0x0, 0x3, 0x0, 0x1B, 0x0,
0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x13, 0x0, 0x2, 0x0,
0x2, 0x0, 0x0, 0x0, 0x21, 0x0, 0x3, 0x0, 0x3, 0x0,
0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x16, 0x0, 0x3, 0x0,
0x6, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x17, 0x0,
0x4, 0x0, 0x7, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0,
0x2, 0x0, 0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x8, 0x0,
0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0,
0x3B, 0x0, 0x4, 0x0, 0x8, 0x0, 0x0, 0x0, 0x9, 0x0,
0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x15, 0x0, 0x4, 0x0,
0xA, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x1, 0x0,
0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0xB, 0x0, 0x0, 0x0,
0x1, 0x0, 0x0, 0x0, 0xA, 0x0, 0x0, 0x0, 0x3B, 0x0,
0x4, 0x0, 0xB, 0x0, 0x0, 0x0, 0xC, 0x0, 0x0, 0x0,
0x1, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0, 0xA, 0x0,
0x0, 0x0, 0xE, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
0x2B, 0x0, 0x4, 0x0, 0xA, 0x0, 0x0, 0x0, 0x10, 0x0,
0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x17, 0x0, 0x4, 0x0,
0x17, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x4, 0x0,
0x0, 0x0, 0x15, 0x0, 0x4, 0x0, 0x18, 0x0, 0x0, 0x0,
0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2B, 0x0,
0x4, 0x0, 0x18, 0x0, 0x0, 0x0, 0x19, 0x0, 0x0, 0x0,
0x1, 0x0, 0x0, 0x0, 0x1C, 0x0, 0x4, 0x0, 0x1A, 0x0,
0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x19, 0x0, 0x0, 0x0,
0x1E, 0x0, 0x6, 0x0, 0x1B, 0x0, 0x0, 0x0, 0x17, 0x0,
0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x1A, 0x0, 0x0, 0x0,
0x1A, 0x0, 0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x1C, 0x0,
0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x1B, 0x0, 0x0, 0x0,
0x3B, 0x0, 0x4, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x1D, 0x0,
0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0,
0xA, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x2B, 0x0, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0,
0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x2B, 0x0,
0x4, 0x0, 0x6, 0x0, 0x0, 0x0, 0x21, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0xC0, 0x2C, 0x0, 0x5, 0x0, 0x7, 0x0,
0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0,
0x21, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0, 0x6, 0x0,
0x0, 0x0, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0xBF,
0x2B, 0x0, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0, 0x25, 0x0,
0x0, 0x0, 0x0, 0x0, 0x80, 0x3F, 0x2C, 0x0, 0x5, 0x0,
0x7, 0x0, 0x0, 0x0, 0x26, 0x0, 0x0, 0x0, 0x24, 0x0,
0x0, 0x0, 0x25, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0,
0x6, 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x2C, 0x0, 0x0, 0x0,
0x3, 0x0, 0x0, 0x0, 0x17, 0x0, 0x0, 0x0, 0x36, 0x0,
0x5, 0x0, 0x2, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0xF8, 0x0,
0x2, 0x0, 0x5, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0,
0xA, 0x0, 0x0, 0x0, 0xD, 0x0, 0x0, 0x0, 0xC, 0x0,
0x0, 0x0, 0xC4, 0x0, 0x5, 0x0, 0xA, 0x0, 0x0, 0x0,
0xF, 0x0, 0x0, 0x0, 0xD, 0x0, 0x0, 0x0, 0xE, 0x0,
0x0, 0x0, 0xC7, 0x0, 0x5, 0x0, 0xA, 0x0, 0x0, 0x0,
0x11, 0x0, 0x0, 0x0, 0xF, 0x0, 0x0, 0x0, 0x10, 0x0,
0x0, 0x0, 0x6F, 0x0, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0,
0x12, 0x0, 0x0, 0x0, 0x11, 0x0, 0x0, 0x0, 0x3D, 0x0,
0x4, 0x0, 0xA, 0x0, 0x0, 0x0, 0x13, 0x0, 0x0, 0x0,
0xC, 0x0, 0x0, 0x0, 0xC7, 0x0, 0x5, 0x0, 0xA, 0x0,
0x0, 0x0, 0x14, 0x0, 0x0, 0x0, 0x13, 0x0, 0x0, 0x0,
0x10, 0x0, 0x0, 0x0, 0x6F, 0x0, 0x4, 0x0, 0x6, 0x0,
0x0, 0x0, 0x15, 0x0, 0x0, 0x0, 0x14, 0x0, 0x0, 0x0,
0x50, 0x0, 0x5, 0x0, 0x7, 0x0, 0x0, 0x0, 0x16, 0x0,
0x0, 0x0, 0x12, 0x0, 0x0, 0x0, 0x15, 0x0, 0x0, 0x0,
0x3E, 0x0, 0x3, 0x0, 0x9, 0x0, 0x0, 0x0, 0x16, 0x0,
0x0, 0x0, 0x3D, 0x0, 0x4, 0x0, 0x7, 0x0, 0x0, 0x0,
0x1F, 0x0, 0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x85, 0x0,
0x5, 0x0, 0x7, 0x0, 0x0, 0x0, 0x23, 0x0, 0x0, 0x0,
0x1F, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x81, 0x0,
0x5, 0x0, 0x7, 0x0, 0x0, 0x0, 0x27, 0x0, 0x0, 0x0,
0x23, 0x0, 0x0, 0x0, 0x26, 0x0, 0x0, 0x0, 0x51, 0x0,
0x5, 0x0, 0x6, 0x0, 0x0, 0x0, 0x29, 0x0, 0x0, 0x0,
0x27, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x51, 0x0,
0x5, 0x0, 0x6, 0x0, 0x0, 0x0, 0x2A, 0x0, 0x0, 0x0,
0x27, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x50, 0x0,
0x7, 0x0, 0x17, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x0, 0x0,
0x29, 0x0, 0x0, 0x0, 0x2A, 0x0, 0x0, 0x0, 0x28, 0x0,
0x0, 0x0, 0x25, 0x0, 0x0, 0x0, 0x41, 0x0, 0x5, 0x0,
0x2C, 0x0, 0x0, 0x0, 0x2D, 0x0, 0x0, 0x0, 0x1D, 0x0,
0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x3E, 0x0, 0x3, 0x0,
0x2D, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x0, 0x0, 0xFD, 0x0,
0x1, 0x0, 0x38, 0x0, 0x1, 0x0,
];
public byte[] TextMsdfFrag { get; } =
[
0x3, 0x2, 0x23, 0x7, 0x0, 0x0, 0x1, 0x0, 0xB, 0x0,
0x8, 0x0, 0x6C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x11, 0x0, 0x2, 0x0, 0x1, 0x0, 0x0, 0x0, 0x11, 0x0,
0x2, 0x0, 0x32, 0x0, 0x0, 0x0, 0xB, 0x0, 0x6, 0x0,
0x1, 0x0, 0x0, 0x0, 0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73,
0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, 0x0, 0x0, 0x0, 0x0,
0xE, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0,
0x0, 0x0, 0xF, 0x0, 0x8, 0x0, 0x4, 0x0, 0x0, 0x0,
0x4, 0x0, 0x0, 0x0, 0x6D, 0x61, 0x69, 0x6E, 0x0, 0x0,
0x0, 0x0, 0x36, 0x0, 0x0, 0x0, 0x64, 0x0, 0x0, 0x0,
0x67, 0x0, 0x0, 0x0, 0x10, 0x0, 0x3, 0x0, 0x4, 0x0,
0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x3, 0x0, 0x3, 0x0,
0x2, 0x0, 0x0, 0x0, 0xC2, 0x1, 0x0, 0x0, 0x5, 0x0,
0x4, 0x0, 0x4, 0x0, 0x0, 0x0, 0x6D, 0x61, 0x69, 0x6E,
0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x7, 0x0, 0xC, 0x0,
0x0, 0x0, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x6E, 0x28, 0x66,
0x31, 0x3B, 0x66, 0x31, 0x3B, 0x66, 0x31, 0x3B, 0x0, 0x0,
0x0, 0x0, 0x5, 0x0, 0x3, 0x0, 0x9, 0x0, 0x0, 0x0,
0x72, 0x0, 0x0, 0x0, 0x5, 0x0, 0x3, 0x0, 0xA, 0x0,
0x0, 0x0, 0x67, 0x0, 0x0, 0x0, 0x5, 0x0, 0x3, 0x0,
0xB, 0x0, 0x0, 0x0, 0x62, 0x0, 0x0, 0x0, 0x5, 0x0,
0x6, 0x0, 0xF, 0x0, 0x0, 0x0, 0x73, 0x63, 0x72, 0x65,
0x65, 0x6E, 0x50, 0x78, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x28,
0x0, 0x0, 0x5, 0x0, 0x5, 0x0, 0x1E, 0x0, 0x0, 0x0,
0x75, 0x6E, 0x69, 0x74, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x0,
0x0, 0x0, 0x5, 0x0, 0x3, 0x0, 0x1F, 0x0, 0x0, 0x0,
0x55, 0x42, 0x4F, 0x0, 0x6, 0x0, 0x5, 0x0, 0x1F, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x70, 0x78, 0x52, 0x61,
0x6E, 0x67, 0x65, 0x0, 0x5, 0x0, 0x3, 0x0, 0x21, 0x0,
0x0, 0x0, 0x75, 0x62, 0x6F, 0x0, 0x5, 0x0, 0x4, 0x0,
0x2B, 0x0, 0x0, 0x0, 0x6D, 0x73, 0x64, 0x66, 0x0, 0x0,
0x0, 0x0, 0x5, 0x0, 0x6, 0x0, 0x32, 0x0, 0x0, 0x0,
0x73, 0x63, 0x72, 0x65, 0x65, 0x6E, 0x54, 0x65, 0x78, 0x53,
0x69, 0x7A, 0x65, 0x0, 0x0, 0x0, 0x5, 0x0, 0x5, 0x0,
0x36, 0x0, 0x0, 0x0, 0x69, 0x6E, 0x54, 0x65, 0x78, 0x43,
0x6F, 0x6F, 0x72, 0x64, 0x0, 0x0, 0x5, 0x0, 0x3, 0x0,
0x44, 0x0, 0x0, 0x0, 0x6D, 0x73, 0x64, 0x0, 0x5, 0x0,
0x3, 0x0, 0x4A, 0x0, 0x0, 0x0, 0x73, 0x64, 0x0, 0x0,
0x5, 0x0, 0x4, 0x0, 0x4B, 0x0, 0x0, 0x0, 0x70, 0x61,
0x72, 0x61, 0x6D, 0x0, 0x0, 0x0, 0x5, 0x0, 0x4, 0x0,
0x50, 0x0, 0x0, 0x0, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x0,
0x0, 0x0, 0x5, 0x0, 0x4, 0x0, 0x54, 0x0, 0x0, 0x0,
0x70, 0x61, 0x72, 0x61, 0x6D, 0x0, 0x0, 0x0, 0x5, 0x0,
0x7, 0x0, 0x59, 0x0, 0x0, 0x0, 0x73, 0x63, 0x72, 0x65,
0x65, 0x6E, 0x50, 0x78, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6E,
0x63, 0x65, 0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x4, 0x0,
0x5E, 0x0, 0x0, 0x0, 0x6F, 0x70, 0x61, 0x63, 0x69, 0x74,
0x79, 0x0, 0x5, 0x0, 0x5, 0x0, 0x64, 0x0, 0x0, 0x0,
0x6F, 0x75, 0x74, 0x43, 0x6F, 0x6C, 0x6F, 0x72, 0x0, 0x0,
0x0, 0x0, 0x5, 0x0, 0x4, 0x0, 0x67, 0x0, 0x0, 0x0,
0x69, 0x6E, 0x43, 0x6F, 0x6C, 0x6F, 0x72, 0x0, 0x48, 0x0,
0x5, 0x0, 0x1F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x23, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x47, 0x0,
0x3, 0x0, 0x1F, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0,
0x47, 0x0, 0x4, 0x0, 0x21, 0x0, 0x0, 0x0, 0x22, 0x0,
0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x47, 0x0, 0x4, 0x0,
0x21, 0x0, 0x0, 0x0, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x47, 0x0, 0x4, 0x0, 0x2B, 0x0, 0x0, 0x0,
0x22, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x47, 0x0,
0x4, 0x0, 0x2B, 0x0, 0x0, 0x0, 0x21, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x47, 0x0, 0x4, 0x0, 0x36, 0x0,
0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x47, 0x0, 0x4, 0x0, 0x64, 0x0, 0x0, 0x0, 0x1E, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x47, 0x0, 0x4, 0x0,
0x67, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x1, 0x0,
0x0, 0x0, 0x13, 0x0, 0x2, 0x0, 0x2, 0x0, 0x0, 0x0,
0x21, 0x0, 0x3, 0x0, 0x3, 0x0, 0x0, 0x0, 0x2, 0x0,
0x0, 0x0, 0x16, 0x0, 0x3, 0x0, 0x6, 0x0, 0x0, 0x0,
0x20, 0x0, 0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x7, 0x0,
0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0,
0x21, 0x0, 0x6, 0x0, 0x8, 0x0, 0x0, 0x0, 0x6, 0x0,
0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0,
0x7, 0x0, 0x0, 0x0, 0x21, 0x0, 0x3, 0x0, 0xE, 0x0,
0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x17, 0x0, 0x4, 0x0,
0x1C, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x2, 0x0,
0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x1D, 0x0, 0x0, 0x0,
0x7, 0x0, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x1E, 0x0,
0x3, 0x0, 0x1F, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0,
0x20, 0x0, 0x4, 0x0, 0x20, 0x0, 0x0, 0x0, 0x2, 0x0,
0x0, 0x0, 0x1F, 0x0, 0x0, 0x0, 0x3B, 0x0, 0x4, 0x0,
0x20, 0x0, 0x0, 0x0, 0x21, 0x0, 0x0, 0x0, 0x2, 0x0,
0x0, 0x0, 0x15, 0x0, 0x4, 0x0, 0x22, 0x0, 0x0, 0x0,
0x20, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2B, 0x0,
0x4, 0x0, 0x22, 0x0, 0x0, 0x0, 0x23, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x24, 0x0,
0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0,
0x19, 0x0, 0x9, 0x0, 0x28, 0x0, 0x0, 0x0, 0x6, 0x0,
0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1B, 0x0, 0x3, 0x0,
0x29, 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x20, 0x0,
0x4, 0x0, 0x2A, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x29, 0x0, 0x0, 0x0, 0x3B, 0x0, 0x4, 0x0, 0x2A, 0x0,
0x0, 0x0, 0x2B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x17, 0x0, 0x4, 0x0, 0x2E, 0x0, 0x0, 0x0, 0x22, 0x0,
0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0,
0x6, 0x0, 0x0, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0,
0x80, 0x3F, 0x2C, 0x0, 0x5, 0x0, 0x1C, 0x0, 0x0, 0x0,
0x34, 0x0, 0x0, 0x0, 0x33, 0x0, 0x0, 0x0, 0x33, 0x0,
0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x35, 0x0, 0x0, 0x0,
0x1, 0x0, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x3B, 0x0,
0x4, 0x0, 0x35, 0x0, 0x0, 0x0, 0x36, 0x0, 0x0, 0x0,
0x1, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0, 0x6, 0x0,
0x0, 0x0, 0x3A, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3F,
0x17, 0x0, 0x4, 0x0, 0x42, 0x0, 0x0, 0x0, 0x6, 0x0,
0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x20, 0x0, 0x4, 0x0,
0x43, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x42, 0x0,
0x0, 0x0, 0x17, 0x0, 0x4, 0x0, 0x47, 0x0, 0x0, 0x0,
0x6, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x15, 0x0,
0x4, 0x0, 0x4C, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0, 0x4C, 0x0,
0x0, 0x0, 0x4D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x2B, 0x0, 0x4, 0x0, 0x4C, 0x0, 0x0, 0x0, 0x51, 0x0,
0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0,
0x4C, 0x0, 0x0, 0x0, 0x55, 0x0, 0x0, 0x0, 0x2, 0x0,
0x0, 0x0, 0x2B, 0x0, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0,
0x61, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0,
0x4, 0x0, 0x63, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0,
0x47, 0x0, 0x0, 0x0, 0x3B, 0x0, 0x4, 0x0, 0x63, 0x0,
0x0, 0x0, 0x64, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0,
0x2C, 0x0, 0x7, 0x0, 0x47, 0x0, 0x0, 0x0, 0x65, 0x0,
0x0, 0x0, 0x61, 0x0, 0x0, 0x0, 0x61, 0x0, 0x0, 0x0,
0x61, 0x0, 0x0, 0x0, 0x61, 0x0, 0x0, 0x0, 0x20, 0x0,
0x4, 0x0, 0x66, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
0x47, 0x0, 0x0, 0x0, 0x3B, 0x0, 0x4, 0x0, 0x66, 0x0,
0x0, 0x0, 0x67, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
0x36, 0x0, 0x5, 0x0, 0x2, 0x0, 0x0, 0x0, 0x4, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0,
0xF8, 0x0, 0x2, 0x0, 0x5, 0x0, 0x0, 0x0, 0x3B, 0x0,
0x4, 0x0, 0x43, 0x0, 0x0, 0x0, 0x44, 0x0, 0x0, 0x0,
0x7, 0x0, 0x0, 0x0, 0x3B, 0x0, 0x4, 0x0, 0x7, 0x0,
0x0, 0x0, 0x4A, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0,
0x3B, 0x0, 0x4, 0x0, 0x7, 0x0, 0x0, 0x0, 0x4B, 0x0,
0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x3B, 0x0, 0x4, 0x0,
0x7, 0x0, 0x0, 0x0, 0x50, 0x0, 0x0, 0x0, 0x7, 0x0,
0x0, 0x0, 0x3B, 0x0, 0x4, 0x0, 0x7, 0x0, 0x0, 0x0,
0x54, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x3B, 0x0,
0x4, 0x0, 0x7, 0x0, 0x0, 0x0, 0x59, 0x0, 0x0, 0x0,
0x7, 0x0, 0x0, 0x0, 0x3B, 0x0, 0x4, 0x0, 0x7, 0x0,
0x0, 0x0, 0x5E, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0,
0x3D, 0x0, 0x4, 0x0, 0x29, 0x0, 0x0, 0x0, 0x45, 0x0,
0x0, 0x0, 0x2B, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0,
0x1C, 0x0, 0x0, 0x0, 0x46, 0x0, 0x0, 0x0, 0x36, 0x0,
0x0, 0x0, 0x57, 0x0, 0x5, 0x0, 0x47, 0x0, 0x0, 0x0,
0x48, 0x0, 0x0, 0x0, 0x45, 0x0, 0x0, 0x0, 0x46, 0x0,
0x0, 0x0, 0x4F, 0x0, 0x8, 0x0, 0x42, 0x0, 0x0, 0x0,
0x49, 0x0, 0x0, 0x0, 0x48, 0x0, 0x0, 0x0, 0x48, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
0x2, 0x0, 0x0, 0x0, 0x3E, 0x0, 0x3, 0x0, 0x44, 0x0,
0x0, 0x0, 0x49, 0x0, 0x0, 0x0, 0x41, 0x0, 0x5, 0x0,
0x7, 0x0, 0x0, 0x0, 0x4E, 0x0, 0x0, 0x0, 0x44, 0x0,
0x0, 0x0, 0x4D, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0,
0x6, 0x0, 0x0, 0x0, 0x4F, 0x0, 0x0, 0x0, 0x4E, 0x0,
0x0, 0x0, 0x3E, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x0, 0x0,
0x4F, 0x0, 0x0, 0x0, 0x41, 0x0, 0x5, 0x0, 0x7, 0x0,
0x0, 0x0, 0x52, 0x0, 0x0, 0x0, 0x44, 0x0, 0x0, 0x0,
0x51, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0, 0x6, 0x0,
0x0, 0x0, 0x53, 0x0, 0x0, 0x0, 0x52, 0x0, 0x0, 0x0,
0x3E, 0x0, 0x3, 0x0, 0x50, 0x0, 0x0, 0x0, 0x53, 0x0,
0x0, 0x0, 0x41, 0x0, 0x5, 0x0, 0x7, 0x0, 0x0, 0x0,
0x56, 0x0, 0x0, 0x0, 0x44, 0x0, 0x0, 0x0, 0x55, 0x0,
0x0, 0x0, 0x3D, 0x0, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0,
0x57, 0x0, 0x0, 0x0, 0x56, 0x0, 0x0, 0x0, 0x3E, 0x0,
0x3, 0x0, 0x54, 0x0, 0x0, 0x0, 0x57, 0x0, 0x0, 0x0,
0x39, 0x0, 0x7, 0x0, 0x6, 0x0, 0x0, 0x0, 0x58, 0x0,
0x0, 0x0, 0xC, 0x0, 0x0, 0x0, 0x4B, 0x0, 0x0, 0x0,
0x50, 0x0, 0x0, 0x0, 0x54, 0x0, 0x0, 0x0, 0x3E, 0x0,
0x3, 0x0, 0x4A, 0x0, 0x0, 0x0, 0x58, 0x0, 0x0, 0x0,
0x39, 0x0, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0, 0x5A, 0x0,
0x0, 0x0, 0xF, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0,
0x6, 0x0, 0x0, 0x0, 0x5B, 0x0, 0x0, 0x0, 0x4A, 0x0,
0x0, 0x0, 0x83, 0x0, 0x5, 0x0, 0x6, 0x0, 0x0, 0x0,
0x5C, 0x0, 0x0, 0x0, 0x5B, 0x0, 0x0, 0x0, 0x3A, 0x0,
0x0, 0x0, 0x85, 0x0, 0x5, 0x0, 0x6, 0x0, 0x0, 0x0,
0x5D, 0x0, 0x0, 0x0, 0x5A, 0x0, 0x0, 0x0, 0x5C, 0x0,
0x0, 0x0, 0x3E, 0x0, 0x3, 0x0, 0x59, 0x0, 0x0, 0x0,
0x5D, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0, 0x6, 0x0,
0x0, 0x0, 0x5F, 0x0, 0x0, 0x0, 0x59, 0x0, 0x0, 0x0,
0x81, 0x0, 0x5, 0x0, 0x6, 0x0, 0x0, 0x0, 0x60, 0x0,
0x0, 0x0, 0x5F, 0x0, 0x0, 0x0, 0x3A, 0x0, 0x0, 0x0,
0xC, 0x0, 0x8, 0x0, 0x6, 0x0, 0x0, 0x0, 0x62, 0x0,
0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x0, 0x0,
0x60, 0x0, 0x0, 0x0, 0x61, 0x0, 0x0, 0x0, 0x33, 0x0,
0x0, 0x0, 0x3E, 0x0, 0x3, 0x0, 0x5E, 0x0, 0x0, 0x0,
0x62, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0, 0x47, 0x0,
0x0, 0x0, 0x68, 0x0, 0x0, 0x0, 0x67, 0x0, 0x0, 0x0,
0x3D, 0x0, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0, 0x69, 0x0,
0x0, 0x0, 0x5E, 0x0, 0x0, 0x0, 0x50, 0x0, 0x7, 0x0,
0x47, 0x0, 0x0, 0x0, 0x6A, 0x0, 0x0, 0x0, 0x69, 0x0,
0x0, 0x0, 0x69, 0x0, 0x0, 0x0, 0x69, 0x0, 0x0, 0x0,
0x69, 0x0, 0x0, 0x0, 0xC, 0x0, 0x8, 0x0, 0x47, 0x0,
0x0, 0x0, 0x6B, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
0x2E, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0x68, 0x0,
0x0, 0x0, 0x6A, 0x0, 0x0, 0x0, 0x3E, 0x0, 0x3, 0x0,
0x64, 0x0, 0x0, 0x0, 0x6B, 0x0, 0x0, 0x0, 0xFD, 0x0,
0x1, 0x0, 0x38, 0x0, 0x1, 0x0, 0x36, 0x0, 0x5, 0x0,
0x6, 0x0, 0x0, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x37, 0x0, 0x3, 0x0,
0x7, 0x0, 0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x37, 0x0,
0x3, 0x0, 0x7, 0x0, 0x0, 0x0, 0xA, 0x0, 0x0, 0x0,
0x37, 0x0, 0x3, 0x0, 0x7, 0x0, 0x0, 0x0, 0xB, 0x0,
0x0, 0x0, 0xF8, 0x0, 0x2, 0x0, 0xD, 0x0, 0x0, 0x0,
0x3D, 0x0, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0, 0x11, 0x0,
0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0,
0x6, 0x0, 0x0, 0x0, 0x12, 0x0, 0x0, 0x0, 0xA, 0x0,
0x0, 0x0, 0xC, 0x0, 0x7, 0x0, 0x6, 0x0, 0x0, 0x0,
0x13, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x25, 0x0,
0x0, 0x0, 0x11, 0x0, 0x0, 0x0, 0x12, 0x0, 0x0, 0x0,
0x3D, 0x0, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0, 0x14, 0x0,
0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0,
0x6, 0x0, 0x0, 0x0, 0x15, 0x0, 0x0, 0x0, 0xA, 0x0,
0x0, 0x0, 0xC, 0x0, 0x7, 0x0, 0x6, 0x0, 0x0, 0x0,
0x16, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x28, 0x0,
0x0, 0x0, 0x14, 0x0, 0x0, 0x0, 0x15, 0x0, 0x0, 0x0,
0x3D, 0x0, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0, 0x17, 0x0,
0x0, 0x0, 0xB, 0x0, 0x0, 0x0, 0xC, 0x0, 0x7, 0x0,
0x6, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x1, 0x0,
0x0, 0x0, 0x25, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0,
0x17, 0x0, 0x0, 0x0, 0xC, 0x0, 0x7, 0x0, 0x6, 0x0,
0x0, 0x0, 0x19, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
0x28, 0x0, 0x0, 0x0, 0x13, 0x0, 0x0, 0x0, 0x18, 0x0,
0x0, 0x0, 0xFE, 0x0, 0x2, 0x0, 0x19, 0x0, 0x0, 0x0,
0x38, 0x0, 0x1, 0x0, 0x36, 0x0, 0x5, 0x0, 0x6, 0x0,
0x0, 0x0, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0xE, 0x0, 0x0, 0x0, 0xF8, 0x0, 0x2, 0x0, 0x10, 0x0,
0x0, 0x0, 0x3B, 0x0, 0x4, 0x0, 0x1D, 0x0, 0x0, 0x0,
0x1E, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x3B, 0x0,
0x4, 0x0, 0x1D, 0x0, 0x0, 0x0, 0x32, 0x0, 0x0, 0x0,
0x7, 0x0, 0x0, 0x0, 0x41, 0x0, 0x5, 0x0, 0x24, 0x0,
0x0, 0x0, 0x25, 0x0, 0x0, 0x0, 0x21, 0x0, 0x0, 0x0,
0x23, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0, 0x6, 0x0,
0x0, 0x0, 0x26, 0x0, 0x0, 0x0, 0x25, 0x0, 0x0, 0x0,
0x50, 0x0, 0x5, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x27, 0x0,
0x0, 0x0, 0x26, 0x0, 0x0, 0x0, 0x26, 0x0, 0x0, 0x0,
0x3D, 0x0, 0x4, 0x0, 0x29, 0x0, 0x0, 0x0, 0x2C, 0x0,
0x0, 0x0, 0x2B, 0x0, 0x0, 0x0, 0x64, 0x0, 0x4, 0x0,
0x28, 0x0, 0x0, 0x0, 0x2D, 0x0, 0x0, 0x0, 0x2C, 0x0,
0x0, 0x0, 0x67, 0x0, 0x5, 0x0, 0x2E, 0x0, 0x0, 0x0,
0x2F, 0x0, 0x0, 0x0, 0x2D, 0x0, 0x0, 0x0, 0x23, 0x0,
0x0, 0x0, 0x6F, 0x0, 0x4, 0x0, 0x1C, 0x0, 0x0, 0x0,
0x30, 0x0, 0x0, 0x0, 0x2F, 0x0, 0x0, 0x0, 0x88, 0x0,
0x5, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x31, 0x0, 0x0, 0x0,
0x27, 0x0, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x3E, 0x0,
0x3, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x31, 0x0, 0x0, 0x0,
0x3D, 0x0, 0x4, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x37, 0x0,
0x0, 0x0, 0x36, 0x0, 0x0, 0x0, 0xD1, 0x0, 0x4, 0x0,
0x1C, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0x37, 0x0,
0x0, 0x0, 0x88, 0x0, 0x5, 0x0, 0x1C, 0x0, 0x0, 0x0,
0x39, 0x0, 0x0, 0x0, 0x34, 0x0, 0x0, 0x0, 0x38, 0x0,
0x0, 0x0, 0x3E, 0x0, 0x3, 0x0, 0x32, 0x0, 0x0, 0x0,
0x39, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0, 0x1C, 0x0,
0x0, 0x0, 0x3B, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x0,
0x3D, 0x0, 0x4, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x3C, 0x0,
0x0, 0x0, 0x32, 0x0, 0x0, 0x0, 0x94, 0x0, 0x5, 0x0,
0x6, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x0, 0x0, 0x3B, 0x0,
0x0, 0x0, 0x3C, 0x0, 0x0, 0x0, 0x85, 0x0, 0x5, 0x0,
0x6, 0x0, 0x0, 0x0, 0x3E, 0x0, 0x0, 0x0, 0x3A, 0x0,
0x0, 0x0, 0x3D, 0x0, 0x0, 0x0, 0xC, 0x0, 0x7, 0x0,
0x6, 0x0, 0x0, 0x0, 0x3F, 0x0, 0x0, 0x0, 0x1, 0x0,
0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x3E, 0x0, 0x0, 0x0,
0x33, 0x0, 0x0, 0x0, 0xFE, 0x0, 0x2, 0x0, 0x3F, 0x0,
0x0, 0x0, 0x38, 0x0, 0x1, 0x0,
];
public byte[] TextTransformVert { get; } =
[
0x3, 0x2, 0x23, 0x7, 0x0, 0x0, 0x1, 0x0, 0xB, 0x0,
0x8, 0x0, 0x2D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x11, 0x0, 0x2, 0x0, 0x1, 0x0, 0x0, 0x0, 0xB, 0x0,
0x6, 0x0, 0x1, 0x0, 0x0, 0x0, 0x47, 0x4C, 0x53, 0x4C,
0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, 0x0, 0x0,
0x0, 0x0, 0xE, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0,
0x1, 0x0, 0x0, 0x0, 0xF, 0x0, 0xB, 0x0, 0x0, 0x0,
0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x6D, 0x61, 0x69, 0x6E,
0x0, 0x0, 0x0, 0x0, 0xD, 0x0, 0x0, 0x0, 0x19, 0x0,
0x0, 0x0, 0x25, 0x0, 0x0, 0x0, 0x27, 0x0, 0x0, 0x0,
0x29, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x0, 0x0, 0x3, 0x0,
0x3, 0x0, 0x2, 0x0, 0x0, 0x0, 0xC2, 0x1, 0x0, 0x0,
0x5, 0x0, 0x4, 0x0, 0x4, 0x0, 0x0, 0x0, 0x6D, 0x61,
0x69, 0x6E, 0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x6, 0x0,
0xB, 0x0, 0x0, 0x0, 0x67, 0x6C, 0x5F, 0x50, 0x65, 0x72,
0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x0, 0x0, 0x0, 0x0,
0x6, 0x0, 0x6, 0x0, 0xB, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x67, 0x6C, 0x5F, 0x50, 0x6F, 0x73, 0x69, 0x74,
0x69, 0x6F, 0x6E, 0x0, 0x6, 0x0, 0x7, 0x0, 0xB, 0x0,
0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x67, 0x6C, 0x5F, 0x50,
0x6F, 0x69, 0x6E, 0x74, 0x53, 0x69, 0x7A, 0x65, 0x0, 0x0,
0x0, 0x0, 0x6, 0x0, 0x7, 0x0, 0xB, 0x0, 0x0, 0x0,
0x2, 0x0, 0x0, 0x0, 0x67, 0x6C, 0x5F, 0x43, 0x6C, 0x69,
0x70, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x0,
0x6, 0x0, 0x7, 0x0, 0xB, 0x0, 0x0, 0x0, 0x3, 0x0,
0x0, 0x0, 0x67, 0x6C, 0x5F, 0x43, 0x75, 0x6C, 0x6C, 0x44,
0x69, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x0, 0x5, 0x0,
0x3, 0x0, 0xD, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x5, 0x0, 0x3, 0x0, 0x11, 0x0, 0x0, 0x0, 0x55, 0x42,
0x4F, 0x0, 0x6, 0x0, 0x7, 0x0, 0x11, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72,
0x6F, 0x6A, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x0, 0x0,
0x5, 0x0, 0x3, 0x0, 0x13, 0x0, 0x0, 0x0, 0x75, 0x62,
0x6F, 0x0, 0x5, 0x0, 0x4, 0x0, 0x19, 0x0, 0x0, 0x0,
0x69, 0x6E, 0x50, 0x6F, 0x73, 0x0, 0x0, 0x0, 0x5, 0x0,
0x5, 0x0, 0x25, 0x0, 0x0, 0x0, 0x6F, 0x75, 0x74, 0x54,
0x65, 0x78, 0x43, 0x6F, 0x6F, 0x72, 0x64, 0x0, 0x5, 0x0,
0x5, 0x0, 0x27, 0x0, 0x0, 0x0, 0x69, 0x6E, 0x54, 0x65,
0x78, 0x43, 0x6F, 0x6F, 0x72, 0x64, 0x0, 0x0, 0x5, 0x0,
0x5, 0x0, 0x29, 0x0, 0x0, 0x0, 0x6F, 0x75, 0x74, 0x43,
0x6F, 0x6C, 0x6F, 0x72, 0x0, 0x0, 0x0, 0x0, 0x5, 0x0,
0x4, 0x0, 0x2B, 0x0, 0x0, 0x0, 0x69, 0x6E, 0x43, 0x6F,
0x6C, 0x6F, 0x72, 0x0, 0x48, 0x0, 0x5, 0x0, 0xB, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x48, 0x0, 0x5, 0x0, 0xB, 0x0,
0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xB, 0x0, 0x0, 0x0,
0x1, 0x0, 0x0, 0x0, 0x48, 0x0, 0x5, 0x0, 0xB, 0x0,
0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0xB, 0x0, 0x0, 0x0,
0x3, 0x0, 0x0, 0x0, 0x48, 0x0, 0x5, 0x0, 0xB, 0x0,
0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0xB, 0x0, 0x0, 0x0,
0x4, 0x0, 0x0, 0x0, 0x47, 0x0, 0x3, 0x0, 0xB, 0x0,
0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x48, 0x0, 0x4, 0x0,
0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x0,
0x0, 0x0, 0x48, 0x0, 0x5, 0x0, 0x11, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x23, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x48, 0x0, 0x5, 0x0, 0x11, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x10, 0x0,
0x0, 0x0, 0x47, 0x0, 0x3, 0x0, 0x11, 0x0, 0x0, 0x0,
0x2, 0x0, 0x0, 0x0, 0x47, 0x0, 0x4, 0x0, 0x13, 0x0,
0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
0x47, 0x0, 0x4, 0x0, 0x13, 0x0, 0x0, 0x0, 0x21, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x47, 0x0, 0x4, 0x0,
0x19, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x47, 0x0, 0x4, 0x0, 0x25, 0x0, 0x0, 0x0,
0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x47, 0x0,
0x4, 0x0, 0x27, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x0,
0x1, 0x0, 0x0, 0x0, 0x47, 0x0, 0x4, 0x0, 0x29, 0x0,
0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
0x47, 0x0, 0x4, 0x0, 0x2B, 0x0, 0x0, 0x0, 0x1E, 0x0,
0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x13, 0x0, 0x2, 0x0,
0x2, 0x0, 0x0, 0x0, 0x21, 0x0, 0x3, 0x0, 0x3, 0x0,
0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x16, 0x0, 0x3, 0x0,
0x6, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x17, 0x0,
0x4, 0x0, 0x7, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0,
0x4, 0x0, 0x0, 0x0, 0x15, 0x0, 0x4, 0x0, 0x8, 0x0,
0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x2B, 0x0, 0x4, 0x0, 0x8, 0x0, 0x0, 0x0, 0x9, 0x0,
0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1C, 0x0, 0x4, 0x0,
0xA, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x9, 0x0,
0x0, 0x0, 0x1E, 0x0, 0x6, 0x0, 0xB, 0x0, 0x0, 0x0,
0x7, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0xA, 0x0,
0x0, 0x0, 0xA, 0x0, 0x0, 0x0, 0x20, 0x0, 0x4, 0x0,
0xC, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0xB, 0x0,
0x0, 0x0, 0x3B, 0x0, 0x4, 0x0, 0xC, 0x0, 0x0, 0x0,
0xD, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x15, 0x0,
0x4, 0x0, 0xE, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0,
0x1, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0, 0xE, 0x0,
0x0, 0x0, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x18, 0x0, 0x4, 0x0, 0x10, 0x0, 0x0, 0x0, 0x7, 0x0,
0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x3, 0x0,
0x11, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x20, 0x0,
0x4, 0x0, 0x12, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0,
0x11, 0x0, 0x0, 0x0, 0x3B, 0x0, 0x4, 0x0, 0x12, 0x0,
0x0, 0x0, 0x13, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0,
0x20, 0x0, 0x4, 0x0, 0x14, 0x0, 0x0, 0x0, 0x2, 0x0,
0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x17, 0x0, 0x4, 0x0,
0x17, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x3, 0x0,
0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x18, 0x0, 0x0, 0x0,
0x1, 0x0, 0x0, 0x0, 0x17, 0x0, 0x0, 0x0, 0x3B, 0x0,
0x4, 0x0, 0x18, 0x0, 0x0, 0x0, 0x19, 0x0, 0x0, 0x0,
0x1, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0, 0x6, 0x0,
0x0, 0x0, 0x1B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3F,
0x20, 0x0, 0x4, 0x0, 0x21, 0x0, 0x0, 0x0, 0x3, 0x0,
0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x17, 0x0, 0x4, 0x0,
0x23, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x2, 0x0,
0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x24, 0x0, 0x0, 0x0,
0x3, 0x0, 0x0, 0x0, 0x23, 0x0, 0x0, 0x0, 0x3B, 0x0,
0x4, 0x0, 0x24, 0x0, 0x0, 0x0, 0x25, 0x0, 0x0, 0x0,
0x3, 0x0, 0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x26, 0x0,
0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x23, 0x0, 0x0, 0x0,
0x3B, 0x0, 0x4, 0x0, 0x26, 0x0, 0x0, 0x0, 0x27, 0x0,
0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x3B, 0x0, 0x4, 0x0,
0x21, 0x0, 0x0, 0x0, 0x29, 0x0, 0x0, 0x0, 0x3, 0x0,
0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x2A, 0x0, 0x0, 0x0,
0x1, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x3B, 0x0,
0x4, 0x0, 0x2A, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x0, 0x0,
0x1, 0x0, 0x0, 0x0, 0x36, 0x0, 0x5, 0x0, 0x2, 0x0,
0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x3, 0x0, 0x0, 0x0, 0xF8, 0x0, 0x2, 0x0, 0x5, 0x0,
0x0, 0x0, 0x41, 0x0, 0x5, 0x0, 0x14, 0x0, 0x0, 0x0,
0x15, 0x0, 0x0, 0x0, 0x13, 0x0, 0x0, 0x0, 0xF, 0x0,
0x0, 0x0, 0x3D, 0x0, 0x4, 0x0, 0x10, 0x0, 0x0, 0x0,
0x16, 0x0, 0x0, 0x0, 0x15, 0x0, 0x0, 0x0, 0x3D, 0x0,
0x4, 0x0, 0x17, 0x0, 0x0, 0x0, 0x1A, 0x0, 0x0, 0x0,
0x19, 0x0, 0x0, 0x0, 0x51, 0x0, 0x5, 0x0, 0x6, 0x0,
0x0, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x1A, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x51, 0x0, 0x5, 0x0, 0x6, 0x0,
0x0, 0x0, 0x1D, 0x0, 0x0, 0x0, 0x1A, 0x0, 0x0, 0x0,
0x1, 0x0, 0x0, 0x0, 0x51, 0x0, 0x5, 0x0, 0x6, 0x0,
0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x1A, 0x0, 0x0, 0x0,
0x2, 0x0, 0x0, 0x0, 0x50, 0x0, 0x7, 0x0, 0x7, 0x0,
0x0, 0x0, 0x1F, 0x0, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x0,
0x1D, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x1B, 0x0,
0x0, 0x0, 0x91, 0x0, 0x5, 0x0, 0x7, 0x0, 0x0, 0x0,
0x20, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x1F, 0x0,
0x0, 0x0, 0x41, 0x0, 0x5, 0x0, 0x21, 0x0, 0x0, 0x0,
0x22, 0x0, 0x0, 0x0, 0xD, 0x0, 0x0, 0x0, 0xF, 0x0,
0x0, 0x0, 0x3E, 0x0, 0x3, 0x0, 0x22, 0x0, 0x0, 0x0,
0x20, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0, 0x23, 0x0,
0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x27, 0x0, 0x0, 0x0,
0x3E, 0x0, 0x3, 0x0, 0x25, 0x0, 0x0, 0x0, 0x28, 0x0,
0x0, 0x0, 0x3D, 0x0, 0x4, 0x0, 0x7, 0x0, 0x0, 0x0,
0x2C, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x0, 0x0, 0x3E, 0x0,
0x3, 0x0, 0x29, 0x0, 0x0, 0x0, 0x2C, 0x0, 0x0, 0x0,
0xFD, 0x0, 0x1, 0x0, 0x38, 0x0, 0x1, 0x0,
];
public byte[] VideoYuv2RgbaFrag { get; } =
[
0x3, 0x2, 0x23, 0x7, 0x0, 0x0, 0x1, 0x0, 0xB, 0x0,
0x8, 0x0, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x11, 0x0, 0x2, 0x0, 0x1, 0x0, 0x0, 0x0, 0xB, 0x0,
0x6, 0x0, 0x1, 0x0, 0x0, 0x0, 0x47, 0x4C, 0x53, 0x4C,
0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, 0x0, 0x0,
0x0, 0x0, 0xE, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0,
0x1, 0x0, 0x0, 0x0, 0xF, 0x0, 0x7, 0x0, 0x4, 0x0,
0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x6D, 0x61, 0x69, 0x6E,
0x0, 0x0, 0x0, 0x0, 0x11, 0x0, 0x0, 0x0, 0x2E, 0x0,
0x0, 0x0, 0x10, 0x0, 0x3, 0x0, 0x4, 0x0, 0x0, 0x0,
0x7, 0x0, 0x0, 0x0, 0x3, 0x0, 0x3, 0x0, 0x2, 0x0,
0x0, 0x0, 0xC2, 0x1, 0x0, 0x0, 0x5, 0x0, 0x4, 0x0,
0x4, 0x0, 0x0, 0x0, 0x6D, 0x61, 0x69, 0x6E, 0x0, 0x0,
0x0, 0x0, 0x5, 0x0, 0x3, 0x0, 0x9, 0x0, 0x0, 0x0,
0x79, 0x75, 0x76, 0x0, 0x5, 0x0, 0x5, 0x0, 0xD, 0x0,
0x0, 0x0, 0x59, 0x53, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x72,
0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x5, 0x0, 0x11, 0x0,
0x0, 0x0, 0x54, 0x65, 0x78, 0x43, 0x6F, 0x6F, 0x72, 0x64,
0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x5, 0x0, 0x1A, 0x0,
0x0, 0x0, 0x55, 0x53, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x72,
0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x5, 0x0, 0x21, 0x0,
0x0, 0x0, 0x56, 0x53, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x72,
0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x5, 0x0, 0x2E, 0x0,
0x0, 0x0, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6F, 0x6C, 0x6F,
0x72, 0x0, 0x0, 0x0, 0x47, 0x0, 0x4, 0x0, 0xD, 0x0,
0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0,
0x47, 0x0, 0x4, 0x0, 0xD, 0x0, 0x0, 0x0, 0x21, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x47, 0x0, 0x4, 0x0,
0x11, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x47, 0x0, 0x4, 0x0, 0x1A, 0x0, 0x0, 0x0,
0x22, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x47, 0x0,
0x4, 0x0, 0x1A, 0x0, 0x0, 0x0, 0x21, 0x0, 0x0, 0x0,
0x1, 0x0, 0x0, 0x0, 0x47, 0x0, 0x4, 0x0, 0x21, 0x0,
0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0,
0x47, 0x0, 0x4, 0x0, 0x21, 0x0, 0x0, 0x0, 0x21, 0x0,
0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x47, 0x0, 0x4, 0x0,
0x2E, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x13, 0x0, 0x2, 0x0, 0x2, 0x0, 0x0, 0x0,
0x21, 0x0, 0x3, 0x0, 0x3, 0x0, 0x0, 0x0, 0x2, 0x0,
0x0, 0x0, 0x16, 0x0, 0x3, 0x0, 0x6, 0x0, 0x0, 0x0,
0x20, 0x0, 0x0, 0x0, 0x17, 0x0, 0x4, 0x0, 0x7, 0x0,
0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0,
0x20, 0x0, 0x4, 0x0, 0x8, 0x0, 0x0, 0x0, 0x7, 0x0,
0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x19, 0x0, 0x9, 0x0,
0xA, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x1, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x1B, 0x0, 0x3, 0x0, 0xB, 0x0, 0x0, 0x0,
0xA, 0x0, 0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0xC, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB, 0x0, 0x0, 0x0,
0x3B, 0x0, 0x4, 0x0, 0xC, 0x0, 0x0, 0x0, 0xD, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x17, 0x0, 0x4, 0x0,
0xF, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x2, 0x0,
0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x10, 0x0, 0x0, 0x0,
0x1, 0x0, 0x0, 0x0, 0xF, 0x0, 0x0, 0x0, 0x3B, 0x0,
0x4, 0x0, 0x10, 0x0, 0x0, 0x0, 0x11, 0x0, 0x0, 0x0,
0x1, 0x0, 0x0, 0x0, 0x17, 0x0, 0x4, 0x0, 0x13, 0x0,
0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0,
0x15, 0x0, 0x4, 0x0, 0x15, 0x0, 0x0, 0x0, 0x20, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0,
0x15, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x18, 0x0, 0x0, 0x0,
0x7, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x3B, 0x0,
0x4, 0x0, 0xC, 0x0, 0x0, 0x0, 0x1A, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0, 0x15, 0x0,
0x0, 0x0, 0x1F, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
0x3B, 0x0, 0x4, 0x0, 0xC, 0x0, 0x0, 0x0, 0x21, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0,
0x15, 0x0, 0x0, 0x0, 0x26, 0x0, 0x0, 0x0, 0x2, 0x0,
0x0, 0x0, 0x2B, 0x0, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0,
0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0xBD, 0x2B, 0x0,
0x4, 0x0, 0x6, 0x0, 0x0, 0x0, 0x29, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0xBF, 0x2C, 0x0, 0x6, 0x0, 0x7, 0x0,
0x0, 0x0, 0x2A, 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0,
0x29, 0x0, 0x0, 0x0, 0x29, 0x0, 0x0, 0x0, 0x20, 0x0,
0x4, 0x0, 0x2D, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0,
0x13, 0x0, 0x0, 0x0, 0x3B, 0x0, 0x4, 0x0, 0x2D, 0x0,
0x0, 0x0, 0x2E, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0,
0x2B, 0x0, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0, 0x30, 0x0,
0x0, 0x0, 0xF4, 0xFD, 0x94, 0x3F, 0x2B, 0x0, 0x4, 0x0,
0x6, 0x0, 0x0, 0x0, 0x31, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x2B, 0x0, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0,
0x32, 0x0, 0x0, 0x0, 0x6, 0x81, 0xE5, 0x3F, 0x2C, 0x0,
0x6, 0x0, 0x7, 0x0, 0x0, 0x0, 0x33, 0x0, 0x0, 0x0,
0x30, 0x0, 0x0, 0x0, 0x31, 0x0, 0x0, 0x0, 0x32, 0x0,
0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x35, 0x0, 0x0, 0x0,
0x3, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x2B, 0x0,
0x4, 0x0, 0x6, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0,
0xAC, 0x1C, 0x5A, 0xBE, 0x2B, 0x0, 0x4, 0x0, 0x6, 0x0,
0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0xB0, 0x72, 0x8, 0xBF,
0x2C, 0x0, 0x6, 0x0, 0x7, 0x0, 0x0, 0x0, 0x3A, 0x0,
0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0,
0x39, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0, 0x6, 0x0,
0x0, 0x0, 0x3E, 0x0, 0x0, 0x0, 0x2, 0x2B, 0x7, 0x40,
0x2C, 0x0, 0x6, 0x0, 0x7, 0x0, 0x0, 0x0, 0x3F, 0x0,
0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x3E, 0x0, 0x0, 0x0,
0x31, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0, 0x6, 0x0,
0x0, 0x0, 0x42, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3F,
0x2B, 0x0, 0x4, 0x0, 0x15, 0x0, 0x0, 0x0, 0x43, 0x0,
0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x36, 0x0, 0x5, 0x0,
0x2, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0xF8, 0x0, 0x2, 0x0,
0x5, 0x0, 0x0, 0x0, 0x3B, 0x0, 0x4, 0x0, 0x8, 0x0,
0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0,
0x3D, 0x0, 0x4, 0x0, 0xB, 0x0, 0x0, 0x0, 0xE, 0x0,
0x0, 0x0, 0xD, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0,
0xF, 0x0, 0x0, 0x0, 0x12, 0x0, 0x0, 0x0, 0x11, 0x0,
0x0, 0x0, 0x57, 0x0, 0x5, 0x0, 0x13, 0x0, 0x0, 0x0,
0x14, 0x0, 0x0, 0x0, 0xE, 0x0, 0x0, 0x0, 0x12, 0x0,
0x0, 0x0, 0x51, 0x0, 0x5, 0x0, 0x6, 0x0, 0x0, 0x0,
0x17, 0x0, 0x0, 0x0, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x41, 0x0, 0x5, 0x0, 0x18, 0x0, 0x0, 0x0,
0x19, 0x0, 0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x16, 0x0,
0x0, 0x0, 0x3E, 0x0, 0x3, 0x0, 0x19, 0x0, 0x0, 0x0,
0x17, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0, 0xB, 0x0,
0x0, 0x0, 0x1B, 0x0, 0x0, 0x0, 0x1A, 0x0, 0x0, 0x0,
0x3D, 0x0, 0x4, 0x0, 0xF, 0x0, 0x0, 0x0, 0x1C, 0x0,
0x0, 0x0, 0x11, 0x0, 0x0, 0x0, 0x57, 0x0, 0x5, 0x0,
0x13, 0x0, 0x0, 0x0, 0x1D, 0x0, 0x0, 0x0, 0x1B, 0x0,
0x0, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x51, 0x0, 0x5, 0x0,
0x6, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x1D, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x41, 0x0, 0x5, 0x0,
0x18, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x9, 0x0,
0x0, 0x0, 0x1F, 0x0, 0x0, 0x0, 0x3E, 0x0, 0x3, 0x0,
0x20, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x3D, 0x0,
0x4, 0x0, 0xB, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0,
0x21, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0, 0xF, 0x0,
0x0, 0x0, 0x23, 0x0, 0x0, 0x0, 0x11, 0x0, 0x0, 0x0,
0x57, 0x0, 0x5, 0x0, 0x13, 0x0, 0x0, 0x0, 0x24, 0x0,
0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x23, 0x0, 0x0, 0x0,
0x51, 0x0, 0x5, 0x0, 0x6, 0x0, 0x0, 0x0, 0x25, 0x0,
0x0, 0x0, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x41, 0x0, 0x5, 0x0, 0x18, 0x0, 0x0, 0x0, 0x27, 0x0,
0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x26, 0x0, 0x0, 0x0,
0x3E, 0x0, 0x3, 0x0, 0x27, 0x0, 0x0, 0x0, 0x25, 0x0,
0x0, 0x0, 0x3D, 0x0, 0x4, 0x0, 0x7, 0x0, 0x0, 0x0,
0x2B, 0x0, 0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x81, 0x0,
0x5, 0x0, 0x7, 0x0, 0x0, 0x0, 0x2C, 0x0, 0x0, 0x0,
0x2B, 0x0, 0x0, 0x0, 0x2A, 0x0, 0x0, 0x0, 0x3E, 0x0,
0x3, 0x0, 0x9, 0x0, 0x0, 0x0, 0x2C, 0x0, 0x0, 0x0,
0x3D, 0x0, 0x4, 0x0, 0x7, 0x0, 0x0, 0x0, 0x2F, 0x0,
0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x94, 0x0, 0x5, 0x0,
0x6, 0x0, 0x0, 0x0, 0x34, 0x0, 0x0, 0x0, 0x2F, 0x0,
0x0, 0x0, 0x33, 0x0, 0x0, 0x0, 0x41, 0x0, 0x5, 0x0,
0x35, 0x0, 0x0, 0x0, 0x36, 0x0, 0x0, 0x0, 0x2E, 0x0,
0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x3E, 0x0, 0x3, 0x0,
0x36, 0x0, 0x0, 0x0, 0x34, 0x0, 0x0, 0x0, 0x3D, 0x0,
0x4, 0x0, 0x7, 0x0, 0x0, 0x0, 0x37, 0x0, 0x0, 0x0,
0x9, 0x0, 0x0, 0x0, 0x94, 0x0, 0x5, 0x0, 0x6, 0x0,
0x0, 0x0, 0x3B, 0x0, 0x0, 0x0, 0x37, 0x0, 0x0, 0x0,
0x3A, 0x0, 0x0, 0x0, 0x41, 0x0, 0x5, 0x0, 0x35, 0x0,
0x0, 0x0, 0x3C, 0x0, 0x0, 0x0, 0x2E, 0x0, 0x0, 0x0,
0x1F, 0x0, 0x0, 0x0, 0x3E, 0x0, 0x3, 0x0, 0x3C, 0x0,
0x0, 0x0, 0x3B, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0,
0x7, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x0, 0x0, 0x9, 0x0,
0x0, 0x0, 0x94, 0x0, 0x5, 0x0, 0x6, 0x0, 0x0, 0x0,
0x40, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x0, 0x0, 0x3F, 0x0,
0x0, 0x0, 0x41, 0x0, 0x5, 0x0, 0x35, 0x0, 0x0, 0x0,
0x41, 0x0, 0x0, 0x0, 0x2E, 0x0, 0x0, 0x0, 0x26, 0x0,
0x0, 0x0, 0x3E, 0x0, 0x3, 0x0, 0x41, 0x0, 0x0, 0x0,
0x40, 0x0, 0x0, 0x0, 0x41, 0x0, 0x5, 0x0, 0x35, 0x0,
0x0, 0x0, 0x44, 0x0, 0x0, 0x0, 0x2E, 0x0, 0x0, 0x0,
0x43, 0x0, 0x0, 0x0, 0x3E, 0x0, 0x3, 0x0, 0x44, 0x0,
0x0, 0x0, 0x42, 0x0, 0x0, 0x0, 0xFD, 0x0, 0x1, 0x0,
0x38, 0x0, 0x1, 0x0,
];
}

View File

@ -13,12 +13,16 @@ public class GraphicsDevice : IDisposable
public BackendFlags Backend { get; }
public bool DebugMode { get; }
// Built-in shaders
public Shader FullscreenVertexShader { get; private set; }
public Shader VideoFragmentShader { get; private set; }
public Shader TextVertexShader { get; private set; }
public Shader TextFragmentShader { get; private set; }
// Built-in video pipeline
internal GraphicsPipeline VideoPipeline { get; }
internal GraphicsPipeline VideoPipeline { get; private set; }
// Built-in text shader info
public Shader TextVertexShader;
public Shader TextFragmentShader;
public VertexInputState TextVertexInputState { get; }
// Built-in samplers
@ -53,85 +57,21 @@ public class GraphicsDevice : IDisposable
Backend = (BackendFlags)Refresh.Refresh_GetBackend(Handle);
IEmbeddedShaders embeddedShaders;
switch (Backend)
{
case BackendFlags.Vulkan:
embeddedShaders = new EmbeddedShadersSpirV();
break;
case BackendFlags.D3D11:
throw new NotImplementedException("D3D11 embedded shaders");
break;
case BackendFlags.Metal:
throw new NotImplementedException("Metal embedded shaders");
break;
default: throw new ArgumentOutOfRangeException();
}
TextVertexInputState = VertexInputState.CreateSingleBinding<FontVertex>();
Shader fullscreenVertShader;
Shader textVertShader;
Shader textFragShader;
Shader videoFragShader;
PointSampler = new Sampler(this, SamplerCreateInfo.PointClamp);
LinearSampler = new Sampler(this, SamplerCreateInfo.LinearClamp);
using (MemoryStream fullscreenVertStream = new MemoryStream(embeddedShaders.FullscreenVert))
{
fullscreenVertShader = new Shader(
this,
fullscreenVertStream,
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = embeddedShaders.ShaderFormat
}
);
}
fencePool = new FencePool(this);
commandBufferPool = new CommandBufferPool(this);
}
using (MemoryStream videoYuv2RgbaFragStream = new MemoryStream(embeddedShaders.VideoYuv2RgbaFrag))
{
videoFragShader = new Shader(
this,
videoYuv2RgbaFragStream,
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = embeddedShaders.ShaderFormat,
SamplerCount = 3
}
);
}
using (MemoryStream textTransformVertStream = new MemoryStream(embeddedShaders.TextTransformVert))
{
textVertShader = new Shader(
this,
textTransformVertStream,
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = embeddedShaders.ShaderFormat,
UniformBufferCount = 1
}
);
}
using (MemoryStream textMsdfFragStream = new MemoryStream(embeddedShaders.TextMsdfFrag))
{
textFragShader = new Shader(
this,
textMsdfFragStream,
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = embeddedShaders.ShaderFormat,
SamplerCount = 1,
UniformBufferCount = 1
}
);
}
internal void LoadDefaultPipelines()
{
FullscreenVertexShader = ResourceManager.Load<Shader>("Shaders/Fullscreen.vert");
VideoFragmentShader = ResourceManager.Load<Shader>("Shaders/Video.frag");
TextVertexShader = ResourceManager.Load<Shader>("Shaders/Text.vert");
TextFragmentShader = ResourceManager.Load<Shader>("Shaders/Text.frag");
VideoPipeline = new GraphicsPipeline(
this,
@ -144,25 +84,14 @@ public class GraphicsDevice : IDisposable
)
),
DepthStencilState = DepthStencilState.Disable,
VertexShader = fullscreenVertShader,
FragmentShader = videoFragShader,
VertexShader = FullscreenVertexShader,
FragmentShader = VideoFragmentShader,
VertexInputState = VertexInputState.Empty,
RasterizerState = RasterizerState.CCW_CullNone,
PrimitiveType = PrimitiveType.TriangleList,
MultisampleState = MultisampleState.None
}
);
TextVertexShader = textVertShader;
TextFragmentShader = textFragShader;
TextVertexInputState = VertexInputState.CreateSingleBinding<FontVertex>();
PointSampler = new Sampler(this, SamplerCreateInfo.PointClamp);
LinearSampler = new Sampler(this, SamplerCreateInfo.LinearClamp);
fencePool = new FencePool(this);
commandBufferPool = new CommandBufferPool(this);
}
/// <summary>

View File

@ -1,10 +0,0 @@
namespace Nerfed.Runtime.Graphics;
internal interface IEmbeddedShaders
{
ShaderFormat ShaderFormat { get; }
byte[] FullscreenVert { get; }
byte[] TextMsdfFrag { get; }
byte[] TextTransformVert { get; }
byte[] VideoYuv2RgbaFrag { get; }
}

View File

@ -1,91 +0,0 @@
using RefreshCS;
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace Nerfed.Runtime.Graphics;
/// <summary>
/// Shaders are used to create graphics pipelines.
/// Graphics pipelines take a vertex shader and a fragment shader.
/// </summary>
public class Shader : RefreshResource
{
protected override Action<IntPtr, IntPtr> ReleaseFunction => Refresh.Refresh_ReleaseShader;
public uint SamplerCount { get; }
public uint StorageTextureCount { get; }
public uint StorageBufferCount { get; }
public uint UniformBufferCount { get; }
public unsafe Shader(
GraphicsDevice device,
string filePath,
string entryPointName,
in ShaderCreateInfo shaderCreateInfo
) : base(device)
{
using FileStream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
Handle = CreateFromStream(
device,
stream,
entryPointName,
shaderCreateInfo
);
SamplerCount = shaderCreateInfo.SamplerCount;
StorageTextureCount = shaderCreateInfo.StorageTextureCount;
StorageBufferCount = shaderCreateInfo.StorageBufferCount;
UniformBufferCount = shaderCreateInfo.UniformBufferCount;
}
public unsafe Shader(
GraphicsDevice device,
Stream stream,
string entryPointName,
in ShaderCreateInfo shaderCreateInfo
) : base(device)
{
Handle = CreateFromStream(
device,
stream,
entryPointName,
shaderCreateInfo
);
SamplerCount = shaderCreateInfo.SamplerCount;
StorageTextureCount = shaderCreateInfo.StorageTextureCount;
StorageBufferCount = shaderCreateInfo.StorageBufferCount;
UniformBufferCount = shaderCreateInfo.UniformBufferCount;
}
private static unsafe IntPtr CreateFromStream(
GraphicsDevice device,
Stream stream,
string entryPointName,
in ShaderCreateInfo shaderCreateInfo
) {
void* bytecodeBuffer = NativeMemory.Alloc((nuint) stream.Length);
Span<byte> bytecodeSpan = new Span<byte>(bytecodeBuffer, (int) stream.Length);
stream.ReadExactly(bytecodeSpan);
Refresh.ShaderCreateInfo refreshShaderCreateInfo;
refreshShaderCreateInfo.CodeSize = (nuint) stream.Length;
refreshShaderCreateInfo.Code = (byte*) bytecodeBuffer;
refreshShaderCreateInfo.EntryPointName = entryPointName;
refreshShaderCreateInfo.Stage = (Refresh.ShaderStage) shaderCreateInfo.ShaderStage;
refreshShaderCreateInfo.Format = (Refresh.ShaderFormat) shaderCreateInfo.ShaderFormat;
refreshShaderCreateInfo.SamplerCount = shaderCreateInfo.SamplerCount;
refreshShaderCreateInfo.StorageTextureCount = shaderCreateInfo.StorageTextureCount;
refreshShaderCreateInfo.StorageBufferCount = shaderCreateInfo.StorageBufferCount;
refreshShaderCreateInfo.UniformBufferCount = shaderCreateInfo.UniformBufferCount;
IntPtr shaderModule = Refresh.Refresh_CreateShader(
device.Handle,
refreshShaderCreateInfo
);
NativeMemory.Free(bytecodeBuffer);
return shaderModule;
}
}

View File

@ -60,20 +60,8 @@ public class GuiController : IDisposable
io.DisplaySize = new Vector2(mainWindow.Width, mainWindow.Height);
io.DisplayFramebufferScale = Vector2.One;
ShaderCreateInfo vertexCreateInfo = new ShaderCreateInfo {
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV,
UniformBufferCount = 1,
};
imGuiVertexShader = new Shader(graphicsDevice, Path.Combine(shaderContentPath, "imgui-vertex.spv"), "main", in vertexCreateInfo);
ShaderCreateInfo fragCreateInfo = new ShaderCreateInfo {
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV,
SamplerCount = 1,
};
imGuiFragmentShader = new Shader(graphicsDevice, Path.Combine(shaderContentPath, "imgui-frag.spv"), "main", in fragCreateInfo);
imGuiVertexShader = ResourceManager.Load<Shader>("Shaders/ImGui.vert");
imGuiFragmentShader = ResourceManager.Load<Shader>("Shaders/ImGui.frag");
imGuiSampler = new Sampler(graphicsDevice, SamplerCreateInfo.LinearClamp);
@ -642,8 +630,8 @@ public class GuiController : IDisposable
fontTexture?.Dispose();
imGuiVertexBuffer?.Dispose();
imGuiIndexBuffer?.Dispose();
imGuiFragmentShader?.Dispose();
imGuiVertexShader?.Dispose();
ResourceManager.Unload(imGuiVertexShader);
ResourceManager.Unload(imGuiFragmentShader);
imGuiPipeline?.Dispose();
imGuiSampler?.Dispose();
resourceUploader?.Dispose();

View File

@ -32,12 +32,12 @@
</PropertyGroup>
<ItemGroup>
<Compile Include="Libraries\SDL2CS\src\SDL2.cs"/>
<Compile Include="Libraries\RefreshCS\RefreshCS.cs"/>
<Compile Include="Libraries\FAudio\csharp\FAudio.cs"/>
<Compile Include="Libraries\WellspringCS\WellspringCS.cs"/>
<Compile Include="Libraries\dav1dfile\csharp\dav1dfile.cs"/>
<Compile Include="Libraries\ImGui.NET\src\ImGui.NET\**\*.cs"/>
<Compile Include="Libraries\SDL2CS\src\SDL2.cs" />
<Compile Include="Libraries\RefreshCS\RefreshCS.cs" />
<Compile Include="Libraries\FAudio\csharp\FAudio.cs" />
<Compile Include="Libraries\WellspringCS\WellspringCS.cs" />
<Compile Include="Libraries\dav1dfile\csharp\dav1dfile.cs" />
<Compile Include="Libraries\ImGui.NET\src\ImGui.NET\**\*.cs" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=resource/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@ -0,0 +1,9 @@
namespace Nerfed.Runtime;
public abstract class Resource
{
public string Path { get; internal set; }
internal abstract void Load(Stream stream);
internal abstract void Unload();
}

View File

@ -0,0 +1,43 @@
namespace Nerfed.Runtime;
public static class ResourceManager
{
private const string rootName = "Resources";
private static readonly Dictionary<string, Resource> loadedResources = new Dictionary<string, Resource>();
public static T Load<T>(string resourcePath) where T : Resource
{
if (loadedResources.TryGetValue(resourcePath, out Resource resource))
{
return (T)resource;
}
if (typeof(T) == typeof(Shader))
{
resource = new Shader();
}
else
{
throw new Exception("Failed to create resource");
}
Assert.Always(resource != null);
resource.Path = resourcePath;
resource.Load(StorageContainer.OpenStream(Path.Combine(AppContext.BaseDirectory, rootName, resourcePath) + ".bin"));
loadedResources.Add(resourcePath, resource);
return (T)resource;
}
public static void Unload(Resource resource)
{
if (!loadedResources.ContainsKey(resource.Path))
{
return;
}
resource.Unload();
resource.Path = string.Empty;
loadedResources.Remove(resource.Path);
}
}

View File

@ -0,0 +1,58 @@
using System.Runtime.InteropServices;
using RefreshCS;
namespace Nerfed.Runtime;
public class Shader : Resource
{
public IntPtr Handle { get; private set; }
public uint SamplerCount { get; private set; }
public uint StorageTextureCount { get; private set; }
public uint StorageBufferCount { get; private set; }
public uint UniformBufferCount { get; private set; }
internal Shader() { }
internal override unsafe void Load(Stream stream)
{
using (BinaryReader reader = new BinaryReader(stream))
{
Refresh.ShaderCreateInfo createInfo;
createInfo.Format = (Refresh.ShaderFormat)reader.ReadInt32();
createInfo.Stage = (Refresh.ShaderStage)reader.ReadInt32();
createInfo.UniformBufferCount = (uint)reader.ReadInt32();
createInfo.StorageBufferCount = (uint)reader.ReadInt32();
createInfo.StorageTextureCount = (uint)reader.ReadInt32();
createInfo.SamplerCount = (uint)reader.ReadInt32();
int byteCodeSize = reader.ReadInt32();
void* byteCodeBuffer = NativeMemory.Alloc((nuint)byteCodeSize);
Span<byte> byteCodeSpan = new Span<byte>(byteCodeBuffer, byteCodeSize);
int bytesRead = 0;
while (bytesRead < byteCodeSize)
{
bytesRead += reader.Read(byteCodeSpan.Slice(bytesRead));
}
createInfo.CodeSize = (nuint)byteCodeSize;
createInfo.Code = (byte*)byteCodeBuffer;
createInfo.EntryPointName = "main";
Handle = Refresh.Refresh_CreateShader(Engine.GraphicsDevice.Handle, createInfo);
NativeMemory.Free(byteCodeBuffer);
SamplerCount = createInfo.SamplerCount;
StorageTextureCount = createInfo.StorageTextureCount;
StorageBufferCount = createInfo.StorageBufferCount;
UniformBufferCount = createInfo.UniformBufferCount;
}
}
internal override void Unload()
{
Refresh.Refresh_ReleaseShader(Engine.GraphicsDevice.Handle, Handle);
Handle = IntPtr.Zero;
}
}

View File

@ -5,35 +5,46 @@ VisualStudioVersion = 17.10.35013.160
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nerfed.Runtime", "Nerfed.Runtime\Nerfed.Runtime.csproj", "{98E09BAF-587F-4238-89BD-7693C036C233}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nerfed.Builder", "Nerfed.Builder\Nerfed.Builder.csproj", "{1B88DE56-2AD8-441E-9B10-073AA43840BF}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nerfed.Builder", "Nerfed.Builder\Nerfed.Builder.csproj", "{1B88DE56-2AD8-441E-9B10-073AA43840BF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nerfed.Editor", "Nerfed.Editor\Nerfed.Editor.csproj", "{FF7D032D-7F0B-4700-A818-0606D66AECF8}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nerfed.Editor", "Nerfed.Editor\Nerfed.Editor.csproj", "{FF7D032D-7F0B-4700-A818-0606D66AECF8}"
ProjectSection(ProjectDependencies) = postProject
{1B88DE56-2AD8-441E-9B10-073AA43840BF} = {1B88DE56-2AD8-441E-9B10-073AA43840BF}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nerfed.Compiler", "Nerfed.Compiler\Nerfed.Compiler.csproj", "{3DFEB8A4-5354-41EA-A249-27ADC7F666CF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Test|x64 = Test|x64
Release|x64 = Release|x64
Debug|x64 = Debug|x64
Release|x64 = Release|x64
Test|x64 = Test|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1B88DE56-2AD8-441E-9B10-073AA43840BF}.Test|x64.ActiveCfg = Test|x64
{1B88DE56-2AD8-441E-9B10-073AA43840BF}.Test|x64.Build.0 = Test|x64
{1B88DE56-2AD8-441E-9B10-073AA43840BF}.Release|x64.ActiveCfg = Release|x64
{1B88DE56-2AD8-441E-9B10-073AA43840BF}.Release|x64.Build.0 = Release|x64
{1B88DE56-2AD8-441E-9B10-073AA43840BF}.Debug|x64.ActiveCfg = Debug|x64
{1B88DE56-2AD8-441E-9B10-073AA43840BF}.Debug|x64.Build.0 = Debug|x64
{FF7D032D-7F0B-4700-A818-0606D66AECF8}.Test|x64.ActiveCfg = Test|x64
{FF7D032D-7F0B-4700-A818-0606D66AECF8}.Test|x64.Build.0 = Test|x64
{FF7D032D-7F0B-4700-A818-0606D66AECF8}.Release|x64.ActiveCfg = Release|x64
{FF7D032D-7F0B-4700-A818-0606D66AECF8}.Release|x64.Build.0 = Release|x64
{FF7D032D-7F0B-4700-A818-0606D66AECF8}.Debug|x64.ActiveCfg = Debug|x64
{FF7D032D-7F0B-4700-A818-0606D66AECF8}.Debug|x64.Build.0 = Debug|x64
{98E09BAF-587F-4238-89BD-7693C036C233}.Test|x64.ActiveCfg = Test|x64
{98E09BAF-587F-4238-89BD-7693C036C233}.Test|x64.Build.0 = Test|x64
{98E09BAF-587F-4238-89BD-7693C036C233}.Release|x64.ActiveCfg = Release|x64
{98E09BAF-587F-4238-89BD-7693C036C233}.Release|x64.Build.0 = Release|x64
{98E09BAF-587F-4238-89BD-7693C036C233}.Debug|x64.ActiveCfg = Debug|x64
{98E09BAF-587F-4238-89BD-7693C036C233}.Debug|x64.Build.0 = Debug|x64
{98E09BAF-587F-4238-89BD-7693C036C233}.Release|x64.ActiveCfg = Release|x64
{98E09BAF-587F-4238-89BD-7693C036C233}.Release|x64.Build.0 = Release|x64
{98E09BAF-587F-4238-89BD-7693C036C233}.Test|x64.ActiveCfg = Test|x64
{98E09BAF-587F-4238-89BD-7693C036C233}.Test|x64.Build.0 = Test|x64
{1B88DE56-2AD8-441E-9B10-073AA43840BF}.Debug|x64.ActiveCfg = Debug|x64
{1B88DE56-2AD8-441E-9B10-073AA43840BF}.Debug|x64.Build.0 = Debug|x64
{1B88DE56-2AD8-441E-9B10-073AA43840BF}.Release|x64.ActiveCfg = Release|x64
{1B88DE56-2AD8-441E-9B10-073AA43840BF}.Release|x64.Build.0 = Release|x64
{1B88DE56-2AD8-441E-9B10-073AA43840BF}.Test|x64.ActiveCfg = Test|x64
{1B88DE56-2AD8-441E-9B10-073AA43840BF}.Test|x64.Build.0 = Test|x64
{FF7D032D-7F0B-4700-A818-0606D66AECF8}.Debug|x64.ActiveCfg = Debug|x64
{FF7D032D-7F0B-4700-A818-0606D66AECF8}.Debug|x64.Build.0 = Debug|x64
{FF7D032D-7F0B-4700-A818-0606D66AECF8}.Release|x64.ActiveCfg = Release|x64
{FF7D032D-7F0B-4700-A818-0606D66AECF8}.Release|x64.Build.0 = Release|x64
{FF7D032D-7F0B-4700-A818-0606D66AECF8}.Test|x64.ActiveCfg = Test|x64
{FF7D032D-7F0B-4700-A818-0606D66AECF8}.Test|x64.Build.0 = Test|x64
{3DFEB8A4-5354-41EA-A249-27ADC7F666CF}.Debug|x64.ActiveCfg = Debug|x64
{3DFEB8A4-5354-41EA-A249-27ADC7F666CF}.Debug|x64.Build.0 = Debug|x64
{3DFEB8A4-5354-41EA-A249-27ADC7F666CF}.Release|x64.ActiveCfg = Release|x64
{3DFEB8A4-5354-41EA-A249-27ADC7F666CF}.Release|x64.Build.0 = Release|x64
{3DFEB8A4-5354-41EA-A249-27ADC7F666CF}.Test|x64.ActiveCfg = Test|x64
{3DFEB8A4-5354-41EA-A249-27ADC7F666CF}.Test|x64.Build.0 = Test|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE