OpenGL FS/VS Shader Program Compiling Flow

由于GLSL的跨平台性,所以OpenGL没有编译器,由显卡驱动来完成着色器的编译工作

Compiling flow

flow

programlbe compiling

fixed pipeline

LLVM IR -> MVP Assemble

llvm

Source code

/home/icube/mesa3d/src/gallium/drivers/mvp/mvp_shader_lib

Understanding OpenGL Shader Compiling Flow

GLSL330内置类型分布

  • Vertex Shader

|sys in(in stack)|attr in(13 slot)|attr out(18 slot)|
|:--             |:--             |:--              |
|int gl_VertexID <br>int gl_InstanceID | vec4  gl_Color  <br>vec4  gl_SecondaryColor <br>vec4  gl_Normal <br>vec4  gl_Vertex     <br>vec4  gl_MultiTexCoord0 <br>vec4  gl_MultiTexCoord1 <br>vec4  gl_MultiTexCoord2 <br>vec4  gl_MultiTexCoord3 <br> vec4  gl_MultiTexCoord4 <br>vec4  gl_MultiTexCoord5 <br>vec4  gl_MultiTexCoord6 <br> vec4  gl_MultiTexCoord7 <br>float gl_FogCoord    |vec4  gl_Position <br>vec4  gl_FrontColor <br>vec4  gl_BackColor <br>float gl_FogFragCoord <br>float gl_PointSize <br>int   gl_Layer <br> ... |
对于VS attr in,插槽不做固定分配,按照定义顺序逐一分配,直到插槽上限
![vs out](../../../../_images/2023-06-09_112650.png)
  • Fragment Shader

|sys in(1 slot)|attr in(15 slot)|attr out(10 slot)|
|:--             |:--             |:--              |
| int  gl_SampleID <br> vec2 gl_SamplePosition <br> int  gl_SampleMaskIn | vec4 gl_FragCoord <br> vec4  gl_Color<br>int   gl_PrimitiveID <br>bool  gl_FrontFacing <br> vec2  gl_PointCoord <br> float gl_FogFragCoord <br>int   gl_Layer | float gl_FragDepth <br> vec4  gl_FragColor <br> vec4  gl_FragData[gl_MaxDrawBuffers] ... |
![fs in](../../../../_images/2023-06-09_113308.png)
![fs out](../../../../_images/2023-06-09_113345.png)

下面是shader编译过程中用到的一些自定义库函数,这些函数在shader执行之前帮助完成了相关的数据准备工作。

VS

shader.vs

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;

out vec3 ourColor;

void main()
{
    gl_Position = vec4(aPos, 1.0);
    ourColor = aColor;
}
#define CORE_REG_TID		0xc2600c84
#define CORE_REG_CMD		0xc2600c88
#define CORE_REG_VTX_DONE	0xc2601000
#define IC1000_IO_BASE      0xC2600000

// attribute count + draw_start index + 8 * (attribute stride + addr)
#define ATTRIBUTE_SIZE          ((1 + 1 + 8 * 2) * 4)
// save misc info address /* attributes addr + vs_constant_buffer addr + ps_constant_buffer addr */
#define IC1000_CORE_REGS_GP     (1024*3 + 0x30 + IC1000_IO_BASE)
#define MVP_LM_BASE             0xC2000000

#define ATTR_FORMAT_VEC1	0
#define ATTR_FORMAT_VEC2	1
#define ATTR_FORMAT_VEC3	2
#define ATTR_FORMAT_VEC4	3

extern void vs_main(float* gl_in, float* gl_out, float* gl_const, unsigned int index, unsigned int instance_id);

void calc_in_out(float** gl_in, float** gl_out, unsigned int* vtxIndex, unsigned int *instanceId)
{
    unsigned int lm_base = MVP_LM_BASE;
    unsigned int lm_size = 1024;

    unsigned int tid = *( unsigned int *)(CORE_REG_TID);
    unsigned int cmd = *( unsigned int *)(CORE_REG_CMD);
    unsigned int bid = (cmd >> 28) & 1;
    unsigned int varying_num = 8;
    *gl_in = *gl_out = (float *)(lm_base + (tid * lm_size) + bid * varying_num * 16);
    *vtxIndex = *(unsigned int *)(*gl_in);
    *instanceId = *((unsigned int *)(*gl_in) + 4);
}

