Xbox LIVE Indie Games
Sort Discussions: Previous Discussion Next Discussion
Page 1 of 2 (26 posts) 1 2 Next >

Exception being thrown by Texture2D.GetData

Last post 9/26/2010 4:34 PM by UberGeekGames. 25 replies.
  • 12/5/2007 6:35 PM

    Exception being thrown by Texture2D.GetData

    When calling .GetData on a Texture2D (it's a spritesheet)

    "The operation was aborted. You may not modify a resource that has been set on a device, or after it has been used within a tiling bracket."

    It's confusing to me because because I didn't realize I was modifying anything when calling GetData. 

    I'm attempting to read a single pixel value from the sheet in order to perform per-pixel collision with the mouse.  Sometimes it just works fine, sometimes this happens.  I haven't found a way to reproduce it consistently.  I have no clue how to make it go away.

    This is with 2.0 Beta.
  • 12/5/2007 7:01 PM In reply to

    Re: Exception being thrown by .GetTexture

    >within a tiling bracket

    Are you running on the 360 in a high res like 1080p?

    There was some mention on one of the gamefest talks about the restictions that occur in the API when XNA framework goes into predicated tiling mode...  see http://msdn2.microsoft.com/en-us/library/bb464139.aspx

  • 12/5/2007 7:18 PM In reply to

    Re: Exception being thrown by .GetTexture

    This is happening on Windows.

    It's during Update, before I draw anything.
  • 12/6/2007 4:12 PM In reply to

    Re: Exception being thrown by .GetTexture

    im getting the same error doing the following (also in XNA 2)

    uint[] pixelData = new uint[texture.Width * texture.Height];
    // Populate the array
    texture.GetData(pixelData, 0, texture.Width * texture.Height);
  • 12/6/2007 4:45 PM In reply to

    Re: Exception being thrown by .GetData

    Changed thread title, I meant Texture2D.GetData (not .GetTexture). 

    Other than the supplied target array, I'm still unclear what's being "modified" when calling Texture2D.GetData.

    My app hasn't thrown this exception since yesterday, but there have been no code changes to the engine.
  • 12/6/2007 4:56 PM In reply to

    Re: Exception being thrown by .GetData

    my problem is sorted... i moved it out from the Update to the Render and the error message changed to the dimensions being wrong... which was what was actually wrong.
  • 12/6/2007 5:12 PM In reply to

    Re: Exception being thrown by .GetData

    Interesting.  I'm only ever dealing with a 1x1 pixel for mouse collision, but maybe I'm rarely grabbing a pixel outside the texture's coordinate space, and this exception message is simply not sync'd to the actual problem.  I'll check it out (if I can get it to throw it again).
  • 12/20/2007 2:26 PM In reply to

    Re: Exception being thrown by .GetData

    I'm still getting this error, sporadically (now with GS 2.0)

    I've verified that my dimensions are correct and that I'm not attempting to access pixels outside the texture.  E.g., it threw the error yesterday on a call to Texture2D.GetTexture against a 1024 x 1024 texture grabbing with a rectangle [400, 300, 1, 1].  Tells me I can't modify a resource, and sometimes it simply throws an invalidoperation error with no description.

    XNA bug?
  • 12/21/2007 10:30 PM In reply to

    Re: Exception being thrown by .GetData

    emachine, I got this same error today, coincidentally doing something very similar to what you were doing.  I was checking for mouse collision on the non-transparent portions of an on-screen texture.  I searched the web for the error text, and found no solutions - only your post popped up!

    Something you said, though, made me wonder if the issue wasn't with the GetData, per se, but with the fact that the texture resource was being used by another process in XNA.  Not modified, necessarily, but POTENTIALLY modified.

    I tested a little, and I think it's true.  When the texture being checked with GetData is currently being displayed on the screen, I get the exception.  XNA must lock it somehow to prevent certain manipulations.  I agree with you, though, that GetData should be a harmless read-only operation.

    My code worked fine once I made a copy of the source graphic and loaded that content into my project.  I displayed one of the graphics, and did the GetData test against the other.  It had to be two different content files - two different Texture2D objects pointing to the same AssetName didn't work.

    Hope this helps.  It doesn't exactly solve the complete mystery, but it's a step.

    -Doc

  • 12/21/2007 10:40 PM In reply to

    Re: Exception being thrown by .GetData

    Could you file a bug about this on Connect, please?

    Thanks!

    As a workaround, setting null into GraphicsDevice.Textures[0] (or whatever other index you previously used when drawing the texture) before the GetData call should get rid of the error. You shouldn't have to do that, though.
  • 12/27/2007 7:13 PM In reply to

    Re: Exception being thrown by Texture2D.GetData

    I have just had a similiar issue except when trying to access the vertex buffer of the graphics device so i could write my own boundingbox algorithm. I solved my problem by changing the order of my object initialisations. I was initialising the sprite objects first then the 3d objects, switching these around solved the problem. If you have used the XNA game components list try adding your objects to the component list in a different order see if that helps.
  • 12/28/2007 3:09 PM In reply to

    Re: Exception being thrown by .GetData

    Shawn Hargreaves:
    Could you file a bug about this on Connect, please?

    Thanks!

    As a workaround, setting null into GraphicsDevice.Textures[0] (or whatever other index you previously used when drawing the texture) before the GetData call should get rid of the error. You shouldn't have to do that, though.

    Bug filed - https://connect.microsoft.com/feedback/ViewFeedback.aspx?FeedbackID=320165&SiteID=226

    The workaround in my case was to fill the Color array in the LoadContent. In a spritesheet that holds sprite animation where you only want part of the texture to check this would mean allocating more than is necessary. I was only filling the Color array when a possible collision between sprites was detected through Rectangle comparison, so wasn't doing this every frame.

  • 12/28/2007 4:32 PM In reply to

    Re: Exception being thrown by .GetData

    I filed a bug for this on Connect a couple of weeks back:

    https://connect.microsoft.com/feedback/ViewFeedback.aspx?FeedbackID=318195&SiteID=226

  • 12/30/2007 1:53 AM In reply to

    Re: Exception being thrown by .GetData

    I am experiencing the same issue after upgrading to 2.0.  My example is really strange though.  I am working on a 2d vertical scrolling shooter and I use GetData to get the data from 2 Texture2D objects to see if they are colliding.The code is as follows:

    playerColor = new Color[curShip.getTexture(curTexture).Width * curShip.getTexture(curTexture).Height];

    curShip.getTexture(curTexture).GetData(playerColor);

    enemyColor = new Color[enemyShip.getTexture(3).Width * enemyShip.getTexture(3).Height];

    enemyShip.getTexture(3).GetData(enemyColor);

    The exception happens when I get the texture data of curShip.  If I comment out that line, the program runs fine, even though I am using the exact same function to do the exact same thing to a different texture!  Weird.

     

    jorj

  • 12/30/2007 2:10 AM In reply to

    Re: Exception being thrown by .GetData

    It's likely that the texture you are trying to GetData from is still set as an active Texture on the GraphicsDevice. Try calling:

    graphicsDevice.Textures[0] = null;

    before you get any data from a texture.

  • 12/30/2007 10:10 AM In reply to

    Re: Exception being thrown by .GetData

    That fixed it!  Thanks!  Strange that it was only a problem with curShip and not enemyShip though.

     

    jorj

     

  • 1/5/2008 12:48 PM In reply to

    Re: Exception being thrown by Texture2D.GetData

    Hate to dig up an old thread but I get the same exception using SetData on a DynamicVertexBuffer. The buffer in question is always the last one set with GraphicsDevice.Vertices[0].SetSource() in my render code. Releasing my buffer by calling GraphicsDevice.Vertices[0].SetSource(null, 0, 0) after all rendering calls are complete fixes the problem. It seems the exception description 'You may not modify a resource that has been set on a device' is dead on. Looks like a complete work around would be to implement my own blocking mechanism that postpones updating the buffer until its no longer in use, seeing as how Draw() and Update() can run at different frequencies. Anyways this is just an FYI and I'm not sure what can be done about it but an inuse flag on the resources sure would be helpful. And yes this is 2.0
  • 1/5/2008 1:54 PM In reply to

    Re: Exception being thrown by Texture2D.GetData

    I think that the Update() and Draw() calls are synchronized in XNA 2.0.

    The usual way to avoid waiting for the graphics card to finish with a resource is to 'double buffer' the resource. Have two versions of the resource, dynamic vb in your case, and update one while you use the other on the graphics card, then swap and repeat.

    Cheers,
    Leaf.
  • 1/29/2008 4:17 AM In reply to

    Re: Exception being thrown by Texture2D.GetData

    TomSlick:
    Hate to dig up an old thread but I get the same exception using SetData on a DynamicVertexBuffer. The buffer in question is always the last one set with GraphicsDevice.Vertices[0].SetSource() in my render code. Releasing my buffer by calling GraphicsDevice.Vertices[0].SetSource(null, 0, 0) after all rendering calls are complete fixes the problem. It seems the exception description 'You may not modify a resource that has been set on a device' is dead on. Looks like a complete work around would be to implement my own blocking mechanism that postpones updating the buffer until its no longer in use, seeing as how Draw() and Update() can run at different frequencies. Anyways this is just an FYI and I'm not sure what can be done about it but an inuse flag on the resources sure would be helpful. And yes this is 2.0


    I've got the same thing. So does it mean that the resource is in use, and what driver do when I call device.Vertices[0].SetSource(null, 0, 0)? Does this produce some significant performance hit, some stall? I'm just curious, cause I do not want to use it in my final code, so I really don't care;) I use it just for some debug drawing.
  • 2/4/2008 8:37 PM In reply to

    Re: Exception being thrown by Texture2D.GetData

    I was having this issue with SetData once I ported to GS 2.0. 

    Adding in the GraphicsDevice.Vertices[0].SetSource(null, 0, 0); fixed it. :)
  • 2/6/2008 12:06 AM In reply to

    Re: Exception being thrown by Texture2D.GetData

    Alright, now I'm guilty of digging up an old thread.

    I'm trying to simply copy one section of a Texture2D to another.  I'm getting an InvalidOperationException when trying to call texture.GetData<Color>(0, rect, data, 0, 1) on a Texture2D of format Color (data is a Color[]).  It works fine when I use the single parameter version of GetData(data).  I even tried manipulating the size of the array and the size of the rectangle.  If I use a rectangle of size (1, 1) with an array of size 1, it works.  If I change the size of the Color array to 2 and the size of the rectangle to (2, 1), it throws the exception.  Does anyone out there know what's going on?  Has anyone seen this?  Thanks!

     

  • 2/7/2008 2:22 AM In reply to

    Re: Exception being thrown by Texture2D.GetData

    Robert:

    Alright, now I'm guilty of digging up an old thread.

    I'm trying to simply copy one section of a Texture2D to another.  I'm getting an InvalidOperationException when trying to call texture.GetData<Color>(0, rect, data, 0, 1) on a Texture2D of format Color (data is a Color[]).  It works fine when I use the single parameter version of GetData(data).  I even tried manipulating the size of the array and the size of the rectangle.  If I use a rectangle of size (1, 1) with an array of size 1, it works.  If I change the size of the Color array to 2 and the size of the rectangle to (2, 1), it throws the exception.  Does anyone out there know what's going on?  Has anyone seen this?  Thanks!

     

    Yea that's pretty much what I was getting.  Shawn's workaround (submitted about 12 replies up) solved it for me:
    ShawnBot:
    ...setting null into GraphicsDevice.Textures[0] (or whatever other index you previously used when drawing the texture) before the GetData call should get rid of the error...
    I haven't received the error since implementing the workaround, all my calls to GetData have worked as expected.
  • 4/28/2009 7:33 AM In reply to

    Re: Exception being thrown by Texture2D.GetData

    You guys just saved my butt on a project I'm working on. Thanks much.
  • 9/26/2010 3:11 PM In reply to

    Re: Exception being thrown by Texture2D.GetData

    Just raising my hand up to say that I've been hit by this too.

    Basically what I'm doing is playing a video and capturing it's data to perform some effects on it (longer story: to convert a video to a series of texture2Ds, which will later be combined into a spritesheet). I've been having problems actually getting the data from the texture, and I can't narrow down where exactly it's coming from. I've been doing some tests to try and see what's causing it, so maybe this will help shed some light on what the underlying issue is.

    Here's some code. This produces a blank image:

    Texture2D CopyTexture(GraphicsDevice gd, Texture2D tex) 
        Color[] data = new Color[tex.Width * tex.Height]; 
        tex.GetData<Color>(data); 
                 
        Texture2D nTex = new Texture2D(gd, tex.Width, tex.Height); 
        nTex.SetData<Color>(data); 
        return nTex; 

    This produces the actual video frame:
    Texture2D CopyTexture(GraphicsDevice gd, Texture2D tex) 
        Color[] data = new Color[tex.Width * tex.Height]; 
        tex.GetData<Color>(data); 
                
        tex.SetData<Color>(data); 
        return tex; 

    Just to be certain it's actually setting the new texture data, this code successfully produces the image without it's red channel:
     
    Texture2D CopyTexture(GraphicsDevice gd, Texture2D tex) 
        Color[] data = new Color[tex.Width * tex.Height]; 
        tex.GetData<Color>(data); 
     
        for (int x = 0; x < data.Length; x++) 
            data[x].R = 0; 
     
        tex.SetData<Color>(data); 
        return tex; 


    So... It appears that GetData and SetData are very, very fickle and break under some seemingly random circumstances. :\ I've tried nulling out GraphicsDevice.Textures[0] (and even a few other random indices) but haven't been able to get this working.

    I'll see if I can hack around it by creating the new texture elsewhere with the same color data. Note that I fully understand how it's terrible for performance but the app is PC only and will step through it's content - it's not real time, nor does it need to be, as it's a utility app for converting movies into spritesheets.

    Any other ideas?
  • 9/26/2010 3:57 PM In reply to

    Re: Exception being thrown by Texture2D.GetData

    Have you checked to make sure tex.Width and tex.Height are what you'd expect them to be when you create the new Texture2D? Maybe the transient nature of video textures is causing that to wind up zeroed out after the GetData call. Not that that should be happening, but in the land of the bizarre, the bizarro idea is king. The solution to that being to save tex.Width & Height to local ints before calling GetData.

    I'm leaving this in, but the more I think about it, the more it makes absolutely no sense. It was my first idea and the above was a throw-away idea but the above makes much more sense. I don't have time to test either just now though. So here's the idea that probably doesn't work:

    Another possible workaround would be to create a copy of the data before creating the new Texture2D:

     

    Texture2D CopyTexture(GraphicsDevice gd, Texture2D tex)    
    {    
        Color[] data = new Color[tex.Width * tex.Height];  
        Color[] dataCopy = new Color[tex.Width * tex.Height];  
     
        tex.GetData<Color>(data);    
        
        for (int x = 0; x < data.Length; x++)  
        {  
            dataCopy[x] = data[x];    
        }  
     
        Texture2D nTex = new Texture2D(gd, tex.Width, tex.Height);  
        nTex.SetData<Color>(dataCopy);  
        return nTex;    
    }    
     

    I don't have time to create a test sample, but that creates a copy of the data with all links to the original severed before you create the new Texture2D so if it's some bizarro link to the data being maintained then this should work. Though if a link existed still then I'd expect corruption not blank.

     

     

Page 1 of 2 (26 posts) 1 2 Next > Previous Discussion Next Discussion