「 OpenGL 」一覧

GalaxyS4 Kitkat (4.4) で GL extension


GalaxyS4 について kitkatに更新してからGL Extensionのリストを取得してみました。

OpenGL ES 3.0 V@45.0 AU@  (CL@3869936)
Qualcomm  Adreno (TM) 320

GL_AMD_compressed_ATC_texture
GL_AMD_performance_monitor
GL_AMD_program_binary_Z400
GL_EXT_debug_label
GL_EXT_debug_marker
GL_EXT_discard_framebuffer
GL_EXT_robustness
GL_EXT_texture_format_BGRA8888
GL_EXT_texture_type_2_10_10_10_REV
GL_NV_fence
GL_OES_compressed_ETC1_RGB8_texture
GL_OES_depth_texture
GL_OES_depth24
GL_OES_EGL_image
GL_OES_EGL_image_external
GL_OES_element_index_uint
GL_OES_fbo_render_mipmap
GL_OES_fragment_precision_high
GL_OES_get_program_binary
GL_OES_packed_depth_stencil
GL_OES_depth_texture_cube_map
GL_OES_rgb8_rgba8
GL_OES_standard_derivatives
GL_OES_texture_3D
GL_OES_texture_float
GL_OES_texture_half_float
GL_OES_texture_half_float_linear
GL_OES_texture_npot
GL_OES_vertex_half_float
GL_OES_vertex_type_10_10_10_2
GL_OES_vertex_array_object
GL_QCOM_alpha_test
GL_QCOM_binning_control
GL_QCOM_driver_control
GL_QCOM_perfmon_global_mode
GL_QCOM_extended_get
GL_QCOM_extended_get2
GL_QCOM_tiled_rendering
GL_QCOM_writeonly_rendering
GL_EXT_sRGB
GL_EXT_sRGB_write_control
GL_EXT_texture_sRGB_decode
GL_EXT_texture_filter_anisotropic
GL_EXT_multisampled_render_to_texture
GL_EXT_color_buffer_float
GL_EXT_color_buffer_half_float
GL_EXT_disjoint_timer_query

Ubuntuで EGL使えるか?


先日NVIDIAのドライバをインストールした Ubuntu ですが、なんとEGLやGLES2についてのライブラリをもっているようでした。(331.20ではダメだった・・・)

これは X 上で EGL & GLES2が使えるんじゃないかと思い試してみることにしました。

続きを読む


OpenGL の ComputeShader


今回はようやくOpenGLでのComputeShaderを扱ってみます。意外とOpenGLでのComputeShaderって話題になっていないようで、ワクワクしています。

手順

VertexShader, FragmentShader などを生成するように、ComputeShader を生成します。ComputeShaderもまたGLSLで記述するので、今までのシェーダーを生成するような感じでプログラムを記述します。ひとつ違うのは出力する箇所でしょうか、今まではピクセルに出力する感じで out 変数に入れていましたが、ComputeShader では imageXXX というサンプラーっぽい型のuniform変数に値を書き込んでいく感じになります。

C++側のコードは以下のような感じになります。通常のシェーダーと同じようにGLSLをコンパイルして ShaderProgram を作成します。

ComputeShaderからの結果を格納するためのテクスチャを用意しておきます。
このときいつも通りにテクスチャを用意した後、下記のAPIにて設定しておきます。これが Shader Image load store 拡張のAPIになります。これによりテクスチャをUAV化というか書き込み先として利用できるようになります。

通常のメインループにおいては、以下のような感じでコンピュートシェーダーを実行し、結果をテクスチャとして利用して貼り付けています。コンピュートシェーダーの実行は glDispatchCompute で行います。

GL_computeshader

今回は gl_GlobalInvocationID を使って処理しているだけですが、各処理ブロックを識別するのに使える変数がもっとたくさんあります。これらの意味を理解して適切に使っていかないと折角の演算力を生かし切ることができません。
CUDAやDirectComputeのほうでもこれらのパラメータに相当するものがあるようなので、またそれらを試してみたときにどういう対応なのか、どの部分を指し示すのかをまとめてみたいと思います。


OpenGLでComputeShaderを使う前に


OpenGLでComputeShader を使う前に実は知っておくべきことが意外とある、ということで今回はその内容についてです。

ComputeShader は演算のためのシェーダーです。その演算内容をどこかに書き出さなければなりません。OpenGLでは、2種類ほどあるようでそれが以下の物に該当するようです。

  • Shader Image load store
  • Shader Storage buffer object (ssbo)

前者はOpenGL 4.2で取り入れられたもので、後者は 4.3 ではいったもののようです。

Shader Image load storeは、フォーマットが決められた出力先へ記録することができるようです。たとえば float4つの値を2次元テクスチャに記録するとか、そんな感じです。DirectXのほうはよくわかっていませんが RWTexture2D とかそういう系列のものに近いんじゃないかと思います。

