aboutsummaryrefslogtreecommitdiffstatsci
path: root/SpirVTasks
diff options
context:
space:
mode:
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>2019-08-29 00:40:50 +0200
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>2019-08-29 00:40:50 +0200
commitc6a4a1dfae50d83edf0050aa92dbddda625aa3e2 (patch)
tree2864f9597345d17a0f84247af8f77e7c5f1d416d /SpirVTasks
parenta20b4729bfbd50feaa1054d3aa2093ae86ac30fb (diff)
SpiprVTask nuget package
Diffstat (limited to 'SpirVTasks')
-rw-r--r--SpirVTasks/CompileGLSLTask.cs203
-rw-r--r--SpirVTasks/SpirVTasks.csproj40
-rw-r--r--SpirVTasks/SpirVTasks.targets29
-rw-r--r--SpirVTasks/spirv.xml9
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>