JavaFX effects and hardware acceleration…

Posted by Steven Herod on Jul 20, 2009 in Uncategorized |

Note, this entry has been superceeded by Take 3, you can read it for historical context/further explanation.  The comments of this blog are also of value as they lead to what I’ve restated in ‘Take 3′

This post was sparked today by Jonathan Giles and his optimization of Josh Marinacci’s particle accelerator demo.

One of the questions I asked after he posted his blog entry was “Do you know if hardware acceleration being used for your effects?”

He didn’t know, and to be honest, I wasn’t entirely sure how to check myself.

So, I whipped up this test called Leadfoot (because it’s all about Acceleration :-)

It’s a JavaFX 1.2 app, and you can run it using webstart by clicking here.

Here are some of the answers so far:

What does it all mean? Well, “CPU/SIMD” apparently is hardware acceleration. I’m still not entirely sure! I believe CPU/SIMD relates to the fact it is using the SSE instructions on the CPU. Which is NOT by my definition, the GPU on your video card. So the question remains, under what circumstances does GPU aceleration actually occur?

More news: Other users have reported OpenGL (On a MacBook Pro, see gallery) and CPU/Java (On Ubuntu and on Windows with an older Toshiba laptop)

Below is the source code, feedback welcome!


/*
* Main.fx
*
* Created on Jul 20, 2009, 8:38:21 PM
*/

package leadfoot;

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.ListView;

import javafx.scene.effect.Blend;

import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import javafx.scene.effect.Bloom;
import javafx.scene.effect.ColorAdjust;
import javafx.scene.effect.DisplacementMap;
import javafx.scene.effect.DropShadow;
import javafx.scene.effect.Flood;
import javafx.scene.effect.GaussianBlur;
import javafx.scene.effect.Glow;
import javafx.scene.effect.Identity;
import javafx.scene.effect.InnerShadow;
import javafx.scene.effect.InvertMask;
import javafx.scene.effect.Lighting;
import javafx.scene.effect.MotionBlur;
import javafx.scene.effect.PerspectiveTransform;
import javafx.scene.effect.Reflection;
import javafx.scene.effect.SepiaTone;
import javafx.scene.effect.Shadow;

import javafx.scene.effect.BoxBlur;

/**
* @author steven
*/

function getAccelerationFaults():Object[] {

def gc = GraphicsEnvironment.
getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();

def gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();

var returnVal:Object[];

var blend:Blend = new Blend();
insert “blend: {blend.getAccelType(gc)}” into returnVal;

var bloom:Bloom = new Bloom();
insert “bloom: {bloom.getAccelType(gc)}” into returnVal;

var boxBlur:BoxBlur = new BoxBlur();
insert “boxBlur: {boxBlur.getAccelType(gc)}” into returnVal;

var colorAdjust:ColorAdjust = new ColorAdjust();
insert “colorAdjust: {colorAdjust.getAccelType(gc)}” into returnVal;

var displacmentMap:DisplacementMap = new DisplacementMap();
insert “displacmentMap: {displacmentMap.getAccelType(gc)}” into returnVal;

var dropShadow:DropShadow = new DropShadow();
insert “dropShadow: {dropShadow.getAccelType(gc)}” into returnVal;

var flood:Flood = new Flood();
insert “flood: {flood.getAccelType(gc)}” into returnVal;

var gaussianBlur:GaussianBlur = new GaussianBlur();
insert “gaussianBlur: {gaussianBlur.getAccelType(gc)}” into returnVal;

var glow:Glow = new Glow();
insert “glow: {glow.getAccelType(gc)}” into returnVal;

var identity:Identity = new Identity();
insert “identity: {identity.getAccelType(gc)}” into returnVal;

var innerShadow:InnerShadow = new InnerShadow();
insert “innerShadow: {innerShadow.getAccelType(gc)}” into returnVal;

var invertMask:InvertMask = new InvertMask();
insert “invertMask: {invertMask.getAccelType(gc)}” into returnVal;

var lighting:Lighting = new Lighting();
insert “lighting: {lighting.getAccelType(gc)}” into returnVal;

var motionBlur:MotionBlur = new MotionBlur();
insert “motionBlur: {motionBlur.getAccelType(gc)}” into returnVal;

var perspectiveTransform:PerspectiveTransform = new PerspectiveTransform();
insert “perspectiveTransform: {perspectiveTransform.getAccelType(gc)}” into returnVal;

var reflection:Reflection = new Reflection();
insert “reflection: {reflection.getAccelType(gc)}” into returnVal;

var sepiaTone:SepiaTone = new SepiaTone();
insert “sepiaTone: {sepiaTone.getAccelType(gc)}” into returnVal;

var shadow:Shadow = new Shadow();
insert “shadow: {shadow.getAccelType(gc)}” into returnVal;

return returnVal;
}

Stage {
title: “Leadfoot”
width: 250
height: 400
scene: Scene {
content: [
ListView {
width: 250
items: getAccelerationFaults()
}

]
}
}

16 Comments


[...] Excerpt from: Fumbling Forward » Blog Archive » JavaFX effects and hardware … [...]


 
OtengiM
Jul 20, 2009 at 11:31 am

It seems that CPU/SIMD it is a software renderer. They are optimizing using the SIMD instruction but this is not 3D GPU hardware acceleration or even shaders. Also I dont know much about JavaFX architecture but if they are using something of Java2D, they could be using some of the 3d hardware acceleration pipelines but I dont know to what extent. Also I read that the scenegraph have serious performance problems and the only solution for JavaFX is to replace the existing scenegraph with another, thats a shame.

Better consult to one JavaFX guru for better analisys. In the other side I know Flash 10 and Silverlight 3 begin to use shaders and 3d hardware acceleration on the GPU and if the feature is not supported by the gpu in turns to software rendering(CPU/SIMD).


 

