Поддержка семантического расширения OpenGL - PullRequest
1 голос
/ 26 августа 2011

В настоящее время я использую привязку OpenGL на C #, автоматически генерируемую из файлов .spec Khronos, найденных в реестре .

Я очень доволен качеством креплений; Вот пример функции:

/// <summary>
/// Binding for glGenFramebuffers function.
/// </summary>
/// <remarks>
/// This function belongs to 'ARB_framebuffer_object'.
/// <para>
/// Depending on driver implementation, this routine could call the following (equivalent) routines:
/// - glGenFramebuffers
/// - glGenFramebuffersEXT
/// </para>
/// </remarks>
/// <param name="n">
/// A <see cref="Int32"/>.
/// </param>
/// <param name="framebuffers">
/// A <see cref="UInt32*"/>.
/// This parameter holds data returned from function.
/// </param>
public static void GenFramebuffer(Int32 n, [Out] UInt32[] framebuffers) {
    unsafe {
        fixed (UInt32* fp_framebuffers = framebuffers)
        {
            if      (Delegates.pglGenFramebuffers != null)
                Delegates.pglGenFramebuffers(n, fp_framebuffers);
            else if (Delegates.pglGenFramebuffersEXT != null)
                Delegates.pglGenFramebuffersEXT(n, fp_framebuffers);
            else
                throw new InvalidOperationException("binding point GenFramebuffer cannot be found");
        }
    }
    LogProc("glGenFramebuffers("+n+", "+framebuffers+")");
}

Как вы можете заметить, фиксированный блок пытается вызвать двух разных делегатов ( Delegates.pglGenFramebuffers и Delegates.pglGenFramebuffersEXT ).

Это возможно, поскольку они имеют одинаковую подпись:

[System.Security.SuppressUnmanagedCodeSecurity()]
internal unsafe delegate void glGenFramebuffers(Int32 n, [Out] UInt32* framebuffers);
internal static glGenFramebuffers pglGenFramebuffers = null;

[System.Security.SuppressUnmanagedCodeSecurity()]
internal unsafe delegate void glGenFramebuffersEXT(Int32 n, [Out] UInt32* framebuffers);
internal static glGenFramebuffersEXT pglGenFramebuffersEXT = null;

Делегаты имеют одинаковую подпись, потому что спецификация (файл .spec) одинакова для двух подпрограмм, представленных расширениями различий.


Ранее привязки имели поддержку только для расширений core, ARB и EXT; генератор привязок просто избегает определения этих подпрограмм, если существует другая эквивалентная программа с более высоким приоритетом.

Чтобы увеличить поддержку расширений (стимулируется этим SO вопросом ), я требую объявить делегатов и импортировать объявление также для тех подпрограмм, которые были переведены в ARB или в базовую реализацию, и написать реализацию-обертку, которая вызывает все эквивалентные процедуры (те, которые определены).

Таким образом, я получил источник, объявленный выше.


Проблемы начинаются при работе с объявлениями функций 2K +. У меня есть генератор привязок, так как я не могу написать все привязки OpenGL.

Но как генератор привязок может узнать, является ли подпрограмма func семантически эквивалентной другой подпрограмме funcARB или funcEXT (с той же сигнатурой)

Я думаю, что единственный вариант, который у меня есть, - написать внешний файл (контролируемый разработчиком), в котором перечислены случаи исключений (то есть две подпрограммы, имеющие базовое имя и одинаковую подпись, не являются семантически эквивалентными).

Конечной целью должна быть свернутая библиотека обертки связывания OpenGL, чтобы минимизировать усилия, необходимые для управления расширениями OpenGL.


После некоторых экспериментов ...

Возможно, что оба соответствующих расширения реализованы (то есть ARB_framebuffer_object и EXT_framebuffer_object). Так как точки входа разные (разные имена), мне нужны все функции обоих расширений .... но!

Если я отдам приоритет поддерживаемым расширениям (скажем, ARB имеет более высокий приоритет, чем EXT, EXT имеет более высокий показатель, чем VENDOR), предложенная реализация в моем вопросе приемлема для среды оболочки, поскольку расширение ARB реализовано, реализация фреймворка предпочла бы его, чем реализация EXT (независимо от того, какая функциональность).

Это бы сработало, но побочным эффектом является то, что эта политика навязывается пользователям привязки OpenGL (на данный момент никто! Так что никто не будет жаловаться на это! :)).

1 Ответ

1 голос
/ 26 августа 2011

Тебе придется немного поработать, но это не так плохо, как ты думаешь. Вместо того, чтобы работать на уровне функций, вам нужно работать на уровне расширений.

Либо расширение было переведено в ядро ​​с точно такой же функциональностью , либо это не так. Если это не так, то неуместно заменять одно другим. Так что вам нужен список расширений, которые продвигаются до ядра, пришли с модификациями.

Например, EXT_FBO был не повышен до ARB_FBO / core без изменений. Произошли некоторые существенные изменения, и было бы неправильно просто иметь приложение, использующее функции EXT, использующее эквиваленты ARB без изменений.

Создание списка расширений, которые изменились с продвижением, не так просто. Для этого потребуется просмотреть действительные спецификации и посмотреть, что фактически изменилось с одной версии на другую.

Один положительный момент заключается в том, что в последнее время ARB имеет привычку делать так называемые «базовые расширения». Это расширения ARB, которые идеально отражают поведение ядра, вплоть до имен функций. Таким образом, функции и перечислители ARB_FBO не имеют суффикса "ARB". Большинство новых расширений ARB попадают в эту категорию.

В качестве альтернативы вы можете использовать поле alias в файле gl.spec. Это поле предположительно представляет альтернативную версию функции. Например, если вы посмотрите «GenFramebuffersEXT» в gl.spec, вы обнаружите, что оно имеет значение alias «GenFramebuffers». Псевдоним, кажется, всегда указывает от функции расширения на эквивалент ядра. Я не имею ни малейшего понятия, насколько актуальна или точна эта информация, но вы можете ее использовать. Не составит труда изменить генератор кода, чтобы использовать информацию и посмотреть, что из нее получится.

Из беглого изучения gl.spec кажется, что псевдонимы не следуют правилам, которые я изложил выше. Есть некоторые псевдонимы (например, NV_transform_feedback для обратной связи преобразования ядра), которые на самом деле не очень хорошая идея. NV_transform_feedback позволяет вам установить параметры обратной связи после того, как вы свяжете программу. И хотя кто-то наверняка захочет эту функциональность, ядро ​​этого не позволяет. Поэтому, если вы разрешите их использовать псевдоним, пользователь может случайно использовать функциональные возможности NV на карте NVIDIA, и внезапно его код перестанет работать на картах не-NVIDIA.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...