Archives

July 2015 の記事

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<uint>    UColor  : register( u0 );
RasterizerOrderedTexture2D<float>   UDepth  : register( u1 );
RasterizerOrderedTexture2D<uint>    UStack  : register( u2 );
RasterizerOrderedTexture2D<float>   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


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

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

RasterizerOrderedTexture2D<float4> UBuffer0 : register( u0 ); // R8G8B8A8
RasterizerOrderedTexture2D<float>  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


DirectX12 / DirectX11.3 の新機能である ROV (Rasterizer Order View) を試してみました。対応している GPU は下記の通り。新 Maxwell (GTX900) と HD Graphics 系です。ただし Intel HD Graphics は Typed UAV がありません。両方対応しているのは Maxwell 2 だけとなっています。

                          ROV   TypedUAV
----------------------------------------------------
GeForce  Maxwell 2         Y       Y      (GTX900)
GeForce  Maxwell 1         N       Y      (GTX750)
GeForce  Kepler            N       N
RADEON GCN 1.1             N       Y
RADEON GCN 1.0             N       Y
Intel HD Graphics Gen8     Y       N      (Broadwell)
Intel HD Graphics Gen7.5   Y       N      (Haswell)

より詳しい機能表は下記のページに掲載しています。

Direct3D 12 (DirectX 12) Windows 詳細

Shader は複数の Unit で同時に走るので、実行順番は保証されずバッファアクセスは競合します。しかしながら Pixel の出力自体は順序が保証されており結果は一定です。Blend や Depth/Stencil Test では同一の Draw Call で重ね書きしても正しい値で評価されます。
シェーダー内で任意に読み書きできる UAV はこのルールが適用されませんでした。ROV を使うと UAV の読み書きの整合性が取れるようになります。

(1) が通常の RenderTarget への描画です。
(2) は RenderTarget への書き込みと全く同じものを UAV にも書き込んでいます。擬似 MRT

// (1) hlsl
Texture2D       ColorMap0   : register( t0 );
SamplerState    Sampler0    : register( s0 );

struct PS_OUT {
    float4  Color   : SV_Target;
};

PS_OUT pmain( VS_OUT pin )
{
    PS_OUT  pout;
    float4  color_map= ColorMap0.Sample( Sampler0, pin.Texcoord );
    pout.Color= color_map;
    return  pout;
}


// (2) hlsl
Texture2D           ColorMap0   : register( t0 );
SamplerState        Sampler0    : register( s0 );
RWTexture2D<float4> UAVBuffer0  : register( u0 );

PS_OUT pmain( VS_OUT pin, float4 pos : SV_Position )
{
    PS_OUT  pout;
    float4  color_map= ColorMap0.Sample( Sampler0, pin.Texcoord );
    pout.Color= color_map;

    UAVBuffer0[ uint2(pos.xy) ]= color_map;
    return  pout;
}


dx12_rov_01.png

↑(2) の結果を 2つ並べて表示したのがこちらです。左が RTV (RenderTarget), 右が UAV です。使用したのは GeForce GTX960 (Maxwell2)。

↑右の UAV では重ね合わせに問題が生じています。並列度が上がるためプリミティブが小さい方が発生しやすいです。
これを ROV に変更したのが (3) です。

// (3) hlsl
Texture2D           ColorMap0   : register( t0 );
SamplerState        Sampler0    : register( s0 );
RasterizerOrderedTexture2D<float4>    UAVBuffer0  : register( u0 );

PS_OUT pmain( VS_OUT pin, float4 pos : SV_Position )
{
    PS_OUT  pout;
    float4  color_map= ColorMap0.Sample( Sampler0, pin.Texcoord );
    pout.Color= color_map;

    UAVBuffer0[ uint2(pos.xy) ]= color_map;
    return  pout;
}


dx12_rov_02.png

↑ (3) の結果です。左が RTV (RenderTarget), 右が ROV。
ROV では重ね合わせが正しく行われ RTV と見た目が同一になりました。


さらに ROV では、RenderTarget と違って値をシェーダーで読むことができます。
(4) は Shader 内で Blend したもの。

// (4) hlsl
Texture2D           ColorMap0   : register( t0 );
SamplerState        Sampler0    : register( s0 );
RasterizerOrderedTexture2D<float4>   UAVBuffer0  : register( u0 );

PS_OUT pmain( VS_OUT pin, float4 pos : SV_Position )
{
    PS_OUT  pout;
    float4  color_map= ColorMap0.Sample( Sampler0, pin.Texcoord );
    pout.Color= color_map;

    float4  prev_color= UAVBuffer0[uint2(pos.xy)];
    UAVBuffer0[uint2(pos.xy)]= prev_color * 0.7f + map * 0.7f;
    return  pout;
}


dx12_rov_03.png

↑(4) の結果。左が RTV, 右が ROV の半透明合成

ROV はかなり自由度が高く MRT の制限がほぼ無くなったような印象です。パフォーマンス等は調べてませんがかなり応用が効きそうです。

なお Intel HD Graphics では Typed UAV が使えないので、今まで使用してきた下記のコードが動きません。

RWTexture2D<float4> UAVBuffer0  : register( u0 );
RasterizerOrderedTexture2D<float4>    UAVBuffer0  : register( u0 );

一応対応してみました。UAV を R32_UINT として読み込みます。

// cpp HD Graphics
#define USE_TYPED_UAV 0
    D3D12_RESOURCE_DESC res_desc;
    flatlib::memory::MemClear( res_desc );
    res_desc.Dimension= D3D12_RESOURCE_DIMENSION_TEXTURE2D;
    res_desc.Alignment= 0;
    res_desc.Width= width;
    res_desc.Height= height;
    res_desc.DepthOrArraySize= 1;
    res_desc.MipLevels= 1;
#if USE_TYPED_UAV
    res_desc.Format= DXGI_FORMAT_R8G8B8A8_UNORM;
#else
    res_desc.Format= DXGI_FORMAT_R8G8B8A8_TYPELESS;
#endif
    res_desc.SampleDesc.Count= 1;
    res_desc.Layout= D3D12_TEXTURE_LAYOUT_UNKNOWN;
    res_desc.Flags= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS|D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;

    D3D12_HEAP_PROPERTIES   heap;
    flatlib::memory::MemClear( heap );
    heap.Type= D3D12_HEAP_TYPE_DEFAULT;
    heap.CPUPageProperty= D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
    heap.MemoryPoolPreference= D3D12_MEMORY_POOL_UNKNOWN;

    D3D12_CLEAR_VALUE   clear_value;
    flatlib::memory::MemClear( clear_value );
    clear_value.Format= DXGI_FORMAT_R8G8B8A8_UNORM;

    iD3DDevice->CreateCommittedResource(
            &heap,
            D3D12_HEAP_FLAG_NONE,
            &res_desc,
            D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
            &clear_value, IID_PPV_ARGS(&iUAVTexture0) );

    D3D12_UNORDERED_ACCESS_VIEW_DESC    uav_desc;
    flatlib::memory::MemClear( uav_desc );
#if USE_TYPED_UAV
    uav_desc.Format= DXGI_FORMAT_R8G8B8A8_UNORM;
#else
    uav_desc.Format= DXGI_FORMAT_R32_UINT;
#endif
    uav_desc.ViewDimension= D3D12_UAV_DIMENSION_TEXTURE2D;

    UINT    uav_descriptor_size= iD3DDevice->GetDescriptorHandleIncrementSize( D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV );
    D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle= iHeapUAV->GetCPUDescriptorHandleForHeapStart();
    cpu_handle.ptr+= uav_descriptor_size * (UAV_DYNAMIC_COUNT);
    iD3DDevice->CreateUnorderedAccessView( iUAVTexture0, nullptr, &uav_desc, cpu_handle );

シェーダーは下記の通り。

// hlsl (HD Graphics)
//RWTexture2D<uint>    UAVBuffer0    : register( u0 );
RasterizerOrderedTexture2D<uint>   UAVBuffer0  : register( u0 );

PS_OUT  pmain( VS_OUT pin, float4 pos : SV_Position )
{
    PS_OUT  pout;
    float4  color_map= TextureMap0.Sample( Sampler0, pin.Texcoord );
    pout.Color= color_map;

    uint    fetch= UAVBuffer0[ uint2(pos.xy) ];
    float4  prev_color;
    prev_color.x= ((fetch>> 0) & 255) * (1.0f/255.0f);
    prev_color.y= ((fetch>> 8) & 255) * (1.0f/255.0f);
    prev_color.z= ((fetch>>16) & 255) * (1.0f/255.0f);
    prev_color.w= ((fetch>>24) & 255) * (1.0f/255.0f);
    float4  color= saturate( prev_color * 0.7f + color_map * 0.7f );
    UAVBuffer0[ uint2(pos.xy) ]= ((uint)(color.x * 255.0f) << 0)
                                |((uint)(color.y * 255.0f) << 8)
                                |((uint)(color.z * 255.0f) <<16)
                                |((uint)(color.w * 255.0f) <<24);
    return  pout;
}

