简体   繁体   English

如何在C#项目中使用VS2012的自动HLSL编译?

[英]How can I use VS2012's automatic HLSL compiling in a C# project?

http://blogs.msdn.com/b/chuckw/archive/2012/05/07/hlsl-fxc-and-d3dcompile.aspx http://blogs.msdn.com/b/chuckw/archive/2012/05/07/hlsl-fxc-and-d3dcompile.aspx

The above link states that "Note: This automatic integration only works for C++ projects, not C# projects.". 上面的链接指出“注意:这种自动集成仅适用于C ++项目,而不适用于C#项目。” I'm using SlimDX and surely there's a way to make it so Visual Studio will compile HLSL shaders at build time in C# projects? 我正在使用SlimDX,当然有一种方法可以实现,所以Visual Studio将在C#项目的构建时编译HLSL着色器?

I think you will find this might do it for you. 我想你会发现这可能会为你做到这一点。

You must have the fxc.exe directx compiler in the bin folder, it can be found in the direct x sdk. 你必须在bin文件夹中有fxc.exe directx编译器,它可以在direct x sdk中找到。

This class provides an observable collection that can be used in WPF to show the list of shader profiles. 此类提供了一个可观察的集合,可以在WPF中用于显示着色器配置文件列表。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Collections.ObjectModel;
using System.Threading;
using System.Reflection;

namespace Mars.HLSLEditor
{
    public class ShaderModel {
        public string Key {get; set;}
        public string Name { get; set; }
    }

    public class EffectCompiler
    {
        private static Dictionary<string, string> profiles = new Dictionary<string,string>();

        public static ObservableCollection<shadermodel> Profiles
        {
            get {
                var x = from p in profiles select new ShaderModel { Key = p.Key, Name = p.Value};
                return new ObservableCollection<shadermodel>(x);
            }
        }

        public static ShaderModel ProfileByKey(string key) {
            return new ShaderModel { Key = key, Name = profiles[key] };
        }

        public static int GetProfileIndex(ShaderModel model) {
            return Array.IndexOf(profiles.Keys.ToArray(), model.Key);
        }

        static EffectCompiler() {

            profiles.Add("cs_4_0", "Compute Shader model 4.0");
            profiles.Add("cs_4_1", "Compute Shader model 4.1");
            profiles.Add("cs_5_0", "Compute Shader model 5.0");
            profiles.Add("ds_5_0", "Domain Shader model 5.0");
            profiles.Add("fx_2_0", "Effect model 2.0");
            profiles.Add("fx_4_0", "Effect model 4.0");
            profiles.Add("fx_4_1", "Effect model 4.1");
            profiles.Add("fx_5_0", "Effect model 5.0");

            profiles.Add("gs_4_0", "Geometry Shader model 4.0");
            profiles.Add("gs_4_1", "Geometry Shader model 4.1");
            profiles.Add("gs_5_0", "Geometry Shader model 5.0");

            profiles.Add("hs_5_0", "Hull Shader model 5.0");

            profiles.Add("ps_2_0", "Pixel Shader model 2.0");
            profiles.Add("ps_2_a", "Pixel Shader model 2.0 A");
            profiles.Add("ps_2_b", "Pixel Shader model 2.0 B");
            profiles.Add("ps_2_sw", "Pixel Shader model 2.0 (software)");
            profiles.Add("ps_3_0", "Pixel Shader model 3.0");
            profiles.Add("ps_3_sw", "Pixel Shader model 3.0 (software)");
            profiles.Add("ps_4_0", "Pixel Shader model 4.0");
            profiles.Add("ps_4_0_level_9_0", "Pixel Shader model 4.0 (level 9.0)");
            profiles.Add("ps_4_0_level_9_1", "Pixel Shader model 4.0 (level 9.1)");
            profiles.Add("ps_4_0_level_9_3", "Pixel Shader model 4.0 (level 9.3)");
            profiles.Add("ps_4_1", "Pixel Shader model 4.1");
            profiles.Add("ps_5_0", "Pixel Shader model 5.0");

            profiles.Add("tx_1_0", "Texture Shader model 1.0 (software)");

            profiles.Add("vs_1_1", "Vertex Shader model 1.1");
            profiles.Add("vs_2_0", "Vertex Shader model 2.0");
            profiles.Add("vs_2_a", "Vertex Shader model 2.0 A");
            profiles.Add("vs_2_sw", "Vertex Shader model 2.0 (software)");
            profiles.Add("vs_3_0", "Vertex Shader model 3.0");
            profiles.Add("vs_3_sw", "Vertex Shader model 3.0 (software)");
            profiles.Add("vs_4_0", "Vertex Shader model 4.0");
            profiles.Add("vs_4_0_level_9_0", "Vertex Shader model 4.0 (level 9.0)");
            profiles.Add("vs_4_0_level_9_1", "Vertex Shader model 4.0 (level 9.1)");
            profiles.Add("vs_4_0_level_9_3", "Vertex Shader model 4.0 (level 9.3)");
            profiles.Add("vs_4_1", "Vertex Shader model 4.1");
            profiles.Add("vs_5_0", "Vertex Shader model 5.0");
        }

