-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Пошаговая работа программы:
-
Парсинг файла сцены в линкед листы в структуре t_app
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/include/rt.h#L119-L121
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/src/read_scene.c#L65 -
Инициализация SDL
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/src/main.c#L15-L24 -
Старт программы
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/src/app.c#L60
3.1 Инициализация OpenCL, поиск девайса для исполнения кода (GPU или CPU). создание контекста, туторил чтобы было понятен общий концепт OpenCL
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/src/ocl/ocl_init.c#L33
3.2 Инициализация структуры t_renderer, она держит в себе программу OpenCL, которую мы будем потом запускать на каждом пикселе. Программу нужно скомпилировать из .cl файлов, для этого написаны удобные функции
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/src/ocl/ocl_program.c#L16
Далее создается очередь, в которую мы будем отправлять команды для запуска нашей программы
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/src/renderer.c#L45
И в конце создается кернель, который мы будем запускать, по сути, после компиляции программы OpenCL мы можем получить "ссылки" на функции помеченные __kernel аттрибутом
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/res/ocl/k_render.cl#L5-L14
это наша входная точка в OpenCL программу, которую мы скомпилили
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/src/renderer.c#L48
(их можно сделать несколько, но имена функций должны быть уникальными).
Как видно по аргументам, мы будем туда передавать все, что нужно для рендера. -
Инициализация SDL_Renderer это структура нужна будет потом, для вывода SDL_Texture на экран (в них мы будем записывать результат рендера)
-
Загружаем наши линкед листы с объектами в бафферы
https://github.com/MikhailPasechnik/RTv1/blob/93194ff13adac3e27081dcfaf77d2a3d739b6781/src/sync.c#L22
https://github.com/MikhailPasechnik/RTv1/blob/93194ff13adac3e27081dcfaf77d2a3d739b6781/src/sync.c#L50
Баффер это структура которая держит в себе массив на хостe (С программа) и указатель на память на девайсе (OpenCL) которая содержит этот массив.
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/include/rt.h#L69-L75
Далее мы будем использовать функции push/pull/free/create суть которых в передаче памяти туда-сюда ее создание и удаление.
Важно заметить, что мы сразу проставляем в наш кернель аргументы, в которые передаем указатели на память на девайсе из бафферов. Делаем это один раз.
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/src/sync.c#L46-L47
К примеру тут мы устанавливаем аргумент для ссылки на массив объектов, по сути, при запуске кернеля, который мы создали выше, туда придет эта ссылка
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/res/ocl/k_render.cl#L5-L14 -
Далее происходит первый рендер, этот же метод будет вызываться каждый раз, когда нужно пересчитать рендер.
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/src/app.c#L33
Первое что происходит, это выбор текстурного баффера, который мы будем отображать в окне,
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/src/app.c#L35-L44
текстурный баффер, это тот-же баффер, но вместо обычного массива на хосту у нас SDL_Texture, остальное все тоже самое что и с просто баффером
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/include/rt.h#L77-L84 -
Далее вызывается функция app_pre_render
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/src/app.c#L15
ее задача в том, чтобы подготовить все данные для рендера, бафферы
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/src/app_utils.c#L38
в которые будет писать кернель, аргументы камеры и опции, это происходит, только в случае изменения размера окна и флагов *_changed.
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/src/app.c#L22-L29 -
Далее вызывается функция render, ее задача, запустить кернель на пикселях окна
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/src/renderer.c#L74 -
Далее уже знакомыми методами для бафферов мы получаем информацию, которую для нас записал кернель
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/src/app.c#L49-L57 -
Собственно все, далее запускается Event Loop, который в зависимости от ивентов, что-то меняет в структуре t_app и вызывает при необходимости app_render
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/src/app.c#L96 -
Структуры данных в obj.h определены сразу для хоста и девайса, с помощью макроса. Про тонкости компиляции расскажу отдельно
https://github.com/MikhailPasechnik/RTv1/blob/master/include/obj.h#L91
Важно заметить, что для всех типов объектов используется одна и та-же структура, для облегчения передачи данных на девайс, в эту структуру можно смело добавлять нужные поля.
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/include/obj.h#L91-L100
Но важно чтобы типы были из OpenCL
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/include/obj.h#L26-L31
И определены через typedef в obj.h и в rt.hcl
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/res/ocl/rt.hcl#L8-L14 -
Фактический рендер происходит в кернели
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/res/ocl/k_render.cl#L5
важно, что он запускается для каждого пикселя, номер (y*x) которого мы получаем вот так
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/res/ocl/k_render.cl#L29
дальше происходит всем знакомый трейсинг и запись в аутпуты, полученной информации
https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/res/ocl/k_render.cl#L70-L73