OBS-D3D11渲染梳理
+ -

ShaderProcessor词法分析

2026-02-01 8 0

ShaderProcessor主要实现如下功能:

着色器分析Process

Process 通过输入的着色器代码进行词法分析,分拆分出以下几种类型:

struct shader_parser {
    struct cf_parser cfp;

    DARRAY(struct shader_var) params;
    DARRAY(struct shader_struct) structs;
    DARRAY(struct shader_sampler) samplers;
    DARRAY(struct shader_func) funcs;
};
结构体

结构体由shader_struct表示

enum shader_var_type {
    SHADER_VAR_NONE,
    SHADER_VAR_IN = SHADER_VAR_NONE,
    SHADER_VAR_INOUT,
    SHADER_VAR_OUT,
    SHADER_VAR_UNIFORM,
    SHADER_VAR_CONST
};
struct shader_var {
    char *type;
    char *name;
    char *mapping;
    enum shader_var_type var_type;
    int array_count;
    size_t gl_sampler_id; /* optional: used/parsed by GL */

    DARRAY(uint8_t) default_val;
};
struct shader_struct {
    char *name;
    DARRAY(struct shader_var) vars;
};
采样器状态
struct shader_sampler {
    char *name;
    DARRAY(char *) states;
    DARRAY(char *) values;
};
函数
struct shader_func {
    char *name;
    char *return_type;
    char *mapping;
    DARRAY(struct shader_var) params;

    struct cf_token *start, *end; //函数体开始结束指针
};
参数

参数由shader_var结构本表示(见上)

字符转换

执行完成语义分析之后,需要输出最终的代码给编译器进行编译。由于着色器为了兼容OPENGL和D3D11使用的是通用写法,枚对一些关键词需要替换输出。

void ShaderProcessor::BuildString(string &outputString)
{
    stringstream output;
    output << "static const bool obs_glsl_compile = false;\n\n";

    cf_token *token = cf_preprocessor_get_tokens(&parser.cfp.pp);
    while (token->type != CFTOKEN_NONE) {
        /* cheaply just replace specific tokens */
        if (strref_cmp(&token->str, "POSITION") == 0)
            output << "SV_Position";
        else if (strref_cmp(&token->str, "TARGET") == 0)
            output << "SV_Target";
        else if (strref_cmp(&token->str, "texture2d") == 0)
            output << "Texture2D";
        else if (strref_cmp(&token->str, "texture3d") == 0)
            output << "Texture3D";
        else if (strref_cmp(&token->str, "texture_cube") == 0)
            output << "TextureCube";
        else if (strref_cmp(&token->str, "texture_rect") == 0)
            throw "texture_rect is not supported in D3D";
        else if (strref_cmp(&token->str, "sampler_state") == 0)
            output << "SamplerState";
        else if (strref_cmp(&token->str, "VERTEXID") == 0)
            output << "SV_VertexID";
        else
            output.write(token->str.array, token->str.len);

        token++;
    }

    outputString = move(output.str());
}

如下的代码:

替换前POSITION

struct VertInOut {     
    float4 pos : POSITION; 
}; 

VertInOut main(VertInOut vert_in) { 
    VertInOut vert_out;     
    vert_out.pos = float4(vert_in.pos.xyz, 1.0);     
    return vert_out; 
}

替换后SV_Position

static const bool obs_glsl_compile = false;

struct VertInOut {     
    float4 pos : SV_Position; 
}; 

VertInOut main(VertInOut vert_in) { 
    VertInOut vert_out;     
    vert_out.pos = float4(vert_in.pos.xyz, 1.0); 
    return vert_out; 
}

0 篇笔记 写笔记

作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!