Awesome Speeds With VolatileImage

I am in the making of this game in java,
It runs at 30fps(capped).

As a benchmark, I removed the cap and got 92-97fps…
This was with a BufferedImage…
Then i changed it to VolatileImage, it now runs at 192-197fps…
That was a 100fps increase, that’s just badass :smiley:

So i have added the following code at the beginning of the rendering code to initialize the BufferGraphics:

if(vBuffer == null && useGPU) {
	vBuffer = RandomRPG.GamePanel.createVolatileImage(800, 600);
	BufferGraphics = vBuffer.createGraphics();
	BufferGraphics.setBackground(Color.BLACK);
	BufferGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
} else if(Buffer == null && !useGPU) {
	Buffer = new BufferedImage(800, 600, 2);
	BufferGraphics = Buffer.createGraphics();
	BufferGraphics.setBackground(Color.BLACK);
	BufferGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
}

, and at the end:

if(useGPU) {
	g.drawImage(vBuffer, 0, 0, RandomRPG.GamePanel.getPreferredSize().width, RandomRPG.GamePanel.getPreferredSize().height, null);
	vBuffer.flush();
} else {
	g.drawImage(Buffer, 0, 0, RandomRPG.GamePanel.getPreferredSize().width, RandomRPG.GamePanel.getPreferredSize().height, null);
	Buffer.flush();
}
Toolkit.getDefaultToolkit().sync();

This way i can choose either to use the GPU or not…

PS:
CPU Usage was around 17-20% on an Intel Core i5-2540M 2.6GHz 2-Core, 4-Logical Processors
when i used the BufferedImage…
But when i used the VolatileImage, this sank to about 6-7%…
That is because now the GPU is used to take the load of the CPU.
Now i can have lots more stuff in the GameLoop :stuck_out_tongue:

…I thought Java2D could never take advantage of the GPU. Are you sure that is what’s actually happening?
Simply changing to a volatile image shouldn’t make that kind of difference…unless I’ve totally missed something

Yes it should - VolatileImage is backed directly by Direct3d or OpenGL textures. It’s almost as fast at drawing as pure OpenGL is for various ordinary operations.

Cas :slight_smile:

Doesn’t it just use VRAM.
BufferedImages uses normal RAM,
and VolatileImages uses VRAM.
So with Volatile the GPU reads VRAM direcly which is faster than reading RAM.
Correct me if I’m wrong

That’s right. Though I think since JDK1.5 BufferedImage converts to VolatileImage under-the-hood when it can.

Cas :slight_smile:

I also did a smaller benchmark with one image. Drew 5000 frames to buffer then to screen, with both:
VolatileImage: 7 seconds
BufferedImage: 25 seconds

So VolatileImage used 18 seconds less time than the BufferedImage…
VolatileImage is 350% more efficient than BufferedImage.

Drawbacks? When I read up on Volatile Images I remember there were a few drawbacks that required caution.

I don’t have the book on hand right now, I’ll check it when I get back home.

Indeed. Volatiles can be unloaded and disappear (artifact) at any moment.

Yes since java 1.5 all images loaded will try and become manged images if they can.

The major thing that volatile can do better than bufferedImages is acting like a backbuffer.

volatileImage.getGraphics() /BufferedImage.getGraphics()

draw…draw…draw…

BufferedImages are slow for this but for just using BufferedStrategy and g2d.drawImage there is no difference and you really get no speed boost for using a volatile image as a back buffer instead of a BufferedStrategy

Not quite accurate. A managed BufferedImage can automatically cache the data in the graphics hardware for rendering from, but all rendering to it happens in software. A VolatileImage can be rendered to by the hardware pipeline. BufferedImage is more akin to texture, VolatileImage to FBO - in fact, from recollection that’s how they’re done in the OpenGL pipeline.

As I recall BufferStrategy uses VolatileImage under the hood anyway, and it’s easier to use. VolatileImage is best used in the same places you’d use render-to-texture (composite sprites, etc.)

Just ran some tests and without any transparency, volatileimages are much faster then most bufferedimages. With transparency, they are 10-15% slower.

Basically Alphacomp will give you a huge slow down (8300 sprites) 80fps to 8fps when using volatileimages. So anything that does not need to fade or have any transparency should be a volatileimage (backgrounds and stuff);

What OS / pipeline?

Hehe win 7 d3d and I just ran it under opengl pipeline and buffered images were as good as volatile and they can load transparent images where volatile cannot…well I have never gotten them to. And opengl flag also boosts alphacomp performances as well…

Sorry for reviving an old thread, but BufferStrategy uses VolatileImage underneath, so use that instead of VI directly.

Woot! ra4king’s back!!! And reviving old threads to repeat what’s already been said! :stuck_out_tongue: I’m getting that cage prepared as I type … :wink:

To be pedantic, while BufferStrategy uses VolatileImage under the covers, it does not therefore follow that all uses of VolatileImage can be replaced by BufferStrategy.

Right, but for basic rendering like the one portrayed by the OP, it should be used.

And what’s already been said? searches older posts again … oh I thought it wasn’t mentioned :frowning:

Sorry I dig out an old thread, but it is not “ended” with proper information.

Java2D can be accelerated (mostly defaultly it is) by Direct3D or OpenGL.

http://docs.oracle.com/javase/1.5.0/docs/guide/2d/flags.html - here you can set some flags to force acceleration (usefult to force direct3d on windows and opengl everywhere else)

BufferedImage when loaded from resources may be INCOMPATIBLE … there are several types of BufferedImage (depending on layout of pixeldata inside)
For maximum performance, you can create compatible BufferedImage with GraphicsConfiguration
http://docs.oracle.com/javase/7/docs/api/java/awt/GraphicsConfiguration.html#createCompatibleImage(int,%20int,%20int)

Java2D tries to cache BufferedImage as texture whenever possible, so drawing it anywhere is as fast as drawing texture.

problem is… drawing ON BufferedImage is performed in software, while drawing ON VolatileImage is (if possible) on GPU.

so its only faster to use VolatileImage if you want to draw ON IT, otherwise its better to use compatible BufferedImage.

Here is some more info on OpenGL acceleration in Java2D:
http://today.java.net/pub/a/today/2004/11/12/graphics2d.html#Image_Rendering

Direct3D pipeline is very similiar.

What you say was true in 2004 / Java 5 (as the links imply) indeed. Drawing ON a BufferedImage is often hardware accelerated now.

Nope, drawing ON BufferedImages is never accelerated - its just modern CPUs got quite fast :wink:

orogamo:
Try to only make the Buffer a VolatieImage, and use BufferedImage for your sprites.
It should give similar or even better throughput.

Wrong. BufferedImages are accelerated now. Look into “managed images”.