Directx9代码在AMD显卡上运行良好,但在Nvidia硬件上失败

时间:2015-01-17 01:03:04

标签: c++ post processing amd-processor direct3d9

所以我为一些旧的开源游戏写了一篇Post Processing课程,

我有一个开始场景功能,一个结束场景功能,一个渲染功能和一个用于创建屏幕小队和资源的功能。

bool CPostProcessingChain::BeginScene()
{
    if (!m_lpSourceTexture || !m_lpLastPass || !m_lpTarget || !m_lpDepthStencilSurface)
    {
        if (!CreateResources())
        {
            return false;
        }
    }

    STATEMANAGER.GetDevice()->GetRenderTarget(0, &m_lpBackupTargetSurface);
    STATEMANAGER.GetDevice()->SetRenderTarget(0, m_lpSourceTextureSurface);
    STATEMANAGER.GetDevice()->GetDepthStencilSurface(&m_lpDepthStencilBackup);
    STATEMANAGER.GetDevice()->SetDepthStencilSurface(m_lpDepthStencilSurface);

    return true;
}


bool CPostProcessingChain::EndScene()
{
    STATEMANAGER.GetDevice()->SetRenderTarget(0, m_lpBackupTargetSurface);
    STATEMANAGER.GetDevice()->SetDepthStencilSurface(m_lpDepthStencilBackup);
    m_lpDepthStencilBackup->Release();
    m_lpDepthStencilBackup = nullptr;
    m_lpBackupTargetSurface->Release();
    m_lpBackupTargetSurface = nullptr;

    D3DXMATRIX mWorld, mView, mProj, mIdentity;
    D3DXMatrixIdentity(&mIdentity);
    STATEMANAGER.GetDevice()->GetTransform(D3DTS_WORLD, &mWorld);
    STATEMANAGER.GetDevice()->GetTransform(D3DTS_VIEW, &mView);
    STATEMANAGER.GetDevice()->GetTransform(D3DTS_PROJECTION, &mProj);
    STATEMANAGER.GetDevice()->SetTransform(D3DTS_WORLD, &mIdentity);
    STATEMANAGER.GetDevice()->SetTransform(D3DTS_VIEW, &mIdentity);
    STATEMANAGER.GetDevice()->SetTransform(D3DTS_PROJECTION, &mIdentity);
    STATEMANAGER.SaveRenderState(D3DRS_ZENABLE, FALSE);
    STATEMANAGER.SaveRenderState(D3DRS_MULTISAMPLEANTIALIAS, FALSE);

    STATEMANAGER.GetDevice()->Clear(0, nullptr, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0.0f);
    STATEMANAGER.GetDevice()->SetTexture(0, m_lpTarget);
    STATEMANAGER.GetDevice()->SetPixelShader(nullptr);
    STATEMANAGER.GetDevice()->SetVertexShader(nullptr);
    STATEMANAGER.GetDevice()->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
    STATEMANAGER.GetDevice()->SetStreamSource(0, m_lpScreenQuad, 0, sizeof(TRTTVertex));
    STATEMANAGER.GetDevice()->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);

    STATEMANAGER.RestoreRenderState(D3DRS_MULTISAMPLEANTIALIAS);
    STATEMANAGER.RestoreRenderState(D3DRS_ZENABLE);
    STATEMANAGER.GetDevice()->SetTransform(D3DTS_WORLD, &mWorld);
    STATEMANAGER.GetDevice()->SetTransform(D3DTS_VIEW, &mView);
    STATEMANAGER.GetDevice()->SetTransform(D3DTS_PROJECTION, &mProj);

    return true;
}