Shader Storage buffer object (SSBOと略するらしい) は、フォーマットは比較的自由でGLのシェーダーの中からは Read/WriteできるUniform Buffer Object(UBO)のようなものとしてアクセスができる物のようです。DirectX11のほうでいえば、RWStructuredBuffer に相当するといったところでしょうか。

一方DirectXのRWByteAddressBuffer に相当する物はちょっとわかりませんでした。あまり一般的に使われる物ではない、という位置づけでOpenGLでは入っていないのでしょうか。知っている人がいたら教えて下さい。

言い忘れていましたが、これらUAV相当ということでひとまとめにしてもいいのかもしれません。


GLSLのシェーダーリフレクション (2)


OpenGL (GLSL) のユニフォームブロックでのシェーダーリフレクションを試してみました。
ここで使った vertexShader, fragment shaderは以下のようなものです。

これらのシェーダーについて情報を出してみるとこのような感じになりました。
まずはシェーダーユニフォームの一覧.

ユニフォームブロックの中身のメンバには、ロケーションIDは振られていないことが確認できます。ユニフォームのインデックスは振られており、情報はこちら軽油で取得できるようです。
そして、ユニフォームブロックに関して情報を取得してみます。

ユニフォームブロック内でのシェーダー定数のオフセットが取得できました。
ユニフォームブロック内に構造体を配置しても、従来のシェーダー定数の場合と変わらないような名前でオフセットやデータ型を取得できることがわかります。

std140 とかレイアウト指定をしない場合、シェーダーによって(環境によって?)定数の位置が変わりそうです。
そのため、UBOを複数のシェーダーで使い回すのは難しそうです。この場合結局定数毎に書き込む位置を見てバッファ内のデータ更新という手続きをとるので、あまりUBOによる描画効率化に繋がらないように感じます。

ユニフォームブロック内の定数であっても GL_ACTIVE_UNIFORMS にて有効なユニフォーム変数としてカウントされていることに少々驚きました。ただしユニフォームブロック内の変数名からは有効なロケーションが取得できません。ユニフォームブロック内の変数についてはロケーション=-1となっているようです。


GLSLのシェーダーリフレクション


GLSLいじりの過程で、シェーダーリフレクションっぽいことをやってみたのでその調査結果です。

OpenGLでは別に他のライブラリに依存することなく、シェーダーリフレクションの機能を持っています。普段ではuniform変数のロケーション情報を名前から取得しているかと思いますが、その延長上でいろいろな情報をとれるようになっています。

そこで次のようなシェーダープログラム(抜粋)で、どのように情報がとれてくるか試してみました。

結果はこんな感じでした。ドライバの状態によっては別の結果を返してきそうな気配も・・・。AMDやIntelで試してみたいところです。

NVIDIA 331.65 のドライバの結果。

ここからわかることは、次のような感じかと。

  • 配列の場合には [0] とか付加されて返ってくる. (NVIDIAの場合限定かも?)
  • サイズとして配列のサイズ(長さ)が返ってくる
  • 構造体メンバの場合は、構造体変数名が間に挟まっている
  • 構造体だからといって、1つのuniform location に集約されるわけではない

GLSLは構造体使えるから、お?とおもっていたのですが、実際のところは内部のメンバに対して1つずつロケーションが与えられているようです。

次回には、Uniform Blockでのリフレクションのチェックをしてみたいと思います。


最近のGLSLでは色々廃止になってる…


最近のGLSLでは結構廃止になっている部分が多い。ちょっと踏んだところをメモとして残しておきます。

varying, attribute 廃止

これは割と定番ですが、最近のGLSLでは廃止になってます。
代わりに in/out を使用して、シェーダーに対する入力、出力を記述していきます。

その割に、頂点入力としては glGetAttribLocation 使用して、頂点シェーダーの in で書かれた変数を取得するなど、APIとしてはアンバランスに感じます。

textureCUBEの廃止

キューブマップからのテクセルのサンプルで textureCUBEを使用していた部分が最近のものではコンパイルエラーとなるようです。自分の環境では以下のエラーが出力されました。

ではキューブマップからのフェッチはどうするのかというと、以下のような感じで良さそうです。

どうやらtextureCubeだけが廃止扱いではないようです。続く。

texture1D廃止

texture1D, texture1DProj, texture1DLod, texture1DProjLod が廃止になっています。代わりに texture 関数を使えとのことです。

texture2D廃止

texture2D, texture2DProj, texure2DLod, texture2DProjLod が廃止になっています。代わりに texture 関数を使えとのことです。

texture3D廃止

texture3D, texture3DProj, texture3DLod, texture3DProjLod が廃止になっています。代わりに texture 関数を使えとのことです。

