0

このサンプルを実行したときに発生するエラーを解決しようとしています。

クエリ オクルージョンに関しては、基本的にビューポートごとに変化する正方形を 4 回レンダリングしますが、最初と最後のビューポートが意図的にモニター領域の外にあるため、実際に何かをレンダリングするのは中央の 2 回だけです。

    viewports[0] = new Vec4(windowSize.x * -0.5f, windowSize.y * -0.5f, windowSize.x * 0.5f, windowSize.y * 0.5f);
    viewports[1] = new Vec4(0, 0, windowSize.x * 0.5f, windowSize.y * 0.5f);
    viewports[2] = new Vec4(windowSize.x * 0.5f, windowSize.y * 0.5f, windowSize.x * 0.5f, windowSize.y * 0.5f);
    viewports[3] = new Vec4(windowSize.x * 1.0f, windowSize.y * 1.0f, windowSize.x * 0.5f, windowSize.y * 0.5f);

今回は毎回glBeginQuery、異なるクエリを使用して最初にレンダリングし、次にクエリを実行しますGL_ANY_SAMPLES_PASSED

    // Samples count query
    for (int i = 0; i < viewports.length; ++i) {

        gl4.glViewportArrayv(0, 1, viewports[i].toFA_(), 0);

        gl4.glBeginQuery(GL_ANY_SAMPLES_PASSED, queryName.get(i));
        {
            gl4.glDrawArraysInstanced(GL_TRIANGLES, 0, vertexCount, 1);
        }
        gl4.glEndQuery(GL_ANY_SAMPLES_PASSED);
    }

次に、結果を読み取ろうとします

    gl4.glBindBuffer(GL_QUERY_BUFFER, bufferName.get(Buffer.QUERY));
    IntBuffer params = GLBuffers.newDirectIntBuffer(1);
    for (int i = 0; i < viewports.length; ++i) {
        params.put(0, i);
        gl4.glGetQueryObjectuiv(queryName.get(i), GL_QUERY_RESULT, params);
    }

しかし、私は得る:

GlDebugOutput.messageSent(): GLDebugEvent[ id 0x502
    type Error
    severity High: dangerous undefined behavior
    source GL API
    msg GL_INVALID_OPERATION error generated. Bound query buffer is not large enough to store result.
    when 1455696348371
    source 4.5 (Core profile, arb, debug, compat[ES2, ES3, ES31, ES32], FBO, hardware) - 4.5.0 NVIDIA 356.39 - hash 0x238337ea]

APIドキュメントを見ると、次のように書かれています:

params

    If a buffer is bound to the GL_QUERY_RESULT_BUFFER target, then params is treated as an offset to a location within that buffer's data store to receive the result of the query. If no buffer is bound to GL_QUERY_RESULT_BUFFER, then params is treated as an address in client memory of a variable to receive the resulting data. 

そのフレーズにはエラーがあると思います。彼らはGL_QUERY_BUFFER代わりにを意味していたと思いますGL_QUERY_RESULT_BUFFER。実際、たとえばここでもGL_QUERY_BUFFER使用しています..とにかく、そこに何かがバインドされている場合、params はオフセットとして解釈されます。

しかし、私のバッファは十分に大きいです:

    gl4.glBindBuffer(GL_QUERY_BUFFER, bufferName.get(Buffer.QUERY));
    gl4.glBufferData(GL_QUERY_BUFFER, Integer.BYTES * queryName.capacity(), null, GL_DYNAMIC_COPY);
    gl4.glBindBuffer(GL_QUERY_BUFFER, 0);

だから問題は何ですか?

バッファーサイズに 500 などの大きな数値を書き込もうとしましたが、成功しませんでした...

エラーは別の場所にあると思います..見えますか?

4

1 に答える 1

2

答える必要がある場合は、バッファを GL_QUERY_BUFFER ターゲットにバインドすると、OpenGL は params とインタープリタ内の値を、クエリの結果を保存するオフセット (バイト単位) として読み取る必要があると思います。

いいえ、そうではありません。

C/C++ では、 が受け取る値glGetQueryObjectはポインターであり、通常はクライアント メモリ バッファーへのポインターです。この特定の関数の場合、これは多くの場合、スタック変数になります。

GLuint val;
glGetQueryObjectuiv(obj, GL_QUERY_RESULT, &val);

valクライアント コード (つまり、OpenGL を呼び出すコード) によって宣言されます。このコードは、その変数にポインターを渡し、glGetQueryObjectuivこのポインターにデータを書き込みます。

これは、型を使用して C# バインディングでエミュレートされ*Bufferます。これらは、C# が C および C++ の配列へのポインターと互換性のあるポインターを抽出できる連続した値の配列を表します。

ただし、バッファが にバインドされるGL_QUERY_BUFFERと、パラメータの意味が変わります。ご指摘のとおり、メモリへのクライアント ポインタからオフセットになります。しかし、それが言うことに注意してください。「オフセットへのクライアントポインター」とは言いませ

つまり、ポインター値自体は、実際のメモリへのポインターではなくなります。代わりに、ポインターの数値がオフセットとして扱われます。

C++ の用語では、次のようになります。

glBindBuffer(GL_QUERY_BUFFER, buff);
glGetQueryObjectuiv(obj, GL_QUERY_RESULT, reinterpret_cast<void*>(16));

16 バイトのオフセットを取得し、この値が実際にvoid*は 16 という数値であるかのように見せかけていることに注意してください。これが再解釈キャストの動作です。

C# でどのように行うのですか? 何も思いつきません; 使用しているバインディングによって異なりますが、それが何であるかを指定したことはありません。Tao はとっくの昔に亡くなっており、OpenTK もその方向に向かっているようです。しかし、 OpenTK でこれを行う方法を見つけました

あなたがする必要があるのはこれです:

gl4.glBindBuffer(GL_QUERY_BUFFER, bufferName.get(Buffer.QUERY));
for (int i = 0; i < viewports.length; ++i)
{
    gl4.glGetQueryObjectuiv(queryName.get(i), GL_QUERY_RESULT,
        (IntPtr)(i * Integer.BYTES));
}

値はint の配列への整数インデックスではなく、バッファーへのバイト オフセットInteger.BYTESであるため、時間を掛けます。

于 2016-02-17T16:19:21.180 に答える