bool CPostProcessingChain::Render()
{
    D3DXMATRIX mWorld, mView, mProj, mIdentity;
    D3DXMatrixIdentity(&mIdentity);
    STATEMANAGER.GetDevice()->GetTransform(D3DTS_WORLD, &mWorld);
    STATEMANAGER.GetDevice()->GetTransform(D3DTS_VIEW, &mView);
    STATEMANAGER.GetDevice()->GetTransform(D3DTS_PROJECTION, &mProj);
    STATEMANAGER.GetDevice()->SetTransform(D3DTS_WORLD, &mIdentity);
    STATEMANAGER.GetDevice()->SetTransform(D3DTS_VIEW, &mIdentity);
    STATEMANAGER.GetDevice()->SetTransform(D3DTS_PROJECTION, &mIdentity);
    STATEMANAGER.GetDevice()->SetRenderTarget(0, m_lpLastPassSurface);
    STATEMANAGER.SaveRenderState(D3DRS_ZENABLE, FALSE);
    STATEMANAGER.SaveRenderState(D3DRS_MULTISAMPLEANTIALIAS, FALSE);

    STATEMANAGER.GetDevice()->Clear(0, nullptr, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0.0f);
    STATEMANAGER.GetDevice()->SetTexture(0, m_lpSourceTexture);
    STATEMANAGER.GetDevice()->SetPixelShader(nullptr);
    STATEMANAGER.GetDevice()->SetVertexShader(nullptr);
    STATEMANAGER.GetDevice()->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
    STATEMANAGER.GetDevice()->SetStreamSource(0, m_lpScreenQuad, 0, sizeof(TRTTVertex));
    STATEMANAGER.GetDevice()->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);

    IDirect3DSurface9* pCurrentTarget = m_lpTargetSurface;

    STATEMANAGER.GetDevice()->SetTexture(1, m_lpSourceTexture);

    for (std::list<CPostProcessingEffect>::iterator it = m_kEffects.begin(); it != m_kEffects.end(); ++it)
    {
        D3DSURFACE_DESC kDesc;
        pCurrentTarget->GetDesc(&kDesc);

        D3DXVECTOR4 vScreenSize = D3DXVECTOR4(kDesc.Width, kDesc.Height, 0.0f, 0.0f);
        (*it).GetConstants()->SetFloatArray(STATEMANAGER.GetDevice(), "ScreenSize", reinterpret_cast<float*>(&vScreenSize), 4);

        if ((*it).Apply())
        {
            STATEMANAGER.GetDevice()->SetRenderTarget(0, pCurrentTarget);
            STATEMANAGER.GetDevice()->Clear(0, nullptr, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0.0f);
            STATEMANAGER.GetDevice()->SetTexture(0, pCurrentTarget == m_lpLastPassSurface ? m_lpTarget : m_lpLastPass);
            STATEMANAGER.GetDevice()->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
            STATEMANAGER.GetDevice()->SetStreamSource(0, m_lpScreenQuad, 0, sizeof(TRTTVertex));
            STATEMANAGER.GetDevice()->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);
            pCurrentTarget = pCurrentTarget == m_lpLastPassSurface ? m_lpTargetSurface : m_lpLastPassSurface;
        }
    }

    STATEMANAGER.GetDevice()->SetTexture(1, nullptr);

    if (pCurrentTarget == m_lpTargetSurface)
    {
        STATEMANAGER.GetDevice()->SetRenderTarget(0, m_lpTargetSurface);
        STATEMANAGER.GetDevice()->Clear(0, nullptr, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0.0f);
        STATEMANAGER.GetDevice()->SetTexture(0, m_lpLastPass);
        STATEMANAGER.GetDevice()->SetPixelShader(nullptr);
        STATEMANAGER.GetDevice()->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
        STATEMANAGER.GetDevice()->SetStreamSource(0, m_lpScreenQuad, 0, sizeof(TRTTVertex));
        STATEMANAGER.GetDevice()->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);
    }

    STATEMANAGER.RestoreRenderState(D3DRS_MULTISAMPLEANTIALIAS);
    STATEMANAGER.RestoreRenderState(D3DRS_ZENABLE);
    STATEMANAGER.GetDevice()->SetTransform(D3DTS_WORLD, &mWorld);
    STATEMANAGER.GetDevice()->SetTransform(D3DTS_VIEW, &mView);
    STATEMANAGER.GetDevice()->SetTransform(D3DTS_PROJECTION, &mProj);

    return true;
}

