Войти
ПрограммированиеФорумГрафика

OpenGL, VAO и тормоза

Страницы: 1 2 3 4 5 Следующая »
#0
9:08, 14 сен. 2020

Итак, я рисую линии в 2D: (X1,Y1)-(X2,Y2). Сделал 1 VAO на все линии; в нем 3 VBO – для цвета, шаблона и масштаба. Тестирую на 20 тыс. линий. При панорамировании изображение отстает от позиции курсора, при его остановке – догоняет. Субъективно по скорости также как при использовании glBegin/glEnd. Измерял время отрисовки в 2-х вариантах: время полного цикла и время непосредственного вывода.

Замер времени полного цикла отрисовки делал так:

  QueryPerformanceFrequency(FClockRate);
  QueryPerformanceCounter(FStartDrawTime);

  wglMakeCurrent(FDC, FRC);
  glClearColor(0.0, 0.0, 0.0, 0.0);
  glClear(GL_COLOR_BUFFER_BIT);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity;
  glScalef(FScale, FScale, 1.0);
  glTranslatef(FPanX, FPanY, 0.0);

  glBindVertexArray(FLines.FVao);
  glDrawArrays(GL_LINES, 0, FLines.FBuffersItemsCount);
  glBindVertexArray(0);

  SwapBuffers(FDC);
  wglMakeCurrent(0, 0);

  QueryPerformanceCounter(FEndDrawTime);
  FTimeDraw:= (FEndDrawTime - FStartDrawTime) / FClockRate;

Замер времени непосредственно отрисовки делал так:

  wglMakeCurrent(FDC, FRC);
  glClearColor(0.0, 0.0, 0.0, 0.0);
  glClear(GL_COLOR_BUFFER_BIT);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity;
  glScalef(FScale, FScale, 1.0);
  glTranslatef(FPanX, FPanY, 0.0);

  QueryPerformanceFrequency(FClockRate);
  QueryPerformanceCounter(FStartDrawTime);

  glBindVertexArray(FLines.FVao);
  glDrawArrays(GL_LINES, 0, FLines.FBuffersItemsCount);
  glBindVertexArray(0);

  QueryPerformanceCounter(FEndDrawTime);
  FTimeDraw:= (FEndDrawTime - FStartDrawTime) / FClockRate;

  SwapBuffers(FDC);
  wglMakeCurrent(0, 0);
Макс. время полного цикла отрисовки = 37 мс. Макс. время непосредственно отрисовки = 0,14 мс! Отключал шейдер - картина не меняется. Т.е. тормозит где-то вне непосредственно отрисовки. Прошу помощи, как это ускорить? Спасибо.


#1
9:51, 14 сен. 2020

а зачем ты в каждом рендере кадра делаешь активным контекст, а в конце деактивируешь? это ж тебе и может создавать такие тормоза, достаточно один раз сделать активным контекст и все

пс. glClearColor достаточно один раз вызвать, чтоб указать каким цветом ты хочешь очищать буфер цвета

#2
(Правка: 11:13) 11:02, 14 сен. 2020

zombihello
> а зачем ты в каждом рендере кадра делаешь активным контекст, а в конце
> деактивируешь? это ж тебе и может создавать такие тормоза, достаточно один раз
> сделать активным контекст и все
Нет, активация контекста никак не дает тормоза, хоть каждый drawcall можно активировать.

greencad
Попробуй замерить glClear(GL_COLOR_BUFFER_BIT);
Но практически в твоем случае выполнение отрисовки идет в момент вызова SwapBuffers(FDC);

Каждая из команд glClear, glDrawArrays загружает конвейер команд видеокарты. Когда он переполняется начинает работать сама видеокарта на отрисовку, это может происходить когда угодно, но в основном в конце отрисовки.

#3
11:12, 14 сен. 2020

