DirectX12 / DirectX11.3 の ROV のテストです。
前回はこちら→ 「Direct3D12 ROV を試してみる (2) Depth Test と半透明ソート」
やっと Intel HD Graphics でも動くようになりました。

↑Celeron N3150 Braswell Intel HD Graphics (Gen8) 使用
Intel HD Graphcis で問題だったのは PipelineState 生成時にエラーになることです。いろいろ試した結果 Shader に原因があることが判明。理由はよくわかっていませんが if 文中の代入を無くし、同等の加算に置き換えることで回避出来ました。GeForce では元のままで問題ありませんでした。
↓ Intel HD Graphics
あとは Typed UAV を使わずに展開しています。シェーダーは下記の通り。
関連エントリ
・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 と半透明ソート」
やっと Intel HD Graphics でも動くようになりました。

↑Celeron N3150 Braswell Intel HD Graphics (Gen8) 使用
Intel HD Graphcis で問題だったのは PipelineState 生成時にエラーになることです。いろいろ試した結果 Shader に原因があることが判明。理由はよくわかっていませんが if 文中の代入を無くし、同等の加算に置き換えることで回避出来ました。GeForce では元のままで問題ありませんでした。
zstack_x= pz;
stack_x= color_enc;
stack_x= color_enc;
↓ Intel HD Graphics
zstack_x*= 1e-32f;
zstack_x+= pz;
stack_x*= 0;
stack_x+= color_enc;
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;
}
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
2015/07/23
Direct3D12 ROV を試してみる (2) Depth Test と半透明ソート
DirectX12 / DirectX11.3 の ROV のテスト続きです。
前回はこちら→ 「Direct3D12 ROV (Rasterizer Order View) を試してみる」
ROV は自分で Depth Test できます。
R32_FLOAT の UAV を 1枚追加しています。
下記は UAV (UBuffer0) の結果です。(Geforce GTX960)
↓ROV 無し, Depth Test 無し

↓ROV あり, Depth Test 無し

↓ROV 無し, Depth Test あり

↓ROV あり, Depth Test あり

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

力技ですがバッファ固定で 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
前回はこちら→ 「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;
}
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 無し

↓ROV あり, Depth Test 無し

↓ROV 無し, Depth Test あり

↓ROV あり, Depth Test あり

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

力技ですがバッファ固定で 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 だけとなっています。
より詳しい機能表は下記のページに掲載しています。
・Direct3D 12 (DirectX 12) Windows 詳細
Shader は複数の Unit で同時に走るので、実行順番は保証されずバッファアクセスは競合します。しかしながら Pixel の出力自体は順序が保証されており結果は一定です。Blend や Depth/Stencil Test では同一の Draw Call で重ね書きしても正しい値で評価されます。
シェーダー内で任意に読み書きできる UAV はこのルールが適用されませんでした。ROV を使うと UAV の読み書きの整合性が取れるようになります。
(1) が通常の RenderTarget への描画です。
(2) は RenderTarget への書き込みと全く同じものを UAV にも書き込んでいます。擬似 MRT

↑(2) の結果を 2つ並べて表示したのがこちらです。左が RTV (RenderTarget), 右が UAV です。使用したのは GeForce GTX960 (Maxwell2)。
↑右の UAV では重ね合わせに問題が生じています。並列度が上がるためプリミティブが小さい方が発生しやすいです。
これを ROV に変更したのが (3) です。

↑ (3) の結果です。左が RTV (RenderTarget), 右が ROV。
ROV では重ね合わせが正しく行われ RTV と見た目が同一になりました。
さらに ROV では、RenderTarget と違って値をシェーダーで読むことができます。
(4) は Shader 内で Blend したもの。

↑(4) の結果。左が RTV, 右が ROV の半透明合成
ROV はかなり自由度が高く MRT の制限がほぼ無くなったような印象です。パフォーマンス等は調べてませんがかなり応用が効きそうです。
なお Intel HD Graphics では Typed UAV が使えないので、今まで使用してきた下記のコードが動きません。
一応対応してみました。UAV を R32_UINT として読み込みます。
シェーダーは下記の通り。
これで Intel HD Graphics でも同等の結果になりました。
RADEON は残念ながら ROV 非対応です。下記は RADEON GCN 1.1 (UAV) の結果で、こちらも GeForce 同様ブロック状のノイズが生じています。

関連エントリ
・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 の対応
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;
}
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;
}
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;
}

↑(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;
}
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;
}

