Running Shader in DX9 Returns Previous Frame

Started by
17 comments, last by unbird 8 years, 7 months ago

I finally got the code to run a HLSL pixel shader in DX9 almost working.

https://github.com/mysteryx93/AviSynthShader/blob/master/VideoPresenter/D3D9RenderImpl.cpp

Here's a weird issue I'm still having. As I load the script, the first frame is black, which is OK. Then, the first time I seek towards a different frame, the frame remains black. The second time I seek to another frame, the first frame is returned. It seems to always returns the frame data of the previous call.

So if I make a diff between the input and output frames of the shader, it looks totally wrong; because it's a diff between two different frames.

Why is it not returning me the current frame data right away?

... just a thought ... could it be that the frame isn't done being processed when I call to get the result?

Advertisement

Shaders don’t “return frames”—they don’t run on anything but the frame they are given.

could it be that the frame isn't done being processed when I call to get the result?

That’s what double-buffering is. You draw to the current frame while the previous frame is being displayed to the viewer.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

So... what do I need to change for GetRenderTargetData to return the result of the frame I had just sent in?

I suspect that the code to adapt might be in CopyFromRenderTarget.

https://github.com/mysteryx93/AviSynthShader/blob/master/VideoPresenter/D3D9RenderImpl.cpp#L197

If it *is* a basic principle of double-buffering, there has got to be a simple solution around it, right?

Delay the audio of your video by 1 frame?

I have no idea what you can do about it. That’s up to your project. You’re the only one who can decide which frame from the video to grab based on what is being displayed through your shader system in such a way that they are synchronized. Since I expect your video to be played through Direct3D and through your system/shaders, I am not sure why you need to specifically synchronize them other than for debug purposes (validate your output), and for that, again, you can just grab the previous video frame instead of the current.

A 1-frame delay never hurt anyone singing karaoke.

And…???????????????????

L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

I don't display anything to the user and I don't use any audio data. The library takes a video frame in, passes it through the shader and returns the frame data back. It has no graphical interface.

Then don’t use double-buffering.
You aren’t really helping us help you.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

I'm simply using a Render Target texture. The code is simple and is attached to the post.

I asked someone very knowledgeable in this and he answered this

You may have to flush the GPU to make sure rendering is complete. This is just a guess, maybe flushing won't help, in that case there is probably a bug in your code. There are various ways to flush, from what I remember:

1) You can lock the surface by using LockRect. But only some types of surfaces can be locked, so this might not work.
2) You can StretchRect to another surface, but I'm not sure if this is really reliable, you'd have to try.
3) Use IDirect3DQuery9 to manually flush the GPU. You should find some code via google.

I'll need time to explore those options. Do you guys have anything else to add to put me on the right track?

After calling GetRenderTargetData, I do call LockRect, so shouldn't that be flushing it already?

You have a bug in your code and you are passing an incorrect frame.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

There is no way I could be passing an incorrect frame. On each call to ProcessFrame, I have no access to data of any other frame.

Most likely cause is that the GPU isn't being flushed and "pending work" isn't being returned.

This topic is closed to new replies.

Advertisement