Skip to content

Структура #21

@MikhailPasechnik

Description

@MikhailPasechnik

Пошаговая работа программы:

  1. Парсинг файла сцены в линкед листы в структуре 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

  2. Инициализация SDL
    https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/src/main.c#L15-L24

  3. Старт программы
    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
    (их можно сделать несколько, но имена функций должны быть уникальными).
    Как видно по аргументам, мы будем туда передавать все, что нужно для рендера.

  4. Инициализация SDL_Renderer это структура нужна будет потом, для вывода SDL_Texture на экран (в них мы будем записывать результат рендера)

  5. Загружаем наши линкед листы с объектами в бафферы
    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

  6. Далее происходит первый рендер, этот же метод будет вызываться каждый раз, когда нужно пересчитать рендер.
    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

  7. Далее вызывается функция 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

  8. Далее вызывается функция render, ее задача, запустить кернель на пикселях окна
    https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/src/renderer.c#L74

  9. Далее уже знакомыми методами для бафферов мы получаем информацию, которую для нас записал кернель
    https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/src/app.c#L49-L57

  10. Собственно все, далее запускается Event Loop, который в зависимости от ивентов, что-то меняет в структуре t_app и вызывает при необходимости app_render
    https://github.com/MikhailPasechnik/RTv1/blob/91f8c0cfe29f9c14f09824aa56c5a1e7519d2867/src/app.c#L96

  11. Структуры данных в 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

  12. Фактический рендер происходит в кернели
    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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions