Многопользовательский рендеринг SDL2 вызывает мерцание экрана: синхронизация или проблема обрезки?C++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Многопользовательский рендеринг SDL2 вызывает мерцание экрана: синхронизация или проблема обрезки?

Сообщение Anonymous »

Я реализую многопоточный 3D -рендеринг или файлы OBJ с использованием SDL2 в C ++. Экран делится на горизонтальные плитки, каждая из которых обрабатывается отдельным потоком. В то время как модель правильно отображается в однопользованном режиме, включение многопоточности вызывает сильное мерцание. Я подозреваю, что проблема синхронизации или неверная логика треугольника. Синхронизация использует две переменные условия и вектор с готовыми потоками. Также каждый поток записывает расчетный цвет непосредственно в Window_surface-> Pixels, но все функции SDL (SDL_LOCKSURFACE, SDL_UNLOCKSURFACE, SDL_UPDATEWINDOWSURFACE) вызываются в основном потоке.//class fields for sync
std::mutex render_mutex;
std::condition_variable render_cv;
std::condition_variable main_cv;

std::atomic threads_completed{ 0 };
std::vector thread_ready;
std::atomic stop_requested{ false };

void Renderer::RenderThread(int index, int y_start, int y_end) {
while (true) {

std::unique_lock lock(render_mutex);

render_cv.wait(lock, [&] {
return stop_requested || !thread_ready[index];
});

if (stop_requested) break;

lock.unlock();

//clearing the scene here

//rendering the scene here

lock.lock();
thread_ready[index] = true;
threads_completed++;
if (threads_completed == MAX_THREADS) {
main_cv.notify_one();
}
}
}

void Renderer::Render() {

if (!is_running) return;

SDL_LockSurface(window_surface);

{
std::lock_guard lock(render_mutex);
threads_completed = 0;
std::fill(thread_ready.begin(), thread_ready.end(), false);
}

render_cv.notify_all();

{
std::unique_lock lock(render_mutex);
main_cv.wait(lock, [&] {
return threads_completed == MAX_THREADS;
});
}

SDL_UnlockSurface(window_surface);
SDL_UpdateWindowSurface(window.get());
}
< /code>
Вот треугольная обрезка, по сути, я преобразую координаты треугольника из локального пространства в пространство для экрана, рассчитываю его ограничивающую коробку, и после этого я либо обрезаю, чтобы соответствовать области рендеринга, либо полностью пропустить. < /p>
int min_x = (int)std::round(std::min({ v0_transformed.x, v1_transformed.x, v2_transformed.x }));
min_x = std::max(0, min_x);
int min_y = (int)std::round(std::min({ v0_transformed.y, v1_transformed.y, v2_transformed.y }));
min_y = std::max(0, min_y);
int max_x = (int)std::round(std::max({ v0_transformed.x, v1_transformed.x, v2_transformed.x }));
max_x = std::min(WIDTH, max_x);
int max_y = (int)std::round(std::max({ v0_transformed.y, v1_transformed.y, v2_transformed.y }));
max_y = std::min(HEIGHT, max_y);

if (min_y > y_end - 1 || max_y < y_start) continue;
min_y = std::max(min_y, y_start);
max_y = std::min(max_y, y_end);
< /code>
Вот как это выглядит.
с многопоточным чтением
без многопоточности < /p>

Подробнее здесь: https://stackoverflow.com/questions/794 ... -or-clippi
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»