How to enable VSYNC in D3D windowed app? - directx

So, Im using D3D in a windowed application.
I inited D3D with the following parameters:
windowed: true;
backbufferformat: D3DFMT_X8R8G8B8;
presentinterval: D3DPRESENT_INTERVAL_ONE;
swapeffect: DISCARD
Each time OnPaint is called, I render the image to the backbuffer and present it to front.
As far as I know (and so does MSDN say), once I set D3DPRESENT_INTERVAL_ONE, vsync will work.
But in this case, the image is teared when dragging horizontally.
(It seems there's a line across the image, image below the line shows on the monitor and the above part follows.)
Some sites say D3DPRESENT_INTERVAL_ONE will not work in windowed applications.
How can I enable vsync anyway?
p.s. I finally found D3D vsync is enabled, while some window settings are not right that perhaps the window itself is not sync ed. though, I haven't peek the settings out.

I assume you're using D3D9? Should add that tag. On your D3DPRESENT_PARAMS variable:
if (bVysncEnabled)
{
presentParams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
presentParams.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
}
else
{
presentParams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
presentParams.FullScreen_RefreshRateInHz = 0;
}
If you've done this and you're using the old GDI stuff, it's not your vsync setting that's wrong, but the window settings. You must enable double buffering or you'll still get tearing.

You cannot vsync while in windowed, only in fullscreen. However, you could potentially ghetto it by getting info from the default display and finding the refresh rate, and then nerfing your renderer to only render at that rate...although I wouldn't suggest that route.

Windowed historically haven't been able to be vsynced for d3d, and only recently has this been possible, when aero is enabled in WinVista or Win7 and the app isn't running in presentation mode immidiate.

How often do you call ::OnPaint ? The reason I am asking is, that you must be calling ::OnPaint more often than the refresh rate of your attached monitor.
For me, I solved the refresh issue by forcing an ::OnPaint whenever the message loop is idle with invalidating the window. What will happen if you do that, is, that the RenderPresent command for D3D will WAIT until the graphic card finished rendering, which gives you a very precise timing of the ::OnPaint in sync with the actual monitor refresh rate !
I am having good success with this, and the statements above that windowed mode cannot vsync is definitely not true. Even in DirectX 9 Win XP, this just works.
Oh and last but not least, if you have more than one display attached, make sure to vsync with the actual display which presents your window. This seems a bit more tricky.

not exactly D3D, but AntiTearing.html describes how MPC-HC uses windowed EVR et al to try and avoid tearing of a windowed display. The links here: http://betterlogic.com/roger/2012/05/gdi-vsync-to-avoid-tearing/ may be useful for synchronizing, too (albeit something of a work around).

Related

'Capture GPU frame' first frame for iOS app

My application performs several rendering operations on the first frame (I am using Metal, although I think the same applies to GLES). For example, it renders to targets that are used in subsequent frames, but not updated after that. I am trying to debug some of draw calls from these rendering operations, and I would like to use the 'GPU Capture Frame' functionality to do so. I have used it in the past for on-demand GPU frame debugging, and it is very useful.
Unfortunately, I can't seem to find a way to capture the first frame. For example, this option is unavailable when broken in the debugger (setting a breakpoint before the first frame). The Xcode behaviors also don't seem to allow for capturing the frame once debugging starts. There also doesn't appear to even be an API for performing GPU captures, in Metal APIs or the CAMetalLayer.
Has anybody done this successfully?
I've come across this again, and figured it out properly now. I'll add this as a separate answer, since it's a completely different approach from my other answer.
First, some background. There are three components to capturing a GPU frame:
Telling Xcode that you want to capture a GPU frame. In typical documented use, you do this manually by clicking the GPU Frame Capture "camera" button in Xcode.
Indicating the start of the next frame to capture. Normally, this occurs at the next occurrence of MTLCommandBuffer presentDrawable:, which is invoked to present the framebuffer to the underlying view.
Indicating the end of the frame being captured. Normally, this occurs at the next-but-one occurrence of MTLCommandBuffer presentDrawable:.
In capturing the first frame, or activity before the first frame, only the third of these is available, so we need an alternate way to perform the first two items:
To tell Xcode to begin capturing a frame, add a breakpoint in Xcode at a line in your code somewhere before the point at which you want to start capturing a frame. Right-click the breakpoint, select Edit Breakpoint... from the pop-up menu, and add a Capture GPU Frame action to the breakpoint:
To indicate the start of the frame to capture, before the first occurrence of MTLCommandBuffer presentDrawable:, you can use the MTLCommandQueue insertDebugCaptureBoundary method. For example, you could invoke this method as soon as you instantiate the MTLCommandQueue, to immediately begin capturing everything submitted to the queue. Make sure the breakpoint in item 1 will be triggered before the point this code is invoked.
To indicate the end of the captured frame, you can either rely on the first normal occurrence of MTLCommandBuffer presentDrawable:, or you can add a second invocation of MTLCommandQueue insertDebugCaptureBoundary.
Finally, the MTLCommandQueue insertDebugCaptureBoundary method does not actually cause the frame to be captured. It just marks a boundary point, so you can leave it in your code for future debugging use. Wrap it in a DEBUG compilation conditional if you want it gone from production code.
Try...
[myMTLCommandEncoder insertDebugSignpost: #"com.apple.GPUTools.event.debug-frame"].
To be honest, I haven't tried it myself, but it's analogous to the similar
glInsertEventMarkerEXT(0, "com.apple.GPUTools.event.debug-frame")
documented for OpenGL ES, and there is some mention on the web of it working for Metal.
First, in Metal, I usually use Metal to do parallel compute, then GPU Capture frame is alway grey. So, there are two ways until now I found is Ok.
In iOS 11
you can use the [[MTLCaptureManager alloc] startCaptureWithDevice:m_Device]; to capture frame so you can profile the compute shader performance
lower than iOS 11 (MTLCaptureManager && MTLCaptureScope are new in iOS 11.0 )
you can use the breakpoint, then edit the Action.Capture GPU Frame

OpenGL app's framerate has detiorated following an upgrade from iOS7.1 to iOS8.1

The app uses OpenGL ES2 and the GLKit framework, and the render/update loop provided by GLKitViewController. It used to run at a steady 60 fps on my iPad2 with iOS7.1, but once I updated the iPad2 to iOS8.1, the exact same code now fluctuates between 56-59 FPS. (CPU utlitization, however, remains at 40-60% as before ).
Profiling reveals that the OpenGL drawing commands are using a much larger proportion of CPU time than they used to. The biggest change seems to be that calls to "GLKBaseEffect prepareToDraw" are taking much longer than they used to.
(The app uses a single GLKBaseEffect which is reconfigured at various points during the render loop, neccessitating a call to prepareToDraw each time. I realise it may be possible to optimize by having multiple instances of GLKBaseEffect, and that is something I was considering for later, however, the performance, as it was, was solid on iOS7.1)
I'm now examining theĀ OpenGL ES Analyzer trace in Instruments to determine the OpenGL calls generated by "GLKBaseEffect prepareToDraw", to see if anything seems unusual, and will update the post accordingly once I've managed to figure anything out.
I'd be very grateful for any guidance on how to progress at this point - why might calls to GLKBaseEffect prepareToDraw take longer on iOS8.1?
The cause of the problem was identified by Jim Hillhouse and confirmed by Frogblast on the Apple Dev Forums thread "OpenGL Performance Drops > 50% in iOS 8 GM": setting the text property of a UITextField (or UILabel, in my case) in a view which is a subview of GLKView is causing the GLKView superview to layout, which is then causing framebuffers to be deallocated and reallocated. This wasn't happening in iOS 7.
Jim Hillhouse's workaround was to place the subview inside a UIViewController, and embed that in GLKView. I've done the same, using a Container View to hold the view controller, and can confirm that it works.

DX10 setfullscreenstate not working on second monitor

I have two display monitors connected to my pc.
I am using DirectX 10. I have a basic app, when I press space button I call;
swapChain->SetFullscreenState(true, 0);
to make it fullscreen.
It works well on my main monitor, but when I move the app to other monitor and press space button it does not work. Also throws first-chance exception.
Is it enough to just call SetFullscreenState function ? Or do I have to make sth else ?
Thanks for help.
Edit : I solved this problem.
You must assign your monitor to an IDXGIOutput type variable and pass it to SetFullscreenState function as second parameter.
swapChain->SetFullscreenState(true, &curr_monitor);

D3D10 (DirectX10) fullscreen performance issue

I have a bit of a problem setting up my DirectX10 (Win32/c++) application for fullscreen mode. The problem is that I want to have my app running in fullscreen right from the start. This can be done by taking the DXGISwapChain::SetFullScreenState function. This works, but i get a small notice in my Visualc++ 2008 debugger which states:
"DXGI Warning: IDXGISwapChain::Present: Fullscreen presentation inefficiencies incurred due to application not using IDXGISwapChain::ResizeBuffers appropriately, specifying a DXGI_MODE_DESC not available in IDXGIOutput::GetDisplayModeList, or not using DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH."
What this means is that DirectX will not take full ownership of the graphicscard and flip the images from front to backbuffer but instead blit them which is much slower.
Now, i do have the DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH enabled and i did try to resize my buffers but i have absolutely no idea what would be the best way to go into fullscreen mode. I have looked on MSDN but there they mostly assume you will only go into Fullscreen by pressing Alt+Enter which lest DXGI do all the work. If someone please could post a bit of code which takes DirectX10 into fullscreen mode and takes full advantage of the "flipping" it would be greatly appriciated!
For anybody interested in the code used on resize:
ReleaseCOM(m_pD3DRenderTargetView);
ReleaseCOM(m_pD3DDepthStencilView);
ReleaseCOM(m_pD3DDepthStencilBuffer);
DXGI_MODE_DESC* mod = new DXGI_MODE_DESC;
mod->Format = DXGI_FORMAT_R8G8B8A8_UNORM;
mod->Height = m_ScreenHeight;
mod->Width = m_ScreenWidth;
mod->RefreshRate.Denominator = 0;
mod->RefreshRate.Numerator = 0;
mod->ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
mod->Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
delete mod; mod = 0;
m_pSwapChain->ResizeTarget(mod);
HR(m_pSwapChain->ResizeBuffers(1, m_ScreenWidth, m_ScreenHeight, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH))
throw(Exception(GET_BUFFER_FAIL, AT));
//problem area
m_pSwapChain->SetFullscreenState(TRUE, NULL);
ID3D10Texture2D* pBackBuffer;
HR( m_pSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (LPVOID*)&pBackBuffer))
throw(Exception(GET_BUFFER_FAIL, AT)); //continues as usual
Is there any reason you delete your mode desc?
Have you also tried putting your mode desc through "FindClosestMatchingMode"?
Check out http://msdn.microsoft.com/en-us/library/cc627095(VS.85).aspx The "Full-Screen issues" section contains a lot of useful information.
There are some prerequisites for enabling flipping in DXGI (which is the most efficient fullscreen presentation mode):
1) You should go into fullscreen state specifying a mode that exists in the system (you could do that either by using mode from IDXGIOutput::GetDisplayModeList or finding it using IDXGIOutput::FindClosestMatchingMode). Your code just specifies screen resolution, so most likely mode is set correctly.
2) After SetFullscreenState, you should call ResizeBuffers with the right buffer size matching mode, this is where DXGI would setup flipping mode.
Typically, it should happen naturally as reaction to WM_SIZE message send by SetFullscreenState transition, so if your app doesn't call ResizeBuffers on WM_SIZE, it probably should.
You can call ResizeBuffers manually after SetFullscreenState and that should work as well.
And yeah, MSDN has a good article about DXGI practices, including fullscreen transition:
http://msdn.microsoft.com/en-us/library/cc627095(VS.85).aspx#Full_Screen_Issues

