Programowanie współbieżne, Języki programowania, Aplikacje, Gry

Trójkąt w DirectX 11

Chwilowo odbiegnę od głównego tematu mojej strony czyli programowania współbieżnego. Niedawno potrzebowałem przygotować małą aplikacje z wykorzystaniem DirectX. Ponieważ nie miałem narzuconej wersji, postanowiłem sprawdzić najnowszy DirectX 11. O ile do wersji 10 w DirectX SDK znajduje się dość konkretny tutorial, o tyle do jedenastki mamy pusty projekt albo kilka konkretniejszych aplikacji. To czego ja potrzebowałem to szablon aplikacji wyświetlającej zwykły trójkąt. Postanowiłem że po prostu przerobie szybko aplikacje z lekcji 2 i 3 tutoriala do DirectX 10. Okazało się że sprawa nie jestem całkiem prosta więc stwierdziłem że podzielę się tutaj napotkanymi przeze mnie problemami i ich rozwiązaniami.

Wszystkie testy przeprowadzałem na Windows 7 x64 i DirectX SDK August 2009. DirectX 11 będzie dostępny na systemie Windows Vista za pomocą platform update. Nie sprawdzałem postępu prac nad platform update i nie jestem w stanie powiedzieć czy aktualna wersja pozwoli uruchomić aplikacje DirectX 11.

Przerabiając aplikacje wyświetlającą trójkąt z dziesiątki na jedenastke trzeba zdać sobie sprawę z kilku rzeczy:

  • DirectX 11 wprowadza nowy model programowania wielowątkowego. W tym celu interfejs ID3D11Device został rozdzielony na dwa niezależne interfejsy ID3D11Device i i ID3D11DeviceContext. Dzięki temu drugiemu możliwe jest generowanie komend renderowania grafiki z wielu wątków.
  • D3DXMath został zastąpiony przez XnaMath. Zamiast np. D3DXVECTOR3 można użyć XMFLOAT3. XnaMath dostępne jest po dołączeniu xnamath.h
  • Effects są teraz dostępne jako projekt vc++ w katalogu DX SDK\Utilities\Source\Effects11. Należy je skompilować, najlepiej od razu wszystkie 4 warianty (x86 – x64, Debug – Release) aby później dołączyć header i plik lib do programu wyświetlającego trójkąt.
  • Nie istnieje funkcja do jednoczesnej kompilacji kodu hlsl i stworzenia efektu. Teraz należy najpierw skompilować shadery a później utworzyć effecty.
  • Kompilator shaderów obsługuje tylko format fx_5_0. Aby stworzyć kod zgodny z kartami DirectX 10 należy w definicji techniki przekazać odpowiedni parametr, np vs_4_0, ps_4_0.

To by było w zasadzie wszystko co jest potrzebne do wyświetlenia trójkąta w DirectX gdyby nie pewien mały problem. Przy obecnej wersji Effects w DX SDK  nie jest możliwe poprawne uruchomienie takiej aplikacji na karcie zgodnej z co najwyżej z DX10.1 (Z tego co mi wiadomo na Radeonach HD5xxx wszystko chodzi bardzo ładnie 😉 ) Problem jest opisany tutaj. Podane są tam dwa przykładowe rozwiązania. W skrócie podczas wywołania D3DX11CreateEffectFromMemory wywoływane są funkcje Create…Shader interfejsu ID3D11Device. Jednym z parametrów tych funkcji jest ID3D11ClassLinkage *pClassLinkage. Parametr ten w zależność od levelu: D3D_FEATURE_LEVEL_11_0 lub inny powinien zawierać poprawny wskaźnik lub być wartością NULL. Osobiście aby u siebie uzyskać działający profil D3D_FEATURE_LEVEL_10_0 i D3D_FEATURE_LEVEL_10_1 zamieniłem linie 1272 i 1273 w pliku EffectNonRuntime.cpp w projekcie Effects11 z:

else if( FAILED( (m_pDevice->*(pShader->pVT->pCreateShader))((UINT *) pShader->pReflectionData->pBytecode, pShader->pReflectionData->BytecodeLength,m_pClassLinkage, &pShader->pD3DObject) ) )
                pShader->IsValid = FALSE;

na

else if( FAILED( (m_pDevice->*(pShader->pVT->pCreateShader))((UINT *) pShader->pReflectionData->pBytecode, pShader->pReflectionData->BytecodeLength, 0, &pShader->pD3DObject) ) )
               pShader->IsValid = FALSE;

Należy pamiętać że w ten sposób wyłączam level 11_0. Dla mnie to w tej chwili nie jest problemem ponieważ testuje ten program tylko u siebie na sprzęcie zgodnym z DX10. Jeśli jednak potrzebujemy mieć działające wszystkie profile, możemy np. dodać parametr do tej funkcji i przekazać jawnie na którym levelu operujemy i wtedy dodać ifa wywołującego CreateShader z classlinkage albo bez lub np próbować tworzyć shader najpierw z classlinkage a w razie nie powodzenia bez.

Na koniec załączam zip z projektem stworzonym  w Visual Studio 2010 beta2 wyświetlającym piękny żółty trójkąt. Program działa u mnie poprawnie na karcie AMD (ATI) zgodnej z DX10.1 i NVIDII zgodnej z DX10. W przypadku próby kompilacji załączonego kodu w poprzednich wersjach VS wystarczy stworzyć projekt win32 C++, zaimportować pliki .h i .cpp, dodać w pliku dx11.h po includach

#define nullptr 0

(nullptr to taki ładny null z VC++ 10), upewnić się że vs ma dostęp do odpowiednich headerów i libów i dodać linkerowi liby: d3d11.lib d3dx11d.lib D3DX11EffectsD.lib D3DCompiler.lib w przypadku trybu Debug i d3d11.lib d3dx11.lib D3DX11Effects.lib D3DCompiler.lib w przypadku trybu Release.

DX11Triangle (3242)

d3d11.lib
d3dx11d.lib
D3DX11EffectsD.lib
D3DCompiler.lib

One Response to “Trójkąt w DirectX 11”

  1. Wojciech Gebczyk Says:
    Kwiecień 7th, 2010 at 7:45 pm

    „nullptr to taki ładny null z VC++ 10”
    nie koniecznie z VC…
    http://en.wikipedia.org/wiki/C%2B%2B0x#Null_pointer_constant

Leave a Reply