FireMonkey에서 DirectX 사용을 강제하려면

사용자 삽입 이미지윈도우비스타/7/8인데도 불구하고 FireMonkey 애플리케이션이 DirectX 기반이 아닌 GDI+ 기반으로 돌아가는 경우가 있습니다. 주로 그래픽 칩셋이 저성능 버전일 때인데요. (윈도우 XP/2003의 경우는 DirectX 10.1을 지원되지 않아 오직 GDI+만 사용할 수 있음)

GDI+ 캔바스는 DirectX 캔바스에 비해 드로잉 성능이 많이 떨어집니다. 같은 그래픽 칩셋에서 GDI+ 캔바스와 DirectX 캔바스로 각각 같은 동작을 해보면, DirectX 캔바스를 사용했을 때 그래픽 성능이 눈에 띄게 뛰어납니다. 그래서 윈도우 비스타 이상이라면 DirectX 캔바스를 사용하도록 강제하는 편이 훨씬 좋은데요.

결론부터 먼저 말하자면, 프로젝트 소스의 가장 앞 Application.Initialize; 앞에서 다음과 같이 코드 두 줄을 추가하면 됩니다. (XE3와 XE2에서 조금 다릅니다)

Delphi/C++Builder XE3의 경우,


Delphi/C++Builder XE2의 경우


(프로젝트 소스의 uses에 FMX.Types, System.SysUtils를 추가해야 합니다)

팁 끝!

...하면 너무 허무하니까.. 좀 자세히 설명해보겠습니다. --;;

지난주에 개발 테스트 목적으로 윈도우8 태블릿인 에이서 아이코니아 w510을 구입했는데요. 개발중인 프로젝트를 테스트해보다가, 제 데스크탑, 노트북에 비해 파이어몽키 애플리케이션의 그래픽 성능이 현저하게 떨어지는 것을 발견했습니다. 물론 w510은 클로버트레일 아톰 기반이라 인텔의 주력 CPU들에 비하면 그래픽 성능이 많이 떨어지는 것은 당연한 일이긴 하지만, 아무리 그래도 이해가 되지 않을 정도로 너무 심하게 떨어지더군요.

원인을 찾아나가다가, 혹시 DirectX와 GDI+ 사이에서 성능이 떨어지는 GDI+ 쪽으로 선택되는 것이 아닌가 하는 의심을 하게 되었습니다. FireMonkey는 윈도우 비스타 이상에서는 기본적으로 DirectX를 사용하고 그보다 아래 버전인 윈도우 XP/2003에서는 GDI+를 사용하는 것으로 알고 있었는데요. 그래서, 현재 FireMonkey에서 선택된 Canvas의 구체적인 종류를 알려주는 방법을 찾게 되었습니다.

VCL과 달리 파이어몽키에서는 TCanvas가 가상화되어 있고, 윈도우의 경우 DirectX 캔바스(TCanvasD2D) 및 GDI+ 캔바스(TCanvasGdiPlus)가 등록됩니다. 그리고 MacOSX에서는Quartz 캔바스(TCanvasQuartz)로 만들어집니다.

현재 애플리케이션에서 선택된 캔바스의 종류를 알아내려면, XE3 버전의 경우TCanvasManager.DefaultCanvas, 그리고 XE2 버전의 경우 DefaultCanvasClass를 확인하면 되더군요. 그러니까, ShowMessage(TCanvasManager.DefaultCanvas.ClassName) 이런 코드를 실행했을 때, 'TCanvasD2D'나오면 DirectX 캔바스, 'TCanvasGdiPlus'가 나오면 GDI+ 캔바스인 거죠.

의심했던 대로, 제 w510에서 파이어몽키 애플리케이션을 실행했을 경우, 윈도우 8인데도 불구하고 GDI+ 캔바스를 사용하고 있었습니다. 그래서, TCanvasD2D 혹은 TCanvasGdiPlus 둘 중에서 어느 것이 선택되는지 알아보기 위해 파이어몽키 소스를 이리저리 거의 다 뒤져봤는데요.

파이어몽키 기반 애플리케이션은 기동 직후 초기화 과정에서 TCanvasGdiPlus와 TCanvasD2D 두 종류의 캔버스 클래스를 모두 등록하려고 시도하더군요. 둘 다 사용 가능하면 두 다 등록하는데요. DirectX 캔바스의 경우 등록되기 위한 조건이 좀 많았습니다.