        static object locker = new object();

        public static bool TryCompile(string code, ShaderModel model, string entrypoint, out string error) {

            lock (locker)
            {
                string id = Thread.CurrentThread.ManagedThreadId.ToString();
                string path = string.Format("{0}\\tmp{1}.fx", Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), id);

                using (FileStream fs = new FileStream(path, FileMode.Create))
                {
                    byte[] data = Encoding.ASCII.GetBytes(code);
                    fs.Write(data, 0, data.Length);
                }

                string fxc = Path.Combine(new Uri(System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase)).AbsolutePath, @"fxc.exe");

                if (!File.Exists(fxc))
                {
                    error = "No effect compiler executable!";
                    return false;
                }

                ProcessStartInfo psi = new ProcessStartInfo(fxc);
                psi.CreateNoWindow = true;
                psi.UseShellExecute = false;
                psi.RedirectStandardError = true;
                psi.Arguments = string.Format("/T {1} /E {2} /Fo\"{0}.obj\" \"{0}\"", path, model.Key, entrypoint);

                error = string.Empty;

                using (Process p = Process.Start(psi))
                {

                    StreamReader sr = p.StandardError;
                    error = sr.ReadToEnd().Replace(path, "Line ");

                    if (!p.WaitForExit(5000))
                    {
                        error = "General failure while compiling (timeout).";
                        return false;
                    }
                }

                if (File.Exists(path))
                    File.Delete(path);

                if (File.Exists(path + ".obj"))
                File.Delete(path + ".obj");

                if (error == string.Empty)
                {
                    return true;
                }

                error = error.Replace("compilation failed; no code produced", "");
                error = error.Trim();

                return false;
            }
        }
    }
}

This code belongs to Mars at: (he really should receive the bounty) http://marscode.blogspot.com.au/2011/04/directx-xna-shader-test-compiler-in-c.html 此代码属于火星 :(他真的应该收到赏金) http://marscode.blogspot.com.au/2011/04/directx-xna-shader-test-compiler-in-c.html

This is another useful resource: 这是另一个有用的资源:

It shows how to use public abstract class ShaderEffect : Effect for C# within the System.Windows.Media.Effects Namespace 它展示了如何在System.Windows.Media.Effects Namespace使用public abstract class ShaderEffect : Effect for C#

http://msdn.microsoft.com/en-us/library/vstudio/system.windows.media.effects.shadereffect(v=vs.100).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1 http://msdn.microsoft.com/en-us/library/vstudio/system.windows.media.effects.shadereffect(v=vs.100).aspx?cs-save-lang=1&cs-lang=csharp#code -snippet-1

He mentions public class EffectCompiler 他提到public class EffectCompiler

http://msdn.microsoft.com/library/windows/desktop/bb232919(v=vs.85).aspx http://msdn.microsoft.com/library/windows/desktop/bb232919(v=vs.85).aspx

Edit: 编辑:

Please include 请包括

using System.IO;

before 之前

using System.Windows.Shapes;

It throws an error, but it will work in this order, with a warning, it still compiles. 它会抛出一个错误,但它会按此顺序工作,并带有警告,它仍会编译。 There is ambiguity using Path with both namespaces. 使用Path和两个名称空间存在歧义。

Please advise if this solves your problem. 请告知是否可以解决您的问题。

There's no easy way to add the Visual C++ MSBuild rules for HLSL to a C# project. 没有简单的方法可以将HLSL的Visual C ++ MSBuild规则添加到C#项目中。 Generally you have to use Custom Build steps or, as was suggested elsewhere on StackOverflow, you can have a C++ project in your solution that just builds the shaders. 通常,您必须使用自定义构建步骤,或者如在StackOverflow上的其他位置所建议的那样,您可以在解决方案中创建一个仅构建着色器的C ++项目。

You can manually add the 3D Assets and Content support to a C# project as was done for the code in Stenning's Direct3D Rendering Cookbook to get the DDS, FBX->CMO, and DGSL shader pipeline support. 您可以手动将3D资产和内容支持添加到C#项目,就像在Stenning的Direct3D渲染手册中为代码所做的那样,以获得DDS,FBX-> CMO和DGSL着色器管道支持。 You can see the projects on GitHub . 你可以在GitHub上看到这些项目。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM