【问题标题】:C# SharpDX compilefromfile with embedded resourceC# SharpDX compilefromfile 与嵌入式资源
【发布时间】:2018-10-16 17:50:59
【问题描述】:

您好,我现在有一些文件是嵌入式资源,但问题是使用:

CompilationResult result = SharpDX.D3DCompiler.ShaderBytecode.CompileFromFile(
            fileName,
            entryPoint,
            profile,
            shaderFlags,
            include: FileIncludeHandler.Default,
            defines: defines);

放置错误: System.IO.FileNotFoundException: 'Unable to find file'。我发现还有其他从源代码编译的函数:

CompilationResult result = SharpDX.D3DCompiler.ShaderBytecode.Compile(data,profile,shaderFlags);

要从嵌入式资源文件中读取,我使用这个小类:Link 1

用法如下:

string data = ResourceHelper.GetEmbeddedResource(fileName);
CompilationResult result = SharpDX.D3DCompiler.ShaderBytecode.Compile(data,profile,shaderFlags);

但是现在我得到了这个错误:

System.ArgumentNullException: 'Value cannot be null.
Parameter name: entryPoint'

为了检查应用程序是否加载了所有嵌入资源,我使用了这个小方法,它返回所有嵌入资源

string[] zz = Assembly.GetExecutingAssembly().GetManifestResourceNames();
        MessageBox.Show(string.Join("\n", zz));

我在这里缺少什么?

编辑 1:

这是我如何使用它的完整方法:

public static ShaderBytecode CompileShader(string fileName, string entryPoint, string profile, ShaderMacro[] defines = null)
    {
        var shaderFlags = ShaderFlags.None;
        var assembly = Assembly.GetExecutingAssembly();
        using (Stream stream = assembly.GetManifestResourceStream(fileName))
        {
            using (var reader = new StreamReader(stream))
            {
                CompilationResult result = SharpDX.D3DCompiler.ShaderBytecode.Compile(reader.ReadToEnd(),entrypoint,profile,shaderFlags);

                /*CompilationResult result = SharpDX.D3DCompiler.ShaderBytecode.CompileFromFile(
                    fileName,
                    entryPoint,
                    profile,
                    shaderFlags,
                    include: FileIncludeHandler.Default,
                    defines: defines);*/
                return new ShaderBytecode(result);
            }
        }    
    }

实际用法:

string MainName = "my_project";
_shaders["standardVS"] = D3DUtility.CompileShader(MainName+".Shaders.Default.hlsl", "VS", "vs_5_1");
//50 other files...

Image 1

编辑 2:向 Compile 方法添加入口点,但现在它抛出错误:

System.NullReferenceException: 'Object reference not set to an instance of an object.'

在:

return new ShaderBytecode(result);

执行处理程序显示:

Message="C\FileLocation: error X1505: No include handler specified, can't perform a #include. Use D3DX APIs or provide your own include handler.\n"

编辑 3:使用@J。 van Langen 更新了它显示的方法:

System.Exception: 'C:\Users\test\source\repos\myapp\Debug\Resources\DemoScene\unknown(14,10-30): error X1505: No include handler specified, can't perform a #include. Use D3DX APIs or provide your own include handler.'

result.Message = result.Message="error CS0452: The type 'ShaderBytecode' must be a reference type in order to use it as parameter 'T' in the generic type or method 'CompilationResultBase<T>'"

编辑 4:我想我找到了它抛出错误的原因,因为它包含在其中: Pastebin

【问题讨论】:

  • 您的着色器代码似乎不正确。查看我的更新如何捕捉它
  • 在编辑 3 中看到我更新的错误
  • 查看我的编辑 4 我想我找到了它抛出错误的原因
  • 看起来#include 不起作用。我不知道有什么替代方法。

标签: c# sharpdx


【解决方案1】:

您不应该使用CompileFromFile,而只使用Compile,您需要使用Compile(string shaderSource, string entryPoint, string profile, ShaderFlags shaderFlags, ..... 进行重载,其余参数使用默认值。

这是我做过的一个旧项目的一个例子:

static GradientRenderer()
{
    // This may be changed to GetType()   (see 'The new reflection API')
    var assembly = typeof(GradientRenderer).GetTypeInfo().Assembly;

    //string[] resources = assembly.GetManifestResourceNames();

    string code;

    // use the full filename with namespace
    using (var stream = assembly.GetManifestResourceStream("MirageDX11.Renderers.Gradient.Gradient.hlsl"))
    using (var reader = new StreamReader(stream))
        // read the whole content to a string.
        code = reader.ReadToEnd();

    var shaderFlags = ShaderFlags.None;

#if DEBUG
    shaderFlags |= ShaderFlags.Debug;
    shaderFlags |= ShaderFlags.SkipOptimization;
#endif

    // Compile the vertex shader and the pixel shader  "VS" & "PS" => entrypoint
    _vertexShaderByteCode = ShaderBytecode.Compile(code, "VS", "vs_5_0", shaderFlags);
    _pixelShaderByteCode = ShaderBytecode.Compile(code, "PS", "ps_5_0", shaderFlags);
}

这是着色器

struct VertexIn
{
    float3 PosL : POSITION;
    float4 Color : COLOR;
};

struct VertexOut
{
    float4 PosH : SV_POSITION;
    float4 Color: COLOR;
};

VertexOut VS(VertexIn vin)
{
    VertexOut vout;
    vout.PosH = float4(vin.PosL, 1.0f);
    vout.Color = vin.Color;
    return vout;
}

float4 PS(VertexOut pin) : SV_Target
{
    float4 value = pin.Color;
    value.w = 1.0f;
    return value;
}

关于如何捕获着色器错误的更新:

我已修改您的方法以捕获着色器编译错误。它会引发一个带有有用消息的异常。

public static ShaderBytecode CompileShader(string fileName, string entryPoint, string profile, ShaderMacro[] defines = null)
{
    var shaderFlags = ShaderFlags.None;
    var assembly = Assembly.GetExecutingAssembly();
    using (Stream stream = assembly.GetManifestResourceStream(fileName))
    {
        using (var reader = new StreamReader(stream))
        {
            CompilationResult result = SharpDX.D3DCompiler.ShaderBytecode.Compile(reader.ReadToEnd(),entrypoint,profile,shaderFlags);

            // when the Bytecode == null, means that an error has occurred
            if (result.Bytecode == null)
                throw new InvalidOperationException(result.Message);

            // removed old code in comment...

            return new ShaderBytecode(result);
        }
    }    
}

【讨论】:

  • 我添加了我的用法,和你的很相似。
  • @speed258 您的函数接受入口点,但编译函数没有将入口点参数作为参数... SharpDX.D3DCompiler.ShaderBytecode.Compile(reader.ReadToEnd(), &lt;&lt;HERE&gt;&gt;, profile,shaderFlags); 您缺少入口点.. 函数的名称..
猜你喜欢
  • 2011-10-30
  • 1970-01-01
  • 1970-01-01
  • 2016-09-09
  • 2013-11-25
  • 1970-01-01
  • 1970-01-01
  • 2013-12-29
  • 2010-09-07
相关资源
最近更新 更多