Thanks for your replies.
I got lucky and was able to reproduce the problem. This resulted in some data.
But first, a couple additional notes:
- I am running on Windows 7 64 bit with the latest JRE from Oracle:
java.runtime.version=1.6.0_25-b06.
Here is the VM version:
java.vm.version=20.0-b11
I have an ATI 5770 HD card.
- I am running with the following flags on:
-Dsun.java2d.translaccel=true
-Dsun.java2d.accthreshold=0
-Dsun.java2d.ddforcevram
-Dsun.java2d.d3d=true
-Dsun.java2d.ddscale=true
Maybe I have a bad combination of settings here. My knowledge in this area is little and I am learning as I go along. I am trying to accelerate as much as possible. I have NO Volatile Images because I am drawing on a JPanel.
I have checked to see if my images are hw accelerated and the method returns true. I do really get amazing performance when things go correctly. There are times where I can draw 600+ translucent images with a 0 MS draw time (Yes, I am using nano time for my benchmarking)!! This is fantastical.
- I am creating the BufferedImages with the following code:
public static BufferedImage loadBufferedImage(String imageFile)
{
BufferedImage bufferedImage;
try
{
Image image = ImageIO.read(new File(imageFile));
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsConfiguration gc = ge.getDefaultScreenDevice().getDefaultConfiguration();
bufferedImage = gc.createCompatibleImage(image.getWidth(null), image.getHeight(null), Transparency.TRANSLUCENT);
Graphics2D g2d = (Graphics2D)bufferedImage.createGraphics();
g2d.drawImage(image, 0, 0, null);
g2d.dispose();
return bufferedImage;
}
catch (IOException e)
{
e.printStackTrace();
}
return null;
}
So it is very similar to what you have (though it looks like you are doing a convert if it is not a compatible image). 99% of my images have partial transparency. There are some images, namely, icons for the user interface that do not but I use the same method to load them. Would this cause the problem?
As mentioned at the beginning of the reply, I did get some more data. The program runs fine and then “something happens”. Then the performance goes down the tubes. The funny thing is, it happens at the same point within in the program even if I reload new images from disk. For example, every 500th image seems to take an extra 100 MS to rotate, draw, and rotate. But all of the ones before and after it, take less than 1 MS. I have not acquired more data yet to see if this is how it behaves each time the performance goes down. Maybe this was a one time instance and there are other times that multiple images take additional times. I had an idea where I would detect long rotate, draw and rotate times and remove the image from the list to be drawn. Then I would see if my performance went back up to normal.
Here are some numbers I acquired:
drawImage only:
Scale of 0.4f:
graphicLocations: before(9472): : 4 MS.
graphicLocations(drawn: 149. Transform checks: 0): after: 24 MS. (This took 20 MS to draw: 24-4=20)
(I drew 149 out of 9472 images)
rotate, drawImage, rotate:
Scale of 1.0f:
graphicLocations: before(9472): : 4 MS.
graphicLocations(drawn: 44. Transform checks: 0): after: 138 MS. (This took 134 MS to draw: 138-4=134)
(I drew 44 out of 9472 images)
Note: I was not able to get the behavior at the same scale because the game will only rotate if you are zoomed in close enough to see it. But the evidence looks fairly strong.
Here are some numbers when everything is working fine:
rotate, drawImage, rotate:
Scale of 1.0f:
graphicLocations: before(9472): : 0 MS.
graphicLocations(drawn: 23. Transform checks: 0): after: 0 MS.
drawImage only:
Scale of 0.05f:
graphicLocations: before(9870): : 0 MS.
graphicLocations(drawn: 6672. Transform checks: 0): after: 9 MS. !!!!! 9 MS to draw over 6000 images.
I looked at the GC and this is the report when execution stops:
Heap
def new generation total 127936K, used 45871K [0x04590000, 0x0d060000, 0x14590000)
eden space 113728K, 35% used [0x04590000, 0x06cfe700, 0x0b4a0000)
from space 14208K, 38% used [0x0c280000, 0x0c7dd6e8, 0x0d060000)
to space 14208K, 0% used [0x0b4a0000, 0x0b4a0000, 0x0c280000)
tenured generation total 284228K, used 223198K [0x14590000, 0x25b21000, 0x34590000)
the space 284228K, 78% used [0x14590000, 0x21f87888, 0x21f87a00, 0x25b21000)
compacting perm gen total 12288K, used 2821K [0x34590000, 0x35190000, 0x38590000)
the space 12288K, 22% used [0x34590000, 0x348517f0, 0x34851800, 0x35190000)
ro space 10240K, 54% used [0x38590000, 0x38b0e770, 0x38b0e800, 0x38f90000)
rw space 12288K, 55% used [0x38f90000, 0x39634ac8, 0x39634c00, 0x39b90000)
It seems the GC collects around 100 MB per collection (it seems to be around 1-2 seconds). The amount it collects goes up slightly (maybe 5-10MB) when things start to go bad.
Here is the GC collection report for a short run when everything went fine:
Heap
def new generation total 123136K, used 54532K [0x04590000, 0x0cb20000, 0x14590000)
eden space 109504K, 45% used [0x04590000, 0x07659e98, 0x0b080000)
from space 13632K, 33% used [0x0bdd0000, 0x0c247500, 0x0cb20000)
to space 13632K, 0% used [0x0b080000, 0x0b080000, 0x0bdd0000)
tenured generation total 273416K, used 204071K [0x14590000, 0x25092000, 0x34590000)
the space 273416K, 74% used [0x14590000, 0x20cd9db8, 0x20cd9e00, 0x25092000)
compacting perm gen total 12288K, used 1866K [0x34590000, 0x35190000, 0x38590000)
the space 12288K, 15% used [0x34590000, 0x34762830, 0x34762a00, 0x35190000)
ro space 10240K, 54% used [0x38590000, 0x38b0e770, 0x38b0e800, 0x38f90000)
rw space 12288K, 55% used [0x38f90000, 0x39634ac8, 0x39634c00, 0x39b90000)
Finally, here are some Java2D traces:
Here is the trace for when everything went bad (I ran the program for around 10 minutes):
7025 calls to D3DDrawLine
649 calls to sun.java2d.loops.Blit::Blit(FourByteAbgr, SrcNoEa, IntArgb)
1 call to sun.java2d.d3d.D3DSurfaceToGDIWindowSurfaceBlit::Blit("D3D Surface", AnyAlpha, "GDI")
990959 calls to sun.java2d.loops.MaskFill::MaskFill(AnyColor, Src, IntRgb)
11150 calls to sun.java2d.loops.Blit$GeneralMaskBlit::Blit(IntArgbPre, SrcOverNoEa, IntRgb)
11150 calls to sun.java2d.loops.MaskBlit::MaskBlit(IntArgbPre, SrcOver, IntRgb)
20748 calls to sun.java2d.loops.FillRect::FillRect(AnyColor, SrcNoEa, AnyInt)
55583 calls to sun.java2d.d3d.D3DTextureToSurfaceTransform::TransformBlit("D3D Texture", AnyAlpha, "D3D Surface")
2082 calls to sun.java2d.loops.DrawGlyphList::DrawGlyphList(AnyColor, SrcNoEa, AnyInt)
432305 calls to D3DFillAAParallelogram
5062 calls to D3DDrawRect
6000 calls to sun.java2d.loops.MaskBlit::MaskBlit(IntArgbPre, SrcOver, IntArgbPre)
78977 calls to sun.java2d.loops.Blit$GeneralMaskBlit::Blit("D3D Surface (render-to-texture)", SrcNoEa, IntRgb)
1 call to sun.java2d.windows.GDIBlitLoops::Blit(IntRgb, SrcNoEa, "GDI")
78977 calls to sun.java2d.d3d.D3DSurfaceToSwBlit::Blit("D3D Surface", SrcNoEa, IntArgb)
261632 calls to sun.java2d.d3d.D3DMaskFill::MaskFill(OpaqueColor, SrcNoEa, "D3D Surface")
64 calls to sun.java2d.loops.Blit::Blit(ThreeByteBgr, SrcNoEa, IntArgbPre)
763031 calls to sun.java2d.loops.TransformHelper::TransformHelper(IntArgbPre, SrcNoEa, IntArgbPre)
7 calls to D3DCopyArea
78977 calls to sun.java2d.loops.MaskBlit$General::MaskBlit("D3D Surface (render-to-texture)", SrcNoEa, IntRgb)
10732 calls to sun.java2d.loops.DrawRect::DrawRect(AnyColor, SrcNoEa, AnyInt)
301365 calls to D3DDrawGlyphs
35578 calls to sun.java2d.loops.DrawGlyphListLCD::DrawGlyphListLCD(AnyColor, SrcNoEa, IntRgb)
78977 calls to sun.java2d.loops.MaskBlit::MaskBlit(IntArgb, AnyAlpha, IntRgb)
1 call to sun.java2d.loops.Blit::Blit(ByteIndexed, SrcNoEa, IntArgbPre)
649 calls to sun.java2d.loops.Blit$GeneralMaskBlit::Blit(FourByteAbgr, SrcOverNoEa, IntArgbPre)
10488 calls to sun.java2d.d3d.D3DTextureToSurfaceBlit::Blit("D3D Texture", AnyAlpha, "D3D Surface")
66838 calls to sun.java2d.loops.MaskFill::MaskFill(AnyColor, Src, IntArgbPre)
649 calls to sun.java2d.loops.MaskBlit::MaskBlit(IntArgb, SrcOver, IntArgbPre)
649 calls to sun.java2d.loops.MaskBlit$General::MaskBlit(FourByteAbgr, SrcOverNoEa, IntArgbPre)
3901 calls to sun.java2d.d3d.D3DSwToSurfaceBlit::Blit(IntRgb, AnyAlpha, "D3D Surface")
6000 calls to sun.java2d.loops.Blit$GeneralMaskBlit::Blit(IntArgbPre, SrcOverNoEa, IntArgbPre)
10595 calls to D3DFillRect
2400240 calls to sun.java2d.d3d.D3DTextureToSurfaceScale::ScaledBlit("D3D Texture", AnyAlpha, "D3D Surface")
70261 calls to sun.java2d.d3d.D3DRTTSurfaceToSurfaceBlit::Blit("D3D Surface (render-to-texture)", AnyAlpha, "D3D Surface")
1062 calls to sun.java2d.d3d.D3DSwToTextureBlit::Blit(IntArgbPre, SrcNoEa, "D3D Texture")
36437 calls to D3DDrawAAParallelogram
25771 calls to sun.java2d.loops.DrawLine::DrawLine(AnyColor, SrcNoEa, AnyInt)
5864573 total calls to 38 different primitives
Here is a short trace for when everything went fine:
(I didn’t do much here so there are less calls overall)
6000 calls to sun.java2d.loops.Blit$GeneralMaskBlit::Blit(IntArgbPre, SrcOverNoEa, IntArgbPre)
590642 calls to sun.java2d.d3d.D3DTextureToSurfaceScale::ScaledBlit("D3D Texture", AnyAlpha, "D3D Surface")
154 calls to sun.java2d.d3d.D3DSwToTextureBlit::Blit(IntArgbPre, SrcNoEa, "D3D Texture")
14541 calls to D3DDrawGlyphs
262 calls to sun.java2d.d3d.D3DTextureToSurfaceBlit::Blit("D3D Texture", AnyAlpha, "D3D Surface")
635 calls to sun.java2d.loops.MaskBlit::MaskBlit(IntArgb, SrcOver, IntArgbPre)
661 calls to sun.java2d.d3d.D3DTextureToSurfaceTransform::TransformBlit("D3D Texture", AnyAlpha, "D3D Surface")
3593 calls to sun.java2d.d3d.D3DRTTSurfaceToSurfaceBlit::Blit("D3D Surface (render-to-texture)", AnyAlpha, "D3D Surface")
635 calls to sun.java2d.loops.MaskBlit$General::MaskBlit(FourByteAbgr, SrcOverNoEa, IntArgbPre)
635 calls to sun.java2d.loops.Blit::Blit(FourByteAbgr, SrcNoEa, IntArgb)
21920 calls to D3DFillAAParallelogram
210 calls to D3DFillRect
1 call to D3DDrawRect
65580 calls to sun.java2d.loops.MaskFill::MaskFill(AnyColor, Src, IntArgbPre)
83878 calls to sun.java2d.d3d.D3DMaskFill::MaskFill(OpaqueColor, SrcNoEa, "D3D Surface")
1927 calls to D3DDrawAAParallelogram
6000 calls to sun.java2d.loops.MaskBlit::MaskBlit(IntArgbPre, SrcOver, IntArgbPre)
635 calls to sun.java2d.loops.Blit$GeneralMaskBlit::Blit(FourByteAbgr, SrcOverNoEa, IntArgbPre)
61 calls to sun.java2d.loops.Blit::Blit(ThreeByteBgr, SrcNoEa, IntArgbPre)
797970 total calls to 19 different primitives
Well that is all of the information I have now. It is a lot because I am trying to really track down this issue. I will put in the code to perform a convert on the buffered image to the correct transparency and see if that improves things.
Well, thanks for reading and I hope that you guys can find an error in the information I provided. I am going to continue working on this with the new buffered image code provided and try to get some additional data, etc.
Thanks again!