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));
    // when I debug, m_pPixelShader does get set properly)
    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));


    return m_pDevice->SetRenderTarget(0, m_pTextureSurface);
  • \$\begingroup\$ What gives you the impression that StretchRect would go through a pixel shader? What you need to do here is to render a screen-filling quad to a render target texture. \$\endgroup\$ Jul 17, 2015 at 20:45
  • \$\begingroup\$ I'm rendering to a RenderTarget texture. I suppose the vertexes are to create a screen-filling quad? What needs to be done from here? \$\endgroup\$ Jul 17, 2015 at 22:24

1 Answer 1


StretchRect function does not execute the pixel shader.

Instead: Set up your render target and draw a polygon to cover the entire screen. This is the common way to perform a "full screen shader" pass.

Anecdotally, My personal recommendation is to investigate the Compute Shader.

  • \$\begingroup\$ Very few compute shaders run in Direct3D 9. \$\endgroup\$ Jan 12, 2016 at 11:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .