[SOLVED]GPU Buffer more than one Texture at the Time

Hey Guys,

i saw the idea from nkast to use more than one Texture on the GPU: Dictionary and Texture2D instances as a key.
I implemented all of it with a Cloned Monogame Repo but i don’t get the Shader to work, if i apply my Shader it Shows nothing:
Here is my Shader:

    if OPENGL
        #define SV_POSITION POSITION
        #define VS_SHADERMODEL vs_3_0
        #define PS_SHADERMODEL ps_3_0
    else
        #define VS_SHADERMODEL vs_4_0_level_9_1
        #define PS_SHADERMODEL ps_4_0_level_9_1
    endif

    float4x4 MatrixTransform;

    sampler Texture : register(s0);
    sampler Texture1 : register(s1);
    sampler Texture2 : register(s2);
    sampler Texture3 : register(s3);
    sampler Texture4 : register(s4);
    sampler Texture5 : register(s5);
    sampler Texture6 : register(s6);
    sampler Texture7 : register(s7);
    sampler Texture8 : register(s8);
    sampler Texture9 : register(s9);
    sampler Texture10 : register(s10);
    sampler Texture11 : register(s11);
    sampler Texture12 : register(s12);
    sampler Texture13 : register(s13);
    sampler Texture14 : register(s14);
    sampler Texture15 : register(s15);


    struct VertexShaderInput
    {
        float4 position    : POSITION0;
        float4 color : COLOR0;
        float3 texCoord : TEXCOORD0;
    };

    struct VertexShaderOutput
    {
        float4 position     : SV_Position;
        float4 color        : COLOR0;
        float3 texCoord     : TEXCOORD0;
    };

    VertexShaderOutput SpriteVertexShader(in VertexShaderInput input)
    {
        VertexShaderOutput output = (VertexShaderOutput)0;
        output.position = mul(input.position, MatrixTransform);
        output.color = input.color;
        output.texCoord = input.texCoord;
        return output;
    }

    float4 SpritePixelShader(VertexShaderOutput input) : COLOR0
    {
        if (input.texCoord.z <= 7)
        {
            if (input.texCoord.z <= 3)
            {
                if (input.texCoord.z <= 1)
                {
                    if (input.texCoord.z == 0)
                        return tex2D(Texture, input.texCoord.xy) * input.color;
                    else
                        return tex2D(Texture1, input.texCoord.xy) * input.color;
                }
                else
                {
                    if (input.texCoord.z == 2)
                        return tex2D(Texture2, input.texCoord.xy) * input.color;
                    else
                        return tex2D(Texture3, input.texCoord.xy) * input.color;
                }
            }
            else
            {
                if (input.texCoord.z <= 5)
                {
                    if (input.texCoord.z == 4)
                        return tex2D(Texture4, input.texCoord.xy) * input.color;
                    else
                        return tex2D(Texture5, input.texCoord.xy) * input.color;
                }
                else
                {
                    if (input.texCoord.z == 6)
                        return tex2D(Texture6, input.texCoord.xy) * input.color;
                    else
                        return tex2D(Texture7, input.texCoord.xy) * input.color;
                }
            }
        }
        else
        {
            if (input.texCoord.z <= 11)
            {
                if (input.texCoord.z <= 1)
                {
                    if (input.texCoord.z == 8)
                        return tex2D(Texture8, input.texCoord.xy) * input.color;
                    else
                        return tex2D(Texture9, input.texCoord.xy) * input.color;
                }
                else
                {
                    if (input.texCoord.z == 10)
                        return tex2D(Texture10, input.texCoord.xy) * input.color;
                    else
                        return tex2D(Texture11, input.texCoord.xy) * input.color;
                }
            }
            else
            {
                if (input.texCoord.z <= 13)
                {
                    if (input.texCoord.z == 12)
                        return tex2D(Texture12, input.texCoord.xy) * input.color;
                    else
                        return tex2D(Texture13, input.texCoord.xy) * input.color;
                }
                else
                {
                    if (input.texCoord.z == 14)
                        return tex2D(Texture14, input.texCoord.xy) * input.color;
                    else
                        return tex2D(Texture15, input.texCoord.xy) * input.color;
                }
            }
        }
    }


    technique BasicColorDrawing
    {
        pass Pass0
        {
            VertexShader = compile VS_SHADERMODEL SpriteVertexShader();
            PixelShader = compile PS_SHADERMODEL SpritePixelShader();
        }
    }

