3

しばらくの間 PyOpenGL を楽しく使用した後、私は真剣に立ち往生しています。私は、GLSL シェーダーと OpenCL プログラムを画像処理に使用できるようにする Python パッケージに取り組んでおり、GLSL シェーダーと OpenCL プログラムにデータを出し入れするための標準化された方法としてテクスチャを使用しています。

テクスチャを pbo (ピクセル バッファ オブジェクト) にコピーできないことを除いて、すべてが機能します。私は pbo を使用してテクスチャ データを OpenCL に出し入れしていますが、PyOpenCL ではうまく高速に動作します。OpenCL 出力を pbo からテクスチャにコピーして表示できます。また、データを CPU からpbo。しかし、GPU に既にあるテクスチャ データで pbo を埋めようとして絶望的に立ち往生しています。これは、GLSL シェーダーによって生成された画像をさらに処理するために OpenCL にロードするために必要なことです。

これを行う 2 つの方法について読みました: バリアント 1 は、pbo をバインドし、テクスチャをバインドし、glGetTexImage() を使用します バリアント 2 は、テクスチャをフレーム バッファ オブジェクトにアタッチし、fbo と pbo をバインドし、glReadPixels() を使用します

また、glReadPixels() と glGetTexImage() の両方の PyOpenGL バージョンには、バインドされた pbo があるときに使用する必要がある「Null」ポインターに問題があることも読みました。そのため、OpenGL.raw.GL バリアントを使用しています。

しかし、どちらの場合も「無効な操作」エラーが発生し、何が間違っているのかわかりません。私の pixelbuffer Python クラスの load_texture() メソッドの 2 つのバージョンの下に、それらを削除しすぎていないことを願っています...

バリアント 1:

    def _load_texture(self, texture):
        glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, self.id)
        glEnable(texture.target)
        glActiveTexture(GL_TEXTURE0_ARB)
        glBindTexture(texture.target, texture.id)
        OpenGL.raw.GL.glGetTexImage(texture.target, 0, texture.gl_imageformat,
                                    texture.gl_dtype, ctypes.c_void_p(0))
        glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0)
        glDisable(texture.target)

バリアント 2:

    def _load_texture(self, texture):
        fbo = FrameBufferObject.from_textures([texture])
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
        texture.target, texture.id, 0)
        glReadBuffer(GL_COLOR_ATTACHMENT0)
        glBindFramebuffer(GL_FRAMEBUFFER, fbo.id)
        glBindBuffer(GL_PIXEL_PACK_BUFFER, self.id)
        OpenGL.raw.GL.glReadPixels(0, 0, self.size[0], self.size[1],
                                   texture.gl_imageformat, texture.gl_dtype,  
                                   ctypes.c_void_p(0))
        glBindBuffer(GL_PIXEL_PACK_BUFFER, 0)
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                               GL_TEXTURE_RECTANGLE_ARB, 0, 0)
        glBindFramebuffer(GL_FRAMEBUFFER, 0)

EDIT(私のpboのエラーと初期化に関するいくつかの情報を追加):

バリアント 1 で得られるエラーは次のとおりです。

OpenGL.error.GLError: GLError(
    err = 1282,
    description = 'invalid operation',
    baseOperation = glGetTexImage,
    cArguments = (
        GL_TEXTURE_RECTANGLE_ARB,
        0,
        GL_RGBA,
        GL_UNSIGNED_BYTE,
        c_void_p(None),
    )

そして、私は次のように私のpboを初期化しています:

    self.usage = usage
    if isinstance(size, tuple):
        size = size[0] * size[1] * self.imageformat.planecount
    bytesize = self.imageformat.get_bytesize_per_plane() * size
    glBindBuffer(self.arraytype, self.id)
    glBufferData(self.arraytype, bytesize, None, self.usage)
    glBindBuffer(self.arraytype, 0)

'self.arraytype' は GL_ARRAY_BUFFER, self.usage 念のためすべての可能性を試しましたが、GL_STREAM_READ が私のタイプの使用には最も論理的であると思われました。私が通常使用しているサイズは 1024 x 1024、4 プレーン、プレーンあたり 1 バイトです。これは unsigned int であるためです。これは、ホストからピクセル データを転送するときに問題なく動作します。

また、GPU に 3Gb のメモリを搭載した NVIDIA GeForce GTX 580 を使用し、独自のドライバー、バージョン 295.33 を使用して、Kubuntu 11.10 を使用しています。

私は何が欠けていますか?

4

1 に答える 1

1

なぜそれが大きな違いを生むのかを本当に理解せずに、自分で解決策を見つけました。

私が持っていたコード (両方のバリアント) は基本的に正しいものでしたが、動作させるにはそこに glBufferData を呼び出す必要があります。元のコードで pbo を初期化するときに、同じ呼び出しを既に行っていますが、その初期化とテクスチャをロードしようとする試みの間に、pbo メモリがその間に何らかの形で割り当て解除されるのに十分な時間があったと推測されます。

これで、その呼び出しを glGetTexImage 呼び出しの近くに移動しただけで、他に何も変更せずに機能します。

奇妙なことに、それがバグなのか機能なのか、PyOpenGL に関連しているのか、NVIDIA ドライバーに関連しているのか、または他の何かに関連しているのかはわかりません。予想される動作であるかどうかを簡単に見つけることができる場所には文書化されていません。

以下のバリアント 1 のコードは動作し、非常に高速です。バリアント 2 も同様に処理すると問題なく動作しますが、速度は約半分になります。

def _load_texture(self, texture):
    bytesize = (self.size[0] * self.size[1] *
                self.imageformat.planecount *
                self.imageformat.get_bytesize_per_plane())
    glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, self.id)
    glBufferData(GL_PIXEL_PACK_BUFFER_ARB,
                 bytesize,
                 None, self.usage)
    glEnable(texture.target)
    glActiveTexture(GL_TEXTURE0_ARB)
    glBindTexture(texture.target, texture.id)
    OpenGL.raw.GL.glGetTexImage(texture.target, 0, texture.gl_imageformat,
                                texture.gl_dtype, ctypes.c_void_p(0))
    glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0)
    glDisable(texture.target)
于 2012-05-10T01:24:14.647 に答える