Cheb's Game Engine

Планы, идеология, архитектура и т.п.

Модератор: Модераторы

Re: Cheb's Game Engine

Сообщение Alex2013 » 08.03.2021 21:55:21

Уф! "Ужасный тормоз" победил ! Очень просто, кстати ... Поместил в снятие скрин-шота в отдельный поток (с двухступенчатой активаций по дополнительному таймеру ) и что выдумаете? Рендер вообще его "не замечает" ... Но появилось странное ограничение по объему данных.
(Разрешению текстуры 1150х1000 все ок а например 1200х1000 не работает причем как-то странно внезпно "вспоминает" самый первый из захваченных кадров... ).
Толи не успевает. Толи еще что-то...
Была бы это программа на ХайАсме я бы точно сказал, что это снова"кольцевание прорезалось " но в Лазарусе вроде такого почти не бывает .

FPS радует а глюк нет ...
ИзображениеИзображение
Зы
Извиняюсь за оффтоп . :idea:
Alex2013
долгожитель
 
Сообщения: 2090
Зарегистрирован: 03.04.2013 11:59:44

Re: Cheb's Game Engine

Сообщение Cheb » 09.03.2021 02:26:04

Опенгл и отдельный поток - это "безумству храбрых поём мы песню".
То есть, иногда, у кого-то, работает. Иногда. У кого-то. После плясок с бубном, достойных битого жизнью профессионала в этом гапи.
По моему скромному мнению - скриншот можно снимать в отдельном потоке, а вот в текстуру заливать - только в основном. Иначе драйвер может не понять и обделаться от неожиданности.

У меня в движке создание текстур и заливка в них содержимого - фоновые задачи, разрешённые к выполнению только в основном потоке.

З.Ы. Говорят, что текстуры заливать можно, после определённых плясок с бубном: https://www.khronos.org/opengl/wiki/Ope ... ithreading
но всё же ведь зависит от радиуса кривизны драйвера

Добавлено спустя 15 часов 38 минут 54 секунды:
Вот к вопросу о глобальных переменных: когда всё состояние БД собрано в одну запись (сколько я на отдельные глобальные переменные охотился, сколько они крови моей выпили!) его можно одним махом подменить, заморозив один модуль в памяти и запустив другой.
Пока использую только для модуля панели управления, который заведует выбором языка, выбором модуля и показом всяких страшных сообщений:

Код: Выделить всё
  function THubModule.FreezeInMemory: boolean;
  begin
    Result:= true;
    if f_frozen then exit;
    f_frozen:= true;

    MOVE(chepersy.Cps, SavedChepersyState, sizeof(chepersy.Cps)); //включая диспетчер памяти инстансов и всю информацию о зарегистрированных классах
    FillChar(chepersy.Cps, sizeof(chepersy.Cps), 0); // NO deinit!

    SavedState:= Mother^.Module.State - [msa_MustUnload];
    FillChar(Mother^.Module.State, sizeof(Mother^.Module.State), 0);

    SavedLogClass:= MyLogClass;
    MyLogClass:= nil;

    if Module = Self then Module:= nil;
    HubModule:= Self;
    Mother^.Module.HubState:= _hubInert;
    Mother^.Module.HubPrevState:= _hubInert;
  end;

  procedure THubModule.UnFreezeFromMemory;
  begin
    if not f_frozen then Die('Cannot unfreeze, not frozen.');
    if not chepersy.Cps.IsDone then begin
      Mother^.State.StateTrashedRestartRequired:= true;
      Die(RuEn(
        'FATAL: предыдущий модуль не завершил работу с %0',
        'FATAL: the previous module failed to close the %0'
      ), [ChepersyTitle]);
    end;
    MOVE(SavedChepersyState, chepersy.Cps, sizeof(chepersy.Cps));
    Mother^.Module.State:= SavedState;
    MyLogClass:= THubLogic;
    f_frozen:= false;
    Module:= Self;
  end;
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 885
Зарегистрирован: 06.06.2005 15:54:34

