 |
forums.ps2dev.org Homebrew PS2, PSP & PS3 Development Discussions
|
| View previous topic :: View next topic |
| Author |
Message |
coolkehon
Joined: 20 Oct 2008 Posts: 355
|
Posted: Fri Jul 17, 2009 3:18 pm Post subject: Problem Rendering large image on gu |
|
|
| it renders images that are of smaller sizes but when i try to render a background image that is 480x272 they image becomes smaller and the framerate slows to about 18 frames per second does anyone have any idea why and how to solve this |
|
| Back to top |
|
 |
Jim

Joined: 02 Jul 2005 Posts: 487 Location: Sydney
|
Posted: Fri Jul 17, 2009 10:38 pm Post subject: |
|
|
Use swizzled textures, use lower bit-depth textures or palettised textures, don't clear the screen if you're rendering all of it, disable alpha.
Jim _________________ http://www.dbfinteractive.com |
|
| Back to top |
|
 |
coolkehon
Joined: 20 Oct 2008 Posts: 355
|
Posted: Fri Jul 17, 2009 10:46 pm Post subject: |
|
|
| i think i problem is because of the psp texture width limits is there a workaround for this and if so can someone explain it because i'm new to the gu |
|
| Back to top |
|
 |
rapso
Joined: 28 Mar 2005 Posts: 147
|
Posted: Sat Jul 18, 2009 12:50 am Post subject: |
|
|
| maybe it's downscaled to a power of two texture, scale it up to 512x512 (or add border), that might work, and yeah, follow the jim's tips for performance. |
|
| Back to top |
|
 |
J.F.
Joined: 22 Feb 2004 Posts: 2906
|
Posted: Sat Jul 18, 2009 1:05 am Post subject: |
|
|
You'll see in many examples and apps that wide textures are drawn in "slices". The reason is the PSP uses a texture cache that can only hold so much data - if you go too wide on the texture, the cache is reloaded (maybe more than once) on every single line drawn. If you cut a wide texture into vertical pieces that are narrow enough to fit in the cache, it will draw many lines before needing to reload the texture cache. Swizzling the texture also helps because otherwise the PSP will swizzle the texture during load, slowing the loading. Note that compressed textures cannot be swizzled.
Alpha computation also takes time, so if you know you don't need it, don't enable it. A good example is drawing the initial background that fills the screen completely. |
|
| Back to top |
|
 |
coolkehon
Joined: 20 Oct 2008 Posts: 355
|
Posted: Sat Jul 18, 2009 1:56 am Post subject: |
|
|
| cool thanks could you provide an example and all i'm doing is drawing a background image |
|
| Back to top |
|
 |
J.F.
Joined: 22 Feb 2004 Posts: 2906
|
Posted: Sat Jul 18, 2009 4:21 am Post subject: |
|
|
| Look at the ubiquitous graphics.c. Look at any program that draws using the GU. Look at nearly every gu sample in the sdk. The samples are there for a reason. |
|
| Back to top |
|
 |
