demoii16_3.cpp
上传用户:husern
上传日期:2018-01-20
资源大小:42486k
文件大小:15k
源码类别:

游戏

开发平台:

Visual C++

  1. // DEMOII16_3.CPP - SIMD demo, contains class and demo code
  2. // I N C L U D E S ///////////////////////////////////////////////////////////
  3. #define INITGUID
  4. #define WIN32_LEAN_AND_MEAN  
  5. #include <windows.h>   // include important windows stuff
  6. #include <windowsx.h> 
  7. #include <mmsystem.h>
  8. #include <objbase.h>
  9. #include <iostream.h> // include important C/C++ stuff
  10. #include <conio.h>
  11. #include <stdlib.h>
  12. #include <malloc.h>
  13. #include <memory.h>
  14. #include <string.h>
  15. #include <stdarg.h> 
  16. #include <stdio.h>
  17. #include <math.h> 
  18. #include <io.h> 
  19. #include <fcntl.h> 
  20. #include <direct.h>
  21. #include <wchar.h>
  22. #include <limits.h>
  23. #include <float.h>
  24. #include <xmmintrin.h>
  25. #include <emmintrin.h>
  26. #include <fvec.h>
  27. // DEFINES ////////////////////////////////////////////////////////////////////
  28. // below is a simple macro to help build up the shuffle control word used by the 
  29. // shuffle class instructions shufps*
  30. // basically there are 4 bit fields each field encodes the source double
  31. // word to move from source to destination, and destination to destination
  32. // it's all very confusing, but in essence when the shufps instruction is used:
  33. //
  34. // shufps xmm_dest, xmm_src, control_flags
  35. //
  36. // xmm_dest is the destination SIMD register and xmm_src is the source SIMD
  37. // register. The tricky part is how the instructions works (refer to intel
  38. // manual for more detail), basically the instruction takes 2 of the 4 words
  39. // from the source register and places them in the destination register hi words
  40. // and also takes 2 of the 4 words from the destination register and places
  41. // them in the low words of the destination register! So the destination is used
  42. // as a "source" and a destination -- but just think of the source and destination
  43. // registers as both being sources and the final result just happens to be STORED
  44. // in one of the source registers at the END of the process
  45. // in any case, the bit encoding to select a particular 32-bit word from either the 
  46. // source or destination are:
  47. // 00 - selects word 0
  48. // 01 - selects word 1
  49. // 10 - selects word 2
  50. // 11 - selects word 3  
  51. // the the control_flags has the following encoding:
  52. // (high bit) A1A0 B1B0 C1C0 D1D0 (low bit)
  53. // 
  54. //  bits  operation
  55. //
  56. //  D1D0  Selects the 32-word from the DESTination operand and places it in the (low) word 0 of the result
  57. //  C1C0  Selects the 32-word from the DESTination operand and places it in the word 1 of the result    
  58. //  B1B0  Selects the 32-word from the SOURce operand and places it in the word 2 of the result    
  59. //  A1A0  Selects the 32-word from the SOURce operand and places it in the (hi) word 3 of the result    
  60. // and the parameters for the macro map these as follows:
  61. // 
  62. // srch - A1A0
  63. // srcl - B1B0
  64. // desth - C1C0
  65. // destl - D1D0
  66. // this is all in the intel "IA-32 Intel Architecture Software Developer Manual: Vol II"
  67. #define SIMD_SHUFFLE(srch,srcl,desth,destl) (((srch) << 6) | ((srcl) << 4) 
  68.                                             | ((desth) << 2) | ((destl)))
  69. // enable the final output type by setting one of these to 1 (the rest MUST be 0!)
  70. #define SIMD_INTRISIC      0
  71. #define SIMD_ASM           1
  72. // CLASESS ////////////////////////////////////////////////////////////////////
  73. // this is the new vector class that supports SIMD sse, note the numerous ways we 
  74. // can access the data members, this allows transparent support of assignments,
  75. // data access, and intrinsic library use without lots of casts
  76. class C_VECTOR4D
  77. {
  78. public:
  79. union
  80.     {
  81.     __declspec(align(16)) __m128 v;   // SIMD data type access
  82.     float M[4];                       // array indexed storage
  83.     // explicit names
  84.     struct
  85.          {
  86.          float x,y,z,w;
  87.          }; // end struct
  88.     }; // end union
  89. // note: the declspec is redundant since in the type __m128 forces
  90. // the compiler to align in 16-byte boundaries, so as long as __m128 is 
  91. // part of the union declspec is NOT needed :) But, it can't 
  92. // hurt and when you are defining locals and globals, always put 
  93. // declspec(align(16)) to KNOW data is on 16-byte boundaries
  94. // CONSTRUCTORS //////////////////////////////////////////////////////////////
  95. C_VECTOR4D() 
  96. {
  97. // void constructor
  98. // initialize vector to 0.0.0.1
  99. x=y=z=0; w=1.0;
  100. } // end C_VECTOR4D
  101. //////////////////////////////////////////////////////////////////////////////
  102. C_VECTOR4D(float _x, float _y, float _z, float _w = 1.0) 
  103. {
  104. // initialize vector to sent values
  105. x = _x;
  106. y = _y;
  107. z = _z;
  108. w = _w;
  109. } // end C_VECTOR4D
  110. // FUNCTIONS ////////////////////////////////////////////////////////////////
  111. void init(float _x, float _y, float _z, float _w = 1.0) 
  112. {
  113. // initialize vector to sent values
  114. x = _x;
  115. y = _y;
  116. z = _z;
  117. w = _w;
  118. } // end init
  119. //////////////////////////////////////////////////////////////////////////////
  120. void zero(void)
  121. {
  122. // initialize vector to 0.0.0.1
  123. x=y=z=0; w=1.0;
  124. } // end zero
  125. //////////////////////////////////////////////////////////////////////////////
  126. float length(void)
  127. {
  128. // computes the length of the vector
  129. C_VECTOR4D vr = *this;
  130. // set w=0
  131. vr.w = 0;
  132. // compile pure asm version?
  133. #if (SIMD_ASM==1)
  134. // begin inline asm version of SIMD dot product since we need its 
  135. // results for the length since length = sqrt(v*v)
  136. _asm
  137.    {
  138.    // first we need dot product of this*this
  139.    movaps xmm0, vr.v   // move left operand into xmm0
  140.    mulps xmm0, xmm0    // multiply operands vertically
  141.    
  142.    // at this point, xmm0  = 
  143.    // [ (v1.x * v2.x), (v1.y * v2.y), (v1.z * v2.z), (1*1) ]
  144.    // or more simply: let xmm0 = [x,y,z,1] = 
  145.    // [ (v1.x * v2.x), (v1.y * v2.y), (v1.z * v2.z), (1*1) ]
  146.    // we need to sum the x,y,z components into a single scalar
  147.    // to compute the final dot product of:
  148.    // dp = x + y + z == x1*x2 + y1*y2 + z1*z2
  149.    // begin 
  150.    // xmm0: = [x,y,z,1] (note: all regs in low to hight order)
  151.    // xmm1: = [?,?,?,?]
  152.    movaps xmm1, xmm0 // copy result into xmm1
  153.    // xmm0: = [x,y,z,1]
  154.    // xmm1: = [x,y,z,1]
  155.    shufps xmm1, xmm0, SIMD_SHUFFLE(0x01,0x00,0x03,0x02) 
  156.    // xmm0: = [x,y,z,1]
  157.    // xmm1: = [z,1,x,y]
  158.    addps xmm1, xmm0
  159.    // xmm0: = [x  ,y  ,z  ,1]
  160.    // xmm1: = [x+z,y+1,x+z,y+1]
  161.    shufps xmm0, xmm1, SIMD_SHUFFLE(0x02,0x03,0x00,0x01) 
  162.    // xmm0: = [y  ,x  ,y+1,x+z]
  163.    // xmm1: = [x+z,y+1,x+z,y+1]
  164.    // finally we can add!
  165.    addps xmm0, xmm1
  166.    // xmm0: = [x+y+z,x+y+1,x+y+z+1,x+y+z+1]
  167.    // xmm1: = [x+z  ,y+1  ,x+z    ,y+1]
  168.    // xmm0.x contains the dot product
  169.    // xmm0.z, xmm0.w contains the dot+1
  170.    // now low double word contains dot product, let's take squaroot
  171.    sqrtss xmm0, xmm0
  172.  
  173.    movaps vr, xmm0 // save results
  174.    } // end asm
  175. #endif // end use inline asm version
  176. // compile intrinsic version?
  177. #if (SIMD_INTRISIC==1)
  178. #endif // end use intrinsic library version
  179. // return result
  180. return(vr.x);
  181. } // end length
  182. // OVERLOADED OPERATORS //////////////////////////////////////////////////////
  183. float& operator[](int index)
  184. {
  185. // return the ith element from the array
  186. return(M[index]);
  187. } // end operator[]
  188. //////////////////////////////////////////////////////////////////////////////
  189. C_VECTOR4D operator+(C_VECTOR4D &v)
  190. {
  191. // adds the "this" vector and the sent vector
  192. __declspec(align(16)) C_VECTOR4D vr; // used to hold result, aligned on 16 bytes
  193. // compile pure asm version?
  194. #if (SIMD_ASM==1)
  195. // begin inline asm version of SIMD add
  196. _asm
  197.    {
  198.    mov esi, this       // "this" contains a point to the left operand
  199.    mov edi, v          // v points to the right operand
  200.    movaps xmm0, [esi]  // esi points to first vector, move into xmm0
  201.    addps  xmm0, [edi]  // edi points to second vector, add it to xmm0
  202.     
  203.    movaps vr, xmm0     // move result into output vector
  204.    } // end asm
  205. #endif // end use inline asm version
  206. // compile intrinsic version?
  207. #if (SIMD_INTRISIC==1)
  208. vr.v = _mm_add_ps(this->v, v.v);
  209. #endif // end use intrinsic library version
  210. // always set w=1
  211. vr.w = 1.0;
  212. // return result
  213. return(vr);
  214. } // end operator+
  215. //////////////////////////////////////////////////////////////////////////////
  216. C_VECTOR4D operator-(C_VECTOR4D &v)
  217. {
  218. // subtracts the "this" vector and the sent vector
  219. __declspec(align(16)) C_VECTOR4D vr; // used to hold result, aligned on 16 bytes
  220. // compile pure asm version?
  221. #if (SIMD_ASM==1)
  222. // begin inline asm version of SIMD add
  223. _asm
  224.    {
  225.    mov esi, this       // "this" contains a point to the left operand
  226.    mov edi, v          // v points to the right operand
  227.    movaps xmm0, [esi]  // esi points to first vector, move into xmm0
  228.    subps  xmm0, [edi]  // edi points to second vector, subtract it from xmm0
  229.     
  230.    movaps vr, xmm0     // move result into output vector
  231.    } // end asm
  232. #endif // end use inline asm version
  233. // compile intrinsic version?
  234. #if (SIMD_INTRISIC==1)
  235. vr.v = _mm_sub_ps(this->v, v.v);
  236. #endif // end use intrinsic library version
  237. // always set w=1
  238. vr.w = 1.0;
  239. // return result
  240. return(vr);
  241. } // end operator-
  242. //////////////////////////////////////////////////////////////////////////////
  243. float operator*(C_VECTOR4D &v)
  244. {
  245. // the dot product will be * since dot product is a more common operation
  246. // computes the dot between between the "this" vector and the sent vector
  247. __declspec(align(16)) C_VECTOR4D vr; // used to hold result, aligned on 16 bytes
  248. // compile pure asm version?
  249. #if (SIMD_ASM==1)
  250. // begin inline asm version of SIMD dot product
  251. _asm
  252.    {
  253.    mov esi, this       // "this" contains a point to the left operand
  254.    mov edi, v          // v points to the right operand
  255.    movaps xmm0, [esi]  // move left operand into xmm0
  256.    mulps xmm0,  [edi]  // multiply operands vertically
  257.    
  258.    // at this point, xmm0  = 
  259.    // [ (v1.x * v2.x), (v1.y * v2.y), (v1.z * v2.z), (1*1) ]
  260.    // or more simply: let xmm0 = [x,y,z,1] = 
  261.    // [ (v1.x * v2.x), (v1.y * v2.y), (v1.z * v2.z), (1*1) ]
  262.    // we need to sum the x,y,z components into a single scalar
  263.    // to compute the final dot product of:
  264.    // dp = x + y + z where x = x1*x2, y = y1*y2, z = z1*z2
  265.    // begin 
  266.    // xmm0: = [x,y,z,1] (note: all regs in low to hight order)
  267.    // xmm1: = [?,?,?,?]
  268.    movaps xmm1, xmm0 // copy result into xmm1
  269.    // xmm0: = [x,y,z,1]
  270.    // xmm1: = [x,y,z,1]
  271.    shufps xmm1, xmm0, SIMD_SHUFFLE(0x01,0x00,0x03,0x02) 
  272.    // xmm0: = [x,y,z,1]
  273.    // xmm1: = [z,1,x,y]
  274.    addps xmm1, xmm0
  275.    // xmm0: = [x  ,y  ,z  ,1]
  276.    // xmm1: = [x+z,y+1,x+z,y+1]
  277.    shufps xmm0, xmm1, SIMD_SHUFFLE(0x02,0x03,0x00,0x01) 
  278.    // xmm0: = [y  ,x  ,y+1,x+z]
  279.    // xmm1: = [x+z,y+1,x+z,y+1]
  280.    // finally we can add!
  281.    addps xmm0, xmm1
  282.    // xmm0: = [x+y+z,x+y+1,x+y+z+1,x+y+z+1]
  283.    // xmm1: = [x+z  ,y+1  ,x+z    ,y+1]
  284.    // xmm0.x contains the dot product
  285.    // xmm0.z, xmm0.w contains the dot+1
  286.    movaps vr, xmm0
  287.    } // end asm
  288. #endif // end use inline asm version
  289. // compile intrinsic version?
  290. #if (SIMD_INTRISIC==1)
  291. vr.v = _mm_mul_ps(this->v, v.v);
  292. return(vr.x + vr.y + vr.z);
  293. #endif // end use intrinsic library version
  294. // return result
  295. return(vr.x);
  296. } // end operator*
  297. //////////////////////////////////////////////////////////////////////////////
  298. void print(void)
  299. {
  300. // this member function prints out the vector
  301. printf("nv = [%f, %f, %f, %f]", this->x, this->y, this->z, this->w);
  302. } // end print
  303. //////////////////////////////////////////////////////////////////////////////
  304. };  // end class C_VECTOR4D
  305. // DEFINES /////////////////////////////////////////////////////////////////
  306. // TYPES ///////////////////////////////////////////////////////////////////
  307. // MACROS //////////////////////////////////////////////////////////////////
  308. // GLOBALS //////////////////////////////////////////////////////////////////
  309. HWND main_window_handle           = NULL; // save the window handle
  310. HINSTANCE main_instance           = NULL; // save the instance
  311.  
  312. // MAIN //////////////////////////////////////////////////////////////////
  313. void main()
  314. {
  315. // create some vectors
  316. C_VECTOR4D v1, v2, v3; // create some vectors
  317. // what kind of SIMD support do we have
  318. if (IsProcessorFeaturePresent(PF_MMX_INSTRUCTIONS_AVAILABLE))
  319.    printf("nMMX Available.");
  320. else
  321.    printf("nMMX NOT Available.");
  322. if (IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE))
  323.    printf("nXMMI Available.");
  324. else
  325.    printf("nXMMI NOT Available.");
  326. int sel = 0;
  327. // enter main loop
  328. while(1)
  329.      {
  330.      printf("nnSIMD Demo Main Menun");
  331.      printf("n1 - Print out all vectors v1, v2, v3");
  332.      printf("n2 - Enter values for v1");
  333.      printf("n3 - Enter values for v2");
  334.      printf("n4 - Enter values for v3");
  335.      printf("n5 - Compute v3=v1+v2");
  336.      printf("n6 - Compute v3=v1-v2");
  337.      printf("n7 - Compute v1.v2");
  338.      printf("n8 - Compute Length of v1, v2, v3");
  339.      printf("n0 - Exit this menu");
  340.      printf("nnSelect one?");
  341.      scanf("%d", &sel);
  342.      // get input
  343.      switch(sel)
  344.           {
  345.           case 0: // printf("n0 - Exit this menu.");
  346.                 {
  347.                 return;
  348.                 } break;
  349.           case 1: // printf("n1 - Print out all vectors v1, v2, v3.");
  350.                 {
  351.                 printf("nv1:");
  352.                 v1.print();
  353.                 printf("nv2:");
  354.                 v2.print();
  355.                 printf("nv3:");
  356.                 v3.print();
  357.                 } break;
  358.           case 2: // printf("n2 - Enter values for v1.");
  359.                 {
  360.                 printf("nEnter x,y,z values for v1 seperated by spaces?");
  361.                 scanf("%f %f %f", &v1.M[0], &v1.M[1], &v1.M[2]);
  362.                 v1.M[3] = 1;
  363.                 } break;
  364.           case 3: // printf("n3 - Enter values for v2.");
  365.                 {
  366.                 printf("nEnter x,y,z values for v2 seperated by spaces?");
  367.                 scanf("%f %f %f", &v2.M[0], &v2.M[1], &v2.M[2]);
  368.                 v2.M[3] = 1;
  369.                 } break;
  370.           case 4: // printf("n4 - Enter values for v3.");
  371.                 {
  372.                 printf("nEnter x,y,z values for v3 seperated by spaces?");
  373.                 scanf("%f %f %f", &v3.M[0], &v3.M[1], &v3.M[2]);
  374.                 v3.M[3] = 1;
  375.                 } break;
  376.           case 5: // printf("n5 - Compute v3=v1+v2");
  377.                 {
  378.                 v3=v1+v2;
  379.                 } break;
  380.           case 6: // printf("n6 - Compute v3=v1-v2");
  381.                 {
  382.                 v3=v1-v2;
  383.                 } break;
  384.           case 7: // printf("n7 - Compute v1.v2");
  385.                 {
  386.                 float dp = v1*v2; 
  387.                 printf("nv1.v2 = %f",dp);
  388.                 } break;
  389.           case 8: // printf("n8 - Compute Length of v1, v2, v3.");
  390.                 {
  391.                 float l1 = v1.length();
  392.                 float l2 = v2.length();
  393.                 float l3 = v3.length();
  394.        
  395.                 printf("nlength(v1) = %f", l1);
  396.                 printf("nlength(v2) = %f", l2);
  397.                 printf("nlength(v3) = %f", l3);
  398.                 } break;
  399.           default: break;
  400.           } // end switch
  401.      } // end while
  402. } // end main