さて、私自身の質問に答えようとします。 OpenGL経由でビットマップを表示するための簡単な方法があるように見えます。テクスチャ+ピクセルバッファオブジェクトを使用する代わりに、テクスチャフォーマットGL_RGBA8
をサポートするcudaGraphicsGLRegisterImage()
をCUDA Toolkit 4.0以降使用できます。
例を簡潔にするため、cutilSafeCall()
またはエラーチェックはありません。私はOpenGLに関する知識はほとんど持っておらず、お勧めを聞いてうれしいです。
#include <stdio.h>
#include <string.h>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <cuda_runtime_api.h>
#include <cuda_gl_interop.h>
/* Handles OpenGL-CUDA exchange. */
cudaGraphicsResource *cuda_texture;
/* Registers (+ resizes) CUDA-Texture (aka Renderbuffer). */
void resizeTexture(int w, int h) {
static GLuint gl_texture = 0;
/* Delete old CUDA-Texture. */
if (gl_texture) {
cudaGraphicsUnregisterResource(cuda_texture);
glDeleteTextures(1, &gl_texture);
} else glEnable(GL_TEXTURE_2D);
glGenTextures(1, &gl_texture);
glBindTexture(GL_TEXTURE_2D, gl_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
cudaGraphicsGLRegisterImage(&cuda_texture, gl_texture, GL_TEXTURE_2D, cudaGraphicsMapFlagsWriteDiscard);
}
void updateMemDevice(cudaArray *memDevice, int w, int h) {
struct Color {
unsigned char r, g, b, a;
} *memHost = new Color[w*h];
memset(memHost, 128, w*h*4);
for (int y = 0; y<h; ++y) {
for (int x = 0; x<w; ++x) {
Color &c = memHost[y*w + x];
c.r = c.b = 255 * x/w;
}
}
cudaMemcpyToArray(memDevice, 0, 0, memHost, w*h*4, cudaMemcpyHostToDevice);
delete [] memHost;
}
void editTexture(int w, int h) {
cudaGraphicsMapResources(1, &cuda_texture);
cudaArray* memDevice;
cudaGraphicsSubResourceGetMappedArray(&memDevice, cuda_texture, 0, 0);
updateMemDevice(memDevice, w, h);
cudaGraphicsUnmapResources(1, &cuda_texture);
}
void windowResizeFunc(int w, int h) {
glViewport(-w, -h, w*2, h*2);
}
void displayFunc() {
glBegin(GL_QUADS);
glTexCoord2i(0, 0); glVertex2i(0, 0);
glTexCoord2i(1, 0); glVertex2i(1, 0);
glTexCoord2i(1, 1); glVertex2i(1, 1);
glTexCoord2i(0, 1); glVertex2i(0, 1);
glEnd();
glFlush();
}
int main(int argc, char *argv[]) {
/* Initialize OpenGL context. */
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB);
glutInitWindowSize(400, 300);
glutCreateWindow("Bitmap in Device Memory");
glutReshapeFunc(windowResizeFunc);
glutDisplayFunc(displayFunc);
glewInit();
cudaGLSetGLDevice(0);
int width = 5, height = 5;
resizeTexture(width, height);
editTexture(width, height);
glutMainLoop();
return 0;
}
「これはすべて、ちょっと複雑で些細なことだと思います」タフ;そういうものだ。 CUDAは何も描画できません。そしてCUDAは小さな世界に住んでいます。何かを描くためには、CUDAの世界から、実際に物を描くことができるものの世界にデータを取得する必要があります。 CUDAデータをOpenGLまたはD3Dオブジェクトに直接生成する方が良いでしょう。 –
はい、私はCUDAがコンピューティングのためだけであることを理解しています。もしあなたが好きなら、CUDAを忘れることができます。主なものは、ビットマップを保持する線形のデバイスメモリのアドレスがあるからです。私が必要とするのは、このビットマップをフレームバッファにビットblitすることだけです。私はDirect2Dがその解決策の一つであると推測していますが、残念ながらWindows 7/Vistaのみでサポートされています。 – AlexP
私は、Direct2Dがそのブリッティング関数で "線形配置されたデバイスメモリ"へのポインタを取っていないことは確かです。これらのポインタを表すオブジェクトを取ります。そのため、変換レイヤーが必要です。ほとんどの描画APIはGPUメモリへのポインタとそれらからのblitを持つだけではありません。そうしても、CUDAポインタが他のAPIで使用されるポインタと同じ種類であるという保証はありません。 –