これで Intel HD Graphics でも同等の結果になりました。
RADEON は残念ながら ROV 非対応です。下記は RADEON GCN 1.1 (UAV) の結果で、こちらも GeForce 同様ブロック状のノイズが生じています。

dx12_rov_04rad.png


関連エントリ
3D 低レベル API の違い Direct3D 12/Metal
Direct3D 12 GeForce GTX970 は FeatureLevel 12_1 対応、Resource Bind/Heap Tier は低い
3D 低レベル API の現状 Direct3D 12/Metal
Direct3D 12 (DirectX12) GPU と API の対応表
DirectX 12 (Direct3D 12) と GPU の対応


前回はこちら→ 「3D 低レベル API の現状 Direct3D 12/Metal

新しい API はあらゆる面で負荷の低減が行われています。

・バッファの無駄なコピーの排除
・Command など動的な変換をできるだけ避ける
・GPU との同期も暗黙に行わずアプリケーションに委ねる

自動化されていると便利ですが、アプリケーションによっては内部の仕組みが見えづらく、最適化の妨げになる場合があります。API の低レベル化は、オーバーヘッドを減らすと同時に用途に合わせて最適化が出来る範囲が広がりました。
具体的にどのあたりがこれまでと異なっているのか、いくつかまとめてみます。


● CommandBuffer と CommandQueue (D3D12/Metal)

従来の API では Context に暗黙の CommandBuffer が含まれていました。必要に応じてその都度 Command 生成 (Compile) やバッファ構築が行われており、実行や GPU との同期も表面上見えません。

新しい API では明示的に CommandBuffer (CommandList) を作成します。CommandBuffer はいくつでも生成可能でスレッド化も容易です。実行も直接 Command Queue に登録することで行います。API によっては再利用可能な事前コンパイルされた Buffer を作っておくことも可能です。CommandBuffer の完了は自分で判定する必要があります。


● PipelineState (D3D12/Metal)

以前の API では Context が State を所有していました。State は常に変更される可能性があるため Draw の直前まで内容を確定できません。Draw 命令のタイミングで必要な State を集めて Command 化が行われるため Draw Call API の負担が大きくなります。

新しい API では描画に必要な State の大半を Pipeline State に集約しています。この Object は事前に生成できるので、Command Compile や Error 判定など負荷のかかる処理を予め済ませておくことが可能。Draw Call の負担を大きく減らすことに繋がります。


● Resource Binding Table (D3D12)

Shader に割り当てるリソースのテーブルもこれまでは Context が所有していました。CBV 14個、SRV 128個、Sampler 16個 など API 毎に決められた数のスロットがあります。描画のたびに上書きされるため、Draw 毎に CommandBuffer へのコピーが必要でした。

新しい API では Resource Binding Table (Descriptor Table) もユーザーサイドで用意します。Table のサイズに制限はなくなり API 上の上限は撤廃。任意の部分を Register に割り当てるなどマッピングの自由度も高くなっています。また必要な Table を事前に生成しておけるため動的なコピーも減らせます。


● Resource 同期 (D3D12/Metal)

直前に書き込んだ Buffer を次の描画で Texture 参照する場合など、リソースの依存が発生する場合があります。ShaderUnit の実行は並列化されるので、複数の描画命令が部分的にオーバラップする可能性があるからです。従来の API では依存が発生した場合の完了待ちやキャッシュの同期はドライバの役割でした。

D3D12 ではリソースに State を設けており、読み書きのアクセスタイプが切り替わる場合 Barrier 命令を挿入する必要があります。

Metal では同期よりも PowerVR の Tile を最適化する目的で State (Action) が設けられています。RenderTarget を Texture 参照する場合は Store で、逆に Rendering 前に Tile に書き戻す場合は Load が必要です。本来の目的は違いますが他の GPU では Barrier に相当する役割を担っていると思われます。


