D3D Shader/OpenGL」カテゴリーアーカイブ

Apple Watch の CPU の種類と浮動小数点演算速度

VFP Benchmark を走らせてみました。

ARCH: ARMv7A
FPU: VFPv4-D32 NEON
SingleT SP max: 0.951 GFLOPS
SingleT DP max: 0.470 GFLOPS
MultiT  SP max: 0.945 GFLOPS
MultiT  DP max: 0.469 GFLOPS
CPU core: 1
NEON: yes
FMA: yes

詳細な結果はこちら。

VFP Benchmark Log

下記は抜粋です。

* VFP/NEON (single fp)               sec     MFLOPS     MFLOPS
--------------------------------------------------------------
VFP fmuls (32bit x1) n8       :    2.649      453.0      453.0
VFP fadds (32bit x1) n8       :    2.557      469.3      469.3
VFP fmacs (32bit x1) n8       :    2.586      928.2      928.2
NEON vmul.f32 (32bit x4) n8   :   10.097      475.4      475.4
NEON vadd.f32 (32bit x4) n8   :   10.182      471.4      471.4
NEON vmla.f32 (32bit x4) n8   :   10.165      944.4      944.4

* VFP/NEON (double fp)               sec     MFLOPS     MFLOPS
--------------------------------------------------------------
VFP fmuld (64bit x1) n8       :   10.164      118.1      118.1
VFP faddd (64bit x1) n8       :    2.554      469.8      469.8
VFP fmacd (64bit x1) n8       :   10.746      223.3      223.3

Single core で VFPv4 と NEON に対応していることがわかります。
ただし NEON でも結果はスカラーと同じ速度しか出ていません。(上の表の MFLOPS)
また倍精度の乗算速度も加算の 1/4 まで落ちています。

これらの特徴を踏まえると Cortex-A7 が使われているものと思われます。速度を見る限り実行クロックは 500MHz 程度でしょう。CPU core 毎の浮動小数点演算能力 (特徴) は下記にまとめています。

CPU の浮動小数点演算能力の詳細

Apple S1 のアプリケーションプロセッサは Android Wear に使われている Snapdragon 400 と比べると少々非力です。CPU core は同じですがクロックはおよそ半分で Single core になります。

↓ 一応 Apple Watch で ChiRaKS 動きました。まだ操作と速度に問題があります。

chiraks_awatch01.png

関連エントリ
iPod touch 6 の浮動小数点演算速度は Core 2 Duo ライン超え
Android Wear Sony SmartWatch 3 SWR50 は速い
iPad Air 2 (Apple A8X) の浮動小数点演算能力
Android Wear VFP Benchmark
ndroid Wear LG G Watch (LG-W100) の速度(実測)
VFP Benchmark 関連

AEP を取り込んだ OpenGL ES 3.2 は機能面で Desktop に並ぶ, Android は Vulkan へ

OpenGL ES 3.2 が登場しました。OpenGL ES 3.1 AEP (Android Extension Pack) の機能が取り込まれています。これまで ES にはなかった GeometryShader や Tessellator などに対応しており、機能面では OpenGL 4.x/Direct3D 11 と完全に並ぶことになります。

おそらく AEP 対応 GPU がそのまま OpenGL ES 3.2 になるのではないかと思われます。
現在発売されている端末で AEP (GL_ANDROID_extension_pack_es31a) が含まれている GPU は下記の通り。

Tegra K1  Keper (192)     SHIELD Tablet / Nexus 9
Tegra X1  Maxwell (256)   SHIELD
Adreno 4xx                Snapdragon 805/808/810 等

Intel HD Graphics Gen8 も対応しているので、Cherry Trail 搭載 Android 端末が出ればこの一覧に入ることになるでしょう。

シェーダーのバージョンも 3.2 (320 es) です。Version 番号の空きを使い尽くしたので、もし次があるなら番号が飛ぶことになるかもしれません。(GLSL Version 一覧)

NVIDIA の Beta Driver がすでに使えるようになっているので試してみました。
GL_ARB_ES3_2_compatibility で実際に Context を作ることができます。

GL_VERSION: OpenGL ES 3.2 NVIDIA 355.58
GL_RENDERER: GeForce GTX 760/PCIe/SSE2
GL_VENDOR: NVIDIA Corporation
GL_SHADING_LANGUAGE_VERSION: OpenGL ES GLSL ES 3.20

↓詳細はこちら

Desktop GPU Extensions

OpenGL ES 3.2 は ASTC 対応ですが、やはり OpenGL 4.5 context のまま Texture を読むとパフォーマンスの警告が出るようです。

また OpenGL 4.5 の方にはかなり気になる Extension が増えています。スレッドを使ったシェーダーのコンパイルが可能になるとのこと。

GL_ARB_parallel_shader_compile

なお Android もついに低レベル API である Vulkan 対応を発表しています。予想されてきたことではありますが、低レベル API はプラットフォームごとに完全に分かれることになりました。

API             Platform
------------------------------------------
Direct3D 12     Windows Desktop / Mobile
Metal           iOS / Mac OS X
Vulkan          Android

