Graphics
Intel® graphics drivers and software, compatibility, troubleshooting, performance, and optimization
20493 Discussions

Simple demo of HD 4400 and HD 4600 screen tearing under Windows 8.1 + DirectX 9

ARCH_R_Intel
Employee
2,045 Views
Summary

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.

Details

The 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:

  1. Fill a buffer with RED pixels.
  2. Overwrite the buffer with BLUE pixels.
  3. Ship the buffer to the screen.
  4. 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 Experts

More 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.

0 Kudos
11 Replies
Jose_H_Intel1
Employee
856 Views

Does the issue occur with an older graphics driver version?

0 Kudos
ARCH_R_Intel
Employee
856 Views

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.

0 Kudos
ROBERT_U_Intel
Employee
856 Views

@ Arch, I have our DX developers looking at this and will update this thread when we have additional information.

Thanks

Robert

0 Kudos
ROBERT_U_Intel
Employee
856 Views

@ 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

0 Kudos
ARCH_R_Intel
Employee
856 Views

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

0 Kudos
ROBERT_U_Intel
Employee
856 Views

@ 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

0 Kudos
ROBERT_U_Intel
Employee
856 Views

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

0 Kudos
ARCH_R_Intel
Employee
856 Views

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

0 Kudos
ROBERT_U_Intel
Employee
856 Views

Thanks for the feedback Arch, we are investigating it.

Robert

0 Kudos
ROBERT_U_Intel
Employee
856 Views

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

0 Kudos
ARCH_R_Intel
Employee
856 Views

A Windows 8.1 update some time spring of 2015 has fixed the problem.

0 Kudos
Reply