Re: Cheb's Game Engine

Сообщение runewalsh » 09.03.2021 18:45:53

Вроде бы безопасный способ скопировать по указателю что угодно, включая управляемые типы — это
Код: Выделить всё
var
   a, b: T;
procedure fpc_finalize(data, typeInfo: pointer); [external name 'FPC_FINALIZE'];
function fpc_addref(data, typeInfo: pointer): SizeInt; [external name 'FPC_ADDREF'];

fpc_finalize(@b, TypeInfo(T));
// ↑ Или просто Finalize(b), если переменная b типизирована, а не скрыта за голым указателем.
// ↑ Или изкоробочное FinalizeArray(@b, TypeInfo(T), 1).
Move(a, b, sizeof(T));
fpc_addref(@b, TypeInfo(T)); // Нет аналога из коробки.

По идее можно было бы использовать единственную fpc_copy(src, dest, typeInfo) или изкоробочную CopyArray, но последний раз они у меня работали ТОЛЬКО с managed-типами, а fpc_finalize + Move + fpc_addref копирует что угодно, и вроде как полностью универсально и безопасно (даже совместимо с managed operators).
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 523
Зарегистрирован: 27.04.2010 00:15:25

Re: Cheb's Game Engine

Сообщение Alex2013 » 09.03.2021 22:24:53

Cheb писал(а):Опенгл и отдельный поток - это "безумству храбрых поём мы песню".

Это ты слишком хорошо обо мне думаешь.... :lol: Разумеется "в поток" я упрятал только "снятие скрина" ("Наружу" выглядывает только глобальная переменная из которой рендер "ложками черпает вдохновение" :idea: ) Рендер я кстати "утрамбовал" в мультимедийный таймер и неуверен что это хорошая идея ( но в примерах такое встречается )
Зы
Глюк тоже немного укротил .
(Оказалась что "играть в суперсэмплинг" плохая идея и максимальный размер выдергиваемого скрина должен быть ("Ширина экрана","Высота экрана"-2) тоже непонятно, но уже несмертельно . )

ИзображениеИзображение
Alex2013
долгожитель
 
Сообщения: 2090
Зарегистрирован: 03.04.2013 11:59:44

Re: Cheb's Game Engine

Сообщение Cheb » 10.03.2021 02:39:57

runewalsh писал(а):Вроде бы безопасный способ скопировать по указателю что угодно, включая управляемые типы — это

Спасибо, буду иметь в виду.
Но я намеренно копирую так, "чтобы компилятор ни о чём не догадался". Как бы замораживая всю эту сущность со всеми её счётчиками ссылок в безвременье.
А собирание глобальных переменных в одну запись имеет то преимущество, что по скорости ничем не отличается от обращения к отдельным глобальным переменным.
Кстати, для оптимизации необходимо будет запилить свой аналог массива, адресуемого только последовательно. Т.е. добавить в конец, начать сначала, прочитать следующий, очистить - все доступные операции. И без никакого счётчика ссылок.

Но пока я никак эту заразную машину состояний модуля не добью. То один глюк прёт, то другой.

Alex2013 писал(а):"Высота экрана"-2

Ы? :shock:
А там, случаем, где-то параметр не "нижний край" вместо "высота"? А то знаю я этих затейников.
Кстати, теперь понятно. Блит со стретчем - какая-то стрёмная операция, я бы не рискнул. Суперсэмплинг эффективнее делается внутри огля, на шейдерах.

Проверено на практике: если выборки из текстуры ложатся кучно в очень малую область - можно хоть тридцать чтений из текстуры на пиксел в full HD. И это - на хилом Intel HD 3000.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 885
Зарегистрирован: 06.06.2005 15:54:34

Re: Cheb's Game Engine

Сообщение Alex2013 » 10.03.2021 13:47:15

