Sign in to follow this  
th3matr1x

need some help with multithreaded texture loading

Recommended Posts

hi @ll I'm trying to load a texture with direct3d using the threading technique. I have a triangle with no texture on it, and when the user pressed a special button, it starts a thread wich loads my texture, and then i bin the texture to the triangle. Somehow it turned out to be not that easy and i don't know why, when i run the programm and start the thead, the texture is loaded properly, but i gut an unhandled exeption on this code : g_pVB->Lock( 0, i*sizeof(CUSTOMVERTEX), (void**)&pVertices, 0 ); here is how i start the thread: AfxBeginThread(WorkerThreadProc,m_pd3dDevice,THREAD_PRIORITY_IDLE,0,0,NULL); and here is the implementation of the thread: UINT WorkerThreadProc( LPVOID Param ) { LPDIRECT3DDEVICE9 m_pd3dDevice = (LPDIRECT3DDEVICE9) Param; if( FAILED(D3DXCreateTextureFromFile(m_pd3dDevice,"C:\\1280x960.jpg",&pPyramideTexture))) MessageBox(NULL,"Texture Loading Failed",MB_OK,MB_OK); else MessageBox(NULL,"Texture Loading Succeded",MB_OK,MB_OK); return TRUE; } Can someone help with this? thanx in advance.

Share this post


Link to post
Share on other sites
This is a very complicated thing to do correctly.

For starters, you need to initialize COM with the multi-threaded apartment model. COM is initialized for you by one of the first DirectX calls you make - the one that creates the initial Direct3D object factory. You have to supply the CoInitializeEx API call with the multi-threading flag.
I haven't used 9, but I think 8 had a flag you could pass to the initialization routine to tell it you wanted the free-threading version.

I'm assuming you had this working as a single-threaded version first? Just loading the thread inline? If not, get that working first.

How do you wait for the thread to finish its work before you bind the texture?

Share this post


Link to post
Share on other sites
I'm afraid that if you don't understand what was just posted (or read up on it so you do), then there is little that can be done to help you.

An example is far to big and complicated to come up with and post. If you had a problem with a specific thing - say D3D initialization - then perhaps we could help you (you might also improve your chances of recieving assistance if you spelled "you" correctly).

Anyway - go and do some reading and come back. I'll even highlight some key words to get you started:
Quote:
This is a very complicated thing to do correctly.

For starters, you need to initialize COM with the multi-threaded apartment model. COM is initialized for you by one of the first DirectX calls you make - the one that creates the initial Direct3D object factory. You have to supply the CoInitializeEx API call with the multi-threading flag.
I haven't used 9, but I think 8 had a flag you could pass to the initialization routine to tell it you wanted the free-threading version.

I'm assuming you had this working as a single-threaded version first? Just loading the thread inline? If not, get that working first.

How do you wait for the thread to finish its work before you bind the texture?


What you are trying to do is not exactly simple.

Share this post


Link to post
Share on other sites
It's true; using Direct3D from multiple threads is no small feat. The issue comes up because you are trying to use the Direct3D device in multiple threads. By default D3D is not initialized to do this. What the previous posters have writen about is how to correctly initialize Direct3D to support threads. It's still not as easy as just setting a flag, so here's another alternative.

I'm not sure what exactly you are trying to do, but could you try this? It doesn't provide all of the texture creation in a seperate thread, but it removes the need to run Direct3D in two threads:



// NOTE: a better mutex sychronization is needed here other than a bool value

unsigned char* g_pTextureBuffer = 0;
bool g_bTextureValid = false;
unsigned long g_uTextureBufferSize = 0;


mainThread()
{
HRESULT hResult;

AfxBeginThread(WorkerThreadProc, NULL,THREAD_PRIORITY_IDLE,0,0,NULL);

while ( g_bTextureValid == false )
{
Sleep( 0 );
}

// Now create the texture, in main thread, from the loaded data
hResult = D3DXCreateTextureFromFileInMemoryEx( g_pD3DDevice,
g_pTextureBuffer,
g_uTextureBufferSize,
D3DX_DEFAULT,
D3DX_DEFAULT,
D3DX_DEFAULT,
0,
D3DFMT_UNKNOWN,
D3DPOOL_DEFAULT,
D3DX_DEFAULT,
D3DX_DEFAULT,
0,
NULL,
NULL,
&pPyramideTexture );

assert( hResult == D3D_OK );

delete []g_pTextureBuffer;
g_pTextureBuffer = 0;
g_bTextureValue = false;
}


//
// Worker thread doesn't create the texture, but it does the costly loading
//


INT WorkerThreadProc( LPVOID Param )
{

FILE* fp = fopen( "C:\\1280x960.jpg", "wb" );


// Get the filesize
fseek( fp, 0, SEEK_END );
g_uTextureBufferSize = ftell( fp )
fseek( fp, 0, SEEK_SET );

// Allocate the buffer for the texture
g_pTextureBuffer = new unsigned char[ g_uTextureBufferSize ];

if ( fread( g_pTextureBuffer, sizeof( unsigned char ), g_uTextureBufferSize, fp ) != g_uTextureBufferSize )
{
// Error, data not read correctly
delete []g_pTextureBuffer;
fclose( fp );
return FALSE;
}

fclose( fp );

// Texture data is loaded now, signal to main thread
g_bTextureValid = true;

return TRUE;
}



In the above example, the load of the data is done in a seperate thread. Loading the data has no effect on Direct3D.

In the main thread, once it detects that the buffer for the texture is loaded, it creates the texture.

I grant you that you will still have a halt in your main thread, but it won't be as long as if you did all the work in your main thread.

It might be enough for your needs.

- S

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this