DX9中如何模拟DX10/11里的ConstantBuffer

今天,我的引擎的DX9 RenderApi插件终于可以跑起来了。虽然问题还很多。不过总算看到图像了。立碑纪念一下。

一开始基于DX10的API来构造整个渲染系统的。DX10的API带来很多新的概念设计。比如Constant Buffer的概念,能统一Shader Constant的管理,当然在DX10/DX11里能有效的提高参数传递的效率。

比如:我做了个TransformBuffer。这个Buffer绑定掉了所有的Matrix上。当Camera变化,或者Matrix变化得时候,我只需要加个标记。下次使用这个Buffer的时候,我检查这个Dirty标记。如果Dirty了。那就下载数据到GPU Constant Buffer中。这样的好处就不会所有的Shader都需要download一遍相同的数据到GPU中了。严重节省了GPU-CPU数据交换的时间。

 

但是杯具的是,DX9中没这个东西。

不过虽然没有。我至少在行为上可以模拟的像一点。顶多不需要那严重节省下来的时间而已。

 

DX9的ConstantTable里。可以检查一个Constant是不是Struct。 如果是一个Struct,那么它的数据都是连续的。我们可以用Struct来模拟Constant Buffer。

比如:

struct cTransformBuffer
{
      matrix matWorld;
      matrix matView;
      matrix matProject;
      float4 cameraUp;
      float4 cameraPos;
      float4 cameraDir;
      float4 cameraArg;//[Near , Far , Fov , Aspect]
};
cTransformBuffer TransformBuffer;

 

我就有了一个名字为TransformBuffer的Struct。而且这个Struct的大小,和总的D3DXHANDLE在ConstantTable里是都可以拿的到得。

在我们需要数据的时候,用pConstantTable->SetValue()函数,把整块数据扔给ShaderConstantTable就Ok了。

 

虽然这样没有节省任何CPU-GPU时间。不过代码变的真是干净彻底啊。

 

 

PS: 同理把渲染状态进行管理。按照DX11/DX10的分类。然后成组的设置。管理渲染状态也变得更加方便了。

代码如下,自带渲染状态重复判断。不会多设置一个不需要设置的多余的渲染状态。

 

void xD3D9ZStencilState::Install(xD3D9ZStencilState* pOldStencil)
{
    IDirect3DDevice9* pDevice = m_pD3D9RenderApi->getDevice();
    if(pOldStencil)
    {
        GUID_VALUE(m_Stencil.m_Enable   ) pDevice->SetRenderState(D3DRS_STENCILENABLE    , m_Stencil.m_Enable   );
        GUID_VALUE(m_Stencil.m_Ref      ) pDevice->SetRenderState(D3DRS_STENCILREF       , m_Stencil.m_Ref      );
        GUID_VALUE(m_Stencil.m_Mask     ) pDevice->SetRenderState(D3DRS_STENCILMASK      , m_Stencil.m_Mask     );
        GUID_VALUE(m_Stencil.m_WriteMask) pDevice->SetRenderState(D3DRS_STENCILWRITEMASK , m_Stencil.m_WriteMask);
       
        GUID_VALUE(m_Stencil.m_OpCW.m_Fail )  pDevice->SetRenderState(D3DRS_STENCILFAIL  , m_Stencil.m_OpCW.m_Fail );
        GUID_VALUE(m_Stencil.m_OpCW.m_zFail)  pDevice->SetRenderState(D3DRS_STENCILZFAIL , m_Stencil.m_OpCW.m_zFail);
        GUID_VALUE(m_Stencil.m_OpCW.m_Pass )  pDevice->SetRenderState(D3DRS_STENCILPASS  , m_Stencil.m_OpCW.m_Pass );
        GUID_VALUE(m_Stencil.m_OpCW.m_Func )  pDevice->SetRenderState(D3DRS_STENCILFUNC  , m_Stencil.m_OpCW.m_Func );

        GUID_VALUE(m_Stencil.m_OpCCW.m_Fail )  pDevice->SetRenderState(D3DRS_CCW_STENCILFAIL  , m_Stencil.m_OpCCW.m_Fail );
        GUID_VALUE(m_Stencil.m_OpCCW.m_zFail)  pDevice->SetRenderState(D3DRS_CCW_STENCILZFAIL , m_Stencil.m_OpCCW.m_zFail);
        GUID_VALUE(m_Stencil.m_OpCCW.m_Pass )  pDevice->SetRenderState(D3DRS_CCW_STENCILPASS  , m_Stencil.m_OpCCW.m_Pass );
        GUID_VALUE(m_Stencil.m_OpCCW.m_Func )  pDevice->SetRenderState(D3DRS_CCW_STENCILFUNC  , m_Stencil.m_OpCCW.m_Func );
    }
    else
    {
        pDevice->SetRenderState(D3DRS_STENCILENABLE    , m_Stencil.m_Enable   );
        pDevice->SetRenderState(D3DRS_STENCILREF       , m_Stencil.m_Ref      );
        pDevice->SetRenderState(D3DRS_STENCILMASK      , m_Stencil.m_Mask     );
        pDevice->SetRenderState(D3DRS_STENCILWRITEMASK , m_Stencil.m_WriteMask);

        pDevice->SetRenderState(D3DRS_STENCILFAIL      , m_Stencil.m_OpCW.m_Fail );
        pDevice->SetRenderState(D3DRS_STENCILZFAIL     , m_Stencil.m_OpCW.m_zFail);
        pDevice->SetRenderState(D3DRS_STENCILPASS      , m_Stencil.m_OpCW.m_Pass );
        pDevice->SetRenderState(D3DRS_STENCILFUNC      , m_Stencil.m_OpCW.m_Func );

        pDevice->SetRenderState(D3DRS_CCW_STENCILFAIL  , m_Stencil.m_OpCCW.m_Fail );
        pDevice->SetRenderState(D3DRS_CCW_STENCILZFAIL , m_Stencil.m_OpCCW.m_zFail);
        pDevice->SetRenderState(D3DRS_CCW_STENCILPASS  , m_Stencil.m_OpCCW.m_Pass );
        pDevice->SetRenderState(D3DRS_CCW_STENCILFUNC  , m_Stencil.m_OpCCW.m_Func );
    }
}

 

 

 

 

 

你可能感兴趣的:(struct,buffer,download,float,Matrix,shader)