How to create a depth-stencil-only pixel shader?

Started by
7 comments, last by Husbj 8 years, 6 months ago

I am having some issues setting up a pixel shader for use with a depth-only pass (rendering shadow maps).
The reason I am at all using a pixel shader for this is so that I can sample the diffuse texture and clip if on a sufficiently transparent pixel.

Here is my incredibly simple pixel shader:


void PS_DepthOnly(vs_depth_out IN) {
	clip(DiffuseMap.Sample(DiffuseSampler, IN.texcoord).a - 0.1);
	return;
}

Now this all works as intended, but the debug layer is complaining about the pixel shader expecting a render target to be bound to slot zero.
I have in fact intentionally unbound any render targets prior to drawing using the above pixel shader; I set it to have a void type, which I was under the impression would mean that it would not write to any render target. But this doesn't seem to be the case. Am I missing something here?

Now I know that I can just disable the warning, but it seems like it is actually trying to write something to the render target, while I was hoping it would be possible to bypass that part alltogether?

Advertisement

You can set a render target for it and set the write mask so that output is disabled, that's what I did in my engine.. :D

.:vinterberg:.

That could work yes... but it feels like a pretty cheap workaround :p

Is it really not supposed to be possible; how could a void pixel shader possibly write to a render target? Or is it just the debug layer erroneously reporting that line without there actually being any (discarded but still) writes?

So let me ask a simple question, since clip just discard pixel whose values are less than 0, where should that pass that test go ? Write mask is not a cheap work-around as that is the intented purpose of that feature. As long a your pixel shader is producing output you need somewhere to store the result i.e your render target. AFAIK there is no such thing as a pixel shader that produces no output. The fix-function stages after the pixel shader can be configured such that the result of running the pixel shader is not realized ( visible output in the attached rendertarget ), as well a using some form of fragment discard. However, the only such a fragment shader would be correct is if all fragments are discard, since it would be a blatant error to be producing output when there is no rendertarget, in which case, why do you need a pixel shader ?

Are you positive you've bound the right shader? I've done this plenty of times and never recall getting such a warning from the debug layer.

Adam Miles - Principal Software Development Engineer - Microsoft Xbox Advanced Technology Group

Now this all works as intended, but the debug layer is complaining about the pixel shader expecting a render target to be bound to slot zero.

That means one of the shaders is trying to use SV_Target.
Likely something you missed to unbind, or you didn't realize it was using SV_Target. Anyway, use RenderDoc to quickly figgure out what shaders are being used.

So let me ask a simple question, since clip just discard pixel whose values are less than 0, where should that pass that test go ? Write mask is not a cheap work-around as that is the intented purpose of that feature. As long a your pixel shader is producing output you need somewhere to store the result i.e your render target. AFAIK there is no such thing as a pixel shader that produces no output. The fix-function stages after the pixel shader can be configured such that the result of running the pixel shader is not realized ( visible output in the attached rendertarget ), as well a using some form of fragment discard. However, the only such a fragment shader would be correct is if all fragments are discard, since it would be a blatant error to be producing output when there is no rendertarget, in which case, why do you need a pixel shader ?

It's perfectly valid to not return anything if the only thing bound is a depth buffer: the result of the clip decides whether to write to it or not (commonly used for shadowmaps).

I'm not sure if a void return type is valid in older shader models (3.0-), but it definitely works in newer ones (4.0+).


So let me ask a simple question, since clip just discard pixel whose values are less than 0, where should that pass that test go ?

These are just early tests, that shader may or may not be how it will look in the end, just my first guess since I don't really have anything more than trial-and-error to go by. The intention is that transparent (enough) pixels should not make it into the depth map, hence I went with the same way you do for normal alpha tests. For meshes that don't use semi-transparent textures it is my understanding that it should be fine to bind a null pixel shader to bypass all this overhead you're mentioning; I mean to try this once I get this general-purpose (transparency supporting) version functional.

Of course this might be the wrong approach to achieving my desired results, if that is the case I'd be more than happy for some pointers on what to try next.

Are you positive you've bound the right shader? I've done this plenty of times and never recall getting such a warning from the debug layer.

I'm quite positive but I will have a look at that again when I get home!

Edit: I didn't see the new posts before posting this, that sounds promising; maybe I have indeed just some mesh accidentally being rendered with another shader. We shall see smile.png

Right, it turns out I accidentally had set a normal rendering shader to a billboard instead of this depth one, so that was indeed trying to write to SV_Target. How embarrasing. On the upside, no more warnings now that I have fixed that oversight!

Thanks a lot for pointing it out ajmiles and Matias Goldberg :)

This topic is closed to new replies.

Advertisement