DX9 How to Apply HLSL Shader with StretchRect

| | August 4, 2015

Using DirectX 9,I’m trying to run a HLSL pixel shader on video frame data while copying it from one texture buffer to another texture buffer without displaying it. StretchRect at the end is what copies the data from pOffsceenSurface to pTextureSurface, which should pass through the pixel shader. The video data does get passed over and I can read it back, but the shader isn’t being applied.

What do I need to do to process the texture through the shader? And does register(S0) get automatically filled, or how do I set the source? The code I have allows configuring register(C0), register(C1), etc. through m_pPixelConstantTable, but not the S registers. Some shaders take S0 and S1 so it needs to be configured somehow.

Here’s the code

HRESULT D3D9RenderImpl::SetPixelShader(LPCSTR pPixelShaderName, LPCSTR entryPoint, LPCSTR shaderModel, LPSTR* ppError)
{
    CComPtr<ID3DXBuffer> code;
    CComPtr<ID3DXBuffer> errMsg;

    HR(D3DXCompileShaderFromFile(pPixelShaderName, NULL, NULL, entryPoint, shaderModel, 0, &code, &errMsg, &m_pPixelConstantTable));
    return m_pDevice->CreatePixelShader((DWORD*)code->GetBufferPointer(), &m_pPixelShader);
}

HRESULT D3D9RenderImpl::CreateScene(void)
{
    HR(m_pDevice->Clear(D3DADAPTER_DEFAULT, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0));
    HR(m_pDevice->BeginScene());
    HR(m_pDevice->SetFVF(D3DFVF_CUSTOMVERTEX));
    // when I debug, m_pPixelShader does get set properly)
    HR(m_pDevice->SetPixelShader(m_pPixelShader));
    HR(m_pDevice->SetTexture(0, m_pTexture));
    HR(m_pDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2));
    return m_pDevice->EndScene();
}

HRESULT D3D9RenderImpl::Present(void)
{
    HR(m_pDevice->ColorFill(m_pTextureSurface, NULL, D3DCOLOR_ARGB(0xFF, 0, 0, 0)));
    return(m_pDevice->StretchRect(m_pOffsceenSurface, NULL, m_pTextureSurface, NULL, D3DTEXF_LINEAR));
    // This line doesn't seem necessary
    // return m_pDevice->Present(NULL, NULL, NULL, NULL);
}

What’s missing?

EDIT: Here’s what I’m rendering to

HRESULT D3D9RenderImpl::CreateRenderTarget()
{
    // HR(m_pDevice->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, m_displayMode.Format, D3DPOOL_DEFAULT, &m_pTexture, NULL));
    HR(m_pDevice->CreateTexture(m_videoWidth, m_videoHeight, 1, D3DUSAGE_RENDERTARGET, m_format, D3DPOOL_DEFAULT, &m_pTexture, NULL));
    HR(m_pTexture->GetSurfaceLevel(0, &m_pTextureSurface));
    HR(m_pDevice->CreateVertexBuffer(sizeof(VERTEX) * 4, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &m_pVertexBuffer, NULL));

    VERTEX vertexArray[] =
    {
        { D3DXVECTOR3(0, 0, 0), D3DCOLOR_ARGB(255, 255, 255, 255), D3DXVECTOR2(0, 0) },  // top left
        { D3DXVECTOR3(m_videoWidth, 0, 0), D3DCOLOR_ARGB(255, 255, 255, 255), D3DXVECTOR2(1, 0) },  // top right
        { D3DXVECTOR3(m_videoWidth, m_videoHeight, 0), D3DCOLOR_ARGB(255, 255, 255, 255), D3DXVECTOR2(1, 1) },  // bottom right
        { D3DXVECTOR3(0, m_videoHeight, 0), D3DCOLOR_ARGB(255, 255, 255, 255), D3DXVECTOR2(0, 1) },  // bottom left
    };

    VERTEX *vertices;
    HR(m_pVertexBuffer->Lock(0, 0, (void**)&vertices, D3DLOCK_DISCARD));

    memcpy(vertices, vertexArray, sizeof(vertexArray));

    HR(m_pVertexBuffer->Unlock());

    return m_pDevice->SetRenderTarget(0, m_pTextureSurface);
}

Leave a Reply