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

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

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)

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

Using the Renderer for Table 1

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

Using the Renderer for Table 2

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)

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

Using the Renderer for Table 1

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

Using the Renderer for Table 2

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:

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

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

// 清除旧的表面和纹理
SDL_FillRect(pSurfaceMap, NULL, 0x000000);
SDL_DestroyTexture(pTextureMap);

// 将此规则的确定矩形绘制到表面上
SDL_FillRects(pSurfaceMap, sCellRects, iCountRectsRendered, SDL_MapRGBA(pSurfaceMap->format, cDarkYellow.r, cDarkYellow.g, cDarkYellow.b, cDarkYellow.a));

// 从表面创建纹理
pTextureMap = SDL_CreateTextureFromSurface(pRenderer, pSurfaceMap);

(在FrameDrawingFunction中)

SDL_RenderCopy(pRenderer, pTextureMap, NULL, NULL);

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

英文:

UPDATE:

My current solution boils down to this:

(After a new ruleset is choosen)

// Flush the old surface and texture

SDL_FillRect(pSurfaceMap, NULL, 0x000000);
SDL_DestroyTexture(pTextureMap);

// Draw determined rects of this rule to a surface

SDL_FillRects(pSurfaceMap, sCellRects, iCountRectsRendered, SDL_MapRGBA(pSurfaceMap->format, cDarkYellow.r, cDarkYellow.g, cDarkYellow.b, cDarkYellow.a));

// Create a texture from the surface

pTextureMap = SDL_CreateTextureFromSurface(pRenderer, pSurfaceMap);

(In the FrameDrawingFunction)

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:

确定