Cheb's Game Engine

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

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

Re: Cheb's Game Engine

Сообщение Cheb » 06.03.2021 17:07:39

После длительного простоя разморозить проект. Блин, я позабыл всё!

Долгие копания в погоне за ужосныя крахом приводят - угадайте, куда? К глобальной переменной, которую упустил, переселяя состояние Чеперси в единую глобальную запись с методами инициализации и очистки

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

По ходу, нашёл трагическую историю о том, что чужие движки - зло, вдохновившую меня пинками разбудить разработку собственного.
https://www.youtube.com/watch?v=HPkhw2VR0RU
Вкратце: чувак годами пилил проект мечты, наплодил громадье неписей и транспортных средств, завязанных на симуляцию физики... И не смог перейти с четвёртой юньки на пятую: автоконвертер превращал все его оттюнингованные модели и скрипты в г-но. Потребовалось бы всё переделывать и тюнинговать с нуля! Он остался на четвёртой. И в итоге упёрся в её 32-битность: проект перестал собираться, ископаемая юнька падает с "пшёлнанетбольшепамяти".
И - всё. Песец проекту мечты, в который вложены годы труда.
Его машинки: https://www.youtube.com/watch?v=F5azGpy ... 2&index=23
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 994
Зарегистрирован: 06.06.2005 15:54:34

Re: Cheb's Game Engine

Сообщение Sharfik » 06.03.2021 18:12:24

Оффтоп:
:lol: Прям история моей жизни. Стал писать на Delphi, перешел на Turbo Delphi, ее кинули в мусорку, а у меня она сказала я твою модную винду не знаю и работать тут не буду. Делал как то видюшку с высокой степенью проработки света в Autodesk Navisworks(64), через пару дней она сказала - "пшёлнанетбольшепамяти". Кодек у нее был 32х битный))) :lol: :lol: :lol:
Запили прогу мечты, тестил к ней плагин и забросил из-за багов движка - через два года проще заново написать плагин, чем вспоминать где и что. Программирование на разных платформах это классная вещь - учит, что нельзя упираться в одно. Ничто не вечно, и надо соизмерять затраты и результат.
PS: Обычно я эту тему не читаю, ибо смысл через три слова понимаю написанного, но тут...)))
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 763
Зарегистрирован: 20.07.2013 01:04:30

Re: Cheb's Game Engine

Сообщение runewalsh » 06.03.2021 21:47:03

Глобальные переменные — абсолютное (в т. ч. в прямом смысле — по адресу в памяти процесса) зло и не нужны. Делая что-то глобальной переменной, ты предполагаешь, что оно может существовать только в одном экземпляре, а это по-хорошему неверно даже для таких фундаментальных вещей, как лог, менеджер памяти или файловая система, не говоря уже о состоянии движка. Например, если скрипт аллоцирует-освобождает память как сумасшедший, ты можешь захотеть выдать ему отдельный менеджер памяти, чтобы он не фрагментировал общий. Аналогично с логом отдельной задачи в рамках процесса, или тупо со вторым окном на том же движке с совершенно другим содержимым, то есть с отдельным состоянием движка: у этого окна может быть другой пиксельный формат и вообще GAPI.

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

Вот я буквально вчера делал видосик со способами движения камеры: Мгн — мгновенно-дёргано, Л+Э — линейно+экспоненциально, КР — по сплайну Катмулла-Рома между прошлым и будущим. Если бы камера была глобальной, это внезапно стало бы сложной задачей, а так мы легко и непринуждённо делаем вместо одной камеры три.
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 578
Зарегистрирован: 27.04.2010 00:15:25

Re: Cheb's Game Engine

Сообщение Alex2013 » 07.03.2021 01:31:31

Рад что это не злобный "корова-вирус" ! Поздравляю с преодолением очередных трудностей. :idea:

Cheb писал(а):Опциональная поддержка виар - это хорошо, но до той стадии стабильности, что оней можно будет думать - ещё семь вёрст раком.

...и все лесом ! (О да теперь я на собственной шкуре немного лучше начинаю понимать "насколько широка река из дерьма" под названием "гам-диз-айн"... ) Но я тут решил наоборот "от ВиАр" медленно но верно "двигаться к движку"( ну или к чему-то на него "отдаленно похожему", бо задачи все же немного другие )
Зы
Кстати можешь проконсультировать по вопросу быстрой перезагрузки текстур в OpenGL ?
"В муках творчества" написал вот такую крякозябру :
Код: Выделить всё
function  CapTextureBMP: GLuint;
var
   rs : Integer;
  bmp: TBitmap;
Const
   texID : GLuint=0;
   OW : GLuint=0;
   OH : GLuint=0;
begin
try
bmp:=TBitmap.Create;
if RSBS Then rs:=FRender else RS:=0;

// Как можно по названию догадаться это  захват экрана в битмап
CaptureForm.CreateSnapshotPlusWH(bmp,R_W,R_H,unit6.FHandle,RS);

if (Tbmp = nil) or (( OW <> R_W) or (OH <>R_H)) then begin
// Почему неюзаю напрямую ? А черт его знает почему, но иначе не работает .
if (Tbmp = nil) then  begin
  Tbmp:=TBitmap.Create;
  Tbmp.PixelFormat:=pf24bit;
   end else glDeleteBuffers(1,@texID);

  Tbmp.SetSize(R_W,R_H);

// тут пошла "плясать деревня" ( в  OpenGL я почти по прежнему "темный как штаны пожарника".  ) 
//  Первый проход создает пустую текстуру
glEnable(GL_TEXTURE_2D);
  glGenTextures( 1, @texID );
  glBindTexture( GL_TEXTURE_2D, texID );
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
                    tbmp.Width, tbmp.Height,
                    0, GL_RGB, GL_UNSIGNED_BYTE, nil
                    );

glDisable(GL_TEXTURE_2D);

end
else begin

// А дальше я ее перезагружаю ... "Нео в ужосе!"  :)))
Tbmp.Canvas.Draw(0, 0, bmp);
glEnable(GL_TEXTURE_2D);
glBindTexture( GL_TEXTURE_2D, texID );
glTexSubImage2D ( GL_TEXTURE_2D, 0, 0, 0,
  tbmp.Width, tbmp.Height,
       GL_BGR
        , GL_UNSIGNED_BYTE, Tbmp.RawImage.Data );

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glDisable(GL_TEXTURE_2D);
end;
  finally
    Result := texID;
    bmp.Free;
    OW:=R_W; oh:=R_H;
  end;
end;

Вообщем худо бедно работает ... Но тормоз еще тот .
Отсюда вопрос: можно ли грузить текстуры напрямую из "HDC" (то бишь "дисплейного контекста" )?
А еще не будет ли быстрее если для создания "виртуального экран" вместо текстуры юзать "цветные вершины"?
Alex2013
долгожитель
 
Сообщения: 2938
Зарегистрирован: 03.04.2013 11:59:44

Re: Cheb's Game Engine

Сообщение Seenkao » 07.03.2021 12:02:34

Alex2013, то есть, тебя не смущает, что ты делаешь скриншот и потом перекидываешь в текстуру?
Вопрос в том, зачем ты это делаешь?
Seenkao
энтузиаст
 
Сообщения: 502
Зарегистрирован: 01.04.2020 03:37:12

Re: Cheb's Game Engine

Сообщение Alex2013 » 07.03.2021 13:04:02

Seenkao писал(а):Alex2013, то есть, тебя не смущает, что ты делаешь скриншот и потом перекидываешь в текстуру?
Вопрос в том, зачем ты это делаешь?

Есть такая штука "Виртуальный Десктоп" (посылке несколько скринов из двух общеизвестных программ ) называется, и это приблуда которая так или иначе востребована постоянно (Кроме того это хорошая учебная задача с "потенциально полезным выхлопом" ) ...
Alex2013
долгожитель
 
Сообщения: 2938
Зарегистрирован: 03.04.2013 11:59:44

Re: Cheb's Game Engine

Сообщение Cheb » 07.03.2021 15:47:19

Alex2013 писал(а): можно ли грузить текстуры напрямую из "HDC" (то бишь "дисплейного контекста" )?

Никогда этим не задавался, т.к. оно платформеннозависимое.
Если DC позволяет получить указатель на сырые пикселы - то, наверно, возможно.
Скорей всего, жопа (и глубокая) в подборе формата пиксела: у DC он аппаратно зависимый, а ГЛ требует конкретного, который нравится ей.
Я бы копал в сторону захвата из DC в DIB и заливки в текстуру прямо из неё - но это всё равно тормозная операция.

