HLSL losing vertex elements?

Could it have anything to do with the ā€œlocationā€ field of the VertexAttributes? When I poked around at the internal variables in the GraphicsDevice and shader, it found that the VertexAttributes have the following ā€œlocationā€ field values:

Position: 0
Normal: 3
Binormal: -1
Tangent: -1
TextureCoordinate: -1

I have no idea what these values are used for, nor whence they came, but none of the other effects Iā€™m using have a negative location (or anything other than 0, really). Could this have something to do with it?

Edit: Ran it again, and found these locations:

Position: 0
Normal: -1
Binormal: -1
Tangent: -1
TextureCoordinate: 4

It will use 0 as index if you donā€™t specify any. [quote=ā€œed022, post:4, topic:7724ā€]
even with these semantics changed as described above
[/quote]
Itā€™s really weird that that makes a difference. There should be no problem with using 3 normal semantics with a different index.

Try adding

    [StructLayout(LayoutKind.Sequential, Pack = 1)]

above the definition of your custom VertexType. It might fix the ordering. Though I thought it was sequential by default, so it might not fix it.

Nah, that didnā€™t make any difference. =/ But thanks for the suggestion.

I donā€™t know for sure if the -1 location is indeed the cause, but it seems like a likely culprit. Looking at Monogameā€™s source, it seems to come from being read in from the compiled shader code directly. I also donā€™t know where else it is used. However, if that is indeed the problem, itā€™s coming from the shader compiler.

I removed all but two of the vertex attributes (in both the shader and the vertex declaration) - Position and TexCoord. The location issue (if it was an issue at all) resolved, but my shader in general is still not working; itā€™s as though the texture coordinates are (0, 0) at every point, although the incoming vertex data has valid coordinates.

Now Iā€™ve replaced my custom vertex structure with the default VertexPositionNormalTexture, and the same things are happening, both in terms of the VertexAttributeā€™s ā€œlocationā€ field (if relevant) and the data coming in as zero. Therefore, I infer that it must be a problem with the shader or its compilation, as these are where both of these remaining issues would reside.

Are you using a non-ancient version of MG? If so, the issue is most likely on your side. Could you show the parts of your code where you set the parameters for the shader, set the data in the vertex buffer and also how you draw your model. I think there must be some kind of mistake in one of those parts of your code.

Hmm, alright, thanks, Iā€™ll poke at it some more. Iā€™ll try isolating the draw to see if thereā€™s a conflict arising somewhere else.

Ok, Iā€™m still utterly baffled, perhaps now more than before. It seems that something decidedly bizarre is going on.

Iā€™ve traced it down to a single line of code - a GraphicsDevice.DrawUserIndexedPrimitives - that, if I comment it out, everything works just fine; subsequent draws have the proper incoming TexCoords, Normals, etc. However, if I leave the aforementioned line in, the later draw in question seems to have all of its incoming vertex data as zero, even though no other code changes, the offending line is never called again in between, and there are three other sets of SetRenderTarget and Clear in between these two. How can this be? =O The only connection I can see between these two seemingly conflicting draws are that theyā€™re using the same effect, but why would a DrawUserIndexedPrimitives change its behaviour? Even the EffectPass.Apply doesnā€™t seem to affect it.

DirectX or OpenGL? It would be useful if you can show a bit more code of how you handle the effect and drawing, like the failing draw calls and initialization you do before that.
Seems this might be a bug after allā€¦

OpenGL.

My code is spread out over several classes, methods, and files, but here is the sequence of events (so I donā€™t have to send my entire program:

Exhibit A:

        public override void Prepare(Level level)
        {
            Camera.GraphicsDevice.SetRenderTarget(backbuffer);
            Camera.GraphicsDevice.Clear(Color.Black);
            level.DrawHighlight();
            base.Prepare(level);
        }

Within level.DrawHighlight:

            foreach (IDrawable d in AllObjectsToBeDrawn(0, float.PositiveInfinity))
            {
                Camera.GraphicsDevice.DepthStencilState = DepthStencilState.None;
                Camera.GraphicsDevice.BlendState = BlendState.AlphaBlend;
                d.DrawSilhouette(Camera, this);
                Camera.GraphicsDevice.DepthStencilState = DepthStencilState.None;
                Camera.GraphicsDevice.BlendState = BlendState.Additive;
                d.DrawHighlight(Camera, this);
            }
            Camera.GraphicsDevice.DepthStencilState = DepthStencilState.Default;

In one of the IDrawables to be drawn: (which, mind, is not an XNA IDrawable, but rather an interface of my own):

        public override void DrawSilhouette(Camera camera, Level environment)
        {
            Vector3 backup = DiffuseColour;
            DiffuseColour = Vector3.Zero;
            ApplyStandardParameters(effect, environment);
            effect.World = World;

            camera.ApplyParameters(effect);
            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Apply();
                //This is the line that, if uncommented, prevents vertex data from working later on
                //Camera.GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionNormalsTexture>(PrimitiveType.TriangleList, vbuf, 0, vbuf.Length, ibuf, 0, ibuf.Length / 3);
            }
            DiffuseColour = backup;
        }
        protected void ApplyStandardParameters(ObjectEffect effect, Level environment)
        {
            effect.Mode = ObjectEffect.Modes.Standard;
            effect.World = World;
            effect.Alpha = Alpha;
            effect.DiffuseColour = DiffuseColour;
            effect.FogColour = environment.FogColour;
            effect.FogDistance = environment.FogDistance;
            effect.FogEnabled = environment.FogEnabled;
        }

