[solved] Issues with Transparent Texture in VRAM

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
centralunit
Posts: 4
Joined: Sun Nov 19, 2006 11:41 am

[solved] Issues with Transparent Texture in VRAM

Post by centralunit »

Greetings!

When I use a 128x128 transparent texture, staticly allocated in VRAM, I get 5-6 white line artifakts across the texture. However if I use the same texture in system ram it works perfectly. The format Im using is 4444, Ive also tried 8888 but same result.

I dont think it's an texture allocation problem since my other textures work like they should. Im mixing 5650 and 4444 textures. Ive tried to only have my transparent texture in VRAM but I get the same white artifakts.

I also don't think it's a cache flush problem since it's only my transparent texture that get these artifacts.

Im also using the PSPTexTool, created by Henrik Rydgård, to convert my png textures.

here is my code for GU Init

Code: Select all

m_pBackBuffer	= m_VRAM.getStaticVramBuffer( m_BufferWidth, m_ScreenHeight, GU_PSM_5650 );
m_pFrontBuffer	= m_VRAM.getStaticVramBuffer( m_BufferWidth, m_ScreenHeight, GU_PSM_5650 );
m_pZBuffer		= m_VRAM.getStaticVramBuffer( m_BufferWidth, m_ScreenHeight, GU_PSM_4444 );
m_pShadowMapTarget	= m_VRAM.getStaticVramTexture( 128, 128, GU_PSM_4444 );

sceGuInit();
sceGuStart( GU_DIRECT, GetDrawList() );
		
sceGuDrawBuffer( GU_PSM_5650, m_pBackBuffer, m_BufferWidth );
sceGuDispBuffer( m_ScreenWidth, m_ScreenHeight, m_pFrontBuffer, m_BufferWidth );
sceGuDepthBuffer( m_pZBuffer, m_BufferWidth );

sceGuOffset( 2048 - (m_ScreenWidth/2),2048 - (m_ScreenHeight/2) );
sceGuViewport( 2048,2048, m_ScreenWidth, m_ScreenHeight);
sceGuDepthRange( 65535,0 );
sceGuScissor( 0, 0, m_ScreenWidth, m_ScreenHeight );
sceGuEnable(GU_SCISSOR_TEST);
sceGuDepthFunc(GU_GEQUAL);
sceGuEnable(GU_DEPTH_TEST);
sceGuFrontFace(GU_CW);
sceGuShadeModel(GU_SMOOTH);
sceGuEnable(GU_CULL_FACE);
sceGuEnable(GU_TEXTURE_2D);
sceGuEnable(GU_CLIP_PLANES);

//	sceGuClutMode(GU_PSM_4444,0,255,0);
//	sceGuClutLoad(256/8,palette);

sceGuEnable(GU_LIGHTING);
sceGuEnable(GU_LIGHT0);
sceGuEnable(GU_LIGHT1);
		
sceGuFinish();
sceGuSync(0,0);

sceDisplayWaitVblankStart();
sceGuDisplay(GU_TRUE);

here is the code for uploading the texture to vram. Im doing this when I load my level. getStaticVramTexture is the same as in the sdk samples.

Code: Select all

void TextureManager::UploadTexture( unsigned int a_idTexture, bool a_bStatic )
{
	Texture* pTexture = m_vTexturePool[ a_idTexture ];

	if( a_bStatic )
	{
		pTexture->m_pVRAM = m_pVRAM->getStaticVramTexture( pTexture->m_ulCanvasWidth, pTexture->m_ulHeight, pTexture->m_Format );

		sceGuStart( GU_DIRECT, m_pDevice->GetDrawList() );

		sceGuCopyImage( pTexture->m_Format, 0, 0, pTexture->m_ulWidth, pTexture->m_ulHeight, pTexture->m_ulCanvasWidth, pTexture->m_pBuffer, 0, 0, pTexture->m_ulCanvasWidth, pTexture->m_pVRAM );			

		sceGuFinish();
		sceGuSync( 0, 0 );
	}
	else
	{
		pTexture->m_pVRAM = (void*) sceGuGetMemory( (pTexture->m_ulCanvasWidth*pTexture->m_ulCanvasHeight)*pTexture->m_bpp );
		sceGuCopyImage( pTexture->m_Format, 0, 0, pTexture->m_ulWidth, pTexture->m_ulHeight, pTexture->m_ulCanvasWidth, pTexture->m_pBuffer, 0, 0, pTexture->m_ulCanvasWidth, pTexture->m_pVRAM );
		sceGuTexSync();
	}
}

