CG & C++ blog
57 subscribers
13 photos
2 files
129 links
Краткий обзор публикаций, презентаций, докладов по графике и C++
Download Telegram
В CMake есть проблема с зависимостями между проектом с динамически загружаемой библиотекой (DLL) и проектом, который эту DLL использует.
При изменении только CPP файла в DLL проекте, перестраивается только один проект, а зависящие от него скрипты, например копирование DLL, не срабатывают и остальные проекты продолжат использовать старую DLL.

Решение есть, хоть и не самое удобное:
* код создает пустой CPP файл при компиляции "DllProject".

set( DllProject.trigger "DllProject.trigger.cpp" CACHE INTERNAL "" FORCE )
add_custom_command( TARGET "DllProject" POST_BUILD COMMAND ${CMAKE_COMMAND} -E touch "${DllProject.trigger}" )

* добавляем СPP файл в проект, который использует DLL

add_dependencies( "ExeProject" "DllProject" )
target_sources( "ExeProject" PRIVATE "${DllProject.trigger}" )
set_property( SOURCE "${DllProject.trigger}" PROPERTY GENERATED 1 )

Теперь при компиляции "DllProject" будет принудительно компилироваться "ExeProject" и запустятся все связаные с ним скрипты сборки.
Так как меняется только один CPP файл, то скорость сборки замедляется незначительно.
#cmake #snippets
Authoring Efficient Shaders for Optimal Mobile Performance
1..8 - описание дебагера и профайлера под Mali GPU и офлайн профайлера шейдеров.
9..16 - как разработчики игр используют тулзы от ARM для оптимизации.
17..19 - детали Valhall архитектуры
20.. - пример оптимизации шейдера
#mali #gpu_opt
Doom 2016. Комбинация light probes и screen space reflections приводит к таким двойным отражениям, когда light probe находится в стороне от источника освещения.
#cg #SSR
Cyberpunk 2077. Разница между screen space reflections и трассировкой лучей. Для оптимизации SSR применяется везде, где возможно и только за пределами экрана включается RT. Результат сильно различается.
#raytracing #SSR #cg
Screen space reflections неправильно обрабатывают двойное отражение, так как отражение зависит от того, под каким углом приходит луч. То же самое относится и к кэшированию освещения при трассировке.
#cg #raytracing #SSR #blog
Какая должна быть многопоточность в ОС
Сейчас ОС управляет потоками, у кого выше приоритет, тот получает больше времени ядра ЦП. ОС может остановить поток в любой момент и запустить другой поток на этом ядре, может перекинуть поток на другое ядро.
Переключение между потоками очень дорогое (более 1мс), что не позволяет выделить по одному потоку на задачу, а несколько параллельно запущенных приложений могут начать конкуренцию за ЦП с большими потерями на переключение потоков.

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

Проблема решается заменой потоков на систему тасков в ОС, но это потребует переделать или отказаться от контекста потока.

Дальше можно оптимизировать доступ к памяти - делать загрузку из ОЗУ в кэш до запуска таска, чтобы сам таск выполнялся максимально быстро, например для модели типа ECS/DOD, где доступ к данным полностью предсказуем.
#threading #blog
Подборка интервью с Jim Keller

Jim Keller: Moore's Law, Microprocessors, and First Principles
3:43 - Граф зависимостей в ЦП.
12:08 - Предсказание ветвлений.
22:41 - каждые 5 лет архитектура ЦП переделывается с нуля.

Jim Keller: The Future of Computing, AI, Life, and Consciousness
7:33 - Javascript
11:40 - RISC vs CISC
17:09 - Intel vs ARM
37:18 - Модульный дизайн ЦП позволил упростить тестирование, прям как в софте.
49:50 - Специализированное железо для машинного обучения.

Ian Interviews: Jim Keller, Silicon Wizard
19:44 - Arm vs x86 vs RISC-V
1:19:48 - Intel vs AMD, Intel vs Apple
#cpu #hw
Кадр из NSight GPUTrace.
#gpu_sync #nvidia
Особенности шедулера в NVidia

1. Работает 2 очереди, зеленое - пиксельный шейдер, оранжевое - асинхроный компьют шейдер. На NVidia когда активна графическая очередь, на асинхронную компьют очередь выделяется не более 30% варпов.

2. По какой-то причине графическая очередь вытесняет компьют очередь.

3. Заканчивается рендер пасс и начинается обновление юниформ для следующего рендер пасса. Небольшой всплеск похож на рендеринг до фрагментного шейдера, который ждет обновление юниформ.
Барьер никак не затрагивает компьют очередь, асинхронный компьют как раз и нужен чтобы заполнять такие пустоты, но запуск шейдеров не происходит. Как и в начале (1) шедулер раскидывает графику по всем варпам и только потом добавляет к ним асинхронный компьют.

4. Начинаются короткие рендер пассы, разделенные барьерами. При этом на компьют выделяется не более 30% варпов, даже когда часть варпов простаивает (светло-сервый).

5. При более долгом простое (полная остановка графической очереди), компьют очередь занимает более 30%.

В итоге обновление юниформ буфера между рендер пассами может вызвать простой ГП на 0.3мс и даже асинхронные очереди не заполняют простаивающие варпы.
Более правильный способ - обновлять юниформы один раз в начале кадра.
#gpu_sync #nvidia
Advanced API Performance: Async Compute and Overlap
Статья от NVidia, рассказывают как правильно использовать async compute, как профилировать.
#gpu_sync #nvidia
Advanced Shading Techniques with Pixel Local Storage
Примеры использования внутренней памяти тайла (tile/pixel local storage).
Поддерживается на OpenGLES с Mali GPU, а так же на Metal с Apple GPU.
На Adreno используется другое расширение, только для сложного блендинга.
Поддержка TLS/PLS на Vulkan добавленна только в новых версиях API и только в новых девайсах из-за невозможности обновления графических драйверов.
#cg #gl #vk #OIT #mali
(video) CPU design effects - Jakub Beránek
Детально рассказывается про предсказание ветвлений, из интересного - в GCC подсказка __builtin_expect игнорируется ЦП.
41.53 - пример, где denorm float работает в 2 раза медленее.
51:56 - false sharing, как происходит синхронизация кэшей
#cpp #cpu_opt #intel_cpu
Ошибка в системе сборки, которая сразу обнаружилась через pragma detect_mismatch

Есть два проекта: основной и компилятор ресурсов. Компилятор ресурсов может собираться в другой конфигурации для ускорения компиляции ресурсов.
После рефакторинга пути для бинарников совпали и получилось так:
* сборка основного проекта - движок.
* сборка компилятора ресурсов, в результате чего менялись либы движка.
* сборка приложения используя либы движка и динамически подключаемый компилятор ресурсов.
* линковка приложения завершается с ошибкой, так как макросы не совпадают.

#ifdef MACRO
# pragma detect_mismatch( "MACRO", "1" )
#else
# pragma detect_mismatch( "MACRO", "0" )
endif
При этом во всем основном проекте макрос установлен в 1 и я долго не мог понять откуда приходит 0.
Без pragma detect_mismatch найти ошибку было бы еще сложнее.
#cpp #blog
Создание World of Tanks Blitz на базе собственного движка DAVA
Как происходит переход из OOP/сценеграфа в ECS/DOD.
И продолжение: Blitz Engine & Battle Prime: ECS и сетевой код
#cpp #ecs #dod #rus
Зачем нужен безразмерный массив юниформ в шейдере
В шейдере можно не указывать размер массива ресурсов (юниформ), но в Vulkan обязательно указывать количество дескрипторово в VkPipelineLayout.
Получается, что безразмерный массив в шейдере никак не избавляет от создания нескольких PSO под разные размеры массива.
В чем же преимущество:
1. Не нужно компилировать несколько шейдеров и хранить несколько бинарников.
2. На мобильных девайсах количество ресурсов сильно ограниченно, поэтому нельзя захардкодить массив на 1000 элементов.

Также, по документации Vulkan, нельзя оставлять дескрипторы без ресурсов, это может привести к крэшу, так как в некоторых случаях происходит неявный доступ к ресурсам, который пользователь никак не контролирует.
Фича nullDescriptor позволяет обойти эту проблему и использовать один большой массив, но может повлиять на производительность.

Новое расширение buffer_device_address дает большую гибкость - можно сделать storage buffer с динамическим массивом uint64_t/uvec2, что не требует разных VkPipelineLayout, но пока это расширение поддерживается только на десктопах и топовых мобилках.
#vk #blog
Как мы отказались от JPEG, JSON, TCP и ускорили ВКонтакте в два раза
То что новые форматы лучше и так понятно, а вот отказ от TCP в пользу UDP уже интереснее.
Рассказывают как работает сеть, ограничение скорости провайдером и тд.
#web #backend #rus
https://www.gdcvault.com/free/gdc-22/
В открытом доступе появились доклады с GDC 2022
#news
UDP vs TCP
Пост в блоге, о разнице между UDP и TCP для мультиплеерных игр.

Virtual Connection over UDP
Reliability and Congestion Avoidance over UDP
Как сделать свой аналог TCP поверх UDP. Это позволяет использовать только UDP для создания надежного соединения для критичных данных и ненадежного для часто обновляемых данных.
#cpp #backend
Размер кэшлинии и страницы памяти

Для x86/x64 архитектуры:
* кэшлиния: 64 байта
* страница: 4Кб
Можно увеличить до 4Мб если активировать large pages

Для ARMv7 архитектуры:
* кэшлиния: 64 байта
* страницы: 4Кб, 64Кб, 1Мб

Для ARMv8 архитектуры:
* кэшлиния: 64 байта
* страницы: кратные 4Кб, 16Кб, 64Кб в зависимости от ЦП.
источник

Для Mac M1 (ARMv8):
* кэшлиния: 128 байт
* страница: 16Кб

Зачем нужно знать размер кэш линии и так понятно (DOD, lock-free, false sharing), а вот размер страницы памяти нужен не так часто.
В некоторых рекомендациях по оптимизации говорят, что копирование между страницами памяти работает быстрее.
Еще есть нюансы по работе встроенного аллокатора в C++, он выделяет страницу памяти и разбивает ее на мелкие блоки, при этом аллокация страницы памяти намного медленее, чем поиск свободного блока.
#blog