fxc的使用及shader调试技巧

本文详细介绍了如何在Visual Studio 2005中使用fxc编译器编译和调试DirectX Shader。包括在不同配置下如何设置编译选项,如何在编译后的文件中加入调试信息,以及如何使用Pix工具进行shader调试。重点分析了如何处理不同版本的Shader,以及如何在编译时选择合适的Shader模型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



如果当前使用的版本是dx10的fxc,则当前fxc不支持ps_1_x的shader,在编译该类shader时需加上/Gec,fxc会自动的把ps_1_x版本的shader编译成ps_2_x的版本。当然该shader只能在支持shader2的机器上运行。

如果要使用传统版本的fxc即dx9下的fxc,这时要使用/LD,此时就支持ps_1_x到ps_3_x的所有的shader版本。

查看所有的编译选项请参考syntax。

 

下面的介绍简单的分析了如何在VS2005中加入fxc编译支持:

CompiledEffect分析

 

这个例子必须使用VisualStudio中编译后才能执行,直接运行Bin下的CompiledEffect.exe会提示找不到CompiledEffect.fxo文件。CompiledEffect.fxo文件CompiledEffect.fx编译后的文件。在VisualStudio中,右键选择CompiledEffect.fx,弹出菜单中选择属性,“自定义生成步骤”的命令行中,显示的是CompiledEffect.fxo的生成命令:
fxc /Od /Zi /Tfx_2_0 /Fo"$(ProjectDir)$(InputName).fxo" "$(InputPath)"
输出项中显示的是生成的文件名:
$(ProjectDir)$(inputName).fxo

fxc是effect文件的离线编译工具,是一命令行程序。位于“(SDK root)/Utilities/Bin/x86/”中,使用方法和相关编译选项参见SDK文档:DirectX Graphics/Tools/Effect-Compiler Tool。

使用已编译的文件创建ID3DXEffect对象时,是不能设置编译选项的。编译选项必须在使用fxc.exe编译CompiledEffect.fxo文件时,在fxc.exe的参数中设置。对于此程序,有三个生成配置:Debug,Debug Shader,Release,使用的参数是不相同的。
Debug:
fxc /Tfx_2_0 /Fo"$(ProjectDir)$(InputName).fxo" "$(InputPath)"
Release:
fxc /Tfx_2_0 /Fo"$(ProjectDir)$(InputName).fxo" "$(InputPath)"
Debug Shader:
fxc /Od /Zi /Tfx_2_0 /Fo"$(ProjectDir)$(InputName).fxo" "$(InputPath)"

其中选项:
/Od-不使用优化(Disable optimizations)
/Zi-允许调试信息(Enable debugging information)
/Tfx_2_0-Shader模型为Effect fx_2_0。

创建ID3DXEffect对象代码为:
D3DXCreateEffectFromFile( pd3dDevice, str, NULL, NULL, D3DXFX_NOT_CLONEABLE, NULL, &g_pEffect, NULL );
与使用非编译Effect文件时的代码对比:
DWORD dwShaderFlags = D3DXFX_NOT_CLONEABLE;
#ifdef DEBUG_VS
    dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;
#endif
#ifdef DEBUG_PS
    dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT;
#endif
D3DXCreateEffectFromFile( pd3dDevice, str, NULL, NULL, dwShaderFlags, NULL, &g_pEffect9, NULL )

 

 

 

注意:

在该例子中定义了两个sampler但是只使用了第二个,所以只有第二个会被加入到寄存器中,由于前面没有其他使用的sampler所以该sampler会被放入s0中,而在.cpp中指定了第0层texture,这时s0和第0层texutre就产生了默认的对应关系,可以不再显式的指定sampler的texture。

 

可以直接使用字符串来为effect或shader中的变量进行赋值:

    D3DXCOLOR colorMtrlDiffuse( 1.0f, 1.0f, 1.0f, 1.0f );
    D3DXCOLOR colorMtrlAmbient( 0.35f, 0.35f, 0.35f, 0 );
    g_pEffect->SetVector( "g_MaterialAmbientColor", ( D3DXVECTOR4* )&colorMtrlAmbient );
    g_pEffect->SetVector( "g_MaterialDiffuseColor", ( D3DXVECTOR4* )&colorMtrlDiffuse );

 

但是最好使用handle进行赋值,避免了每次赋值都要进行字符串的比较,特别是对变化较频繁的变量:

//获取handle

g_hWorldViewProjection = g_pEffect->GetParameterByName( NULL, "g_mWorldViewProjection" );

 

// Update the effect's variables 为handle赋值
g_pEffect->SetMatrix( g_hWorldViewProjection, &mWorldViewProjection );

 

 

