Поддержка семантического расширения OpenGL

1

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

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

/// <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) одинакова для двух подпрограмм, введенных разностными расширениями.


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

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

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


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

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

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

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


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

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

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

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

Теги:
opengl
binding

1 ответ

1
Лучший ответ

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

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

Например, EXT_FBO не был переведен в ARB_FBO/ядро ​​без изменений. Существовали некоторые существенные изменения, и было бы неправильно просто использовать приложение, которое использовало бы функции 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.

  • 0
    Хорошая идея для псевдонима . Жаль «якобы» (я бы хотел спецификацию спецификации!). Тем не менее, структура приносит структуры, которые объявляют, какое расширение поддерживается или нет; эти флаги можно использовать для изменения семантики без вызова разных функций каждый раз.
  • 0
    Да, это более стабильная информация, чем единственное имя функции, но есть случаи, когда сигнатуры функций не совпадают между псевдонимами, поэтому требуется двойная проверка; Я буду исследовать проблему более глубоко позже.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню