月別アーカイブ: 2013年9月

iPhone 5s A7 CPU の浮動小数点演算速度 (32bit)

iPhone 5s の浮動小数点演算速度を命令単位で比べてみました。
A7 の CPU core は ARMv8 で 64bit 命令に対応していますが、
ここでの比較は AArch32 (32bit mode) の VFP/NEON 命令となっています。
64bit mode (AArch64) ではレジスタの個数や view が異なるので
違う結果になる可能性があります。

                 (1)      (2)    (3)     (4)      (5)      (6)
                Nexus7  EVO 3D  iPhone5  HTL21  Nexus10  iPhone5s
              Cortex-A9 Scorpion Swift   Krait Cortex-A15   ?
                Tegra3  MSM8660    A6  APQ8064 Exynos5D     A7
                1.2GHz  1.2GHz  1.3GHz  1.5GHz  1.7GHz    1.3GHz?
-----------------------------------------------------------------
a:m44 vmla_A Q   3.959   2.859   1.293   1.337   0.619     0.700
b:m44 vmla_B Q   2.002   1.136   1.359   0.931   0.569     0.670
c:m44 vmla_A D   3.980   3.053   1.669   1.889   0.557     0.649
d:m44 vmla_B D   2.003   1.434   1.329   1.532   0.568     0.745
A:m44 vfma_A Q   -----   -----   1.632   1.882   0.746     0.707
B:m44 vfma_B Q   -----   -----   1.594   0.695   0.840     0.699
e:fadds      A   3.343   3.383   3.090   2.774   2.383     3.551
f:fmuls      A   3.337   3.383   3.167   2.747   2.369     3.475
g:fmacs      A   3.337   3.379   6.180   5.574   2.956     3.480
h:vfma.f32   A   -----   -----   6.180   2.747   2.957     3.480
i:vadd.f32 D A   3.426   3.377   3.091   2.762   1.183     1.031
j:vmul.f32 D A   3.421   3.383   3.168   2.746   1.478     1.545
k:vmla.f32 D A   3.792   3.380   3.166   5.604   1.480     1.567
l:vadd.f32 Q A   6.688   3.377   3.090   2.801   2.365     1.031
m:vmul.f32 Q A   6.681   3.384   3.166   2.761   2.364     1.548
n:vmla.f32 Q A   6.681   3.380   3.167   5.606   2.367     1.574
o:vfma.f32 D A   -----   -----   3.167   2.833   1.479     1.574
p:fadds      B   3.347   5.917   6.181   3.467   2.956     6.953
q:fmuls      B   4.195   5.917   6.180   3.556   3.558     6.652
r:fmacs      B   6.688   8.451  12.361   6.298   5.912     9.867
s:vfma.f32   B   -----   -----  12.363   3.430   5.910     9.859
t:vadd.f32 D B   3.421   5.916   3.090   3.529   2.958     3.663
u:vmul.f32 D B   3.422   5.073   3.169   3.447   2.364     3.114
v:vmla.f32 D B   7.561   8.451   6.180   6.293   4.728     6.185
w:vadd.f32 Q B   6.705   5.916   3.090   3.457   2.961     3.659
x:vmul.f32 Q B   6.683   5.074   3.167   3.428   2.363     3.101
y:vmla.f32 Q B   7.532   8.457   6.179   6.372   4.729     6.199
z:vfma.f32 D B   -----   -----   6.181   3.437   4.730     6.188

↑数値は実行時間(秒) 数値が小さい方が高速

速いと思った iPhone 5 A6 の Swift から 1年、A7 はさらに強力な演算能力を
持っているようです。
ほぼ同クロック(?)でも最大で Swift の 3倍のスループットとなっており、
クロック差があるにも関わらず Cortex-A15 に匹敵するスコアが出ているようです。

特に NEON 命令が高速であることがわかります。
D と Q で差がないので、演算は 128bit 単位だと考えられます。
それでも Cortex-A15 の 64bit 2pipe で実現している速度に追いついているので、
あくまで憶測ですが A7 は 128bit pipe が複数存在している可能性があります。