● Buffer Renaming (D3D12/Metal)

従来の API では CPU 側から見て簡単に扱えるよう Buffer は複雑な構造を持っていました。同じバッファを部分的に書き換えて何度も描画に用いることができます。これを実現するには内部的にバッファをコピーしたり、描画のたびに異なるバッファを割り当てる Renaming が必要です。

新しい API では GPU/CPU から見える Buffer は常に同一なので、描画アクセス中のバッファ書き換えは結果に影響を与えます。Map() が返すアドレスは常に同じもので Renaming しません (Unmap が必須ではない)。動的に書き換える場合は多重化が必要です。CommandBuffer, Descriptor Table なども同様です。

従来の API でも usage パラメータとしてヒントがありましたが、内部動作の違いはわかりにくいものでした。低レベル API ではこれらの区別を自分で実装することになるため、どこで無駄が生じるのか明快です。個人的にはとてもわかりやすくなったと思っています。


関連エントリ
3D 低レベル API の現状 Direct3D 12/Metal


新しい iPod touch 6 は iPhone 4S 相当から 2世代飛んで一気に iPhone 6 世代へ移行しています。最も安価な iOS Device の底上げが行われました。

CPU SoC iPhone iPod iPad iPad mini
Cortex-A9 A5 iPhone 4S iPod touch 5 iPad2/iPad3 mini
Swift A6 iPhone 5/5c -- iPad4 --
Cyclone A7 iPhone 5s -- iPad Air mini2/mini3
Cyclone2 A8 iPhone 6/6p iPod touch 6 iPad Air2 --

GPU も一番新しい PowerVR Series 6XT の世代へ。

GPU PVR iPhone iPod iPad iPad mini
SGX543/554 5XT iPhone 4S/5/5c iPod touch 5 iPad2/iPad3/iPad4 mini
G6430 6 iPhone 5s -- iPad Air mini2/mini3
GX6450/6850 6XT iPhone 6/6p iPod touch 6 iPad Air2 --

RAM 容量も一段上がっています。

RAM iPhone iPod iPad iPad mini
512MB iPhone 4S iPod touch 5 iPad2 mini
1GB iPhone 5/5c/5s/6/6p iPod touch 6 iPad3/iPad4/Air mini2/mini3
2GB -- -- iPad Air2 --

歴代 iOS Device との速度比較は下記の通りです。(vfpbenchmark)

Device SoC CPU Clock S-SP S-DP M-SP M-DP
iPad Air 2 A8X Cyclone2 x3 1.5GHz 23.568 11.751 68.591 33.968
iPhone 5s A7 Cyclone x2 1.3GHz 20.621 10.313 40.871 20.480
iPad mini 2 A7 Cyclone x2 1.3GHz 20.373 10.223 40.616 20.238
iPod touch 6 A8 Cyclone2 x2 1.1GHz 17.964 8.899 35.530 17.775
Mac mini 2009 Core 2 Duo x2 2.0GHz 15.916 6.365 31.662 12.724
iPad 4 A6X Swift x2 1.4GHz 10.855 1.818 21.502 3.573
iPhone 5 A6 Swift x2 1.3GHz 10.094 1.710 20.029 3.398
iPad 2 A5 Cortex-A9 x2 1.0GHz 3.960 0.989 7.830 1.961
iPad mini A5 Cortex-A9 x2 1.0GHz 3.846 0.983 7.800 1.941
iPad 3 A5X Cortex-A9 x2 1.0GHz 3.394 0.983 7.752 1.954
iPod touch 5 A5 Cortex-A9 x2 0.8GHz 3.161 0.790 6.203 1.565
iPod touch 4 A4 Cortex-A8 x1 0.8GHz 3.139 0.112 3.139 0.112

S-SP = Single Thread 単精度  (GFLOPS) いずれも数値が大きいほうが高速
S-DP = Single Thread 倍精度  (GFLOPS)
M-SP = Multi Thread 単精度  (GFLOPS)
M-DP = Multi Thread 倍精度  (GFLOPS)

浮動小数点演算のピーク値だけの比較なので実際のアプリケーションの速度とは異なります。ですが、浮動小数点演算の速度だけでも Apple の公称値である「CPU 速度で 6倍」に近い数値を得ることが出来ました。

