低帧率在SDL2中渲染146.735个正方形(2×2)时?

huangapple go评论115阅读模式
英文:

Low fps when rendering 146.735 squares (2x2) in sdl2?

问题

I build a printer for one-dimensional cellular automata, for which I use SDL_RenderFillRect() / SDL_RenderFillRects() to print the cells.
The view allows certain zoom levels for a rule, the lowest zoom level (width of a square) will render 146.735 squares for Rule 30 (see screenshot), with each square having a dimension of 2x2 px (total px: 586.940).

However, the fps are not what I expected...

(Rule 30 at pixeldim 2x2)
低帧率在SDL2中渲染146.735个正方形(2×2)时?

I first used SDL_RenderFillRect() in a loop which resulted in the following fps

Rendering Rule 30 using SDL_RenderFillRect():

Zoom fps
10 59
9 59
8 59
7 59
6 59
5 55
4 36
3 19
2 9

I then handed the data to SDL_RenderFillRects() which resulted in the following fps

Rendering Rule 30 using SDL_RenderFillRects():

Zoom fps
10 59
9 59
8 59
7 59
6 59
5 59
4 59
3 59
2 45

That is way better but I still don't understand how a simple task like that drops to anything below 60 on a modern office computer ??

My question is: Is SDL_RenderFillRect() / SDL_RenderFillRects() not the right thing for this use case? What would be a more efficient approach?

Renderer (uses vsync and hardware acceleration)

  1. ...
  2. pRenderer = SDL_CreateRenderer(pWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
  3. ...

Using the Renderer for Table 1

  1. // Render only the zoomed contents
  2. for (int i = 0; i < iZoomedCells; i++) {
  3. if (sCellMap[i].bActive) {
  4. SDL_RenderFillRect(pRenderer, &sCellMap[i].rCell);
  5. }
  6. }

Using the Renderer for Table 2

  1. SDL_RenderFillRects(pRenderer, sCellRects, iZoomedCells);

Anything black is the background and not a call to RenderFillRect(). Also: the more black space a rule has, the higher the fps are.

英文:

I build a printer for one dimensional cellular automata, for which I use SDL_RenderFillRect()/ SDL_RenderFillRects() to print the cells.
The view allows certain zoom levels for a rule, the lowest zoom level (width of a square) will render 146.735 squares for Rule 30 (see screenshot), with each square having a dimension of 2x2 px (total px: 586.940 ).

However, the fps are not what I expected...

(Rule 30 at pixeldim 2x2)
低帧率在SDL2中渲染146.735个正方形(2×2)时?

I first used SDL_RenderFillRect() in a loop which resulted in the following fps

Rendering Rule 30 using SDL_RenderFillRect():

Zoom fps
10 59
9 59
8 59
7 59
6 59
5 55
4 36
3 19
2 9

I then handed the data to SDL_RenderFillRects() which resulted in the following fps

Rendering Rule 30 using SDL_RenderFillRects():

Zoom fps
10 59
9 59
8 59
7 59
6 59
5 59
4 59
3 59
2 45

That is way better but I still don't understand how a simple task like that drops to anything below 60 on a modern office computer ??

My question is:
Is SDL_RenderFillRect()/ SDL_RenderFillRects() not the right thing for this usecase ?
What would be a more efficient approach ?

Renderer (uses vsync and hardware acceleration)

  1. ...
  2. pRenderer = SDL_CreateRenderer(pWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
  3. ...

Using the Renderer for Table 1

  1. // Render only the zoomed contents
  2. for (int i = 0; i < iZoomedCells; i++) {
  3. if (sCellMap[i].bActive) {
  4. SDL_RenderFillRect(pRenderer, &sCellMap[i].rCell);
  5. }
  6. }

Using the Renderer for Table 2

  1. SDL_RenderFillRects(pRenderer, sCellRects, iZoomedCells);

Anything black is background and not a call to RenderFillRect().
Also: the more black space a rule has the higher the fps are.

答案1

得分: -1

UPDATE:

我的当前解决方案可以归结为以下内容:

(在选择新的规则集之后)

  1. // 清除旧的表面和纹理
  2. SDL_FillRect(pSurfaceMap, NULL, 0x000000);
  3. SDL_DestroyTexture(pTextureMap);
  4. // 将此规则的确定矩形绘制到表面上
  5. SDL_FillRects(pSurfaceMap, sCellRects, iCountRectsRendered, SDL_MapRGBA(pSurfaceMap->format, cDarkYellow.r, cDarkYellow.g, cDarkYellow.b, cDarkYellow.a));
  6. // 从表面创建纹理
  7. pTextureMap = SDL_CreateTextureFromSurface(pRenderer, pSurfaceMap);

(在FrameDrawingFunction中)

  1. SDL_RenderCopy(pRenderer, pTextureMap, NULL, NULL);

这种方法将导致稳定的59帧每秒的垂直同步(vsync),以及700多帧每秒的非同步。这已经更符合我对简单渲染任务工作负荷的期望了。

英文:

UPDATE:

My current solution boils down to this:

(After a new ruleset is choosen)

  1. // Flush the old surface and texture
  2. SDL_FillRect(pSurfaceMap, NULL, 0x000000);
  3. SDL_DestroyTexture(pTextureMap);
  4. // Draw determined rects of this rule to a surface
  5. SDL_FillRects(pSurfaceMap, sCellRects, iCountRectsRendered, SDL_MapRGBA(pSurfaceMap->format, cDarkYellow.r, cDarkYellow.g, cDarkYellow.b, cDarkYellow.a));
  6. // Create a texture from the surface
  7. pTextureMap = SDL_CreateTextureFromSurface(pRenderer, pSurfaceMap);

(In the FrameDrawingFunction)

  1. SDL_RenderCopy(pRenderer, pTextureMap, NULL, NULL);

That approach will lead to stable 59 fps vsynced and 700+ fps unsynced.
That is already more like what I expected a simple rendering task's workload should cause.

huangapple
  • 本文由 发表于 2023年3月31日 21:01:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/75898858.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定