1)видеокарта и операционка какая?
2)разрешение? включено ли MSAA? блендинг?
3)сколько занимает рисование одного пустого glClear? Нет ли еще каких синхронизаций? Кстати, перед swap buffers не должен быть glFinish? (это так же вопрос к другим знатокам, вроде должен)

#4
(Правка: 11:16) 11:15, 14 сен. 2020

MAMOHT-92
> Кстати, перед swap buffers не должен быть
> glFinish? (это так же вопрос к другим знатокам, вроде должен)

eglSwapBuffers performs an implicit flush operation on the context (glFlush for an OpenGL ES or OpenGL context, vgFlush for an OpenVG context)
#5
(Правка: 11:24) 11:20, 14 сен. 2020

greencad

Еще рекомендую после glBegin/glEnd еще забыть навсегда и про

  
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity;
  glScalef(FScale, FScale, 1.0);
  glTranslatef(FPanX, FPanY, 0.0);

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

И научиться в аналогичный но более соответствующий функционал с помощью

https://glm.g-truc.net/0.9.9/index.html

https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glUniform.xhtml

#6
11:31, 14 сен. 2020

foxes
> Нет, активация контекста никак не дает тормоза, хоть каждый drawcall можно
> активировать.
не знал про это, думал подобная операция такая же дорогая как и смена стейта OpenGL'a

#7
11:45, 14 сен. 2020

Спасибо всем ответившим.
Уточняю. ОС Win7 x64, ОЗУ 8 ГБ, видео встроенное в Core i7, разрешение 1920x1080, OGL 4.0. В свойствах видео (Intel HD Graphics 4600) - доступно графической памяти 1760 МБ, используется - 256. Приложение 32 бит. Никакие блендинги и синхронизации не включаю, инициализация:

  InitOpenGL;
  FPPI:= GetDeviceCaps(FDC, LOGPIXELSX);
  SetDCPixelFormat(FDC);
SetDCPixelFormat такой:
procedure SetDCPixelFormat (hdc: HDC);
var
  pfd: TPixelFormatDescriptor;
  nPixelFormat: Integer;
begin
  FillChar(pfd, SizeOf (pfd), 0);
  with pfd do
  begin
    nSize:= SizeOf(pfd);
    nVersion:= 1;
    dwFlags:= PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER;
    iPixelType:= PFD_TYPE_RGBA;
    cColorBits:= 24;
    cDepthBits:= 32;
    iLayerType:= PFD_MAIN_PLANE;
  end;
  nPixelFormat:= ChoosePixelFormat(hdc, @pfd);
  SetPixelFormat(hdc, nPixelFormat, @pfd);
end;
Насчет выкинуть glScalef/glTranslatef смущает вот что. Сейчас в шейдере у меня:
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
Станет:
gl_Position = ModelViewMatrix * ProjectionMatrix * gl_Vertex;
Т.е. на каждую вершину он будет умножать ModelViewMatrix * ProjectionMatrix и при каждом сдвиге панорамирования передавать ему эти матрицы - это не дольше? Но! Я уже писал, что при отключении шейдера (рисует просто белые линии) тормоза такие же! Засада, блин. glClear замерю.

#8
(Правка: 13:08) 12:08, 14 сен. 2020

greencad
> Насчет выкинуть glScalef/glTranslatef смущает вот что.
Это даст тебе небольшой прирост производительности в случае если у тебя много разрозненных объектов имеющих свои позиции.

greencad
> Т.е. на каждую вершину он будет умножать ModelViewMatrix * ProjectionMatrix и
> при каждом сдвиге панорамирования передавать ему эти матрицы - это не дольше?
> Но! Я уже писал, что при отключении шейдера (рисует просто белые линии) тормоза
> такие же!
Ты думаешь что при отключенном шейдере проекция вершин на экран не вычисляется?

zombihello
> не знал про это думал подобная операция такая же дорогая как и смена стейта OpenGL'a
При классическом случае, когда все данные и текущие состояния отправляются в видеокарту только при вызове отрисовке, эти изменения не играют ни какой роли. Есть оптимизация в современных дравах при которой не посылаются повторно значения состояний и тп, в этих случаях можно будет получить прирост производительность, но не для данного примера.

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

wglMakeCurrent - привязывает конкретный контекст к окну, и если у тебя работают два приложения, в том числе DX или Vulcan, то при отсутствии в твоем приложении повторной установки wglMakeCurrent, контекст со всеми настройками все равно будет неявно устанавливаться при отрисовке. Понятное дело что сам рабочий стол (aero) использует контекст, так что это переключение все равно происходит (может не так часто).

wglMakeCurrent(0, 0) - вообще по своей сути ни чего не делает, поскольку первый параметр ноль - это означает что для нулевого устройства (обычно это рабочий стол или экран) сбрасывается контекст. Для окна и приложения это пустая команда и по факту баг.

#9
13:17, 14 сен. 2020

foxes

> Ты думаешь что при отключенном шейдере проекция вершин на экран не вычисляется?

Конечно вычисляется, но я думаю, что glScalef/glTranslatef один раз вычислит произведение [ModelViewMatrix * ProjectionMatrix], а эту готовую матрицу помножит на координаты вершин, а вот в шейдере при такой записи: gl_Position = ModelViewMatrix * ProjectionMatrix * gl_Vertex оно будет вычисляться для каждой вершины. Не?
#10
(Правка: 13:54) 13:25, 14 сен. 2020

greencad
> оно будет вычисляться для каждой вершины. Не?
Если ты имеешь в виду одно матричное умножение, то небольшая просадка будет, но это все таки вычисляется параллельно для каждой вершины. В общем случае объем вычислений для каждой вершины будет по прежнему достаточно мал. Также тебе ни что не мешает самому их умножить один раз и отправлять готовую матрицу. Просто glScalef/glTranslatef делает это не лучшим образом, а загрузка матрицы как параметр дает дополнительный прирост. Но это тоже все условно и для твоего случая (как и для многих других) вообще ни чего не даст.

greencad
> разрешение 1920x1080
У тебя случайно линии не толстые? glLineWidth(0.1);

greencad
> и синхронизации не включаю
А если попробовать выключить? wglSwapIntervalEXT(0);

greencad
> glClear замерю.
В коротких примерах лучше всего замерять SwapBuffers (glFlush), так ты приблизительно поймешь нагрузку на саму видеокарту.

#11
(Правка: 13:44) 13:43, 14 сен. 2020

greencad
> gl_Position = ModelViewMatrix * ProjectionMatrix * gl_Vertex

ModelViewMatrix * ProjectionMatrix  ты можешь точно так же умножить на процессоре вне шейдера и передать результат в glUniformMatrix4fv. Причем обычно так и делают, и в шейдер передают одну финальную ModelViewProjection матрицу, которая делает сразу всё, если специально не нужны именно отдельные матрицы.

#12
(Правка: 14:13) 14:08, 14 сен. 2020

greencad
Ты можешь после каждого метода  glClear, glDrawArrays, поставить glFlush и замерить сколько эти методы действительно жрут от производительности, чтобы не бегать по коду и не искать странные просадки производительности. Для тестов в больших проектах glFlush ставят перед и после тестируемого метода.

#13
14:13, 14 сен. 2020

foxes
> поставить glFlush и замерить сколько эти методы действительно жрут от
> производительности,

Правильнее будет это делать через временные метки с помощью glQueryCounter или через glBeginQuery/glEndQuery с таргетом gl_time_elapsed.

#14
(Правка: 14:21) 14:20, 14 сен. 2020

0xc0de
> Правильнее будет
ARB_timer_query не везде может поддерживаться, это надо проверять, а glQueryCounter доступен с версии 3.2.

Страницы: 1 2 3 4 5 Следующая »
ПрограммированиеФорумГрафика