M-SP: 35.5 (iPod touch 6) / 6.2 (iPod touch 5) = 5.7倍

また 32bit 世代 (A4~A6) と 64bit 世代 (A7/A8) の間に入る調度良い比較対象だったので Mac mini Early 2009 の結果も載せてみました。もちろん最新の Core i5/i7 には敵いません。Android や Desktop PC 含めた結果を下記に載せています。

VFP Benchmark Log

GPU は ASTC 対応で PowerVR Series6XT (iOS GPUFamily2) を確認。

GL_VERSION: OpenGL ES 3.0 Apple A8 GPU - 53.13
GL_RENDERER: Apple A8 GPU
GL_VENDOR: Apple Inc.
GL_SHADING_LANGUAGE_VERSION: OpenGL ES GLSL ES 3.00

Extension:
GL_OES_standard_derivatives
GL_KHR_texture_compression_astc_ldr
GL_EXT_color_buffer_half_float
GL_EXT_debug_label
GL_EXT_debug_marker
GL_EXT_pvrtc_sRGB
GL_EXT_read_format_bgra
GL_EXT_separate_shader_objects
GL_EXT_shader_framebuffer_fetch
GL_EXT_shader_texture_lod
GL_EXT_shadow_samplers
GL_EXT_texture_filter_anisotropic
GL_APPLE_clip_distance
GL_APPLE_color_buffer_packed_float
GL_APPLE_copy_texture_levels
GL_APPLE_rgb_422
GL_APPLE_texture_format_BGRA8888
GL_IMG_read_format
GL_IMG_texture_compression_pvrtc

RAM は 1GB でした。

HW INFO: Machine = iPod7,1
HW INFO: Model = N102AP
HW INFO: Arch = N102AP
HW INFO: ByteOrder = 1234
HW INFO: NCPU = 2
HW INFO: MemSize = 1039306752
HW INFO: UserMem = 862314496
HW INFO: PageSize = 16384
HW INFO: VectorUnit = 0
HW INFO: Float = 0


関連エントリ
iPad Air 2 (Apple A8X) の浮動小数点演算能力
Android x86 Binary Translator を試してみる
iPhone 5s A7 CPU の浮動小数点演算速度 (2) (arm64/AArch64/64bit)
VFP Benchmark 関連


GeForce GTX970 (新 Maxwell) は DirectX12 の Feature Level 12_1 に対応していることを確認しました。

RADEON GeForce GeForce Intel HD
R3 8400 GTX 970 GTX 750 Ti Graphics
GCN 1.1 HSA Maxwell 2 Maxwell Gen 8
15.200.1023 353.30 353.30 10.18.15.4235
FEATURE_LEVEL 12_0 12_1 11_0 11_1
DoublePrec true true true true
OMLogicOp true true true true
MinPrecision NONE NONE NONE NONE
TiledResTier Tier 2 Tier 3 Tier 1 --
ResBindingTier Tier 3 Tier 2 Tier 2 Tier 1
StencilRef true false false false
TypedUAVFormat true true true false
ROV Supported false true false true
ConservativeRas -- Tier 1 -- --
GPUVAddrBits 38 38 31 31
StdSwizzle64K false false false false
CrossNodeTier -- -- -- --
CrossAdaptTex false false false false
VPAndRTArray false false false true
ResHeapTier Tier 2 Tier 1 Tier 1 Tier 2

同じ Maxwell でも、GeForce GTX900 では ROV 及び Conservative Rasterization など新しいハードウエア機能に対応していることがわかります。ただし Resource Binding/Heap Tier は Kelper/旧Maxwell 世代と変わらず、リソースの上限は残ったままです。他の GPU 含めたより詳しい表は下記ページに載せています。

Direct3D 12 (DirectX 12) Windows 詳細

これらの新しい機能自体は GPU が対応していれば Direct3D 11.3 でも使用できます。
DirectX の API Version は下記のように細かく別れています。API Version が古いと新しい機能を利用することができません。ID3D11Device2/ID3D11Device3 のように必要な機能に対応した Interface を使う必要があります。

Direct3D 11.0      Windows 7 (Vista)
Direct3D 11.1      Windows 8 (7)
Direct3D 11.2      Windows 8.1
Direct3D 11.3      Windows 10
Direct3D 12        Windows 10