パフォーマンスだけでなく Mobile / Desktop API の統合や、レガシーな OpenGL API からの脱却などさまざまなメリットもありますが、開発者にとっては悩ましいところです。

関連エントリ
Desktop GPU と OpenGL ES 3.1 API
Android 5.x OpenGL ES 3.1 と対応 GPU
OpenGL ES 3.1 は OpenGL 4.x 相当で ComputeShader に対応
3D 低レベル API の現状 Direct3D 12/Metal

Metal iOS 半透明ソート (PowerVR GX6450)

ROV のテストで用いたシェーダーはそのまま Metal でも動きました。

metal_ios_sort.png

↑上記は iPod touch 6 (A8) の結果です。
左が DepthTest 無しの通常の RenderTarget の内容、
右がバッファをソートした結果。
iOS のみです。Metal というより PowerVR の機能です。

fragment PS_OUT pmain(
    VS_OUT  pin     [[stage_in]],
    constant GeometryBuffer&    geometry    [[buffer(1)]],
    half4   rcolor  [[color(0)]],
    float4  zstack  [[color(1)]],
    uint4   stack   [[color(2)]]
    )
{
    PS_OUT  pout;
    half3   Light= normalize( half3( 0.0h, -0.5h, -1.0h ) );
    half3   normal= normalize( half3(pin.Normal) );
    half3   eyevec= normalize( half3( 0.0h, 0.0h, -120.0h ) - half3(pin.WPos.xyz) );
    half3   hvect= normalize( eyevec.xyz + Light.xyz );
    half3   spec= pow( saturate( dot( hvect, normal ) ), 82.0h ) * saturate( half3(geometry.Color.xyz) + half3( 0.6h, 0.6h, 0.6h ) );
    half    diffuse= saturate( max( dot( normal, Light ), 0.0h ) + 0.2h );
    half4   color;
    color.xyz= half3(geometry.Color.xyz) * diffuse + spec;
    color.w= half(geometry.Color.w);
    uint    color_enc= EncodeColor( color );
    float   pz= pin.Position.z;
    if( pz < zstack.w ){
        zstack.w= pz;
        stack.w= color_enc;
    }
    if( pz < zstack.z ){
        zstack.w= zstack.z;
        stack.w= stack.z;
        zstack.z= pz;
        stack.z= color_enc;
    }
    if( pz < zstack.y ){
        zstack.z= zstack.y;
        stack.z= stack.y;
        zstack.y= pz;
        stack.y= color_enc;
    }
    if( pz < zstack.x ){
        zstack.y= zstack.x;
        stack.y= stack.x;
        zstack.x= pz;
        stack.x= color_enc;
    }
    pout.Color= color;
    pout.Color1= zstack;
    pout.Color2= stack;
    return  pout;
}

関連エントリ
Direct3D12 ROV を試してみる (3) 半透明ソートと Intel HD Graphics
Direct3D12 ROV を試してみる (2) Depth Test と半透明ソート
Direct3D12 ROV (Rasterizer Order View) を試してみる
3D 低レベル API の違い Direct3D 12/Metal
Direct3D 12 GeForce GTX970 は FeatureLevel 12_1 対応、Resource Bind/Heap Tier は低い
3D 低レベル API の現状 Direct3D 12/Metal

Direct3D12 ROV を試してみる (3) 半透明ソートと Intel HD Graphics

DirectX12 / DirectX11.3 の ROV のテストです。
前回はこちら→ 「Direct3D12 ROV を試してみる (2) Depth Test と半透明ソート

やっと Intel HD Graphics でも動くようになりました。

dx12_rov_suzanne01.png

↑Celeron N3150 Braswell Intel HD Graphics (Gen8) 使用

Intel HD Graphcis で問題だったのは PipelineState 生成時にエラーになることです。いろいろ試した結果 Shader に原因があることが判明。理由はよくわかっていませんが if 文中の代入を無くし、同等の加算に置き換えることで回避出来ました。GeForce では元のままで問題ありませんでした。

zstack_x= pz;
stack_x= color_enc;

↓ Intel HD Graphics

zstack_x*= 1e-32f;
zstack_x+= pz;
stack_x*= 0;
stack_x+= color_enc;

あとは Typed UAV を使わずに展開しています。シェーダーは下記の通り。

// hlsl
struct PS_OUT   {
    float4  Color   :   SV_Target;
};

RasterizerOrderedTexture2D    UColor  : register( u0 );
RasterizerOrderedTexture2D   UDepth  : register( u1 );
RasterizerOrderedTexture2D    UStack  : register( u2 );
RasterizerOrderedTexture2D   UZStack : register( u3 );