bool CPostProcessingChain::CreateResources()
{
    ReleaseResources();

    D3DSURFACE_DESC kDesc;
    IDirect3DSurface9* pSurface;
    STATEMANAGER.GetDevice()->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pSurface);
    pSurface->GetDesc(&kDesc);
    pSurface->Release();

    if (FAILED(STATEMANAGER.GetDevice()->CreateTexture(kDesc.Width, kDesc.Width, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A32B32G32R32F, D3DPOOL_DEFAULT, &m_lpSourceTexture, nullptr)))
    {
        TraceError("CPostProcessingChain unable to create render target");
        return false;
    }
    m_lpSourceTexture->GetSurfaceLevel(0, &m_lpSourceTextureSurface);
    if (FAILED(STATEMANAGER.GetDevice()->CreateTexture(kDesc.Width, kDesc.Width, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A32B32G32R32F, D3DPOOL_DEFAULT, &m_lpLastPass, nullptr)))
    {
        TraceError("CPostProcessingChain unable to create pass render target");
        return false;
    }
    m_lpLastPass->GetSurfaceLevel(0, &m_lpLastPassSurface);
    if (FAILED(STATEMANAGER.GetDevice()->CreateTexture(kDesc.Width, kDesc.Width, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A32B32G32R32F, D3DPOOL_DEFAULT, &m_lpTarget, nullptr)))
    {
        TraceError("CPostProcessingChain unable to create final render target");
        return false;
    }
    m_lpTarget->GetSurfaceLevel(0, &m_lpTargetSurface);

    STATEMANAGER.GetDevice()->GetDepthStencilSurface(&pSurface);
    pSurface->GetDesc(&kDesc);
    pSurface->Release();
    if (FAILED(STATEMANAGER.GetDevice()->CreateDepthStencilSurface(kDesc.Width, kDesc.Width, D3DFMT_D16, kDesc.MultiSampleType, kDesc.MultiSampleQuality, FALSE, &m_lpDepthStencilSurface, nullptr)))
    {
        TraceError("CPostProcessingChain unable to create depth surface");
        return false;
    }

    if (FAILED(STATEMANAGER.GetDevice()->CreateVertexBuffer(sizeof(TRTTVertex)* 6, 0, D3DFVF_XYZRHW | D3DFVF_TEX1, D3DPOOL_MANAGED, &m_lpScreenQuad, nullptr)))
    {
        TraceError("CPostProcessingChain unable to create screen quad");
        return false;
    }

    float fWidth = static_cast<float>(kDesc.Width) - 0.5f;
    float fHeight = static_cast<float>(kDesc.Height) - 0.5f;
    float fTexPos = fHeight / fWidth;

    TRTTVertex* pVertices;
    m_lpScreenQuad->Lock(0, 0, reinterpret_cast<void**>(&pVertices), 0);
    pVertices[0].p = D3DXVECTOR4(-0.5f, -0.5f, 0.0f, 1.0f);
    pVertices[0].t = D3DXVECTOR2(0.0f, 0.0f);
    pVertices[1].p = D3DXVECTOR4(-0.5f, fHeight, 0.0f, 1.0f);
    pVertices[1].t = D3DXVECTOR2(0.0f, 1.0f);
    pVertices[2].p = D3DXVECTOR4(fWidth, fHeight, 0.0f, 1.0f);
    pVertices[2].t = D3DXVECTOR2(1.0f, 1.0f);
    pVertices[3].p = D3DXVECTOR4(-0.5f, -0.5f, 0.0f, 1.0f);
    pVertices[3].t = D3DXVECTOR2(0.0f, 0.0f);
    pVertices[4].p = D3DXVECTOR4(fWidth, fHeight, 0.0f, 1.0f);
    pVertices[4].t = D3DXVECTOR2(1.0f, 1.0f);
    pVertices[5].p = D3DXVECTOR4(fWidth, -0.5f, 0.0f, 1.0f);
    pVertices[5].t = D3DXVECTOR2(1.0f, 0.0f);
    m_lpScreenQuad->Unlock();

    /*0, 0          | up left
    0, height       | down left
    width, height   | down right

    0, 0            | up left
    width, height   | down right
    width, 0        | up right*/

    AddEffect("shaders/testshader.xml");

    return true;
}

此代码适用于AMD显卡,但不适用于NVida显卡, 我已经尝试使用cl2p clamp纹理,但这没有用,所以目前我一点也不知道为什么它在AMD上运行而不在Nvidia卡上

它不会在Nvidia上崩溃,但屏幕是黑色的

如果您有任何想法,请回复, 提前致谢

0 个答案:

没有答案