Если надо скриншот всего десктопа - я сам быстрых способов ленился изучать, у себя в движке наскоро слабал через еретическую glReadPixels. Ибо запись в png всё равно во много раз толще.

Если надо рендерить в текстуру и быстро - тогда *только* FBO, альтернативы нет.

Если надо заливать в текстуру из всяких странных источников - в помощь glPixelStore, особливо GL_UNPACK_ALIGNMENT . У гля он по умолчанию 1, а у глеса - сюрприииз! - 4. Сколько столов лбом пробито...

Алсо, glEnable(GL_TEXTURE_2D); - атавизм, который современные драйверы терпят ради совместимости, но при миграции на более продвинутое г-но мамонта типа GL ES 2, начинают плеваться GL_INVALID_ENUM

Про цветные вершины совсем не понял :(

runewalsh писал(а):Частичным исключением могут быть кэши@пулы и прочее, что реально осмысленно в единственном экземпляре в рамках процесса.

Это компромисс. Реализовать моё громадье с поддержкой многопоточности - просто не хватит жизни. Поэтому пришлось сказать себе "хватит" и самую главную часть движка - логику/физику оставить строго single-threaded, а лишние ядра процессора - только для рендера и для фоновых загрузок всяких.

В теории, если я всё правильно сделаю, оно по любому упрётся в память и плоскопараллельно, сколько там ядер.

Соответственно, весь механизм БД, включая диспетчер памяти - однопоточный, без расходов на блокировки.

Для повышения производительности предназначены две фичи, призванные сделать просчёт физики кеш-фриндли:
1. Просчёт физики каждым объектом на N тиков вперёд, зато редко: образно говоря, моб представляет собой не капсулу, а квантовое состояние из 8 капсул просчитанных в будущее. Любые операции чтения - включая те, что сами для будущего - интерполируют между ними. Если незапланированное внешнее - воздействие - моба будят, схлопывая его квантовое состояние в единственную капсулу и добавляя в очередь просчёта физики. Но когда его не будили - а таковых 99% случаев - моб спит, а движение идёт. ИЧСХ, записи в память при этом нет, а чтение - только когда кто-то ещё прётся через то же место, что тоже не всегда.
2. Ускоренные поля. Что-то типа нищебродской ECS. Уже используется обходчиками графа для индексов, ускоряя их. Все ускоренные поля определённого индекса диспетчер памяти хранит в отдельном массиве (индекс вычисляется простыми побитовыми операциями над Self инстанса). Если, скажем, инстансы - 128 байт, а упакованные поля - 4 байта, получаем 32-кратную экономию на загрязнении кеша. А сброс индексов - вообще бесплатный, массивы просто освобождаются, не надо елозить по содержимому. В старых версиях сброс индексов засирал кеш страшно: ведь надо было обойти все объекты графа и записать ноль во все инстансы. А это 64 байта на каждый.

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

Re: Cheb's Game Engine

Сообщение Alex2013 » 07.03.2021 16:16:30

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

Кроссплатформенность моим ВиАр поделкам пока "не светит" ( поддержка OpenVr в линуксе как-бы есть, но на практике ее "как-бы и нет " (хотя исходная демка "вроде как КП" но есть глубокие сомнения в ее целесообразности ) )
Cheb писал(а):Я бы копал в сторону захвата из DC в DIB и заливки в текстуру прямо из неё - но это всё равно тормозная операция.

Типа пытался но того "Каринка не той системы" пиксель формат соблюдён но что-то не то и не так.

ПроцеДура захвата ...
SВS нужен для "стереофикации" старых игр просмотра стереофильмов и стереофоток .
Код: Выделить всё

procedure TCaptureForm.CreateSnapshotPlusWH (var B:TBitmap;W,H:Integer;WindowHD:HWND;Sbs:Integer);

  var
      wnd:HWND;
      dc:HDC;
      r:TRect;
      X,WS,HS:Longint;
  begin
  If B=Nil then exit;

      wnd :=WindowHD;
      if wnd = 0 then
          begin
           dc := GetDC(0);
        Ws:=Screen.Width;
        Hs:=Screen.Height;
          end
         else
          begin
          dc := GetWindowDC(wnd);
           GetWindowRect(wnd,r);
           Ws:=r.Right-r.Left;
           Hs:=r.Bottom-r.Top;
          end;

      if SBS in [1,2] then ws:=ws div 2;
      if SBS in [0,1] then X:=0;
      if SBS = 2 then x:=ws;
      b.SetSize(W,H);

  StretchBlt(B.Canvas.Handle,0,0,B.Width,B.Height,DC,x,0,WS,HS,SRCCOPY);
  ReleaseDC(wnd,dc);
  end;


Вот что тут может быть с картинкой такого что она не грузится в текстуры напрямую ?
Зы
А понял ты про DIBits... Хм это я еще не пробовал.
Alex2013
долгожитель
 
Сообщения: 2938
Зарегистрирован: 03.04.2013 11:59:44

Re: Cheb's Game Engine

Сообщение Cheb » 07.03.2021 17:46:34

Кстати, в теории никто же не мешает вызывать glTexSubImage2d построчно - т.е. строчками из одного пиксела. И делать их за кадр сколько влезет. Тогда если мощА не тянет - будет падать частота кадров текстуры, но не частота кадров рендера.

Alex2013 писал(а):пиксель формат соблюдён но что-то не то и не так.

Это - в сторону glPixelStore, которая описывает формат для glTexImage. Вроде, она должна разные трюки уметь. Типа порядка компонент, выравнивания и прочего.

З.Ы. Главные косяки выполол, падать почти перестало. Нашёл сложносочинённый баг типа "ошибка при попытке вывести сообщение об ошибке" - и хватит на сегодня. До следующего воскресенья.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 994
Зарегистрирован: 06.06.2005 15:54:34

Re: Cheb's Game Engine

Сообщение Seenkao » 07.03.2021 18:52:40

Alex2013 писал(а):Есть такая штука "Виртуальный Десктоп" (посылке несколько скринов из двух общеизвестных программ ) называется, и это приблуда которая так или иначе востребована постоянно (Кроме того это хорошая учебная задача с "потенциально полезным выхлопом" ) ...

То есть, ты выводишь изображение на экран, потом с этого экрана скринишь и выводишь на очки?

Объясни, что ты делаешь. Потому что то, что ты пишешь - это не понятно! Выше я написал, как я это понял. )))
Seenkao
энтузиаст
 