Cheb писал(а):. Блит со стретчем - какая-то стрёмная операция

Угу ...
Кусок самого "загадочного" кода в моей программе .
Код: Выделить всё
procedure  TCaptureThread.Execute;
begin
while (not Terminated) do begin
IF (bmp <> Nil ) and UPDATE  Then begin  UPDATE:=False;
ProcessRUN :=True;
CaptureForm.CreateSnapshotPlusWH(bmp,R_W,R_H,unit6.FHandle,RS);
Tbmp:=bmp; Tbmp.Canvas.Draw(0, 0 ,bmp);
ProcessRUN :=False;
end
end
end; 

:shock:
Нет я знаю что Tbmp:=bmp; Tbmp.Canvas.Draw(0, 0 ,bmp); это дичайший бредовый бред ... но без него текстура "не подхватывается" .

Cheb писал(а): Суперсэмплинг эффективнее делается внутри огля, на шейдерах.

Дело за малым научиться использовать эти самые шейдеры. А я еще и в самом "классическом OpenGL " ой как "плаваю".
Alex2013
долгожитель
 
Сообщения: 2090
Зарегистрирован: 03.04.2013 11:59:44

Re: Cheb's Game Engine

Сообщение Cheb » 11.03.2021 05:33:51

Alex2013 писал(а):научиться использовать эти самые шейдеры.

Боль. Боооооль. :x
Зато потом ощущаешь себя, словно ты на холме с пулемётом, а вокруг одни дикари :D

это дичайший бредовый бред ... но без него текстура "не подхватывается" .

А как не подхватывается - просто ничего не происходит, или её развозит на разводы?
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 885
Зарегистрирован: 06.06.2005 15:54:34

Re: Cheb's Game Engine

Сообщение Alex2013 » 11.03.2021 11:49:24

Cheb писал(а):А как не подхватывается - просто ничего не происходит, или её развозит на разводы?

Просто не видит текстуру как будто её нет. Возможно заявлений размер не совпадает с реальным или еще что-то.

"Пиксель формат" проверял pf24bit все ок.
Для проверки есть простая спец. процедура.
Код: Выделить всё
Function BitmapTest(var TB:TBitmap; Mode:TPixelFormat;
   F_Free:Boolean=true):Boolean ;
   Var
   CB:TBitmap;
   Begin
    Result:= tb.PixelFormat=mode ;
   if not Result then
   begin
   CB:=TBitmap.Create;
   cb.PixelFormat:=Mode;
   cb.SetSize(tb.Width,tb.Height);
   Cb.Canvas.Draw(0,0,TB);
   if F_Free then tb.free;
   Tb:=CB;
   end
   end;



На этом битмапе вообще интересные дела творятся ... Например решил я нарисовать курсор мыши, но думаю, а что мешает мне сделать "битовую версию" рисования линии ? Сказано сделано ! И что ? "Помехи" почти как КП 2077 любят показывать(но не пиксиляция, а "суб пиксельные" черные полосы типа "разсинхронизация" ). Сделал через канвас все ок . Вот откуда ? Да."Выводит OpenGL" но я рисую крестик курсора до того как OpenGL вообще узнает о самом существовании текстуры.
Alex2013
долгожитель
 
Сообщения: 2090
Зарегистрирован: 03.04.2013 11:59:44

Re: Cheb's Game Engine

Сообщение Cheb » 11.03.2021 14:37:27

Вангую, что этот битмап - сложная сущность с встроенной двойной буферизацией. И для получения из него "указателя на данные" с ним надо сначала что-то сделать, чтобы привести в пригодное к чтению состояние.

Журналируй, что кормишь glTexImage - указатель не нулевой, случаем?
Смотри, что говорит glGetError()

вот может пригодится
Код: Выделить всё
function GlErrorCodeToString(c: GLenum): Utf16String;
begin
  case c of
    GL_INVALID_ENUM: Result:= 'GL_INVALID_ENUM';
    GL_INVALID_VALUE: Result:= 'GL_INVALID_VALUE';
    GL_INVALID_OPERATION: Result:= 'GL_INVALID_OPERATION';
    GL_STACK_OVERFLOW: Result:= 'GL_STACK_OVERFLOW';
    GL_STACK_UNDERFLOW: Result:= 'GL_STACK_UNDERFLOW';
    GL_OUT_OF_MEMORY: Result:= 'GL_OUT_OF_MEMORY';
    GL_INVALID_FRAMEBUFFER_OPERATION_EXT: Result:= 'GL_INVALID_FRAMEBUFFER_OPERATION_EXT';
    GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: Result:= 'GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT';
    GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: Result:= 'GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT';
    GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT: Result:= 'GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT';
    GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: Result:= 'GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT';
    GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: Result:= 'GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT';
    GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: Result:= 'GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT';
    GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: Result:= 'GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT';
    GL_FRAMEBUFFER_UNSUPPORTED_EXT: Result:= 'GL_FRAMEBUFFER_UNSUPPORTED_EXT';
    GL_FRAMEBUFFER_STATUS_ERROR_EXT: Result:= 'GL_FRAMEBUFFER_STATUS_ERROR_EXT';
  else
    Result:= RuEn('код', 'code') + ' ' + IntToHex(c, 8) + 'h';
  end;
end; 


Добавлено спустя 8 минут 36 секунд:
P.S.
В многопоточке такой метод разграничения
Код: Выделить всё
ProcessRUN :=True;

эффективен, как картонная броня против снаряда главного калибра.
Другой поток выполняется на другом ядре, до которого изменения памяти могут доходить с большой задержкой, как до того жирафа. Ведь кеши 1 и 2 уровня у ядер собственные.
Только TCriticalSection.
Плюс, двойную буферизацию: битмапа - два, один хватает экран, из другого опенгл грузит в текстуру. Потом меняются. Переключение битмапа и чтение в текстуру обернуть в одну критическую секцию.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 885
Зарегистрирован: 06.06.2005 15:54:34

Re: Cheb's Game Engine

Сообщение Alex2013 » 12.03.2021 02:45:28

Cheb писал(а):В многопоточке такой метод разграничения эффективен, как картонная броня против снаряда главного калибра.

Это разумеется верно но мне нужно узнать закончилось ли снятие скрина или нет чтобы снова поднять флаг UPDATE.
А поскольку проверка происходит по таймеру (а рендер крутится в другом ) то особой точности не нужно (другое дело что рендер может теоретически попасть в момент "пересменки " но ничего особо страшного это вызвать не может никакой "обратной записи" вне TCaptureThread нет, а "кусок памяти по адресу" так останется куском памяти по адресу )

Cheb писал(а):Плюс, двойную буферизацию: битмапа - два, один хватает экран, из другого опенгл грузит в текстуру. Потом меняются. Переключение битмапа и чтение в текстуру обернуть в одну критическую секцию.


А вот это разумеется дельная мысль, попробую !

вот может пригодится
Угу только в рендере с "ВиАр контестом" особо "не попрыгаешь" (уже убедился, что любые задержки больше 10-20 мс (или нестабильности) делают, что-то нехорошее с тамошней хитрой репроекцией ( запоминающей кадры и частично "подменяющей рендер" при быстром движении башкой ) )

glTexImage пробовал и "нулевой" и "не нулевой" и как мне показалось разницы нет потому что дальше все равно идет glTexSubImage2D. (Вот на несовпадение размеров реакция действительно жесткая )
Последний раз редактировалось Alex2013 13.03.2021 16:25:55, всего редактировалось 1 раз.
Alex2013
долгожитель
 
Сообщения: 2090
Зарегистрирован: 03.04.2013 11:59:44

Re: Cheb's Game Engine