↑ (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;
}
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;
}

↑(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 );
#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;
}
//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 同様ブロック状のノイズが生じています。

関連エントリ
・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 の対応
2015/07/20
3D 低レベル API の違い Direct3D 12/Metal
前回はこちら→ 「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
新しい 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
2015/07/19
iPod touch 6 の浮動小数点演算速度は Core 2 Duo ライン超え
新しい iPod touch 6 は iPhone 4S 相当から 2世代飛んで一気に iPhone 6 世代へ移行しています。最も安価な iOS Device の底上げが行われました。
GPU も一番新しい PowerVR Series 6XT の世代へ。
RAM 容量も一段上がっています。
歴代 iOS Device との速度比較は下記の通りです。(vfpbenchmark)
浮動小数点演算のピーク値だけの比較なので実際のアプリケーションの速度とは異なります。ですが、浮動小数点演算の速度だけでも 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) を確認。
RAM は 1GB でした。
関連エントリ
・iPad Air 2 (Apple A8X) の浮動小数点演算能力
・Android x86 Binary Translator を試してみる
・iPhone 5s A7 CPU の浮動小数点演算速度 (2) (arm64/AArch64/64bit)
・VFP Benchmark 関連
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 に対応していることを確認しました。
同じ 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 を使う必要があります。
D3D12 で使える Feature Level は今のところ下記の 4 種類で API Version とは異なっています。こちらは実際に GPU が対応している機能をグループ化したものです。option 扱いの個別の機能を 1つ 1つ判定するのは面倒ですが、Feature Level 毎に必須の機能を決めておくことでまとめて区別しやすくなります。OpenGL の Extension と GL Version 番号の関係に似ているかもしれません。
GPU の機能面に注目する場合は、どの API に対応しているかよりも、どの FeatureLevel に属しているかの方が重要となります。Direct3D11 対応と書かれていても FeatureLevel 9_1 の可能性もあるからです。
下記のページにも同じ表を載せています。
・Direct3D (Direct3D/12/11/10)
GeForce GTX970 の OpenGL の結果も下記に追加しました。
・Desktop GPU Extensions
↓ Maxwell v1 との違い
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
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
2015/07/12
3D 低レベル API の現状 Direct3D 12/Metal
もうすぐ 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世代目以降になります。
PowerVR 専用だった Metal ですが、Mac OS X (10.11 El Capitan) でも採用が発表されました。El Capitan 対応 Mac の中には D3D10 世代の GPU 搭載機種も含まれています。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 非対応となっています。ハード的な制約だけでなくドライバのサポート上の都合もあるのかもしれません。
● 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
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
2015/07/08
Intel HD Graphics Gen 8 は Open GL 4.4/OpenGL ES 3.1 AEP 対応 (Broadwell/Cherry Trail/Braswell)
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 に対応しているものと思われます。
この世代の GPU には、Core i の Broadwell だけでなく Atom 系 CPU Airmont を搭載した Cherry Trail や Braswell も含まれます。
実際にこれらのデータは Braswell Celeron N3150 で調べています。
Intel HD Graphics の世代と対応 API まとめ (より詳しくはこちら)
詳細な結果は下記ページに掲載しました。
・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 対応が増えてくるものと思われます。
また 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 に対応
今後 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 に対応
2015/07/07
Atom プロセッサの比較
Android から Windows Tablet まで、幅広く使われている Atom core 搭載のプロセッサは非常に種類が多くなっています。
同一世代でも意外に性能の開きが大きいので比べてみました。
・Hyperでんち: Atom プロセッサの比較 : 続きはこちら
同一世代でも意外に性能の開きが大きいので比べてみました。
・Hyperでんち: Atom プロセッサの比較 : 続きはこちら
2015/07/04
Texture File Format の種類と解説
Texture File Format の解説を更新しました。
・Hyperでんち: Texture File Format
関連エントリ
・OpenGL / OpenGL ES テクスチャファイルフォーマット KTX と DDS
・Android OpenGL ES 2.0 の圧縮テクスチャ
・Direct3D10 と DDS テクスチャフォーマット
・DirectX SDK November 2007 Gather と 新DDS フォーマット
・Hyperでんち: Texture File Format
関連エントリ
・OpenGL / OpenGL ES テクスチャファイルフォーマット KTX と DDS
・Android OpenGL ES 2.0 の圧縮テクスチャ
・Direct3D10 と DDS テクスチャフォーマット
・DirectX SDK November 2007 Gather と 新DDS フォーマット