Сообщения: 502
Зарегистрирован: 01.04.2020 03:37:12

Re: Cheb's Game Engine

Сообщение runewalsh » 07.03.2021 18:54:51

Cheb писал(а):GL_UNPACK_ALIGNMENT . У гля он по умолчанию 1

Он всегда был 4. У тебя в исходниках затесалась glPixelStorei(Gl_UNPACK_ALIGNMENT, 1), про которую ты успешно забыл, 100%.

Cheb писал(а):с поддержкой многопоточности

Так я вообще не про многопоточность, описанные сценарии применимы и к полностью однопоточной программе.

Cheb писал(а):В старых версиях сброс индексов засирал кеш страшно: ведь надо было обойти все объекты графа и записать ноль во все инстансы. А это 64 байта на каждый.

Я вот недавно ковырялся с SSE-интринсиками в Free Pascal более обстоятельно. Если вкратце, захотелось ту же текстуру с шумом Перлина для эффектов генерировать при первом запуске, чтобы не таскать с собой 8 Мб-дуру (128×128×128×RGBA8), но это занимало секунд 7, что ставило крест на идее. Но она отлично поддалась оптимизации, связанной с генерацией пачками. Если мы генерируем текстуру не попиксельно, а целыми пачками со startPixel по endPixel, то, помимо тривиального распараллеливания, появляется возможность использовать её пространственную когерентность:
— 99% времени мы идём по X при неизменных Y и Z, поэтому всё, что связано с Y и Z, достаточно пересчитывать в начале строки пикселей
— Параметры, связанные с целочисленными кубиками шумовой функции, достаточно пересчитывать в момент пересечения границ таких кубиков.

Все эти оптимизации ускорили генерацию в 25 раз (до 250 мс), из них 5 раз (до 1,3 с) — тупо распараллеливание, и ещё 5 раз — ленивый пересчёт параметров. Что уже более-менее вменяемо. И если распараллелить можно и попиксельную генерацию, то ленивый пересчёт параметров возможен только в рамках генерации пачками.

