Sign in to follow this  
cozzie

DX11 Moving to DirectXMath

Recommended Posts

cozzie    5029
Hi,
I'm at the point where my codebase is growing larger and larger.
Since I'm still on dx9 and plan to move to / also support dx11, I'm thinking about moving from using d3dx to directxmath. Especially because I'm expanding my codebase with quite some math related stuff (collisions and intersections).

My question is basically what your advice would be, pro's and cons
(will directxmath work fine both with dx9 and 11? Etc)

Ps: for mesh usage and loading for now I'll stick to d3dxmesh, will change that later on. Above I'm aiming at basically ALL other d3dx usage in my engine.

Share this post


Link to post
Share on other sites
Alessio1989    4634

DirectXMath is not directly related to Direct3D/DXGI/WDDM stuffs, so you can use it with both DX9 and DX11, work with both X86 (IA32/SSE/SSE2/x64) and ARM (with ARM NEON support).

It is pretty easy to use, you only need to pay attention to data alignment of vector and matrix structures  (you can disable the alignment requirement if you want with the _XM_NO_INTRINSICS_ macro).

 

On MSDN library you can find a pretty decent programming guide (with migration notes from D3DXMath and compatibility tables with D3DDECLTYPE, D3DFORMAT and DXGI_FORMAT).

 

The reference guide is pretty decent too, however you had to pay attention if you are using the RH coordinate system since some function without the proper coordinate system suffix need some attention (like the function involving axis... see the "remark" paragraph of related reference guide).

 

On directx sdk blog you can find some additional x86 SIMD extensions (SSE3/3S/4./4.1, AVX, FMA3/4, F16C...), they are linked somewhere on msdn library too.

 

DirectX Tool Kit has a DirectXMath wrapper too if you find it too much complicated.

Edited by Alessio1989

Share this post


Link to post
Share on other sites
SeanMiddleditch    17565

(you can disable the alignment requirement if you want with the _XM_NO_INTRINSICS_ MAXRO).


There is no good reason to do this. XMVECTOR is _not_ meant for storing in general heap-allocated objects. It's for doing computations in local variables or special-purpose buffers. Use XMFLOAT2/3/4 for storing data in heap-allocated objects. Using strict alignment is a performance win but not at all mandatory if the DirectXMath library if used correctly.

Share this post


Link to post
Share on other sites
Alessio1989    4634

 

(you can disable the alignment requirement if you want with the _XM_NO_INTRINSICS_ MAXRO).


There is no good reason to do this. XMVECTOR is _not_ meant for storing in general heap-allocated objects. It's for doing computations in local variables or special-purpose buffers. Use XMFLOAT2/3/4 for storing data in heap-allocated objects. Using strict alignment is a performance win but not at all mandatory if the DirectXMath library if used correctly.

 

 

A good reason could be immediately starting using DirectXMath and become familiar with it, avoiding awkward alignments (like _aligned_mallc plus placement new) if you planned to write your own custom allocator (maybe with different platforms-specific intrinsics) but you don't have it yet ready. When your custom allocator is done and it's ready to use, you will just need to remove that macro.

Edited by Alessio1989

Share this post


Link to post
Share on other sites
cozzie    5029
Thanks. I'll probably move on to using directxmath asap.
When I read stuff about intrinsics, macro's etc., honestly I'm not connected.

Maybe I'm thinking too simple, but I believe these are the main things I have to do
- replace all class members of type D3DXVECTOR3 by XMFLOAT3's
- do the same for local D3DXVECTOR3's, which are created on the stack/ within scope of (member) functions
- do the above again, but for D3DXMATRIX to XMFLOAT4X4
- remove all includes of d3dx9(d).h, except in my mesh class header and cpp file
- compile and replace all uses d3dxfunctions by the directxmath replacement, throughout my codebase

Ofcourse I'll run into some minor bumps, but I believe this should be it.
For now I don't see reasons to use XMVECTOR or XMMATRIX instead, based on the MSDN reference I read. I currently also don't use the D3DX.....16 types, for alignment, because I don't have specific reasons to do so (no pre-optimizations wasting time and increasing future risks).

But... If I'm overseeing something, please tell me

Share this post


Link to post
Share on other sites
Buckeye    10747

You've pretty much covered a lot. I recently switched from DX9 to D3D11. I've converted quite a few classes using just the method you described.

 

A couple of times I did a search/replace-all in a file for the classes you named and hit the compile key to let VS locate needed corrections. You will need to use XMVECTOR and XMMATRIX for calcs but you'll pick that up pretty quickly. E.g.,

D3DXMATRIX mat1, mat2, mat3;
mat3 = mat1 * mat2;

becomes

XMFLOAT4X4 mat1, mat2, mat3;
XMStoreFloat4x4(&mat3, XMMatrixMultiply(XMLoadFloat4x4(&mat1),XMLoadFloat4x4(&mat2));

That will come pretty quickly to you, I believe.

Share this post


Link to post
Share on other sites
Alessio1989    4634

Thanks. I'll probably move on to using directxmath asap.
When I read stuff about intrinsics, macro's etc., honestly I'm not connected.

Maybe I'm thinking too simple, but I believe these are the main things I have to do
- replace all class members of type D3DXVECTOR3 by XMFLOAT3's
- do the same for local D3DXVECTOR3's, which are created on the stack/ within scope of (member) functions
- do the above again, but for D3DXMATRIX to XMFLOAT4X4
- remove all includes of d3dx9(d).h, except in my mesh class header and cpp file
- compile and replace all uses d3dxfunctions by the directxmath replacement, throughout my codebase

Ofcourse I'll run into some minor bumps, but I believe this should be it.
For now I don't see reasons to use XMVECTOR or XMMATRIX instead, based on the MSDN reference I read. I currently also don't use the D3DX.....16 types, for alignment, because I don't have specific reasons to do so (no pre-optimizations wasting time and increasing future risks).

But... If I'm overseeing something, please tell me

XMFLOAT* structures don't require any particular alignment and they are meant to be used for simple tasks and getting/settings data.
 
XMVECTOR and XMMATRIX take advantage of CPU SIMD so they are meant to be used for computation and most useful DirectXMath function need and use XMVECTOR and XMMATRIX.
 
They require 16-byte alignment in order to use CPU SIMD extensions like SSE2 and ARM NEON. For automatic allocation (data and stack) you only need to add the /Zp16 compiler flag, for dynamic allocation you need to manually it manually (like _aligned_malloc + placement new) or to write your own custom allocator.
 
If 16-byte alignment is a problem for you or a pre-optimization wasting time just declare the _XM_NO_INTRINSICS_ macro, and everything will run fine.
 
Here you can find a direct D3DX-DirectXMath comparison and migration guide: http://msdn.microsoft.com/en-us/library/windows/desktop/ff729728(v=vs.85).aspx Edited by Alessio1989

Share this post


Link to post
Share on other sites
cozzie    5029
Thanks. I've read the programming guide on MSDN.
There are some blanks for me. Are these conclusions correct:

- my goal is to make advantage of computation advantages (SSE intrinsics etc.)
- having a good balance, without having to use macro's or manual alignment code

I'll do this by:
- making class members of the types XMFLOATx and XMFLOATxXx
(for alignment reasons)
- for local variables in scope of functions I use XMVECTOR and XMMATRIX types, to take advantage of better computation (SSE etc.) without casting
-- when I need to use, either read or write to the class members of XMFLOAT... type, I always have to cast them to XMVECTOR/XMMATRIX types, when I want to use the DirectXMath functions. I probably also need to "cast" the results back into the class members

This sounds doable.

Till now I always used D3DX and build up a code base for frustum culling, bounding volume checks (intersection/ collision) etc. Besides the math I've learned doing this, I'm thinking about using the functions that do the same coming from the DirectXMath library. What do you think?

Another assumption I have to check, is that I can pass both XMFLOAT (class members in my case) as XMVECTOR/MATRIX type to set shader constants (for now with d3d9, later on d3d11). Now I think of it, I also have to find a solution when not using the d3dx effect framework anymore. Probably compiling the PS and VS manually. The good thing is that I don't set any states through my effects (I use my own state manager for that, through my code).

Share this post


Link to post
Share on other sites
Alessio1989    4634

- my goal is to make advantage of computation advantages (SSE intrinsics etc.)

Then you need 16-byte aligment.
 

- having a good balance, without having to use macro's or manual alignment code

Then you need to define and code your own allocator.
 

- making class members of the types XMFLOATx and XMFLOATxXx
(for alignment reasons)

XMFLOATx and XMFLOAtxXx don't need 16-byte aligment.
 

- for local variables in scope of functions I use XMVECTOR and XMMATRIX types, to take advantage of better computation (SSE etc.) without casting

Remember that /Zp16 must be used setted, you can find the option in the C++ /Code generation tab in the project proprieties.
 

-- when I need to use, either read or write to the class members of XMFLOAT... type, I always have to cast them to XMVECTOR/XMMATRIX types, when I want to use the DirectXMath functions. I probably also need to "cast" the results back into the class members

DirectXMath provides loading and storing function for that : )
 

Till now I always used D3DX and build up a code base for frustum culling, bounding volume checks (intersection/ collision) etc. Besides the math I've learned doing this, I'm thinking about using the functions that do the same coming from the DirectXMath library. What do you think?

Aside from data alignment, DirectXMath is a natural evolution of D3DX, you should not having particular problem to convert the code.
 

