[quote="DimkaM"]
А Rindex всё в бутылку лезит.
Хорошо, что не бутылка лезет в риндекса.
[img]http://zxdemos.ru/oldforum/img/posts/posts_20/11217.jpg[/img]
ZXAAA → PC-ZX Staff, Emmulator's → Unreal+Youtube. И про проблемы синхронизации в эмуляторах.
Страницы Назад 1 … 7 8 9 10 11 … 22 Далее
Чтобы отправить ответ, вы должны войти или зарегистрироваться
[quote="DimkaM"]
А Rindex всё в бутылку лезит.
Хорошо, что не бутылка лезет в риндекса.
[img]http://zxdemos.ru/oldforum/img/posts/posts_20/11217.jpg[/img]
[quote="deathsoft"]
Проблема в том, что там есть только нотификация об окончании буфера, но нету информации о текущей позиции проигрывания. Ну и не известно с какой точностью все это работает. Буферы 1мс поддерживаются только начиная с win10, я у себя проверил, у меня даже на win10 только 10мс буферы (функция выдает, что минимальный размер буфера 10мс).
Так нотификация об окончании есть и сейчас везде. Это нам ничего не дает нового.
И 1мс буфер тоже ничего особо точного не даст.
Ситуацию здорово решит информация о текущей позиции воспроизведения.
[quote="dr.Titus"]
А что делает твой asm_pause()? Что ты делаешь в моменты между двумя опросами видюхи?
Я в эти моменты засыпаю на 1мс.
Вызывает инструкцию процессора pause, (аналог intrinsic функции _mm_pause() https://msdn.microsoft.com/en-us/librar … s.85).aspx)
Sleep(1) переходит в режим ядра, и может выполняться существенно больше чем 1мс. Но у меня и Sleep(n) используется когда делается синхронизация по TSC, там n вычисляется, а остаток докручивается холостым циклом.
static void do_idle()
{
if(conf.SyncMode != SM_TSC)
return;
static unsigned long long last_cpu = rdtsc();
unsigned long long cpu = rdtsc();
if(conf.sleepidle && ((cpu-last_cpu) < temp.ticks_frame))
{
ULONG Delay = ULONG(((temp.ticks_frame - (cpu-last_cpu)) * 1000ULL) / temp.cpufq);
if(Delay > 5)
{
Sleep(Delay-1);
}
}
for (cpu = rdtsc(); (cpu-last_cpu) < temp.ticks_frame; cpu = rdtsc())
{
asm_pause();
}
last_cpu = rdtsc();
}
Отредактировано deathsoft (2016-10-23 20:37:51)
[quote="deathsoft"]
Вызывает инструкцию процессора pause, (аналог intrinsic функции _mm_pause() https://msdn.microsoft.com/en-us/librar … s.85).aspx)
Не стремная ли она? Написано, что работает начиная только с интеловских гипертридингов.
[quote="deathsoft"]
Sleep(1) переходит в режим ядра, и может выполняться существенно больше чем 1мс. Но у меня и Sleep(n) используется когда делается синхронизация по TSC, там n вычисляется, а остаток докручивается холостым циклом.
Может сколько хочешь выполняться, но по факту выполняется примерно 1мс.
У нас все равно виндовс система не реального времени, и если надо где-то ей притормозить, она притормозит.
У меня тоже примерно так и делается. Ближе к концу кадра холостым циком уже сканируется бит VBlank'а.
[quote="dr.Titus"]
Не стремная ли она? Написано, что работает начиная только с интеловских гипертридингов.
Она везде работает, только не везде действие оказывает, эта инструкция кодируется как rep nop, что позволяет коду работать на любых даже самых древних процах типа 386го.
[quote="dr.Titus"]
У нас все равно виндовс система не реального времени, и если надо где-то ей притормозить, она притормозит.
Для этого процессу надо выставить максимальный приоритет, если есть права админа или спец параметр в политиках включен, то можно даже риал тайм приорити класс процессу назначить, тогда общий приоритет у него будет 31 (максимальный) и процесс эмуляции сможет вытеснять даже драйвер мыши и подобные низкоприоритетные драйвера.
Максимальный приоритет это:
SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS); // тут нужна привелегия SE_INC_BASE_PRIORITY_PRIVILEGE
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);Отредактировано deathsoft (2016-10-23 20:44:57)
[quote="deathsoft"]
Она везде работает, только не везде действие оказывает, эта инструкция кодируется как rep nop, что позволяет коду работать на любых даже самых древних процах типа 386го.
Тогда она на старых процах просто тормознет систему жутко, т.к. будет равна холостому циклу.
И еще возникает вопрос - Sleep(n) нам не дает гарантии о выходе из слипа за точно заданное время, мало ли чего системе вздумается.
Но каково время возвращения в наш таск после asm_pause()? Какова частота их переключения? Не может ли там таких же тормозов быть, как при Sleep?
[quote="deathsoft"]
Для этого процессу надо выставить максимальный приоритет, если есть права админа или спец параметр в политиках включен, то можно даже риал тайм приорити класс процессу назначить, тогда общий приоритет у него будет 31 (максимальный) и процесс эмуляции сможет вытеснять даже драйвер мыши и подобные низкоприоритетные драйвера.
Кстати, да) У меня у эмуля прироритет ставится очень высокий. Не realtime, а предыдущий перед ним. Когда ставил realtime, и эмуль зависал, то все системе была крышка, даже мышка не двигалась) Но это правда на однопроцессорном XP.
Хотя, тормознуть могло и при realtime, т.к. часть работы делает видюха (переброска буфера в окно), обработка оконных событий и т.д., а там уж как система решит по времени, так и будет.
[quote="dr.Titus"]
Sleep(n) нам не дает гарантии о выходе из слипа за точно заданное время, мало ли чего системе вздумается.
Именно поэтому слип делается на существенно меньшее время чем нужно, а дальше точная докрутка по rdtsc(), asm_pause() - просто хинт процу, что идет пустой цикл, чтобы он меньше грелся.
[quote="dr.Titus"]
Когда ставил realtime, и эмуль зависал, то все системе была крышка, даже мышка не двигалась) Но это правда на однопроцессорном XP.
Так и должно быть. Программу надо писать так, чтобы она не зависала. Ну и на одном проце лучше риалтайм не ставить.
Еще важно AffinityMask выставить для текущего потока, чтобы он как говно в проруби не болтался по процам, а был привязан к текущему ядру.Отредактировано deathsoft (2016-10-23 20:49:05)
[quote="deathsoft"]
Еще важно AffinityMask выставить для текущего потока, чтобы он как говно в проруби не болтался по процам, а был привязан к текушему ядру.
Не ставил. Ибо был одноядерник.
А что будет, если будет болтаться по ядрам?
[quote="dr.Titus"]
Хотя, тормознуть могло и при realtime, т.к. часть работы делает видюха (переброска буфера в окно), обработка оконных событий и т.д., а там уж как система решит по времени, так и будет.
Это все асинхронно делается, через DMA внутри видеокарты, оно с системой вообще никак не связано, если только системный вызов не синхронный.
В современных виндах, наверное, и не выставишь RealTime приоритет, если ты не под админом?
[quote="dr.Titus"]
А что будет, если будет болтаться по ядрам?
Трата ресурсов впустую на переключение контекстов по разным процам (в обычном случае раз в 15мс, а с timeBeginPeriod(1) каждую 1мс), а самое главное у каждого ядра свой TSC и они между ядрами не синхронизованы, т.е. любая разность двух показаний TSC даст рандом вместо ожидаемого результата.
В унриале на старте делается так:
SetThreadAffinityMask(GetCurrentThread(), 1);Отредактировано deathsoft (2016-10-23 20:53:18)
[quote="deathsoft"]
Это все асинхронно делается, через DMA внутри видеокарты, оно с системой вообще никак не связано, если только системный вызов не синхронный.
По факту тестирования, во всяком случае на одноядернике, самый большой разброс времени - это именно системный рендер всякий и обработка системных событий. У меня на окошке скоростеметр сделан, где разными цветами показано, что на что тратится.
Причем, переброс буфера в окно нельзя сделать асинхронным (во всяком случае под тем директиксом, который был на XP). Только синрхонным. Вызвал функцию, и жди, пока перебросит.
[quote="dr.Titus"]
Только синрхонным. Вызвал функцию, и жди, пока перебросит.
Неправда, можно делать асинхронно.
r = surf2->Blt(0, 0, 0, DDBLT_WAIT | DDBLT_ASYNC | DDBLT_COLORFILL, &Fx);
DDBLT_ASYNC - асинхронный режим.Отредактировано deathsoft (2016-10-23 20:55:37)
[quote="deathsoft"]
Трата ресурсов впустую на переключение контекстов по разным процам (в обычном случае раз в 15мс, а с timeBeginPeriod(1) каждую 1мс), а самое главное у каждого ядра свой TSC и они между ядрами не синхронизованы, т.е. любая разность двух показаний TSC даст рандом вместо ожидаемого результата.
Мне кажется, что система сама должна следить бы за этими делами, в плане неэкономичного болтания процессов и их переключения.
А TSC я не использую напрямую, ибо на современных засыпающих ядрах, он засыпает вместе с ними.
Я использую таймер высокого разрешения, который, как я понимаю, привязывается или же к TSC, либо же к таймеру материнки, но это система уже решает сама.
[quote="deathsoft"]
Неправда, можно делать асинхронно.
Пробовал. Не работало асинхронно.
res = lpPrimarySurf->Blt(&DRect, lpBackSurf, &SRect, NULL, &ddbltfx);
[quote="dr.Titus"]
ибо на современных засыпающих ядрах, он засыпает вместе с ними.
Не засыпает, проверить этом можно спец флагом в cpu id, называется Invariant TSC, есть очень небольшое количество процов, где частота TSC плавает (у меня есть один такой ноутбук с Pentium M).
Может быть у меня интерфейс еще стародревний используется, когда это не поддерживалось)
[quote="deathsoft"]
Не засыпает, проверить этом можно спец флагом в cpu id, называется Invariant TSC, есть очень небольшое количество процов, где частота TSC плавает (у меня есть один такой ноутбук с Pentium M).
Поэтому все равно корректнее использовать систему для таймера высокого разрешения, вполне себя оправдывает.
[quote="dr.Titus"]
Пробовал. Не работало асинхронно.
Ну как же не работало, когда при установке этого флага Blt выходит мгновенно (можно через TSC замерить).
[quote="deathsoft"]
Ну как же не работало, когда при установке этого флага Blt выходит мгновенно (можно через TSC замерить).
Проверял, разумеется. Не выходило.
Опять же повторюсь, что возможно это из-за использования старого интерфейса.
[quote="dr.Titus"]
Поэтому все равно корректнее использовать систему для таймера высокого разрешения, вполне себя оправдывает.
Этот таймер "высокого" разрешения часто сваливается на обычный системный таймер разрешение которого всего 1МГц, а у TSC разрешение 2-3ГГц (что в 2-3 тысячи раз выше).
Именно по этому в унриале есть несколько режимов синхронизации, таймер, видео, аудио.Отредактировано deathsoft (2016-10-23 21:02:00)
[quote="dr.Titus"]
Опять же повторюсь, что возможно это из-за использования старого интерфейса.
Так в унриале такой же старый интерфейс используется.
Вроде бы материнский таймер что-то около 3.5МГц, если я не ошибаюсь.
Может это для режима фулскрин работает асинхронная переброска?
А для окна, когда нужно клиппирование и все такое прочее - не работает?
[quote="dr.Titus"]
Вроде бы материнский таймер что-то около 3.5МГц, если я не ошибаюсь.
1МГц он "The PIT contains a crystal oscillator which emits a signal 1193182 hz"[quote="dr.Titus"]
Может это для режима фулскрин работает асинхронная переброска?
А для окна, когда нужно клиппирование и все такое прочее - не работает?
Всегда асинхронная переброска при этом флаге. Более того, ты даже можешь IDirectDraw7 запросить, унриал то вообще IDirectDraw2 использует.
Для фулскрина Blt вообще не нужен, на фул скрине можно просто в бэкбуфер рисовать и переключать буферы по кругу через Flip.
Надо тогда перепроверить еще раз.
А как определить, закончилась предыдущая переброска или еще нет?
И что будет делать система, если предыдущая не закончилась, а я запросил новую? Поставит в очередь или же откажет?
Страницы Назад 1 … 7 8 9 10 11 … 22 Далее
Чтобы отправить ответ, вы должны войти или зарегистрироваться
ZXAAA → PC-ZX Staff, Emmulator's → Unreal+Youtube. И про проблемы синхронизации в эмуляторах.