diff options
| author | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2019-08-29 00:40:50 +0200 |
|---|---|---|
| committer | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2019-08-29 00:40:50 +0200 |
| commit | c6a4a1dfae50d83edf0050aa92dbddda625aa3e2 (patch) | |
| tree | 2864f9597345d17a0f84247af8f77e7c5f1d416d /SpirVTasks | |
| parent | a20b4729bfbd50feaa1054d3aa2093ae86ac30fb (diff) | |
SpiprVTask nuget package
Diffstat (limited to 'SpirVTasks')
| -rw-r--r-- | SpirVTasks/CompileGLSLTask.cs | 203 | ||||
| -rw-r--r-- | SpirVTasks/SpirVTasks.csproj | 40 | ||||
| -rw-r--r-- | SpirVTasks/SpirVTasks.targets | 29 | ||||
| -rw-r--r-- | SpirVTasks/spirv.xml | 9 |
4 files changed, 281 insertions, 0 deletions
diff --git a/SpirVTasks/CompileGLSLTask.cs b/SpirVTasks/CompileGLSLTask.cs new file mode 100644 index 0000000..c2d1a7e --- /dev/null +++ b/SpirVTasks/CompileGLSLTask.cs @@ -0,0 +1,203 @@ +using System; +using System.Diagnostics; +using System.IO; +using Microsoft.Build.Framework; + +namespace SpirVTasks { + + public class IncludeFileNotFound : FileNotFoundException { + public string SourceFile; + public int SourceLine; + + public IncludeFileNotFound(string srcFileName, int srcLine, string includeFileName) : + base ("include file not found", includeFileName) { + + SourceFile = srcFileName; + SourceLine = srcLine; + } + } + + public class CompileGLSLTask : Microsoft.Build.Utilities.Task { + + [Required] + public ITaskItem SourceFile { + get; + set; + } + [Required] + public ITaskItem TempDirectory { + get; + set; + } + public ITaskItem AdditionalIncludeDirectories { + get; + set; + } + public ITaskItem SpirVCompilerPath { + get; + set; + } + [Required] + [Output] + public ITaskItem DestinationFile { + get; + set; + } + + volatile bool success; + + bool tryFindInclude (string include, out string incFile) { + if (!string.IsNullOrEmpty (AdditionalIncludeDirectories?.ItemSpec)) { + foreach (string incDir in AdditionalIncludeDirectories.ItemSpec.Split (';', ',', '|')) { + incFile = Path.Combine (incDir, include); + if (File.Exists (incFile)) + return true; + } + } + incFile = ""; + return false; + } + + void build_source (string src, StreamWriter temp) { + using (StreamReader sr = new StreamReader (File.OpenRead (src))) { + int srcLine = 0; + while (!sr.EndOfStream) { + string line = sr.ReadLine (); + if (line.Trim ().StartsWith ("#include", StringComparison.Ordinal)) { + string include = line.Split ('"', '<', '>')[1]; + string incFile = Path.Combine (Path.GetDirectoryName (src), include); + if (!File.Exists (incFile)) { + if (!tryFindInclude(include, out incFile)) + throw new IncludeFileNotFound (src, srcLine, include); + } + build_source (incFile, temp); + } else + temp.WriteLine (line); + srcLine++; + } + } + } + + bool tryFindGlslcExecutable (out string glslcPath) { + if (!string.IsNullOrEmpty (SpirVCompilerPath?.ItemSpec)) { + glslcPath = SpirVCompilerPath.ItemSpec; + if (!File.Exists (glslcPath)) + return false; + } + + string glslcExec = "glslc"; + if (Environment.OSVersion.Platform.ToString ().StartsWith ("Win", StringComparison.Ordinal)) + glslcExec = glslcExec + "exe"; + + glslcPath = Path.Combine (Environment.GetEnvironmentVariable ("VULKAN_SDK"), "bin"); + glslcPath = Path.Combine (glslcPath, glslcExec); + if (File.Exists (glslcPath)) + return true; + + string envStrPathes = Environment.GetEnvironmentVariable ("PATH"); + if (!string.IsNullOrEmpty (envStrPathes)) { + foreach (string path in envStrPathes.Split (';')) { + glslcPath = Path.Combine (path, glslcExec); + if (File.Exists (glslcPath)) + return true; + } + } + return false; + } + + + public override bool Execute () { + + success = true; + + if (!tryFindGlslcExecutable(out string glslcPath)) { + BuildErrorEventArgs err = new BuildErrorEventArgs ("execute", "VK001", BuildEngine.ProjectFileOfTaskNode, 0, 0, 0, 0, $"glslc command not found: {glslcPath}", "Set 'VULKAN_SDK' environment variable", "SpirVTasks"); + BuildEngine.LogErrorEvent (err); + return false; + } + + string tempFile = Path.Combine (TempDirectory.ItemSpec, SourceFile.ItemSpec); + if (File.Exists (tempFile)) + File.Delete (tempFile); + try { + Directory.CreateDirectory (Path.GetDirectoryName (tempFile)); + using (StreamWriter sw = new StreamWriter (File.OpenWrite(tempFile))) { + string src = SourceFile.ItemSpec; + build_source (SourceFile.ItemSpec, sw); + } + } catch (IncludeFileNotFound ex) { + BuildErrorEventArgs err = new BuildErrorEventArgs ("include", "VK002", ex.SourceFile, ex.SourceLine, 0, 0, 0, $"include file not found: {ex.FileName}", "", "SpirVTasks"); + BuildEngine.LogErrorEvent (err); + return false; + }catch (Exception ex) { + BuildErrorEventArgs err = new BuildErrorEventArgs ("include", "VK000", SourceFile.ItemSpec, 0, 0, 0, 0, ex.ToString(), "", "SpirVTasks"); + BuildEngine.LogErrorEvent (err); + return false; + } + + Directory.CreateDirectory (Path.GetDirectoryName (DestinationFile.ItemSpec)); + + Process glslc = new Process(); + //glslc.StartInfo.StandardOutputEncoding = System.Text.Encoding.ASCII; + //glslc.StartInfo.StandardErrorEncoding = System.Text.Encoding.ASCII; + glslc.StartInfo.UseShellExecute = false; + glslc.StartInfo.RedirectStandardOutput = true; + glslc.StartInfo.RedirectStandardError = true; + glslc.StartInfo.FileName = glslcPath; + glslc.StartInfo.Arguments = $"{tempFile} -o {DestinationFile.ItemSpec}"; + glslc.StartInfo.CreateNoWindow = true; + + glslc.EnableRaisingEvents = true; + glslc.OutputDataReceived += Glslc_OutputDataReceived; + glslc.ErrorDataReceived += Glslc_ErrorDataReceived; + + glslc.Start (); + + glslc.BeginErrorReadLine (); + glslc.BeginOutputReadLine (); + + Log.LogMessage (MessageImportance.High, $"{SourceFile.ItemSpec} -> {DestinationFile.ItemSpec}"); + + glslc.WaitForExit (); + + return success; + } + + void Glslc_ErrorDataReceived (object sender, DataReceivedEventArgs e) { + if (e.Data == null) + return; + + if (string.Equals (e.Data, "(0)", StringComparison.Ordinal)) + return; + + string[] tmp = e.Data.Split (':'); + + Log.LogMessage (MessageImportance.High, $"glslc: {e.Data}"); + + if (tmp.Length == 5) { + string srcFile = BuildEngine.ProjectFileOfTaskNode; + int line = int.Parse (tmp[1]); + + BuildErrorEventArgs err = new BuildErrorEventArgs ("compile", tmp[2], srcFile, line, 0, 0, 0, $"{tmp[3]} {tmp[4]}", "no help", "SpirVTasks"); + BuildEngine.LogErrorEvent (err); + success = false; + } else { + Log.LogMessage (MessageImportance.High, $"{e.Data}"); + } + } + + + void Glslc_OutputDataReceived (object sender, DataReceivedEventArgs e) { + if (e.Data == null) + return; + if (string.Equals (e.Data, "(0)", StringComparison.Ordinal)) + return; + + Log.LogMessage (MessageImportance.High, $"data:{e.Data}"); + + BuildWarningEventArgs taskEvent = new BuildWarningEventArgs ("glslc", "0", BuildEngine.ProjectFileOfTaskNode, 0, 0, 0, 0, $"{e.Data}", "no help", "SpirVTasks"); + BuildEngine.LogWarningEvent (taskEvent); + } + + } +} diff --git a/SpirVTasks/SpirVTasks.csproj b/SpirVTasks/SpirVTasks.csproj new file mode 100644 index 0000000..ac00130 --- /dev/null +++ b/SpirVTasks/SpirVTasks.csproj @@ -0,0 +1,40 @@ +<Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <TargetFrameworks>net471;netstandard2.0</TargetFrameworks> + <AssemblyVersion>0.1.6</AssemblyVersion> + + <PackageId>SpirVTasks</PackageId> + <PackageTags>msbuild vulkan spirv glsl addons</PackageTags> + <PackageVersion>$(AssemblyVersion)-beta</PackageVersion> + <GeneratePackageOnBuild>True</GeneratePackageOnBuild> + <PackageRequireLicenseAcceptance>False</PackageRequireLicenseAcceptance> + <PackageProjectUrl>https://github.com/jpbruyere/vk.net/blob/master/README.md</PackageProjectUrl> + <License>MIT</License> + <Authors>Jean-Philippe Bruyère</Authors> + <IncludeDefaultNoneItems>false</IncludeDefaultNoneItems> + + <EnableDefaultContentItems>false</EnableDefaultContentItems> + <EnableDefaultNoneItems>false</EnableDefaultNoneItems> + <EnableDefaultCompileItems>true</EnableDefaultCompileItems> + </PropertyGroup> + <ItemGroup> + <PackageReference Include="Microsoft.Build.Utilities.Core" Version="16.0.461" /> + </ItemGroup> + <ItemGroup> + <Content Include="SpirVTasks.targets"> + <Pack>true</Pack> + <IncludeInPackage>true</IncludeInPackage> + <PackagePath>build\net471\</PackagePath> + </Content> + <Content Include="SpirVTasks.targets"> + <Pack>true</Pack> + <IncludeInPackage>true</IncludeInPackage> + <PackagePath>build\netstandard2.0\</PackagePath> + </Content> + <Content Include="spirv.xml"> + <Pack>true</Pack> + <IncludeInPackage>true</IncludeInPackage> + <PackagePath>build</PackagePath> + </Content> + </ItemGroup> +</Project> diff --git a/SpirVTasks/SpirVTasks.targets b/SpirVTasks/SpirVTasks.targets new file mode 100644 index 0000000..8f7ae56 --- /dev/null +++ b/SpirVTasks/SpirVTasks.targets @@ -0,0 +1,29 @@ +<Project> + <UsingTask AssemblyFile="$(MSBuildThisFileDirectory)..\..\lib\$(TargetFramework)\SpirVTasks.dll" TaskName="SpirVTasks.CompileGLSLTask" /> + <ItemGroup> + <PropertyPageSchema Include="$(MSBuildThisFileDirectory)..\spirv.xml" /> + <AvailableItemName Include="GLSLShader"> + <Targets>DXC</Targets> + </AvailableItemName> + </ItemGroup> + <Target Name="CompileShaders" BeforeTargets="BeforeBuild" Condition="'@(GLSLShader)'!=''" Outputs="@(CompiledShaders)"> + <CompileGLSLTask SourceFile="%(GLSLShader.Identity)" + AdditionalIncludeDirectories="$(SpirVAdditionalIncludeDirectories)" + TempDirectory="$(IntermediateOutputPath)" + DestinationFile="$(IntermediateOutputPath)%(RelativeDir)%(Filename)%(Extension).spv" /> + <CreateItem + Include="$(IntermediateOutputPath)%(GLSLShader.RelativeDir)%(Filename)%(Extension).spv"> + <Output + TaskParameter="Include" + ItemName="EmbeddedResource"/> + </CreateItem> + <Message Importance="High" Text="Embedding $(IntermediateOutputPath)%(GLSLShader.RelativeDir)%(Filename)%(Extension).spv" /> + </Target> + <Target Name="ModifyEmbeddedResourceNames" AfterTargets="CompileShaders"> + <ItemGroup> + <EmbeddedResource> + <LogicalName>$(AssemblyName).%(EmbeddedResource.Filename)%(Extension)</LogicalName> + </EmbeddedResource> + </ItemGroup> + </Target> +</Project> diff --git a/SpirVTasks/spirv.xml b/SpirVTasks/spirv.xml new file mode 100644 index 0000000..9635ad6 --- /dev/null +++ b/SpirVTasks/spirv.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<ProjectSchemaDefinitions xmlns="http://schemas.microsoft.com/build/2009/properties"> + <ItemType Name="GLSLShader" DisplayName="GLSL Shader" /> + <ContentType Name="GLSLShader" ItemType="GLSLShader" DisplayName="GLSL Shader" /> + <FileExtension Name=".comp" ContentType="GLSLShader" /> + <FileExtension Name=".geom" ContentType="GLSLShader" /> + <FileExtension Name=".frag" ContentType="GLSLShader" /> + <FileExtension Name=".vert" ContentType="GLSLShader" /> +</ProjectSchemaDefinitions> |