Reading C# ushort in HLSL Float is wrong in Monogame 64 bit compilation

Here is my Shader code for Kinect Depth processing,

PixelShaderOutput PixelShaderFunction(VertexShaderOutput input)
{
	PixelShaderOutput pixOut;

	float2 posUV = float2((input.Tex.x * xScale) - xPos, 
                                            (input.Tex.y * yScale) + yPos);
		// Get the source pixel color		
	float4 ActColor = tex2D(ColorSampler, input.Tex);
	float4 Depth = tex2D(DepthSampler, posUV);

//Here Depth value of Depth.a and Depth.r component are fine,
// But Depth.g and Depth.b values are not as expected.
// I used the same code in XNA 4.0 everything was working fine,
// Now I am porting everything to MONO 64 bit, I think the problem is with 64 bit

	pixOut.depth = depthUV(Depth);
	pixOut.color = ActColor;

	return pixOut;
}

You’ve provided shader code, but the title mentions C# ushort. There’s probably a whole lot more here that you haven’t told us.
What values do you expect?
What surface format is the depth buffer?
How are you providing the depth buffer to the shader?

Thanks for your quick response,

C# Code,

//Declaration of Texture Depth Texture,
`this.kinectDepthTexture = new Texture2D(this.Game.GraphicsDevice, 512, 424, false, SurfaceFormat.Bgra4444);`

//Setting Data to to Texture both for Color and Depth,
public void CPUtoGPU()
{
    this.colorTexture.SetData<byte>(this.colorData);
    this.kinectDepthTexture.SetData<ushort>(this.DepthData);           
}

//Passing it to GPU when Drawing,
    SetShaderParameters(ShaderWorld, CommonInstance.CommonObjects.Instance.View, CommonInstance.CommonObjects.Instance.Projection);
    outlineShader.Parameters["DepthSampler"].SetValue(kinectDepthTexture);
    this.SharedSpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, null, null, this.outlineShader);
    this.SharedSpriteBatch.Draw(colorTexture, new Vector2(-this.colorTexture.Bounds.Center.X, -this.colorTexture.Bounds.Center.Y), Color.White);
    this.SharedSpriteBatch.End();

.fx Code,

PixelShaderOutput PixelShaderFunction(VertexShaderOutput input)
{
	PixelShaderOutput pixOut;
	
	// Get the source pixel color		
	float4 ActColor = tex2D(ColorSampler, input.Tex);
	float4  Depth = tex2D(DepthSampler, input.Tex);

	pixOut.depth = depthUV(ActColor);
	pixOut.color = Depth;

	return pixOut;
}

the code is used in both XNA 4.0 32 bit and MonoGame 64 bit [Current Porting] it gives different output like this,
XNA-> https://drive.google.com/open?id=0B2mcA8D9Coj7V204eVg2Rk1PNUk

MONO -> https://drive.google.com/open?id=0B2mcA8D9Coj7UjhVdnoyVm9TQnM

That certainly does look like it is not handling the SetData<ushort>(this.DepthData) correctly. Looking into it now.

Thanks a lot KonajuGame.

Looking forward to your reply!

There is something odd. Haven’t worked it out yet. I’m falling asleep here, so I’ll get back onto it tomorrow night.

No worries! Good night!

KonajuGames looking forward to your reply !!

Are you building from source? I have a quick fix that should work for you.

In MonoGame.Framework/Windows8/SharpDXHelper.cs around line 68, change

#if WINRT
            case SurfaceFormat.Bgra4444:
                return SharpDX.DXGI.Format.B4G4R4A4_UNorm;
#endif

to

            case SurfaceFormat.Bgra4444:
#if WINRT
                return SharpDX.DXGI.Format.B4G4R4A4_UNorm;
#else
                return (SharpDX.DXGI.Format)115;
#endif

If you can give that a try, then I’ll look at a more permanent solution.

Hi KonajuGames,

Thanks a lot for your effort. I have compiled the Monogame.Framework with this workaround as you said.

Now its working nicely as I expected same as XNA.

I can happily wait for the official commit.

Thank a lot, the porting of my application is almost done now and I found one more issue,

Which is resizing renderTarget to draw in respect to Window Size using SpriteBatch,

