Название: Асинхронная загрузка текстур (OpenGL) Отправлено: UnSeen от Октябрь 05, 2011, 13:49 Задача в следующем - в приложении требуется подгружать текстуры в отдельном потоке, чтобы не затормаживать рисование в основном потоке (программа - аналог Google Earth, т.е. огромное количество текстур, но одновременно показывается только небольшая часть)
Нашёл такой же вопрос тут, но без ответа http://www.prog.org.ru/topic_1564_0.html Как это делать в теории - понятно, но будет здорово, если кто-нибудь скинет рабочий пример. Обычно это делается так: во втором потоке создаётся отдельный контекст рендеринга (т.к. нельзя использовать один в двух потоках одновременно) и они объединяются функцией wglShareLists. После чего текстуры, созданные во втором потоке, становятся доступны и в первом. Вот именно с wglShareLists и проблема - контексты почему-то не хотят объединяться, функиция возвращает false :( Текстуры во втором потоке создаются, но в первом они, само собой, не доступны. В первом потоке используется QGLWidget, поставленный в качестве viewport-а на QGraphicsScene Во втором для создания контекста используется QGLPixelBuffer (так как, насколько я понимаю, создать окно вне основного потока нельзя? если что, с Qt работаю впервые)). При создании QGLPixelBuffer в качестве формата указываю GLWidget->format(), чтобы форматы были одинаковые у обоих контекстов. Но wglShareLists не срабатывает :( Что я делаю не так? © :) Наверняка кто-то такое уже делал, ткните в пример, плиз Название: Re: Асинхронная загрузка текстур (OpenGL) Отправлено: Igors от Октябрь 05, 2011, 18:24 Сейчас занимаюсь тоже OpenGL текстурами, но "с др. стороны", поэтому пример не скину. Возможно полезно будет такое соображение:
Сама "загрузка текстуры для OpenGL" производится ф-цией glTexImage2D или аналогичной - в той обертке что Вы пользуете это выглядит как bindTexture метод. После выполнения этой операции исходный имедж не нужен, OpenGL скопировал его куда надо. Поэтому есть смысл все дела OpenGL делать в одной нитке, а "узкое место" (подгрузка имеджей с диска) вынести в отдельную нитку. Название: Re: Асинхронная загрузка текстур (OpenGL) Отправлено: UnSeen от Октябрь 05, 2011, 18:45 Сейчас занимаюсь тоже OpenGL текстурами, но "с др. стороны", поэтому пример не скину. Возможно полезно будет такое соображение: Сама "загрузка текстуры для OpenGL" производится ф-цией glTexImage2D или аналогичной - в той обертке что Вы пользуете это выглядит как bindTexture метод. После выполнения этой операции исходный имедж не нужен, OpenGL скопировал его куда надо. Поэтому есть смысл все дела OpenGL делать в одной нитке, а "узкое место" (подгрузка имеджей с диска) вынести в отдельную нитку. Я сначала тоже собирался этим ограничиться, но оказалось, что время загрузки и раскодирования с диска jpg текстуры сравнимо со временем закачки текстуры в видеопамять (даже если без создания мипмапов). Как-никак текстурка 1024х1024 - это 4 метра данных. Так что этот способ не идеальный, часть глюков останется, и это будет заметно из-за специфики программы: при перемещении карты приходится одновременно подгружать большое количество текстур, которые раньше были не видны. Так что хотелось бы полностью вынести загрузку во второй поток. Чтобы всё честно, красиво и без извращений :) Название: Re: Асинхронная загрузка текстур (OpenGL) Отправлено: Igors от Октябрь 05, 2011, 19:23 Я сначала тоже собирался этим ограничиться, но оказалось, что время загрузки и раскодирования с диска jpg текстуры сравнимо со временем закачки текстуры в видеопамять (даже если без создания мипмапов). Как-никак текстурка 1024х1024 - это 4 метра данных. Так что этот способ не идеальный, часть глюков останется, и это будет заметно из-за специфики программы: при перемещении карты приходится одновременно подгружать большое количество текстур, которые раньше были не видны. У меня немного похожая задача, текстуры побольше (часто 8x8k), зато легче с drag'ом - я могу (и должен) загрузить все до того как началась интерактивщина. Зачем зачем Вы связались с разделяемым контекстом и.т..п ? Ну делайте glTextImage (затратную работу) во вспомогательной нитке (нужно синхронизировать только создание нового ID текстуры), не вижу почему это должно не работать.Название: Re: Асинхронная загрузка текстур (OpenGL) Отправлено: UnSeen от Октябрь 05, 2011, 19:45 У меня немного похожая задача, текстуры побольше (часто 8x8k), зато легче с drag'ом - я могу (и должен) загрузить все до того как началась интерактивщина. Зачем зачем Вы связались с разделяемым контекстом и.т..п ? Ну делайте glTextImage (затратную работу) во вспомогательной нитке (нужно синхронизировать только создание нового ID текстуры), не вижу почему это должно не работать. Тем не менее, не работает :) Нельзя одновременно использовать один и тот же контекст в двух потоках (что вполне объяснимо. как вы себе представляете, например, параллельное выполнение блоков glBegin-glEnd в разных потоках с одним контекстом?))))wglShareLists, похоже, самое удобное и простое решение http://www.gamedev.ru/code/forum/?id=72099 Название: Re: Асинхронная загрузка текстур (OpenGL) Отправлено: Igors от Октябрь 05, 2011, 20:28 Тем не менее, не работает :) Нельзя одновременно использовать один и тот же контекст в двух потоках (что вполне объяснимо. как вы себе представляете, например, параллельное выполнение блоков glBegin-glEnd в разных потоках с одним контекстом?)))) Ссылка интересная. Но я бы проверился прежде чем лезть в дебри с контекстами, тем более это несложно. Создаю текстуру с новым ID в главной нитке, glGenTextures быстрая операция. Заряжаю созданную текстуру в др. нитке - с какого перепугу это не должно работать? Конечно придется ответить/обеспечить что новое ID еще нигде не используется - ну это нормально. Др. словами: нигде ясно не звучит что, мол, все действия в одной нитке игнорируются контекстом созданным в другой.wglShareLists, похоже, самое удобное и простое решение http://www.gamedev.ru/code/forum/?id=72099 Название: Re: Асинхронная загрузка текстур (OpenGL) Отправлено: UnSeen от Октябрь 05, 2011, 21:47 Заряжаю созданную текстуру в др. нитке - с какого перепугу это не должно работать? Конечно придется ответить/обеспечить что новое ID еще нигде не используется - ну это нормально. Др. словами: нигде ясно не звучит что, мол, все действия в одной нитке игнорируются контекстом созданным в другой. Проблема уже в "заряжаю" :) glBindTexture, вызванное из другого потока с тем же контекстом, выдаёт GL_INVALID_OPERATION . Так что увы, всё не так просто Название: Re: Асинхронная загрузка текстур (OpenGL) Отправлено: Igors от Октябрь 05, 2011, 22:28 Проблема уже в "заряжаю" :) glBindTexture, вызванное из другого потока с тем же контекстом, выдаёт GL_INVALID_OPERATION . Так что увы, всё не так просто Ну привет, делать glBindTexture, (текущей) Вас в др. нитке никто не заставлял, речь шла о glTextImage. Название: Re: Асинхронная загрузка текстур (OpenGL) Отправлено: UnSeen от Октябрь 05, 2011, 22:59 И куда же вы будете загружать текстуру, если она не выбрана?
Нашёл, что я делал не так :) Оказывается, создавать и связывать два контекста нужно в одном потоке. А потом уже можно использовать один из контекстов в другом потоке. А я пытался создавать контексты в разных потоках и это не срабатывало. Почему так - хз... Теперь всё работает :) Название: Re: Асинхронная загрузка текстур (OpenGL) Отправлено: xop от Октябрь 10, 2011, 08:23 Делаю примерно так:
1) контекст только один, в основном потоке 2) выделяю заранее буфер для загрузки типа GL_PIXEL_UNPACK_BUFFER, с usage GL_STREAM_DRAW 3) когда надо грузить текстуру в основном потоке делаю glMapBuffer, полученный указатель на область памяти передаю в параллельный поток 4) в параллельном потоке загружаю текстуру в полученную область памяти и кидаю сообщение основному потоку 5) в основном потоке делаю glUnmapBuffer, и потом с этим буфером привязанным к target GL_PIXEL_UNPACK_BUFFER выполняю нужные glTexImage2D, при этом вместо указателя на данные там передается смещение относительно начала буфера Если нужно подробнее - могу кусочки кода накидать. Название: Re: Асинхронная загрузка текстур (OpenGL) Отправлено: Igors от Октябрь 10, 2011, 11:18 xop, рад Вас видеть т.к. привалило много работы с OpenGL и нужны советы знатока.
Общая задача поддерживать 2 и более текстур на 1 объекте со всеми типами и наворотами маппинга. (изначально приложение обходилось 1 текстурой). Сделал так: создаю UV координаты для каждой текстуры и затем использую glTextImage2D и glTetCoordPointer. Это работает, но возникает капитальнейший геморрой: UV seam (шов). Приходится "распиливать" полигоны по шву, с 2 и более текстурами это особенно неприятно. Есть ли лучшее ("модерновое") решение? Примечание: если лучше вынести это в отдельный топик - нет проблем Спасибо Название: Re: Асинхронная загрузка текстур (OpenGL) Отправлено: xop от Октябрь 15, 2011, 17:18 Думаю лучше все-таки новую тему открыть. И заодно более подробно описать задачу, в которой понадобились разные текстурные координаты для разных текстур
|