Есть 2 GL-приложения, максимально упрощенных. Одну и ту же картинку (868 квада, 2D) рендерит за 50 FPS, второе - даёт 10 FPS.
Карточка Intel, поэтому такое низкое FPS.
Стал смотреть стейты, довёл до идентичности:
[0] ALPHA_TEST (GL_ALWAYS, 0) [0] AUTO_NORMAL [1] BLEND (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) [0] CLIP_PLANE [1] COLOR_MATERIAL (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE) [0] CULL_FACE [0] DEPTH_TEST [1] DITHER [0] FOG [0] LIGHT [0] LIGHTING [0] LINE_SMOOTH [0] LINE_STIPPLE [0] LOGIC_OP [0] MAP1_COLOR_4 [0] MAP1_INDEX [0] MAP1_NORMAL [0] NORMALIZE [0] POINT_SMOOTH [0] POLYGON_SMOOTH [0] POLYGON_STIPPLE [0] SCISSOR_TEST [0] STENCIL_TEST [0] TEXTURE_1D [1] TEXTURE_2D (MIN: GL_LINEAR, MAG: GL_LINEAR, WRAP_S: GL_REPEAT, WRAP_T: GL_REPEAT, ENV_MODE: GL_MODULATE) [0] TEXTURE_GEN_Q [0] TEXTURE_GEN_R [0] TEXTURE_GEN_S [0] TEXTURE_GEN_T SHADE_MODEL: GL_SMOOTH FOG_HINT: GL_DONT_CARE LINE_SMOOTH_HINT: GL_DONT_CARE PERSPECTIVE_CORRECTION_HINT: GL_NICEST POINT_SMOOTH_HINT: GL_DONT_CARE POLYGON_SMOOTH_HINT: GL_DONT_CARE
Сделал максимально идентичный код. Почти всё перерыл.
Не нахожу ответа - в чём проблема.
Какие идеи ?
DevilDevil
> Сделал максимально идентичный код
Дак у тебя исходники есть? Если идентичный - то должно быть одинакого. Ищи что делается лишнего в рендере. Через что идет рендер? immediate/DL/VA/VBO?
Завтра покажу код
Описываю ситуацию:
// вершина TVertex = record X, Y: single; Z: single; BGRA : TBGRA; Tx, Ty: single; end; PVertex = ^TVertex; // квад TQuad = packed record case Integer of 0: (Vertexes: array[0..3] of TVertex); 1: ( LeftTop, RightTop, RightBottom, LeftBottom: TVertex); end; {$I 868_quads.inc} // array[0..868-1] of TQuad; {$I texture_128x128_BGRA.inc} // текстура 128х128 в формате BGRA var QuadPtr, TextureData: pointer; // QuadPtr := @_868_quadsDATA; // TextureData := @texture_128x128_BGRADATA;
Стейты в момент рендера - как в первом посте. В обоих проектах!
FPS 10. Render:
var i: integer; Vertex: PVertex; begin //BeginRender(); glClear(GL_COLOR_BUFFER_BIT{ or GL_DEPTH_BUFFER_BIT}); glViewPort( 0, 0, 800, 600); glMatrixMode( GL_PROJECTION); glLoadIdentity; glOrtho( 0, 800, 600, 0, -1, 1); glMatrixMode( GL_MODELVIEW); glLoadIdentity; // RenderQuads begin glEnable( GL_TEXTURE_2D); if ( Texture = 0) then CreateTexture( ); glBindTexture( GL_TEXTURE_2D, Texture); glBegin( GL_QUADS); Vertex := QuadPtr; for i := 0 to 868*4-1 do with Vertex^ do begin glColor4ub( BGRA.R, BGRA.G, BGRA.B, BGRA.A); glTexCoord2fv( @Tx); glVertex3fv( @X); inc( Vertex); end; glEnd( ); end; //EndRender(); glFlush( ); //ShowRenderBuffer(); SwapBuffers( h_DC); end;
FPS 50. Render:
ogl.Clear(True); // glClear(GL_COLOR_BUFFER_BIT); ogl.Set2D( 0, 0, 800, 600); { glMatrixMode( GL_PROJECTION); glLoadIdentity; glOrtho( x, x + w, y + h, y, -1, 1); glMatrixMode( GL_MODELVIEW); glLoadIdentity; } tex.Enable( Texture); // вроде glBindTexture(GL_TEXTURE_2D, Texture); glBegin( GL_QUADS); Vertex := QuadPtr; for i := 0 to 868*4-1 do with Vertex^ do begin glColor4ub( BGRA.R, BGRA.G, BGRA.B, BGRA.A); glTexCoord2fv( @Tx); glVertex3fv( @X); inc( Vertex); end; glEnd( ); ogl.Swap( ); //glFlush; //SwapBuffers(DC);
Тот проект, который выдаёт 10 FPS - мой. Началось всё с того, что он выдавал низкий FPS при большом количестве полигонов: и DX-рендер, и GL. Взял попробовал тот же самый массив квадов с той же текстурой вывести в eXgine - и увидел fps в 5 раз выше ! Свой пример максимально упростил, подвёл под GL, fps тот же. Какие идеи, ребят ? Давайте попробуем другую апдейт-функцию, инициализацию, оконная функция. Предлагайте свои идеи со своим кодом - буду вставлять и смотреть. Заранее спасибо!
PixelFormat тоже одинаковый? Разрешение?
Вот это меня смущает.
if (Texture = 0) then CreateTexture();
glBindTexture(GL_TEXTURE_2D, Texture);
А вообще профайлер в руки и вперед(AQTime как вариант).
>if (Texture = 0) then CreateTexture();
внутри рендера выделять память как-то нехорошо.
ogl.Set2D(0, 0, 800, 600);
и
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
glOrtho(x, x + w, y + h, y, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity;
- не эквивалентны.
в обоих примерах НЕ используй with (зачастую замедяет ваполнение проги)
>XProger:
>если отключить рендер квадов разница в фпс тоже будет?
eXgine: 347
мой: 137
Чё за херь ?
@!!ex
>Вот это меня смущает.
>if (Texture = 0) then CreateTexture();
> glBindTexture(GL_TEXTURE_2D, Texture);
При первом же рендере, Texture становится единицей
Разрешение 800х600, а инициализацию я сейчас покажу
я инициализирую свёрнутое окно, может из-за этого?
Хотя в DX другой принцип инициализации, результат тот же.
Скорее всего основной цикл и оконнная функция. Приведите свой пример, плиз
профайлер поставь и СРАЗУ все видно станет.
есть профайлер, полегче AQTime (91Мб) ?
Вроде есть что-то опенсорсное, ну естественно близко не AQTime
DevilDevil
> > if (Texture = 0) then CreateTexture();
Может,
if (Texture = 0) then Texture := CreateTexture();
(в OpenGL для создания текстуры служит glGenTextures)
glFlush();
SwapBuffers(h_DC);
Не надо этого делать!
SwapBuffers(h_DC);
и всё...
All
Скачал gDEBugger, что кликнуть, на что обратить внимание ?
Я по прежнему думаю, что дело в оконной функции и основном цикле.
Приведите пожалуйста пример своей оконной функции и своего основного цикла, который вызывает Render и расчитывает FPS.
Может я окно неправильно создаю ?
type TWindowSettings = record dwStyle, dwExStyle : dword; X, Y : integer; WindowWidth, WindowHeight: integer; end; function GetWindowSettings(FullScreen: boolean): TWindowSettings; begin with Result do begin WindowWidth := RenderWindowInfo.WindowWidth; // 800 WindowHeight := RenderWindowInfo.WindowHeight; // 600 if ( FullScreen) then begin // bsNone dwStyle := WS_POPUP or WS_CLIPCHILDREN or WS_CLIPSIBLINGS or WS_SYSMENU; dwExStyle := WS_EX_APPWINDOW;// or WS_EX_TOPMOST; X := 0; Y := 0; end else begin // bsSizable dwStyle := WS_OVERLAPPED{WINDOW} or WS_SYSMENU or WS_CAPTION or WS_MAXIMIZEBOX or WS_MINIMIZEBOX or WS_CLIPCHILDREN or WS_CLIPSIBLINGS; dwExStyle := WS_EX_APPWINDOW or WS_EX_WINDOWEDGE; Inc( WindowWidth, GetSystemMetrics( SM_CXDLGFRAME)*2); Inc( WindowHeight, GetSystemMetrics( SM_CYCAPTION)+GetSystemMetrics( SM_CYDLGFRAME)*2); X := ( DefScreenMode.Width-WindowWidth) div 2; Y := ( DefScreenMode.Height-WindowHeight) div 2; end; end; end; function CreateCrystalWindow( const GameID: string = '') : HWND; var wndClass: TWndClass; _hInstance: integer; begin _hInstance := hInstance; AppClassName := GetGameClassName( GameID); ZeroMemory( @wndClass, SizeOf( wndClass)); with wndClass do begin style := CS_HREDRAW or CS_VREDRAW or CS_OWNDC; lpfnWndProc := @WindowProc; hInstance := _hInstance; hIcon := LoadIcon( _hInstance, 'MAINICON'); lpszClassName := pchar( AppClassName); end; if ( Windows.RegisterClass( wndClass) = 0) then TExcept.Assert( 'Failed to register window class "%s" !', [AppClassName]); with GetWindowSettings( EngineInstance.FullScreen{false}) do Result := CreateWindowEx( dwExStyle,pchar( AppClassName),'Loading...',dwStyle, X, Y, WindowWidth, WindowHeight, 0, 0, hInstance, nil); if Result = 0 then TExcept.Assert( 'Unable to create window!'); MinimizeWindow( Result); // SendMessage(Window, WM_SYSCOMMAND, SC_MINIMIZE, 0) end;
@!!ex
procedure InitializeGL(); var pfd : TPIXELFORMATDESCRIPTOR; PixelFormat : integer; begin h_DC := GetDC( EngineInstance.WindowHandle); if ( h_DC = 0) then TExcept.Assert( 'Unable to get a device context!'); ZeroMemory( @pfd, sizeof( pfd)); 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 := 32; cDepthBits := 16; iLayerType := PFD_MAIN_PLANE; end; PixelFormat := ChoosePixelFormat( h_DC, @pfd); if ( PixelFormat = 0) then TExcept.Assert( 'Unable to find a suitable pixel format!'); if ( not SetPixelFormat( h_DC, PixelFormat, @pfd)) then TExcept.Assert( 'Unable to set the pixel format!'); h_RC := wglCreateContext( h_DC); if ( h_RC = 0) then TExcept.Assert( 'Unable to create an OpenGL rendering context!'); if ( not wglMakeCurrent( h_DC, h_RC)) then TExcept.Assert( 'Unable to activate OpenGL rendering context!'); // BAD_DRIVER := (Pos('GDI', glGetString(GL_RENDERER)) <> 0) or (Pos('MICROSOFT', UpperCase(glGetString(GL_VENDOR))) <> 0); EXTENSIONS := glGetString( GL_EXTENSIONS); @wglSwapIntervalEXT := wglGetProcAddress( 'wglSwapIntervalEXT'); @wglGetSwapIntervalEXT := wglGetProcAddress( 'wglGetSwapIntervalEXT'); SetVSync( EngineInstance.VSync); glClearColor( 0.0, 0.0, 0.0, 0.0); glShadeModel( GL_SMOOTH); glDisable( GL_DEPTH_TEST); glDepthFunc( GL_LEQUAL); glDisable( GL_ALPHA_TEST); glClearDepth( 1.0); glEnable( GL_BLEND); glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable( GL_TEXTURE_2D); glDisable( GL_NORMALIZE); glEnable( GL_COLOR_MATERIAL); // VBO UseVBO := isExtensionSupported( 'GL_ARB_vertex_buffer_object'); if ( UseVBO) then begin // инициализация VBO-функций glBindBufferARB := wglGetProcAddress( 'glBindBufferARB'); glDeleteBuffersARB := wglGetProcAddress( 'glDeleteBuffersARB'); glGenBuffersARB := wglGetProcAddress( 'glGenBuffersARB'); glBufferDataARB := wglGetProcAddress( 'glBufferDataARB'); glMapBufferARB := wglGetProcAddress( 'glMapBufferARB'); glUnmapBufferARB := wglGetProcAddress( 'glUnmapBufferARB'); glEnableClientState := wglGetProcAddress( 'glEnableClientState'); glDisableClientState := wglGetProcAddress( 'glDisableClientState'); glVertexPointer := wglGetProcAddress( 'glVertexPointer'); glColorPointer := wglGetProcAddress( 'glColorPointer'); glTexCoordPointer := wglGetProcAddress( 'glTexCoordPointer'); glDrawArrays := wglGetProcAddress( 'glDrawArrays'); // создание буферов glGenBuffersARB( 2, @VertexBuffers[false]); glBindBufferARB( GL_ARRAY_BUFFER_ARB, VertexBuffers[false]); glBufferDataARB( GL_ARRAY_BUFFER_ARB, MAX_QUADS_COUNT*sizeof( TQuad), nil, GL_STREAM_DRAW_ARB); glBindBufferARB( GL_ARRAY_BUFFER_ARB, VertexBuffers[true]); glBufferDataARB( GL_ARRAY_BUFFER_ARB, MAX_QUADS_COUNT*sizeof( TQuad), nil, GL_STREAM_DRAW_ARB); end else begin GetMem( VertexBuffer, MAX_QUADS_COUNT*sizeof( TQuad)); end; // TestSupports pboolean( @NonbinaryTextureSupports)^ := isExtensionSupported( 'ARB_texture_non_power_of_two'); pboolean( @CompressedTextureSupports)^ := isExtensionSupported( 'GL_ARB_texture_compression'); end;
andriano
procedure CreateTexture(); begin glGenTextures( 1, @Texture); glBindTexture( GL_TEXTURE_2D, Texture); glPixelStorei( GL_UNPACK_ALIGNMENT, 1); glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf( GL_TEXTURE_2D, $8191{GENERATE_MIPMAP_SGIS}, 0); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 128, 128, 0, GL_BGRA, GL_UNSIGNED_BYTE, TextureData); end;
Executor
закомментировал glFlush - ничего не изменилось. На некоторых моих примерах давал прирост скорости в пару десятков fps.
Чё делать ?
Тема в архиве.