How do I make TProgressBar stop lagging?

I've got an app that runs a long set of operations, and I'm trying to use a TProgressBar to keep track of what's going on. I set a number of steps, and call .StepIt to increment the progress bar.
Problem is, it doesn't keep up very well. Instead of jumping directly to the correct position, it seems to like to slide gradually up to it. That's all well and good if it's eye candy you're after, but when I'm trying to get an accurate representation of my routine's progress, this makes it appear to be constantly lagging behind the true status. How can I turn that "feature" off?
I only notice this happening under Windows Vista. Not sure if it's also going on on XP or not, because when I test it on XP, the process goes a lot faster and it's over too quickly. :P But this may or may not be Vista-specific. Either way, it's driving me nuts. Does anyone know how to fix it?
I have a quick but partial and inelegant solution, if you don't mind having the progressbar yellow instead of green:
ProgressBar1.SmoothReverse := True;
ProgressBar1.State := pbsPaused; // for yellow or pbsError for red
Or if you don't mind loosing the vista/theme look and go back to a flat blue one:
UxTheme.SetWindowTheme(ProgressBar1.Handle, ' ', ' ');
The real "problem" according to Microsoft is that you try to "pervert" a ProgressBar into a Meter which they claim it is not.
You could also try to draw it yourself ;-)
Same problem on Windows7 !!
But the answer was already in one of the older posts:
If tou make the progressbar step backwards there will NO delay !!!
So I implemented this..... (and get instant updates)
if(progress < ProgressBar.Max)
then
begin
ProgressBar.Position := progress+1;
ProgressBar.Position := progress; //This will set Progress backwards and give an instant update....
end
else
begin //cannot set position beyond max...
ProgressBar.Max := progress + 1;
ProgressBar.Position := progress + 1;
ProgressBar.Max := progress; //This will also set Progress backwards also so instant update........
end;
I ran into exactly the same problem a while ago. After searching Google for a long time, I found that it is a Vista-specific problem. It seems to boil down to this: Microsoft added fancy animations to the progress bar control in Vista (i.e., the moving 'highlight'). To make updates more smooth, they implemented some sort of 'lagging' in the repaint of the control --- and this basically screws the whole progress bar control. Rather annoying, I'd say, especially since there doesn't seem to be a decent solution.
See for more details the replies by Arvid Winkelsdorf to this Embarcadero Discussion Forum post:
It's the same for VB, C++ and C#
somehow as the problem lies in the
Vista drawing of the new animated
ProgressBars. To provide a smoother
visual feedback drawing is delayed
when moving forward. Your application
cannot be sure that 100% will be
reached at any given time.
By setting the position back to a
smaller value, the ProgressBar drawing
is forced to jump back. No delay in
getting to a position smaller than the
current. So you'll have nearly 100%
immediately. Afterwards set to the
maximum and you'll have exactly 100%.
[...]
There is a similar glitch when using
the new Vista ProgressBar Styles like
PB Paused or PB Error. If the bar is
still moving (MS part) and your app
sets the color to paused by
SendMessage (like in D2009) the
message will be ignored by the
ProgressBar.
Maybe you can try to set the position of the ProgressBar directly instead of using the StepIt procedure. I'm on XP with Delphi 7 here, so I can't test it, but looking at the code of TProgressBar it uses a different message (PBM_SETPOS instead of PBM_STEPIT). So maybe it sets the position of the progressbar without an animation.
Additionally there are several 3rd party components which provide better Progress bar implementations that still render nice on Vista. Personally, I prefer the one from Raize components which works quite well. It doesn't "lag" like the windows control does and works independent of any theming.
If you don't really want anything fancy, then you can always build one yourself using a panel and a tshape aligned left inside the panel. Resize the tshape to be a % of the panel it sets on.
I had the same problem, my solution was to switch to another control available in the VCL :
I choose to use the Range of TTrackBar to display the progression.
(with slider off and control resized to hide the range marks).
Not the same visual (particulary if themed), but it fit well my need (no lag).
Here is a simple solution:
ProgressBar.max := ProgressBar.max +1;
ProgressBar.StepBy(2);
ProgressBar.StepBy(-1);
ProgressBar.max := ProgressBar.max -1;

Resources