デバイス固有情報の取得

久しぶりの更新なので軽めのネタで肩慣らしをしようかと思います.

サマリはこんな感じになります.

  • バイス情報の取得
  • uniform/varying変数のベクトル最大数とパッキングルール
  • (拡張)機能の有無
  • iPad2におけるデバイス情報
  • まとめ

それではさっくりいきましょう.

バイス情報の取得

取得できるデバイス情報には、以下のようなものがある.

GL_MAX_VERTEX_ATTRIBS シェーダーで利用できる、頂点属性の最大数
GL_MAX_VARYING_VECTORS varying 変数で利用できる、ベクトルの最大数
GL_MAX_VERTEX_UNIFORM_VECTORS バーテックスシェーダーで利用できる、uniform(ベクトル)の最大数
GL_MAX_FRAGMENT_UNIFORM_VECTORS フラグメントシェーダーで利用できる、uniform(ベクトル)の最大数
GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS バーテックスシェーダーで利用できる、テクスチャユニットの最大数
GL_MAX_TEXTURE_IMAGE_UNITS フラグメントシェーダーで利用できる、テクスチャユニットの最大数
GL_MAX_TEXTURE_SIZE テクスチャの最大の幅と高さ
GL_MAX_CUBE_MAP_TEXTURE_SIZE キューブテクスチャの最大幅と高さ
GL_MAX_RENDERBUFFER_SIZE レンダーバッファの最大幅と高さ
GL_MAX_VIEWPORT_DIMS ビューポートの最大幅と高さ

このあたりは、gl.h に書かれているので標準的に取得出来ると思う.

使い方は、glGetIntegerv を利用して、次のように取得する.

GLint a_val;
// 頂点点属性の最大数
glGetIntegerv( GL_MAX_VERTEX_ATTRIBS, &a_val );

少しだけわかりづらい点としては、ビューポートの最大幅と高さで、これは、

// ビューポートの最大幅
GLint a_dimes[2];
glGetIntegerv( GL_MAX_VIEWPORT_DIMS, a_dimes);
a_viewport_width = a_dimes[0];
a_viewport_height = a_dimes[1];

のように取得すれば良い.

uniform/varying変数のベクトル最大数とパッキングルール

バーテックスシェーダー/フラグメントシェーダーを利用していると、uniform変数やvarying変数がどの程度利用できるのかが気になる.

ここで前述の GL_MAX_VARYING_VECTORS 等を利用すると、それぞれの変数で利用できるベクトルの最大数が取得出来るが、これを活用するためにはパッキングルールの理解が必要となる.

まず、パッキングルールがなくとも理解できる最大数の利用方法を考えてみる.

iPad2 にて、GL_MAX_VERTEX_UNIFORM_VECTORS の値を取得すると 128 という値が返ってくる.

これは vec4 変数が 128個使えるという意味で、仮にすべて mat4 として利用した場合には(mat4 は、vec4 * 4なので)32個のmat4が利用できることを意味している.

理解のために、コードと表を記しておく.

uniform vec4 v;
uniform mat4 m;
添え字 x y z w
[0] v.x v.y v.z v.w
[1] m[0].x m[0].y m[0].z m[0].w
[2] m[1].x m[1].y m[1].z m[1].w
[3] m[2].x m[2].y m[2].z m[2].w
[4] m[3].x m[3].y m[3].z m[3].w


# ここから、バーテックスシェーダーで行いたい場合には、32個の行列パレットが利用でき
# そうだということがわかる.

もしここですべてを vec3 変数として利用したい場合、vec4 = (4要素) / vec3 = (3要素)なので128個のvec3変数しか利用できなさそうに思える.

イメージとしては次の表を思い浮かべると良い.

これだと、あからさまに利用していないw成分がもったいないので、物理的な格納領域にたいしてどのように変数を割り当てるのかを決めるパッキングルールというものがある.

パッキングルールのイメージを次の表で記す.