//This is not drawing proper cropped output in Mono, But gave perfect output on XNA 4.0
        spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Opaque);
        spriteBatch.Draw((Texture2D)renderTarget, new Rectangle(0, 0, ScreenSizeW, ScreenSizeH), new Rectangle(540, 0, 840, 1080), Color.White);
        spriteBatch.End();

//This is drawing the full renderTarget nicely, But I dont want full rendertarget,
        spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Opaque);
        spriteBatch.Draw(renderTarget, Vector2.Zero, Color.White);
        spriteBatch.End();

Please let me know have you got any idea about this!

Thanks a lot once again!

I’ll need some more information here.

  • What is the output you expect to see?
  • What size is the render target?
  • What size is the screen?

What is the output you expect to see?
Only center part of my render target must be cropped and displayed :slightly_smiling: Source Rectangle (540, 0, 840, 1080);

What size is the render target?
Render target is 1920 x 1080

What size is the screen?
This is Dynamic so stertched to my GameWindow Size, I will update the window size in a rectangle[0, 0, ScreenSizeW, ScreenSizeH]

One more thing is if I keep GraphicsDevice.BackBufferWidth and Height is 1920 x1080 , then only spritebatch is drawing fullTexture, incase If I use less size than renderTarget then I cant see the right side of the Texture[RenderTarget], which is the final output frame of my application.

Thanks a lot! Please let me know if you need more details.

Hi KonajuGames,

Any updates?

Not yet. It is on my list though.

Ok… I hope you can reproduce this issue.

Please let me know when you done. Thanks!

I haven’t been able to find any problems with drawing the central portion of a render target to fill the window.

Are you able to provide us with a sample project that demonstrates the issue?

Hi, Thanks for letting me know,

Here you go I put the entire program to reproduce that Issue,

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Sample
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        Texture2D Textur;
        RenderTarget2D renderTarget;

        private int WINDOW_WIDTH = 1920;
        private int WINDOW_HEIGHT = 1080;

        private const int RENDERTARGET_WIDTH = 1920;
        private const int RENDERTARGET_HEIGHT = 1080;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            graphics.PreferredBackBufferWidth = WINDOW_WIDTH; //RENDERTARGET_WIDTH;
            graphics.PreferredBackBufferHeight = WINDOW_HEIGHT; //RENDERTARGET_HEIGHT;
           
            this.Window.AllowUserResizing = true;
            this.Window.ClientSizeChanged += Window_ClientSizeChanged;

            graphics.ApplyChanges();

            // The model will be drawn in this render target.
            renderTarget = new RenderTarget2D(GraphicsDevice, RENDERTARGET_WIDTH, RENDERTARGET_HEIGHT, true, SurfaceFormat.Color, DepthFormat.Depth24Stencil8, this.GraphicsDevice.PresentationParameters.MultiSampleCount, RenderTargetUsage.PreserveContents);


            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            Textur = Content.Load<Texture2D>("butterfly-pebbles"); // 1920 x 1080 Image 
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            // TODO: Add your update logic here

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            GraphicsDevice.SetRenderTarget(renderTarget);
            GraphicsDevice.Clear(Color.Transparent);

            spriteBatch.Begin();
            spriteBatch.Draw(Textur, Vector2.Zero, Color.White);
            spriteBatch.End();

            GraphicsDevice.SetRenderTarget(null);


            //All my content has been drawn on this RenderTarget Now I am going to 
            // render my final output on Screen using this SpriteBatch
            spriteBatch.Begin();
            spriteBatch.Draw((Texture2D)renderTarget, new Rectangle(0, 0, ScreenSizeW, ScreenSizeH), new Rectangle(540, 0, 840, 1080), Color.White);
            spriteBatch.End();

            base.Draw(gameTime);
        }

        int ScreenSizeW = 1920;
        int ScreenSizeH = 1080;
        private void Window_ClientSizeChanged(object sender, EventArgs e)
        {
            Rectangle rect = this.Window.ClientBounds;
            ScreenSizeW = rect.Width;
            ScreenSizeH = rect.Height;

        }
    }
}

XNA and MONO Different Output when you resize the window.

This is the output Comparison,

NOTE: I have checked in FULSCREEN mode, Mono is giving expected output, So no worries for you can fix it later on if you have any other high priority is on.

Thanks and Regards,
Bala