【问题标题】:Shader reflection : variable name?着色器反射:变量名?
【发布时间】:2014-01-12 03:30:03
【问题描述】:

我如何(如果可能的话)从反射中获取着色器中变量/结构成员的名称?

我说的是原始 hlsl 着色器(没有 effet 框架/没有 D3DX,只有原始 directX)。

我正在使用 SharpDX 并了解如何从着色器签名中获取我需要的大部分信息

new SharpDX.D3DCompiler.ShaderReflection(MyShaderByteCode); 

我可以获得我需要的大部分信息,但是虽然我可以检索语义名称(TEXCOORD、POSITION 等),但我无法检索元素的实际名称(没有“名称”属性)。

我是不是走错了路?这甚至可能吗?

struct Vertex
{
    float4 Position : POSITION;
    float2 UVPosition : TEXCOORD;
};

struct Pixel
{
    float4 Position : SV_POSITION;
    float2 UVPosition : TEXCOORD;
};

float4x4 worldViewProj;

Texture2D<float4> diffuse   : register(t0);
Texture2D<float4> height    : register(t1);
Texture2D<float4> lightmap  : register(t2);
SamplerState pictureSampler;

Pixel PerVertex(Vertex input)
{
    Pixel output = (Pixel) 0;
    input.Position.z += height.SampleLevel(pictureSampler, input.UVPosition, 0).r / 2;
    output.Position = mul(input.Position, worldViewProj);
    output.UVPosition = input.UVPosition;
    return output;
}

float4 PerPixel(Pixel input) : SV_Target
{
    return diffuse.Sample(pictureSampler, input.UVPosition) * lightmap.Sample(pictureSampler, input.UVPosition);
}

我能检索的是“POSITION”和“TEXCOORD”,我要检索的是“Position”和“UVPosition”

【问题讨论】:

    标签: directx shader hlsl directx-11 sharpdx


    【解决方案1】:

    您需要遍历常量缓冲区。 请注意,没有使用 Constant Buffer,它将被剥离字节码。

    遍历所有变量的附加代码:

    SharpDX.D3DCompiler.ShaderReflection sr = new SharpDX.D3DCompiler.ShaderReflection(mybytecode);
            for (int i = 0; i < sr.Description.ConstantBuffers; i++)
            {
                SharpDX.D3DCompiler.ConstantBuffer cb = sr.GetConstantBuffer(i);
                for (int j = 0; j < cb.Description.VariableCount; j++)
                {
                    SharpDX.D3DCompiler.ShaderReflectionVariable variable = cb.GetVariable(j);
                    Console.WriteLine(variable.Description.Name);
                }
            }
    

    【讨论】:

    • 对不起,我应该更具体,这仅适用于常量缓冲区,但我试图检索的是结构中作为输入/输出传递的变量的名称。我找到了一种按名称检索变量的方法: new SharpDX.D3DCompiler.ShaderReflection(pixelShaderByteCode).GetVariable 但不是相反的(变量名称列表)。用我想要得到的示例更新我的问题
    • 好吧有道理,那么你有点不走运,我认为没有办法做到这一点(着色器阶段之间的合同是通过语义完成的,而不是通过变量名,所以它是可能编译器会删除该数据)。正如 drop 所说,解析文件可能是唯一的解决方案。
    • 猜猜这是最好的,那仍然很有用,谢谢:)
    【解决方案2】:

    我认为这是不可能的。

    您还可以做的是显式分配语义索引(除了语义名称):

    struct Vertex
    {
        float4 Position   : POSITION0;
        float2 UVPosition : TEXCOORD0;
    };
    

    并使用它们通过读取D3D11_SIGNATURE_PARAMETER_DESCSemanticNameSemanticIndex 字段来唯一标识您在CPU 端的输入。

    想到的另一种方法是直接解析源 HLSL 文件(因此推出您自己的反射引擎)。

    希望对你有帮助!

    【讨论】:

    • 我真的只对友好名称感兴趣(我想将它们公开给引擎用户)。但是我认为我会使用 HLSL 解析。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-09
    • 2019-01-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多