uniform vec4 v[130];
添え字 x y z w
[0] v[0].x v[0].y v[0].z v[128].x
[1] v[1].x v[1].y v[1].z v[128].y
[2] v[2].x v[2].y v[2].z v[128].z
[3] v[3].x v[3].y v[3].z v[129].x
[4] v[4].x v[4].y v[4].z v[129].y
[127] v[127].x v[127].y v[127].z -

とりあつかうプログラマはどのようにパッキングが行われるのかを意識する必要がないが、このルールの存在を知らないと利用できる変数の数で損をする可能性があるので存在は覚えておく必要がある.

(拡張)機能の有無

glGetIntegerv を利用*せず*に調べる必要がある値も存在する.

たとえば、

GL_OES_depth_texture depth texure の作成が行えるか?
GL_OES_depth24 24bit 形式の depth バッファが作成できるか?
GL_OES_texture_half_float half float 形式のテクスチャが作成できるか?
GL_OES_texture_float float 形式のテクスチャが生成できるか?
GL_HALF_FLOAT_OES half float のサポートされているか?

のようなことを調べることができる.
上の表は、私が興味があることだけを書き出しただけなので、詳しく知りたい場合には glext.h を眺めてみたほうがよい.

これらは、主に拡張機能の有無なので、glext.h にマクロとして定義されているので次のように使えば良い(と思う)

    // depth texure の作成が行えるか?
#ifdef GL_OES_depth_texture
    bool a_support_depth_textre = (GL_OES_depth_texture != 0);
#else
    bool a_support_depth_textre = false;
#endif

ただし、これらの機能の有無を調べたい場合、コード自体をマクロで処理することになることが多いので変数として扱う意味は薄い点と、所詮マクロなのでコンパイル単位でしか判断が行えない点に注意をする必要がある.

具体的にに言えば、HalfFloat が利用できる場合、"GLhalf" などの型が利用できるが、これは glext.h 内で

#if GL_OES_texture_half_float
typedef unsigned short GLhalf;
#endif

このように typedef されているだけなので、環境によってはコンパイルエラーになる可能性がある.

iPad2におけるデバイス情報

手元にある iPad2 で調べた結果を以下に表にする.

GL_MAX_VERTEX_ATTRIBS 16
GL_MAX_VARYING_VECTORS 8
GL_MAX_VERTEX_UNIFORM_VECTORS 128
GL_MAX_FRAGMENT_UNIFORM_VECTORS 64
GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0
GL_MAX_TEXTURE_IMAGE_UNITS 8
GL_MAX_TEXTURE_SIZE 4096
GL_MAX_CUBE_MAP_TEXTURE_SIZE 4096
GL_MAX_RENDERBUFFER_SIZE 4096
GL_MAX_VIEWPORT_DIMS 4096
GL_OES_depth_texture 1
GL_OES_depth24 1
GL_OES_texture_half_float 1
GL_OES_texture_float 1
GL_HALF_FLOAT_OES 1

まとめ

OpenGL ES2.0 のデバイス固有情報の取得を行いました.

パッキングルールに関しては、『OpenGL ES2.0 プログラミングガイド』(p.92 5.6 uniform変数とvarying変数のパッキング)を参考にしました.
また、今回の内容と直接関係ありませんが、この本には巻末の付録に "GL_HALF_FLOAT_OES"の解説が載っており、浮動小数を半浮動小数に(相互)変換するコードが示されておりとても役にたっています.

iOS のデバイス固有情報の取得に関しては、Appleが公開している『iOS OpenGL ESプログラミングガイド』を参考にしました.

iPad2のデバイス情報を覗いてみると、"GL_OES_texture_half_float"が有効になっていたりと意外な発見がありました.

実は詳しいことをわかっていないのですが、おそらく HalfFloat のフォーマットのテクスチャが取り扱えるってことですよね?

レンダリングターゲットにはできるのかな?

描画速度はおいとくとしても、iOSバイスHDRレンダリングが出来たらちょっと楽しそうです.

Open GL ES 2.0 プログラミングガイド

Open GL ES 2.0 プログラミングガイド