디버깅시 브레이크 포인트 걸렸을 때 인풋 렉 발생

비주얼 스튜디오 2008에서 2015로 마이그레이션 중 아래와 같은 에러가 있었습니다.

디버깅시 브레이크 포인트가 걸리면 비주얼 스튜디오 자체에 렉이 걸리더군요. 키보드든 마우스든 모든 입력이 렉이 걸렸습니다. 마치 아래 영상과 비슷한 느낌이었습니다.

이것저것 구글링을 해보고 시도를 해봤습니다.


위와 같은 것들을 모두 시도해 봤지만 어떤것도 문제를 해결해주지는 않았습니다. 하지만 좀만 더 파보니 원인은 dx input과의 충돌이라는게 밝혀졌습니다. dx input의 acquire를 통해서 인풋 장비를 얻어오면 렉이 걸리고 얻어오지 않으면 렉이 없더군요.

//foo.cpp
int dx_input_lag_func()
{
   acquire(false);
   ...
   ...//break point
   ...
   ...
   acquire(ture);
}

대략 위와 같이 브레이크 걸리기전에 acquire(false)로 해주고 디버깅 끝나는 부분에 다시 acquire(true)를 해주는 식으로 테스트를 해봤습니다. 하지만 이것은 디버깅 할 때마다 소스를 이렇게 수정해서 하는 것은 근본적인 해결책이 아니기 때문에 다른 해결책이 필요했습니다.

제가 생각한 해결 방안은 릴리즈는 기존대로 dxinput을 사용하고 디버그시에만 GetAsyncKeyState등을 사용해서 처리하도록 하는 방안이었습니다. 그래서 아답터 패턴을 도입하고 아래와 같은 것들을 처리했습니다.
  • 아답터 패턴 처리
    • 일반용 Input Adapter - 기존과 같이 Dx Input을 사용해서 처리
    • 개발용 Input Adapter - win32 API인 GetAsyncKeyState로 처리
  • 기존 g_pDXInput 전역 변수 제거 후 아답터 패턴 처리 된 객체 싱글턴 처리
키다운 체크 부분의 경우
g_pDXInput->KeyDown(DIK_LCONTROL)
이런것이
Input::InputAdapter::GetInstance()->KeyDown(DIK_LCONTROL)
이런식으로 변경이 되었습니다.

이렇게 해서 디버그 브레이크 포인트시 렉은 사라졌습니다. 다만 GetAsyncKeyState의 특성상? dx input을 완벽히 같게 구현이 되지는 않았습니다. 예로 KeyDown을 아래 2가지 방식중 어떤걸 사용하느냐에 따라 기존과 비슷하거나 다른 결과로 이어지더군요. 하지만 둘다 뭔가 하나씩은 부족했습니다.

if (GetAsyncKeyState(iVKCode) & 0x0001)
if (GetAsyncKeyState(iVKCode) & 0x8000)

공통된 인터페이스로 개발시에는 GetAsyncKeyState로 처리하고 릴리즈는 기존과 동일하기 때문에 인풋 관련 버그가 새로 생기거나 하지도 않을 거라 일단 이렇게 만족하고 있는 상태입니다. 인풋렉도 없어져서 디버깅도 용이했구요.

마지막으로 저희는 #define DIRECTINPUT_VERSION         0x0700 즉 dx input 7.0으로 개발이 된 상태라서 비주얼 스튜디오와 충돌이 발생한게 아닌가 생각됩니다. 좀더 높은 버전의 dxinput을 사용하면 괜찮지 않을까 생각되네요.

이 블로그의 인기 게시물

Unity3D Prime31 처럼 자신만의 안드로이드 플러그인을 만들어보자

CMake Windows에 설치하기

Unity3D iOS Plugin 만들어 연동하기