Traditionaly, yes it would be a performance hit.
How ever, And im not sure if/how this would work, its just something that came to me:
Perhaps using a sort of secondary back buffer. And as you would "flip" the backbuffer to the screen, you could draw your bitmap on the secondary backbuffer once, and every render "flip" it to the standard backbuffer. This shouldnt be much of a performance hit.
Actually, now that im thinking about it. heres some rough psuedo code that might be a good lead. In my programming book for d3d, this is how you would go about plotting a pixel:
// now this is what part of the setpixel method looks like
// .. in render method
LPDIRECT3DSURFACE8 pBackSurf = 0;
HRESULT r = 0;
r = g_pDevice->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pBackSurf );
r = pBackSurf->LockRect( &LockedRect, NULL, 0 );
DWORD * pData = (DWORD*)(LockedRect.pBits);
// set pixel functions
SetPixel32( int X, int y, DWORD Color, int Pitch, DWORD* pData );
pData = 0;
// continue through render method...
now your methods may be different but perhaps you see where im going.
pData[ (((Pitch/4)*y)+x)] = Color;
Create a global copy of the pData array on the first go around and name it BitmapBuffer or something (could be done in GameInit() function instead of render.
Write your own bitmap loading procedure, that reads the color value of every pixel in the bitmap and changes the bitmapBuffer.
Now that you have your bitmap stored in an array very easy to handle, in your render method you can use a memcpy() function to QUICKLY copy BitmapBuffer to the current backbuffer, then render over it with 3D.
Im pretty sure that should work. I hope i didnt lose you. If you still have a question Ask, and I'll see if i can clarify.