[...] from: Fumbling Forward » Blog Archive » JavaFX effects and hardware … 20 Jul 09 | [...]


 
Eric Wendelin
Jul 20, 2009 at 1:24 pm

I’m actually seeing CPU/Java instead of SIMD on my Toshiba laptop with a crappy nVidia card. Perhaps that could clear up our confusion? I would have to guess that CPU/Java means hardware accelerated. I certainly could be wrong.


 
Dmitri Trembovetski
Jul 20, 2009 at 4:57 pm

There’s a bug in your code which causes the runtime to fall to the default simd backend even if hw accelerated one is available:
> var gc:GraphicsConfiguration[] = gd.getConfigurations();
> insert “blend: {blend.getAccelType(gc)}” into returnVal;
You’re passing an array into getAccelType() function, which actually expects a single element.

Here’s simplified version of your test which reports the hw accel status properly:

import javafx.scene.Scene;
import javafx.scene.control.ListView;
import java.awt.*;
import javafx.scene.effect.*;

/**
* @author steven
*/

def gc = GraphicsEnvironment.
getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
def effects = [
Blend {}
Bloom {}
BoxBlur {}
ColorAdjust {}
DisplacementMap {}
DropShadow {}
Flood {}
GaussianBlur {}
Glow {}
Identity {}
InnerShadow {}
InvertMask {}
Lighting {}
MotionBlur {}
PerspectiveTransform {}
Reflection {}
SepiaTone {}
Shadow {}
];

def accel = for (effect in effects)
“{effect.getClass().getSimpleName()}.getAccelType(gc)={effect.getAccelType(gc)}”;

Scene {
content: ListView {
width: 350
items: accel
}
}

Dmitri


 
Steven Herod
Jul 20, 2009 at 6:18 pm

Delighted to be wrong!

I’ll update the app shortly!


 
Jonathan Giles
Jul 20, 2009 at 6:22 pm

From Chris Campbell at Sun: Intrinsic just means the “platform” handles the filtering operation. Like, Reflection is implemented using Java2D operations, no shaders, no special software loops, so it’s marked “intrinsic”. Yeah, not the best name, but then again, people aren’t supposed to know about getAccelType() either if the apidocs kept it hidden like it’s supposed to be


 
Jonathan Giles
Jul 20, 2009 at 7:18 pm

Try the following code to get the graphics config:

var ge:GraphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
var gs:GraphicsDevice[] = ge.getScreenDevices();
var gc:GraphicsConfiguration = gs[0].getDefaultConfiguration();


 
Twitted by sherod
Jul 20, 2009 at 10:58 pm

[...] This post was Twitted by sherod [...]


 
Stephen Chin
Jul 21, 2009 at 12:21 am

I tracked down the issue with hardware acceleration on Windows Vista/7 where it was reporting CPU/SIMD from webstart applications, but Direct3D from regular applications.

It seems like there is a bug in the Decora code that prevents the Direct3D pipeline from running in the sandbox. If you sign your application you will see that the problem goes away and it behaves identically to a desktop app, taking advantage of the Direct3D pipeline. I filed this issue as RT-5193 in the JavaFX issue tracking system.


 
Steven Herod
Jul 21, 2009 at 12:47 am

Thanks Steve

And to think I paused over that checkbox and though. “Nah, it doesn’t need signing…”

This might explain why it seems to be fine on mac.

I’m going to write all this up in another blog entry…


 
Richard Osbaldeston
Jul 21, 2009 at 1:01 am

Hmm I’ve just run it under Windows XP SP2 and got the same mix of CPU/SIMD & Intrinsic result (NVidia 6600 here). The app was definitely signed but I still didnt see Direct3D, have Dmitri’s changes been applied – did they make any difference?


 
Richard Osbaldeston
Jul 21, 2009 at 1:12 am

Oh wait a minute app is signed but theres no security declaration in the JNLP resources section? was expecting to see ??

I really hate that little floaty warning app window icon.. completely missed it, joe user dosent stand a chance (not that he’d understand even if he did).


 
Dmitri Trembovetski
Jul 21, 2009 at 2:07 pm

Note that this becomes an issue only if the application explicitly initializes effect’s peers by calling Effect.getAccelType() before the runtime has a chance to do so. When that happens there’s user code on stack which causes the security exception.

This version of the app should correctly report acceleration:
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.scene.effect.*;
import javafx.stage.Stage;
import java.awt.GraphicsEnvironment;
import javafx.scene.shape.Rectangle;

def gc = GraphicsEnvironment.
getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
def effects = [
Blend {}
Bloom {}
BoxBlur {}
ColorAdjust {}
DisplacementMap {}
DropShadow {}
Flood {}
GaussianBlur {}
Glow {}
Identity {}
InnerShadow {}
InvertMask {}
Lighting {}
MotionBlur {}
PerspectiveTransform {}
Reflection {}
SepiaTone {}
Shadow {}
];
var accel : String[];

Stage {
scene: Scene {
content: [
Rectangle { width: 10 height: 10 effect: GaussianBlur {} }
ListView {
width: 350
items: bind accel
}
]
}
}
FX.deferAction(function():Void {
accel = for (effect in effects)
“{effect.getClass().getSimpleName()}.getAccelType(gc)={effect.getAccelType(gc)}”;
});

Dmitri


 

[...] forget everything I said in part 1 and part 2 of this [...]


 

[...] This is a nice little article which helps you understand whether your javafx implementation is hardware accelerated.Fumbling Forward » Blog Archive » JavaFX effects and hardware acceleration… [...]


 

Reply

Copyright © 2010 Fumbling Forward All rights reserved. Theme by Laptop Geek.