D3D12 で使える Feature Level は今のところ下記の 4 種類で API Version とは異なっています。こちらは実際に GPU が対応している機能をグループ化したものです。option 扱いの個別の機能を 1つ 1つ判定するのは面倒ですが、Feature Level 毎に必須の機能を決めておくことでまとめて区別しやすくなります。OpenGL の Extension と GL Version 番号の関係に似ているかもしれません。

Feature Level 11_0      Fermi/Kepler/Maxwell1
Feature Level 11_1      GCN 1.0/Intel HD Graphics Iris Gen7.5/8
Feature Level 12_0      GCN 1.1/1.2
Feature Level 12_1      Maxwell2

GPU の機能面に注目する場合は、どの API に対応しているかよりも、どの FeatureLevel に属しているかの方が重要となります。Direct3D11 対応と書かれていても FeatureLevel 9_1 の可能性もあるからです。
下記のページにも同じ表を載せています。

Direct3D (Direct3D/12/11/10)

GeForce GTX970 の OpenGL の結果も下記に追加しました。

Desktop GPU Extensions

GL_VERSION: 4.5.0 NVIDIA 353.30
GL_RENDERER: GeForce GTX 970/PCIe/SSE2
GL_VENDOR: NVIDIA Corporation
GL_SHADING_LANGUAGE_VERSION: 4.50 NVIDIA

↓ Maxwell v1 との違い

GL_AMD_vertex_shader_viewport_index
GL_AMD_vertex_shader_layer
GL_EXT_post_depth_coverage
GL_EXT_raster_multisample
GL_EXT_sparse_texture2
GL_EXT_texture_filter_minmax
GL_NV_conservative_raster
GL_NV_conservative_raster_dilate
GL_NV_fill_rectangle
GL_NV_fragment_coverage_to_color
GL_NV_fragment_shader_interlock
GL_NV_framebuffer_mixed_samples
GL_NV_geometry_shader_passthrough
GL_NV_path_rendering_shared_edge
GL_NV_sample_locations
GL_NV_sample_mask_override_coverage
GL_NV_shader_atomic_fp16_vector
GL_NV_viewport_array2

OpenGL ES 3.1 AEP 対応も他の GeForce と同じです。Extension に違いはありますが ASTC は Emulation となっています。今のところ HW 対応を確認した GPU は Intel HD Graphics (Gen8) のみ。


関連エントリ
3D 低レベル API の現状 Direct3D 12/Metal
Intel HD Graphics Gen 8 は Open GL 4.4/OpenGL ES 3.1 AEP 対応 (Broadwell/Cherry Trail/Braswell)
Direct3D 12 (DirectX12) GPU と API の対応表
DirectX 12 (Direct3D 12) と GPU の対応
Desktop GPU と OpenGL ES 3.1 API
GeForce の OpenGL 4.5 ES3_1_Compatibility は AEP 対応
CPU 負荷が低い 新しい 3D API


もうすぐ Windows 10 のリリースとともに DirectX 12 も使えるようになります。
Mantle から始まった新しい API への流れは、昨年の iOS Metal を経ていよいよ Desktop GPU でも起ころうとしています。

新しい API がこれまでと異なっているのは CPU の負担を大きく減らす事ができるということ。もう一つは GPU の世代交代タイミングと一致していないことです。
以前までの DirectX は GPU の新機能に合わせた API セットの追従でした。
新しい API は GPU の世代交代を必ずしも必要としていません。

・CPU の性能をより引き出せる。最適化の余地が生じる。
・GPU の世代交代タイミングが異なる。対応していれば現状の GPU のまま効果あり。

低レベル API とはいわば、これまで JavaScript や Python で書かれていたアプリケーションを C言語で書き直すようなものです。同じプロセッサの上で走らせても、その都度翻訳する手間が省けるためより効率よく実行できるようになります。

その反面、使える命令はより低レベルになるので、メモリ管理など多くの部分がアプリケーション側の負担となります。また従来の API と互換性が無いので、コードを大きく書き換える必要も生じます。


● Metal

Metal は iOS 向けに昨年(2014)リリースされておりすでに利用可能です。
対応している GPU は下記の通り。
iOS に採用された GPU としては 4世代目以降になります。

