Hi all,
this is my first post on the Code Project forums, since I'm using one of the tool posted here, I thought I should ask where the knowledge lies in order to solve my problem
the problem
In my 3d engine, each texture creation reserves 3 times the space it should need in memory.
Hypotheses
- 3d engine based on Loulou's YesEngine (here, in French)
- Runs on Windows Mobile 6.1 with Direct 3d Mobile (D3D subset)
- Windows Mobile is much restrictive concerning virtual memory (32MB against desktop's 2GB), so the heap is full pretty fast.
1st step: texture creation
IRscTextureBase* GDirect3DMRenderer::CreateTexture(const TVector2I& Size, TPixelFormat Format, unsigned long Flags) const
{
bool HasMipmaps = (Flags & TEX_NOMIPMAP) != 0;
bool AutoMipmaps = false;
unsigned long Usage = m_SurfCaps_Texture;
LPDIRECT3DMOBILETEXTURE Texture = NULL;
HRESULT hr;
if ( FAILED ( hr = D3DMXCreateTexture(m_Device, Size.x, Size.y, 0, Usage, CD3DMEnum::Get(Format), m_SurfCaps_Pool, &Texture) ) )
throw CD3DMException(_T("D3DXCreateTexture"), _T("CreateTexture"));
return new CD3DMTexture(Size, Format, HasMipmaps, AutoMipmaps, Usage, Texture);
}
D3DMXCreateTexture reserves memory space (ok), but new CD3DMTexture (simple object to encapsulate my D3DM texture) does the same ! We exit the function with 2 spaces reserved in memory instead of one.
reference :
class CD3DMTexture : public IRscTextureBase
{
public :
CD3DMTexture(const TVector2I& Size, TPixelFormat Format, bool HasMipmaps, bool AutoMipmaps, unsigned long Usage, IDirect3DMobileTexture* Texture);
IDirect3DMobileTexture* GetDxTexture() const;
private :
virtual void Update(const CRectangle& Rect);
void UpdateSurface(const D3DMLOCKED_RECT& LockedRect, const CRectangle& Rect);
CSmartPtr<IDirect3DMobileTexture , CResourceCOM > m_Texture;
unsigned long m_Usage;
};
2d step : texture update
A lot of devices (let's say Omnia) don't allow texture locking, thus we're forced to use surface locking, and then copy pixels from one surface to another... as follows :
void CD3DMTexture::Update(const CRectangle& Rect)
{
Assert(CRectangle(0, 0, m_Size.x, m_Size.y).Intersects(Rect) == INT_IN);
if (m_Format == m_Data.GetFormat() && (m_Usage & D3DMUSAGE_LOCKABLE) )
{
D3DMLOCKED_RECT LockedRect;
RECT Lock = {Rect.Left(), Rect.Top(), Rect.Right(), Rect.Bottom()};
m_Texture->LockRect(0, &LockedRect, &Lock, 0);
UpdateSurface(LockedRect, Rect);
m_Texture->UnlockRect(0);
}
else
{
CSmartPtr<IDirect3DMobileDevice, CResourceCOM> Device;
m_Texture->GetDevice(&GetPtr(Device));
CSmartPtr<IDirect3DMobileSurface, CResourceCOM> Src;
HRESULT res = Device->CreateImageSurface(Rect.Width(), Rect.Height(), CD3DMEnum::Get(m_Data.GetFormat()), &GetPtr(Src));
if (FAILED(res))
{
throw CD3DMException(_T("CreateImageSurface"), _T("CD3DMTexture::Update"));
}
D3DMLOCKED_RECT LockedRect;
Src->LockRect(&LockedRect, NULL, 0);
UpdateSurface(LockedRect, Rect);
Src->UnlockRect();
CSmartPtr<IDirect3DMobileSurface, CResourceCOM> Dest;
m_Texture->GetSurfaceLevel(0, &GetPtr(Dest));
RECT DestRect = {Rect.Left(), Rect.Top(), Rect.Right(), Rect.Bottom()};
if (FAILED(D3DMXLoadSurfaceFromSurface(Dest, NULL, &DestRect, Src, NULL, NULL, D3DMX_DEFAULT, 0)))
throw CD3DMException(_T("D3DXLoadSurfaceFromSurface"), _T("CD3DMTexture::Update"));
m_Texture->GetSurfaceLevel(0, &GetPtr(Dest));
IDirect3DMobileSurface_Release(GetPtr(Dest));
}
}
Src surface reserves the space needed during CreateImageSurface, then free it when we exit the brackets where it's defined (thanks smart pointer).
However, Dest does also a reservation about the same size during D3DMXLoadSurfaceFromSurface... but doesn't release it when the smart pointer is freed !
Conclusion
We have 3 times the needed space reserved by a texture, that other components of the program won't be able to use. With 32MB of virtual memory, I guess you already figured how painful it may be !
There shall be some stuff I messed up, or maybe is it due to the implementation of the YesEngine (encapsulating the D3D texture for instance ?) creating some conflict with D3DM data types... anyway...
Help !
Thanks for your help, may you be WM developer or not (it's after all only a subset of Windows API and DirectX )
ps: see here for more information about the well named "WM virtual memory monster" (and thanks a lot to it's author)
http://www.codeproject.com/KB/mobile/VirtualMemory.aspx
modified on Tuesday, August 18, 2009 4:46 AM
|