SNVampyre блог
GameDev.ru
/ GameDev.ru / Страницы / SNVampyre блог / Статьи / Блок-схема основных классов рендера SH-engine 2

Блок-схема основных классов рендера SH-engine 2

Автор: Николай Сосновиков

Блок-схема разрабатываемого рендера в движке.

Мне очень понравились диаграмки, которые делают некоторые ребята, решил сделать свою.
На схеме изображена цель того, что я сейчас делаю.
Рисовать может только класс рендера из своего потока с контекстом OpenGL, а другие потоки могут отсылать ему команды на отрисовку. То есть что-то типа многопоточного рендеринга в DX11. В голове итоговая система уже видна, осталось только её реализовать. На данном этапе сделал только часть с текстурами, включая стриминг. Любую текстуру из любого материала можно будет указать на стриминг, и скорее всего можно будет указывать анимации из пользовательского кода.
В движке будет 6 основных потоков и 6 основных подсистем:
1) shRoot
- интерфейс
- пользовательский код
2) shRenderWindow + shRenderHardware
- окно, ввод
- буферизованный OpenGL-рендер
3) shMaterialManager
- инициализация материалов, текстур и параметров
- стриминг текстур
- сборка программ из шейдеров
4) shSceneManager
- загрузка  мешей
- построение списков на рендер
5) shDynamics
6) shSoundManager

4 января 2012

Категории: схема

Комментарии:

Страницы: 1 2 Следующая

slava_mibМодераторwww4 янв. 201221:55#1
Блок-схема красивая 8-)

А вот разбиение на потоки кажется немного страным... Мне одному?

Скажем, тот же самый стримиинг, несомненно, напрашивается в отдельный поток. Но почему только стримминг текстур? А почему там нет звуков, скажем, или физ. данных или (частей?) уровней ?

Ну и по остальным пунктам тоже направшиваются вопросы...

SNVampyreПостоялецwww4 янв. 201222:11#2
slava_mib
> Скажем, тот же самый стримиинг, несомненно, напрашивается в отдельный поток. Но
> почему только стримминг текстур? А почему там нет звуков, скажем, или физ.
> данных или (частей?) уровней ?
Написано же:
В движке будет 6 основных потоков и 6 основных подсистем:
1) shRoot
- интерфейс
- пользовательский код
2) shRenderWindow + shRenderHardware
- окно, ввод
- буферизованный OpenGL-рендер
3) shMaterialManager
- инициализация материалов, текстур и параметров
- стриминг текстур
- сборка программ из шейдеров
4) shSceneManager
- загрузка  мешей
- построение списков на рендер
5) shDynamics
6) shSoundManager
slava_mibМодераторwww4 янв. 201223:40#3
Так я прочитал - вот и говорю, у меня лично вызывает некоторое удивление такое разбиение, потому как кажется оно не слишком оптимальным.
ReanПостоялецwww5 янв. 20127:41#4
А почему именно 6 потоков? Получается если я запущу приложение на 1ядерном процессоре - получу постоянные переключения между потоками, а если на 12ядерном - то половина ядер будет простаивать?
По моему если уж делать то как-то вот так: http://software.intel.com/ru-ru/articles/designing-the-framework-… -game-engine/
SNVampyreПостоялецwww5 янв. 20128:14#5
Rean
> А почему именно 6 потоков? Получается если я запущу приложение на 1ядерном
> процессоре - получу постоянные переключения между потоками, а если на 12ядерном
> - то половина ядер будет простаивать?
6 потоков потому, что получилось 6 основных подсистем. Физика может быть сама по себе с любым количеством потоков, а пользователь может создать потоки свои, например для рассчётов ИИ, так что процессор загрузить всегда можно.
Что касается однопроцессорных компов, то да, будет постоянно переключать. Правда я ни разу не видел одноядерных компов с поддержкой OpenGL 3.3.

slava_mib
> у меня лично вызывает некоторое удивление такое разбиение, потому как кажется
> оно не слишком оптимальным.
Каждый поток работает со своим набором данных, по-моему всё как раз достаточно оптимально и в традициях инкапсуляции.

