2

Я хочу выполнить некоторую работу в моем проекте OpenGL ES в параллельных очередях GCD. Это нормально, если создать EAGLContext для каждого потока? Я собираюсь сделать это с таким образом:Можно ли создать EAGLContext для каждого потока?

queue_ = dispatch_queue_create("test.queue", DISPATCH_QUEUE_CONCURRENT); 


    dispatch_async(queue_, ^{ 
    NSMutableDictionary* threadDictionary = [[NSThread currentThread] threadDictionary]; 
    EAGLContext* context = threadDictionary[@"context"]; 
    if (!context) { 
     context = /* creating EAGLContext with sharegroup */; 
     threadDictionary[@"context"] = context; 
    } 

    if ([EAGLContext setCurrentContext:context]) { 
     // rendering 
     [EAGLContext setCurrentContext:nil]; 
    } 

}); 

Если не исправить то, что является лучшей практикой для распараллеливания рендеринга OpenGL?

ответ

1

Это не только хорошо, это только образом, вы можете поделиться OpenGL ресурсов между несколькими потоками. Обратите внимание, что общие ресурсы обычно ограничены ресурсами, которые выделяют память (например, объекты буфера, текстуры, шейдеры). Они не включают объекты, которые просто сохраняют состояние (например, глобальный конечный автомат, объекты Framebuffer или объекты массива вершин). Но если вы планируете модифицировать данные, которые вы используете для рендеринга, я бы настоятельно советовал этому.

Всякий раз, когда GL имеет команду в конвейере, которая еще не завершена, любая попытка изменить ресурс, используемый этой командой, будет блокироваться до тех пор, пока команда не завершится. Лучшим решением будет двойной буфер ресурсов, копия, которую вы используете для рендеринга, и отдельную копию, которую вы используете для обновления. Когда вы закончите обновление, в следующий раз, когда поток рисования будет использовать этот ресурс, замените его буферами, используемыми для обновления и рисования. Это уменьшит время, в течение которого драйвер должен синхронизировать рабочие потоки с потоком чертежа.

Теперь, если вы предлагаете здесь, что хотите нарисовать из нескольких потоков, вам следует пересмотреть свою стратегию. OpenGL обычно не выигрывает от выпуска команд рисования из нескольких потоков, он просто создает кошмар синхронизации. Многопоточность полезна в основном для управления VSYNC на нескольких окнах (возможно, это не то, с чем вы когда-либо столкнетесь в ES) или потоковых данных ресурсов в фоновом режиме.

+0

Я собираюсь использовать фон только для загрузки текстуры. Но я хочу сделать это в параллельной очереди (для загрузки нескольких текстур в один момент). Это нормально для этого случая? Есть ли у EAGLContext некоторые издержки памяти? Могу ли я создать EAGLContexts столько, сколько захочу? –

+1

Последний вопрос - конкретный вариант реализации, но я сомневаюсь, что вы сможете создать достаточно контекстов, чтобы нанести какой-либо лимит в любом разумно написанном программном обеспечении. Что касается двух других, если вы создаете общие контексты, то они будут использовать одну и ту же память для текстур. И если все, что вы делаете, загружает ** новые ** текстуры в другие потоки, то это большой случай использования для общих контекстов в нескольких потоках. Если вы пытались обновить данные в текстуре, которая уже использовалась для создания чего-то, тогда вы создадите источник неявной синхронизации драйверов, которая может повредить производительность. –

+2

Практически говоря, если многократные текстуры загружаются с одного и того же устройства (то есть одна и та же флешка, один и тот же жесткий диск и т. Д.), Вы, вероятно, не увидите большой выгоды от одновременного загрузки нескольких фоновых потоков, поскольку в конечном итоге они собираются сериализуется при выполнении ввода/вывода на одном устройстве. Если вы делаете какую-то интенсивную постобработку процессора, * возможно *, будет какая-то польза, но я был бы удивлен, если бы несколько параллельных фоновых нагрузок превзошли последовательную загрузку нескольких текстур на одном фоновом потоке. – ipmcc

Смежные вопросы