shadow系の廃止

shadow1D, shadow2D, shadow1DProj, shadow2DProj, shadow1DLod, shadow2DLod, shadow1DProjLod, shadow2DProjLod が廃止になっています。

デフォルトのグローバルで使えた各変数

これらのものが廃止扱いになっています。あまり使うことはなかったかもしれませんが、たまに使われているケースがあってこのことを知らないと悩みます。
gl_FragColor もまた廃止なので注意が必要です。


Texture Buffer Object (TBO)について


どうやらこれはTextureBuffer-Objectではなく、Texture-BufferObject という意味であるとのことです。そしてこれは、VBO(Vertex buffer object)のバッファデータをテクスチャとして利用するための仕組みであるとのことです。

テクスチャのデータは glTexImage系の関数で準備をしますが、TBOについてはあくまでバッファオブジェクトなので glBufferData などでデータを転送します。そして転送後はこのバッファをテクスチャデータの供給元とすべく、テクスチャのIDとの関連付けを行います。これらの作業をコードで示すと以下のような感じになります。

注意点としては、関連付けるテクスチャを GL_TEXTURE_2Dではなく GL_TEXTURE_BUFFER にバインドする点でしょうか。

TBOの特徴

サンプラ不要でデータにアクセスすることが可能となる点が挙げられます。
通常の2Dテクスチャと違って samplerBuffer を使用することや texelFetch でインデックス指定でアクセスすることも違っています。TBOは1次元配列のように使うという感じでしょうか。

個人的に思うのはこれはジオメトリシェーダーからのストリームアウト(Transform feedback)での結果はVBOに書かれます。これをテクスチャとして使いたいケースでもあるのかなと思いました。
あるいは、バッファオブジェクトを作成して何らかのデータを格納しておきたいケースがあるとか。このデータをテクスチャとして参照することで、リードオンリーではあるものの割と大きなテーブルとして利用可能である、とか。


OpenGLとDirectX11で、あと何が足りてないか


ここ1ヶ月ほどは主に最近のOpenGLについて勉強しているわけですが、DirectX11と比べてまだ何が足りていないかまとめてみます。

やったこと

  • テクスチャ配列 (DX10だけど)
  • ジオメトリシェーダーでストリームアウト&ポイントスプライト (DX10だけど)
  • ハードウェアでのインスタンシング描画
  • テセレーションのシェーダーについて(TCS, TES)
  • シェーダーの実行関数の動的切替(DX11でいうところのDynamic Shader Linkage)
  • インダイレクト描画

まだやれていないこと

  • Texture Buffer (なんかよくわかっていない)
  • コンピュートシェーダー(OpenGL4.3で入った)
  • UAV関連(↑のコンピュートシェーダーの範疇かも)
  • NVIDIA の DirectX と OpenGL の inteop
  • NVIDIA の bindless 色々(GL4.4では標準化されてGL_ARB_bindless_texture).
  • Tiled Resource (DirectX11.2の機能らしい. GLではGL_ARB_sparse_textureだとか)

OpenGL Shader subroutine を試してみた


GLSLシェーダープログラムの関数を切り替える拡張である GL_ARB_shader_subroutine を試してみました。使ってみた感想としては C言語プログラムの関数ポインタを設定して実行先を切り替える、そんなものとずいぶん近い気がします。

シェーダープログラムでは、切り替える関数の宣言、切り替えに使う変数を先に宣言しておきます。
今回はLambertとPhongのライティングを切り替えるように関数を準備してみました。

なんとなくわかるかと思いますが、先に切り替える関数そのもののプロトタイプ宣言みたいなものを行います(1行目)。そして、関数を示す変数を uniform で用意します。main関数の箇所ではこの変数を関数ポインタのようにして、実際の処理関数を呼び出します。
 切り替える関数そのものは、subroutine(プロトタイプ宣言)のような修飾を関数先頭におこなって、プログラムコードを書きます。

続いて C++ 側のコードについて説明します。uniform 変数のようにして関数ポインタもどきを用意しましたが、これは通常のuniform 変数のようにロケーションを取得できません。取得する際には、 glGetSubroutineIndex という関数を用います。また関数がどのシェーダーに実装が入っているのかを識別するためにシェーダーのタイプもまた必要になっています。

そして、このインデックスをシェーダーに対してセットすることで、処理関数が決定されます。

経過時間で関数を切り替えて描画してみたのが以下になります。

DirectXとの比較

DirectXでは、この同様の機能は、シェーダーの動的リンクというものになるのではないかと思います。DirectX11からの機能で、HLSLでインターフェースクラスを作成し、実装はその継承先でという形をとります。つまり Cスタイルで切り替えるか、C++スタイルで切り替えるかの違いでしかないようです。どちらも同じように処理自体は実現可能のように思います。