glGetQueryObjectuiv,"Bound query buffer is not large enough to store result."
glGetQueryObjectuiv, "Bound query buffer is not large enough to store result."
我正在尝试解决 运行 this sample.
时出现的错误
它考虑到查询遮挡,本质上它渲染四次方形,每次视口都会改变,但只有中央两次它会实际渲染一些东西,因为第一个和最后一个视口是故意在监控区域之外的。
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 doc 他们会说:
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
也 here..
无论如何,如果那里绑定了任何东西,那么 params 被解释为偏移量,ok
但我的缓冲区足够大:
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,但没有成功...
我想错误出在其他地方..你能看到吗?
if I have to answer, I say I expect that if I bind a buffer to GL_QUERY_BUFFER target, then OpenGL should read the value inside params and interpreter that as the offset (in bytes) where it should save the result of the query to.
不,事情不是这样的。
在C/C++中,glGetQueryObject
取的值是一个指针,通常是一个指向客户端内存缓冲区的指针。对于这个特定的函数,这通常是一个堆栈变量:
GLuint val;
glGetQueryObjectuiv(obj, GL_QUERY_RESULT, &val);
val
由客户端代码声明(即:调用 OpenGL 的代码)。此代码将指针传递给该变量,glGetQueryObjectuiv
将数据写入该指针。
这是通过使用 *Buffer
类型在 C# 绑定中模拟的。这些表示连续的值数组,C# 可以从中提取与 C 和 C++ 指针数组兼容的指针。
但是,当缓冲区绑定到 GL_QUERY_BUFFER
时,参数的含义会发生变化。正如您所指出的,它从一个指向内存的客户端指针变成了一个偏移量。但请注意上面说的是什么。它不是说"client pointer to an offset"。
也就是说,指针值本身不再是指向实际内存的指针。相反,指针的数值被视为偏移量。
用 C++ 术语来说,就是这样:
glBindBuffer(GL_QUERY_BUFFER, buff);
glGetQueryObjectuiv(obj, GL_QUERY_RESULT, reinterpret_cast<void*>(16));
请注意它如何获取 16 个字节的偏移量并假装此值实际上是一个 void*
,其数值为 16。这就是重新解释转换所做的。
你如何在 C# 中做到这一点?我不知道;这将取决于您使用的绑定,并且您从未指定那是什么。 Tao 早就死了,OpenTK looks to be heading that way too. But I did find out how to do this in 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));
}
您乘以 Integer.BYTES
次,因为该值是 字节偏移量 到缓冲区,而不是整数数组的整数索引。
我正在尝试解决 运行 this sample.
时出现的错误它考虑到查询遮挡,本质上它渲染四次方形,每次视口都会改变,但只有中央两次它会实际渲染一些东西,因为第一个和最后一个视口是故意在监控区域之外的。
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 doc 他们会说:
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
也 here..
无论如何,如果那里绑定了任何东西,那么 params 被解释为偏移量,ok
但我的缓冲区足够大:
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,但没有成功...
我想错误出在其他地方..你能看到吗?
if I have to answer, I say I expect that if I bind a buffer to GL_QUERY_BUFFER target, then OpenGL should read the value inside params and interpreter that as the offset (in bytes) where it should save the result of the query to.
不,事情不是这样的。
在C/C++中,glGetQueryObject
取的值是一个指针,通常是一个指向客户端内存缓冲区的指针。对于这个特定的函数,这通常是一个堆栈变量:
GLuint val;
glGetQueryObjectuiv(obj, GL_QUERY_RESULT, &val);
val
由客户端代码声明(即:调用 OpenGL 的代码)。此代码将指针传递给该变量,glGetQueryObjectuiv
将数据写入该指针。
这是通过使用 *Buffer
类型在 C# 绑定中模拟的。这些表示连续的值数组,C# 可以从中提取与 C 和 C++ 指针数组兼容的指针。
但是,当缓冲区绑定到 GL_QUERY_BUFFER
时,参数的含义会发生变化。正如您所指出的,它从一个指向内存的客户端指针变成了一个偏移量。但请注意上面说的是什么。它不是说"client pointer to an offset"。
也就是说,指针值本身不再是指向实际内存的指针。相反,指针的数值被视为偏移量。
用 C++ 术语来说,就是这样:
glBindBuffer(GL_QUERY_BUFFER, buff);
glGetQueryObjectuiv(obj, GL_QUERY_RESULT, reinterpret_cast<void*>(16));
请注意它如何获取 16 个字节的偏移量并假装此值实际上是一个 void*
,其数值为 16。这就是重新解释转换所做的。
你如何在 C# 中做到这一点?我不知道;这将取决于您使用的绑定,并且您从未指定那是什么。 Tao 早就死了,OpenTK looks to be heading that way too. But I did find out how to do this in 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));
}
您乘以 Integer.BYTES
次,因为该值是 字节偏移量 到缓冲区,而不是整数数组的整数索引。