[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[pygame] Bizarre(?) per-pixel alpha vs. no alpha benchmark results
I benchmarked (code attached) blitting a 128x128 sprite
(attached) with and without per pixel alpha information
under PyGame. On each frame, I clear the 640x480 screen
with the background color via fill(), then blit the
sprite 4 times. The results are quite interesting:
640x480 windowed 16-bit 32-bit
===============================================
plain opaque blit: 70 fps 47 fps
per pixel alpha : 80 fps (!) 49 fps
per pixel alpha + RLEACCEL: 93 fps (!) 55 fps
Comment: Why is p.p. Alpha blit faster in
windowed modes? Does this mean that there
will not be much benefit gained from optimizing
the alpha blending routines (like say, using
MMX)?
120Hz 640x480 16-bit full screen, SWSURFACE
DOUBLEBUF no DOUBLEBUF
=============================================================
plain opaque blit: 120 fps 71 fps (!)
per pixel alpha : 24 fps(!) 80 fps
per pixel alpha + RLEACCEL: 30 fps(!) 95 fps
Comment: Why does using double-buffering impose
such a huge performance hit on the alpha blending and
at the same time INCREASE the performance of the
plain opaque blit?!? Could this be an artifact of
using PyGame? 640x480 32-bit mode exhibited analogous
behavior. No tearing visible in all tests.
120Hz 640x480 16-bit full screen, HWSURFACE
DOUBLEBUF no DOUBLEBUF
=============================================================
plain opaque blit: 120 fps / 146 fps
per pixel alpha : 23 fps / 25 fps
per pixel alpha + RLEACCEL: 35 fps / 35 fps
Comment: Severe tearing when not using DOUBLEBUF, even
when the fps was way below the refresh rate as in the
case of the alpha blits! Why would using HWSURFACE
create tearing? 32-bit results analogous to 16-bit
ones.
Notes
=====
1. Enabling RLEACCEL made no difference for all the
plain opaque blits.
2. In windowed mode, HWSURFACE doesn't seem to have
an effect even if i use a low-res mode like 800x600.
Considering I'm using a 16MB Voodoo3, shouldn't
there be plenty of video memory to store the sprite
in?
Details on the sprite image I used
==================================
They come from the same image generated under
Photoshop. One was saved as a Targa (with alpha
channel) and the other is a PNG (Photoshop 6 does
not export alpha channel for PNGs), otherwise
identical. I've included it the PNG version to
show the background pixel to non-background pixel
ratio as well as the alpha channel in grayscale
PNG.
My setup
========
DirectX 8
Win2K SP1
16MB Voodoo3 AGP
120Hz refresh at 640x480 fullscreen
import pygame
import pygame.image
import whrandom
from pygame.locals import *
from whrandom import randint
# position sprites randomly clustered in the center
pos1=randint(200,300); pos2=randint(150,200);
pos3=randint(200,300); pos4=randint(150,200);
pos5=randint(200,300); pos6=randint(150,200);
pos7=randint(200,300); pos8=randint(150,200);
whrandom.seed(1,2,2)
fps_frames = 0
fps_time = 0
def main():
global screen,alpha1
pygame.init()
# Uncomment for proper display mode
#screen = pygame.display.set_mode((640,480))
screen = pygame.display.set_mode((640,480), FULLSCREEN, 32)
#screen = pygame.display.set_mode((640,480), HWSURFACE|FULLSCREEN, 32)
print screen.get_flags()
# Select between alpha, no alpha, RLEACCEL and none
alpha1 = pygame.image.load('c:\\temp\\alpha1.tga')
#alpha1 = pygame.image.load('c:\\temp\\alpha1.png')
alpha1.set_alpha(255,RLEACCEL)
while not pygame.event.peek((QUIT,KEYDOWN,MOUSEBUTTONDOWN)):
calculateFrame()
pygame.display.flip()
calcfps()
def calcfps():
global fps_time, fps_frames
if not fps_time:
fps_time = pygame.time.get_ticks()
fps_frames = 0
return
fps_frames += 1
now = pygame.time.get_ticks()
time = now - fps_time
if time > 1000:
time = time / 1000.0
print 'TIME: %.3f FPS: %.2f' % (time/fps_frames, fps_frames/time)
fps_frames = 0
fps_time = now
def initscreen():
pygame.init()
screen = pygame.display.set_mode((640,480), 0, 32)
print screen.get_flags()
def benchblit():
while not pygame.event.peek((QUIT,KEYDOWN,MOUSEBUTTONDOWN)):
calculateFrame()
pygame.display.flip()
calcfps()
def calculateFrame():
global pos1,pos2,pos3,pos4,pos5,pos6,pos7,pos8
if randint(0,1)==0: pos1=pos1+randint(0,6)-3
if randint(0,1)==0: pos2=pos2+randint(0,6)-3
if randint(0,1)==0: pos3=pos3+randint(0,6)-3
if randint(0,1)==0: pos4=pos4+randint(0,6)-3
if randint(0,1)==0: pos5=pos5+randint(0,6)-3
if randint(0,1)==0: pos6=pos6+randint(0,6)-3
if randint(0,1)==0: pos7=pos7+randint(0,6)-3
if randint(0,1)==0: pos8=pos8+randint(0,6)-3
screen.fill((200,200,200))
screen.blit(alpha1,[pos1,pos2])
screen.blit(alpha1,[pos3,pos4])
screen.blit(alpha1,[pos5,pos6])
screen.blit(alpha1,[pos7,pos8])
if __name__ == '__main__': main()
alpha1-channel.png
alpha1.png