ReanПостоялецwww5 янв. 201219:36#6
SNVampyre
> 6 потоков потому, что получилось 6 основных подсистем. Физика может быть сама
> по себе с любым количеством потоков, а пользователь может создать потоки свои,
> например для рассчётов ИИ, так что процессор загрузить всегда можно.
> Что касается однопроцессорных компов, то да, будет постоянно переключать.
> Правда я ни разу не видел одноядерных компов с поддержкой OpenGL 3.3.
Да дело то не в том, есть ли сейчас современные одноядерные компы или нет, а в том, что изначально подход к многопоточности не масштабируемый получается, трудно будет эффективно нагрузить произвольное кол-во ядер в конечной системе. Если я правильно понимаю - сейчас планируется заведение 6 потоков, которые в начале кадра будут выполнять строго определенные функции, а потом остаток процессорного времени будет отдано ИИ и физике? Т.е. изначально планируется некая урезанная очередь задач для потоков, почему бы не абстрагироваться еще немного: заводим потоки по числу ядер в системе, в начале кадра формируем общую очередь задач относительно мелких задач, в которую каждый поток будет стучаться брать задачку и исполнять ее, как только всю очередь отработаем - отрисовываем кадр.
SNVampyreПостоялецwww5 янв. 201220:23#7
Rean
> Да дело то не в том, есть ли сейчас современные одноядерные компы или нет, а в
> том, что изначально подход к многопоточности не масштабируемый получается,
> трудно будет эффективно нагрузить произвольное кол-во ядер в конечной системе.
У меня такой задачи не стоит: загрузить любой процессор на 100% только основными подсистемами. Есть задача разгрузить поток рендера (который распараллелить нельзя) и сделать буферизованный вывод. Всё равно даже если полностью готовые и сортированные данные на рендер подавать, этот поток займёт ядро на 100%, а остальные подсистемы едва ли займут целиком второе ядро, и это при том, что сейчас везде 4-хядерные процессоры.
Обычно в играх создаются десятки потоков, без оглядки на число ядер в процессоре, и это никого почему-то не заботит.

> Если я правильно понимаю - сейчас планируется заведение 6 потоков, которые в
> начале кадра будут выполнять строго определенные функции, а потом остаток
> процессорного времени будет отдано ИИ и физике?
Нет никакой привязки к кадрам и никакой синхронизации. Если у подсистемы нет текущих задач, то она в основном спит. Я старался так распределить задачи, чтобы все подсистемы были загружены и во время загрузки, и во время цикла рендера.

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

Правка: 5 янв. 2012 20:25

StiXУчастникwww5 янв. 201221:03#8
slava_mib
> А вот разбиение на потоки кажется немного страным... Мне одному?
Поддерживаю. Не масштабируемое решение
SNVampyreПостоялецwww5 янв. 201221:22#9
StiX
Не очень понимаю о каком масштабировании идёт речь. Вот есть поток рендеринга, который занимает ядро на 100% и является главным тормозом. Есть ещё какое-то количество потоков, которые, дай Бог, загрузят ещё одно ядро. Что ещё масштабировать здесь?
StiXУчастникwww6 янв. 201217:58#10
А остальные ядра будут простаивать. Когда у тебя поток рендеринга упрется в 100% утилизации ядра, то это значит, что ты ЦПУ лимитед, если разгрузить по другим ядрам, то можно сабмитить больше геометри, круче эффекты и т.д. Тоесть стремиться как можно больше перенести на гпу, так как мощи в нем много и грех её не использовать ;) Ну и такая архитектура скоро устареет. Вычислительные способности ядра растут мало, растет количество этих самых ядер и требования к качеству игры (особенно к картинке). Потому через некоторое время из-за не масштабируемости тебе приедется почти полностью переписать движок...
SNVampyreПостоялецwww6 янв. 201218:22#11
StiX
> Когда у тебя поток рендеринга упрется в 100% утилизации ядра
А он по-любому в неё упрётся, так как рендер не может быть многопоточным.

> А остальные ядра будут простаивать
И не в моих силах исправить эту ситуацию, по крайней мере, не рендером их можно загружать.

> если разгрузить по другим ядрам
Я должен тебя разочаровать, но распределить рендер на несколько ядер процессора невозможно. Есть попытка сделать подобное в DX11, но там по сути та же система, что у меня - всё равно есть основной поток, который собирает команды и отправляет их драйверу.

> больше геометри, круче эффекты и т.д
Это от процессора вообще никак не зависит, по крайней мере у меня.

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

> Ну и такая архитектура скоро устареет.
Пока не переделают работу драйвера, такая архитектура будет наиболее перспективной.

> Вычислительные способности ядра растут мало, растет количество этих самых ядер
> и требования к качеству игры (особенно к картинке). Потому через некоторое
> время из-за не масштабируемости тебе приедется почти полностью переписать движок...
Скорее всего драйверописателям придётся придумать что-нибудь новенькое, а пока приходится корчиться и выдавливать из себя что-то неудобное, но зато быстрое.

Правка: 6 янв. 2012 18:27

slava_mibМодераторwww6 янв. 201220:48#12
>поток
>инкапсуляции.
Тоже несколько спорно 8-)

>рендер не может быть многопоточным.
Не знаю как под ОГЛ, но под ДХ - может. Так же ДХ умеет самостоятельно делать стримминг текстур в отдельном потоке(ах), который сам менеджит.

