Skip to main content
GameDev.net gamedev.net
🔒 Locked

access violation while using SSE

Started by billconan Jan 21, 2008 at 5:19 PM 1 replies 1.5k views
Original Post
billconan
billconan
hi guys, i'm using SSE for vector calculation. but i failed and got access violation. the problematic line is this

		inline void operator+=(Vector& v1,const Vector& v2)
		{
			v1.data=_mm_add_ps(v1.data,v2.data);
		}
i know that The memory the sse instructions access need to be 16-byte aligned. so i did do my own new and delete operations like this:

			static void* operator new(size_t size)
			{
				void *p=_aligned_malloc(size,16);
				return p;
			};

			static void operator delete (void *p)
			{
				_aligned_free(p);
			}
i found a post here talking about the same problem, but no solution was given. http://www.devmaster.net/forums/archive/index.php/t-4995.html can any one tell me how to fix this? thank you very much.

		class Vector
		{
		protected:
			__m128 data;
		public:
			float getX()
			{
				return data.m128_f32[0];
			};

			float getY()
			{
				return data.m128_f32[1];
			};

			float getZ()
			{
				return data.m128_f32[2];
			};

			float getW()
			{
				return data.m128_f32[3];
			};

			void setX(float x)
			{
				data.m128_f32[0]=x;
			};

			void setY(float y)
			{
				data.m128_f32[1]=y;
			};

			void setZ(float z)
			{
				data.m128_f32[2]=z;
			};

			void setW(float w)
			{
				data.m128_f32[3]=w;
			};

			void setVector(float x,float y,float z)
			{
				data.m128_f32[0]=x;
				data.m128_f32[1]=y;
				data.m128_f32[2]=z;
				data.m128_f32[3]=1.0f;
			};

			void setVector(float x,float y,float z,float w)
			{
				data.m128_f32[0]=x;
				data.m128_f32[1]=y;
				data.m128_f32[2]=z;
				data.m128_f32[3]=w;
			};
		
		public:
			Vector(void)
			{
				data.m128_f32[0]=0.0f;
				data.m128_f32[1]=0.0f;
				data.m128_f32[2]=0.0f;
				data.m128_f32[3]=1.0f;
			};

			Vector(float f)
			{
				data.m128_f32[0]=data.m128_f32[1]=data.m128_f32[2]=data.m128_f32[3]=f;
			};

			Vector(float f1,float f2)
			{
				data.m128_f32[0]=data.m128_f32[1]=data.m128_f32[2]=f1;
				data.m128_f32[3]=f2;
			};

			Vector(Vector& v)
			{
				float a=v.getX();
				data.m128_f32[0]=v.getX();
				data.m128_f32[1]=v.getY();
				data.m128_f32[2]=v.getZ();
				data.m128_f32[3]=v.getW();
			};

			Vector(float x,float y,float z)
			{
				data.m128_f32[0]=x;
				data.m128_f32[1]=y;
				data.m128_f32[2]=z;
				data.m128_f32[3]=1.0f;
			};

			Vector(float x, float y, float z, float w)
			{
				data.m128_f32[0]=x;
				data.m128_f32[1]=y;
				data.m128_f32[2]=z;
				data.m128_f32[3]=w;
			};

			void operator=(Vector& in)
			{
				data.m128_f32[0]=in.getX();
				data.m128_f32[1]=in.getY();
				data.m128_f32[2]=in.getZ();
				data.m128_f32[3]=in.getW();
			};

			void null()
			{
				data.m128_f32[0]=data.m128_f32[1]=data.m128_f32[2]=0.0f;
				data.m128_f32[3]=1.0f;
			};

			static void* operator new(size_t size)
			{
				void *p=_aligned_malloc(size,16);
				return p;
			};

			static void operator delete (void *p)
			{
				_aligned_free(p);
			}
   
			friend void operator+=(Vector& v1, const Vector& v2);
			friend void operator-=(Vector& v1, const Vector& v2);
			friend Vector operator-(Vector& v1, Vector& v2);
			friend Vector operator+(Vector& v1,Vector& v2);

			float operator[](int i)
			{
				return data.m128_f32;
			};

			friend void operator*=(Vector &v,float f);
			friend void operator/=(Vector &v,float f);
			friend void operator*=(Vector &v1,Vector &v2);
			friend void operator/=(Vector &v1,Vector &v2);

			friend Vector operator*(Vector &v1,Vector &v2);
			friend Vector operator/(Vector &v1,Vector &v2);

			friend Vector operator*(Vector &v1,float f);
			friend Vector operator*(float f,Vector &v1);

			friend Vector operator/(Vector &v1,float f);

			bool operator==(Vector &v)
			{
				return (data.m128_f32[0]==v.getX())&&(data.m128_f32[1]==v.getY())&&(data.m128_f32[2]==v.getZ())&&(data.m128_f32[3]==v.getW());
			};

			float getLength()
			{
				__m128 temp1=data;
				__m128 temp2;
				temp1.m128_f32[3]=0.0f;
				temp2=(temp1=_mm_mul_ps(temp1,temp1));
				temp2=_mm_shuffle_ps(temp2,temp2,0x4E);
				temp1=_mm_add_ps(temp1,temp2);
				temp2=_mm_shuffle_ps(temp1,temp1,0x11);
				temp1=_mm_add_ss(temp1,temp2);
				temp1=_mm_sqrt_ss(temp1);
				return temp1.m128_f32[0];
			};

			float getLengthSquare()
			{
				__m128 temp1=data;
				__m128 temp2;
				temp1.m128_f32[3]=0.0f;
				temp2=(temp1=_mm_mul_ps(temp1,temp1));
				temp2=_mm_shuffle_ps(temp2,temp2,0x4E);
				temp1=_mm_add_ps(temp1,temp2);
				temp2=_mm_shuffle_ps(temp1,temp1,0x11);
				temp1=_mm_add_ss(temp1,temp2);
				return temp1.m128_f32[0];
			};

			float distanceTo(Vector &v)
			{
				__m128 temp1;
				temp1.m128_f32[0]=v.getX();
				temp1.m128_f32[1]=v.getY();
				temp1.m128_f32[2]=v.getZ();
				temp1.m128_f32[3]=0.0f;

				temp1=_mm_sub_ps(data,temp1);
				__m128 temp2;
				temp1.m128_f32[3]=0.0f;
				temp2=(temp1=_mm_mul_ps(temp1,temp1));
				temp2=_mm_shuffle_ps(temp2,temp2,0x4E);
				temp1=_mm_add_ps(temp1,temp2);
				temp2=_mm_shuffle_ps(temp1,temp1,0x11);
				temp1=_mm_add_ss(temp1,temp2);
				temp1=_mm_sqrt_ss(temp1);
				return temp1.m128_f32[0];
			};

			float distanceToSquare(Vector &v)
			{
				__m128 temp1;
				temp1.m128_f32[0]=v.getX();
				temp1.m128_f32[1]=v.getY();
				temp1.m128_f32[2]=v.getZ();
				temp1.m128_f32[3]=0.0f;

				temp1=_mm_sub_ps(data,temp1);
				__m128 temp2;
				temp1.m128_f32[3]=0.0f;
				temp2=(temp1=_mm_mul_ps(temp1,temp1));
				temp2=_mm_shuffle_ps(temp2,temp2,0x4E);
				temp1=_mm_add_ps(temp1,temp2);
				temp2=_mm_shuffle_ps(temp1,temp1,0x11);
				temp1=_mm_add_ss(temp1,temp2);
				return temp1.m128_f32[0];				
			}

			void negate()
			{
				__m128 temp;
				temp.m128_f32[0]=temp.m128_f32[1]=temp.m128_f32[2]=temp.m128_f32[3]=0.0f;
				data=_mm_sub_ps(temp,data);
			}

			friend Vector cross(Vector &v1,Vector &v2);

			void normalize()
			{
				__m128 temp1=data;
				__m128 temp2;
				temp1.m128_f32[3]=0.0f;
				temp2=(temp1=_mm_mul_ps(temp1,temp1));
				temp2=_mm_shuffle_ps(temp2,temp2,0x4E);
				temp1=_mm_add_ps(temp1,temp2);
				temp2=_mm_shuffle_ps(temp1,temp1,0x11);
				temp1=_mm_add_ss(temp1,temp2);
				temp1=_mm_sqrt_ss(temp1);

				temp2.m128_f32[0]=temp2.m128_f32[1]=temp2.m128_f32[2]=temp1.m128_f32[0];
				temp2.m128_f32[3]=1.0f;

				data=_mm_div_ps(data,temp2);
			}


		public:
			~Vector(void){};
		};
		
		inline void operator+=(Vector& v1,const Vector& v2)
		{
			v1.data=_mm_add_ps(v1.data,v2.data);
		}

		inline void operator-=(Vector& v1, const Vector& v2)
		{
			v1.data=_mm_sub_ps(v1.data,v2.data);
		}

		inline Vector cross(Vector &v1,Vector &v2)
		{

			__m128 data1;
			__m128 data2;

			data1.m128_f32[0]=v1.getX();
			data1.m128_f32[1]=v1.getY();
			data1.m128_f32[2]=v1.getZ();
			data1.m128_f32[3]=v1.getW();

			data2.m128_f32[0]=v2.getX();
			data2.m128_f32[1]=v2.getY();
			data2.m128_f32[2]=v2.getZ();
			data2.m128_f32[3]=v2.getW();

			__m128 temp1=_mm_shuffle_ps(data1,data1,0xc9);
			__m128 temp2=_mm_shuffle_ps(data2,data2,0xd2);

			temp1=_mm_mul_ps(temp1,temp2);

			__m128 temp3=_mm_shuffle_ps(data1,data1,0xd2);
			__m128 temp4=_mm_shuffle_ps(data2,data2,0xc9);

			temp3=_mm_mul_ps(temp3,temp4);

			temp4=_mm_sub_ps(temp1,temp3);

			Vector result(temp4.m128_f32[0],temp4.m128_f32[1],temp4.m128_f32[2]);
			return result;
		}

		inline Vector operator-(Vector& v1, Vector& v2)
		{
			__m128 temp1;
			__m128 temp2;

			temp1.m128_f32[0]=v1.getX();
			temp1.m128_f32[1]=v1.getY();
			temp1.m128_f32[2]=v1.getZ();
			temp1.m128_f32[3]=v1.getW();

			temp2.m128_f32[0]=v2.getX();
			temp2.m128_f32[1]=v2.getY();
			temp2.m128_f32[2]=v2.getZ();
			temp2.m128_f32[3]=v2.getW();

			__m128 temp=_mm_sub_ps(temp1,temp2);
			Vector result(temp.m128_f32[0],temp.m128_f32[1],temp.m128_f32[2]);
			return result;
		}

		inline Vector operator+(Vector& v1,Vector& v2)
		{
			__m128 temp1;
			__m128 temp2;

			temp1.m128_f32[0]=v1.getX();
			temp1.m128_f32[1]=v1.getY();
			temp1.m128_f32[2]=v1.getZ();
			temp1.m128_f32[3]=v1.getW();

			temp2.m128_f32[0]=v2.getX();
			temp2.m128_f32[1]=v2.getY();
			temp2.m128_f32[2]=v2.getZ();
			temp2.m128_f32[3]=v2.getW();

			__m128 temp=_mm_add_ps(temp1,temp2);
			Vector result(temp.m128_f32[0],temp.m128_f32[1],temp.m128_f32[2]);
			return result;			
		}


		inline void operator*=(Vector &v,float f)
		{
			__m128 temp;
			temp.m128_f32[0]=temp.m128_f32[1]=temp.m128_f32[2]=f;
			temp.m128_f32[3]=1.0f;
			v.data=_mm_mul_ps(v.data,temp);
		}

		inline void operator/=(Vector &v,float f)
		{
			__m128 temp;
			temp.m128_f32[0]=temp.m128_f32[1]=temp.m128_f32[2]=f;
			temp.m128_f32[3]=1.0f;
			v.data=_mm_div_ps(v.data,temp);
		}

		inline void operator*=(Vector &v1,Vector &v2)
		{
			v1.data=_mm_mul_ps(v1.data,v2.data);
		}

		inline void operator/=(Vector &v1,Vector &v2)
		{
			v1.data=_mm_div_ps(v1.data,v2.data);
		}

		inline Vector operator*(Vector &v1,Vector &v2)
		{
			__m128 temp;
			temp=_mm_mul_ps(v1.data,v2.data);
			Vector result(temp.m128_f32[0],temp.m128_f32[1],temp.m128_f32[2]);
			return result;
		}
		
		inline Vector operator/(Vector &v1,Vector &v2)
		{
			__m128 temp;
			temp=_mm_div_ps(v1.data,v2.data);
			Vector result(temp.m128_f32[0],temp.m128_f32[1],temp.m128_f32[2]);
			return result;
		}

		inline Vector operator*(Vector &v1,float f)
		{
			__m128 temp;
			temp.m128_f32[0]=temp.m128_f32[1]=temp.m128_f32[2]=f;
			temp.m128_f32[3]=1.0f;
			temp=_mm_mul_ps(temp,v1.data);
			Vector result(temp.m128_f32[0],temp.m128_f32[1],temp.m128_f32[2]);
			return result;
		}
		
		inline Vector operator*(float f,Vector &v1)
		{
			__m128 temp;
			temp.m128_f32[0]=temp.m128_f32[1]=temp.m128_f32[2]=f;
			temp.m128_f32[3]=1.0f;
			temp=_mm_mul_ps(temp,v1.data);
			Vector result(temp.m128_f32[0],temp.m128_f32[1],temp.m128_f32[2]);
			return result;
		}

		inline Vector operator/(Vector &v1,float f)
		{
			__m128 temp;
			temp.m128_f32[0]=temp.m128_f32[1]=temp.m128_f32[2]=f;
			temp.m128_f32[3]=1.0f;
			temp=_mm_mul_ps(v1.data,temp);
			Vector result(temp.m128_f32[0],temp.m128_f32[1],temp.m128_f32[2]);
			return result;
		}

		inline Vector perpendicular(Vector& v1,Vector& v2)
		{
			Vector result(cross(v1,v2));
			float temp=result.getZ();
			result.setZ(result.getX());
			result.setX(temp);
			return result;
		}


