• Advertisement
Sign in to follow this  

Device Context Question

This topic is 1645 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

So, 

 

My app has been working fine as long as I was drawing one kind of object. Now that I'm trying to draw a second object with a different shader my app is crashing the system. It occurred to me that I still have all the old stuff, like the old hull shader, on my device context that's not being used for the new object. I need to clean up my device context after each set of similar draw calls... right? 

 

I tried the ClearState function before setting up for a draw call, but that eliminates my viewports also. I don't want to go that far so that I have to set my viewports multiple times per frame.

 

Should I set all my shaders on the device context to null after my drawing is done for a particular object?

 

For example, I was drawing a tesselated object, and now in the same frame I want to draw a series of lines with a different set of shaders. How is this transition normally handled?

Share this post


Link to post
Share on other sites
Advertisement

ClearState is too drastic, yes, but I sometimes use it as a quick hack during  debugging/testing/researching to get rid of inconsistencies . Actually the latter should show up as errors/warnings in the debug log (if the device was created with debug info).

 

I still use the effect framework which simplifies things, but even so I sometimes have to manually clear shaders (set to null). For your current problem it sounds like you have to clear all tesselation shaders. No need to set everything to null first though.

Edit: Clarification. Only at the moment you draw (or dispatch) something, your shader pipe has to make sense, no sooner.

 

Another common source of problems is when you try to bind a resource for both input and output, which the pipeline doesn't allow. It won't "crash" though, but the pipeline will nullify such an attempt. Unbind a resource first, then bind it elsewhere.

 

You got more info about that crash ?

Edited by unbird

Share this post


Link to post
Share on other sites

 

 

You got more info about that crash ?

 

Well, I haven't actually explored the cause. I'm still just theorizing. What happened was that everything froze, including my mouse pointer. Had to reset the machine. When I tried using ClearState, it didn't crash the whole system, the debugger stopped when I tried to get some viewport information.

 

There's a lot of stuff that might need resetting though. For example, I also use a texture in my tessellated stuff, but no texture in the lines I'm trying to draw. If I reset the pixel shader to a different one, will it still try to bind the old resource and sampler to new pixel shader, or does it automatically throw that stuff out?

 

I can kind of have things set up in an XNA sort of way where I have drawable game components that have their own independent drawing routines. I need a best practice to prevent the different components from stepping on each others device contexts. I'm not sure I'm always going to know which component draws first or what the immediate context's state is going to be. I can do that with 2 components I suppose, but it might be hard to manage when there's 20. Some of these components might be reusable in the far distant future, ya know when I'm CEO and founder of a game company that puts out 3 games per year..... yeah. 

Share this post


Link to post
Share on other sites

Wait! Are you using multithreading and/or deferred contexts ?

No. Strait single threaded. I do not understand deferred contexts and I'm not ready for that. Hisssss.

Share this post


Link to post
Share on other sites
Neither am I. wink.png
 
Strange. Because your description: "stepping on each others device contexts" sounds like so and the system-wide freeze smells like some really bad stuff (e.g. a hard to track race condition or something).
 
Since you say no, I can only suspect some driver issue. Because issuing your pipeline setup and drawing one after the other (your components) in the main thread should really pose no problem - and give proper debug feedback.
 
Sounds like you need to go the log-file and comment/uncomment debug route then. With the current information I can't provide any better idea. sad.png
 
Edit

There's a lot of stuff that might need resetting though. For example, I also use a texture in my tessellated stuff, but no texture in the lines I'm trying to draw. If I reset the pixel shader to a different one, will it still try to bind the old resource and sampler to new pixel shader, or does it automatically throw that stuff out?


That should be no problem whatsoever, really. If the pixel shader doesn't use a resource, then it doesn't matter what you set into that slot.

As for your problem: Just a gut feeling: Disable any D3D 11.1 related stuff first (from our PM discussion you mentioned you use it for D2D interop or something).
And to exclude a driver issue: Test with the reference device and/or with different hardware. Edited by unbird

