Easy GPU Benchmark
Flash Plaer 11対応のGPUの簡易ベンチマークです。
CPUをなるべく使わず、GPUを痛めつけます。
※負荷のためか、OSが落ちてしまった方がいらっしゃるので編集中のファイルは保存して閉じる等して、十分に気をつけてください。
矩形の描写数を増やしていき、
直近10秒の平均fpsが30以下になった時点の矩形の数をスコアとしています。
GPUスペックの高い人は1分以上時間がかかるかもしれません。
GPUと一緒に教えていただけるとありがたいです。
FPS算出方法その他UI : http://wonderfl.net/c/hvy2
GPUの調べ方
Windows
ファイル名を指定して実行(ウィンドウズキー+R)→"dxdiag"で実行→"ディスプレイ"タブ→デバイス
GPU-Z
http://www.techpowerup.com/gpuz/
Mac
りんご→このMacについて→詳しい情報→ハードウェア→グラフィックス/ディスプレイ
linux
/sbin/lspci | grep VGA
package {
import com.adobe.utils.AGALMiniAssembler;
import flash.display.Sprite;
import flash.display.Stage3D;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.display3D.Context3D;
import flash.display3D.Context3DCompareMode;
import flash.display3D.Context3DProgramType;
import flash.display3D.Context3DRenderMode;
import flash.display3D.Context3DTriangleFace;
import flash.display3D.Context3DVertexBufferFormat;
import flash.display3D.IndexBuffer3D;
import flash.display3D.Program3D;
import flash.display3D.VertexBuffer3D;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.net.navigateToURL;
import flash.net.URLRequest;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.utils.ByteArray;
import flash.utils.getTimer;
/**
* ...
* @author
*/
[SWF(frameRate=240)]
public class Main extends Sprite {
private const MAX_PARTICLES:uint = 16383;
private const STEP:uint = 50;
//
private var stageWidth:int;
private var stageHeight:int;
//
private var stage3D:Stage3D;
private var context3D:Context3D;
private var indexBuffer:IndexBuffer3D;
private var vertexBufferIndex:uint = 0;
private var draw:uint = 0;
//
private var score:uint = 0;
private var txtDrawCnt:TextField;
private var txtFrameCnt:TextField;
private var frameCnt:int = 0;
private var oldTimer:int;
private var frameRates:Vector.<int> = Vector.<int>([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
private var frameIndex:int = 0;
private var aveTotal:int = 0;
private var aveLength:uint = 0;
private var ave:int = 120;
public function Main():void {
Wonderfl.disable_capture();
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
stageWidth = stage.stageWidth;
stageHeight = stage.stageHeight;
//
txtDrawCnt = new TextField();
txtDrawCnt.autoSize = TextFieldAutoSize.LEFT;
txtDrawCnt.background = true;
addChild(txtDrawCnt);
//
txtFrameCnt = new TextField();
txtFrameCnt.autoSize = TextFieldAutoSize.LEFT;
txtFrameCnt.background = true;
txtFrameCnt.y = 30;
addChild(txtFrameCnt);
//
stage3D = stage.stage3Ds[0];
stage3D.addEventListener(Event.CONTEXT3D_CREATE, onContextCreate);
stage3D.requestContext3D(Context3DRenderMode.AUTO);
}
private function onContextCreate(e:Event):void {
context3D = stage3D.context3D;
//context3D.enableErrorChecking = true;
if (context3D.driverInfo.match("Software")){
complete(false);
} else {
prepare();
}
}
private function prepare():void {
context3D.configureBackBuffer(stageWidth, stageHeight, 0, true);
//vertex buffer
var vertexBuffer:VertexBuffer3D = context3D.createVertexBuffer(MAX_PARTICLES * 4, 5);
var vertices:Vector.<Number> = new Vector.<Number>(MAX_PARTICLES * 4);
var index:uint = 0;
var offsetX:Vector.<Number> = Vector.<Number>([-0.1, -0.1, 0.1, 0.1]);
var offsetY:Vector.<Number> = Vector.<Number>([-0.1, 0.1, 0.1, -0.1]);
for (var i:int = 0; i < MAX_PARTICLES; i++){
var posX:Number = (Math.random() - 0.5) * 2;
var posY:Number = (Math.random() - 0.5) * 2;
var color:uint = Math.random() * 0x1000000;
var r:Number = ((color >> 16) & 0xff) / 255;
var g:Number = ((color >> 8) & 0xff) / 255;
var b:Number = (color & 0xff) / 255;
for (var j:int = 0; j < 4; j++){
vertices[index++] = posX + offsetX[j];
vertices[index++] = posY + offsetY[j];
vertices[index++] = r;
vertices[index++] = g;
vertices[index++] = b;
}
}
vertexBuffer.uploadFromVector(vertices, 0, MAX_PARTICLES * 4);
//index buffer
indexBuffer = context3D.createIndexBuffer(MAX_PARTICLES * 6);
var indeices:Vector.<uint> = new Vector.<uint>(MAX_PARTICLES * 6);
index = 0;
for (var k:int = 0; k < MAX_PARTICLES; k++){
var n:uint = k * 4;
indeices[index++] = n;
indeices[index++] = n + 1;
indeices[index++] = n + 2;
indeices[index++] = n;
indeices[index++] = n + 2;
indeices[index++] = n + 3;
}
indexBuffer.uploadFromVector(indeices, 0, MAX_PARTICLES * 6);
//shader and set Context3D
var shaderProgram:Program3D = context3D.createProgram();
var vertexShader:ByteArray = new AGALMiniAssembler().assemble(Context3DProgramType.VERTEX, "mov op va0\n" + "mov v0 va1\n");
var fragmentShader:ByteArray = new AGALMiniAssembler().assemble(Context3DProgramType.FRAGMENT, "mov oc v0\n");
//var vertexShaderStr:String="oAEAAAChAAAAAAAAAA8DAAAA5AAAAAAAAAAAAAAAAAAAAAAAAA8EAQAA5AAAAAAAAAAAAAAAAA==";
//var fragmentShaderStr:String="oAEAAAChAQAAAAAAAA8DAAAA5AQAAAAAAAAAAAAAAA==";
//var base64Decoder:Base64Decoder = new Base64Decoder();
//base64Decoder.decode(vertexShaderStr);
//vertexShader = base64Decoder.toByteArray();
//vertexShader.endian = Endian.LITTLE_ENDIAN;
//base64Decoder.decode(fragmentShaderStr);
//fragmentShader = base64Decoder.toByteArray();
//fragmentShader.endian = Endian.LITTLE_ENDIAN;
shaderProgram.upload(vertexShader, fragmentShader);
context3D.setProgram(shaderProgram);
context3D.setDepthTest(true, Context3DCompareMode.ALWAYS)
context3D.setCulling(Context3DTriangleFace.BACK);
context3D.setVertexBufferAt(0, vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_2);
context3D.setVertexBufferAt(1, vertexBuffer, 2, Context3DVertexBufferFormat.FLOAT_3);
//
oldTimer = getTimer();
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
//
private function onEnterFrame(e:Event):void {
updateFrame();
if (ave <= 30){
removeEventListener(Event.ENTER_FRAME, onEnterFrame);
complete(true);
return;
}
//
draw += STEP;
score += STEP;
if (draw > MAX_PARTICLES){
draw -= MAX_PARTICLES;
vertexBufferIndex++;
}
txtDrawCnt.text = "score : " + score;
//
context3D.clear();
var drawT:uint;
for (var i:int = 0; i <= vertexBufferIndex; i++){
if (i == vertexBufferIndex){
drawT = draw << 1;
} else {
drawT = MAX_PARTICLES << 1;
}
context3D.drawTriangles(indexBuffer, 0, drawT);
}
context3D.present();
}
//
private function updateFrame():void {
frameCnt++;
if (getTimer() - oldTimer >= 1000){
aveTotal += frameCnt;
if (aveLength < 10){
aveLength++;
} else {
aveTotal -= frameRates[frameIndex];
}
frameRates[frameIndex] = frameCnt;
ave = aveTotal / aveLength;
frameIndex = ++frameIndex % 10;
//
txtFrameCnt.text = "fps : " + frameCnt + "/" + stage.frameRate + "\nave : " + ave;
frameCnt = 0;
oldTimer = getTimer();
}
}
private function complete(isSupported:Boolean):void {
var tf:TextField = new TextField();
tf.autoSize = TextFieldAutoSize.LEFT;
tf.background = true;
tf.backgroundColor = 0xffffff;
if (isSupported){
tf.text = "YOUR SCORE : " + score;
tf.scaleX = tf.scaleY = 3;
} else {
tf.text = "Hardware accelerated rendering\nis not supported\non YOUR GPU or CHIPSET";
tf.scaleX = tf.scaleY = 2;
}
tf.x = stageWidth / 2 - tf.width / 2;
tf.y = stageHeight / 2 - tf.height;
addChild(tf);
//
var button:TextField = new TextField();
button.background = true;
button.backgroundColor = 0xcccccc;
button.autoSize = TextFieldAutoSize.LEFT;
button.selectable = false;
button.text = "twitterに投稿";
button.scaleX = button.scaleY = 2;
button.x = stageWidth / 2 - button.width / 2;
button.y = stageHeight / 2;
var result:String
if (isSupported){
result = String(score);
} else {
result = "not supported";
}
var url:String = "http://twitter.com/?status=Easy GPU Benchmark SCORE : " + result + " [" + context3D.driverInfo + "] http://wonderfl.net/c/cTZT %23Stage3DBench";
button.addEventListener(MouseEvent.CLICK, function():void {
navigateToURL(new URLRequest(url));
});
addChild(button);
}
}
}