GPU                                 OpenGL         Metal iOS
-------------------------------------------------------------------
PowerVR MBX                         OpenGL ES 1.1
PowerVR Series 5    SGX535          OpenGL ES 2.0
PowerVR Series 5XT  SGX543MP/554MP  OpenGL ES 2.0
PowerVR Series 6    G6430           OpenGL ES 3.0  Metal GPUFamily1
PowerVR Series 6XT  GX6450/GX6650   OpenGL ES 3.0  Metal GPUFamily2

PowerVR 専用だった Metal ですが、Mac OS X (10.11 El Capitan) でも採用が発表されました。El Capitan 対応 Mac の中には D3D10 世代の GPU 搭載機種も含まれています。Metal の適用範囲がどこまでかは未確認です。

GPU                             OpenGL        Metal OSX
-------------------------------------------------------
GeForce 9400M                   OpenGL 3.3    ?
Intel HD Graphics 4000 (Gen7)   OpenGL 4.1    Metal

Intel HD Graphics 4000 (Ivy Bridge) は Direct3D 12 には対応していませんが、Metal では利用可能なことがわかりました。低レベル API は GPU の世代と直接関係ないため、API の種類によって対応する GPU も異なっています。HD 4000 に限っては Windows より OSX の方が性能を引き出せる可能性があります。

Metal のこれまでの問題は対応ハードウエアが限られていたことです。iPhone Simulator でも使えなかったので、Metal を使ったアプリケーション開発には iPhone 5s 以降か iPad Air/mini retina の実機が必要でした。Mac OS X の対応により開発のハードルが大きく下がります。また将来的には Simulator でも Metal を実行できるようになるかもしれません。

なお Metal はもともと Mobile GPU 向けに設計されており、想定している GPU は OpenGL ES 3.1 世代となっています。ComputeShader はありますが GeometryShader/Tessellator 等はないので、Desktop 向けとは言え OpenGL 4.x の完全な置換えにはなっていません。今後 OpenGL 4.x 相当まで拡張されるのか、それとも iOS と機能面の歩調を合わせて成長させていくのかは不明です。


● Direct3D 12

Mobile GPU から始まった Metal とは逆に、Direct3D は最初から Desktop GPU 向けにリリースされます。

例えば Metal では PowerVR (TBDR) を想定した RenderPass / CommandEncoder がありました。D3D12 には TB を想定した RenderTarget Group は特になく、その代わり RTV -> SRV のように依存が発生する場合のリソースバリアを自分で設定します。

リソースの上限も撤廃されており、RADEON GCN (Mantle) の仕様が API に影響を与えていると思われます。そのため D3D11 世代でも GCN 以外の D3D12 対応 GPU では仕様に完全に対応出来ていないものがあります。

同じ D3D11 世代でも RADEON HD5000/6000, Intel HD Graphics 2500/4000(Ivy Bridge/BayTrail) は D3D12 非対応となっています。ハード的な制約だけでなくドライバのサポート上の都合もあるのかもしれません。

GPU                               OpenGL  ES          D3D12
-----------------------------------------------------------
Intel HD Graphcis Gen7.5 Haswell    4.3   ES 3.1      D3D12
Intel HD Graphcis Gen8   Broadwell  4.4   ES 3.1 AEP  D3D12
GeForce Fermi                       4.5   ES 3.1 AEP  対応予定
GeForce Kepler                      4.5   ES 3.1 AEP  D3D12
GeForce Maxwell                     4.5   ES 3.1 AEP  D3D12
RADEON  GCN 1.0                     4.5   ES 3.1      D3D12
RADEON  GCN 1.1                     4.5   ES 3.1      D3D12


● Android

Windows, iOS/OSX 共に Mobile/Desktop 区別なく新しい API への移行が始まっています。
しかしながら Android では未だ Graphics 向けの Low Level API への対応が行われていません。SHIELD など Android ベースの Game Console もいくつか登場しているので、同等の API への要望は決して少なくはないでしょう。

ゲーム専用機は互換性を考える必要が無いため 3D API のオーバーヘッドが小さく、汎用 OS に対する利点の一つとなっていました。
低レベル API (Low Overhead API) の登場でその差が縮まります。汎用 OS を使った Console も実現しやすくなると同時に、性能だけ見れば専用機の必要性も薄れてくると思われます。

おそらく Khronos の Vulkan が採用されるのではないかと思いますが、Android が今後どのようなタイミングで新しい API に対応してくるか注目です。


