Loading Mesh in a different thread problem

Started by
4 comments, last by dmc2005 16 years, 8 months ago
Hi, I have a 3d directx c# screensaver that shows a nice object and some realtime monitoring information about servers and visitors. Currently i'm trying to switch the current rendered object with another one. This works fine but i want this process in a background thread. When i'm trying to do this in a background thread while rendering i'm getting an error on the beginscene(); I'm using the following situation.


private void LoadNextObject()
{
loadThread = new Thread(new ThreadStart(LoadObjectTask));
loadThread.Start();
}


private void LoadObjectTask()
{
LoadTmpMesh(m_oFramework.Device, MainApp.InstallPath + "Data/" + meshes[new_mesh] + ".obj", MainApp.InstallPath + "Data/" + meshes[new_mesh] + ".shd");
}


private void  LoadTmpMesh(Device device, string meshFileName, string resultsFileName) 
{

newmeshloading = true;

    prtMeshTmp.LoadMesh(device, meshFileName);

    prtMeshTmp.LoadCompPrtBufferFromFile(resultsFileName);

    prtMeshTmp.ExtractCompressedDataForPrtShader();

    prtMeshTmp.LoadEffects(device, device.DeviceCaps);

newmeshloaded = true;

}

In the main render loop i have something like.

public void SceneMainRender(Device device, double appTime, float elapsedTime){

 if (newmeshloading )
 {
 RenderLoadingScreen(device, appTime, elapsedTime);
 }
 else
 {
 RenderMesh(device, appTime, elapsedTime);
 }

}

private void RenderLoadingScreen(Device device, double appTime, float elapsedTime)
{

bool beginSceneCalled = false;

device.Clear(ClearFlags.ZBuffer | ClearFlags.Target, System.Drawing.Color.FromArgb(0, 200, 200,100), 1.0f, 0);


 device.BeginScene();  // <--- Exception on this line after few sec.
 beginSceneCalled = true;

 // Loadingstuff

 if (beginSceneCalled)
 device.EndScene();


}

At the line device.BeginScene(); i get the following error. -20005530516 (D3DERR_INVALIDCALL) on Microsoft.DirectX.Direct3D.Device.BeginScene(); Anybody has a clue what's i'm doing wrong. When i don't render anything everything works fine only when i'm trying to render while the thread is running it works for a few seconds and sometimes it works without an error but most of the time it crashes. I use more threading operations (getting xml files from the internet) while rendering that runs fine but they aren't that heavy as this one and doesn't need the device. I use managed Directx Version 1.0.2911.0 Greetings, Dmc
Advertisement
Are you using D3DCREATE_MULTITHREADED? If not then that's the first thing to do.

The other thing you'll need to do is make sure that you're not rendering the mesh during the load. As you don't seem to set newmeshloading to false anywhere, that could be your problem.

Also make sure that newmeshloading is declared as volatile since you access it on both threads.
Yes i use the following for threading.

settings.BehaviorFlags |= CreateFlags.MultiThreaded;

For the loading of the second mesh i use 2 mesh objects so the second mesh can be loaded while the first is still rendered. All works if don't use threads but since i want a dynamic loading screen while the first mesh is still rendering i need this in a different thread.

I think the problem is more that i use the device also in the other thread.

I made some modifications and the crash/error occurs now every +/- 6 times. 5 times it goes well. So it looks idd like a memory problem.

This mesh loading problem in an other thread is not the only problem.

Currently i'm loading the whole application in a single thread with a loading screen. Takes about 10 seconds to load. But since the whole application hangs while loading i wanted to also load everything in an other thread so the loading screen would run smooth. But this also results in the same error on BeginScene().

While rendering i use 2 other threads every 1 minutes that downloads 2 xml files reads them and fills arrays. That works fine.

But the mesh loading seems to be a bit more complex.


D3DERR_INVALIDCALL isn't the error message. You'll want to enable the debug runtimes to get the correct error message from DX.

the Forum FAQ has information on how to enable the Debug Runtimes.
Sirob Yes.» - status: Work-O-Rama.
Yepz your right. My project got messed up a month ago and only got alert boxes with debug info. But after your post and an hour of searching i'm finnaly managed to got my correct debug info back.
But it doesn't show much better (Invallid call Exception on the same line) and now sometimes device.EndScene() too.