Another assumption I have to check, is that I can pass both XMFLOAT (class members in my case) as XMVECTOR/MATRIX type to set shader constants (for now with d3d9, later on d3d11). Now I think of it, I also have to find a solution when not using the d3dx effect framework anymore. Probably compiling the PS and VS manually. The good thing is that I don't set any states through my effects (I use my own state manager for that, through my code).

Dunno if XMVECTOR could be passed directly to shaders(I always used XMFLOAT* for getting and settings data), however XMMATRIX could bepassed as D3D11_MAPPED_SUBRESOURCE.pData. Edited by Alessio1989

Share this post


Link to post
Share on other sites
Adam_42    3629


Remember that /Zp16 must be used setted

 

You don't need /Zp16 at all. The vector types are already set up with __declspec(align(16)) so they will get 16 byte aligned as local/global/static variables without any need for compiler flags. The only time you need to worry about alignment is on heap allocated data.

 

http://blogs.msdn.com/b/oldnewthing/archive/2007/12/27/6873648.aspx

Share this post


Link to post
Share on other sites
Alessio1989    4634

Remember that /Zp16 must be used setted

 
You don't need /Zp16 at all. The vector types are already set up with __declspec(align(16)) so they will get 16 byte aligned as local/global/static variables without any need for compiler flags. The only time you need to worry about alignment is on heap allocated data.
 
http://blogs.msdn.com/b/oldnewthing/archive/2007/12/27/6873648.aspx

 
XMMATRIX and opaque vectors (XMVECTORF32, XMVECTORI32, XMVECTORU8, XMVECTORU32) are defined with __declspec(align(16)) , but not XMVECTOR:
 
//------------------------------------------------------------------------------
// Vector intrinsic: Four 32 bit floating point components aligned on a 16 byte 
// boundary and mapped to hardware vector registers
#if defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_)
typedef __m128 XMVECTOR;
#elif defined(_XM_ARM_NEON_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_)
typedef __n128 XMVECTOR;
#else
typedef __vector4 XMVECTOR;
#endif
EDIT: you're right  : = 0
 
__m128 is 16-byte aligned
typedef union __declspec(intrin_type) _CRT_ALIGN(16) __m128 {
     float               m128_f32[4];
     unsigned __int64    m128_u64[2];
     __int8              m128_i8[16];
     __int16             m128_i16[8];
     __int32             m128_i32[4];
     __int64             m128_i64[2];
     unsigned __int8     m128_u8[16];
     unsigned __int16    m128_u16[8];
     unsigned __int32    m128_u32[4];
 } __m128;
where _CRT_ALIGN(16) is an alias of the CRT

