Performance problem with Texture.FromBitmap

I reduced program boot time (when running from within the IDE) from 12 seconds to less than 1 second by re-writing Texture.FromBitmap using unsafe code.  For me it was easy because I'm only using 32 bit textures and 32 bit bitmaps.  It would be nice to see this function optimized in future releases of the SDK.  BTW, Texture.FromStream has the same problem.

-Jeremy



Answer this question

Performance problem with Texture.FromBitmap

  • Dhurean

  • IanRich

    After some further discussion over on gamedev RoKo has moved this one over to the debugger forum so subscribe to this thread if you want to follow it.

    From the MDX perspective, Texture from bitmap calls bitmap.GetPixel X*Y times, and as RoKo has shown there is some perf degredation when you run with the debugger attached. But its not an MDX problem directly, we are just seeing the effects.


  • shamuthekillercoder

    Ah, that helped, thanks. I only checked the stride of the Bitmap which was always just it's width, but the stride of the Texture was not (I didn't see that first, cause there it's called pitch).

    This one works for me:


    texture = new Texture(device, bitmap.Width, bitmap.Height, 1, Usage.Dynamic, Format.A8R8G8B8, Pool.Default);
    int pitch;
    Microsoft.DirectX.GraphicsStream a = texture.LockRectangle(0, LockFlags.None, out pitch);
    System.Drawing.Imaging.BitmapData bd = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
    unsafe
    {
    byte* to = (byte*) a.InternalDataPointer;
    byte* from = (byte*) bd.Scan0.ToPointer();
    for (int y = 0; y < bd.Height; ++y)
    for (int x = 0; x < bd.Width * 4; ++x)
    to[pitch * y + x] = from[y * bd.Stride + x];
    }
    texture.UnlockRectangle(0);
    bitmap.UnlockBits(bd);

     


  • Mister

    No, really. Yours is not as bad as it could be, cause you call bitmap.Width only bitmap.Height times. If you call bitmap.Width bitmap.Width * bitmap.Height times, it's about as slow as Texture.FromBitmap while debugging in VS2005.
    I actually wrapped System.Drawing.Bitmap in my own class, which caches Width and Height, so I'm never tempted to call those properties more than once.

  • PBuchetta

    I am also having the same problem.  I've posted in the MSDN newsgroups, but I haven't received a reply from Microsoft yet.  It would be nice to find a workaround to this problem, as it is slowing my app down tremendously when I need to run it in the debugger.

  • Wops

    Look at the linked thread at gamedev. You have to do something like


    texture = new Texture(device, bitmap.Width, bitmap.Height, 1, Usage.Dynamic, Format.A8R8G8B8, Pool.Default);
    Microsoft.DirectX.GraphicsStream a = texture.LockRectangle(0, LockFlags.None);
    System.Drawing.Imaging.BitmapData bd = bitmapitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
    unsafe
    {
    uint* to = (uint*) a.InternalDataPointer;
    uint* from = (uint*) bd.Scan0.ToPointer();
    for (int i = 0; i < bd.Height * bd.Width; ++i) to[ i] = from[ i];
    }
    texture.UnlockRectangle(0);
    bitmap.UnlockBits(bd);

     

    Doesn't work for all textures though, but I'm sure somebody around here can correct that.

  • Sam_bham

    That's what I experienced too -> http://www.gamedev.net/community/forums/topic.asp topic_id=357621
    It's only really slow, when you run with debugging. That was not the case in VS2003 though.

  • Jazz4sale

    I'm having the same problem. The loading time of a DirectX 9 application I wrote is several times higher with .NET 2.0 than it was with 1.1.
  • davros-too

    I bet you $5 mine is faster :)

  • Naseer_PK

    FYI: I use the above code for Texture.FromBitmap and (and a similar solution for Texture.FromStream), which works as long as your bitmaps are 32BppArgb.

    -Jeremy

  • dagilleland

    Nice asserts.
    It's essentially the same of course...but mine is much faster, at least in VS2005's debug mode. You're using bitmap.Width and bitmap.Height in a loop. Don't do that, it's just as slow as everything else you can do with the Bitmap. Please don't ask me why.

  • J-Man3568

    Here's what I used:


       Texture texture = new Texture(dx, bitmap.Width, bitmap.Height, 1,
             Usage.AutoGenerateMipMap, Format.A8R8G8B8, Pool.Managed);
       BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
       int pitch;
       GraphicsStream textureData = texture.LockRectangle(0, LockFlags.None, out pitch);

       Debug.Assert(bitmap.PixelFormat == PixelFormat.Format32bppArgb);
       Debug.Assert(sizeof(int) == 4 && (bitmapData.Stride & 3) == 0 && (pitch & 3) == 0);

       unsafe
       {
        int *texturePointer = (int*)textureData.InternalDataPointer;
        for (int y = 0;  y < bitmap.Height;  y++)
        {
         int *bitmapLinePointer = (int*)bitmapData.Scan0 + y*(bitmapData.Stride/sizeof(int));
         int *textureLinePointer = texturePointer + y*(pitch/sizeof(int));
         int length = bitmap.Width;
         while (--length >= 0)
          *textureLinePointer++ = *bitmapLinePointer++;
        }
       }

       bitmap.UnlockBits(bitmapData);
       texture.UnlockRectangle(0);


  • Alex Weinert

    Don't know if it matters, but I copied mine line by line and used the Stride to calculate the starting position of the lines.  Another important thing is that the bitmap be converted to 32 bits before using this function, and I've noticed that Bitmap.Clone() doesn't always do the conversion properly.  Finally, you can use this function along with Bitmap.FromStream to speed up Texture.FromStream.

    -Jeremy


  • Sean Sexton

    It was recommended that a bug was raised. If you want to follow this bug, or add your validation or vote then you can find it here:

    http://lab.msdn.microsoft.com/productfeedback/viewfeedback.aspx feedbackid=0dda86da-a83f-475d-8610-d3a08a14cc7f



  • Performance problem with Texture.FromBitmap