here is the code for activating the texture

Code: Select all

void TextureManager::SetTexture( unsigned int a_idTexture )
{
	Texture* pTexture = m_vTexturePool[ a_idTexture ];

	sceGuEnable( GU_TEXTURE_2D );
	sceGuTexFunc( GU_TFX_MODULATE, GU_TCC_RGBA );
	sceGuTexWrap( GU_REPEAT, GU_REPEAT );
	sceGuTexFilter( GU_LINEAR, GU_LINEAR );
	sceGuTexScale( 1.0f, 1.0f );
	sceGuTexOffset( 0.0f, 0.0f );

	if( pTexture->m_pVRAM != NULL )
	{
		sceGuTexMode( pTexture->m_Format, 0, 0, pTexture->m_bSwizzled );
		sceGuTexImage( 0, pTexture->m_ulCanvasWidth, pTexture->m_ulCanvasHeight, pTexture->m_ulCanvasWidth, pTexture->m_pVRAM );
	}
	else
	{
		sceGuTexMode( pTexture->m_Format, 0, 0, pTexture->m_bSwizzled );
		sceGuTexImage( 0, pTexture->m_ulCanvasWidth, pTexture->m_ulCanvasHeight, pTexture->m_ulCanvasWidth, pTexture->m_pBuffer );
	}
}

this is how I render the transparent objects.

Code: Select all


sceGuStart( GU_DIRECT, GetDrawList() );

sceGuClearColor( 0xff554433 );
sceGuClearDepth( 0 );
sceGuClear( GU_COLOR_BUFFER_BIT|GU_DEPTH_BUFFER_BIT );	

sceGuTexEnvColor( 0xffff00 );
sceGuAmbientColor( 0xffffffff );

sceGuSpecular(12.0f);
sceGuAmbient(0x00222222);

// Update camera
m_pCamera->Update( m_CellSelector.GetPos() );

sceGumMatrixMode(GU_MODEL);

sceGuDisable( GU_LIGHTING );
sceGuEnable( GU_BLEND );
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0 );		
sceGuTexFunc( GU_TFX_MODULATE, GU_TCC_RGBA );		
m_pTextureManager->SetTexture( 4 );

// Draw player X
for&#40; size_t i=0; i<m_PlayerXData.m_vOnCells.size&#40;&#41;; i++ &#41;
&#123;
         sceGumLoadIdentity&#40;&#41;;
	sceGumTranslate&#40; &m_PlayerXData.m_vOnCells&#91;i&#93;->m_vPos &#41;;
	sceGumDrawArray&#40; GU_TRIANGLES, GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_NORMAL_32BITF | GU_VERTEX_32BITF | GU_TRANSFORM_3D, m_PlayerXMesh.GetNumVerts&#40;&#41;, 0, m_PlayerXMesh.GetVertices&#40;&#41; &#41;;
&#125;

sceGuFinish&#40;&#41;;
sceGuSync&#40; 0, 0 &#41;;	

sceDisplayWaitVblankStart&#40;&#41;;
m_pBackBuffer = sceGuSwapBuffers&#40;&#41;;


Hope I have provided you all with usefull information. Tell me if I need to add something. Thanks in advance.

PS. Ill try to get a screenshot.

// CentralUnit
Last edited by centralunit on Mon Nov 20, 2006 10:45 pm, edited 1 time in total.
User avatar
Raphael
Posts: 646
Joined: Tue Jan 17, 2006 4:54 pm
Location: Germany
Contact:

Re: Issues with Transparent Texture in VRAM

Post by Raphael »

here is the code for uploading the texture to vram. Im doing this when I load my level. getStaticVramTexture is the same as in the sdk samples.

Code: Select all

void TextureManager&#58;&#58;UploadTexture&#40; unsigned int a_idTexture, bool a_bStatic &#41;
&#123;
	Texture* pTexture = m_vTexturePool&#91; a_idTexture &#93;;

	if&#40; a_bStatic &#41;
	&#123;
		pTexture->m_pVRAM = m_pVRAM->getStaticVramTexture&#40; pTexture->m_ulCanvasWidth, pTexture->m_ulHeight, pTexture->m_Format &#41;;

		sceGuStart&#40; GU_DIRECT, m_pDevice->GetDrawList&#40;&#41; &#41;;

		sceGuCopyImage&#40; pTexture->m_Format, 0, 0, pTexture->m_ulWidth, pTexture->m_ulHeight, pTexture->m_ulCanvasWidth, pTexture->m_pBuffer, 0, 0, pTexture->m_ulCanvasWidth, pTexture->m_pVRAM &#41;;			

		sceGuFinish&#40;&#41;;
		sceGuSync&#40; 0, 0 &#41;;
	&#125;
	else
	&#123;
		pTexture->m_pVRAM = &#40;void*&#41; sceGuGetMemory&#40; &#40;pTexture->m_ulCanvasWidth*pTexture->m_ulCanvasHeight&#41;*pTexture->m_bpp &#41;;
		sceGuCopyImage&#40; pTexture->m_Format, 0, 0, pTexture->m_ulWidth, pTexture->m_ulHeight, pTexture->m_ulCanvasWidth, pTexture->m_pBuffer, 0, 0, pTexture->m_ulCanvasWidth, pTexture->m_pVRAM &#41;;
		sceGuTexSync&#40;&#41;;
	&#125;
&#125;
I think you got something wrong about sceGuGetMemory and it's usage. It does not allocate memory in VRAM or sth alike. All it does is return a pointer into your drawlist of the given size (which lies in system memory and not in VRAM). This pointer then is only legal during the one sceGuStart/sceGuFinish block (unless you have a double-buffered drawlist). After that, the memory in that area is very probable overwritten by commands for GU (which could lead to artifacts), so it's generally bad to store your textures there. Apart from that, you waste a lot of time (and memory) copying your texture from one position in sysram to another one, which you anyway would need to do every frame.