Векторные SSE-инструкции — просто приятный бонус ко всему этому, они не ускоряют процесс (т. к. узким местом по-прежнему является сама шумовая функция), но нужны хотя бы ради красоты: если мы генерируем текстуру пачками, то для дальнейшей работы с ними (того же составления фрактального шума из октав) полезны сложение 2 пачек, умножение и т. п., которые, в свою очередь, расписываются как
while (осталось ≥4 элементов) складывать 4-векторами;
while (осталось ≥1 элемента) складывать поэлементно.

Так вот. Тогда же я узнал про non-temporal stores, которые местами ускоряют запись выходной пачки в каждой такой операции на 10–50% за счёт уполовинивания использования пропускной способности памяти — кэш-линия не подтягивается в кэш перед записью.

Они ведь буквально предназначены для решения этой проблемы, нет?
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 578
Зарегистрирован: 27.04.2010 00:15:25

Re: Cheb's Game Engine

Сообщение Alex2013 » 07.03.2021 23:00:31

Seenkao писал(а):То есть, ты выводишь изображение на экран, потом с этого экрана скринишь и выводишь на очки?

Объясни, что ты делаешь. Потому что то, что ты пишешь - это не понятно! Выше я написал, как я это понял. )))

Давай переберемся в другую тему, а то местный хозяин может справедливо возмутится ...
Например сюда :arrow: viewtopic.php?p=161873#p161873 :idea:
Alex2013
долгожитель
 
Сообщения: 2938
Зарегистрирован: 03.04.2013 11:59:44

Re: Cheb's Game Engine

Сообщение Cheb » 08.03.2021 05:19:50

runewalsh писал(а):Все эти оптимизации ускорили генерацию в 25 раз (до 250 мс), из них 5 раз (до 1,3 с) — тупо распараллеливание, и ещё 5 раз — ленивый пересчёт параметров.

Фигасе :o
Вот. Когда удаётся сделать лениво - это страшная сила!

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

Ну, и ускоренные поля нужны - сюрприз! - в том числе для расслоения мира в лагокомпенсаторе. Чтобы метод объекта "а есть у тебя клон в моём слое" не трогал сам инстанс. Потому что обращение к ускоренному полю - чистая арифметика над Self (метод не может быть виртуальным, естественно).
P.S. То есть, всё те же рандомные поскакушки - но уже по пулу памяти, раз в 50 меньшему, чем память инстансов.

О! Ты меня натолкнул на идею оптимизации на отдалённое будущее!
Периодически (раз в ~15 минут, когда возле игрока нет монстров) выполнять дефрагментацию пула инстансов. Для этого понадобится как-то научить Чеперси иметь две копии диспетчера памяти - и выполняется процесс, аналогичный сохранению игры в поток, посредством обходчика. Только вместо сериализации инстансов идёт клонирование во второй диспетчер памяти. По завершении обработки графа первый диспетчер памяти убивается, второй подставляется на его место, правятся ссылки извне на корень графа - и опа, все инстансы расположены в памяти согласно их месту в графе, весь мусор и утечки волшебным образом исчезли.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 994
Зарегистрирован: 06.06.2005 15:54:34

Re: Cheb's Game Engine

Сообщение runewalsh » 08.03.2021 07:27:50

Чёрт, вот я слишком долго и косвенно подводил к основной мысли, так что она вовсе потерялась за пачками и всем таким.

Я говорю, пока я разбирался с SSE, просёк, что там есть non-temporal stores / loads (операции с NT в мнемонике: MOVNTDQ и т. д.), специально предназначенные для того, чтобы что-то записать в память (или даже прочитать) мимо кэша, и в моём случае они действительно существенно ускоряют процесс, когда он ограничен пропускной способностью памяти. И это не x86-специфичная штука, похожие вещи, преследующие ту же цель, есть в других архитектурах, том же ARM. Не хочешь положиться на них?
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 578
Зарегистрирован: 27.04.2010 00:15:25

Re: Cheb's Game Engine

Сообщение Cheb » 08.03.2021 14:32:40

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

Хотя... При обходе ещё чтение самого инстанса идёт. Туда NT чтения пришлись бы в кассу - но это на далёкое будущее: столько процедур пришлось бы апгрейдить! Включая обходы массивов, внутри которых тоже могут быть ссылки на инстансы. И все операции чтения для сериализации.
С другой стороны, в штатном режиме все не-managed поля без промежутков между ними у меня уже сериализуются, как бинарный блоб.
Хммм...
Ставлю задачу на после доведения перетряха до завершения.
Хотя, нет. Отбой.
Объясняю: чтение - многими вызовами разных процедур, как поля в инстансе расбросаны. Каждый вызов ничего не знает о других, иначе был бы комбинаторный взрыв. Внутри может оказаться лирическое отступление на следующий инстанс, а потом - снова чтения полей.
Кеширование чтения в данном случае - нужно.