coolkehon
Joined: 20 Oct 2008 Posts: 355
|
Posted: Sat Jul 18, 2009 6:46 am Post subject: |
|
|
yeah i looked at the sdk gu stuff and it doesn't have a sample showing any of this stuff that i'm looking for like spliting the texture and drawing parts of it and i looked at the graphics.c and it just wont load the image if it is < 512 and it seems that this background image is exactly 512x512 but its not greater so why is the gu messing this up here is the load function
| Code: | Image * ImageUtil::loadImageFilePNG(FILE * fp, PixelFormat pixelFormat , bool swizzle, bool in_vram, DrawingCanvas * canvas)
{
if(fp == NULL || !is_png(fp))
return NULL;
Image * rimg = new Image(canvas);
rimg->image = (Image::ImageData *) malloc(sizeof(Image::ImageData));
if(rimg->image == NULL)
{
rimg->Delete();
return NULL;
}
Image::ImageData * image = rimg->image;
memset(image,0,sizeof(Image::ImageData));
image->pixelFormat = pixelFormat;
image->in_vram = in_vram;
png_structp png_ptr;
png_infop info_ptr;
// png_uint_32 width, height;
// int bit_depth, color_type, interlace_type;
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
if(png_ptr == NULL)
{
rimg->Delete();
return NULL;
}
info_ptr = png_create_info_struct(png_ptr);
if(info_ptr == NULL)
{
rimg->Delete();
png_destroy_read_struct(&png_ptr, NULL, NULL);
return NULL;
}
if (setjmp(png_jmpbuf(png_ptr)))
{
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
rimg->Delete();
return NULL;
}
png_init_io(png_ptr, fp);
// png_set_sig_bytes(png_ptr, 8);
if(pixelWidths[pixelFormat] <= 8)
{
png_read_png(png_ptr,info_ptr,
PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_BGR, NULL );
}
else
{
png_read_png( png_ptr, info_ptr,
PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_BGR, NULL );
}
png_uint_32 width = info_ptr->width;
png_uint_32 height = info_ptr->height;
png_uint_32 depth = info_ptr->bit_depth;
int color_type = info_ptr->color_type;
png_byte **pRowTable = info_ptr->row_pointers;
unsigned char r=0, g=0, b=0, a=0;
int wantedPixelFormat = pixelFormat;
if (!info_ptr->num_palette && pixelWidths[pixelFormat] <= 8)
{
pixelFormat = GU_PSM_8888;
image->width = width;
image->height = height;
image->pixelFormat = pixelFormat;
image->in_vram = false;
}
else
{
image->width = width;
image->height = height;
image->pixelFormat = pixelFormat;
image->in_vram = in_vram;
}
image->swizzled = false;
if(image->width > 512)
image->textureWidth = image->width;
else
image->textureWidth = getNextPower2(image->width);
if(image->height > 512)
image->textureHeight = image->height;
else
image->textureHeight = getNextPower2(image->height);
image->size = (image->textureWidth * image->textureHeight * pixelWidths[image->pixelFormat]) >> 3;
if(image->in_vram)
image->data = (uint *)valloc(image->size);
else
image->data = (uint *)memalign(16,image->size);
if(image->data == NULL)
{
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
rimg->Delete();
return NULL;
}
if(pixelWidths[pixelFormat] <= 8)
{
image->palette = Image::CreatePalette(MIN(info_ptr->num_palette, 1 << paletteSizes[pixelFormat]), in_vram, GU_PSM_8888);
if(image->palette == NULL)
{
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
rimg->Delete();
return NULL;
}
info_ptr->num_palette = MIN(info_ptr->num_palette, image->palette->nentries);
for(int i = 0; i < info_ptr->num_palette; i++)
{
int r = info_ptr->palette[i].red;
int g = info_ptr->palette[i].green;
int b = info_ptr->palette[i].blue;
int a = 0xff;
}
sceKernelDcacheWritebackInvalidateRange(image->palette->data,image->palette->size);
}
u32 *p_dest4 = (u32*)image->data;
u16 *p_dest2 = (u16*)image->data;
u8 *p_dest1 = (u8*)image->data;
u32 x, y;
int color_per_entry = 8 / depth;
int color_offset, pixel_value = 0;
int mask = (1 << depth) - 1;
for ( y = 0; y < height; ++y )
{
const png_byte * pRow = pRowTable[y];
for ( x = 0; x < width; ++x )
{
switch ( color_type )
{
case PNG_COLOR_TYPE_GRAY:
r = g = b = *pRow++;
if ( r == 0 && g == 0 && b == 0 )
a = 0x00;
else
a = 0xff;
break;
case PNG_COLOR_TYPE_GRAY_ALPHA:
r = g = b = *pRow++;
if ( r == 0 && g == 0 && b == 0 )
a = 0x00;
else
a = 0xff;
pRow++;
break;
case PNG_COLOR_TYPE_RGB:
b = *pRow++;
g = *pRow++;
r = *pRow++;
a = 0xff;
break;
case PNG_COLOR_TYPE_RGB_ALPHA:
b = *pRow++;
g = *pRow++;
r = *pRow++;
a = *pRow++;
break;
case PNG_COLOR_TYPE_PALETTE:
color_offset = x % color_per_entry;
pixel_value = (*pRow >> (8 - depth * (color_offset + 1))) & mask;
if (x % color_per_entry == color_per_entry - 1)
pRow++;
if (image->palette)
{
r = (((u32*)image->palette->data)[pixel_value]) & 0xff;
g = ((((u32*)image->palette->data)[pixel_value]) >> 8) & 0xff;
b = ((((u32*)image->palette->data)[pixel_value]) >> 16) & 0xff;
a = ((((u32*)image->palette->data)[pixel_value]) >> 24) & 0xff;
}
else
{
b = info_ptr->palette[pixel_value].blue;
g = info_ptr->palette[pixel_value].green;
r = info_ptr->palette[pixel_value].red;
a = 0xff;
}
break;
}
if (pixelFormat == GU_PSM_8888)
p_dest4[x] = RGBA(r,g,b,a);
else if (pixelFormat == GU_PSM_5650)
p_dest2[x] = RGB16(r,g,b);
else if (pixelFormat == GU_PSM_5551)
p_dest2[x] = RGBA15(r,g,b,a);
else if (pixelFormat == GU_PSM_4444)
p_dest2[x] = RGBA12(r,g,b,a);
else if (pixelFormat == GU_PSM_T8)
p_dest1[x] = pixel_value;
else if (pixelFormat == GU_PSM_T4)
{
p_dest1[x >> 1] &= ~(15 << ((x & 1) << 2));
p_dest1[x >> 1] |= (pixel_value & 15) << ((x & 1) << 2);
}
}
p_dest1 += ( image->textureWidth * pixelWidths[pixelFormat]) >> 3;
p_dest2 += ( image->textureWidth );
p_dest4 += ( image->textureWidth );
}
sceKernelDcacheWritebackInvalidateRange(image->data,image->size);
rimg->setStart(Location(0,0));
rimg->setEnd(Location(image->width,image->height));
// TODO swizzle images and convert pixel formats
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
return rimg;
} |
as you can see i copied this from oslib/oslibmod and modified it a little well a lot because i would basically be doing the same thing and i used it to learn about how to do it smaller images less than 512 are ok but this isnt so why is that |
|
| Back to top |
|
 |
