glGetQueryObjectuiv, "Связанный буфер запросов недостаточно велик для хранения результата".
Я пытаюсь решить ошибку, полученную при запуске этого образца.
Он относится к окклюзии запроса, по сути, он каждый раз визуализирует четыре раза квадрат, изменяя область просмотра, но только центральный два раза он фактически что-то визуализирует, поскольку первая и последняя область просмотра специально находятся вне области монитора.
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, для размера буфера, но безуспешно...
Я думаю, что ошибка лежит где-то еще.. вы могли видеть это?
1 ответ
если мне нужно ответить, я говорю, что ожидаю, что если я свяжу буфер с целью 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#? Я понятия не имею; это будет зависеть от привязки, которую вы используете, и вы никогда не указали, что это было. Тао давно умер, и 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));
}
Вы умножаете раз Integer.BYTES
потому что значение является байтовым смещением в буфере, а не целочисленным индексом в массиве целых чисел.