//EDIT: Fixed your code tags, you can read about how they work in the FAQ. - jba. [Edited by - jbadams on January 21, 2008 11:57:10 PM]
janta
janta
Did you actually check with your debugger that the your Vectors are actually 16 bytes aligned? Your Vector may come from the stack and may not be properly aligned (though if that's the case, I'd be surprised since I would have thought that __m128 would have enforced 16 bytes alignment)

JA

And code tags use square brackets [] and not <> ;)
And for code of this size you'd better use source tags instead of code tags ;)
frob
frob
I'm curious, why are you writing this?

There are hundreds of high quality debugged math libraries already out there that have been seriously optimized for the hardware.

The really good libraries are written by experts who know the math, know the hardware, and can tell you exactly where all the bits will reside within the CPU's pipeline, exactly how to prevent that pipeline from stalling, and the optimal order to stream the instructions into the cache. The good libraries are also generally free with your compiler. You can also get them directly from AMD and from Intel, through their developer web sites.

Also you should know that shortly after SSE was released a decade or so ago it became well known and well researched that using SSE without a good knowledge of how, when, and why it should be used tended to make games slower than their naively coded counterparts. The good libraries can handle all of that for you.


Is there a reason you are re-inventing the wheel out of primitives when your search engine can find you high performance, optimized, debugged wheels for free?


Of course, if you are intending on doing it exclusively for a learning exercise, then by all means continue. I'm guessing its either a data alignment issue or an FPU/SSE state flag in an unexpected state.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.