Подключение "Стандартных сборок".

Здравствуйте, решил я значит сделать игру используя Pascal ABC. И решил подключить уже существующие библиотеки во вкладке GAC. Но к моему удивлению, ничего не работает, кроме System библиотек. Вопрос, можно ли вообще работать с библиотеками сторонними, такими как DirectX или OpenGL в среде PascalABC?

Что за вкладка GAC? Вы имеете в виду вид в форме папки? Там несколько вариантов, укажите точно чтобы небыло путаницы.

PascalABC и PascalABC.Net это разные языки.

В частности, GAC (Global Assembly Cache) это .Net библиотеки, к которым была заранее применена JIT компиляция, чтобы ускорить запуск программ, подключающих эти библиотеки.
Но .Net библиотеки можно подключать только к .Net программам. Поэтому к давно сдохшему PascalABC вы их не подключите.

Тем временем, OpenGL.dll и библиотеки DirectX это неуправляемые (средой выполнения .Net). Они не могут быть в GAC.
И они не содержат интерфейс в виде типов данных и т.п., подключать из них можно только подпрограммы. И то, подпрограмме надо всегда вручную указать сигнатуру, потому что в библиотеке есть только точка входа (адрес в .dll файле, откуда начинать выполнять подпрограмму).

К примеру в User32.dll есть эта подпрограмма:
MessageBox function (winuser.h) - Win32 apps | Microsoft Learn
Если перевести сигнатуру с C/C++ на паскаль, получается:

function MessageBox(hWnd: System.IntPtr; lpText, lpCaption: string; uType: cardinal): integer; 
  external 'User32.dll' name 'MessageBox'; 

(взял из справки, поиск по external, но там чуток неправильно)

Вообще при переводе сигнатур есть куча неоднозначностей. К примеру такую подпрограмму C/C++:

void p1(int* x);

Можно перевести как:

procedure p1(x: ^integer); // указатель, то есть неуправляемый адрес
procedure p1(var x: integer); // ссылка, то есть управляемый адрес
procedure p1(x: array of integer); // массив целиком

И на этом сложности не заканчиваются. Если у вас есть массив var a := new integer[10], который вы хотите передать библиотеке - вызвать вам даст любую из этих 3 перегрузок: p1(@a[0]), p1(a[0]) и p1(a) соответственно. Но первая приведёт к утечке памяти, ибо нечего бездумно смешивать ссылочные типы (классы, коими являются массивы) с указателями.


Не знаю как работает DirectX, но в OpenGL не все подпрограммы находятся в .dll, некоторые надо загружать особой функцией после создания контекста OpenGL.

Я уже реализовал сигнатуры всех подпрограмм (включая расширения) и всю их загрузку, вы можете подключать готовый модуль OpenGL. И посмотрите в папку примеров:
PABCWork.NET\Samples\StandardUnits\OpenGL и OpenCL
Там, кроме собственно примеров, .html файлы, объясняющие как такие модули использовать.

Про подключение OpenTK, Tao, sharpDX можете у TheMrDen3D на YouTube посмотреть. Можно создать новый проект. Проект. Подключить сборку. NuGet. И подгрузить их, вроде как. Это для PascalABC.NET. У меня, кстати, “Крутящийся треугольник” из примеров выдаёт ошибку:

Common.pas(48) : Ошибка времени выполнения: Крутящийся треугольник.vert:
ERROR: 0:15: 'gl_FrontColor' : undeclared identifier 
ERROR: 0:15: 'rgb' : vector field selection out of range 
ERROR: 0:15: 'assign' :  cannot convert from 'attribute 3-component vector of highp float' to 'highp float'
ERROR: 0:16: 'a' : vector field selection out of range 


“точки на поле” работает

Какая модель GPU и версия библиотеки OpenGL?

Что если добавить:

out vec4 gl_FrontColor;

?

(или может придётся другое имя выбрать, если ему не понравится что пользовательское имя начинается с gl_… в любом случае, отпишитесь какая ошибка во всех случаях что вы протестили)

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

Попробуйте это: Крутящийся треугольник.rar (2,7 КБ)
Ну, даже если так работает - пж отпишитесь о всём остальном тож… Я пока подожду менять это в исходном репозитории.

Intel(R) HD Graphics 620. версия драйвера 25.20.100.6617. Версию OpenGL не знаю как посмотреть. Открывается окно, закрашенное чёрным. в окне вывода: INVALID_OPERATION

Это в каком из случаев?

это вы файл прислали

Очень древняя версия, ещё с 2019, поидее уже должно быть и новее… У Intel-а есть своя утилита для обновления дров.

    // получаем тип последней ошибки
    var err := gl.GetError;
    // и если ошибка есть - выводим её
    if err<>ErrorCode.NO_ERROR then Writeln(err);

Это проверяется единожны после каждого кадра. Надо найти после какой строчки даёт эту ошибку - только вы этим можете занятся, потому что у вас воспроизводится. Но сначала таки обновитесь, потому что в старых драйверах искать проблему дело неблагодарное.

Драйвер загружаются. После этой строчки:

// Оставляем всё настроенным и привязанным
// В данном случае можно, потому что шейдерная программа одна
gl.VertexAttribFormat(attribute_position, 2,VertexAttribType.FLOAT, false, 0);

Если добавить

out vec4 gl_FrontColor;

ему gl_ не нравится:

Common.pas(48) : Ошибка времени выполнения: Крутящийся треугольник.vert:
ERROR: 0:5: 'gl_FrontColor' : the gl_ identifier prefix is reserved for use by OpenGL ES gl_


Ну, то что ему gl_ не нравится это я уже ожидал. А добавляете вы куда?
Вы же вроде сказали что то что я в .rar прислал запускаете - там уже отредактировано, так что добавлять ничего не надо. А если в исходный пример, который с паскалем устанавливается - говорите сразу, иначе путаница будет…

В любом случае, где всё же получается INVALID_OPERATION? В какой версии примера и на какой строчке?

INVALID_OPERATION возникает в версии, которую вы прислали после 64 строчки. добавлял в пример, идущий с паскалем. Об этом вам надо было сюда писать, я только сейчас заметил

Да, теперь уже дошло…

Из справки:

GL_INVALID_OPERATION is generated by glVertexAttribFormat, … if no vertex array object is bound.

gl_vertex_array это вообще отдельная штука, но я знаю наверняка что она тут не обязательна.
Возможно оно хочет чтобы вы сначала выполнили Bind, чтобы оно сразу смогло скопировать данные из буфера куда-то себе… Хотя это странное поведение драйвера, но попробуйте поменять местами в том что я .rar кидал, чтобы было так:

    gl.BindVertexBuffer(attribute_position, vertex_pos_buffer, IntPtr.Zero, sizeof(Vec2f));
    gl.VertexAttribFormat(attribute_position, 2,VertexAttribType.FLOAT, false, 0);

(ниже, в случае inp_color так же поменять надо будет, но поидее будет сразу видно что ошибка ниже, если вы раскомментировали и использовали var RaiseIfError := procedure->)

Ну, не принципиально. Я тут тоже обитаю. Основное преимущество issue в том, что их можно на долго оставлять - забыть не получится. Но я думаю это дело можно сегодня сразу и решить.

так тоже INVALID_OPERATION пишет

gl.BindVertexBuffer(attribute_position, vertex_pos_buffer, IntPtr.Zero, sizeof(Vec2f));
    // получаем тип последней ошибки
var err := gl.GetError;
    // и если ошибка есть - выводим её
if err<>ErrorCode.NO_ERROR then Writeln(err);
gl.VertexAttribFormat(attribute_position, 2,VertexAttribType.FLOAT, false, 0);

я драйвер обновлю сейчас

Теперь ваша версия работает. Версия в примерах даёт ту же ошибку c gl_FrontColor. Версия драйвера: 31.0.101.2121 Его дата: 03.03.2023

Ладно, раз в последней версии драйвера работает - наверное баг в драйверах был. Подход с gl.VertexAttribFormat вместо gl.VertexAttribPointer более современный…

Про gl_FrontColor? Ну ладно, вариант с простеньким фрагментным шейдером немного объёмней, но и более правильный.

Новую версию модуля OpenGL, вместе с этим исправленным примером, я собираюсь через несколько недель послать, чтобы в установщик добавили. Пока используйте эту временную версию, что в .rar тут была…