OpenGL: вторичный поток для загрузки ресурсов?

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

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

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

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

Ответ 1

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

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

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

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

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

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

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

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

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

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 могут конвейерно выполнять различные операции.

Ответ 2

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

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

Ответ 3

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