Well i'm a bit further now. The main problem seems to be the line with

prtMeshTmp.LoadEffects(device, device.DeviceCaps);

Without that line i don't get any errors. Still dont know why its particular this function it's crashing on.

Still everthing runs fine now 70% of the time.
But an application running fine and then not gives me the creeps :P

But all information you guys provided made me a few steps further so thx already.
Well i just removed the loadeffects and put it outside the thread since it only takes 0.1 sec loading time and everything is stable again. So it works fine now.

For your information the loadeffects is part of the PRTPerVertex example in the directx SDK.

The function contains the following.

    public void LoadEffects( Device device, Caps caps)        {            int numberChannels      = prtCompBuffer.NumberChannels;            int numberClusters      = prtCompBuffer.NumberClusters;            int numberPcaVectors    = prtCompBuffer.NumberPcaVectors;            // The number of vertex consts need by the shader can't exceed the             // amount the HW can support            int numberVConsts = numberClusters * (1 + numberChannels * numberPcaVectors / 4) + 4;            if( numberVConsts > caps.MaxVertexShaderConst )                throw new PrtMeshException("Number of Vertex shader constants cannot exceed the amount the Hardware can support");            if(prtEffect != null)            {                prtEffect.Dispose();                prtEffect = null;            }            if(shIrradEnvMapEffect != null)            {                shIrradEnvMapEffect.Dispose();                shIrradEnvMapEffect = null;            }            if(ndotlEffect != null)            {                ndotlEffect.Dispose();                ndotlEffect = null;            }            Macro[] defines = new Macro[3];            string maximumNumberClusters = string.Format( "{0}", numberClusters );            string maximumNumberPcaVectors = string.Format("{0}", numberPcaVectors );            defines[0].Name = "NumberClusters";            defines[0].Definition = maximumNumberClusters;            defines[1].Name = "NumberPcaVectors";            defines[1].Definition = maximumNumberPcaVectors;            defines[2].Name = String.Empty;            defines[2].Definition = String.Empty;            // Define DEBUG_VS and/or DEBUG_PS to debug vertex and/or pixel shaders with the shader debugger.              // Debugging vertex shaders requires either REF or software vertex processing, and debugging             // pixel shaders requires REF.  The "ShaderFlags.Force{Pixel/Vertex}ShaderSoftwareNoOptimizations" flag improves the debug             // experience in the shader debugger.  It enables source level debugging, prevents instruction             // reordering, prevents dead code elimination, and forces the compiler to compile against the next             // higher available software target, which ensures that the unoptimized shaders do not exceed             // the shader model limitations.  Setting these flags will cause slower rendering since the shaders             // will be unoptimized and forced into software.  See the DirectX documentation for more information             // about using the shader debugger.            ShaderFlags shaderFlags = ShaderFlags.NotCloneable;            #if(DEBUG_VS)                shaderFlags |= ShaderFlags.ForceVertexShaderSoftwareNoOptimizations;            #endif            #if(DEBUG_PS)                shaderFlags |= ShaderFlags.ForcePixelShaderSoftwareNoOptimizations;            #endif                    // Read the effect file            string mediaFileLongName = Utility.FindMediaFile(MainApp.InstallPath + "Data/Effects/PRTColorLights.fx");            // If this fails, there should be debug output            // that the .fx file failed to compile            string errors;            prtEffect = Effect.FromFile(device, mediaFileLongName, defines, null, null, shaderFlags, null, out errors);            if ( (errors != null) && (errors.Length > 0) )                throw new InvalidOperationException(errors);                        // Make sure the technique works on this card            prtEffect.ValidateTechnique("RenderWithPrtColorLights");            mediaFileLongName = Utility.FindMediaFile(MainApp.InstallPath + "Data/Effects/Lightning.fx");            ndotlEffect = Effect.FromFile(device, mediaFileLongName, null, null, shaderFlags, null);            mediaFileLongName = Utility.FindMediaFile(MainApp.InstallPath + "Data/Effects/Mapping.fx");            shIrradEnvMapEffect = Effect.FromFile(device, mediaFileLongName, null, null, shaderFlags, null);        }

This topic is closed to new replies.

Advertisement