関連エントリ
CPU 負荷が低い 新しい 3D API


Broadwell 世代の Intel HD Graphics (Iris Pro) は OpenGL 4.4 に対応していることがわかりました。また ES3 Compatibility では OpenGL ES 3.1 Context を作成可能で GL_ANDROID_extension_pack_es31a が含まれます。つまり OpenGL ES 3.1 AEP です。

今後 Cerry Trail 搭載 Android 端末が登場したら同じように OpenGL ES 3.1 AEP に対応しているものと思われます。

# Braswell Celeron N3150 Windows 10 x64
GL_VERSION: 4.4.0 - Build 10.18.15.4235
GL_RENDERER: Intel(R) HD Graphics
GL_VENDOR: Intel
GL_SHADING_LANGUAGE_VERSION: 4.40 - Build 10.18.15.4235

# Braswell Celeron N3150 Windows 10 x64
GL_VERSION: OpenGL ES 3.1 - Build 10.18.15.4235
GL_RENDERER: Intel(R) HD Graphics
GL_VENDOR: Intel
GL_SHADING_LANGUAGE_VERSION: OpenGL ES GLSL ES 3.10 - Build 10.18.15.4235

この世代の GPU には、Core i の Broadwell だけでなく Atom 系 CPU Airmont を搭載した Cherry Trail や Braswell も含まれます。
実際にこれらのデータは Braswell Celeron N3150 で調べています。

Intel HD Graphics の世代と対応 API まとめ (より詳しくはこちら)

世代 FeatureLevel OpenGL OpenGL ES D3D12 ASTC
Gen 7 11_0 4.0 3.1 N N Ivy Bridge/Bay Trail
Gen 7.5 11_1 4.3 3.1 Y N Haswell
Gen 8 11_1 4.4 3.1 AEP Y Y Broadwell/Cherry Trail/Braswell

詳細な結果は下記ページに掲載しました。

Desktop GPU Extensions

上のページに掲載した "Intel HD Graphics Gen 8 (Braswell Celeron N3150)" の Extension 一覧を見ると、OpenGL 4.4 でも ASTC に Native で対応していることがわかります。
GeForce の Fermi/Kepler/Maxwell1 では Emulation でしたが、今後は Desktop GPU でも ASTC 対応が増えてくるものと思われます。

Extension より
GL_KHR_texture_compression_astc_ldr
GL_ANDROID_extension_pack_es31a

また Atom CPU (Airmont) の Braswell も DirectX12 (Direct3D 12) API に対応していることを確認しました。CPU 性能はあまり変わっていませんが、内蔵 GPU においては Bay Trail との差は非常に大きいようです。
↓こちらの表も更新しています。

Direct3D 12 (DirectX 12) Windows 詳細

D3D12 API からみた Feature Options は今のところ Gen7.5 と変わっていないようです。
ただし、今後ドライバの更新等で仕様が変わる可能性があります。


関連エントリ
Atom プロセッサの比較
Direct3D 12 (DirectX12) GPU と API の対応表
DirectX 12 (Direct3D 12) と GPU の対応
Desktop GPU と OpenGL ES 3.1 API
GeForce の OpenGL 4.5 ES3_1_Compatibility は AEP 対応
CPU 負荷が低い 新しい 3D API
OpenGL ES 3.1 は OpenGL 4.x 相当で ComputeShader に対応


Android から Windows Tablet まで、幅広く使われている Atom core 搭載のプロセッサは非常に種類が多くなっています。
同一世代でも意外に性能の開きが大きいので比べてみました。

Hyperでんち: Atom プロセッサの比較 : 続きはこちら


VisualStudio の Build tool 、MSBuild の解説を書きました。
make の機能と比較しながら、シンボル定義、Task の実行、Target の依存関係の記述その他に触れています。

Hyperでんち: Visual Studio (MSBuild) 続きはこちら

VisualStudio の vcxproj などで共通の設定を Import しておけば、シンボルの設定や Custom の Build 手順などをプロジェクト間で共有することができます。


関連エントリ
VisualStudio と C++11 、コンパイラの違いなど
fastmake
VisualStudio 2010 beta1
VisualStudio と UTF-8
Visual Studio 2008 IDE で MP を使う
Visual Studio 2008
_T() と TEXT() の違いやソースの文字コード
64bit 開発設定のメモ