Вообще, последние годы вроде бы много говорят о тасковой многопоточности (т.е. когда каждый поток просто выполняет небольшие таски, которые ему ставятся, и не важно какие они там). Такой подход позволяет без проблем масштабировать приложение под любое количество ядер/потоков. Правда, я в этом особо не шарю, потому больше сказать особо нечего ))) Просто прими к сведению.

>Есть ещё какое-то количество потоков, которые, дай Бог, загрузят ещё одно ядро.
Да совсем не обязательно. Например, стрииминг данных (а точнее их декомпрессия) может загрузить поток/ядро сразу на несколько секунд, ну или как минимум десятых долей секунды вообще легко. Соответственно, если в очереди стоят десятки текстур, то время запуска приложения будет обратно попорциональна количеству потоков, занимающихся декомпрессией даных. Если движок загружает, скажем, текстуры из JPG-формата и перегоняет их в сжатые DDS/BC-форматы, то ситуация усугубится ещё больше.

Та же самая физика, скажем, легко может сожрать отдельный поток/ядро и, даже не один. Хэвок, вроде как, умеет. Буллет обещали что будет. Остальные - я не в курсе просто.

Звук вот вряд ли. НО если качество очень высокое + звуковые доролжки длинные (держать их все в кэше невозможно) - тоже нагрузка немалая.

В общем, загрузить ядра, как правило, не проблема ))) Проблема загрузить их так, что бы это всё работать не перестало )))

SNVampyreПостоялецwww6 янв. 201221:01#13
slava_mib
> Например, стрииминг данных (а точнее их декомпрессия) может загрузить
> поток/ядро сразу на несколько секунд, ну или как минимум десятых долей секунды
> вообще легко. Соответственно, если в очереди стоят десятки текстур, то время
> запуска приложения будет обратно попорциональна количеству потоков,
> занимающихся декомпрессией даных. Если движок загружает, скажем, текстуры из
> JPG-формата и перегоняет их в сжатые DDS/BC-форматы, то ситуация усугубится ещё
> больше.
Я не собираюсь грузить какие-либо текстуры кроме DDS и TGA.
Зачем игре грузить неготовые к рендеру форматы? Это глупость.
А если вдруг выяснится, что поток стриминга текстур будет тяжёлым, то без проблем его распараллелить. Практика показывает, что можно стримить порядка 1000 текстур 2048х2048 в секунду, этого достаточно, чтобы все текстуры в игре сделать анимированными.

> Та же самая физика, скажем, легко может сожрать отдельный поток/ядро и, даже не
> один. Хэвок, вроде как, умеет. Буллет обещали что будет. Остальные - я не в
> курсе просто.
У меня используется буллет и я уже несколько раз написал, что им можно загрузить сколько угодно ядер, только при чём тут рендер?

> В общем, загрузить ядра, как правило, не проблема ))) Проблема загрузить их
> так, что бы это всё работать не перестало )))
Вот именно. Проблема - разгрузить поток рендера, который всегда однопоточный, и многопоточным быть не может в принципе. Он всегда будет грузить один поток на 100%, все игры подтверждают это правило, сколько бы там потоков не было.

> Вообще, последние годы вроде бы много говорят о тасковой многопоточности (т.е.
> когда каждый поток просто выполняет небольшие таски, которые ему ставятся, и не
> важно какие они там).
Но это не применимо к работе с GAPI.

slava_mib
> Не знаю как под ОГЛ, но под ДХ - может

Не может. Команды отправляются из одного потока даже в "многопоточном" DX11, инфа 100%. Это даже в рекламных картинках указано.
Может они там какие-то шипко оптимизированные конечно, но драйвер от этого никуда не исчезнет.

Правка: 6 янв. 2012 21:20

SNVampyreПостоялецwww6 янв. 201221:24#14
Direct3D 10 only allows graphics commands to be issued from a single thread (there is a multithreaded mode, but Microsoft explicitly warns against using it due to its poor performance). In an API such as Direct3D, issuing graphics commands involves a fair amount of CPU overhead. Given the trend towards increasing the number of cores on a processor rather than the performance of a single core, it is desirable to efficiently spread this work among multiple threads.

Direct3D 11 adds the ability to create display lists from multiple threads and execute them from the main rendering thread. In addition, the Device (which creates resources) has been separated from the Context (which issues graphics commands). This enables creating resources asynchronously. Deferred Contexts are used to create display lists and the Immediate Context issues graphics commands to the GPU, including the execution of display lists created on Deferred Contexts.


Никакой принципиальной разницы с моей системой нет, просто мне чуть больше писать.

Страницы: 1 2 Следующая

/ Форум / SNVampyre блог

2001—2012 © GameDev.ru — Разработка игр