В настоящее время я использую привязку 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 (на данный момент никто! Так что никто не будет жаловаться на это! :)).