justinstenning / Direct3DHook

DirectX Capture and Overlays by using Direct3D API hooks
http://spazzarama.com/2011/03/14/c-screen-capture-and-overlays-for-direct3d-9-10-and-11-using-api-hooks
MIT License
584 stars 176 forks source link

ImageFormat.PixelData fails with MapFlags set to DoNotWait #63

Closed jazzup closed 6 years ago

jazzup commented 6 years ago

Hello Justin,

Using latest release with SharpDX v4.0.1 Option set to ImageFormat.PixelData

DXHookD3D11.cs Line: 490 I think calling MapSubresource with MapFlags.DoNotWait is returning an empty DataBox. It seems mapping is done before the gpu has actually finished with CopySubresourceRegion.

If, on the other hand, MapSubresource is called with MapFlags.None (gpu stalls and framerate drops become more noticeable when Load Test is used):

db = _finalRT.Device.ImmediateContext.MapSubresource(_finalRT, 0, MapMode.Read, SharpDX.Direct3D11.MapFlags.None/*DoNotWait*/);

ProcessCapture Line: 509 will succeed for both single capture and Load Test, but the resulting image/images have the wrong colorspace. To correct this, in BaseDXHook's ProcessCapture after Marshal.Copy(pBits, data, 0, size); rearrange...

for (int i = 0; i < data.Length; i += 4) { byte tmp = data[i]; data[i] = data[i + 2]; data[i + 2] = tmp; }

Calling ProcessCapture Line: 509 with System.Drawing.Imaging.PixelFormat.Format32bppArgb will cover most but not all games.

justinstenning commented 6 years ago

@jazzup sorry missed this one - did you close this because it is no longer an issue or some other reason?

jazzup commented 6 years ago

I closed this issue because I'm unsure about the explanation I gave...namely the databox being empty and not wanting to mislead anyone.

PixelData is broken for multiple captures, but occasionally works for a single capture. This is with MapFlags set to DoNotWait and that's what we want. Just to test, try Thread.Sleep(1) while waiting for query result (line 479) and that databox is not empty after all.

Some posters here have said that sometimes the target crashes with no error messages. I found that they are logged in the Event Viewer and they point to a SystemArgumentNullException at line 208 in BaseDXHook, (SystemArgumentNullException: one or more passed parameters is null when it's not supposed to be) and to my understanding, this could only happen if the databox is empty...so go figure.