shader调试相关

      调试shader主要使用pix,该工具的使用比较简单直观,复杂的是调试环境的设置。下面分几点进行阐述:

 

1. 要调试一个应用程序的shader,首先要对该应用程序进行编译,生成一个.exe文件。编译时需注意,可以定义:

    //#define DEBUG_VS   // Uncomment this line to debug vertex shaders 
    //#define DEBUG_PS   // Uncomment this line to debug pixel shaders

    使用这两个宏,表示此时编译的.exe文件适合用于调试shader,在发布应用程序时别忘了注释掉这两行。

    调试顶点shader时最好需要设备类型为REF而不是HAL,或者使用HAL和软件顶点处理相结合。

    调试像素shader时最好使用设备类型为REF。

    // Debugging vertex shaders requires either REF or software vertex processing 
    // and debugging pixel shaders requires REF.  
#ifdef DEBUG_VS
    if( pDeviceSettings->d3d9.DeviceType != D3DDEVTYPE_REF )
    {
        pDeviceSettings->d3d9.BehaviorFlags &= ~D3DCREATE_HARDWARE_VERTEXPROCESSING;
        pDeviceSettings->d3d9.BehaviorFlags &= ~D3DCREATE_PUREDEVICE;
        pDeviceSettings->d3d9.BehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
    }
#endif
#ifdef DEBUG_PS
    pDeviceSettings->d3d9.DeviceType = D3DDEVTYPE_REF;
#endif 

    当然上面的对设备类型及顶点处理类型要求也不是必须的,有时会发现,即使不使用REF设备,或软件顶点处理方式,shader也是可以被调试的。但是建议最好还是采用上面的建议,因为硬件设备不同会导致结果不同,采用REF设备,虽然运行会慢,但是它能支持所有的d3d的特性,能首先排除硬件因素。

 

    除了上面提及的对设备类型及顶点处理类型的要求以外,还要在编译shader选项上下功夫,无论是在代码中对shader编译还是使用fxc来编译。

    相关具体代码如下:

    // Define DEBUG_VS and/or DEBUG_PS to debug vertex and/or pixel shaders with the 
    // shader debugger. Debugging vertex shaders requires either REF or software vertex 
    // processing, and debugging pixel shaders requires REF.  The 
    // D3DXSHADER_FORCE_*_SOFTWARE_NOOPT flag improves the debug experience in the 
    // shader debugger.  It enables source level debugging, prevents instruction 
    // reordering, prevents dead code elimination, and forces the compiler to compile 
    // against the next higher available software target, which ensures that the 
    // unoptimized shaders do not exceed the shader model limitations.  Setting these 
    // flags will cause slower rendering since the shaders will be unoptimized and 
    // forced into software.  See the DirectX documentation for more information about 
    // using the shader debugger.
    DWORD dwShaderFlags = D3DXFX_NOT_CLONEABLE;

#if defined( DEBUG ) || defined( _DEBUG )
    // Set the D3DXSHADER_DEBUG flag to embed debug information in the shaders.
    // Setting this flag improves the shader debugging experience, but still allows 
    // the shaders to be optimized and to run exactly the way they will run in 
    // the release configuration of this program.
    dwShaderFlags |= D3DXSHADER_DEBUG;
    #endif

#ifdef DEBUG_VS
        dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;
    #endif
#ifdef DEBUG_PS
        dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT;
    #endif

 

其中dwShaderFlags是编译shader时使用的选项。

由上面代码可看出:

主要是采用了D3DXSHADER_DEBUG使得可以在调试时看到HLSL代码,还有D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT和D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT使得在编译时禁止了优化,使得调试时的代码与原始代码保持一致,易于发现错误。

 

2.上面生成的.exe为数据源为pix建立一个新的调试环境。选择按帧捕捉的模式。并启动调试。按下f12即可捕捉当前帧。关闭调试环境即可得到所有捕捉的帧的数据分析结果。

 

3.选择任何一帧,在detail面板中选择render选项,则会看到当前帧的画面,可以在任何一个感兴趣的像素上单击右键选择调试该像素或顶点shader。

 

4.也可以选择任何一个绘制函数,这时在detail面板中选择mesh选项,则会看到当前要绘制的模型,及所有输入顶点信息PreVS和所有的顶点shader的输出信息PostVS.可以在PostVS中选择任何一个顶点进行调试。

 

5.当切换到detail的debug窗口时,可以以汇编或HLSL的方式进行调试。每运行到一行当前行的变量及寄存器的值都会在最下面的窗口中显示。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值