├── images ├── vs2015.png ├── errorlist.png ├── contextmenu.png ├── humanreadable.png └── contextmenufolder.png ├── SPIRV-VSExtension ├── Key.snk ├── Resources │ ├── SPIRVCommands.psd │ ├── SPIRVExtension.ico │ └── SPIRVExtension.png ├── Shared │ ├── ShaderFile.cs │ ├── OutputWindow.cs │ ├── Utils.cs │ ├── ErrorList.cs │ ├── DocumentHelper.cs │ ├── GlslangCompiler.cs │ └── DxcCompiler.cs ├── LICENSE ├── Properties │ └── AssemblyInfo.cs ├── source.extension.vsixmanifest ├── packages.config ├── CommandCompileHLSL.cs ├── CommandCompileOpenGL.cs ├── CommandCompileVulkan.cs ├── CommandPrintSPIRV.cs ├── SPIRVExtensionPackage.cs ├── VSPackage.resx ├── SPIRVExtensionPackage.vsct ├── ShaderCommandBase.cs └── SPIRV-VSExtension.csproj ├── SPIRV-VSExtension.sln ├── LICENSE ├── README.md └── .gitignore /images/vs2015.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaschaWillems/SPIRV-VSExtension/HEAD/images/vs2015.png -------------------------------------------------------------------------------- /images/errorlist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaschaWillems/SPIRV-VSExtension/HEAD/images/errorlist.png -------------------------------------------------------------------------------- /images/contextmenu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaschaWillems/SPIRV-VSExtension/HEAD/images/contextmenu.png -------------------------------------------------------------------------------- /SPIRV-VSExtension/Key.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaschaWillems/SPIRV-VSExtension/HEAD/SPIRV-VSExtension/Key.snk -------------------------------------------------------------------------------- /images/humanreadable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaschaWillems/SPIRV-VSExtension/HEAD/images/humanreadable.png -------------------------------------------------------------------------------- /images/contextmenufolder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaschaWillems/SPIRV-VSExtension/HEAD/images/contextmenufolder.png -------------------------------------------------------------------------------- /SPIRV-VSExtension/Resources/SPIRVCommands.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaschaWillems/SPIRV-VSExtension/HEAD/SPIRV-VSExtension/Resources/SPIRVCommands.psd -------------------------------------------------------------------------------- /SPIRV-VSExtension/Resources/SPIRVExtension.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaschaWillems/SPIRV-VSExtension/HEAD/SPIRV-VSExtension/Resources/SPIRVExtension.ico -------------------------------------------------------------------------------- /SPIRV-VSExtension/Resources/SPIRVExtension.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaschaWillems/SPIRV-VSExtension/HEAD/SPIRV-VSExtension/Resources/SPIRVExtension.png -------------------------------------------------------------------------------- /SPIRV-VSExtension/Shared/ShaderFile.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * SPIR-V Visual Studio Extension 3 | * 4 | * Copyright (C) 2016 by Sascha Willems - www.saschawillems.de 5 | * 6 | * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) 7 | */ 8 | 9 | using Microsoft.VisualStudio.Shell.Interop; 10 | using System.IO; 11 | 12 | namespace SPIRVExtension 13 | { 14 | /// 15 | /// Encaspulates details of a shader file 16 | /// 17 | public class ShaderFile 18 | { 19 | public uint itemid; 20 | public IVsHierarchy hierarchy; 21 | public string fileName; 22 | public string fileExt; 23 | 24 | public ShaderFile(uint id, IVsHierarchy hr, string file) 25 | { 26 | itemid = id; 27 | hierarchy = hr; 28 | fileName = file; 29 | fileExt = Path.GetExtension(file); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /SPIRV-VSExtension.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26228.10 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPIRV-VSExtension", "SPIRV-VSExtension\SPIRV-VSExtension.csproj", "{914B9574-655F-435E-9928-FE245DABB221}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {914B9574-655F-435E-9928-FE245DABB221}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {914B9574-655F-435E-9928-FE245DABB221}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {914B9574-655F-435E-9928-FE245DABB221}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {914B9574-655F-435E-9928-FE245DABB221}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Sascha Willems 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /SPIRV-VSExtension/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Sascha Willems 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /SPIRV-VSExtension/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("SPIRVExtension")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("SPIRVExtension")] 13 | [assembly: AssemblyCopyright("")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // Version information for an assembly consists of the following four values: 23 | // 24 | // Major Version 25 | // Minor Version 26 | // Build Number 27 | // Revision 28 | // 29 | // You can specify all the values or you can default the Build and Revision Numbers 30 | // by using the '*' as shown below: 31 | // [assembly: AssemblyVersion("1.0.*")] 32 | [assembly: AssemblyVersion("1.0.0.0")] 33 | [assembly: AssemblyFileVersion("1.0.0.0")] 34 | -------------------------------------------------------------------------------- /SPIRV-VSExtension/Shared/OutputWindow.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * SPIR-V Visual Studio Extension 3 | * 4 | * Copyright (C) 2016 by Sascha Willems - www.saschawillems.de 5 | * 6 | * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) 7 | */ 8 | 9 | using System; 10 | using Microsoft.VisualStudio.Shell; 11 | using Microsoft.VisualStudio.Shell.Interop; 12 | 13 | namespace SPIRVExtension 14 | { 15 | /// 16 | /// Helper class for displaying messages in a custom output window pane 17 | /// 18 | public static class OutputWindow 19 | { 20 | static private IVsOutputWindowPane customPane() 21 | { 22 | IVsOutputWindow outputWindow = Package.GetGlobalService(typeof(SVsOutputWindow)) as IVsOutputWindow; 23 | Guid customGuid = new Guid("6AFC25E1-1622-4589-82D7-136503A69B2F"); 24 | string customTitle = "SPIRV Commands Extension"; 25 | outputWindow.CreatePane(ref customGuid, customTitle, 1, 1); 26 | IVsOutputWindowPane pane; 27 | outputWindow.GetPane(ref customGuid, out pane); 28 | return pane; 29 | } 30 | 31 | static public void Add(string text) 32 | { 33 | customPane().OutputString(text); 34 | } 35 | 36 | public static void Clear() 37 | { 38 | customPane().Clear(); 39 | } 40 | 41 | public static void Show() 42 | { 43 | customPane().Activate(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /SPIRV-VSExtension/Shared/Utils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace SPIRVExtension.Shared 9 | { 10 | class Utils 11 | { 12 | /// 13 | /// Returns true if the file has a valid shader extension that can be used as an input for the reference compiler 14 | /// 15 | public static bool IsShaderFile(string fileName) 16 | { 17 | var shaderExtensions = new[] { ".vert", ".tesc", ".tese", ".geom", ".frag", ".comp", ".mesh", ".task", ".rgen", ".rint", ".rahit", ".rchit", ".rmiss", ".rcall" }; 18 | foreach (string ext in shaderExtensions) 19 | { 20 | if (string.Compare(ext, Path.GetExtension(fileName), StringComparison.OrdinalIgnoreCase) == 0) 21 | { 22 | return true; 23 | } 24 | } 25 | return false; 26 | } 27 | 28 | /// 29 | /// Returns true if the file has a ray tracing related file extension 30 | /// 31 | public static bool IsRayTracingShaderFile(string fileName) 32 | { 33 | var shaderExtensions = new[] { ".rgen", ".rint", ".rahit", ".rchit", ".rmiss", ".rcall" }; 34 | foreach (string ext in shaderExtensions) 35 | { 36 | if (string.Compare(ext, Path.GetExtension(fileName), StringComparison.OrdinalIgnoreCase) == 0) 37 | { 38 | return true; 39 | } 40 | } 41 | return false; 42 | } 43 | 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /SPIRV-VSExtension/Shared/ErrorList.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * SPIR-V Visual Studio Extension 3 | * 4 | * Copyright (C) 2016 by Sascha Willems - www.saschawillems.de 5 | * 6 | * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) 7 | */ 8 | 9 | using System; 10 | using Microsoft.VisualStudio.Shell; 11 | using Microsoft.VisualStudio.Shell.Interop; 12 | 13 | namespace SPIRVExtension 14 | { 15 | /// 16 | /// Helper class for the adding items to the Visual Studio error list 17 | /// 18 | public static class ErrorList 19 | { 20 | private static ErrorListProvider errorListProvider; 21 | 22 | public static void Initialize(IServiceProvider serviceProvider) 23 | { 24 | errorListProvider = new ErrorListProvider(serviceProvider); 25 | } 26 | 27 | public static void Add(string text, string fileName, int line, int column, IVsHierarchy hierarchy) 28 | { 29 | ErrorTask errorTask = new ErrorTask(); 30 | errorTask.Text = text; 31 | errorTask.Line = line - 1; 32 | errorTask.Column = column; 33 | errorTask.Category = TaskCategory.User; 34 | errorTask.ErrorCategory = TaskErrorCategory.Error; 35 | errorTask.Document = fileName; 36 | errorTask.HierarchyItem = hierarchy; 37 | errorTask.Navigate += DocumentHelper.NavigateDocument; 38 | errorListProvider.Tasks.Add(errorTask); 39 | } 40 | 41 | public static void Clear() 42 | { 43 | errorListProvider.Tasks.Clear(); 44 | } 45 | 46 | public static void Show() 47 | { 48 | errorListProvider.Show(); 49 | } 50 | 51 | public static int ErrorCount() 52 | { 53 | return errorListProvider.Tasks.Count; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /SPIRV-VSExtension/source.extension.vsixmanifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SPIRV-VSExtension 6 | Adds SPIR-V commands to the context menu of GLSL/HLSL shader files and folders. Generate SPIR-V binaries for Vulkan or OpenGL and display human readable SPIR-V directly inside Visual Studio. 7 | LICENSE 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /SPIRV-VSExtension/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /SPIRV-VSExtension/CommandCompileHLSL.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * SPIR-V Visual Studio Extensiondeleted 3 | * 4 | * Copyright (C) 2016-2022 by Sascha Willems - www.saschawillems.de 5 | * 6 | * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) 7 | */ 8 | 9 | using System; 10 | using System.ComponentModel.Design; 11 | using System.Collections.Generic; 12 | using Microsoft.VisualStudio.Shell; 13 | 14 | namespace SPIRVExtension 15 | { 16 | internal sealed class CommandCompileHLSL : ShaderCommandBase 17 | { 18 | public const int CommandId = 0x0140; 19 | public static readonly Guid CommandSet = new Guid("c25a4989-8e55-4457-822d-1e690eb23169"); 20 | private readonly Package package; 21 | 22 | private CommandCompileHLSL(Package package) : base(package, "Compile HLSL to SPIR-V (Vulkan only)") 23 | { 24 | if (package == null) 25 | { 26 | throw new ArgumentNullException("package"); 27 | } 28 | 29 | this.package = package; 30 | 31 | OleMenuCommandService mcs = this.ServiceProvider.GetService(typeof(IMenuCommandService)) as OleMenuCommandService; 32 | if (null != mcs) 33 | { 34 | CommandID menuCommandID = new CommandID(CommandSet, (int)CommandId); 35 | OleMenuCommand oleMenuItem = new OleMenuCommand(new EventHandler(MenuItemCallback), menuCommandID); 36 | oleMenuItem.BeforeQueryStatus += new EventHandler(OnBeforeQueryStatus); 37 | mcs.AddCommand(oleMenuItem); 38 | } 39 | } 40 | 41 | public static CommandCompileHLSL Instance 42 | { 43 | get; 44 | private set; 45 | } 46 | 47 | public static void Initialize(Package package) 48 | { 49 | Instance = new CommandCompileHLSL(package); 50 | } 51 | 52 | private void MenuItemCallback(object sender, EventArgs e) 53 | { 54 | List selectedShaderFiles = new List(); 55 | if (GetSelectedShaderFiles(selectedShaderFiles)) 56 | { 57 | CompileShaders(selectedShaderFiles, DxcCompiler.CompileToVulkan); 58 | } 59 | } 60 | 61 | void OnBeforeQueryStatus(object sender, EventArgs e) 62 | { 63 | var item = (OleMenuCommand)sender; 64 | if (item != null) 65 | { 66 | int count = GetSelectedShaderFileCount(); 67 | item.Visible = (count > 0); 68 | item.Text = (count == 1) ? "Compile HLSL to SPIR-V (DXC)" : "Compile HLSL shaders to SPIR-V (DXC)"; 69 | } 70 | } 71 | 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /SPIRV-VSExtension/CommandCompileOpenGL.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * SPIR-V Visual Studio Extension 3 | * 4 | * Copyright (C) 2016 by Sascha Willems - www.saschawillems.de 5 | * 6 | * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) 7 | */ 8 | 9 | using System; 10 | using System.ComponentModel.Design; 11 | using System.Collections.Generic; 12 | using Microsoft.VisualStudio.Shell; 13 | 14 | namespace SPIRVExtension 15 | { 16 | internal sealed class CommandCompileOpenGL : ShaderCommandBase 17 | { 18 | public const int CommandId = 0x0110; 19 | public static readonly Guid CommandSet = new Guid("c25a4989-8e55-4457-822d-1e690eb23169"); 20 | private readonly Package package; 21 | 22 | private CommandCompileOpenGL(Package package) : base(package, "Compile to SPIR-V (OpenGL semantics)") 23 | { 24 | if (package == null) 25 | { 26 | throw new ArgumentNullException("package"); 27 | } 28 | 29 | this.package = package; 30 | 31 | OleMenuCommandService mcs = this.ServiceProvider.GetService(typeof(IMenuCommandService)) as OleMenuCommandService; 32 | if (null != mcs) 33 | { 34 | CommandID menuCommandID = new CommandID(CommandSet, (int)CommandId); 35 | OleMenuCommand oleMenuItem = new OleMenuCommand(new EventHandler(MenuItemCallback), menuCommandID); 36 | oleMenuItem.BeforeQueryStatus += new EventHandler(OnBeforeQueryStatus); 37 | mcs.AddCommand(oleMenuItem); 38 | } 39 | } 40 | 41 | public static CommandCompileOpenGL Instance 42 | { 43 | get; 44 | private set; 45 | } 46 | 47 | public static void Initialize(Package package) 48 | { 49 | Instance = new CommandCompileOpenGL(package); 50 | } 51 | 52 | private void MenuItemCallback(object sender, EventArgs e) 53 | { 54 | List selectedShaderFiles = new List(); 55 | if (GetSelectedShaderFiles(selectedShaderFiles)) 56 | { 57 | CompileShaders(selectedShaderFiles, GlslangCompiler.CompileToOpenGL); 58 | } 59 | } 60 | 61 | void OnBeforeQueryStatus(object sender, EventArgs e) 62 | { 63 | var item = (OleMenuCommand)sender; 64 | if (item != null) 65 | { 66 | int count = GetSelectedShaderFileCount(); 67 | item.Visible = (count > 0); 68 | item.Text = (count == 1) ? "Compile to SPIR-V (OpenGL)" : "Compile shaders to SPIR-V (OpenGL)"; 69 | } 70 | } 71 | 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /SPIRV-VSExtension/CommandCompileVulkan.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * SPIR-V Visual Studio Extension 3 | * 4 | * Copyright (C) 2016 by Sascha Willems - www.saschawillems.de 5 | * 6 | * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) 7 | */ 8 | 9 | using System; 10 | using System.ComponentModel.Design; 11 | using System.Collections.Generic; 12 | using Microsoft.VisualStudio.Shell; 13 | 14 | namespace SPIRVExtension 15 | { 16 | internal sealed class CommandCompileVulkan : ShaderCommandBase 17 | { 18 | public const int CommandId = 0x0100; 19 | public static readonly Guid CommandSet = new Guid("c25a4989-8e55-4457-822d-1e690eb23169"); 20 | private readonly Package package; 21 | 22 | private CommandCompileVulkan(Package package) : base(package, "Compile GLSL to SPIR-V (Vulkan semantics)") 23 | { 24 | if (package == null) 25 | { 26 | throw new ArgumentNullException("package"); 27 | } 28 | 29 | this.package = package; 30 | 31 | OleMenuCommandService mcs = this.ServiceProvider.GetService(typeof(IMenuCommandService)) as OleMenuCommandService; 32 | if (null != mcs) 33 | { 34 | CommandID menuCommandID = new CommandID(CommandSet, (int)CommandId); 35 | OleMenuCommand oleMenuItem = new OleMenuCommand(new EventHandler(MenuItemCallback), menuCommandID); 36 | oleMenuItem.BeforeQueryStatus += new EventHandler(OnBeforeQueryStatus); 37 | mcs.AddCommand(oleMenuItem); 38 | } 39 | } 40 | 41 | public static CommandCompileVulkan Instance 42 | { 43 | get; 44 | private set; 45 | } 46 | 47 | public static void Initialize(Package package) 48 | { 49 | Instance = new CommandCompileVulkan(package); 50 | } 51 | 52 | private void MenuItemCallback(object sender, EventArgs e) 53 | { 54 | List selectedShaderFiles = new List(); 55 | if (GetSelectedShaderFiles(selectedShaderFiles)) 56 | { 57 | CompileShaders(selectedShaderFiles, GlslangCompiler.CompileToVulkan); 58 | } 59 | } 60 | 61 | void OnBeforeQueryStatus(object sender, EventArgs e) 62 | { 63 | var item = (OleMenuCommand)sender; 64 | if (item != null) 65 | { 66 | int count = GetSelectedShaderFileCount(); 67 | item.Visible = (count > 0); 68 | item.Text = (count == 1) ? "Compile GLSL to SPIR-V (Vulkan)" : "Compile GLSL shaders to SPIR-V (Vulkan)"; 69 | } 70 | } 71 | 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /SPIRV-VSExtension/Shared/DocumentHelper.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * SPIR-V Visual Studio Extension 3 | * 4 | * Copyright (C) 2016 by Sascha Willems - www.saschawillems.de 5 | * 6 | * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) 7 | */ 8 | 9 | using System; 10 | using Microsoft.VisualStudio; 11 | using Microsoft.VisualStudio.Shell; 12 | using Microsoft.VisualStudio.Shell.Interop; 13 | using Microsoft.VisualStudio.TextManager.Interop; 14 | 15 | namespace SPIRVExtension 16 | { 17 | /// 18 | /// Helper class for displaying documents and navigating inside of them 19 | /// 20 | public static class DocumentHelper 21 | { 22 | /// 23 | /// Open the file and jump to a line (and optional column) 24 | /// 25 | public static void OpenAndNavigateTo(string fileName, int line, int column = 0) 26 | { 27 | IVsUIShellOpenDocument uishellOpenDocument = Package.GetGlobalService(typeof(IVsUIShellOpenDocument)) as IVsUIShellOpenDocument; 28 | if (uishellOpenDocument != null) 29 | { 30 | Microsoft.VisualStudio.OLE.Interop.IServiceProvider serviceProvider; 31 | IVsWindowFrame frame; 32 | IVsUIHierarchy hierarchy; 33 | uint itemId; 34 | Guid logicalView = VSConstants.LOGVIEWID_Code; 35 | if (ErrorHandler.Succeeded(uishellOpenDocument.OpenDocumentViaProject(fileName, ref logicalView, out serviceProvider, out hierarchy, out itemId, out frame))) 36 | { 37 | object document; 38 | frame.GetProperty((int)__VSFPROPID.VSFPROPID_DocData, out document); 39 | VsTextBuffer buffer = document as VsTextBuffer; 40 | if (buffer == null) 41 | { 42 | IVsTextBufferProvider bufferProvider = document as IVsTextBufferProvider; 43 | if (bufferProvider != null) 44 | { 45 | IVsTextLines lines; 46 | ErrorHandler.ThrowOnFailure(bufferProvider.GetTextBuffer(out lines)); 47 | buffer = lines as VsTextBuffer; 48 | } 49 | } 50 | if (buffer != null) 51 | { 52 | IVsTextManager textManager = Package.GetGlobalService(typeof(VsTextManagerClass)) as IVsTextManager; 53 | textManager.NavigateToLineAndColumn(buffer, ref logicalView, line, column, line, column); 54 | } 55 | } 56 | } 57 | } 58 | 59 | /// 60 | /// Callback to be assigned to a task 61 | /// 62 | public static void NavigateDocument(object sender, EventArgs e) 63 | { 64 | Task task = sender as Task; 65 | OpenAndNavigateTo(task.Document, task.Line, task.Column); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /SPIRV-VSExtension/CommandPrintSPIRV.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * SPIR-V Visual Studio Extension 3 | * 4 | * Copyright (C) 2016 by Sascha Willems - www.saschawillems.de 5 | * 6 | * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) 7 | */ 8 | 9 | using Microsoft.VisualStudio.Shell; 10 | using System; 11 | using System.Collections.Generic; 12 | using System.ComponentModel.Design; 13 | using System.IO; 14 | 15 | namespace SPIRVExtension 16 | { 17 | internal sealed class CommandPrintSPIRV : ShaderCommandBase 18 | { 19 | public const int CommandId = 0x0130; 20 | public static readonly Guid CommandSet = new Guid("c25a4989-8e55-4457-822d-1e690eb23169"); 21 | private readonly Package package; 22 | 23 | private CommandPrintSPIRV(Package package) : base(package, "Print human readable SPIR-V") 24 | { 25 | if (package == null) 26 | { 27 | throw new ArgumentNullException("package"); 28 | } 29 | 30 | this.package = package; 31 | 32 | OleMenuCommandService mcs = this.ServiceProvider.GetService(typeof(IMenuCommandService)) as OleMenuCommandService; 33 | if (null != mcs) 34 | { 35 | CommandID menuCommandID = new CommandID(CommandSet, (int)CommandId); 36 | OleMenuCommand oleMenuItem = new OleMenuCommand(new EventHandler(MenuItemCallback), menuCommandID); 37 | oleMenuItem.BeforeQueryStatus += new EventHandler(OnBeforeQueryStatus); 38 | mcs.AddCommand(oleMenuItem); 39 | } 40 | } 41 | 42 | public static CommandPrintSPIRV Instance 43 | { 44 | get; 45 | private set; 46 | } 47 | 48 | public static void Initialize(Package package) 49 | { 50 | Instance = new CommandPrintSPIRV(package); 51 | } 52 | 53 | private void MenuItemCallback(object sender, EventArgs e) 54 | { 55 | List selectedShaderFiles = new List(); 56 | if (GetSelectedShaderFiles(selectedShaderFiles)) 57 | { 58 | ErrorList.Clear(); 59 | foreach (var shaderFile in selectedShaderFiles) 60 | { 61 | List spirvOutput = new List(); 62 | if (GetReadableSPIRV(shaderFile, out spirvOutput)) 63 | { 64 | string fileName = Path.GetTempPath() + Path.GetFileName(shaderFile.fileName) + ".spirv.readable"; 65 | File.WriteAllLines(fileName, spirvOutput); 66 | VsShellUtilities.OpenDocument(ServiceProvider, fileName); 67 | } 68 | } 69 | if (ErrorList.ErrorCount() > 0) 70 | { 71 | ErrorList.Show(); 72 | } 73 | } 74 | } 75 | 76 | void OnBeforeQueryStatus(object sender, EventArgs e) 77 | { 78 | var item = (OleMenuCommand)sender; 79 | if (item != null) 80 | { 81 | int count = GetSelectedShaderFileCount(); 82 | item.Visible = (count > 0); 83 | item.Text = "Print human-readable SPIR-V"; 84 | } 85 | } 86 | 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SPIR-V extension for Visual Studio (VSIX) 2 | 3 | ## About 4 | 5 | 6 | 7 | This VSIX extension adds commands to the context menu of shader files (and folders containing shaders) that let's you quickly compile to them to SPIR-V and supports both GLSL and HLSL as source. 8 | 9 | ## Requirements 10 | 11 | ### GLSL standalone reference compiler 12 | The extension requires a version of the glslang reference compiler to be in your path that supports SPIR-V: 13 | 14 | - Install the [LunartG Vulkan SDK](https://vulkan.lunarg.com/) (comes with a pre-built version) 15 | - Built from the sources at [https://github.com/KhronosGroup/glslang](https://github.com/KhronosGroup/glslang) 16 | 17 | The extension will search for the ```glslangvalidator.exe``` using the paths from the following environment variables: ```PATH```, ```VK_SDK_PATH``` and ```VULKAN_SDK``` (set by the LunarG SDK). Alternatively you can override this with an explicit location in the extensions' settings page. 18 | 19 | ### DXC standalone compiler 20 | For compiling from HLSL, the extension requires a version of the DirectX shader compiler to be in your path that supports SPIR-V: 21 | 22 | - Install the [LunartG Vulkan SDK](https://vulkan.lunarg.com/) (comes with a pre-built version) 23 | - Built from the sources at [https://github.com/microsoft/DirectXShaderCompiler/](https://github.com/microsoft/DirectXShaderCompiler/) 24 | 25 | The extension will search for the ```dxc.exe``` using the paths from the following environment variables: ```PATH```, ```VK_SDK_PATH``` and ```VULKAN_SDK``` (set by the LunarG SDK). Alternatively you can override this with an explicit location in the extensions' settings page. 26 | 27 | ### Supported Visual Studio versions 28 | The extension supports all editions of **Visual Studio 2015, 2017 and 2019**. 29 | 30 | ## Installation 31 | 32 | The extension is available at the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=SaschaWillems.SPIRV-VSExtension) and can be installed directly from the IDE. 33 | 34 | ## New context menu entries 35 | 36 | 37 | 38 | The context menu entries will be displayed if the current file selection or folder includes at least one shader file with a file extension supported by the GLSL reference compiler: 39 | - ```.vert``` (Vertex shader) 40 | - ```.tesc``` (Tessellation control shader) 41 | - ```.tese``` (Tessellation evaluation shader) 42 | - ```.geom``` (Geometry shader) 43 | - ```.frag``` (Fragment shader) 44 | - ```.comp``` (Compute shader) 45 | - ```.mesh``` (Mesh shader) 46 | - ```.task``` (Task shader) 47 | - ```.rgen``` (Ray generation shader) 48 | - ```.rint``` (Ray intersection shader) 49 | - ```.rahit``` (Ray any hit shader) 50 | - ```.rchit``` (Ray closest hit shader) 51 | - ```.rmiss``` (Ray miss shader) 52 | - ```.rcall``` (Ray callable shader) 53 | 54 | These are currently fixed, but future versions may add an options pane to adjust file extensions and how they are treated. 55 | 56 | ## Features 57 | 58 | ### SPIR-V functions 59 | 60 | #### Compile GLSL to SPIR-V (Vulkan semantics) 61 | Compile all selected GLSL shader files to SPIR-V binary using Vulkan semantics (-V). 62 | 63 | #### Compile HLSL to SPIR-V (DXC) 64 | Compile all selected HLSL shader files to SPIR-V binary format using the SPIR-V back-end of the DirectX shader compiler. 65 | 66 | #### Compile to SPIR-V (OpenGL semantics) 67 | Compile all selected shader files to SPIR-V binary using OpenGL semantics (-G). 68 | 69 | **Note:** SPIR-V for OpenGL is supported with the [```GL_ARB_gl_spirv```](https://www.opengl.org/registry/specs/ARB/gl_spirv.txt) extension and implemented as a binary shader format. 70 | 71 | A C++ example for loading a binary SPIR-V shader with OpenGL [can be found here](https://github.com/SaschaWillems/openglcpp/tree/master/SPIRVShader). 72 | 73 | #### Print human-readable SPIR-V 74 | 75 | This will output human readable SPIR-V (-H) using Vulkan semantics and displays it in a new document window. 76 | 77 | ### Error list 78 | 79 | 80 | 81 | Compile errors are added to the error list of Visual Studio and work like regular compile errors. Double clicking on an error will open that shader and jump to the line that the error has occured. 82 | 83 | ## Todo 84 | This is a very early version of this extension, some of the planned features are: 85 | - Extension settings pane 86 | - Add file extension mappings 87 | - Custom binary SPIR-V output file name scheme (instead of a fixed output file scheme) 88 | - Option to disable dialog boxes after compile 89 | - Option to use a remapper (SPIR-V remap etc.) 90 | - Save to text as hexadecimal numbers (-x) 91 | - Generate include headers 92 | - Language features (as soon as their support by the reference compiler is finished) 93 | - Multiple main entry points 94 | - Compile from HLSL 95 | 96 | Issues and pull request for additional features are welcome :) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | *.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.pfx 193 | *.publishsettings 194 | node_modules/ 195 | orleans.codegen.cs 196 | 197 | # Since there are multiple workflows, uncomment next line to ignore bower_components 198 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 199 | #bower_components/ 200 | 201 | # RIA/Silverlight projects 202 | Generated_Code/ 203 | 204 | # Backup & report files from converting an old project file 205 | # to a newer Visual Studio version. Backup files are not needed, 206 | # because we have git ;-) 207 | _UpgradeReport_Files/ 208 | Backup*/ 209 | UpgradeLog*.XML 210 | UpgradeLog*.htm 211 | 212 | # SQL Server files 213 | *.mdf 214 | *.ldf 215 | 216 | # Business Intelligence projects 217 | *.rdl.data 218 | *.bim.layout 219 | *.bim_*.settings 220 | 221 | # Microsoft Fakes 222 | FakesAssemblies/ 223 | 224 | # GhostDoc plugin setting file 225 | *.GhostDoc.xml 226 | 227 | # Node.js Tools for Visual Studio 228 | .ntvs_analysis.dat 229 | 230 | # Visual Studio 6 build log 231 | *.plg 232 | 233 | # Visual Studio 6 workspace options file 234 | *.opt 235 | 236 | # Visual Studio LightSwitch build output 237 | **/*.HTMLClient/GeneratedArtifacts 238 | **/*.DesktopClient/GeneratedArtifacts 239 | **/*.DesktopClient/ModelManifest.xml 240 | **/*.Server/GeneratedArtifacts 241 | **/*.Server/ModelManifest.xml 242 | _Pvt_Extensions 243 | 244 | # Paket dependency manager 245 | .paket/paket.exe 246 | paket-files/ 247 | 248 | # FAKE - F# Make 249 | .fake/ 250 | 251 | # JetBrains Rider 252 | .idea/ 253 | *.sln.iml 254 | 255 | # CodeRush 256 | .cr/ 257 | 258 | # Python Tools for Visual Studio (PTVS) 259 | __pycache__/ 260 | *.pyc 261 | -------------------------------------------------------------------------------- /SPIRV-VSExtension/Shared/GlslangCompiler.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * SPIR-V Visual Studio Extension 3 | * 4 | * Copyright (C) 2016 by Sascha Willems - www.saschawillems.de 5 | * 6 | * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) 7 | */ 8 | 9 | using Microsoft.VisualStudio.Shell; 10 | using SPIRVExtension.Shared; 11 | using System; 12 | using System.Collections.Generic; 13 | using System.Diagnostics; 14 | using System.Globalization; 15 | using System.IO; 16 | 17 | namespace SPIRVExtension 18 | { 19 | /// 20 | /// Helper class for locating and invocating the glslang reference compiler 21 | /// 22 | public class GlslangCompiler 23 | { 24 | /// 25 | /// Searches the PATH environment and common SDK path environment variables for the glslangvalidator 26 | /// 27 | public static string Locate(SPIRVExtensionPackage package) 28 | { 29 | if (package.OptionGlslangValidatorBinaryPath != "") 30 | { 31 | OutputWindow.Add("Using glslangvalidator from options path: " + Path.Combine(package.OptionGlslangValidatorBinaryPath, "glslangvalidator.exe")); 32 | return Path.Combine(package.OptionGlslangValidatorBinaryPath, "glslangvalidator.exe"); 33 | } 34 | 35 | var pathEnv = Environment.GetEnvironmentVariable("PATH"); 36 | List paths = new List(pathEnv.Split(';')); 37 | var additionalPaths = new[] { "VK_SDK_PATH", "VULKAN_SDK" }; 38 | foreach (string path in additionalPaths) 39 | { 40 | if (Environment.GetEnvironmentVariable(path) != null) 41 | { 42 | paths.Add(Environment.GetEnvironmentVariable(path)); 43 | } 44 | } 45 | 46 | foreach (var path in paths) 47 | { 48 | var filePath = Path.Combine(path, "glslangvalidator.exe"); 49 | if (File.Exists(filePath)) 50 | { 51 | return filePath; 52 | } 53 | } 54 | return null; 55 | } 56 | 57 | private static bool Run(string fileName, string commandLine, out List validatorOutput, SPIRVExtensionPackage package) 58 | { 59 | var startInfo = new ProcessStartInfo(); 60 | startInfo.FileName = Locate(package); 61 | startInfo.Arguments = commandLine; 62 | startInfo.UseShellExecute = false; 63 | startInfo.RedirectStandardOutput = true; 64 | startInfo.CreateNoWindow = true; 65 | 66 | var process = new Process(); 67 | process.StartInfo = startInfo; 68 | 69 | try 70 | { 71 | process.Start(); 72 | } 73 | catch (Exception e) 74 | { 75 | //todo: Display error message 76 | OutputWindow.Add("Exception while running: " + e.Message); 77 | throw; 78 | } 79 | 80 | OutputWindow.Add(Locate(package)); 81 | OutputWindow.Add(commandLine); 82 | 83 | List output = new List(); 84 | while (!process.StandardOutput.EndOfStream) 85 | { 86 | output.Add(process.StandardOutput.ReadLine()); 87 | } 88 | 89 | validatorOutput = output; 90 | 91 | return (process.ExitCode == 0); 92 | } 93 | 94 | /// 95 | /// Compile the shader using Vulkan semantics and output to a binary file (.spv) 96 | /// 97 | public static bool CompileToVulkan(string fileName, out List validatorOutput, SPIRVExtensionPackage package) 98 | { 99 | string commandLine = string.Format(CultureInfo.CurrentCulture, "-V \"{0}\" -o \"{1}\"", fileName, fileName + ".spv"); 100 | if (package.OptionTargetEnv != "") 101 | { 102 | commandLine += " --target-env " + package.OptionTargetEnv; 103 | } else 104 | { 105 | // Ray tracing shaders require at least SPIR-V 1.4 106 | if (Utils.IsRayTracingShaderFile(fileName)) { 107 | commandLine += " --target-env spirv1.4"; 108 | } 109 | } 110 | return Run(fileName, commandLine, out validatorOutput, package); 111 | } 112 | 113 | /// 114 | /// Compile the shader using OpenGL semantics and output to a binary file (.spv) 115 | /// 116 | public static bool CompileToOpenGL(string fileName, out List validatorOutput, SPIRVExtensionPackage package) 117 | { 118 | string commandLine = string.Format(CultureInfo.CurrentCulture, "-G \"{0}\" -o \"{1}\"", fileName, fileName + ".spv"); 119 | return Run(fileName, commandLine, out validatorOutput, package); 120 | } 121 | 122 | /// 123 | /// Converts the shader to human readable SPIR-V and returns the reference compiler output 124 | /// 125 | public static bool GetHumanReadableSPIRV(string fileName, out List validatorOutput, SPIRVExtensionPackage package) 126 | { 127 | string commandLine = string.Format(CultureInfo.CurrentCulture, "-H \"{0}\"", fileName); 128 | if (package.OptionTargetEnv != "") 129 | { 130 | commandLine += " --target-env " + package.OptionTargetEnv; 131 | } 132 | return Run(fileName, commandLine, out validatorOutput, package); 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /SPIRV-VSExtension/SPIRVExtensionPackage.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * SPIR-V Visual Studio Extension 3 | * 4 | * Copyright (C) 2016 by Sascha Willems - www.saschawillems.de 5 | * 6 | * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) 7 | */ 8 | 9 | using System; 10 | using System.ComponentModel.Design; 11 | using System.Diagnostics; 12 | using System.Diagnostics.CodeAnalysis; 13 | using System.Globalization; 14 | using System.Runtime.InteropServices; 15 | using System.ComponentModel; 16 | using Microsoft.VisualStudio; 17 | using Microsoft.VisualStudio.OLE.Interop; 18 | using Microsoft.VisualStudio.Shell; 19 | using Microsoft.VisualStudio.Shell.Interop; 20 | using Microsoft.Win32; 21 | 22 | public class OptionPageGrid : DialogPage 23 | { 24 | [Category("GLSL")] 25 | [DisplayName("Target Environment")] 26 | [Description("Select the target environment for Vulkan shader compilation")] 27 | public string OptionTargetEnv { get; set; } = ""; 28 | 29 | [Category("GLSL")] 30 | [DisplayName("glslangvalidator path")] 31 | [Description("Manually specify a path to the glslangvalidator binary to override the default one from PATH")] 32 | public string OptionGlslangValidatorBinaryPath { get; set; } = ""; 33 | 34 | [Category("HLSL")] 35 | [DisplayName("dxc path")] 36 | [Description("Manually specify a path to the dxc binary to override the default one from PATH")] 37 | public string OptionDxcBinaryPath { get; set; } = ""; 38 | } 39 | 40 | namespace SPIRVExtension 41 | { 42 | /// 43 | /// This is the class that implements the package exposed by this assembly. 44 | /// 45 | /// 46 | /// 47 | /// The minimum requirement for a class to be considered a valid package for Visual Studio 48 | /// is to implement the IVsPackage interface and register itself with the shell. 49 | /// This package uses the helper classes defined inside the Managed Package Framework (MPF) 50 | /// to do it: it derives from the Package class that provides the implementation of the 51 | /// IVsPackage interface and uses the registration attributes defined in the framework to 52 | /// register itself and its components with the shell. These attributes tell the pkgdef creation 53 | /// utility what data to put into .pkgdef file. 54 | /// 55 | /// 56 | /// To get loaded into VS, the package must be referred by <Asset Type="Microsoft.VisualStudio.VsPackage" ...> in .vsixmanifest file. 57 | /// 58 | /// 59 | [PackageRegistration(UseManagedResourcesOnly = true)] 60 | [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)] // Info on this package for Help/About 61 | [ProvideMenuResource("Menus.ctmenu", 1)] 62 | [Guid(SPIRVExtensionPackage.PackageGuidString)] 63 | [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "pkgdef, VS and vsixmanifest are valid VS terms")] 64 | [ProvideAutoLoad("f1536ef8-92ec-443c-9ed7-fdadf150da82")] 65 | [ProvideOptionPage(typeof(OptionPageGrid), 66 | "SPIRV Extension", "General", 0, 0, true)] 67 | public sealed class SPIRVExtensionPackage : Package 68 | { 69 | /// 70 | /// SPIRVExtension GUID string. 71 | /// 72 | public const string PackageGuidString = "1ec0f76d-4687-49ea-a037-76a4ab592f51"; 73 | 74 | /// 75 | /// Initializes a new instance of the class. 76 | /// 77 | public SPIRVExtensionPackage() 78 | { 79 | // Inside this method you can place any initialization code that does not require 80 | // any Visual Studio service because at this point the package object is created but 81 | // not sited yet inside Visual Studio environment. The place to do all the other 82 | // initialization is the Initialize method. 83 | } 84 | 85 | #region Package Members 86 | 87 | /// 88 | /// Initialization of the package; this method is called right after the package is sited, so this is the place 89 | /// where you can put all the initialization code that rely on services provided by VisualStudio. 90 | /// 91 | protected override void Initialize() 92 | { 93 | CommandCompileVulkan.Initialize(this); 94 | CommandCompileHLSL.Initialize(this); 95 | CommandCompileOpenGL.Initialize(this); 96 | CommandPrintSPIRV.Initialize(this); 97 | 98 | base.Initialize(); 99 | ErrorList.Initialize(this); 100 | } 101 | 102 | public string OptionTargetEnv 103 | { 104 | get 105 | { 106 | OptionPageGrid page = (OptionPageGrid)GetDialogPage(typeof(OptionPageGrid)); 107 | return page.OptionTargetEnv; 108 | } 109 | } 110 | 111 | public string OptionGlslangValidatorBinaryPath 112 | { 113 | get 114 | { 115 | OptionPageGrid page = (OptionPageGrid)GetDialogPage(typeof(OptionPageGrid)); 116 | return page.OptionGlslangValidatorBinaryPath; 117 | } 118 | } 119 | 120 | public string OptionDxcBinaryPath 121 | { 122 | get 123 | { 124 | OptionPageGrid page = (OptionPageGrid)GetDialogPage(typeof(OptionPageGrid)); 125 | return page.OptionDxcBinaryPath; 126 | } 127 | } 128 | #endregion 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /SPIRV-VSExtension/Shared/DxcCompiler.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * SPIR-V Visual Studio Extension 3 | * 4 | * Copyright (C) 2016-2022 by Sascha Willems - www.saschawillems.de 5 | * 6 | * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) 7 | */ 8 | 9 | using Microsoft.VisualStudio.Shell; 10 | using SPIRVExtension.Shared; 11 | using System; 12 | using System.Collections.Generic; 13 | using System.Diagnostics; 14 | using System.Globalization; 15 | using System.IO; 16 | 17 | namespace SPIRVExtension 18 | { 19 | /// 20 | /// Helper class for locating and invocating the DXC compiler 21 | /// 22 | public class DxcCompiler 23 | { 24 | /// 25 | /// Searches the PATH environment and common SDK path environment variables for the glslangvalidator 26 | /// 27 | public static string Locate(SPIRVExtensionPackage package) 28 | { 29 | if (package.OptionGlslangValidatorBinaryPath != "") 30 | { 31 | OutputWindow.Add("Using glslangvalidator from options path: " + Path.Combine(package.OptionGlslangValidatorBinaryPath, "glslangvalidator.exe")); 32 | return Path.Combine(package.OptionGlslangValidatorBinaryPath, "glslangvalidator.exe"); 33 | } 34 | 35 | var pathEnv = Environment.GetEnvironmentVariable("PATH"); 36 | List paths = new List(pathEnv.Split(';')); 37 | var additionalPaths = new[] { "VK_SDK_PATH", "VULKAN_SDK" }; 38 | foreach (string path in additionalPaths) 39 | { 40 | if (Environment.GetEnvironmentVariable(path) != null) 41 | { 42 | paths.Add(Environment.GetEnvironmentVariable(path)); 43 | } 44 | } 45 | 46 | foreach (var path in paths) 47 | { 48 | var filePath = Path.Combine(path, "dxc.exe"); 49 | if (File.Exists(filePath)) 50 | { 51 | return filePath; 52 | } 53 | } 54 | return null; 55 | } 56 | 57 | private static bool Run(string fileName, string commandLine, out List validatorOutput, SPIRVExtensionPackage package) 58 | { 59 | var startInfo = new ProcessStartInfo(); 60 | startInfo.FileName = Locate(package); 61 | startInfo.Arguments = commandLine; 62 | startInfo.UseShellExecute = false; 63 | startInfo.RedirectStandardOutput = true; 64 | startInfo.CreateNoWindow = true; 65 | 66 | var process = new Process(); 67 | process.StartInfo = startInfo; 68 | 69 | try 70 | { 71 | process.Start(); 72 | } 73 | catch (Exception e) 74 | { 75 | //todo: Display error message 76 | OutputWindow.Add("Exception while running: " + e.Message); 77 | throw; 78 | } 79 | 80 | OutputWindow.Add(Locate(package)); 81 | OutputWindow.Add(commandLine); 82 | 83 | List output = new List(); 84 | while (!process.StandardOutput.EndOfStream) 85 | { 86 | output.Add(process.StandardOutput.ReadLine()); 87 | } 88 | 89 | validatorOutput = output; 90 | 91 | return (process.ExitCode == 0); 92 | } 93 | 94 | /// 95 | /// Compile the shader using Vulkan semantics and output to a binary file (.spv) 96 | /// 97 | public static bool CompileToVulkan(string fileName, out List validatorOutput, SPIRVExtensionPackage package) 98 | { 99 | // Get profile and additional options based on file extension 100 | var profileDictionary = new Dictionary 101 | { 102 | { ".vert", "vs_6_1" }, 103 | { ".frag", "ps_6_1" }, 104 | { ".comp", "cs_6_1" }, 105 | { ".geom", "gs_6_1" }, 106 | { ".tesc", "hs_6_1" }, 107 | { ".tese", "ds_6_1" }, 108 | { ".rgen", "lib_6_3" }, 109 | { ".rchit", "lib_6_3" }, 110 | { ".rmiss", "lib_6_3" }, 111 | }; 112 | string fileExt = Path.GetExtension(fileName).ToLower(); 113 | if (!profileDictionary.ContainsKey(fileExt)) 114 | { 115 | // @todo: add message 116 | List output = new List(); 117 | output.Add("Could not match file extension to HLSL shader profile"); 118 | validatorOutput = output; 119 | return false; 120 | } 121 | string profile = profileDictionary[fileExt]; 122 | 123 | List commandLineArgs = new List(); 124 | commandLineArgs.Add("-spirv"); 125 | commandLineArgs.Add("-T " + profile); 126 | commandLineArgs.Add("-E main"); 127 | if (package.OptionTargetEnv != "") 128 | { 129 | commandLineArgs.Add("-fspv-target-env=" + package.OptionTargetEnv); 130 | } 131 | else 132 | { 133 | // Ray tracing shaders require at least SPIR-V 1.4 134 | if (Utils.IsRayTracingShaderFile(fileName)) 135 | { 136 | commandLineArgs.Add("-fspv-target-env=vulkan1.2"); 137 | } 138 | } 139 | commandLineArgs.Add(fileName); 140 | commandLineArgs.Add("-Fo"); 141 | commandLineArgs.Add(fileName + ".spv"); 142 | 143 | string commandLine = string.Join(" ", commandLineArgs); 144 | return Run(fileName, commandLine, out validatorOutput, package); 145 | } 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /SPIRV-VSExtension/VSPackage.resx: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | text/microsoft-resx 120 | 121 | 122 | 2.0 123 | 124 | 125 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 126 | 127 | 128 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 129 | 130 | 131 | 132 | SPIRV Extension 133 | 134 | 135 | SPIRV Visual Studio Extension Detailed Info 136 | 137 | 138 | Resources\SPIRVExtension.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 139 | 140 | -------------------------------------------------------------------------------- /SPIRV-VSExtension/SPIRVExtensionPackage.vsct: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 25 | 26 | 33 | 34 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 47 | 48 | 49 | 50 | 60 | 61 | 62 | 72 | 73 | 74 | 84 | 85 | 86 | 96 | 97 | 98 | 99 | 100 | 101 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /SPIRV-VSExtension/ShaderCommandBase.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio; 2 | using Microsoft.VisualStudio.Shell; 3 | using Microsoft.VisualStudio.Shell.Interop; 4 | using SPIRVExtension.Shared; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Diagnostics; 8 | using System.Globalization; 9 | using System.IO; 10 | using System.Runtime.InteropServices; 11 | using System.Text.RegularExpressions; 12 | 13 | namespace SPIRVExtension 14 | { 15 | public delegate bool CompileFunc(string a, out List b, SPIRVExtensionPackage p); 16 | 17 | /// 18 | /// Base class for commands that compile to SPIR-V 19 | /// 20 | public class ShaderCommandBase 21 | { 22 | private readonly Package package; 23 | public string name; 24 | 25 | public ShaderCommandBase(Package package, string name) 26 | { 27 | this.package = package; 28 | this.name = name; 29 | } 30 | 31 | /// 32 | /// Gets the service provider from the owner package. 33 | /// 34 | public IServiceProvider ServiceProvider 35 | { 36 | get 37 | { 38 | return this.package; 39 | } 40 | } 41 | 42 | /// 43 | /// Read hierarchy of an item recursively to also include files in folders 44 | /// 45 | public void ReadItemHierarchy(uint itemid, IVsHierarchy hierarchy, List itemids) 46 | { 47 | itemids.Add(itemid); 48 | 49 | object value = null; 50 | int res = hierarchy.GetProperty(itemid, (int)__VSHPROPID.VSHPROPID_FirstVisibleChild, out value); 51 | 52 | if (res != VSConstants.S_OK || value == null) 53 | { 54 | // Single item, add and return 55 | if (value is int) 56 | { 57 | itemids.Add(Convert.ToUInt32(value)); 58 | return; 59 | } 60 | } 61 | else 62 | { 63 | // Item has siblings (e.g. folder) 64 | while (res == VSConstants.S_OK && value != null) 65 | { 66 | if (value is int && (uint)(int)value == VSConstants.VSITEMID_NIL) 67 | { 68 | break; 69 | } 70 | uint childNode = Convert.ToUInt32(value); 71 | ReadItemHierarchy(childNode, hierarchy, itemids); 72 | res = hierarchy.GetProperty(childNode, (int)__VSHPROPID.VSHPROPID_NextVisibleSibling, out value); 73 | } 74 | } 75 | } 76 | 77 | /// 78 | /// Returns a list of valid shader files from the current file selection 79 | /// 80 | /// List to be filled with all valid shader files from the current selection 81 | /// True if at least one shader has been selected 82 | public bool GetSelectedShaderFiles(List shaderFiles) 83 | { 84 | IVsHierarchy hierarchy = null; 85 | uint itemid = VSConstants.VSITEMID_NIL; 86 | int hr = VSConstants.S_OK; 87 | 88 | var monitorSelection = Package.GetGlobalService(typeof(SVsShellMonitorSelection)) as IVsMonitorSelection; 89 | var solution = Package.GetGlobalService(typeof(SVsSolution)) as IVsSolution; 90 | if (monitorSelection == null || solution == null) 91 | { 92 | return false; 93 | } 94 | 95 | IVsMultiItemSelect multiItemSelect = null; 96 | IntPtr hierarchyPtr = IntPtr.Zero; 97 | IntPtr selectionContainerPtr = IntPtr.Zero; 98 | 99 | try 100 | { 101 | hr = monitorSelection.GetCurrentSelection(out hierarchyPtr, out itemid, out multiItemSelect, out selectionContainerPtr); 102 | 103 | if (ErrorHandler.Failed(hr) || hierarchyPtr == IntPtr.Zero || itemid == VSConstants.VSITEMID_NIL) 104 | { 105 | return false; 106 | } 107 | 108 | hierarchy = Marshal.GetObjectForIUnknown(hierarchyPtr) as IVsHierarchy; 109 | if (hierarchy == null) 110 | { 111 | return false; 112 | } 113 | 114 | List itemids = new List(); 115 | 116 | if (multiItemSelect == null) 117 | { 118 | ReadItemHierarchy(itemid, hierarchy, itemids); 119 | } 120 | else 121 | { 122 | // todo: Read hierarchy for multi selects 123 | uint itemCount = 0; 124 | int fSingleHierarchy = 0; 125 | hr = multiItemSelect.GetSelectionInfo(out itemCount, out fSingleHierarchy); 126 | 127 | VSITEMSELECTION[] items = new VSITEMSELECTION[itemCount]; 128 | hr = multiItemSelect.GetSelectedItems(0, itemCount, items); 129 | 130 | foreach (var item in items) 131 | { 132 | itemids.Add(item.itemid); 133 | } 134 | 135 | } 136 | 137 | foreach (var id in itemids) 138 | { 139 | string filepath = null; 140 | ((IVsProject)hierarchy).GetMkDocument(id, out filepath); 141 | if (filepath != null && Utils.IsShaderFile(filepath)) 142 | { 143 | var transformFileInfo = new FileInfo(filepath); 144 | shaderFiles.Add(new ShaderFile(id, hierarchy, filepath)); 145 | } 146 | } 147 | 148 | // todo: hierarchy node 149 | if (itemid == VSConstants.VSITEMID_ROOT) 150 | { 151 | return false; 152 | } 153 | 154 | Guid guidProjectID = Guid.Empty; 155 | 156 | if (ErrorHandler.Failed(solution.GetGuidOfProject(hierarchy, out guidProjectID))) 157 | { 158 | return false; 159 | } 160 | 161 | return (shaderFiles.Count > 0); 162 | } 163 | finally 164 | { 165 | if (selectionContainerPtr != IntPtr.Zero) 166 | Marshal.Release(selectionContainerPtr); 167 | if (hierarchyPtr != IntPtr.Zero) 168 | Marshal.Release(hierarchyPtr); 169 | } 170 | } 171 | 172 | /// 173 | /// Gets the selected shader file count 174 | /// 175 | /// Count of valid selected shader files 176 | public int GetSelectedShaderFileCount() 177 | { 178 | List selectedShaderFiles = new List(); 179 | if (GetSelectedShaderFiles(selectedShaderFiles)) 180 | { 181 | return selectedShaderFiles.Count; 182 | } 183 | return 0; 184 | } 185 | 186 | /// 187 | /// Parse error output from the reference compiler and add it to the error list 188 | /// 189 | /// Output of the reference compiler 190 | /// Shader file info for which the validator output has been generated 191 | public void ParseErrors(List validatorOutput, ShaderFile shaderFile) 192 | { 193 | foreach (string line in validatorOutput) 194 | { 195 | // Examples: 196 | // ERROR: 0:26: 'aaa' : undeclared identifier 197 | // ERROR: E:\Vulkan\public\Vulkan\data\shaders\indirectdraw\ground.frag:16: '' : function does not return a value: test 198 | MatchCollection matches = Regex.Matches(line, @":\d+:\s", RegexOptions.IgnoreCase | RegexOptions.RightToLeft); 199 | if (matches.Count > 0) 200 | { 201 | // Line 202 | int errorLine = Convert.ToInt32(matches[0].Value.Replace(":", "")); 203 | // Error message 204 | string msg = line; 205 | Match match = Regex.Match(line, @"ERROR:\s.*\d+:(.*)", RegexOptions.IgnoreCase); 206 | if (match.Success) 207 | { 208 | msg = match.Groups[1].Value; 209 | } 210 | ErrorList.Add(msg, shaderFile.fileName, errorLine, 0, shaderFile.hierarchy); 211 | } 212 | } 213 | } 214 | 215 | /// 216 | /// Compile the shader file using the given compilation function 217 | /// 218 | public void CompileShaders(List shaderFiles, CompileFunc compileFunc) 219 | { 220 | string title = name; 221 | string msg; 222 | 223 | // @todo 224 | //if (GlslangCompiler.Locate(package as SPIRVExtensionPackage) == null) 225 | //{ 226 | // msg = "Could not locate the glslang reference compiler (glslangvalidator.exe) in system path!"; 227 | // VsShellUtilities.ShowMessageBox(ServiceProvider, msg, title, OLEMSGICON.OLEMSGICON_CRITICAL, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); 228 | // OutputWindow.Add(msg); 229 | // return; 230 | //} 231 | 232 | ErrorList.Clear(); 233 | 234 | bool success = true; 235 | msg = ""; 236 | foreach (var shaderFile in shaderFiles) 237 | { 238 | string targetEnv = (package as SPIRVExtensionPackage).OptionTargetEnv; 239 | 240 | List validatorOutput; 241 | bool compiled = compileFunc(shaderFile.fileName, out validatorOutput, package as SPIRVExtensionPackage); 242 | if (compiled) 243 | { 244 | OutputWindow.Add(string.Join("\n", validatorOutput)); 245 | } 246 | else 247 | { 248 | msg += string.Format(CultureInfo.CurrentCulture, "Shader \"{0}\" could not be compiled to SPIR-V!", shaderFile.fileName) + "\n"; 249 | Debug.Write(msg); 250 | ParseErrors(validatorOutput, shaderFile); 251 | OutputWindow.Add(shaderFile.fileName + "\n" + string.Join("\n", validatorOutput)); 252 | success = false; 253 | } 254 | } 255 | 256 | if (success) 257 | { 258 | if (shaderFiles.Count == 1) 259 | { 260 | msg = string.Format(CultureInfo.CurrentCulture, "Shader successfully compiled to \"{0}\"", shaderFiles[0].fileName + ".spv"); 261 | } 262 | else 263 | { 264 | msg = "All shaders successfully compiled to SPIR-V"; 265 | } 266 | VsShellUtilities.ShowMessageBox(ServiceProvider, msg, title, OLEMSGICON.OLEMSGICON_INFO, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); 267 | } 268 | else 269 | { 270 | VsShellUtilities.ShowMessageBox(ServiceProvider, msg, title, OLEMSGICON.OLEMSGICON_CRITICAL, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); 271 | } 272 | 273 | if (ErrorList.ErrorCount() > 0) 274 | { 275 | ErrorList.Show(); 276 | } 277 | } 278 | 279 | /// 280 | /// Returns the human readble SPIR-V representation of the shader 281 | /// 282 | public bool GetReadableSPIRV(ShaderFile shaderFile, out List spirvOutput) 283 | { 284 | List output = new List(); 285 | spirvOutput = output; 286 | string title = name; 287 | string msg; 288 | 289 | if (GlslangCompiler.Locate(package as SPIRVExtensionPackage) == null) 290 | { 291 | msg = "Could not locate the glslang reference compiler (glslangvalidator.exe) in system path!"; 292 | VsShellUtilities.ShowMessageBox(ServiceProvider, msg, title, OLEMSGICON.OLEMSGICON_CRITICAL, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); 293 | OutputWindow.Add(msg); 294 | return false; 295 | } 296 | 297 | List validatorOutput; 298 | bool res = GlslangCompiler.GetHumanReadableSPIRV(shaderFile.fileName, out validatorOutput, package as SPIRVExtensionPackage); 299 | if (res) 300 | { 301 | spirvOutput = validatorOutput; 302 | } 303 | else 304 | { 305 | msg = string.Format(CultureInfo.CurrentCulture, "Could not get human readable SPIR-V for shader \"{0}\" ", shaderFile.fileName) + "\n"; 306 | Debug.Write(msg); 307 | VsShellUtilities.ShowMessageBox(ServiceProvider, msg, title, OLEMSGICON.OLEMSGICON_CRITICAL, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); 308 | ParseErrors(validatorOutput, shaderFile); 309 | msg += string.Join("\n", validatorOutput); 310 | OutputWindow.Add(msg); 311 | } 312 | 313 | return res; 314 | } 315 | } 316 | } 317 | -------------------------------------------------------------------------------- /SPIRV-VSExtension/SPIRV-VSExtension.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15.0 6 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 7 | 8 | 9 | true 10 | 11 | 12 | 13 | 14 | 15 | 14.0 16 | false 17 | publish\ 18 | true 19 | Disk 20 | false 21 | Foreground 22 | 7 23 | Days 24 | false 25 | false 26 | true 27 | 0 28 | 1.0.0.%2a 29 | false 30 | false 31 | true 32 | 33 | 34 | true 35 | 36 | 37 | Key.snk 38 | 39 | 40 | 41 | Debug 42 | AnyCPU 43 | 2.0 44 | {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 45 | {914B9574-655F-435E-9928-FE245DABB221} 46 | Library 47 | Properties 48 | SPIRVExtension 49 | SPIRVExtension 50 | v4.5 51 | true 52 | true 53 | true 54 | true 55 | true 56 | true 57 | 58 | 59 | true 60 | full 61 | false 62 | bin\Debug\ 63 | DEBUG;TRACE 64 | prompt 65 | 4 66 | True 67 | 68 | 69 | pdbonly 70 | true 71 | bin\Release\ 72 | TRACE 73 | prompt 74 | 4 75 | True 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | Component 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | Always 99 | true 100 | 101 | 102 | 103 | Designer 104 | 105 | 106 | 107 | 108 | Menus.ctmenu 109 | 110 | 111 | 112 | 113 | 114 | 115 | False 116 | 117 | 118 | False 119 | 120 | 121 | False 122 | 123 | 124 | False 125 | 126 | 127 | 128 | 129 | False 130 | 131 | 132 | ..\packages\Microsoft.VisualStudio.Imaging.14.3.25407\lib\net45\Microsoft.VisualStudio.Imaging.dll 133 | True 134 | 135 | 136 | ..\packages\Microsoft.VisualStudio.OLE.Interop.7.10.6070\lib\Microsoft.VisualStudio.OLE.Interop.dll 137 | True 138 | 139 | 140 | ..\packages\Microsoft.VisualStudio.Shell.14.0.14.3.25407\lib\Microsoft.VisualStudio.Shell.14.0.dll 141 | True 142 | 143 | 144 | ..\packages\Microsoft.VisualStudio.Shell.Immutable.10.0.10.0.30319\lib\net40\Microsoft.VisualStudio.Shell.Immutable.10.0.dll 145 | True 146 | 147 | 148 | ..\packages\Microsoft.VisualStudio.Shell.Immutable.11.0.11.0.50727\lib\net45\Microsoft.VisualStudio.Shell.Immutable.11.0.dll 149 | True 150 | 151 | 152 | ..\packages\Microsoft.VisualStudio.Shell.Immutable.12.0.12.0.21003\lib\net45\Microsoft.VisualStudio.Shell.Immutable.12.0.dll 153 | True 154 | 155 | 156 | ..\packages\Microsoft.VisualStudio.Shell.Immutable.14.0.14.3.25407\lib\net45\Microsoft.VisualStudio.Shell.Immutable.14.0.dll 157 | True 158 | 159 | 160 | ..\packages\Microsoft.VisualStudio.Shell.Interop.7.10.6071\lib\Microsoft.VisualStudio.Shell.Interop.dll 161 | True 162 | 163 | 164 | True 165 | ..\packages\Microsoft.VisualStudio.Shell.Interop.10.0.10.0.30319\lib\Microsoft.VisualStudio.Shell.Interop.10.0.dll 166 | True 167 | 168 | 169 | True 170 | ..\packages\Microsoft.VisualStudio.Shell.Interop.11.0.11.0.61030\lib\Microsoft.VisualStudio.Shell.Interop.11.0.dll 171 | True 172 | 173 | 174 | True 175 | ..\packages\Microsoft.VisualStudio.Shell.Interop.12.0.12.0.30110\lib\Microsoft.VisualStudio.Shell.Interop.12.0.dll 176 | True 177 | 178 | 179 | ..\packages\Microsoft.VisualStudio.Shell.Interop.8.0.8.0.50727\lib\Microsoft.VisualStudio.Shell.Interop.8.0.dll 180 | True 181 | 182 | 183 | ..\packages\Microsoft.VisualStudio.Shell.Interop.9.0.9.0.30729\lib\Microsoft.VisualStudio.Shell.Interop.9.0.dll 184 | True 185 | 186 | 187 | ..\packages\Microsoft.VisualStudio.TextManager.Interop.7.10.6070\lib\Microsoft.VisualStudio.TextManager.Interop.dll 188 | True 189 | 190 | 191 | ..\packages\Microsoft.VisualStudio.TextManager.Interop.8.0.8.0.50727\lib\Microsoft.VisualStudio.TextManager.Interop.8.0.dll 192 | True 193 | 194 | 195 | ..\packages\Microsoft.VisualStudio.Threading.14.1.111\lib\net45\Microsoft.VisualStudio.Threading.dll 196 | True 197 | 198 | 199 | ..\packages\Microsoft.VisualStudio.Utilities.14.3.25407\lib\net45\Microsoft.VisualStudio.Utilities.dll 200 | True 201 | 202 | 203 | ..\packages\Microsoft.VisualStudio.Validation.14.1.111\lib\net45\Microsoft.VisualStudio.Validation.dll 204 | True 205 | 206 | 207 | False 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | true 219 | VSPackage 220 | Designer 221 | 222 | 223 | 224 | 225 | False 226 | .NET Framework 3.5 SP1 227 | false 228 | 229 | 230 | 231 | 232 | 233 | 234 | Dieses Projekt verweist auf mindestens ein NuGet-Paket, das auf diesem Computer fehlt. Verwenden Sie die Wiederherstellung von NuGet-Paketen, um die fehlenden Dateien herunterzuladen. Weitere Informationen finden Sie unter "http://go.microsoft.com/fwlink/?LinkID=322105". Die fehlende Datei ist "{0}". 235 | 236 | 237 | 238 | 239 | 240 | 247 | --------------------------------------------------------------------------------