need some help with multithreaded texture loading

Started by
3 comments, last by Sphet 18 years, 10 months ago
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.
I love programming
Advertisement
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?
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
i didn't really understood what u mean, could u please help me with one example? would be cool
I love programming
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.
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 valueunsigned 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

This topic is closed to new replies.

Advertisement