Thread: One pointer that does not work as expected

  1. #1
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485

    One pointer that does not work as expected

    I am trying to take one big array of pixels and split it up so that I have 4 arrays instead. One for red,blue,green and alpha.

    Green, red and alpha is working, but that data for blue is wrong, which I find weird considering I am doing exactly the same for all the colours

    Here is my code:
    Code:
    / Create SSE data
    	// Test sprite is 64*64
    	//64 * 64 = 4096
    	__declspec(align(16)) unsigned short  blue[4096];
    	__declspec(align(16)) unsigned short  green[4096];
    	__declspec(align(16)) unsigned short  red[4096];
    	__declspec(align(16)) unsigned short  trans[4096];
    
    	// Pointer to the original spritedata
    	BYTE *texture = spriteData;
    
    	// Splitt the data up so that we have each colour in a seperate array
    	for(int i = 0; i < 4096; i++)
    	{
    		blue[i]  = *(texture + 0);
    		green[i] = *(texture + 1);
    		red[i]   = *(texture + 2);
    		trans[i] = *(texture + 3);
    		texture += 4;	
    	}
    
    	// Point the variebels in the header file to the values here
    	b = blue;
    	g = green;
    	r = red;
    	t = trans;
    b,g,r,t are class variables
    Code:
    		
    // SSE DATA
    		unsigned short  *b;
    		unsigned short  *g;
    		unsigned short  *r;
    		unsigned short  *t;
    About 25&#37; of the data in blue is correct (the first 25%), but after that it get more and more distorted.

    EDIT:
    This should not matter, as if I draw green as blue it works (all the data is correct no matter which screenColour channel I put it in, apart from blue) So I think it is something wrong with how I split the data, but here is the drawing code:
    Code:
    	// Create a pointer to the colours we are using
    	unsigned short  *cBlue = b;
    	unsigned short  *cGreen = g;
    	unsigned short  *cRed = r;
    	unsigned short  *cAlpha = t;
    
    	for (int i = 0; i < height; i++)
    	{		
    		for (int j = 0; j < dividedWidth; j++)
    		{
    			__m128i textBlue =  _mm_loadu_si128( (__m128i*)cBlue);
    			__m128i textGreen = _mm_loadu_si128( (__m128i*)cGreen);
    			__m128i textRed =   _mm_loadu_si128( (__m128i*)cRed);
    			__m128i textAlpha = _mm_loadu_si128( (__m128i*)cAlpha);
    
    			// Unions
    			SSE_blue.m = textBlue;
    			SSE_green.m = textGreen;
    			SSE_red.m = textRed;
    
    			// Increment colour pointer
    			cBlue  +=8;
    			cGreen +=8;
    			cRed   +=8;
    			cAlpha +=8;
    
    			// Copy the result into the screenData pointer
    			for(int p = 0; p < 8; p++)
    			{
    				*(screenDataPnt)     = SSE_blue.s[p];
    				*(screenDataPnt + 1) = SSE_green.s[p];
    				*(screenDataPnt + 2) = SSE_red.s[p];
    
    				screenDataPnt += 4;
    			}
    
    		}
    		// (ScreenWidth - textureWidth) * number of pixels
    		screenDataPnt += 2304;
    	}

    Any ideas?
    Last edited by h3ro; 07-15-2008 at 11:28 AM.

  2. #2
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    How much memory did you allocate for screenDataPnt (or whatever buffer that points to)?

  3. #3
    Registered User
    Join Date
    Apr 2008
    Posts
    890
    Your image data is stored in BGRA format? I think you want to swap the bytes you read for B and R in the for loop.
    Last edited by medievalelks; 07-15-2008 at 04:16 PM.

  4. #4
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485
    screenDataPnt is (screenWidth * screenHeigth * 4) which in my case is 640*480*4

    Your image data is stored in BGRA format? I think you want to swap the bytes you read for B and R in the for loop.
    My data is stored in BGRA, so that part is correct.

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    More of a coding style thing, but:
    Code:
    		blue[i]  = *(texture + 0);
    		green[i] = *(texture + 1);
    		red[i]   = *(texture + 2);
    		trans[i] = *(texture + 3);
    I find it clearer to use index formatting:
    Code:
    		blue[i]  = texture[0];
    		green[i] = texture[1];
    		red[i]   = texture[2];
    		trans[i] = texture[3];
    When you say "more and more corrupted", can you describe what happens to the data?

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  6. #6
    Registered User
    Join Date
    Apr 2008
    Posts
    890
    What are you using to create your sprite images?

  7. #7
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485
    When you say "more and more corrupted", can you describe what happens to the data?
    I uploaded a picture of it.

    Green and red colour is correct, so I did not include pictures of that. Its just the blue that is off, which I find weird, as I do exactly the same for all colours

    What are you using to create your sprite images?
    A directX wrapper.

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    That is extremely strange. Any chance you can figure out exaxctly at which byte it starts going wrong?

    Have you tried using the array access method that I suggested - if there's a code-generation bug in the compiler [which I find unlikely, but it is POSSIBLE] then you may find that the code generated with array access is slightly different and thus perhaps correct?

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  9. #9
    Registered User
    Join Date
    Apr 2008
    Posts
    890
    Wait, are you assigning arrays allocated on the stack to the b, g, r, and a pointers in one member function and reading the pointed to data in another?

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by medievalelks View Post
    Wait, are you assigning arrays allocated on the stack to the b, g, r, and a pointers in one member function and reading the pointed to data in another?
    Doh, how did I miss that one?

    Make them static or global, or allocate memory some way!

    The reason blue goes bad is that it's the first portion of stack, you never use enough stack-space to clobber the others. If you make a sufficiently large array (16*2K bytes) on the stack in another function and filled it with zero's, you'd find that ALL of the values except a piece of blue the are zero.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  11. #11
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485
    That is extremely strange. Any chance you can figure out exaxctly at which byte it starts going wrong?
    I made this code to check
    Code:
    	BYTE *testTexture = spriteData;
    	for(int i = 0; i < 4096; i++)
    	{
    		// TestTexture is a BYTE, b is a unsigned short
    		if((unsigned short)*testTexture != (unsigned short)*b)
    		{
    			// Debugg point
    			///
    		}
    
    		testTexture+=4;
    		b++;
    	}
    It stops at i = 0 and then:
    *testTexture 255 'ÿ' unsigned char
    *b 255 unsigned short

  12. #12
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485
    Quote Originally Posted by medievalelks View Post
    Wait, are you assigning arrays allocated on the stack to the b, g, r, and a pointers in one member function and reading the pointed to data in another?
    That fixed it. Thanks.

    But why do I need to allocate memory there? I though that the memory I allocate will be valid as long as the sprite object is valid.

  13. #13
    Registered User
    Join Date
    Apr 2008
    Posts
    890
    The arrays you allocate are on the stack. As soon as the function in which they are declared returns, that memory is reclaimed and can and likely will be overwritten later.
    Last edited by medievalelks; 07-16-2008 at 08:02 AM.

  14. #14
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Code:
    	__declspec(align(16)) unsigned short  blue[4096];
    	__declspec(align(16)) unsigned short  green[4096];
    	__declspec(align(16)) unsigned short  red[4096];
    	__declspec(align(16)) unsigned short  trans[4096];
    These are local variables - they only exist (are valid) as long as the function is in use. Once you leave that function the memory they held (on the stack) is freed, and anything else needing stack-space will be allowed to use that space.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. sorting number
    By Leslie in forum C Programming
    Replies: 8
    Last Post: 05-20-2009, 04:23 AM
  2. Request for comments
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 01-02-2004, 10:33 AM
  3. The Bludstayne Open Works License
    By frenchfry164 in forum A Brief History of Cprogramming.com
    Replies: 8
    Last Post: 11-26-2003, 11:05 AM
  4. Struct *** initialization
    By Saravanan in forum C Programming
    Replies: 20
    Last Post: 10-09-2003, 12:04 PM
  5. Contest Results - May 27, 2002
    By ygfperson in forum A Brief History of Cprogramming.com
    Replies: 18
    Last Post: 06-18-2002, 01:27 PM