void load_attributes(float* gl_in, unsigned int index) 
{
    unsigned int* misc_info = (unsigned int *)(*( unsigned int*)(IC1000_CORE_REGS_GP));
    unsigned int* attr_header = (unsigned int *)(*misc_info);
    unsigned int attr_count = attr_header[0];
    index  = attr_header[1] + index;
    unsigned int attr_stride = 0;
    unsigned int attr_format = ATTR_FORMAT_VEC4;
    unsigned int attr_vbo_base = 0;
    float *attr_data_base; 
    unsigned int i = 0;
    for(i = 0; i < attr_count; i++){
        attr_stride = attr_header[ 2 + i*2] & 0x0000ffff;
        attr_format = (attr_header[ 2 + i*2] >> 16) & 0x0000ffff;
        attr_vbo_base = attr_header[ 2 + i*2 + 1];
        attr_data_base = (float *)(attr_vbo_base + index * attr_stride);
        //here just load (4 * float) bytes for one attribute, compiler/mesa will handle the case that attibute is not fvec4 type
        if (attr_format == ATTR_FORMAT_VEC1){
            *(gl_in + i * 4 + 0) = *( attr_data_base + 0);
            *(gl_in + i * 4 + 1) = 0;
            *(gl_in + i * 4 + 2) = 0;
            *(gl_in + i * 4 + 3) = 1;
        }else if(attr_format == ATTR_FORMAT_VEC2){
            *(gl_in + i * 4 + 0) = *( attr_data_base + 0);
            *(gl_in + i * 4 + 1) = *( attr_data_base + 1);
            *(gl_in + i * 4 + 2) = 0;
            *(gl_in + i * 4 + 3) = 1;
        }else if(attr_format == ATTR_FORMAT_VEC3){
            *(gl_in + i * 4 + 0) = *( attr_data_base + 0);
            *(gl_in + i * 4 + 1) = *( attr_data_base + 1);
            *(gl_in + i * 4 + 2) = *( attr_data_base + 2);
            *(gl_in + i * 4 + 3) = 1;
        }else { // ATTR_FORMAT_VEC4
            *(gl_in + i * 4 + 0) = *( attr_data_base + 0);
            *(gl_in + i * 4 + 1) = *( attr_data_base + 1);
            *(gl_in + i * 4 + 2) = *( attr_data_base + 2);
            *(gl_in + i * 4 + 3) = *( attr_data_base + 3);
        }
    }
}

void wrapper_vs(void)
{
    float *gl_in, *gl_out;
    unsigned int index = 0;
    unsigned int instance_id = 0;
    unsigned int *misc_info = (unsigned int *)(*( unsigned int *)(IC1000_CORE_REGS_GP));
    unsigned int gl_const = *(misc_info + 1);
    calc_in_out(&gl_in, &gl_out, &index, &instance_id);

    load_attributes(gl_in, index);

    vs_main(gl_in, gl_out, (float *)gl_const, index, instance_id);
        
    *(unsigned int *)(CORE_REG_VTX_DONE) = index;
}

FS

shader.fs

#version 330 core
out vec4 FragColor;

in vec3 ourColor;

void main()
{
    FragColor = vec4(ourColor, 1.0f);
}
#define CORE_REG_TID		0xc2600c84
#define CORE_REG_CMD		0xc2600c88
#define CORE_REG_VTX_DONE	0xc2601000
#define MVP_LM_BASE             0xC2000000
#define IC1000_IO_BASE          0xC2600000
// attribute count + draw_start index + 8 * (attribute stride + addr)
#define ATTRIBUTE_SIZE          ((1 + 1 + 8 * 2) * 4)
// save misc info address /* attributes + vs_constant_buffer addr + ps_constant_buffer addr */
#define IC1000_CORE_REGS_GP     (1024*3 + 0x30 + IC1000_IO_BASE)

extern void ps_main(float* gl_in, float* gl_out, float* gl_const);

void calc_in_out(float** gl_in, float** gl_out, unsigned int* vtxIndex)
{
    unsigned int lm_base = MVP_LM_BASE;
    unsigned int lm_size = 1024;

    unsigned int tid = *(volatile unsigned int*)(CORE_REG_TID);
    unsigned int cmd = *(volatile unsigned int*)(CORE_REG_CMD);
    unsigned int bid = (cmd >> 28) & 1;
    unsigned int varying_num = 8;
    *gl_in = *gl_out = (float*)(lm_base + (tid*lm_size) + bid*varying_num*16);
}

void wrapper_ps(void)
{
    float *gl_in, *gl_out;
    unsigned int* misc_info = (unsigned int *)(*( unsigned int*)(IC1000_CORE_REGS_GP));
    unsigned int gl_const = *(misc_info + 2);
    calc_in_out(&gl_in, &gl_out, (void*)0);
    ps_main(gl_in, gl_out, (float*)gl_const);
}

mvp_llvm_create_func() mvp_create_function() create_function() mvp_compile_tgsi_main() mvp_compile_tgsi_shader() mvp_shader_create() mvp_build_shader_variant() mvp_build_shader_variant_low_priority()

Reference