Samplers not being set in shader (WindowsGL)

I’ve been using FNA for a while in my project and recently switched back to MonoGame for 3.3. This caused my pixel shaders to stop working and I figured the textures I was setting to GraphicsDevice.Textures[] were no longer available in the shader. Here’s a brief example of what I’m doing:

C#

GraphicsDevice.Textures[1] = _renderTarget1;
GraphicsDevice.Textures[2] = Game.Content.Load<Texture2D>("Texture1");
GraphicsDevice.Textures[3] = _renderTarget2;
GraphicsDevice.Textures[4] = Game.Content.Load<Texture2D>("Texture2");

HLSL

sampler2D textureA      : register(s1);
sampler2D textureB	: register(s2);
sampler2D textureC	: register(s3);
sampler2D textureD	: register(s4);

I couldn’t reference the textures in the shader - tex2D returned nothing. I found that in EffectPass.SetShaderSamplers() the elements within the TextureCollection collection were being overwritten with NULL as the loaded Effect object didn’t have a texture in the Data property of the corresponding parameter. By placing a temporary NULL check around the texture assignment I’ve fixed my problem - the textures are no longer wiped and are available in the shader. I’ve not yet found the real cause of the issue but maybe someone who knows this area could advise on what’s happening here.

private void SetShaderSamplers(Shader shader, TextureCollection textures, SamplerStateCollection samplerStates)
    {
        foreach (var sampler in shader.Samplers)
        {
            var param = _effect.Parameters[sampler.parameter];
            var texture = param.Data as Texture;

            textures[sampler.textureSlot] = texture;

            // If there is a sampler state set it.
            if (sampler.state != null)
                samplerStates[sampler.samplerSlot] = sampler.state;
        }
    }

The same symptoms T_T

I suspect we fixed this in the 3.4 release:

https://github.com/mono/MonoGame/pull/3720

I’ve retested using latest develop - this problem is still occurring.

@tgjones - Does any of this sound familiar to you?

Yes, that sounds familiar :smile:

MonoGame now mimics XNA’s behaviour, as far as I know. The solution is to set the textures into effect parameter values, rather than setting them directly in GraphicsDevice.Textures. i.e. do this:

myEffect.Parameters["textureA"].SetValue(_renderTarget1);
myEffect.Parameters["textureB"].SetValue(Game.Content.Load<Texture2D>("Texture1"));
myEffect.Parameters["textureC"].SetValue(_renderTarget2);
myEffect.Parameters["textureD"].SetValue(Game.Content.Load<Texture2D>("Texture2"));

(Incidentally, your workaround is exactly what MonoGame used to do, but it didn’t match XNA’s behaviour. Again, as far as I can tell, based on exploratory unit testing. I’m happy to be proved wrong.)

@matt - Any chance of sharing a small test project that shows the behavior. We can then try running this on XNA and testing if it works or fails there.

Ok so I did what you suggested tgjones and it works fine. This approach resolves my issues and I’ve tested without my MG hack (checked out EffectPass.cs).

Tom I’ll look at doing that if it’s useful. The one thing I’m certain of is that with FNA that old approach does work where it no longer does in MonoGame.