So basically, your whole "non-static" case is ambigious and should be removed.
If you want dynamic textures in VRAM, you need a dynamic memory manager for it. Fortunately, I already wrote one quite some time ago (http://www.fx-world.org/wordpress/?p=13). You need to exchange your getStaticVramTexture and getStaticVramBuffer with valloc for it to work properly. Your texture then will stay 'static' as long as you don't vfree the pointer. Only problem left with dynamic VRAM textures then is to free their pointer after every drawing cycle (and catch the cases when the valloc fails because of insufficient VRAM), so you need to manage that properly.

Regards,
Raphael
<Don't push the river, it flows.>
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki

Alexander Berl
centralunit
Posts: 4
Joined: Sun Nov 19, 2006 11:41 am

Post by centralunit »

Hi Raphael, Thanks for your reply.

Yeah I know sceGuGetMemory only copy the texture to the displaylist. I only implemented this for test purpuse. I do not upload my textures during the game loop. I upload them (a_bStatic = true) when I load the level. Since I don't have that many textures this works for now.

Ive looked at your memory manager and good work on it. Ill probably use this when I have a more complex world that needs lots of textures.

But I still find it odd that only transparent textures get artifakts.
Ill try to find a host for my textures and screens so that I can show you.

// CentralUnit
centralunit
Posts: 4
Joined: Sun Nov 19, 2006 11:41 am

Post by centralunit »

Here is some screens.

Only have 1 transparent texture in VRAM, also using the posted code to draw it.
Image

All textures in VRAM
Image

All textures in VRAM except the transparent one
Image

Only transparent texture in VRAM rest in system.
Image


png of the transparent texture
Image

ptx file of the texture. non swizzled.
http://www.starman.nu/centralunit/MarkerX.ptx
rapso
Posts: 140
Joined: Mon Mar 28, 2005 6:35 am

Post by rapso »

try to copy the texture back to sysmem after some frames and use it, to see if it has been modified.
User avatar
Raphael
Posts: 646
Joined: Tue Jan 17, 2006 4:54 pm
Location: Germany
Contact:

Post by Raphael »

centralunit wrote:Hi Raphael, Thanks for your reply.

Yeah I know sceGuGetMemory only copy the texture to the displaylist. I only implemented this for test purpuse. I do not upload my textures during the game loop. I upload them (a_bStatic = true) when I load the level. Since I don't have that many textures this works for now.
So I am right to suppose that your textures don't end up in the drawlist, but atm only in VRAM (only the a_bStatic = true case occurs)?

Looking from the cases you showed, it seems that the upload to VRAM somehow creates those white lines in your transparent texture (3rd picture with trans texture not in VRAM does not show those lines).
I can not see any real reason for this, but I noticed you don't have a sceGuTexSync call after your static upload case. In theory this shouldn't be a problem, because the texture upload should be finished at least after the first few frames, but still it would be good habit to make sure all copying has finished before you make use of the textures.
Best would be to follow rapso's tip to check back the texture by downloading it back again from VRAM and check for consistency.
The white edges around your texture however seem independant of location of the texture, so it's more likely that your (transparent) image loader or the image converter is the source of the problem (though it's hard to see a pattern that could be caused by a faulty loader - the pattern is hardly resembled by any functional algorithm that could be used there).
BTW: Are the faces of the boxes all made up of two triangles, or more? IE, could the white corners be triangles that do not get textured due to some cause?
<Don't push the river, it flows.>
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki

Alexander Berl
rapso
Posts: 140
Joined: Mon Mar 28, 2005 6:35 am

Post by rapso »

Raphael wrote: The white edges around your texture however seem independant of location of the texture,
probably they're kinda selection markers :)
centralunit
Posts: 4
Joined: Sun Nov 19, 2006 11:41 am

Post by centralunit »

Thanks for all the replys.
try to copy the texture back to sysmem after some frames and use it, to see if it has been modified.
Good stuff Rapso, thanks for the tip.

So I am right to suppose that your textures don't end up in the drawlist, but atm only in VRAM (only the a_bStatic = true case occurs)?
Yes, you are right. Sorry If I confused you. I should have removed that code when I posted.
The white edges around your texture however seem independant of location of the texture, so it's more likely that your (transparent) image loader or the image converter is the source of the problem (though it's hard to see a pattern that could be caused by a faulty loader - the pattern is hardly resembled by any functional algorithm that could be used there).
zomg.. yeah, It was the image loader for png files that was the root of all evil.
BTW: Are the faces of the boxes all made up of two triangles, or more? IE, could the white corners be triangles that do not get textured due to some cause?
All the faces have two triangles. The white corners are actially a untextured separate mesh. I use it for selecting and moving around in the world. The X texture was a X shaped mesh from the beginning, so that I could create a shadowmap and project it on the ground but it didn't looked that good so I tossed that idea and that's when I started to use transparent textures intead.


----------

Last night I took a break from debugging and instead continued developing. I added more textures, meshes and gameplay. I also started to notice that the texture white lines started to spread to other non transparent textures.

I went through all my textures and loaders and found out that it was my font texture that I use for on-screen debugging that had been faulty allocated in the system ram. So it was only a freaky coincidence that it started to affekt transparent textures and nothing else.


Thanks Raphael and Rapso you all your work.

// CentralUnit.
Post Reply