In the Camera class:

        public void ApplyParameters(ObjectEffect effect)
        {
            effect.View = View;
            effect.Projection = Projection;
        }

And later, Exhibit B:

        public void PrepareLightMap()
        {
            Camera.GraphicsDevice.BlendState = BlendState.AlphaBlend;
            Camera.GraphicsDevice.SetRenderTarget(Camera.LightMap);
            Camera.GraphicsDevice.Clear(new Color(LightColour));

            IEnumerable<IDrawable> objects = AllObjectsToBeDrawn(0, float.PositiveInfinity);
            foreach (IDrawable d in objects)
                d.DrawToLightMap(Camera, this);
        }

And in the same IDrawableā€™s DrawToLightMap method:

            ApplyLightMapParameters(effect, Level);
            effect.NormalMap = normalmap;
            effect.LightDirection = new Vector3(0, .5f, .866f);
            camera.ApplyParameters(effect);
            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Apply();
                //This is the call that seems to be lacking its incoming vertex data (apart from Position)
                Camera.GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionNormalsTexture>(PrimitiveType.TriangleList, vbuf, 0, vbuf.Length, ibuf, 0, ibuf.Length / 3);
            }

And its ApplyLightMapParameters:

        protected void ApplyLightMapParameters(ObjectEffect effect, Level environment)
        {
            effect.Mode = ObjectEffect.Modes.LightMap;
            effect.World = World;
            effect.Alpha = Alpha;
            effect.LightColour = environment.LightColour + EmissiveColour;
            effect.ShadowColour = environment.ShadowColour;
            effect.ShadowMap = environment.Camera.GetShadowMap(Z);
        }

I think thatā€™s all the relevant bits. O.o But as you can see, in between the two draws, Iā€™m setting effect parameters, setting CurrentTechniques (which occurs with the effect.Mode property), setting RenderTarget, and clearing the graphics device; I figured this would be enough to completely separate the two instances, let alone such odd vertex behaviour.

The shader code is effectively the same as in my original posts, but I now have it just returning float4(input.TexCoord, 0, 1), which comes out in many colours when itā€™s working properly, and solid blue when itā€™s not.

This is really weridā€¦ Are you doing this in DirectX or OpenGL? Edit: Oops, didnā€™t see you already mentioned that!
So it looks like some state of the graphicsdevice or something else gets changed by the first DrawUserIndexedPrimitives and not overwritten by the second one, though thatā€™s very weirdā€¦ You could try debugging the VertexDeclaration.Apply calls. As the DrawUserIndexedPrimitives call is causing the issue, it looks like that is the place were something might go wrong.

How do we go about debugging this? Is it something I should do personally, or can we somehow raise the issue to those managing the project? As you can see, and as it seems you agree, I really donā€™t think itā€™s something that Iā€™m doing wrong. =I

You can debug this by getting the source code and switching out the MG reference in your game for the source project, then you can step through and put breakpoints. Youā€™re right that this might be a bug, so it seems like a good idea to open an issue on GitHub. Itā€™s probably fastest if you can figure it out yourself though.

Ok, thanks. =)
Iā€™ll confess that Iā€™m still a bit of a noob when it comes to Monogame (been developing in XNA for nearly a decade though)ā€¦ can you point me to where/how I can obtain the source?

Thereā€™s a guide in the readme on GitHub :slight_smile:

This issue just reared its ugly head once again in a different place. Calling upon DrawUserIndexedPrimitives in one method whilst preparing back textures prevented the TexCoords from being properly passed into another technique of the same effect later on, despite being drawn to a different (and cleared) RenderTarget2D. That seems to be the common cause. Iā€™d propose that perhaps it was optimising out those vertex elements, but theyā€™re used in both techniques; besides, that wouldnā€™t make sense anywayā€¦

I opened an issue on GitHub. Any idea how long it takes for them to notice these?

THIS JUST IN

I went back to the effect Iā€™d been working on the previous week, and, on a whim, decided to change the vertex shader and pixel shader target versions. Apprently it works properly if the techniques compile to different target versions. O.o Iā€™d been compiling to vs_2_0 all along; if I change ONE of the techniques to vs_3_0, then it works, but if I change two to vs_3_0, then the second of which doesnā€™t work again. I wonder if that will help to trace the errorā€¦?

I hate to pester, but, any updates on this? Iā€™m reluctant to continue working on this project as long as this error persists. I added some additional information in the github thread https://github.com/mono/MonoGame/issues/4909.

I found the root of the problem; whomever it may concern, please take a look at it in the thread linked above.

1 Like

Hey @ed022, in case you check this before GitHub, I set up a PR with the fix following your suggestion. Sorry for the incredible slowness and thanks for the help :slight_smile: