XNA着色器编译器在发布模式下出错

我很难搞清楚如果我做错了什么,或者如果Visual Studio有一个错误。

我想通过一个浮动到我的像素着色器,把它夹到一个值,然后返回它作为颜色的一部分。 这是我的着色器代码:

float test; float4 PixelShaderFunction(float2 texCoords:TEXCOORD0) : COLOR0 { float n = clamp(test, 0, 1); float4 color = float4(n, n, n, 1); return color; } technique Technique1 { pass Pass1 { PixelShader = compile ps_2_0 PixelShaderFunction(); } } 

以下是我如何使用着色器:

  protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); simpleEffect.Parameters["test"].SetValue(-1f); spriteBatch.Begin(SpriteSortMode.Immediate, null, null, null, null, simpleEffect); spriteBatch.Draw(pixelTexture, new Rectangle(10, 10, 100, 100), Color.Red); spriteBatch.End(); base.Draw(gameTime); } 

当Visual Studio设置为Debug模式时,着色器编译正常,但是当我将它设置为Release时,它给了我下面的错误(请原谅ShaderModel3Bug解决scheme名称…我同样的着色器模型2和3出现错误) :

 Error 1 Errors compiling E:\_C#\ShaderModel3Bug\ShaderModel3Bug\ShaderModel3BugContent\simple.fx: (15,23): ID3DXEffectCompiler::CompileEffect: There was an error compiling expression ID3DXEffectCompiler: Compilation failed E:\_C#\ShaderModel3Bug\ShaderModel3Bug\ShaderModel3BugContent\simple.fx 15 23 ShaderModel3Bug 

着色器的第15行是这样的:

 PixelShader = compile ps_2_0 PixelShaderFunction(); 

我已经尝试直接使用2010年6月DirectX SDK附带的fxc.exe编译着色器。 使用命令fxc.exe /T fx_2_0 E:\_C#\ShaderModel3Bug\ShaderModel3Bug\ShaderModel3BugContent\simple.fx /Fc:output.fxc ,我得到:

 Microsoft (R) Direct3D Shader Compiler 9.29.952.3111 Copyright (C) Microsoft Corporation 2002-2009. All rights reserved. compilation succeeded; see C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Utilities\bin\x64\output.fxc 

所以我的问题是,为什么Visual Studio不能在Release模式下编译.fx文件? 我在做什么,我不应该做的?

更新

显然,XNA Game Studio不使用最新版本的fxc。 我下载了2009年3月份的DirectX SDK,编译失败,出现与Visual Studio一样的通用错误消息:

 C:\Program Files (x86)\Microsoft DirectX SDK (March 2009)\Utilities\bin\x64\ps.fx(16,23): ID3DXEffectCompiler::CompileEffect: There was an error compiling expression ID3DXEffectCompiler: Compilation failed compilation failed; no code produced 

如果我用/ Op(禁用preshaders)标志运行fxc.exe的2009年3月版本,它会编译成功…我仍然不确定fxc xna使用的是什么版本,或者我需要做什么才能使着色器在发行模式下编译。 任何帮助,将不胜感激。

这看起来像着色器编译器中的一个错误。 XNA(如你所注意到的)使用旧版本的编译器。 已知有错误。

从外观上来看,编译器试图将clamp提升到预处理器,并失败。

可能这里最好的解决scheme是手动提升它(这是XNA的内置效果)。 这样做的标准API是覆盖Effect.OnApply 。 虽然这不是微不足道的,因为内容管道通常会给你一个Effect ,除非你乱搞管道扩展。 制作你自己的封装类可以很简单。

我推荐这个博客文章的一些更多的细节。

使用像素着色器而不使用顶点着色器是否合法? 也许这是为了在XNA中工作,但是它会响起我的警钟,所以你可能会尝试添加一个顶点着色器(它大概只是通过位置和texcoords从input到输出寄存器)。

我再次遇到这个问题,并且无法以在发布模式下成功编译的方式修改着色器代码。

基本的问题是XNA使用的着色器编译器尝试在内容以释放模式构建时生成“预处理器”,并且失败。 我find的解决方法是使用自定义内容处理器,并始终将EffectProcessor对象设置为使用debugging模式。

我在MSDN上关于创建自定义导入程序和处理程序的示例,直到“实现写入程序”部分之前。 (创建CompiledPS类也是不必要的)。

我不得不对PSProcessor做一些改变。 以下是它的样子:

 [ContentProcessor(DisplayName = "Custom FX Processor")] public class PSProcessor : ContentProcessor<PSSourceCode, CompiledEffectContent> { public override CompiledEffectContent Process(PSSourceCode input, ContentProcessorContext context) { EffectContent content = new EffectContent(); content.EffectCode = input.code; EffectProcessor compiler = new EffectProcessor(); compiler.DebugMode = EffectProcessorDebugMode.Debug; CompiledEffectContent compiledEffect = compiler.Process(content, context); return compiledEffect; } } 

解决方法是compiler.DebugMode = EffectProcessorDebugMode.Debug 。 一旦设置完成,着色器编译器将停止尝试在发布模式下生成预处理器。

此外,而不是像样本中返回CompiledPS ,我只是返回CompiledEffectContent 。 我花了一些试验才意识到我应该这样做,因为MSDN文章中有一个非常误导性的注释(它说返回Effect )。

由于此解决方法禁用着色器编译器的“优化”,所以每个人都不能接受(幸运的是我只是在关卡的开始阶段生成过程纹理)。 所以,我会留下当前答案的标记。