Share this post


Link to post
Share on other sites

So, 

 

My app has been working fine as long as I was drawing one kind of object. Now that I'm trying to draw a second object with a different shader my app is crashing the system. It occurred to me that I still have all the old stuff, like the old hull shader, on my device context that's not being used for the new object. I need to clean up my device context after each set of similar draw calls... right? 

 

I tried the ClearState function before setting up for a draw call, but that eliminates my viewports also. I don't want to go that far so that I have to set my viewports multiple times per frame.

 

Should I set all my shaders on the device context to null after my drawing is done for a particular object?

 

For example, I was drawing a tesselated object, and now in the same frame I want to draw a series of lines with a different set of shaders. How is this transition normally handled?

Just turn off anything that you do not need to render the second object.

Share this post


Link to post
Share on other sites

I haven't had a chance yet to mess with it, as the crash occured right before I had to stop for the day. But what would one expect to happen if I am leaving my hull shader in the device context, and passing it garbage data with my line drawing vertex shader? I wouldn't be too surprised to see a system crash. I'll try to clean that up manually tomorrow.

Share this post


Link to post
Share on other sites

It still shouldn't crash that badly IMO. Mismatching data between shader stages should be reported, though. With the effect compiler such things turn up at shader compilation time, with raw shaders you will receive an "linkage" error at draw time.

 

Again: Try the reference device.

Share this post


Link to post
Share on other sites

Ok, after trying the ref device, the only error reported was related to the hull shader that shouldn't be there. Getting rid of unneeded shaders fixed the crash. Naturally, the line drawing I was trying to do was way off the mark, but it's the first time I looked at it. Nothing is ever right the first run.

 

What I take from this is that, when you are drawing objects in a component like fashion where other things are also drawn, you should set all unused shaders to null in case some other component is setting them.

Share this post


Link to post
Share on other sites
Glad to hear it's working. Also be glad you didn't have to go the tedious log-file route or something.
 
Slightly related, I think Jason's journal entry about state monitoring is worth a read. 
 

Nothing is ever right the first run.

 
It happens. But veeeery rarely wink.png


Edit: Since you got such a bad behavior for linkage errors it is probably convenient to detect them early on. You could for instance (ab)use effect compiling, even if you don't use effects, given your shaders are in the same file.
Example:
float4 VS(float4 position: POSITION): SV_Position
{
    return position;
}

float4 PS(float4 position: SV_Position, float4 color: COLOR) : SV_Target
{
    return color;
}

technique11 BadLinkage
{
    pass p0
    {
        VertexShader = compile vs_4_0 VS();
        PixelShader = compile ps_4_0 PS();
    }
}

Both the following will compile, since both shaders are valid (and the technique11 entry doesn't disturb at all).
fxc.exe /T vs_4_0 /E VS shaders.fx
fxc.exe /T ps_4_0 /E PS shaders.fx

The following, however:
fxc.exe /T fx_5_0 shaders.fx
yields this:

D3DEffectCompiler: ERROR: No valid VertexShader-PixelShader combination could be found in Technique BadLinkage, Pass p0.
compilation failed; no code produced

Share this post


Link to post
Share on other sites

Ok, I found the bug related to my line drawing and it is related to this topic. My new constant buffer had the projectionView matrix and a translation vector. I had forgotten to set the constant buffer in my line drawing component, and what happened was that, even though I set new shaders for the new component, the old constant buffer was still available and in use.

 

I was very confused at first because I was assuming that my new constant buffer was being updated, since the projectionView matrix was rotating things just fine, but my translation vector was not working. It turns out that I was using the projectionView matrix from my other constant buffer which was still set! Since the translation vector did not exist in my old buffer, it was just set to zero.

 

So it turns out that you can set a new shader, but all the other stuff attached to it is still attached and treated separately. If you think about it, I guess it needs to be that way.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement