Главная Статьи Ссылки Скачать Скриншоты Юмор Почитать Tools Проекты Обо мне Гостевая Форум |
Данное расширение (введенное в OpenGL 3.2 core) является развитием расширения NV_fence от компании NVidia. Подобно ему расширение ARB_sync вводит понятие примитивов синхронизации. Каждый подобный примитив может находится в одном из дух состояний - GL_SIGNALED и GL_UNSIGNALED. Пользователю предоставляется возможно проверять статус примитива без ожидания и ожидать перевода состояния в GL_SIGNALED как на стороне клиента, так и на стороне сервера.
Каждый примитив соответствует некоторому событию, наступление которого и изменяет статус примитива. Каждый примитив характеризуется значением типа GLsync, отличным от нуля. Проверить, является ли заданное значение идентификатором какого-либо примитива синхронизации, можно при помощи функции glIsSync:
GLboolean glIsSync ( GLsync sync );
На данный момент поддерживается только один тип таких примитивов - fence, позволяющий отслеживать прохождение определенной точки среди последовательности команд. Создание примитива подобного типа и вставка его в текущий поток команд OpenGL осуществляет команда glFenceSync:
GLsync glFenceSync ( GLenum condition, GLbitfield flags );
Данная функция создает примитив синхронизации, выставляет ему статус GL_UNSIGNALED и возвращает его идентификатор (не равный нулю). На данный момент параметр condition может принимать только значение GL_SYNC_GPU_COMMANDS_COMPLETE, а параметр flags - только нулевое значение. Такому выбору соответствует переход объекта в состояние GL_SIGNALED когда все команды, предшествующие данной команде glFenceSync будут выполнены и все их результаты будут доступны и для клиента и для сервера.
Каждый примитив синхронизации обладает целым рядом свойств, в следующей таблице перечислены эти свойства и те значения, которые выставляет вызов glFenceSync.
Таблица 1. Свойства примитива синхронизации после вызова glFenceSync.
Свойство | Начальное значение |
---|---|
GL_OBJECT_TYPE | GL_SYNC_FENCE |
GL_SYNC_CONDITION | GL_SYNC_GPU_COMMANDS_COMPLETE |
GL_SYNC_STATUS | GL_UNSIGNALED |
GL_SYNC_FLAGS | 0 |
В любой момент можно получить значение любого свойства для любого примитива синхронизации при помощи функции glGetSynciv.
void glGetSynciv ( GLsync sync, GLenum pname, GLsizei bufSize, GLsizei * length, GLint * values );
Данный вызов возвращает для объекта синхронизации, заданного параметром sync, свойство, задаваемое параметром pname. Результаты помещаются в массив, задаваемый параметром values, параметр bufSize задает максимальный количество целочисленных значений, которое можно поместить в этот массив. В параметре length возвращается число записанных в values целых чисел. Следующая таблица содержит информацию о возвращаемых значениях для всех допустимых значений pname.
Таблица 2. Возвращаемые значения для функции glGetSynciv.
Значение pname | Возвращаемое значение |
---|---|
GL_OBJECT_TYPE | Возвращает одно целое число, равное GL_SYNC_FENCE |
GL_SYNC_CONDITION | Возвращает одно целочисленное значение, равное GL_SYNC_GPU_COMMANDS_COMPLETE |
GL_SYNC_STATUS | Возвращает одно целочисленное значение, равное GLSIGNALED или GL_UNSIGNALED |
GL_SYNC_FLAGS | Возвращает одно целочисленное значение, равное нулю |
Для уничтожения примитива синхронизации служит функция glDeleteSync:
void glDeleteSync ( GLsync sync );
При этом, если имеет место ожидание по данному примитиву или соответствующее событие еще не наступило, то объект просто помечается для удаления и будет удален по завершению ожидания или наступлению события. В противном случае объект удаляется немедленно.
Существует две функции, служащие для ожидания перевода примитива в состояние GL_SIGNALED. Одна функция служит для ожидания на стороне клиента, другая - для ожидания на стороне сервера.
GLenum glClientWaitSync ( GLsync sync, GLbitfield flags, GLuint64 timeout );
void glWaitSync ( GLsync sync, GLbitfield flags, GLuint64 timeout );
При помощи команды glClientWaitSync можно явно задать ожидание (клиентом) наступления события или же просто проверить статус без ожидания. Параметр flags на данный момент должен быть равен константе GL_SYNC_FLUSH_COMMANDS_BIT, параметр timeout задает время ожидания клиента в наносекундах (10-9 сек). Если параметр timeout равен нулю, то никакого ожидания вообще не происходит, а сразу же возвращается код GL_ALREADY_SIGNALED (если событие уже наступило) или же GL_TIMEOUT_EXPIRED (если событие еще не наступило).
В случае когда параметр timeout не равен нулю, то может произойти ожидание клиентской части, но не более чем заданное количество наносекунд. После чего возвращается одно из значений, перечисленных в таблице 3.
Таблица 3. Возвращаемые значения для функции glClientWaitSync.
Значение pname | Возвращаемое значение |
---|---|
GL_ALREADY_SIGNALED | На момент вызова событие уже наступило |
GL_TIMEOUT_EXPIRED | За timeout наносекунд событие так и не наступило |
GL_CONDITION_SATISFIED | Событие наступило до истечения timeout наносекунд |
GL_WAIT_FALIED | Произошла ошибка |
Функция glWaitSync аналогична функции glClientWaitSync, но она блокирует на время ожидания не клиентскую часть, а GL-сервер. Параметр timeout всегда должен быть равен константе GL_TIMEOUT_IGNORED, а параметр flags должен быть равен нулю. При этом ожидание сервера будет происходит на зависящее от реализации время, которое можно узнать при помощи следующего фрагмента кода:
GLint64 maxTimeout;
glGetInteger64v ( GL_MAX_SERVER_WAIT_TIMEOUT, &maxTimeout );
Обратите внимание, что возможно одновременная блокировка как клиента, так и сервера.
Для удобства работы завернем примитив синхронизации в следующий класс:
#ifndef __SYNC_OBJECT__
#define __SYNC_OBJECT__
class Sync
{
GLsync sync;
public:
Sync ();
~Sync ();
bool isOk () const
{
return sync != 0;
}
void setFence ( GLenum condition = GL_SYNC_GPU_COMMANDS_COMPLETE,
GLbitfield flags = 0 );
GLenum clientWait ( GLuint64 timeout, GLbitfield flags = GL_SYNC_FLUSH_COMMANDS_BIT );
void serverWait ( GLuint64 timeout = GL_TIMEOUT_IGNORED, GLbitfield flags = 0 );
static GLint64 maxServerTimeout ();
};
#endif