Добавлено спустя 2 часа 43 минуты 57 секунд:
Кстати, в 3.2 FillChar под x86_64 использует movnti! :D

Код: Выделить всё
Procedure FillChar(var x;count:SizeInt;value:byte);assembler;nostackframe;
  asm
{ win64: rcx dest, rdx count, r8b value
  linux: rdi dest, rsi count, rdx value }
{$ifndef win64}
    mov    %rdx, %r8
    mov    %rsi, %rdx
    mov    %rdi, %rcx
{$endif win64}

    cmp    $8, %rdx
    jl     .Ltiny

// TODO: movz?q and movs?q are not accepted by FPC asmreader, it needs fixing.
// `movzbl' instead is accepted and generates correct code with internal assembler,
// but breaks targets using external GAS (Mantis #19188).
// So use a different instruction for now.

    { expand byte value  }
    andq   $0xff, %r8
{
    movzbq %r8b, %r8
}
    mov    $0x0101010101010101,%r9
    imul   %r9, %r8

    test   $7, %cl
    je     .Laligned

    { align dest to 8 bytes }
    test   $1, %cl
    je     .L2
    movb   %r8b, (%rcx)
    add    $1, %rcx
    sub    $1, %rdx
.L2:
    test   $2, %cl
    je     .L4
    movw   %r8w, (%rcx)
    add    $2, %rcx
    sub    $2, %rdx
.L4:
    test   $4, %cl
    je     .Laligned
    movl   %r8d, (%rcx)
    add    $4, %rcx
    sub    $4, %rdx

.Laligned:
    mov    %rdx, %rax
    and    $0x3f, %rdx
    shr    $6, %rax
    jne    .Lmore64

.Lless64:
    mov    %rdx, %rax
    and    $7, %rdx
    shr    $3, %rax
    je     .Ltiny

    .balign 16
.Lloop8:                               { max. 8 iterations }
    mov    %r8, (%rcx)
    add    $8, %rcx
    dec    %rax
    jne    .Lloop8
.Ltiny:
    test   %rdx, %rdx
    jle    .Lquit
.Lloop1:
    movb   %r8b, (%rcx)
    inc    %rcx
    dec    %rdx
    jnz    .Lloop1
.Lquit:
    retq

.Lmore64:
    cmp    $0x2000,%rax
    jae    .Lloop64nti

    .balign 16
.Lloop64:
    add    $64, %rcx
    mov    %r8, -64(%rcx)
    mov    %r8, -56(%rcx)
    mov    %r8, -48(%rcx)
    mov    %r8, -40(%rcx)
    dec    %rax
    mov    %r8, -32(%rcx)
    mov    %r8, -24(%rcx)
    mov    %r8, -16(%rcx)
    mov    %r8, -8(%rcx)
    jne    .Lloop64
    jmp    .Lless64

    .balign 16
.Lloop64nti:
    add    $64, %rcx
    movnti %r8, -64(%rcx)
    movnti %r8, -56(%rcx)
    movnti %r8, -48(%rcx)
    movnti %r8, -40(%rcx)
    dec    %rax
    movnti %r8, -32(%rcx)
    movnti %r8, -24(%rcx)
    movnti %r8, -16(%rcx)
    movnti %r8, -8(%rcx)
    jnz    .Lloop64nti
    mfence
    jmp    .Lless64
  end;


Добавлено спустя 40 минут 50 секунд:
З.Ы. Надо запилить собственную ZeroMemory с преферансом и блудницами. Чтобы для объёмов более 4килобайт освобожджало, потом снова выделяло диапазон страниц виртуальной памяти в серёдке, а реально чистило только голову и хвост.
Конская экономия же: винда гарантирует, что заново закоммиченая страница очищена нулями, причём, выделяет под неё физическую память только при первом обращении. Ни кэш не страдает, ни шина не грузится. Хоть гигабайт чисти.
Представляете, настолько подобная FillChar ускорила бы работу с массивами большого размера? :D
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 994
Зарегистрирован: 06.06.2005 15:54:34

Пред.След.

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

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

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

Рейтинг@Mail.ru