|
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
|
|
|
|
|
Are you sure that it is reserved 3 times ? I would guess it is "only" two times:
When you create your texture and pass it to the CD3DMTexture constructor, the pointer will be passed to the the smart pointer, which doesn't make a copy of the pointed object. Thus, you do not duplicate the texture.
MMoi wrote: 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 :
For that part, I can't really help: I never really worked with DirectX before.
|
|
|
|
|
First, thanks a lot Cedric for your quick answer
We agree, it should not reserve it again since I'm juste passing the pointer to a smart pointer. But... it does !
I tried using a simple pointer instead of a smart pointer in CD3DMTexture, but same result
Actually, as soon as I create a new CD3DMTexture instance anywhere in the CreateTexture function of my renderer (didn't try to do it in another place yet), there is a memory reservation the same size than the texture.
Could be also an glitch in the VirtualMemory tool, but still the effect of the virtual memory is felt since the application crashes when I put a little too much textures in it (comment the texture part and my app works as a charm, and VirtualMemory feels happy to show me I didn't use much resource in that case).
Thanks again, still looking for the Grail
|
|
|
|
|
|
Hi all,
I have made a list control in which i am displaying thumbnails of my pictures saved. My problem is once the thumbnail count reaches to 1000 or above and i open window above my dialog box all my thumbnails disappears i.e my list control seems to be empty. Firstly i thought it might be a repaint problem so i opened several other windows and moved my dialog box also but not a single thumbnail reappeared again....
I am not getting what has happened either my image list is being deleted or what...
Can anybody help me in this...
Thanks in advance
|
|
|
|
|
HI all,
i m using sleep function to generate delay in application but its becomes unresponsive all application.
so please tell me there is any other option that is use in place of Sleep.
thanks in advance.
To accomplish great things, we must not only act, but also dream;
not only plan, but also believe.
|
|
|
|
|
|
You can use MsgWaitForMultipleObjects[^].
This function returns when a message comes into the message queue.
Specify the bWaitAll parameter as FALSE .
For the pHandles parameter you can create a waitable timer using CreateWaitableTimer[^].
You can check the return value to find if the function returned because of a timeout or an event.
If it returned because of an event, retrieve the message using GetMessage[^] and use DispatchMessage[^] to send it to the window procedure for processing.
«_Superman_»
I love work. It gives me something to do between weekends.
|
|
|
|
|
What exactly is the purpose of adding a delay to your application? How long do you want it to sleep? And how are you certain about the time, if it is a fixed number?
It is a crappy thing, but it's life -^ Carlo Pallini
|
|
|
|
|
Probably you've to generate the intended delay in a worker thread. Anyway You should be more specific to obtain better help.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
"_$h@nky_" wrote: i m using sleep function to generate delay in application...
Which is usually the result of a bad design. Adding gratuitous calls to Sleep() is hardly ever a solution.
"Old age is like a bank account. You withdraw later in life what you have deposited along the way." - Unknown
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
|
|
|
|
|
If periodic action is required and a 1-5ms delay is permissible, look at SetTimer().
|
|
|
|
|
thats really fine the Sleep() works.
use SetTimer() and in OnTimer(9 you can handle the stuff to do.
Press F1 for help or google it.
Greetings from Germany
|
|
|
|
|
Hi all,
I m using a Dialog Box,here i m using One ListCtrl,some editboxes,OK and Cancel Button.
i also Change the Default Button property of the Okay button from "True" to "False".
In ListCtrl i m inserting some values,i want when i press enter over listctrl the the values of selected item display in edit boxes,its works but ok button call automatically when i enter on ListCtrl.
i want if i click on ListCtrl than ok button not called.
please help me for this.
thanks in advance.
To accomplish great things, we must not only act, but also dream;
not only plan, but also believe.
|
|
|
|
|
Overwrite OnOK, in this, use GetFocus() to check if your list has focus or not, if yes, don't call CDialog::OnOK().
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
> Life: great graphics, but the gameplay sux. <
|
|
|
|
|
A piece of code that worked a dream under XP, but breaks under Vista. The Licence checking software for my code needs to find the serial number of the physical drive from which the application is launched. I Do this in the Following Steps:-
Step1: Use 'GetModuleFileName' to retrieve the app path, and hence the ligical drive. (Typically 'C:'), and running from Network Drives is Not Allowed under the license terms.
Step2: Get a Handle to the logical drive (say C using:
CreateFile("\\\\.\\\\C:",....);
Step3: Use:
DeviceIoControl(h,IOCTL_STORAGE_GET_DEVICE_NUMBER,...)
to retrieve the Physical Drive Number.
Step4: Get a Handle to the Physical Device, using CreateFile
Step5: Use:
DeviceIoControl (hPhys, IOCTL_STORAGE_QUERY_PROPERTY,..)
To retrieve a Datablock from which the serial number can be retrieved.
As said, everything works fine under XP, but it breaks at Step2 with Vista. CreateFile returns -1, even if I reduce the Security of the volume to 'Full Control by All Users'!
Step4+5 etc work fine, and appear not to be affected by the security considerations. I guess that the trick lies in submitting an appropriate security descriptor. Anyone Any Idea How??
Regards,
Bram van Kampen
|
|
|
|
|
You have to have admin privs to open a physical drive or volume. Since you don't have admin privs by default in Vista, you get an access denied error opening \\.\C:
--Mike--
Dunder-Mifflin, this is Pam
|
|
|
|
|
Michael Dunn wrote: You have to have admin privs to open a physical drive or volume
Hmm. Does one get Admin Privs when running in Safe Mode? If so, that would explain why everything works as advertised in Safe Mode.
Amazingly I found no difficulty opening the Physical Drive. The program fails because I try to open the Logical Drive in order to find out what physical drive it is mounted on.
Is there anything I can do with lpSecurityDescriptor, so that the operation acts as if the user has admin privileges. After all, I can open and display the drive from Windows Explorer, without having Admin Privs.
Failing that, is there a way of setting things up to get the thing to start up in Admin mode by default. In the home edition at least, it just seems to start up without asking for logon and password.
Thanks and Regards,
Bram van Kampen
|
|
|
|
|
|
Well, turning off UAC shouldn't be the first thing you do, since it disables the major security feature in Vista. The proper solution is to have the relevant code run elevated. You can a) mark the executable as requiring admin privs using a manifest, or b) move the license-checking code into a COM object, compile that into a separate DLL, and request elevation when you create the COM object.
--Mike--
Dunder-Mifflin, this is Pam
|
|
|
|
|
Hi,
Sorry for the delay.
I see your point vividly, but switching UAC off leaves the user no worse off than when using XP. Also, NONE of the computers on which the software is running is connected to the internet. However, in the medium term, the use of a manifest would be the better option.
I've spent till now trying to investigate what form such manifest should take. Got no further on this though. Any suggestions, or maybe you have a 'template' I could use.
Regards,
Bram van Kampen
|
|
|
|
|
I've not tried this specifically for a logical drive, but I used a similar license enforcement scheme using a combination of other hardware serial numbers using WMI (Windows Management Instrumentation) and it appears to work correctly on 2000, XP, Vista, etc...
Maybe try:
"Win32_LogicalDisk","VolumeSerialNumber"
|
|
|
|
|
Hello people!
I am pondering into the unknown (by me) here so i am not sure if what i am asking now actually makes sense or not, but i though i ask anyways, maybe some of you can give me an answer.
So, importing a class from a DLL, i have seen that you can use __declspec(dllimport) to be able to use a class implemented in a DLL, something like:
class __declspec(dllimport) CImportClass
{
...method and variable declarations
}; I supose on the other end of the world, the DLL exports this class somehow. So, my question would be, can i import this class into my program "as a differently named class". I mean, the DLL exports CImportClass , but in my program i want to import it as COtherImportClass . Would i be able to import this class multiple times with different names too, CFirstImportClass and CSecondImportClass , both having the same implementation of CImportClass sitting in the DLL? Sounds ugly, i know.
Thanks in advance for any answers, folks!
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
> Life: great graphics, but the gameplay sux. <
|
|
|
|
|
No, cannot be done.
The whole Import-Export Mechanism relies on the consistency of the'Mangled' Names being identical in the app where you call the imported function or oject, and the DLL which exports same. Matt Pietreck has several excelent articles on how dynamic linking works. Read them, and you understand why.
From what you describe, I guess that you are trying to do something that would be more appropriately done by derriving several classes in your app, from the baseclass in your DLL.
Regards,
Bram van Kampen
|
|
|
|
|
Thanks!
Thought i try to explain what i thought of doing. I am writing a DLL and when i tried to use std::basic_string in it i got two unresolved external symbols, _String_base::Xlen and _String_base::Xran. I googled around quite a bit and found out some usefull things, however, the possible solutions i found (reorder the include directories e.g.) either did not make any difference or i did not like them. Mostly people hit this when migrating a project from VS2003 to VS2005 and up, however, i am simply writing a program (not migrating anything) in VS2003 and chanhing to a different VS version is not an option right now.
So, what i have found out is that the problem is caused by mismatching calling conventions. The header file (xstring.h i believe) declares the 2 methods as __thiscall, that is, they are two member methods of __Basic_string, however, the library or DLL (am not sure which here) exports these as static, __stdcall methods, thus, they "can't find each other". So i thought, i could maybe implement the __thiscall versions in my code and in them call the __stdcall versions and live happily ever after. But how i would gain access to the __stdcall versions i don't know, if i could have tricked the system by importing the class with a different name from the DLL (since __Basic_string is already declared i can't use that, and i do not wish to modify xstring.h since that would be ugly at least) i could have declared in this class the __stdcall versions and then call them from the __thiscall versions.
Now i am wondering if i could write a lib file i can link to which imports the right class from the DLL (with the __stdcall versions), exposes two methods for Xran and Xlen (which call their static class member counterparts) and then in my program i could call these in the implementations of the __thiscall versions.
There might be a very simple solution for this which i have simply missed or do not (yet) have enough knowledge (as i said, exporting/importing classes in DLLs is still new to me) to realize and i am re-inventing the wheel.
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
> Life: great graphics, but the gameplay sux. <
|
|
|
|
|