My new Spritebatch:

    public SpriteBatch(GraphicsDevice graphicsDevice,Effect effect)
    {
        if (graphicsDevice == null)
        {
            throw new ArgumentNullException("graphicsDevice", FrameworkResources.ResourceCreationWhenDeviceIsNull);
        }

        this.GraphicsDevice = graphicsDevice;

        _spriteEffect = new SpriteEffect(graphicsDevice);
        _spriteEffect.CurrentTechnique = effect.CurrentTechnique;
        _spritePass = _spriteEffect.CurrentTechnique.Passes[0];

        _batcher = new SpriteBatcher(graphicsDevice, 0);

        _beginCalled = false;
    }

And my new Draw is like in the link from nkast: https://github.com/MonoGame/MonoGame/compare/develop...nkast:tnc_SpriteBatch_Texturebatch

Please reformat the code using the preformated text button.

Sorry for that, i clicked first on the preformated text button and than paste the code in, that’s why it don’t formated it :confused:

one of the times were prototyping with a switch case in hlsl would make a world of difference.

    float index = floor(input.texCoord.z);
    // hope the index value will get pre-optimized somehow.
    switch (index)
    {
        case 0:
            return tex2D(Texture, input.texCoord.xy) * input.color;
            break;
        case 1:
            return tex2D(Texture1, input.texCoord.xy) * input.color;
            break;
        case 2:
            return tex2D(Texture2, input.texCoord.xy) * input.color;
            break;
        case 3:
            return tex2D(Texture3, input.texCoord.xy) * input.color;
            break;
        // ect... ect...
    }

There is no point in doing any booleen math here as it’s a ton of look ups.

Boolean tricks are only good for when you are trying to prevent a branch on a calculation or would rather straight do a couple look ups then branch at all.

With 16 textures if that many branches happen you are hit.
You had better pray the hlsl switch will do some optimizations under the hood ahead of time.

Thats nice for more performance (thanks), I’m new with Shader and for my game i have with 4-5 Texture sheets still many Gpu swaps.
For example i swap the Textures every time a different Units is next to another(they will be all animated in future.)


And the Tiles behind have also height, so they also swap very often from TileAtlats to UnitAtlas in the Spritebatch:

I read about the Shader from nkast, to set more than one Texture to the GPU: https://github.com/MonoGame/MonoGame/compare/develop...nkast:tnc_SpriteBatch_Texturebatch1

But i cant get it work, i already changed the Spritebatch and the Spritebatcher like he did but somehow the shader not working correctly or i miss something.

I got with the Switch case a error: in ps_3_0 uints can only be used with known-positives values,use int if possible. In line with the Code: switch (index)
Also i got still no texture Showing up from my shader, only if i assign a Matrix as Parameter it shows big Pixels like in the Image

Are you testing this on a DirectDX or openGL project?
The shader worked on DX. Often a shader need some minor changes here and there to make it work on both platforms.

Im testing with openGL, here it dont work. I have never worked with shader before maybe you can help me out whats wrong with it with openGL, maybe some tipps in the right direction. Thanks! Also it was nice to find your Code, i just want o test it if it improves my rendering for my needs in the Game i do. :slight_smile:

OK never mind the Shader was Correct but i forgot to set the MatrixTransform right, i forgot that in the Spritebatch the transformMatrix was calculated like: transformMatrix.Value * _projection. Sorry for the mistake i did there.