PS_OUT  pmain( VS_OUT pin, float4 pos : SV_Position )
{
    PS_OUT  pout;
    float3  Light= normalize( float3( 0.0f, -0.5f, -1.0f ) );
    float3  normal= normalize( pin.Normal );

    float3  cp= normalize( float3(0.0f, 0.0f, -120.0f) - pin.WPos.xyz );
    float3  hv= normalize( cp.xyz + Light.xyz );
    float3  specular= pow( saturate( dot( hv, normal ) ), 82.0f ) * saturate( Color.xyz + float3(0.6f, 0.6f, 0.6f) );
    float   diffuse= saturate( max( dot( normal, Light ), 0.0f ) + 0.2f );

    float4  color;
    color.xyz= Color.xyz * diffuse + specular;
    color.w= Color.w;
    pout.Color= color;

    float   pz= pos.z;
    uint2   addr2x= uint2( pos.xy );
    addr2x.x*= 4;
    uint2   addr2y= uint2( addr2x.x + 1, addr2x.y );
    uint2   addr2z= uint2( addr2x.x + 2, addr2x.y );
    uint2   addr2w= uint2( addr2x.x + 3, addr2x.y );

    uint    color_enc= EncodeColor( color );
    uint    stack_x= UStack[addr2x];
    uint    stack_y= UStack[addr2y];
    uint    stack_z= UStack[addr2z];
    uint    stack_w= UStack[addr2w];
    float   zstack_x= UZStack[addr2x];
    float   zstack_y= UZStack[addr2y];
    float   zstack_z= UZStack[addr2z];
    float   zstack_w= UZStack[addr2w];
    if( pz < zstack_w ){
        zstack_w*= 1e-32f;
        zstack_w+= pz;
        stack_w*= 0;
        stack_w+= color_enc;
    }
    if( pz < zstack_z ){
        zstack_w= zstack_z;
        stack_w= stack_z;
        zstack_z*= 1e-32f;
        zstack_z+= pz;
        stack_z*= 0;
        stack_z+= color_enc;
    }
    if( pz < zstack_y ){
        zstack_z= zstack_y;
        stack_z= stack_y;
        zstack_y*= 1e-32f;
        zstack_y+= pz;
        stack_y*= 0;
        stack_y+= color_enc;
    }
    if( pz < zstack_x ){
        zstack_y= zstack_x;
        stack_y= stack_x;
        zstack_x*= 1e-32f;
        zstack_x+= pz;
        stack_x*= 0;
        stack_x+= color_enc;
    }
    UStack[addr2x]= stack_x;
    UStack[addr2y]= stack_y;
    UStack[addr2z]= stack_z;
    UStack[addr2w]= stack_w;
    UZStack[addr2x]= zstack_x;
    UZStack[addr2y]= zstack_y;
    UZStack[addr2z]= zstack_z;
    UZStack[addr2w]= zstack_w;

    return  pout;
}

関連エントリ
Direct3D12 ROV を試してみる (2) Depth Test と半透明ソート
Direct3D12 ROV (Rasterizer Order View) を試してみる
3D 低レベル API の違い Direct3D 12/Metal
Direct3D 12 GeForce GTX970 は FeatureLevel 12_1 対応、Resource Bind/Heap Tier は低い
3D 低レベル API の現状 Direct3D 12/Metal

Direct3D12 ROV を試してみる (2) Depth Test と半透明ソート

DirectX12 / DirectX11.3 の ROV のテスト続きです。
前回はこちら→ 「Direct3D12 ROV (Rasterizer Order View) を試してみる

ROV は自分で Depth Test できます。
R32_FLOAT の UAV を 1枚追加しています。

RasterizerOrderedTexture2D UBuffer0 : register( u0 ); // R8G8B8A8
RasterizerOrderedTexture2D  UBuffer1 : register( u1 ); // R32F

PS_OUT pmain( VS_OUT pin, float4 pos : SV_Position )
{
	float	diffuse= max( dot( pin.Normal, Light ), 0.0f ) + 0.2f;
    float4  color= Color * diffuse;
	uint2	addr= uint2( pos.xy );

	float	depth= UBuffer1[addr];
	if( pos.z <= depth ){
		UBuffer0[addr]= color;    // color書き込み
		UBuffer1[addr]= pos.z;    // depth書き込み
	}

    PS_OUT  pout;
    pout.Color= color;
    return  pout;
}

下記は UAV (UBuffer0) の結果です。(Geforce GTX960)

↓ROV 無し, Depth Test 無し
dx12_rov_teapot_01.png

↓ROV あり, Depth Test 無し
dx12_rov_teapot_02.png

↓ROV 無し, Depth Test あり
dx12_rov_teapot_03.png

↓ROV あり, Depth Test あり
dx12_rov_teapot_04.png

ROV の目的とも言える半透明ソートも試してみました。

dx12_rov_teapot_05.png

力技ですがバッファ固定で 4レイヤーまで。一旦 UAV にカラーを保存して 2 pass 目で Blend しています。fp32 Blend を使った方法と違い手前の 4枚を選択できるので破綻が少なくなっています。

関連エントリ
Direct3D12 ROV (Rasterizer Order View) を試してみる
3D 低レベル API の違い Direct3D 12/Metal
Direct3D 12 GeForce GTX970 は FeatureLevel 12_1 対応、Resource Bind/Heap Tier は低い
3D 低レベル API の現状 Direct3D 12/Metal