LWJGL, Clojure, один поток для команд OpenGL

Короткий вопрос:

Учитывая модель параллелизма Clojure, как мне убедиться, что все функции LWJGL OpenGL Update вызываются из одного и того же потока?

Длинный вопрос

После долгой и славной битвы Использование lwjgl в Leiningen/Clojure теперь у меня есть LWJGL + Leiningen + Clojure работают вместе.

Однако, согласно документации LWJGL, похоже, что клиентские команды OpenGL имеют локальное состояние потока, и если я вызываю команды OpenGL из разных потоков, могут произойти Bad Things (TM).

Таким образом, мой вопрос: как правильно в Clojure настроить что-то вроде потоков Swing (но я не могу использовать потоки Swing/должен настроить свои собственные), чтобы:

(1) существует один основной поток, отвечающий за все вызовы OpenGL

(2) другие потоки взаимодействуют с этим основным потоком для координации вызовов OpenGL.

Мой фон

Я знаком с потоками в C/C++. Я знаком с моделью агента/атома/ссылки Clojure. Однако я не знаком с "ручным" параллелизмом/поточностью в Clojure.

Спасибо!


person user1383359    schedule 12.05.2012    source источник


Ответы (1)


Обычный способ, которым я бы спроектировал это, состоял бы в том, чтобы иметь один поток, отвечающий за весь рендеринг. Делая это, вы избегаете необходимости, чтобы другие потоки «выдавали вызовы OpenGL».

Конечно, вам по-прежнему нужен способ передачи информации потоку рендеринга, но с этим можно справиться с помощью стандартных методов параллелизма Clojure. Например, если ваше мировое состояние неизменно, вы можете просто использовать атом для обновления состояния, а поток рендеринга просто выполняет рендеринг, используя последнее мировое состояние, хранящееся в атоме:

  (def world-state (atom (initial-world-state)))

  ;; in rendering thread
  .....
  (loop []
    (render-world @world-state) ; all OpenGL calls happen in this function!!
    (other-stuff)
    (if (still-running) (recur)))

  ;; in other thread responsible for updating world
  (loop []
    (swap! world-state update-world-function)
    (other-stuff)
    (sleep-if-needed)
    (if (still-running) (recur)))
person mikera    schedule 12.05.2012
comment
В (других вещах) я должен вызывать (1) Thread.sleep или (2) использовать Java.util.Timer [они работают в одном потоке?], чтобы поддерживать рендеринг со скоростью 60 кадров в секунду? - person user1383359; 12.05.2012
comment
Я думаю, что в LWJGL есть специальный инструмент для этого: Diaplay.sync(). См.: ninjacave.com/lwjglbasics4. Некоторый хороший пример кода по этой ссылке тоже. - person mikera; 12.05.2012
comment
Именно то, что я искал. Спасибо. Немного, что я бы нашел это, прочитав документацию LWJGL. :-) - person user1383359; 12.05.2012