Komma igång (DirectXMath)
DirectXMath-biblioteket implementerar ett optimalt och portabelt gränssnitt för aritmetiska och linjära algebraåtgärder på flyttalvektorer med enkel precision (2D, 3D och 4D) eller matriser (3×3 och 4×4). Biblioteket har visst begränsat stöd för heltalsvektoroperationer. Dessa åtgärder används i stor utsträckning för rendering och animering av grafikprogram. Det finns inget stöd för dubbelprecisionsvektorer (inklusive longs, shorts eller bytes) och endast begränsade heltalsvektoroperationer.
Biblioteket finns på en mängd olika Windows-plattformar. Eftersom biblioteket innehåller funktioner som inte är tillgängliga tidigare ersätter den här versionen följande bibliotek:
- Xbox Math-biblioteket som tillhandahålls av headerfilen Xboxmath.h
- D3DX 9-biblioteket som tillhandahålls av D3DX 9 DLL:er
- D3DX 10-matematiskt bibliotek som tillhandahålls via D3DX 10 DLL:er
- XNA Math-biblioteket som tillhandahålls av xnamath.h-huvudet i DirectX SDK och Xbox 360 XDK
I de här avsnitten beskrivs grunderna för att komma igång.
- Ladda ned
- Run-Time systemkrav
- Designöversikt
- Matris-konvention
- Grundläggande användning
- Användning av Typ: Riktlinjer
- Skapa vektorer
- extrahera komponenter från vektorer
- Relaterade ämnen
Ladda ned
DirectXMath-biblioteket ingår i Windows SDK. Du kan också ladda ned den från GitHub/Microsoft/DirectXMath. Den här webbplatsen innehåller även relaterade exempelprojekt.
Run-Time systemkrav
DirectXMath-biblioteket använder specialiserade processorinstruktioner för vektoråtgärder när de är tillgängliga. Om du vill undvika att ett program genererar fel med "okänt instruktionsfel" kontrollerar du processorsupporten genom att anropa XMVerifyCPUSupport- innan du använder DirectXMath-biblioteket.
Det här är de grundläggande supportkraven för DirectXMath-bibliotekets körningstid:
- Standardkompilering på en Windows-plattform (x86/x64) kräver SSE/SSE2-instruktionsstöd.
- Standardkompliation på en Windows RT-plattform kräver ARM-NEON instruktionsstöd.
- Kompilering med _XM_NO_INTRINSICS_ definierad kräver endast standardstöd för flyttalsåtgärd.
Not
När du anropar XMVerifyCPUSupportska du ta med <windows.h> innan du inkluderar <DirectXMath.h>. Det här är den enda funktionen i biblioteket som kräver innehåll från <windows.h> så du behöver inte inkludera <windows.h> i varje modul som använder <DirectXMath.h>.
Designöversikt
DirectXMath-biblioteket stöder främst programmeringsspråket C++. Biblioteket implementeras med hjälp av infogade rutiner i huvudfilerna DirectXMath*.inl, DirectXPackedVector.inl och DirectXCollision.inl. Den här implementeringen använder sig av högpresterande kompilatorintrinsiker.
DirectXMath-biblioteket tillhandahåller:
- En implementering med hjälp av inbyggda SSE/SSE2-funktioner.
- En implementering utan inbyggda funktioner.
- En implementering med hjälp av ARM-NEON inbyggda funktioner.
Eftersom biblioteket levereras med hjälp av huvudfiler använder du källkoden för att anpassa och optimera för din egen app.
Matriskonvention
DirectXMath använder radmatriser, radvektorer och pre-multiplikation. Handedness bestäms av vilken funktionsversion som används (RH vs. LH), annars fungerar funktionen med vykoordinater för antingen vänster- eller högerhänta.
Som referens har Direct3D historiskt använt vänsterkoordinatsystem, radmatriser, radvektorer och pre-multiplikation. Modern Direct3D har inget starkt krav på vänster-/högerhänta koordinater, och HLSL-shaders brukar vanligtvis konsumera kolumnhuvudmatriser. Mer information finns i HLSL-matrisordning.
Grundläggande användning
Om du vill använda DirectXMath-biblioteksfunktioner inkluderar du DirectXMath.h, DirectXPackedVector.h, DirectXColors.h och/eller DirectXCollision.h-huvuden. Rubrikerna finns i Windows Software Development Kit för Windows Store-appar.
Riktlinjer för typanvändning
XMVECTOR och XMMATRIX typer är arbetshästar för DirectXMath-biblioteket. Varje åtgärd förbrukar eller genererar data av dessa typer. Att arbeta med dem är nyckeln till att använda biblioteket. Men eftersom DirectXMath använder SIMD-instruktionsuppsättningarna omfattas dessa datatyper av ett antal begränsningar. Det är viktigt att du förstår dessa begränsningar om du vill använda DirectXMath-funktionerna på ett bra sätt.
Du bör tänka på XMVECTOR- som proxy för ett SIMD-maskinvaruregister och XMMATRIX- som proxy för en logisk gruppering av fyra SIMD-maskinvaruregister. Dessa typer kommenteras för att indikera att de kräver justering på 16 byte för att fungera korrekt. Kompilatorn placerar dem automatiskt på stacken när de används som en lokal variabel eller placerar dem i datasegmentet när de används som en global variabel. Med rätt konventioner kan de också skickas på ett säkert sätt som parametrar till en funktion (se Samtalskonventioner för mer information).
Allokeringar från högen är dock mer komplicerade. Därför måste du vara försiktig när du använder antingen XMVECTOR- eller XMMATRIX- som medlem i en klass eller struktur som ska allokeras från heapen. På Windows x64 är alla heap-allokeringar 16 byte alignerade, men för Windows x86 är de bara 8 byte alignerade. Det finns alternativ för att allokera strukturer från heapen med 16 bytes justering (se Korrekt justera allokeringar). För C++-program kan du använda operatorn new/delete/new[]/delete[] overloads (antingen globalt eller klassspecifik) för att framtvinga optimal justering om så önskas.
Anteckning
Som ett alternativ till att framtvinga justering i C++-klassen direkt genom att överbelasta ny/ta bort kan du använda pImpl idiom. Om du ser till att klassen Impl är justerad via _aligned_malloc internt kan du sedan fritt använda justerade typer i den interna implementeringen. Det här är ett bra alternativ när klassen "public" är en Windows Runtime ref-klass eller är avsedd för användning med std::shared_ptr<>, som annars kan störa noggrann justering.
Men ofta är det enklare och mer kompakt att undvika att använda XMVECTOR eller XMMATRIX direkt i en klass eller struktur. Använd i stället XMFLOAT3, XMFLOAT4, XMFLOAT4X3, XMFLOAT4X4och så vidare som medlemmar i din struktur. Dessutom kan du använda funktionerna Vector Loading och Vector Storage för att flytta data effektivt till XMVECTOR- eller XMMATRIX lokala variabler, utföra beräkningar och lagra resultaten. Det finns också strömningsfunktioner (XMVector3TransformStream, XMVector4TransformStreamoch så vidare) som effektivt fungerar direkt på matriser av dessa datatyper.
Skapa vektorer
KONSTANTA VEKTORER
Många åtgärder kräver användning av konstanter i vektorberäkningar, och det finns ett antal sätt att läsa in en XMVECTOR- med önskade värden.
Om du laddar in en skalär konstant i alla element i en XMVECTOR-, ska du använda XMVectorReplicate eller XMVectorReplicateInt.
XMVECTOR vFive = XMVectorReplicate( 5.f );
Om du använder en vektorkonstant med olika fasta värden som en XMVECTOR-använder du strukturerna XMVECTORF32, XMVECTORU32, XMVECTORI32eller XMVECTORU8. Dessa kan sedan refereras direkt var som helst där du använder ett XMVECTOR--värde.
static const XMVECTORF32 vFactors = { 1.0f, 2.0f, 3.0f, 4.0f };
Not
Använd inte initierarlistor direkt med XMVECTOR- (dvs. XMVECTOR v = { 1,0f, 2,0f, 3,0f, 4,0f }). Sådan kod är ineffektiv och är inte portabel på alla plattformar som stöds av DirectXMath.
DirectXMath innehåller ett antal fördefinierade globala konstanter som du kan använda i koden (g_XMOne, g_XMOne3, g_XMTwo, g_XMOneHalf, g_XMHalfPi, g_XMPi och så vidare). Sök i DirectXMath.h-huvudet efter XMGLOBALCONST- värden.
Det finns en uppsättning vektorkonstanter för vanliga RGB-färger (röd, grön, blå, gul och så vidare). Mer information om dessa vektorkonstanter finns i DirectXColors.h och namnområdet DirectX::Colors.
VEKTORER FRÅN VARIABLER
Om du skapar en vektor från en enda skalär variabel kan du läsa XMVectorReplicate och XMVectorReplicateInt.
XMVECTOR v = XMVectorReplicate( f );
Om du skapar en vektor från fyra skalärvariabler kan du läsa XMVectorSet och XMVectorSetInt.
XMVECTOR v = XMVectorSet( fx, fy, fz, fw );
VEKTORER FRÅN VEKTORER
Om du skapar en vektor från en annan vektor med en specifik komponent inställd på en variabel kan du använda Vector Accessor Functions.
XMVECTOR v2 = XMVectorSetW( v1, fw );
Om du skapar en vektor från en annan vektor med en enskild komponent replikerad använder du XMVectorSplatX, XMVectorSplatY, XMVectorSplatZoch XMVectorSplatW.
XMVECTOR vz = XMVectorSplatZ( v );
Om du skapar en vektor från en annan vektor eller en uppsättning vektorer med omordnade komponenter, se XMVectorSwizzle och XMVectorPermute.
XMVECTOR v2 = XMVectorSwizzle<XM_SWIZZLE_Z, XM_SWIZZLE_Y, XM_SWIZZLE_W, XM_SWIZZLE_X>( v1 ); XMVECTOR v3 = XMVectorPermute<XM_PERMUTE_0W, XM_PERMUTE_1X, XM_PERMUTE_0X, XM_PERMUTE_1Z>( v1, v2 );
VEKTORER FRÅN MINNET
- För att ladda ett enkelt flyttalsvärde från minnet, se XMVectorReplicatePtr, XMVectorReplicateIntPtr, XMLoadFloatoch XMLoadInt.
- Vanliga sätt att läsa in flyttalsmatriser är: XMLoadFloat2, XMLoadFloat3, XMLoadFloat4, XMLoadFloat3x3, XMLoadFloat4x3och XMLoadFloat4x4.
- DirectXMath innehåller en omfattande uppsättning typer och relaterade belastningar och lager för hantering av olika datastrukturer och vanliga GPU-format. Se Vector Load och Vector Store.
Extrahera komponenter från vektorer
SIMD-bearbetning är mest effektiv när data läses in i SIMD-register och bearbetas fullständigt innan resultatet extraheras. Konverteringen mellan skalär- och vektorformulär är ineffektiv, så vi rekommenderar att du bara gör det när det behövs. Därför returneras funktioner i DirectXMath-biblioteket som producerar ett skalärt värde i en vektorform där det skalära resultatet replikeras över den resulterande vektorn (det vill XMVector2Dot, XMVector3Lengthoch så vidare). Men när du behöver skalära värden finns här några alternativ för hur du gör:
Om ett enda skalärt svar beräknas är det lämpligt att använda Vector Accessor Functions:
float f = XMVectorGetX( v );
Om flera komponenter i vektorn måste extraheras bör du överväga att lagra vektorn i en minnesstruktur och läsa tillbaka den. Till exempel:
XMFLOAT4A t; XMStoreFloat4A( &t, v ); // t.x, t.y, t.z, and t.w can be individually accessed now
Den mest effektiva formen av vektorbearbetning är att använda strömning från minne till minne där indata läses in från minnet (med hjälp av Vector Load Functions), bearbetas helt i SIMD-form och sedan skrivs till minnet (med Vector Store Functions).
Relaterade ämnen