diff options
| author | Ben Vanik <ben.vanik@gmail.com> | 2015-11-26 08:28:01 -0800 |
|---|---|---|
| committer | Ben Vanik <ben.vanik@gmail.com> | 2015-11-28 16:10:26 -0800 |
| commit | eb3b7d0b758e841d3e6654a28efd6db1e58d14ee (patch) | |
| tree | 3f65a36ba3fc8a373330fda6024873bc404aaf04 /tools | |
| parent | 71b9995448161645a1c3ae89256c1e8c55087273 (diff) | |
Adding a tool to interactively assemble/disassemble shaders using XNA.
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/shader-playground/App.config | 5 | ||||
| -rw-r--r-- | tools/shader-playground/Editor.Designer.cs | 116 | ||||
| -rw-r--r-- | tools/shader-playground/Editor.cs | 110 | ||||
| -rw-r--r-- | tools/shader-playground/Editor.resx | 120 | ||||
| -rw-r--r-- | tools/shader-playground/Program.cs | 49 | ||||
| -rw-r--r-- | tools/shader-playground/README.md | 11 | ||||
| -rw-r--r-- | tools/shader-playground/shader-playground.csproj | 68 | ||||
| -rw-r--r-- | tools/shader-playground/shader-playground.sln | 22 |
8 files changed, 501 insertions, 0 deletions
diff --git a/tools/shader-playground/App.config b/tools/shader-playground/App.config new file mode 100644 index 000000000..aef709404 --- /dev/null +++ b/tools/shader-playground/App.config @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<configuration> + <startup> + <supportedRuntime version="v2.0.50727"/></startup> +</configuration> diff --git a/tools/shader-playground/Editor.Designer.cs b/tools/shader-playground/Editor.Designer.cs new file mode 100644 index 000000000..0f369a566 --- /dev/null +++ b/tools/shader-playground/Editor.Designer.cs @@ -0,0 +1,116 @@ +namespace shader_playground { + partial class Editor { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) { + if (disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() { + this.sourceCodeTextBox = new System.Windows.Forms.TextBox(); + this.outputTextBox = new System.Windows.Forms.TextBox(); + this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.wordsTextBox = new System.Windows.Forms.TextBox(); + this.splitContainer1.Panel1.SuspendLayout(); + this.splitContainer1.Panel2.SuspendLayout(); + this.splitContainer1.SuspendLayout(); + this.SuspendLayout(); + // + // sourceCodeTextBox + // + this.sourceCodeTextBox.AcceptsReturn = true; + this.sourceCodeTextBox.AcceptsTab = true; + this.sourceCodeTextBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.sourceCodeTextBox.Location = new System.Drawing.Point(0, 0); + this.sourceCodeTextBox.Multiline = true; + this.sourceCodeTextBox.Name = "sourceCodeTextBox"; + this.sourceCodeTextBox.Size = new System.Drawing.Size(352, 360); + this.sourceCodeTextBox.TabIndex = 0; + // + // outputTextBox + // + this.outputTextBox.AcceptsReturn = true; + this.outputTextBox.AcceptsTab = true; + this.outputTextBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.outputTextBox.Location = new System.Drawing.Point(0, 0); + this.outputTextBox.Multiline = true; + this.outputTextBox.Name = "outputTextBox"; + this.outputTextBox.ReadOnly = true; + this.outputTextBox.Size = new System.Drawing.Size(349, 360); + this.outputTextBox.TabIndex = 1; + // + // splitContainer1 + // + this.splitContainer1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.splitContainer1.Location = new System.Drawing.Point(12, 12); + this.splitContainer1.Name = "splitContainer1"; + // + // splitContainer1.Panel1 + // + this.splitContainer1.Panel1.Controls.Add(this.sourceCodeTextBox); + // + // splitContainer1.Panel2 + // + this.splitContainer1.Panel2.Controls.Add(this.outputTextBox); + this.splitContainer1.Size = new System.Drawing.Size(705, 360); + this.splitContainer1.SplitterDistance = 352; + this.splitContainer1.TabIndex = 2; + // + // wordsTextBox + // + this.wordsTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.wordsTextBox.Location = new System.Drawing.Point(12, 378); + this.wordsTextBox.Multiline = true; + this.wordsTextBox.Name = "wordsTextBox"; + this.wordsTextBox.ReadOnly = true; + this.wordsTextBox.Size = new System.Drawing.Size(705, 251); + this.wordsTextBox.TabIndex = 4; + // + // Editor + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(729, 641); + this.Controls.Add(this.wordsTextBox); + this.Controls.Add(this.splitContainer1); + this.Name = "Editor"; + this.Text = "Shader Playground"; + this.splitContainer1.Panel1.ResumeLayout(false); + this.splitContainer1.Panel1.PerformLayout(); + this.splitContainer1.Panel2.ResumeLayout(false); + this.splitContainer1.Panel2.PerformLayout(); + this.splitContainer1.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox sourceCodeTextBox; + private System.Windows.Forms.TextBox outputTextBox; + private System.Windows.Forms.SplitContainer splitContainer1; + private System.Windows.Forms.TextBox wordsTextBox; + } +} + diff --git a/tools/shader-playground/Editor.cs b/tools/shader-playground/Editor.cs new file mode 100644 index 000000000..81e7b3a5b --- /dev/null +++ b/tools/shader-playground/Editor.cs @@ -0,0 +1,110 @@ +using Microsoft.Xna.Framework.Graphics; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.IO; +using System.Text; +using System.Windows.Forms; + +namespace shader_playground { + public partial class Editor : Form { + public Editor() { + InitializeComponent(); + + wordsTextBox.Click += WordsTextBox_Click; + + sourceCodeTextBox.TextChanged += SourceCodeTextBox_TextChanged; + sourceCodeTextBox.Text = string.Join( + "\r\n", new string[] { + "xps_3_0", + "dcl_texcoord1 r0", + "dcl_color r1.xy", + "exec", + "alloc colors", + "exece", + "mad oC0, r0, r1.y, c0", + "mul r4.xyz, r1.xyz, c0.xyz", + "+ adds r5.w, r0.xy", + "cnop", + }); + } + + private void WordsTextBox_Click(object sender, EventArgs e) { + wordsTextBox.SelectAll(); + wordsTextBox.Copy(); + } + + void SourceCodeTextBox_TextChanged(object sender, EventArgs e) { + Assemble(sourceCodeTextBox.Text); + } + + class NopIncludeHandler : CompilerIncludeHandler { + public override Stream Open(CompilerIncludeHandlerType includeType, + string filename) { + throw new NotImplementedException(); + } + } + + void Assemble(string shaderSourceCode) { + shaderSourceCode += "\ncnop"; + shaderSourceCode += "\ncnop"; + var preprocessorDefines = new CompilerMacro[2]; + preprocessorDefines[0].Name = "XBOX"; + preprocessorDefines[0].Name = "XBOX360"; + var includeHandler = new NopIncludeHandler(); + var options = CompilerOptions.None; + var compiledShader = ShaderCompiler.AssembleFromSource( + shaderSourceCode, preprocessorDefines, includeHandler, options, + Microsoft.Xna.Framework.TargetPlatform.Xbox360); + + DumpWords(compiledShader.GetShaderCode()); + + var disassembledSourceCode = compiledShader.ErrorsAndWarnings; + disassembledSourceCode = disassembledSourceCode.Replace("\n", "\r\n"); + if (disassembledSourceCode.IndexOf("// PDB hint 00000000-00000000-00000000") == -1) { + outputTextBox.Text = disassembledSourceCode; + return; + } + var prefix = disassembledSourceCode.Substring( + 0, disassembledSourceCode.IndexOf(':')); + disassembledSourceCode = + disassembledSourceCode.Replace(prefix + ": warning X7102: ", ""); + disassembledSourceCode = disassembledSourceCode.Replace( + "// PDB hint 00000000-00000000-00000000\r\n", ""); + var firstLine = disassembledSourceCode.IndexOf("//"); + disassembledSourceCode = disassembledSourceCode.Substring(firstLine); + disassembledSourceCode = disassembledSourceCode.Trim(); + outputTextBox.Text = disassembledSourceCode; + } + + void DumpWords(byte[] shaderCode) { + if (shaderCode == null || shaderCode.Length == 0) { + wordsTextBox.Text = ""; + return; + } + + uint[] swappedCode = new uint[shaderCode.Length / sizeof(uint)]; + Buffer.BlockCopy(shaderCode, 0, swappedCode, 0, shaderCode.Length); + for (int i = 0; i < swappedCode.Length; ++i) { + swappedCode[i] = SwapBytes(swappedCode[i]); + } + var sb = new StringBuilder(); + sb.Append("const uint32_t shader_words[] = {"); + for (int i = 0; i < swappedCode.Length; ++i) { + sb.AppendFormat("0x{0:X8}, ", swappedCode[i]); + } + sb.Append("};"); + wordsTextBox.Text = sb.ToString(); + wordsTextBox.SelectAll(); + } + + uint SwapBytes(uint x) { + return ((x & 0x000000ff) << 24) + + ((x & 0x0000ff00) << 8) + + ((x & 0x00ff0000) >> 8) + + ((x & 0xff000000) >> 24); + } + + } +} diff --git a/tools/shader-playground/Editor.resx b/tools/shader-playground/Editor.resx new file mode 100644 index 000000000..d2320fab8 --- /dev/null +++ b/tools/shader-playground/Editor.resx @@ -0,0 +1,120 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> +</root> diff --git a/tools/shader-playground/Program.cs b/tools/shader-playground/Program.cs new file mode 100644 index 000000000..21ee94660 --- /dev/null +++ b/tools/shader-playground/Program.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Windows.Forms; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("shader-playground")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("shader-playground")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("05d27ad4-ef23-4fa1-ad5a-7cfd587fd093")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] + +namespace shader_playground { + static class Program { + [STAThread] + static void Main() { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new Editor()); + } + } +} diff --git a/tools/shader-playground/README.md b/tools/shader-playground/README.md new file mode 100644 index 000000000..1c8fe7e6a --- /dev/null +++ b/tools/shader-playground/README.md @@ -0,0 +1,11 @@ +This requires XNA Game Studio 3.1 to be installed (not just the redist): +http://www.microsoft.com/en-us/download/details.aspx?id=39 + +It's not really compatible with modern VS', but you can open the downloaded +`XNAGS31_setup.exe` with 7zip and run the included `redists.msi` directly. + +If installed correctly you should have this file: +`C:\Program Files (x86)\Microsoft XNA\XNA Game Studio\v3.1\References\Windows\x86\Microsoft.Xna.Framework.dll` + +XNA is only compatible with 32-bit x86 .NET, so ensure Visual Studio is set to +target that (not `Any CPU`). diff --git a/tools/shader-playground/shader-playground.csproj b/tools/shader-playground/shader-playground.csproj new file mode 100644 index 000000000..163aa713a --- /dev/null +++ b/tools/shader-playground/shader-playground.csproj @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{05D27AD4-EF23-4FA1-AD5A-7CFD587FD093}</ProjectGuid> + <OutputType>WinExe</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>shader_playground</RootNamespace> + <AssemblyName>shader-playground</AssemblyName> + <TargetFrameworkVersion>v2.0</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <TargetFrameworkProfile /> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'"> + <DebugSymbols>true</DebugSymbols> + <OutputPath>bin\x86\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <DebugType>full</DebugType> + <PlatformTarget>x86</PlatformTarget> + <ErrorReport>prompt</ErrorReport> + <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> + <Prefer32Bit>true</Prefer32Bit> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'"> + <OutputPath>bin\x86\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <Optimize>true</Optimize> + <DebugType>pdbonly</DebugType> + <PlatformTarget>x86</PlatformTarget> + <ErrorReport>prompt</ErrorReport> + <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> + <Prefer32Bit>true</Prefer32Bit> + </PropertyGroup> + <ItemGroup> + <Reference Include="Microsoft.Xna.Framework, Version=3.1.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d, processorArchitecture=x86" /> + <Reference Include="System" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Windows.Forms" /> + </ItemGroup> + <ItemGroup> + <Compile Include="Editor.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="Editor.Designer.cs"> + <DependentUpon>Editor.cs</DependentUpon> + </Compile> + <Compile Include="Program.cs" /> + <EmbeddedResource Include="Editor.resx"> + <DependentUpon>Editor.cs</DependentUpon> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <None Include="App.config" /> + </ItemGroup> + <ItemGroup> + <Folder Include="Properties\" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project>
\ No newline at end of file diff --git a/tools/shader-playground/shader-playground.sln b/tools/shader-playground/shader-playground.sln new file mode 100644 index 000000000..68c02f975 --- /dev/null +++ b/tools/shader-playground/shader-playground.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.23107.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "shader-playground", "shader-playground.csproj", "{05D27AD4-EF23-4FA1-AD5A-7CFD587FD093}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {05D27AD4-EF23-4FA1-AD5A-7CFD587FD093}.Debug|x86.ActiveCfg = Debug|x86 + {05D27AD4-EF23-4FA1-AD5A-7CFD587FD093}.Debug|x86.Build.0 = Debug|x86 + {05D27AD4-EF23-4FA1-AD5A-7CFD587FD093}.Release|x86.ActiveCfg = Release|x86 + {05D27AD4-EF23-4FA1-AD5A-7CFD587FD093}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal |
