I'm doing some tests for 2D sprite drawing. But the sceGuTexImage call (before drawing vertices) is very slow because it copies the texture to another place in VRAM (even if my image is already in VRAM...).
I would not need to copy my sprites at each frame, but as I can't choose where the texture is copied, I must do it for each sprite, except if I draw the same sprite multiple times... (which is never the case in reality, except in benchmarks).
With this call, I can only draw about 13'000 64x64 sprites by second (~100 MB/sec). Without this call, I can draw about 45'000 of those sprites by second (~350 MB/sec), but it's always the same image... (but even 45000 spr/sec is still slow). If my image is in RAM, it's even slower.
Here is the code. Do you know what's so slow? Or I should use another method?
Code: Select all
unsigned short *vmemptr = (void*)(0x04100000);
typedef struct {
int larg, haut;
unsigned short *sprite;
} IMAGE;
#define IMAGE_SIZE(img) ((img)->larg*(img)->haut*2)
IMAGE CreateNewImage(int larg, int haut, unsigned short *content) {
IMAGE img;
img.larg = larg;
img.haut = haut;
img.sprite = vmemptr;
if (content != NULL)
memcpy(img.sprite, content, IMAGE_SIZE(&img));
vmemptr += IMAGE_SIZE(&img);
return img;
}
void DrawImage(IMAGE *img, int x, int y) {
struct Vertex* vertices;
sceGuTexImage(0,img->larg,img->haut,img->larg,img->sprite);
sceGuTexScale(1.0f/512.0f,1.0f/512.0f); // scale UVs to 0..1
sceGuTexOffset(0.0f, 0.0f);
vertices = (struct Vertex*)sceGuGetMemory(2 * sizeof(struct Vertex));
vertices[0].u = 0;
vertices[0].v = 0;
vertices[0].color = 0;
vertices[0].x = x;
vertices[0].y = y;
vertices[0].z = 0;
vertices[1].u = img->larg;
vertices[1].v = img->haut;
vertices[1].color = 0;
vertices[1].x = x + img->larg;
vertices[1].y = y + img->haut;
vertices[1].z = 0;
sceGuDrawArray(GU_SPRITES,GU_TEXTURE_16BIT|GU_COLOR_4444|GU_VERTEX_16BIT|GU_TRANSFORM_2D,2,0,vertices);
}
void StartDrawing() {
sceGuStart(GU_DIRECT,list);
sceGuTexMode(GU_PSM_4444,0,0,0);
sceGuTexFunc(GU_TFX_REPLACE,GU_TCC_RGB);
sceGuTexFilter(GU_NEAREST,GU_NEAREST);
sceGuAmbientColor(0xffffffff);
}
void EndDrawing() {
sceGuFinish();
sceGuSync(0,0);
}
void main()
{
unsigned int x,y;
IMAGE myImage;
myImage = CreateNewImage(64, 64, NULL);
for (y=0;y<64;y++)
for (x=0;x<64;x++)
myImage.sprite[y*myImage.larg+x]=x*y;
sceKernelDcacheWritebackAll();
while(1)
{
StartDrawing();
for (x=0;x<1000;x++)
DrawImage(&myImage, val%200, 0);
EndDrawing();
sceGuSwapBuffers();
}
}