#define _CRT_ALIGN(x) __declspec(align(x))
nice to know that : p Edited by Alessio1989

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Similar Content

    • By gsc
      Hi! I am trying to implement simple SSAO postprocess. The main source of my knowledge on this topic is that awesome tutorial.
      But unfortunately something doesn't work... And after a few long hours I need some help. Here is my hlsl shader:
      float3 randVec = _noise * 2.0f - 1.0f; // noise: vec: {[0;1], [0;1], 0} float3 tangent = normalize(randVec - normalVS * dot(randVec, normalVS)); float3 bitangent = cross(tangent, normalVS); float3x3 TBN = float3x3(tangent, bitangent, normalVS); float occlusion = 0.0; for (int i = 0; i < kernelSize; ++i) { float3 samplePos = samples[i].xyz; // samples: {[-1;1], [-1;1], [0;1]} samplePos = mul(samplePos, TBN); samplePos = positionVS.xyz + samplePos * ssaoRadius; float4 offset = float4(samplePos, 1.0f); offset = mul(offset, projectionMatrix); offset.xy /= offset.w; offset.y = -offset.y; offset.xy = offset.xy * 0.5f + 0.5f; float sampleDepth = tex_4.Sample(textureSampler, offset.xy).a; sampleDepth = vsPosFromDepth(sampleDepth, input.uv).z; const float threshold = 0.025f; float rangeCheck = abs(positionVS.z - sampleDepth) < ssaoRadius ? 1.0 : 0.0; occlusion += (sampleDepth <= samplePos.z + threshold ? 1.0 : 0.0) * rangeCheck; } occlusion = saturate(1 - (occlusion / kernelSize)); And current result: http://imgur.com/UX2X1fc
      I will really appreciate for any advice!
    • By isu diss
       I'm trying to code Rayleigh part of Nishita's model (Display Method of the Sky Color Taking into Account Multiple Scattering). I get black screen no colors. Can anyone find the issue for me?
       
      #define InnerRadius 6320000 #define OutterRadius 6420000 #define PI 3.141592653 #define Isteps 20 #define Ksteps 10 static float3 RayleighCoeffs = float3(6.55e-6, 1.73e-5, 2.30e-5); RWTexture2D<float4> SkyColors : register (u0); cbuffer CSCONSTANTBUF : register( b0 ) { float fHeight; float3 vSunDir; } float Density(float Height) { return exp(-Height/8340); } float RaySphereIntersection(float3 RayOrigin, float3 RayDirection, float3 SphereOrigin, float Radius) { float t1, t0; float3 L = SphereOrigin - RayOrigin; float tCA = dot(L, RayDirection); if (tCA < 0) return -1; float lenL = length(L); float D2 = (lenL*lenL) - (tCA*tCA); float Radius2 = (Radius*Radius); if (D2<=Radius2) { float tHC = sqrt(Radius2 - D2); t0 = tCA-tHC; t1 = tCA+tHC; } else return -1; return t1; } float RayleighPhaseFunction(float cosTheta) { return ((3/(16*PI))*(1+cosTheta*cosTheta)); } float OpticalDepth(float3 StartPosition, float3 EndPosition) { float3 Direction = normalize(EndPosition - StartPosition); float RayLength = RaySphereIntersection(StartPosition, Direction, float3(0, 0, 0), OutterRadius); float SampleLength = RayLength / Isteps; float3 tmpPos = StartPosition + 0.5 * SampleLength * Direction; float tmp; for (int i=0; i<Isteps; i++) { tmp += Density(length(tmpPos)-InnerRadius); tmpPos += SampleLength * Direction; } return tmp*SampleLength; } static float fExposure = -2; float3 HDR( float3 LDR) { return 1.0f - exp( fExposure * LDR ); } [numthreads(32, 32, 1)] //disptach 8, 8, 1 it's 256 by 256 image void ComputeSky(uint3 DTID : SV_DispatchThreadID) { float X = ((2 * DTID.x) / 255) - 1; float Y = 1 - ((2 * DTID.y) / 255); float r = sqrt(((X*X)+(Y*Y))); float Theta = r * (PI); float Phi = atan2(Y, X); static float3 Eye = float3(0, 10, 0); float ViewOD = 0, SunOD = 0, tmpDensity = 0; float3 Attenuation = 0, tmp = 0, Irgb = 0; //if (r<=1) { float3 ViewDir = normalize(float3(sin(Theta)*cos(Phi), cos(Theta),sin(Theta)*sin(Phi) )); float ViewRayLength = RaySphereIntersection(Eye, ViewDir, float3(0, 0, 0), OutterRadius); float SampleLength = ViewRayLength / Ksteps; //vSunDir = normalize(vSunDir); float cosTheta = dot(normalize(vSunDir), ViewDir); float3 tmpPos = Eye + 0.5 * SampleLength * ViewDir; for(int k=0; k<Ksteps; k++) { float SunRayLength = RaySphereIntersection(tmpPos, vSunDir, float3(0, 0, 0), OutterRadius); float3 TopAtmosphere = tmpPos + SunRayLength*vSunDir; ViewOD = OpticalDepth(Eye, tmpPos); SunOD = OpticalDepth(tmpPos, TopAtmosphere); tmpDensity = Density(length(tmpPos)-InnerRadius); Attenuation = exp(-RayleighCoeffs*(ViewOD+SunOD)); tmp += tmpDensity*Attenuation; tmpPos += SampleLength * ViewDir; } Irgb = RayleighCoeffs*RayleighPhaseFunction(cosTheta)*tmp*SampleLength; SkyColors[DTID.xy] = float4(Irgb, 1); } }  
    • By amadeus12
      I made my obj parser
      and It also calculate tagent space for normalmap.
      it seems calculation is wrong..
      any good suggestion for this?
      I can't upload my pics so I link my question.
      https://gamedev.stackexchange.com/questions/147199/how-to-debug-calculating-tangent-space
      and I uploaded my code here


      ObjLoader.cpp
      ObjLoader.h
    • By Alessandro Pozzer
      Hi guys, 

      I dont know if this is the right section, but I did not know where to post this. 
      I am implementing a day night cycle on my game engine and I was wondering if there was a nice way to interpolate properly between warm colors, such as orange (sunset) and dark blue (night) color. I am using HSL format.
      Thank  you.
    • By thefoxbard
      I am aiming to learn Windows Forms with the purpose of creating some game-related tools, but since I know absolutely nothing about Windows Forms yet, I wonder:
      Is it possible to render a Direct3D 11 viewport inside a Windows Form Application? I see a lot of game editors that have a region of the window reserved for displaying and manipulating a 3D or 2D scene. That's what I am aiming for.
      Otherwise, would you suggest another library to create a GUI for game-related tools?
       
      EDIT:
      I've found a tutorial here in gamedev that shows a solution:
      Though it's for D3D9, I'm not sure if it would work for D3D11?
       
  • Popular Now