反面、VFP の方は他の CPU とあまり違いが無いようで、
動作クロックの分だけ差がついています。
ただし Swift で極端に苦手だったスカラーの積和命令においては、
A7 できちんと欠点を克服していることがわかります。
それでもレイテンシは Swift 程ではないものの比較的大きくなっているようです。

ARMv8 のアーキテクチャの変更により、NEON 命令でも倍精度の演算が
サポートされました。
このテストは単精度の 32bit 浮動小数点演算ですが、もし倍精度で比較したなら
32bit ARMv7 世代とはさらに差が広がることになります。

x86 でも SSE2 が倍精度命令をサポートしたことにより、
互換性目的以外で FPU (x87) を使う必要がなくなりました。
実際に Windows x64 の 64bit mode では、
FPU を使わずに SSE 命令だけが用いられています。

同じように ARMv8 も Advanced NEON が倍精度をカバーしたことで、
VFP を分ける必要がなくなっています。
AArch32 では VFP 命令でも AArch64 では NEON のスカラーに
置き換わっていると考えられます。

Krait, Swift, Cortex-A15 と ARMv7-A の VFPv4 世代の CPU を
やっと揃えたと思ったら、更に新しい世代の CPU が登場してしまいました。
本当のパフォーマンスは AArch64 (64bit mode) で発揮されるので、
まだまだこれからです。

a:〜z: 個々の詳細と説明は過去の記事を参照してください。
Cortex-A8 を含めて多くの機種の結果を下記のページにまとめました。

ARM CPU core 毎の浮動小数点演算速度の比較 (VFP/NEON)

関連エントリ
2013/04/08:Nexus 10 CPU Cortex-A15 の浮動小数点演算速度
2013/01/09:Qualcomm APQ8064 GPU Adreno 320 の速度
2012/12/23:Qualcomm APQ8064 Krait/A6 swift の浮動小数点演算能力

iPhone 5s の Apple A7 GPU

A7 の GPU は「Apple A7 GPU」と表示されており独自の名前が付けられています。

GL_VERSION: OpenGL ES 3.0 Apple A7 GPU - 27.10
GL_RENDERER: Apple A7 GPU
GL_VENDOR: Apple Inc.
GL_SHADING_LANGUAGE_VERSION: OpenGL ES GLSL ES 3.00

PVRTC に対応しているため PowerVR 系である可能性は高くなっています。
ですが PVRTC(v2) が無く汎用性の高い ETC2/EAC に置き換わっていることもあり、
PowerVR 依存からの方針転換が見て取れるように思います。

OpenGL ES Extension (Mobile GPU)

Mali-T604, Adreno 320 との比較です。(参考)

                                      Nexus 7 (2013)  Nexus 10  iPhone 5s
                                        Adreno 320   Mali-T604   A7 GPU
-------------------------------------------------------------------------
=== GL3:texture
GL_MAX_3D_TEXTURE_SIZE                      1024       4096       2048
GL_MAX_TEXTURE_SIZE                         4096       4096       4096
GL_MAX_ARRAY_TEXTURE_LAYERS                 256        4096       2048
GL_MAX_TEXTURE_LOD_BIAS                     15.984     255.996    16.000
GL_MAX_CUBE_MAP_TEXTURE_SIZE                4096       4096       4096
GL_MAX_RENDERBUFFER_SIZE                    4096       4096       4096
GL_MAX_DRAW_BUFFERS                         4          4          4
GL_MAX_COLOR_ATTACHMENTS                    4          4          4
GL_MAX_VIEWPORT_DIMS                        4096       4096       4096
=== GL3:elements
GL_MAX_ELEMENTS_INDICES                     -1         16777216   150000
GL_MAX_ELEMENTS_VERTICES                    -1         16777216   1048575
=== GL3:vertex
GL_MAX_VERTEX_ATTRIBS                       16         16         16
GL_MAX_VERTEX_OUTPUT_COMPONENTS             69         64         64
=== GL3:pixel
GL_MAX_FRAGMENT_INPUT_COMPONENTS            71         60         64
=== GL3:program
GL_MIN_PROGRAM_TEXEL_OFFSET                 -8         -8         -8
GL_MAX_PROGRAM_TEXEL_OFFSET                 7          7          7
GL_MAX_VARYING_COMPONENTS                   64         60         60
GL_MAX_VARYING_VECTORS                      16         15         15
=== GL3:output stream
GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 64    64         64
GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS       4     4          4
GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS    4     4          4
GL_MAX_SAMPLES                                   4     4          8
=== GL3:uniform block
GL_MAX_VERTEX_UNIFORM_COMPONENTS            1024       1024       2048
GL_MAX_VERTEX_UNIFORM_VECTORS               256        256        512
GL_MAX_VERTEX_UNIFORM_BLOCKS                12         12         12
GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS   --         50176      51200
GL_MAX_FRAGMENT_UNIFORM_COMPONENTS          896        4096       896
GL_MAX_FRAGMENT_UNIFORM_VECTORS             224        1024       224
GL_MAX_FRAGMENT_UNIFORM_BLOCKS              12         12         12
GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 197504     53248      50048
GL_MAX_UNIFORM_BUFFER_BINDINGS              24         36         24
GL_MAX_UNIFORM_BLOCK_SIZE                   65536      16384      16384
GL_MAX_COMBINED_UNIFORM_BLOCKS              24         24         24
=== GL3:tex
GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS           16         16         16
GL_MAX_TEXTURE_IMAGE_UNITS                  16         16         16
GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS         32         32         32

これまでと違う GPU であることがわかります。

Uniform Block 数は横並びの 12 です。
Fragment の Uniform 数は Adreno 同様 OpenGL ES 3.0 の最小値の 896 (224)
で Vertex の方が多くなっています。
PowerVR 5 は他の GPU と比べても Uniform 数が少なく、一度に転送できる
データ量に制限がありました。
OpenGL ES 3.0 の A7 ではこの辺が解消されむしろ余裕があります。

ただし OpenGL ES 2.0 Context では互換性のためか、
従来の PowerVR SGX 5 系と同じ値を返してくるようです。

GL_VERSION: OpenGL ES 2.0 Apple A7 GPU - 27.10
GL_RENDERER: Apple A7 GPU
GL_VENDOR: Apple Inc.
GL_SHADING_LANGUAGE_VERSION: OpenGL ES GLSL ES 1.00

Precision:
 0: [15 15] 10
 1: [15 15] 10
 2: [127 127] 23
 3: [15 14] 0
 4: [15 14] 0
 5: [31 30] 0
 6: [15 15] 10
 7: [15 15] 10
 8: [127 127] 23
 9: [15 14] 0
10: [15 14] 0
11: [31 30] 0

=== GL2:texture
GL_MAX_TEXTURE_SIZE                      4096
GL_MAX_CUBE_MAP_TEXTURE_SIZE             4096
GL_MAX_VIEWPORT_DIMS                     4096
=== GL2:vertex
GL_MAX_VERTEX_ATTRIBS                    16
GL_MAX_VERTEX_UNIFORM_VECTORS            128
GL_MAX_VARYING_VECTORS                   8
=== GL2:pixel
GL_MAX_FRAGMENT_UNIFORM_VECTORS          64
GL_MAX_RENDERBUFFER_SIZE                 4096
=== GL2:tex
GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS        8
GL_MAX_TEXTURE_IMAGE_UNITS               8
GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS      8

TextureFormat 4
00=8c00  GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
01=8c01  GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
02=8c02  GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
03=8c03  GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG

Android 4.3 + OpenGL ES 3.0 の場合は、事実上 2.0 と 3.0 で Context の
違いが無かったので、この点も iOS らしい仕様となっています。
例えば Android 4.2 の Mali-T604 は Fragment Uniform 数 256 (vec4)
でしたが、4.3 では OpenGL ES 2.0 でも 3.0 と同じ 1024 (vec4) を返します。

OpenGL ES 2.0 Context では Vertex Texture Unit が有効になっている点が
気になりました。
A7 だけかと思ったら PowerVR SGX 5XT でも同様の値になっていたので、
iOS 7 で追加されたのかもしれません。