J.F.
Joined: 22 Feb 2004 Posts: 2906
|
Posted: Sat Jul 18, 2009 8:56 am Post subject: |
|
|
| The blit gu sample does slices. Slices are for two reasons: speed (makes better use of the texture cache), and size (anything bigger than 512 can't be done in one operation regardless of speed). |
|
| Back to top |
|
 |
coolkehon
Joined: 20 Oct 2008 Posts: 355
|
Posted: Sat Jul 18, 2009 9:46 am Post subject: |
|
|
| J.F. wrote: | | The blit gu sample does slices. Slices are for two reasons: speed (makes better use of the texture cache), and size (anything bigger than 512 can't be done in one operation regardless of speed). |
haven't tried that yet but how do i do this if the image is rotated
and thanks i because it looks like it will work but i used this from psp-programming because it was less complex
http://www.psp-programming.com/forums/index.php/topic,4393.0.html
| Code: | void blitAlphaImageToScreen(int sx, int sy, int width, int height, Image* source, int dx, int dy)
{
if (!initialized) return;
sceKernelDcacheWritebackInvalidateAll();
guStart();
float u = 1.0f / ((float)source->textureWidth);
float v = 1.0f / ((float)source->textureHeight);
sceGuTexScale(u, v);
int j = 0;
while (j < width) {
Vertex* vertices = (Vertex*) sceGuGetMemory(2 * sizeof(Vertex));
int sliceWidth = 64;
if (j + sliceWidth > width) sliceWidth = width - j;
vertices[0].u = sx + j;
vertices[0].v = sy;
vertices[0].x = dx + j;
vertices[0].y = dy;
vertices[0].z = 0;
vertices[1].u = sx + j + sliceWidth;
vertices[1].v = sy + height;
vertices[1].x = dx + j + sliceWidth;
vertices[1].y = dy + height;
vertices[1].z = 0;
sceGuDrawArray(GU_SPRITES, GU_TEXTURE_16BIT | GU_VERTEX_16BIT | GU_TRANSFORM_2D, 2, 0, vertices);
j += sliceWidth;
}
sceGuFinish();
sceGuSync(0, 0);
} |
|
|
| Back to top |
|
 |
J.F.
Joined: 22 Feb 2004 Posts: 2906
|
Posted: Sat Jul 18, 2009 1:38 pm Post subject: |
|
|
| Set up the proper matrices, then use sceGumDrawArray instead of sceGuDrawArray. Look at the sprites sample. |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|