-
|
|
Texture2D.Sample returns Black, not White, if no texture...
|
In Dx9, OpenGL, etc., if there was no texture assigned to a Sampler, it returned white. DX10, returns black.
What this means, is that shaders need to account for whether there is/isn't a texture and causes a TON of extra processing which slows DX10 down. The workaround solutions we currently have thought of is to -
- Use a 1x1 white texture as a default texture. Problem here, is every texture layer always has a texture assigned.
- Use multiple techniques for each material, which support any combination of textures. With just supporting 4 texture layers, that's an INSANE number of techniques, and causes slowdowns on the CPU, as it has to pick the proper technique based on which texture(s) are present.
- We could use a bitmask, in the pixel shader, but this causes extra processing on the CPU, more bandiwidth, as we need an extra value passed to every shader, and a lot more processing in the GPU, as each pixel has to determine which texture(s) are present, and act accordingly.
None of these would be required, if `Texture*D.Sample` would just return WHITE, instead of BLACK. Is this a bug? Is it going to be changed? Is it a driver problem (I have an OCZ GF8800GTX with driver 169.25)?
|
|
-
|
|
Re: Texture2D.Sample returns Black, not White, if no texture...
|
Returning zero is the defined Direct3D 10 behavior for reading from empty slots. Therefore it would not change.
|
|
-
|
|
Re: Texture2D.Sample returns Black, not White, if no texture...
|
I understand that, but why? The various workarounds I mentioned above cause significant slowdowns. This makes DX10 slower, in fact, in my tests, OpenGL and DirectX9 outperform DX10 by a significant amount, if I use complex materials with multiple textures that may or may not be present. If you use simple materials with no textures, or textures that always exist, then the performance gap is closed.
Again, I know this is the default/defined behavior, but IMO, it's wrong.
|
|
-
|
|
Re: Texture2D.Sample returns Black, not White, if no texture...
|
Why would white be any more correct than black? DirectX has always been this way AFAIK. Really they're being pretty nice considering you're sampling from an unbound sampler.
You should just set boolean flags to say whether or not to sample from a particular sampler or not. Yes this means a tiny bit more work on the CPU, but that cost is almost nothing in reality.
|
|
-
|
|
Re: Texture2D.Sample returns Black, not White, if no texture...
|
Rory:Why would white be any more correct than black? DirectX has always been this way AFAIK. Really they're being pretty nice considering you're sampling from an unbound sampler.
You should just set boolean flags to say whether or not to sample from a particular sampler or not. Yes this means a tiny bit more work on the CPU, but that cost is almost nothing in reality.
Here's why White is better : Consider the most basic Pixel Shader like so -
float4 PS_WithTexture( VS_OUTPUT input ) : SV_Target { return tex1.Sample( samplerTex1, input.TexCoord0 ) * input.Color; } If tex1 is not a valid texture, and it returns white (i.e. float4( 1.0, 1.0, 1.0, 1.0 ) ), then the result would simply be input.Color. If black is returned (i.e. float4( 0.0, 0.0, 0.0, 0.0 ) ), then the result is always 0,0,0,0 or black, regardless of the input.Color (which would be the interpolated vertex color). All versions of Directx I've ever used ( 8 and 9 ) returned white, which gave you the vertex color by default.
Now, as far as this tiny bit of of on the CPU, that's if using multiple techniques. However, consider materials that support any combination of up to 8 textures, that's what, 256 techniques for all possible texture combinations!!! So the answer is to have 256 techniques per Shader? No, that's not acceptable.
My question is this, if the shader is going to work with no texture, then why change from returning white (which AFAIK all previous version of DirectX and even OpenGL did/does), to returning black? There is no benefit of returning black, so why change?
Can you provide any reason why returning black is better than white?
|
|
-
|
|
Re: Texture2D.Sample returns Black, not White, if no texture...
|
I'm not saying black is better than white, I'm just saying that it's not really clear what is correct since you are doing something which doesn't really have any clear expected behavior. If you declare an int variable in C++, then read it, do you expect it to be a certain value?
I could give an equally valid pixel shader where I want to add or subtract using the texture sample, and so black would be better for an unbound sampler. I can how you'd want white in a lot of situations though.
I'm not saying you need to support all permutations of the number of textures, just to set a variable which says whether the sampler has been bound or not. So your loop in code would be something like:
for (int i = 0; i < numTextures; ++i) { constants.validSamplers[i] = textures[i] != NULL; }
Then in your shader, you would just declare an array of bools (one for each sampler which you use), when you sample your texture, just use a function like this instead:
float4 SampleTexture(int index, float2 texcoord) { return validSamplers[index] ? textures[index].Sample(samplers[index], texcoord) : 1; }
Obviously you don't have to use arrays if you don't want to. Something like this should be minimal on the CPU, and not require you to write many permutations of your shaders.
Rory
|
|
-
|
|
Re: Texture2D.Sample returns Black, not White, if no texture...
|
Simply......bad idea. You're suggesting the solution to be an extra boolean check. Given a screen resolution of 1920x1200, and a 50% fill rate, that's an extra 1,152,000 boolean checks, per frame. That's horrendous. Even at 800x600, that's 240,000 extra boolean checks, and that's if you're only supporting 1 texture. What if you're supporting 8 textures, that's 9 million extra boolean comparisons at 1920x1200 per frame, or 1.5 million extra at 800x600. Say bye to performance.
I'm maintain an an engine, that is attempting to add support for DX10 (it's proving to be a nitemare in many respects). That engine needs to provide default materials. Having to support things like this (which I already do with poor performance) makes DX10 rendering much slower than DX9 and OpenGL.
This means people are going to use DX9 or OpenGL, because it's faster, much faster. So then why put the effort into DX10 if it's going to be slower? Geometry Shaders are not a good enough reason, especially when these advanced features are going to be available in OpenGL, without Vista and with much better performance.
|
|
-
|
|
Re: Texture2D.Sample returns Black, not White, if no texture...
|
Look man, I'm trying to help you here. I suggest you go and find out what static branching is. It won't have to evaluate the branch for every fragment because it will take the same side of it every time (within one render call). It's really cheap.
|
|
-
|
|
Re: Texture2D.Sample returns Black, not White, if no texture...
|
The Spintz:
- Use a 1x1 white texture as a default texture. Problem here, is every texture layer always has a texture assigned.
I don't see the problem with this approach, but perhaps I'm just not understanding you clearly. If you don't have a texture bound to a particular slot, it should be relatively straightforward to bind a default one.
|
|
|