问题
So far i have been using SDL 2.0, copy my pixel array into a texture which then gets rendered on the screen. My render method looks like this:
for (int i = 0; i < WIDTH*HEIGHT; i++){
pixels[i] = 0xFFFF0000;
//pixel Format: AARRGGBB
}
SDL_UpdateTexture(sdlTexture, NULL, pixels, 800 * sizeof(Uint32));
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, sdlTexture, NULL, NULL);
SDL_RenderPresent(renderer);
I then measured the time it takes to render it once in nanoseconds (via chrono) and compared it to a similar way of rendering pixels in java: (the pixel array stores the pixels of the "displayImage")
BufferStrategy bs = getBufferStrategy();
if (bs == null){
createBufferStrategy(3);
return;
}
screen.clear()
for (int i = 0; i < WIDTH*HEIGHT; i++){
pixels[i] = 0xFF0000;
//pixel Format: RRGGBB
}
Graphics2D g = (Graphics2D) bs.getDrawGraphics();
g.drawImage(displayImage,0,0,getWidth(),getHeight(),null);
g.dispose();
bs.show();
Surprisingly i then saw that it takes about 600.000 nanoseconds to render it in Java and about 2.000.000 nanoseconds to render it in C++.
So my question is if theres a more efficient way to draw a pixel array like i've got on the screen since (i'm assuming) C++ should render it faster than Java.
Also this is how i measured the time: C++:
auto start = std::chrono::steady_clock::now();
//render function
auto end = std::chrono::steady_clock::now();
auto result = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count();
std::cout << result << std::endl;
Java:
long start = System.nanoTime();
//render function
long end = System.nanoTime();
long result = end - start;
System.out.println(result);
回答1:
First, it should be noted that measuring a time so short isn't always reliable, so the values should be taken with a grain of salt. Even if java and C++ use the same system timer, there might be unrelated differences.
Regarding the code, SDL_UpdateTexture
will issue a copy to the internal buffer, and is therefore a bit slow. You should use SDL_LockTexture
and SDL_UnlockTexture
instead. This will allow a direct access to the internal buffer.
Also, you don't need to clear the screen in your case because your texture spans the whole screen, and therefore overwrite everything.
If you need to fill the screen, of just a line, you can use the assembly instruction rep stos
, which is much faster than a loop. With Visual C++, you can emit rep stos
for uint32 using __stosd
. This works like memset
, but for uint32 (you also have the uint16 version with __stosw
, and uint64 with __stosq
, x64 only). There is the equivalent __movsd
to make a copy, but well implemented memcpy
can be even faster.
来源:https://stackoverflow.com/questions/28279242/how-to-render-a-pixel-array-most-efficiently-to-a-window-in-c