KNI engine

Hello! I have drawing layers. Each layer has its own RenderTarget2D. Each layer sets its rendertarget to the graphics device before drawing, and sets null at the end of drawing. Then all RenderTarget from each layer are drawn in turn. The problem is that I use two KNI projects: Windows and Desktops. Everything works fine only on Windows. If I run the project DesktopGL, then the first frame draws all my objects normally, and then the textures all disappear. And if I use a purely Monogame project, then there are no such problems there. Can you tell me what the problem might be?

Draw layer:

public RenderTarget2D RenderTarget2D;

public void Begin(RenderBatch spriteBatch, SpriteSortMode sortMode = SpriteSortMode.Deferred, BlendState blendState = null,
            SamplerState samplerState = null, DepthStencilState depthStencilState = null, RasterizerState rasterizerState = null,
            Effect effect = null, Matrix? transformMatrix = null)
        {
            graphicsDevice.SetRenderTarget(RenderTarget2D);

            graphicsDevice.Clear(Color.Transparent);
            spriteBatch.Begin(sortMode, blendState, samplerState, depthStencilState, rasterizerState, effect, transformMatrix);
        }

        public void Draw(RenderBatch spriteBatch)
        {
            for (int j = 0; j < _visibleComponents.Count; j++)
            {
                _visibleComponents[j].Draw(spriteBatch);
            }
        }
        public void End(RenderBatch spriteBatch)
        {
            spriteBatch.End();
            graphicsDevice.SetRenderTarget(null);
        }

Draw all layers:

foreach (var layer in layers)
            {
                if(camera != null)
                {
                    if (!camera.Layer.HasFlag(layer.Key))
                        continue;

                    matrix = camera.Projection;
                }

                RenderComponents renderComponents = layer.Value;

                // The layer code is executed here
                renderComponents.Begin(spriteBatch, SpriteSortMode.FrontToBack, null, null, null, null, null, matrix); 
                renderComponents.Draw(spriteBatch);
                renderComponents.End(spriteBatch);

            }

            GraphicsDevice.Clear(Color.CornflowerBlue);

            // Here we draw each RenderTarget from each layer with Position zero and Color.White
            foreach (var item in layers.Values)
            {
                spriteBatch.Begin(SpriteSortMode.Immediate);
                spriteBatch.Draw(item.RenderTarget2D);
                spriteBatch.End();
            }

@nkast Since it’s his engine.

What’s KNI engine?

It’s a fork of MonoGame. Not sure what’s different. Perhaps performance improvements?

How does this line work?

We do not know if the issue has anything to do with rendertargets or is something else.

For example we do not know with what parameters you create the rendertargets, if you are ‘eating’ exceptions, if matrix is set, or any other logical error.

You have to start reducing your code down to a workable test case.
Usually by the time you are halfway in the process you will discover the bug yourself.

This is with the latest version 3.8.9201, correct?

The following is the working test code based on what I can make out from the code you posted.
It’s working fine on my desktop machine.

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;


namespace Benchmarks
{
    public class TestComponent : DrawableGameComponent
    {
        SpriteBatch _spriteBatch;
        Texture2D _tx;
        RenderTarget2D _rt0;
        RenderTarget2D _rt1;

        public TestComponent(Game game) : base(game)
        {
        }

        protected override void LoadContent()
        {
            _spriteBatch = new SpriteBatch(GraphicsDevice);
            _tx = Game.Content.Load<Texture2D>("Tx");

            _rt0 = new RenderTarget2D(GraphicsDevice, 256, 256, true, SurfaceFormat.Color, DepthFormat.Depth24Stencil8, 0, RenderTargetUsage.DiscardContents);
            _rt1 = new RenderTarget2D(GraphicsDevice, 256, 256, true, SurfaceFormat.Color, DepthFormat.Depth24Stencil8, 0, RenderTargetUsage.DiscardContents);
        }

        public override void Draw(GameTime gameTime)
        {
            Matrix? transformMatrix = Matrix.Identity;

            // layer 0
            GraphicsDevice.SetRenderTarget(_rt0);
            GraphicsDevice.Clear(Color.Transparent);
            _spriteBatch.Begin(SpriteSortMode.FrontToBack, null, null, null, null, null, transformMatrix);
            _spriteBatch.Draw(_tx, new Vector2(0, 0), Color.White);
            _spriteBatch.End();
            GraphicsDevice.SetRenderTarget(null);

            // layer 1
            GraphicsDevice.SetRenderTarget(_rt1);
            GraphicsDevice.Clear(Color.Transparent);
            _spriteBatch.Begin(SpriteSortMode.FrontToBack, null, null, null, null, null, transformMatrix);
            _spriteBatch.Draw(_tx, new Vector2(100, 0), Color.White);
            _spriteBatch.End();
            GraphicsDevice.SetRenderTarget(null);

            // draw layers
            GraphicsDevice.Clear(Color.CornflowerBlue);

            _spriteBatch.Begin(SpriteSortMode.Immediate);
            _spriteBatch.Draw(_rt0, Vector2.Zero, Color.White);
            _spriteBatch.Draw(_rt1, Vector2.Zero, Color.White);
            _spriteBatch.End();
        }
    }
}

Ah I see it has a web solution. Will check it out.

1 Like

        public virtual void Draw(Texture2D texture)
        {
            spriteBatch.Draw(texture, Vector2.Zero, Color.White);
        }

Version 3.8.9201

How created rendertarget:


            RenderTarget2D = new RenderTarget2D(graphicsDevice, graphicsDevice.Viewport.Width, graphicsDevice.Viewport.Height);

My apologies. I checked the code without using RenderTarget2D - the problem is the same, only the first frame draws everything, and the next frames do not. I’m trying to figure it out. A little later I will write about the result of the work.

1 Like

Thanks for the test project Besopozzz.

It’s a bug in DrawUserPrimitives.

It detach the IndexBuffer, but it doesn’t set the _indexBufferDirty.
In fact, we don’t need to detach the indexBuffer. DrawArrays(…) operate on the VertexBuffer alone.

DrawUserPrimitives is used by the Physics2D.Diagnostics, so for now you would need to disable it until the next version.

2 Likes

Thanks! Temporarily disabling Physics2D.Diagnostics allows me to see textures. I will be waiting for an update.

1 Like