가장 먼저 시스템에 설치된 다이렉트X의 상태를 확인합니다(TCustomDX10Context.CheckDevice). 이 과정에서 다이렉트X 10.1 dll인 d3d10_1.dll을 로드하고, 이 dll의 D3D10CreateDevice1() 함수로 필요한 기능들을 제대로 지원하는지 체크합니다.

그런데, 이때 D3D10CreateDevice1() 함수에 D3D10_FEATURE_LEVEL_10_1을 인자로 넘기더군요. 그러니까 DirectX의 Feature Level이 10.1을 충족해야만 테스트에 성공하는 겁니다. 그런데 상당수 저성능 그래픽 칩셋에서는 DirectX 10.1이나 11을 지원하면서도 Feature Level은 9.3까지만 지원하는 경우들이 있습니다. 제 윈도우8 태블릿에서 사용하는 클로버트레일 CPU가 바로 그렇습니다.

결국 Feature Level이 충족되지 않는 그래픽 칩셋들에선 다이렉트X 대신 GDI+를 기본 캔바스로 선택하게 되는 겁니다. 하지만 앞에서도 썼다시피, 피쳐 레벨이 충분하지 않은 경우라도 다이렉트X 캔바스를 사용하는 것이 GDI+ 캔바스보다 성능이 훨씬 뛰어납니다.

이걸 피하기 위한 방법이 GlobalUseDX10Software 전역변수의 설정입니다(XE3 버전 기준). 이 변수를 true로 설정하면, 그래픽 칩셋의 DirectX 10.1 피쳐레벨이 어디까지 지원되든 무관하게, 강제로 파이어몽키에서 DirectX를 사용하도록 지정합니다. GlobalUseDX10Software가 true인 경우에는 초기에 d3d10_1.dll을 로드 테스트만 해보고 DirectX를 사용하는 것으로 결정하고 그냥 넘어갑니다.

이 GlobalUseDX10Software 전역변수가, XE2 버전에서는 GlobalUseDirect2DSoftware이었습니다. (파이어몽키의 첫 버전과 두번째 버전 사이에서 소스가 상당히 많이 바뀌었더군요) 엠바카데로의 RAD Studio 헬프 및 문서들에는 제대로 잘 설명이 되어 있지 않습니다만, 어쨌든 코드 설계는 분명히 그렇게 되어 있고 실제로 그렇게 동작도 합니다.

이게 윈도우XP/2003에서도 가능하면 좋겠습니다만, MS가 고의적으로 윈도우XP에서는 다이렉트X 10.1을 지원하지 않았기 때문에 불가능합니다. 따라서 d3d10_1.dll 로드 테스트부터 실패하기 때문에 다이렉트X 캔바스를 사용할 방법이 없어지는 거죠. 거꾸로 말하자면, 윈도우XP라고 해도 다이렉트X 10.1만 제대로 설치할 방법만 있다면 XP에서 파이어몽키가 DirectX 기반으로 돌아갈 수 있게 됩니다만, 그런 방법은 아직 없습니다.

그런데, GlobalUseDX10Software(XE3) 혹은 GlobalUseDX10Software(XE2)의 설정만 바꾸면, 윈도우 XP나 2003에서는 실행 직후에 예외가 발생합니다. FireMonkey 코드 설계를 보면, 이 전역변수들을 true로 설정하더라도 윈도우 비스타보다 낮은 경우 아예 다이렉트X 캔바스를 등록하지 못하기 때문에 다른 문제는 없어야 하는데요, 이건 아무래도 FireMonkey 코드의 버그인 것 같습니다.

어쨌든, 이 런타임 에러 때문에, 그래서 현재의 윈도우 버전을 체크해서 윈도우 비스타 이상일 경우에만 이 변수들을 true로 설정하게 할 필요가 있습니다. 그래서 if 문으로 Win32MajorVersion이 6 이상인지 체크해주는 거죠. (Win32MajorVersion이 6 이상이면 윈도우 비스타 이상입니다)

추가로 몇가지 더 알아낸 것을 써보면...
GlobalUseDX10Software 외에 GlobalUseDX10이라는 전역변수도 있는데, 기본값은 true이며 다이렉트X가 사용가능할 때 사용할 것이냐의 여부를 지정합니다. 이것을 false로 설정하면 윈도우 비스타 이상에서도 강제로 GDI+만을 사용합니다. (XE2 버전에서는 이름이 달라서 GlobalUseDirect2D 입니다) 이런 변수들은 모두 FMX.Types 유닛에 선언되어 있습니다.

2 comments for “FireMonkey에서 DirectX 사용을 강제하려면

  1. Pingback: 볼랜드포럼

답글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.