Сообщение Cheb » 13.03.2021 16:02:23

З.Ы. Не два, а много (с запасом на два экрана). И хватать полосками по 64 пиксела высотой. И в опенгл заливать по полоске.
Минус - гарантирован tearing (когда половина экрана опережает другую). Плюс - вытираешь тапочки об латентность.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 885
Зарегистрирован: 06.06.2005 15:54:34

Re: Cheb's Game Engine

Сообщение Alex2013 » 13.03.2021 22:10:31

Cheb писал(а):З.Ы. Не два, а много (с запасом на два экрана). И хватать полосками по 64 пиксела высотой. И в опенгл заливать по полоске.

Ну это уже на будущее стоит иметь ввиду (ИМХО на уровне техно-демки чрезмерно "вылизывать" оптимизацию смысла нет все равно в "боевом коде" многое будет иначе ). Задача пока просто "попробовать получить результат" в относительно стабильном виде . (Так сказать "на троечку") и двинутся дальше.
Сейчас например разбираюсь с "псевдо-текстовым GUI интерфейсом" точнее с его эмуляций в OpenGL.
(те-же окна, кнопки, панели что и в LCL но "висящие в пространстве" )
Alex2013
долгожитель
 
Сообщения: 2090
Зарегистрирован: 03.04.2013 11:59:44

Re: Cheb's Game Engine

Сообщение Cheb » 14.03.2021 06:44:31

Тоды - не помню уже просто, приводил или нет - простой, как валенок, способ понизить латентность https://habr.com/en/post/308980/ там на лазарусе, но для 11-го директикса. Но для огля тот же метот работает также: перед SwapBuffers вызвать принудительную синхронизацию цпу и гпу путём чтения glReadPixels фрейимбуфера. Он говорит, мипмап надо генерировать, но я думаю прочитать несколько кусочкоа 8х8 из разных мест даст тот же результат: пока не нарисовано - прочитать не сможет, тем самым принуждая синхронизацию.

Добавлено спустя 10 часов 12 минут 5 секунд:
Перелопатил систему привязки системы состояний для тредов на нормальный threadvar, оставив связанный список для специфичного места менеджера тредов в модуле и рисовальщика индикаторов загрузки тредов.
И хватит до следующих выходных.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 885
Зарегистрирован: 06.06.2005 15:54:34

Re: Cheb's Game Engine

Сообщение Cheb » 19.03.2021 09:54:26

Упсник

Долго не мог найти причину странных крахов при выходе, а конкретно - при попытке очистить/вывести буфер сообщений об ошибках. Уводит куда-то в глубины форматирования строк, оттуда - в неведомые недра RTL, и уже там падает.
Потом зацепился взглядом за гистограммы.
Изображение
Чу! Что это за загадочный тред без названия и почему у основного треда нулевая загрузка?
Упс.
Менеджер тредов сводит все их записи в запись основного треда. Которая должна лежать в строго определённой глобальной переменной. А я, когда переделывал...
Короче, указатель на запись для основного треда должен выставляться в @Mother^.ExceptionState , а не new(PMotherSehState) , как у всех остальных.
А я это граничное условие забыл :oops: Ииии-хряп. Ииии-хряп.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 885
Зарегистрирован: 06.06.2005 15:54:34

Re: Cheb's Game Engine

Сообщение Cheb » 20.03.2021 17:52:03

Начал постепенную переделку словесного поноса в журнале на активацию по типам событий вместо бывшего глобального true/false.

Затрахался с машиной состояний, буду всё сносить на и делать проще: переход на панель управления провоцируется переменной, переход обратно - только через соответствующие элементы главного меню панели управления. Ибо выделывало такие коленца, что просто рукалицо.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 885
Зарегистрирован: 06.06.2005 15:54:34

Пред.След.

Вернуться в Разработки на нашем сайте

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1

Рейтинг@Mail.ru