OBS-Direct11数据结构
+ -

D3D11渲染流程笔记

2024-07-29 25 0

顶点

ID3D11DeviceContext::VSSetShader - 设置顶点着色器
ID3D11DeviceContext::IASetInputLayout - 设置顶点着色器的参数布局
ID3D11DeviceContext::VSSetConstantBuffers - 设置顶点着色器常量空间

    device->context->VSSetShader(shader, NULL, 0);
    device->context->IASetInputLayout(layout);
    device->context->VSSetConstantBuffers(0, 1, &constants);//slot,NumBuffers,ID3D11Buffer**

像素

ID3D11DeviceContext::PSSetShader 设置像素着色器
ID3D11DeviceContext::PSSetConstantBuffers 设置像素着器常量空间
ID3D11DeviceContext::PSSetSamplers 设置采样状态

    device->context->PSSetShader(shader, NULL, 0);
    device->context->PSSetConstantBuffers(0, 1, &constants);
    device->context->PSSetSamplers(0, GS_MAX_TEXTURES, states);//slot,数组中的采样器数,采样器

常量空间

常量空间是一片内存,包括所有参数的空间。故常量空间一般只创建一个。而在常量空间内部,各个参数根据其偏移位置对号入座。

void gs_shader::BuildConstantBuffer()
{
//计数常量空间的总大小
    for (size_t i = 0; i < params.size(); i++) {
        gs_shader_param &param = params[i];
        size_t size = 0;

        switch (param.type) {
        case GS_SHADER_PARAM_BOOL:
        case GS_SHADER_PARAM_INT:
        case GS_SHADER_PARAM_FLOAT:
            size = sizeof(float);
            break;
        case GS_SHADER_PARAM_INT2:
        case GS_SHADER_PARAM_VEC2:
            size = sizeof(vec2);
            break;
        case GS_SHADER_PARAM_INT3:
        case GS_SHADER_PARAM_VEC3:
            size = sizeof(float) * 3;
            break;
        case GS_SHADER_PARAM_INT4:
        case GS_SHADER_PARAM_VEC4:
            size = sizeof(vec4);
            break;
        case GS_SHADER_PARAM_MATRIX4X4:
            size = sizeof(float) * 4 * 4;
            break;
        case GS_SHADER_PARAM_TEXTURE:
        case GS_SHADER_PARAM_STRING:
        case GS_SHADER_PARAM_UNKNOWN:
            continue;
        }

        //数组个数
        if (param.arrayCount)
            size *= param.arrayCount;

        /* checks to see if this constant needs to start at a new register 
        //常量总大小没有16字节对齐时
        if (size && (constantSize & 15) != 0) 
        {
            size_t alignMax = (constantSize + 15) & ~15;  //常量总大小16字节对齐后

            //如果超过了,最最大值
            if ((size + constantSize) > alignMax)
                constantSize = alignMax;
        }

        param.pos = constantSize;//参数在常量空间的位置,都是16字节对齐的
        constantSize += size;    //总的常量空间大小
    }

    memset(&bd, 0, sizeof(bd));

    if (constantSize) 
    {
        HRESULT hr;
        bd.ByteWidth = (constantSize + 15) & 0xFFFFFFF0; /* align */
        bd.Usage = D3D11_USAGE_DYNAMIC;
        bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
        bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;

        //创建常量空间
        hr = device->device->CreateBuffer(&bd, NULL, constants.Assign());
        if (FAILED(hr))
            throw HRError("Failed to create constant buffer", hr);
    }

    for (size_t i = 0; i < params.size(); i++)
        gs_shader_set_default(&params[i]); 
}

(gs_effect_set_vec4)-> effect buffer->(gs_shader_set_val) -> gs buffer ->(gs_shader::UpdateParams

- gs_vertexbuffer_flush
)->常量空间

OBS的着色器全局参数空间的设置如上文所述,设置比较曲折。
在解析后创建的着色器有两种结构,分别为解析后的空间和着色器空间。实些其实都在CPU内部,最终由于着色器常量空间是一片连续的内存,故使用gs_shader::UpdateParam构造一块相同大小的内存空间,使用着色器参数填充其空间内容,然后再整体拷贝到着色器内存空间。

渲染流程

  • gs_effect_set_vec4(color, colorVal); //参数到effect buffer
  • gs_technique_begin_pass
    • gs_load_vertexshader
      • ID3D11DeviceContext::VSSetShader - 设置顶点着色器
      • ID3D11DeviceContext::IASetInputLayout - 设置顶点着色器的参数布局
      • ID3D11DeviceContext::VSSetConstantBuffers - 设置顶点着色器常量空间
    • gs_load_pixelshader
      • ID3D11DeviceContext::PSSetShader 设置像素着色器
      • ID3D11DeviceContext::PSSetConstantBuffers 设置像素着器常量空间
      • ID3D11DeviceContext::PSSetSamplers 设置采样状态
    • upload_parameters(tech->effect, false)
      • upload_shader_params(vshader_params, changed_only);
        • gs_shader_set_val()// effect buffer -> gs buffer
      • upload_shader_params(pshader_params, changed_only);
        • gs_shader_set_val
  • gs_draw_sprite(0, 0, context->width, context->height)
    • gs_vertexbuffer_flush(graphics->sprite_buffer); //map unmap更新显卡内部顶点数据
    • gs_load_vertexbuffer(graphics->sprite_buffer); //设置curVertexBuffer为graphics->sprite_buffer
    • gs_load_indexbuffer(NULL); //顶点索引没有用
    • gs_draw(GS_TRISTRIP, 0, 0)
      • device->FlushOutputViews();//设置OMSetRenderTargets
      • gs_effect_update_params(effect)
        • upload_parameters(effect, true)
      • device->LoadVertexBufferData(); //IASetVertexBuffers
      • device->UpdateBlendState(); //OMSetBlendState
      • device->UpdateRasterState(); //光栅化配置
      • device->UpdateZStencilState(); //OMSetDepthStencilState
      • device->UpdateViewProjMatrix();
      • device->curVertexShader->UploadParams();//更新顶点着色器参数到着色器常量空间
      • device->curPixelShader->UploadParams(); //更新像系着色器参数到着色器常量空间
      • device->context->Draw(num_verts, start_vert); //最终绘制D3D11DeviceContext::Draw

0 篇笔记 写笔记

作者信息
站长漫谈
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

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

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