- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I've getting screen tearing on both HD 4400 and HD 4600 machines running Windows 8.1 when using DirectX 9. I've reduced the problem to a short demo program, and made the source code available. The demo, on failing machines, shows red on the screen that should be all blue. More so if the program is compiled in "Release" mode, hence my suspicion of a timing issue.
DetailsThe HD 4400 machine has a BIOS and graphics driver up to date as of 2014-Aug-12. I have not seen the problem on machines with discrete graphics cards running Windows XP or Windows 7. Alas I don't have a HD 4400/4600 machine running Windows 7, so I don't know know if the root cause is Windows 8.1 or the Intel graphics.
The program uses DirectX 9 and double buffering, in a way that I've used successfully for nearly a decade, and I believe is vanilla code. The source code and executable are available from my personal web site (http://www.blonzonics.us/miscellaneous/redflicker RedFlicker - Blonzonics) along with instructions for running the program. Here is what the program does:
- Fill a buffer with RED pixels.
- Overwrite the buffer with BLUE pixels.
- Ship the buffer to the screen.
- Repeat.
By my understanding, the screen should always show BLUE pixels, because the RED pixels are totally overwritten before the buffer is displayed. But the top of the screen shows RED pixels sometimes, as if the buffer is being prematurely displayed, (or is delayed in being not displayed after buffer swapping?) Possibilities:
- I've been using DirectX 9 incorrectly for nearly a decade, and never noticed until Windows 8.1/HD 4x00 showed up.
- DIrectX 9 + Windows 8.1 has a bug.
- Intel's driver or hardware has a bug.
What's the best way to attempt to resolve this issue?
P.S. Gory Details for DirectX 9 ExpertsMore details follow, of possible interest to DirectX experts who might spot something wrong in my code. Below is how I am updating and displaying the buffer (from lines 244-268 of RedFlicker.cpp in the source code from the website):
static void UpdateAndDraw( HWND hwnd ) {
HRESULT hr;
Device->BeginScene();
IDirect3DSurface9* backBuffer=0;
hr = Device->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO,&backBuffer);
Assert(hr==D3D_OK);
D3DSURFACE_DESC desc;
hr = backBuffer->GetDesc(&desc);
Assert(hr==D3D_OK);
D3DLOCKED_RECT lockedRect;
hr = backBuffer->LockRect(&lockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_DISCARD);
Assert(hr==D3D_OK);
FillWithCheckerBoard(desc, lockedRect, 0xFF0000);
FillWithCheckerBoard(desc, lockedRect, 0x0000FF);
hr = backBuffer->UnlockRect();
Assert(hr==D3D_OK);
backBuffer->Release();
Device->EndScene();
hr = Device->Present( 0, 0, 0, 0 );
if( hr!=D3D_OK ) {
Decode(hr);
}
}
Here is the routine that sets up the "present" parameters:
static void SetPresentParameters( D3DPRESENT_PARAMETERS& present ) {
ZeroMemory( &present, sizeof(D3DPRESENT_PARAMETERS) );
present.BackBufferCount = 2;
present.SwapEffect = D3DSWAPEFFECT_DISCARD;
present.BackBufferFormat = D3DFMT_X8R8G8B8;
present.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
present.Windowed = !ExclusiveMode;
if( ExclusiveMode ) {
present.BackBufferHeight = DisplayHeight;
present.BackBufferWidth = DisplayWidth;
}
}
The "present" parameters are transmitted to DirectX in this routine:
static bool InitializeDirectX( HWND hwnd ) {
HRESULT hr;
// Create the Direct3D interface object.
d3d = Direct3DCreate9( D3D_SDK_VERSION );
Assert(d3d!=NULL);
// Get device capabilities
D3DCAPS9 displayCaps;
hr = d3d->GetDeviceCaps(0,D3DDEVTYPE_HAL,&displayCaps);
Assert(hr==D3D_OK);
// Get resolution of current display mode
D3DDISPLAYMODE displayMode;
hr = d3d->GetAdapterDisplayMode(0,&displayMode);
Assert(hr==D3D_OK);
DisplayHeight = displayMode.Height;
DisplayWidth = displayMode.Width;
// Create the device
D3DPRESENT_PARAMETERS present;
SetPresentParameters(present);
hr = d3d->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hwnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&present,
&Device
);
if ( hr!=D3D_OK ) {
char buffer[200];
sprintf_s(buffer,200,"Internal error: d3d->CreateDevice returned %s\n",Decode(hr));
MessageBoxA(hwnd,buffer,NULL,MB_OK|MB_ICONWARNING);
return false;
}
return true;
}
The source code download has the full source (360 lines) and a VS2013 solution for compiling it.
- Tags:
- Intel® HD Graphics
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Does the issue occur with an older graphics driver version?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It was occurring with whatever graphics driver version I was using in February 2014. Alas I don't have the version number for that one, though it was probably the latest available at that time.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@ Arch, I have our DX developers looking at this and will update this thread when we have additional information.
Thanks
Robert
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@ Arch, Could you add the following delay to your code and post your results?
FillWithCheckerBoard(desc, lockedRect, 0xff0000);
FillWithCheckerBoard(desc, lockedRect, 0x0000FF);
SleepEx(12, false);
Thanks
Robert
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
SleepEx(6,false) was sufficient to make problem go away on HD 4600 in a 4770S CPU. Needed as much SleepEx(15,false) to make problem go away on HD 4400 in a 4210U CPU. (Latter is almost a full frame delay at 60 Hz refresh.) Is it known where what root problem is (my code, driver, DirectX, or OS)?
- Arch
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@ Arch, we are still looking into this however, we do not believe it is your code that is at fault. The sleep suggestion is a work around until we understand the issue more. I will post updates here as we get them.
Thanks
Robert
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Arch. Could you try the following driver with your original code?
https://downloadcenter.intel.com/Detail_Desc.aspx?DwnldID=23985&lang=eng&ProdId=3719 Intel® Download Center
Thanks
Robert
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The new driver fixes the problem mostly, but not completely. Changes in the delay parameter seem to bring on red flickers. I've only been able to test on a HD 4600 system since the HD 4400 left for college.
I've updated my https://sites.google.com/site/blonzonics/miscellaneous/redflicker website to add version 2.0 of my demo program, which demonstrates the remaining vestige of the problem. Both the executable and source are there. The 2.0 version is essentially the same as before, but keys a-z set the delay to 0 to 25 milliseconds. If I start RedFlicker_2.0.exe and then alternately press 'b' and 'k' (1 millisecond and 10 milliseconds delays) many times, I see the red flickering.
- Arch
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for the feedback Arch, we are investigating it.
Robert
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Arch
Our DirectX folks have almost completed their investigation and are confident this is an OS issue. I will post an update once they are finished looking at it.
Thanks
Robert
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
A Windows 8.1 update some time spring of 2015 has fixed the problem.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page