Why can't I lock a RenderTexture in DirectX9?

In Unity I grab the Pointer to the RenderTexture with GetNativeTexturePtr() and send that to my plugin (like the native plugin example)

Only when I want to lock the Texture with the following code in my plugin I get an D3DERR_INVALIDCALL

HRESULT hr;
IDirect3DTexture9* d3dtex = (IDirect3DTexture9*)g_TexturePointer;
D3DSURFACE_DESC desc;
d3dtex->GetLevelDesc (0, &desc);
D3DLOCKED_RECT lr;
hr = d3dtex->LockRect (0, &lr, NULL, 0);
// hr is S_OK when i send a Texture2D but not when it's a RenderTexture howcome?

I’m guessing it has something to do with Memory location of the RenderTexture?

I want to read the pixels of the RenderTexture in Direct3D 9

After figuring out that render textures are stored in the Default D3D memory pool… I found out that I needed to access it’s data through a GetRenderTargetData method.
after retrieving the surface from the texture and using the aforementioned method it worked :slight_smile:

IDirect3DTexture9* d3dtex = (IDirect3DTexture9*)g_TexturePointer;
D3DSURFACE_DESC desc;
d3dtex->GetLevelDesc (0, &desc);

if(desc.Pool == D3DPOOL_DEFAULT)
{
	g_IsRenderTexture = true;
	IDirect3DSurface9* offscreenSurface;
	HRESULT hr = g_D3D9Device->CreateOffscreenPlainSurface( desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &offscreenSurface, NULL );
	if(hr == S_OK) 
	{
		g_SurfacePointer = offscreenSurface;
	}
	else
		print_to_log("Couldn't create Offscreen surface for RenderTexture");
	}
}

To copy the render texture you need to get it’s surface data:

// Get References
IDirect3DTexture9* d3dtex = (IDirect3DTexture9*)g_TexturePointer;
IDirect3DSurface9* d3dsurf = (IDirect3DSurface9*)g_SurfacePointer;
				
// Get Texture Surface
IDirect3DSurface9* tmpSurf;
d3dtex->GetSurfaceLevel(0,&tmpSurf);

// Copy Surface to Surface
g_D3D9Device->GetRenderTargetData(tmpSurf,d3dsurf);

I actually ran into a similar issue recently on a colleague’s machine - he was running very old drivers and after updating it fixed the issue.