投稿日
2013/4/8 月曜日
OpenGLに慣れてれば簡単だと思うけど、慣れてないと難しいと思う。
この辺はやはりCUDAとかのGPGPU用のAPIに比べると、必要な手続きが多過ぎる感がある。
1から作る場合はCUDAの方が明らかに楽だけど、ターゲット環境の問題とかでCUDAを選択出来ないときや、すでにOpenGLを使ってるアプリに組み込むときOpenGLでGPGPUをやるのもいいと思う。
XcodeでCommand Line Toolのプロジェクト(言語はC++)を新規作成してOpenGL.frameworkを追加するだけで、コンパイルが出来て実行も出来るソースを載せるけど、具体的な計算に必要な処理は長くなりすぎるので省略してる。
よってこのソースをコンパイルして実行しても意味のある計算は何も行わない。
ただ、省略した部分は普通のOpenGLのコードと同じになるはずなので、OpenGLに慣れてる人はすぐに具体的な処理が書けるんじゃないかと思う。
あとサンプルコードは、OpenGLでGPUコンピューティングを行う雛形であるだけでなく、画面表示無しでOpenGLを使うプログラムの雛形でもある。
#include <iostream>
#include <OpenGL/OpenGL.h>
#include <OpenGL/gl.h>
int main(int argc, const char * argv[])
{
// CGLコンテキストの作成
CGLError errorCode;
CGLPixelFormatAttribute attributes[4] = {
kCGLPFAAccelerated, // GPUを使う
kCGLPFAOpenGLProfile, // ↓で指定するバージョンのコアプロファイルを使用
(CGLPixelFormatAttribute) kCGLOGLPVersion_3_2_Core,
(CGLPixelFormatAttribute) 0
};
CGLPixelFormatObj pixelFormat = NULL;
GLint numPixelFormats = 0;
CGLContextObj cglContext = NULL;
errorCode = CGLChoosePixelFormat(attributes, &pixelFormat, &numPixelFormats);
errorCode = CGLCreateContext(pixelFormat, NULL, &cglContext);
errorCode = CGLSetCurrentContext(cglContext);
// フレームバッファオブジェクトを作成して計算結果の格納先としてテクスチャをアタッチ
GLuint frameBuffer;
GLuint texOut;
GLint fWidth = 8, fHeight = 8;
glGenTextures(1, &texOut);
glBindTexture(GL_TEXTURE_2D, texOut);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fWidth, fHeight, 0, GL_RGBA, GL_FLOAT, NULL);
glGenFramebuffers(1, &frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texOut, 0);
// フレームバッファが使えるか確認
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status == GL_FRAMEBUFFER_COMPLETE) {
printf("glFramebufferTexture2D success!\n");
glViewport(0, 0, fWidth, fHeight);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
/*
あとはここで普通のOpenGLの描画コードを実行していく。
処理の流れはシェーダを使った普通のOpenGLのコードと同じ。
どういう計算を行うかはシェーダに書く。
計算に必要なデータは、頂点データやテクスチャデータやuniform変数とかでシェーダに渡す。
結果はフレームバッファにアタッチされたテクスチャに保存される。
最低限必要な処理は、
・シェーダの読み込み、コンパイル、リンク
・頂点データの用意(画面いっぱいに表示される矩形の分)とGPUへの転送
・計算に使うデータをテクスチャデータとして用意してGPUに転送
・描画コマンドの実行
・glFinish()
*/
// GPUから処理結果を受け取る
float *ret = (float*)malloc(sizeof(float) * fWidth * fHeight * 4);
glBindTexture(GL_TEXTURE_2D, texOut);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, ret);
/*
あとは結果を煮るなり焼くなり
*/
free(ret);
} else {
printf("glFramebufferTexture2D failed!\n");
}
glDeleteTextures(1, &texOut);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// cglContext を破棄
errorCode = CGLSetCurrentContext(NULL);
errorCode = CGLDestroyContext(cglContext);
/*
エラー処理をする場合は、 CGLErrorString(errorCode) とするとエラー内容を表す文字列が得られるっぽい。
OpenGL 部分については、普通に glGetError() で。
*/
return 0;
}
最近のコメント
たかたむ
はじめまして。初リアルフォース(R3ですが)で,同…
nokiyameego
ZFS poolのデバイスラベル破損で悩んていたと…
名前
しゅごい
Jane Doe
FYI Avoid Annoying Unexpe…
Jane Doe
ご存じとは思いますが、whileには、”~の間”と…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…