OpenGL: вторичный поток для загрузки ресурсов? - PullRequest
10 голосов
/ 14 ноября 2011

Работая с C и Win32, я хотел бы знать, как реализовать дополнительный поток OpenGL для загрузки ресурсов (текстур и VBO).

Из того, что я обнаружил, это должно быть сделано с помощью wglShareLists (),но я не уверен, как настроить вторичный поток:

Нужен ли мне новый контекст устройства или только новый контекст рендеринга?

Какие функции wgl мне нужно вызывать?

Ответы [ 3 ]

7 голосов
/ 14 ноября 2011

Вам не нужен новый контекст, потому что вы можете повторно использовать тот же контекст устройства, что и первый. Кстати, вы можете указать другой контекст устройства, но в зависимости от вашей платформы вы должны позаботиться об этом (в Windows контексты устройства должны иметь одинаковый формат пикселей), в противном случае вы не сможете разделить объекты между двумя контекстами

Создайте оба контекста в главном потоке, второй делится с первым. Затем создайте первый ток в главном потоке, а второй ток во вторичном потоке. Обратите внимание, что вы можете поделиться с любым контекстом рендеринга: все контексты совместного использования «видят» один и тот же объект по его имени, в действительности они разделяют пространство имен объекта . Два разных пространства имен объекта (то есть два не разделяемых контекста) могут определять один и тот же объект (то есть имя объекта текстуры - 1), но одно и то же имя фактически указывает на другой объект в зависимости от текущего контекста.

Объекты, созданные вторичным потоком, видны одновременно и последовательно. Однако не все объекты могут быть общими для всех контекстов. Помните, что иногда случается, что драйвер поддерживает неожиданные объекты, а иногда случается, что драйвер не поддерживает правильно ожидаемый объект.

OpenGL становится объектно-ориентированным языком. Вы можете увидеть определенный шаблон для создания объектов:

  • Создать имя ( GenTextures , GenBuffers )
  • Определить объект ( BindTexture , BindBuffer )
  • Существование объекта ( IsTexture , IsShader , IsFramebuffer )
  • Удалить имя (и объект)

(Обратите внимание, что объект, созданный с помощью подпрограмм Gen существует только тогда, когда они связаны)

Классы объектов могут быть

  • Отображение списков
  • Текстурные объекты
  • Буферные объекты
  • Шейдерные объекты и программные объекты
  • Объекты Renderbuffer
  • Объекты кадрового буфера
  • Объекты запросов
  • Синхронизация объектов
  • Преобразование объектов обратной связи

Я бы предложил использовать тест «во время выполнения», например:

private bool TestSharingObject(RenderContext rContextShare)
{
    uint texture = 0;

    // rContextShader is a context sharing with this RenderCOntext

    this.MakeCurrent(true);

    if (Caps.TextureObject.Supported == true) {
        // Generate texture name
        Gl.GenTextures(1, out texture);
        // Ensure existing texture object
        Gl.BindTexture(Gl.TEXTURE_2D, texture);
        Gl.BindTexture(Gl.TEXTURE_2D, 0);
        // Self test
        if (Gl.IsTexture(texture) == false)
            throw new NotSupportedException();
    }

    // Make current sharing context
    rContextShare.MakeCurrent(true);

    return ((texture != 0) && (Gl.IsTexture(texture) == true));
}

Другим предложением может быть выполнение операций с дополнительными потоками, которые требуют значительных ресурсов процессора и не влияют непосредственно на буферы окон системы рисования. Хорошим примером может служить компиляция шейдеров, так как компиляция выполняется на стороне процессора; помните также, что драйвер может асинхронизировать ваши операции и что реализации OpenGL могут передавать различные операции по конвейеру.

1 голос
/ 14 ноября 2011

Загружайте ресурсы так, как вам нужно, во вторичный поток, а затем передайте право владения ими первичному для вызовов GL.

Совместное использование "списков" между контекстами GL должно работать. Выполнение всех ваших вызовов GL в основном потоке работает : :)

0 голосов
/ 06 декабря 2012

Работает !, только если wglShareLists выполняется главным потоком для всего рабочего потока.Используя карту сообщений, передайте ссылку на контекст рендеринга и заставьте основной поток создать контекст рендеринга, используйте wglShareLists только для основного потока.Затем вызовите wglMakeCurrent в рабочем потоке с контекстом рендеринга, созданным основным потоком.Обязательно, чтобы wglShareLists вызывался до того, как какая-либо операция gl была выполнена в контексте рендеринга.Это связано с требованием к параметру hglrc2 (контекст рендеринга OpenGL для совместного использования списков отображения с hglrc1), чтобы он не содержал никаких существующих списков отображения при вызове wglShareLists.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...