OpenGL ES Graphics

上記にも書かれていますが glGetShaderPrecisionFormat() の結果に違いが見られます。
float lowp が mediump と同じ fp16 で、int highp も 32bit になっています。
下記ページも更新しました。

GPU Precision まとめ

ただし上のページにも書いているように API で得られる仕様と
実際の演算結果は異なっていることがあります。
同じ fix10 でも、PowerVR series 5 (SGX535/540) & Tegra2/3 と
series 5XT (SGX543MP/554MP) ではシェーディング結果に差が生じています。
5XT の方が Fragment だけ lowp の精度が高くなっているように見えます。

A7 GPU の場合は最初から fp16 なので、
互換性の意味でも都合の良い仕様だと思います。

関連エントリ
iOS7 と iPhone 5s の sRGB 対応とテクスチャフォーマット
Nexus 7 (2013) の Adreno 320 と OpenGL ES 3.0 (Android 4.3)
OpenGL ES 2.0 GLSL precision 宣言と GPU 毎の演算精度を調べる
GPU Precision まとめ

iOS7 と iPhone 5s の sRGB 対応とテクスチャフォーマット

iPhone 5s が発売されて OpenGL ES 3.0 対応端末が増えました。
OpenGL ES 3.0 に対応している入手可能な端末としては 3 種類目の GPU になります。

・Nexus 10 ( Android 4.3 + Mali-T604 )
・Nexus 7(2013)/Nexus 4 ( Android 4.3 + Adreno 320 )
・iPhone 5s ( iOS 7 + Apple A7 GPU )

Nexus 10 用に作成していた OpenGL ES 3.0 の描画コードも
iPhone 5s であっさりと動作しました。
やはり Adreno 320 にはまだ少々問題があるように思います。

● sRGB

OpenGL ES 3.0 を利用できるのは Apple A7 を搭載した iPhone 5s だけですが、
iOS 7.0 に更新することで従来の端末でも機能拡張が行われているようです。
その一つが前回の記事で触れている sRGB 対応です。

iPhone 5s の OpenGL ES 3.0 で sRGB を扱えるのは当然ですが、
iPad 4 や iPhone 5 など PowerVR SGX554MP/543MP でも extension で
同等の相互変換がサポートされました。(下記ページも更新)

OpenGL ES Extension (Mobile GPU)

例えば PVRTC でも GL_EXT_pvrtc_sRGB によって sRGB からリニアへの変換が
行われるようになっています。

・GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT
・GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT
・GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT
・GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT

前回の表↓を更新しました。

          OpenGL ES 3.0 での sRGB 対応
-----------------------------------------
ETC1         あり(ETC2)
ETC2         あり
PVRTC  (v1)  あり         (PowerVR のみ)
PVRTC2 (v2)  あり         (PowerVR のみ)
ATITC        無し         (Adreno のみ)
ASTC         あり
S3TC(DXT1)   あり

iOS が対応しているフォーマットは PVRTC (v1) だけで PVRTC2 (v2) は
含まれていないようです。
またフレームバッファに対するリニアからの変換 (GL_EXT_sRGB) も
サポートしています。

iOS はもともと Renderbuffer を直接作っていたので、EGL/WGL のような
機能選択が不要です。
さらに GLK (GLKit) なら 1行変えるだけで対応できてしまい、
Android での苦労が嘘のように簡単でした。

PowerVR SGX535 (iPhone4) は未確認ですが、SGX543MP/554MP では
iOS 7.0 で Apple A7 GPU と同じように動作していることを確認しています。

●テクスチャフォーマット

iOS でも OpenGL ES 3.0 では Android 同様 ETC2/EAC が利用できるように
なっています。
Android など他の環境と互換性を保ちやすくなりました。

                           ETC1  ETC2/EAC  DXT(S3TC)  PVRTC(v1)  ATITC
----------------------------------------------------------------------
iOS PowerVR        ES 2.0   --     --        --        ◎         --
iOS PowerVR?       ES 3.0   ◎     ◎        --        ◎         --
Android PowerVR    ES 2.0   ◎     --        --        ◎         --
Android Tegra2/3/4 ES 2.0   ◎     --        ◎        --         --
Android Adreno200  ES 2.0   ◎     --        --        --         ◎
Android Adreno300  ES 3.0   ◎     ◎        --        --         ◎
Android Mali400    ES 2.0   ◎     --        --        --         --
Android Mali600    ES 3.0   ◎     ◎        --        --         --

Android のすべての端末と iOS ES 3.0 以降は ETC1 の読み出しができます。

Android/iOS 区別なく OpenGL ES 3.0 デバイスでは、
いまのところすべて ETC2/EAC を使うことが出来ます。

関連エントリ
OpenGL と sRGB

OpenGL と sRGB

一般的な画像はモニタに合わせてガンマ補正した非線形なデータになっています。
そのまま演算に用いると正しい結果が得られないため、事前にリニア値への
変換が必要になります。
同様に出力時は元のモニタ用の色空間に戻します。

・入力時 sRGB → Linear 変換
・出力時 Linear → sRGB 変換

OpenGL (2.1/3.0) や OpenGL ES 3.0 以降は標準である sRGB 色空間に対応しており、
リニア値との相互変換ができるようになっています。
変換が行われるのは上記のようにテクスチャの読み込みと、フレームバッファへの
書き込みのタイミングです。

●入力時

intenal format に sRGB 形式であることを指定できます。
テクスチャフェッチで同時に Linear に展開されます。
圧縮フォーマットも同様です。

// Linear
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
glCompressedTexImage2D( GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_ETC2, w, h, 0, size, data );
glCompressedTexImage2D( GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, w, h, 0, size, data );

// sRGB
glTexImage2D( GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
glCompressedTexImage2D( GL_TEXTURE_2D, 0, GL_COMPRESSED_SRGB8_ETC2, w, h, 0, size, data );
glCompressedTexImage2D( GL_TEXTURE_2D, 0, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, w, h, 0, size, data );

変換は RGB のみで Alpha は含まれません。
OpenGL 4.x RADEON/GeForce/Intel HD 4000、OpenGL ES 3.0 Mali-T604 で
動作を確認しています。

OpenGL ES 2.0 で用いられていた GPU 固有の圧縮フォーマットには sRGB 形式が
定義されていないものがあります。
現在わかっている情報からまとめると下記の通り。

          OpenGL ES 3.0 での sRGB
----------------------------------------
ETC1         あり(ETC2)
ETC2         あり
PVRTC        無し         (PowerVR のみ)
PVRTC2       無し         (PowerVR のみ)
ATITC        無し         (Adreno のみ)
ASTC         あり
S3TC(DXT1)   あり

ETC1 に対応する sRGB フォーマットがありませんが、ETC2 が上位互換なので
GL_COMPRESSED_SRGB8_ETC2 で読み込むことが出来ます。
OpenGL ES 3.0 GPU は ETC2/EAC に対応しているので、SRGB 形式が必要なら
ETC2 を選択することになるかと思います。

フィルタリングに関与できないので厳密ではありませんが、
シェーダーで Linear に変換することも可能です。
ガンマ補正はデータ圧縮の一種といえるので、sRGB 8bit を展開すると
リニア値は 8bit 以上の精度が必要となります。

●出力時

フレームバッファが sRGB 形式で作られている場合、書き込み時に変換が行われます。
自分で作る場合は簡単で、Texture 同様に internal format に sRGB 形式を指定します。

// Renderbuffer
glGenRenderbuffers( 1, &ColorBuffer );
glBindRenderbuffer( GL_RENDERBUFFER, ColorBuffer );
glRenderbufferStorage( GL_RENDERBUFFER, GL_SRGB8_ALPHA8, w, h );
glBindRenderbuffer( GL_RENDERBUFFER, 0 );

glBindFramebuffer( GL_DRAW_FRAMEBUFFER, FrameBuffer );
glFramebufferRenderbuffer( GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, ColorBuffer );
glBindFramebuffer( GL_DRAW_FRAMEBUFFER, 0 );

// Texture
glGenTextures( 1, &ColorTexture );
glBindTexture( GL_TEXTURE_2D, ColorTexture );
glTexImage2D( GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
glBindTexture( GL_TEXTURE_2D, 0 );

glBindFramebuffer( GL_DRAW_FRAMEBUFFER, FrameBuffer );
glFramebufferTexture2D( GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ColorTexture, 0 );
glBindFramebuffer( GL_DRAW_FRAMEBUFFER, 0 );

OS が用意する Default Framebuffer の場合は wgl や egl を用いて
SRGB 対応のフォーマットを選んでおく必要があります。

ただし Windows 7/8 + RADEON/GeForce では、特に何もしなくても SRGB 形式となっており
glEnable( GL_FRAMEBUFFER_SRGB ) だけで意図した結果が得られるようです。
逆に Intel HD 4000 (9.18.10.3165) では、下記の方法で SRGB バッファを選択しても
Default Framebuffer での変換がうまく出来ませんでした。

wgl を使った選択手段は下記のとおり。

1. wgl extension の wglChoosePixelFormatARB() を取得
2. 必要なパラメータ(attribute) を指定して wglChoosePixelFormatARB() で候補を選ぶ
3. 得られた Config 値を SetPixelFormat() に渡す

static const int PixelFormat_Attr[]= {
    WGL_DRAW_TO_WINDOW_ARB,  TRUE,
    WGL_SUPPORT_OPENGL_ARB,  TRUE,
    WGL_DOUBLE_BUFFER_ARB,   TRUE,
    WGL_PIXEL_TYPE_ARB,      WGL_TYPE_RGBA_ARB,
    WGL_COLOR_BITS_ARB,      32,
    WGL_RED_BITS_ARB,        8,
    WGL_GREEN_BITS_ARB,      8,
    WGL_BLUE_BITS_ARB,       8,
    WGL_ALPHA_BITS_ARB,      8,
    WGL_DEPTH_BITS_ARB,      24,
    WGL_STENCIL_BITS_ARB,    8,
    WGL_ACCELERATION_ARB,    WGL_FULL_ACCELERATION_ARB,
    WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB,   TRUE,
    0
};

int ChooseConfig()
{
    int  pixelformat= 0;
    if( !p_wglChoosePixelFormatARB ){ // extension の確認
        return	ChoosePixelFormat( hDC, &PixelFormat_Default );
    }
    const unsigned int	FORMAT_ARRAY_SIZE= 16;
    int	FormatArray[FORMAT_ARRAY_SIZE];
    unsigned int    array_size= 0;
    if( !wglChoosePixelFormatARB( hDC, PixelFormat_Attr, NULL, FORMAT_ARRAY_SIZE, FormatArray, &array_size ) ){
        return  0;
    }
    return  FormatArray[0];
}

void SetPixelFormat()
{
   int pixelformat= ChooseConfig();
   if( !pixelformat ){
      // error
   }
   SetPixelFormat( hDC, pixelformat, NULL );
}

Intel HD 4000 でも自分で Framebuffer を用意した場合は
glEnable( GL_FRAMEBUFFER_SRGB ) の設定が結果に影響を与えていることを確認できます。
ただし OpenGL 4.0 では結果をそのまま出力する手段が見つかりませんでした。

glBlitFramebuffer() や Texture としての読み込みは、ソースが sRGB の場合に
リニア変換されてしまうので、元が Linear か sRGB か区別出来ないからです。
よって Default Framebuffer に転送する場合にシェーダーでもう一度再エンコードが
必要となります。
OpenGL 4.2 以降ならメモリイメージとして転送できるので、もっと良い方法が
あるかもしれません。

OpenGL ES 3.0 (Mali-T604) では GL_FRAMEBUFFER_SRGB による切り替えが
できないので、Framebuffer に対して正しく変換されているかどうか確認できませんでした。
SRGB はブレンドの結果に影響を与えるので、ブレンド結果を比べれば
機能していること確認できるのではないかと思っています。

入力側は容易でしたが、出力側は必ずしも統一した挙動になってくれないようです。
Framebuffer が HDR の場合リニアのまま格納できるので、互換性を考えると
最終的にシェーダーで変換するのが一番なのかもしれません。

// GLSL
const float  SCALE_0= 1.0/12.92;
const float  SCALE_1= 1.0/1.055;
const float  OFFSET_1= 0.055 * SCALE_1;

float SRGBToLinear_F( float color )
{
    if( color <= 0.04045 ){
        return  color * SCALE_0;
    }
    return  pow( color * SCALE_1 + OFFSET_1, 2.4 );
}
float LinearToSRGB_F( float color )
{
    color= clamp( color, 0.0, 1.0 );
    if( color < 0.0031308 ){
        return  color * 12.92;
    }
    return  1.055 * pow( color, 0.41666 ) - 0.055;
}
vec3 LinearToSRGB_V( vec3 color )
{
    return  vec3(
        LinearToSRGB_F( color.x ),
        LinearToSRGB_F( color.y ),
        LinearToSRGB_F( color.z ) );
}
vec3 SRGBToLinear_V( vec3 color )
{
    return  vec3(
        SRGBToLinear_F( color.x ),
        SRGBToLinear_F( color.y ),
        SRGBToLinear_F( color.z ) );
}

関連エントリ
OpenGL 3.x/4.x のシェーダー GLSL とメモリアクセス命令
OpenGL 4.x Program Pipeline Object (Separate Shader Object)
OpenGL 4.2/4.3 Shader Resource と Buffer API
OpenGL ES 3.0/OpenGL 4.x Uniform Block
OpenGL の各バージョンと GLSL の互換性
OpenGL のエラー判定と OpenGL 4.3 Debug Output
OpenGL ES 3.0/OpenGL 4.4 Texture Object と Sampler Object
OpenGL ES 3.0 と Vertex Array Object

Nexus 7 (2012) Ubuntu desktop 上での開発とバッテリー設定

以前の記事以降、外出時の開発用 PC として Nexus 7 (2012) が活躍しています。
GUI 周りでは Unity の dash 画面 (半透明で全画面を覆うメニュー) が特に
重いですが、terminal を開いてコードを書いたり make する分には十分です。

nexus7_flview4.jpg

↑ 3D (OpenGL ES 2.0) も動きます。(開発中)

最近 OpenGL ES 3.0 のために Nexus 10 ばかり使っていて、
Ubuntu の Nexus 7 (2012) を放置していたら起動しなくなりました。
おそらくバッテリーの過放電でしょう。

きちんと確認しなかったのが悪いのですが、電源容量が低下した時の設定が
Power off ではなく、何もしない設定になっていたのだと思われます。
Sleep で放置していたので、使わない時は電源を切るか
Android でブートしなおしておいた方がよいかもしれません。

他の Nexus 7 (2012) に新たに Ubuntu を入れなおしました。
Android 4.3 に MultiROM で Ubuntu desktop 13.04 を入れましたが
いくつか問題がありました。

(1) factory image JWR66Y (Nexus 7 nakasi) で bootloader が書き込めない

 以前ダウンロードしておいた JWR66V が動いたのでこちらを使用しました。
 JWR66V の bootloader が書き込まれたあとは JWR66Y も適用出来るようです。

(2) TWRP_multirom_n7_20130830 で ubuntu desktop を install できない

 ubuntu の img.zip decode 時にエラーが出ています。
 一つ前のバージョン TWRP_multirom 20130825 ではうまくいきました。

電源容量低下時の設定は Power Off にしています。
その状態になってみないと確認できないので、ある程度は自己責任で使うことに
なるかと思います。

現在 Ubuntu desktop が動くのは Tegra3 の Nexus 7 2012年版だけです。

関連エントリ
Nexus 7 上に開発環境をつくる (3) Ubuntu
Nexus 7 上に開発環境をつくる (2) Bluetooth と OpenGL ES 2.0
Android Tablet Nexus 7 上に開発環境をつくる (Ubuntu)