Skip to content

Commit

Permalink
WIP on native wrapper and generator.
Browse files Browse the repository at this point in the history
  • Loading branch information
tomspilman committed May 20, 2024
1 parent 4305687 commit f66c58e
Show file tree
Hide file tree
Showing 12 changed files with 579 additions and 2,038 deletions.
36 changes: 33 additions & 3 deletions MonoGame.Framework/Platform/Native/ConstantBuffer.Native.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,52 @@
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.

using MonoGame.Interop;
using System;
using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Runtime.InteropServices;

namespace Microsoft.Xna.Framework.Graphics;

internal partial class ConstantBuffer
{
private void PlatformInitialize()
{
internal unsafe MGG_Buffer* Handle;

private unsafe void PlatformInitialize()
{
Handle = MGG.Buffer_Create(GraphicsDevice.Handle, _buffer.Length);
}

private void PlatformClear()
{
// TODO: What is this for?
throw new NotImplementedException();
}

internal unsafe void PlatformApply(GraphicsDevice device, ShaderStage stage, int slot)
{
if (Handle == null)
PlatformInitialize();

if (_dirty)
{
fixed (byte* data = &_buffer[0])
MGG.Buffer_SetData(GraphicsDevice.Handle, ref Handle, 0, data, _buffer.Length, true);
_dirty = false;
}

MGG.GraphicsDevice_BindConstantBuffer(GraphicsDevice.Handle, stage, slot, Handle);
}

internal void PlatformApply(GraphicsDevice device, ShaderStage stage, int slot)
protected override unsafe void Dispose(bool disposing)
{
if (disposing && Handle != null)
{
MGG.Buffer_Destroy(GraphicsDevice.Handle, Handle);
Handle = null;
}

base.Dispose(disposing);
}
}
97 changes: 93 additions & 4 deletions MonoGame.Framework/Platform/Native/GraphicsDevice.Native.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,96 @@
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.

using MonoGame.Interop;
using System;
using System.Collections.Generic;


namespace Microsoft.Xna.Framework.Graphics;


public partial class GraphicsDevice
{
private void PlatformSetup()
internal unsafe MGG_GraphicsDevice* Handle;

internal Texture2D DefaultTexture;

private int _currentFrame;

private unsafe List<PtrTo<MGG_Texture>> _disposeTexturesNextFrame = new List<PtrTo<MGG_Texture>>();
private unsafe List<PtrTo<MGG_Texture>> _disposeTexturesThisFrame = new List<PtrTo<MGG_Texture>>();

private unsafe void PlatformSetup()
{
Handle = MGG.GraphicsDevice_Create();

// Get the device caps.
MGG_GraphicsDevice_Caps caps;
MGG.GraphicsDevice_GetCaps(Handle, out caps);

MaxTextureSlots = caps.MaxTextureSlots;
MaxVertexTextureSlots = caps.MaxVertexTextureSlots;
_maxVertexBufferSlots = caps.MaxVertexBufferSlots;
}

private void PlatformInitialize()
private unsafe void PlatformInitialize()
{
MGG.GraphicsDevice_ResetBackbuffer(Handle,
PresentationParameters.BackBufferWidth,
PresentationParameters.BackBufferHeight,
PresentationParameters.BackBufferFormat,
PresentationParameters.DepthStencilFormat);

_currentFrame = -1;

// Setup the default texture.
DefaultTexture = new Texture2D(this, 2, 2);
DefaultTexture.SetData(new[] { Color.Black, Color.Black, Color.Black, Color.Black });
}

private void OnPresentationChanged()
private unsafe void OnPresentationChanged()
{
// Finish any frame that is currently rendering.
if (_currentFrame > -1)
MGG.GraphicsDevice_Present(Handle, _currentFrame);

// Now resize the back buffer.
MGG.GraphicsDevice_ResetBackbuffer(
Handle,
PresentationParameters.BackBufferWidth,
PresentationParameters.BackBufferHeight,
PresentationParameters.BackBufferFormat,
PresentationParameters.DepthStencilFormat);

// Begin a new frame it if was previously rendering.
if (_currentFrame > -1)
{
_currentFrame = -1;
BeginFrame();
}
}

private unsafe void BeginFrame()
{
if (_currentFrame > -1)
return;

// Start the command buffer now.
_currentFrame = MGG.GraphicsDevice_BeginFrame(Handle);

// We must reapply all the state on a new command buffer.
_scissorRectangleDirty = true;
_blendFactorDirty = true;
_blendStateDirty = true;
_pixelShaderDirty = true;
_vertexShaderDirty = true;
_depthStencilStateDirty = true;
_indexBufferDirty = true;
_rasterizerStateDirty = true;
_vertexBuffersDirty = true;
//_lastNvnBuffer = IntPtr.Zero;
Textures.Dirty();
SamplerStates.Dirty();
}

private void PlatformClear(ClearOptions options, Vector4 color, float depth, int stencil)
Expand All @@ -30,8 +103,24 @@ private void PlatformDispose()
{
}

private void PlatformPresent()
private unsafe void PlatformPresent()
{
if (_currentFrame < 0)
return;

MGG.GraphicsDevice_Present(Handle, _currentFrame);
_currentFrame = -1;

for (int i = 0; i < _disposeTexturesThisFrame.Count; i++)
{
var texture = _disposeTexturesThisFrame[i].Ptr;
MGG.Texture_Destroy(Handle, texture);
}
_disposeTexturesThisFrame.Clear();

var temp = _disposeTexturesThisFrame;
_disposeTexturesThisFrame = _disposeTexturesNextFrame;
_disposeTexturesNextFrame = temp;
}

private void PlatformSetViewport(ref Viewport value)
Expand Down
79 changes: 76 additions & 3 deletions MonoGame.Framework/Platform/Native/Interop.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,88 @@

using Microsoft.Xna.Framework.Graphics;
using System.Runtime.CompilerServices;
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;

namespace MonoGame.Interop;

internal readonly struct GamePtr { }
internal readonly struct Game { }

internal readonly struct GameWindowPtr { }
internal readonly struct GameWindow { }

internal static unsafe partial class GameWrapper
{
[LibraryImport("monogame", StringMarshalling = StringMarshalling.Utf8)]
public static partial void MG_GW_SetAllowUserResizing(GamePtr* game, GameWindowPtr* gameWindow, [MarshalAs(UnmanagedType.U1)] bool allowuserresizing);
public static partial void MG_GW_SetAllowUserResizing(Game* game, GameWindow* gameWindow, [MarshalAs(UnmanagedType.U1)] bool allowuserresizing);
}

internal struct PtrTo<T>
{
public unsafe T* Ptr;
}

internal readonly struct MGG_GraphicsDevice { }
internal readonly struct MGG_Buffer { }
internal readonly struct MGG_Texture { }

internal struct MGG_GraphicsDevice_Caps
{
public int MaxTextureSlots;
public int MaxVertexTextureSlots;
public int MaxVertexBufferSlots;
}

internal static unsafe partial class MGG
{
#region GraphicsDevice

[LibraryImport("monogame", EntryPoint = "MGG_GraphicsDevice_Create", StringMarshalling = StringMarshalling.Utf8)]
public static partial MGG_GraphicsDevice* GraphicsDevice_Create();

[LibraryImport("monogame", EntryPoint = "MGG_GraphicsDevice_GetCaps", StringMarshalling = StringMarshalling.Utf8)]
public static partial void GraphicsDevice_GetCaps(MGG_GraphicsDevice* device, out MGG_GraphicsDevice_Caps caps);

[LibraryImport("monogame", EntryPoint = "MGG_GraphicsDevice_ResetBackbuffer", StringMarshalling = StringMarshalling.Utf8)]
public static partial void GraphicsDevice_ResetBackbuffer(MGG_GraphicsDevice* device, int width, int height, SurfaceFormat color, DepthFormat depth);

[LibraryImport("monogame", EntryPoint = "MGG_GraphicsDevice_BeginFrame", StringMarshalling = StringMarshalling.Utf8)]
public static partial int GraphicsDevice_BeginFrame(MGG_GraphicsDevice* device);

[LibraryImport("monogame", EntryPoint = "MGG_GraphicsDevice_Present", StringMarshalling = StringMarshalling.Utf8)]
public static partial void GraphicsDevice_Present(MGG_GraphicsDevice* device, int currentFrame);

[LibraryImport("monogame", EntryPoint = "MGG_GraphicsDevice_BindConstantBuffer", StringMarshalling = StringMarshalling.Utf8)]
public static partial void GraphicsDevice_BindConstantBuffer(MGG_GraphicsDevice* device, ShaderStage stage, int slot, MGG_Buffer* buffer);

#endregion

#region Buffer

[LibraryImport("monogame", EntryPoint = "MGG_Buffer_Create", StringMarshalling = StringMarshalling.Utf8)]
public static partial MGG_Buffer* Buffer_Create(MGG_GraphicsDevice* game, int length);

[LibraryImport("monogame", EntryPoint = "MGG_Buffer_SetData", StringMarshalling = StringMarshalling.Utf8)]
public static partial void Buffer_SetData(
MGG_GraphicsDevice* game,
ref MGG_Buffer* buffer,
int offset,
byte* data,
int length,
[MarshalAs(UnmanagedType.U1)]
bool discard);

[LibraryImport("monogame", EntryPoint = "MGG_Buffer_Destroy", StringMarshalling = StringMarshalling.Utf8)]
public static partial void Buffer_Destroy(MGG_GraphicsDevice* game, MGG_Buffer* buffer);

#endregion

#region Texture

[LibraryImport("monogame", EntryPoint = "MGG_Texture_Destroy", StringMarshalling = StringMarshalling.Utf8)]
public static partial void Texture_Destroy(MGG_GraphicsDevice* game, MGG_Texture* texture);

#endregion
}


46 changes: 25 additions & 21 deletions Tools/MonoGame.Generator.CTypes/EnumWritter.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
// MonoGame - Copyright (C) The MonoGame Team
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.

using System;
using System.Text;

namespace MonoGame.Generator.CTypes;

class EnumWritter
{
private readonly Dictionary<string, Type> _types;
private readonly StringBuilder _outputText;
private readonly Dictionary<string, string> _duplicateChecker;

public EnumWritter()
{
Expand All @@ -21,39 +26,34 @@ public EnumWritter()
""");
_duplicateChecker = [];

_types = [];
}

public static bool IsValid(Type type)
private static bool IsValid(Type type)
{
return type.IsEnum && !type.IsNested;
}

public bool Append(Type type)
public bool TryAppend(Type type)
{
if (!IsValid(type))
return false;

if (_duplicateChecker.TryGetValue(type.Name, out string? dupFullName))
{
if (type.FullName != type.FullName)
{
Console.WriteLine($"""
WARNING: Duplicate enum name for {type.Name}:
- {type.FullName}
- {dupFullName}
if (_types.ContainsKey(type.Name))
return true;

""");
}
_types.Add(type.Name, type);
return true;
}

return false;
}

private void Generate(Type type)
{
var enumValues = Enum.GetValues(type);

// Write all values to output
_outputText.AppendLine($$"""
enum CS{{type.Name}} : {{Util.GetCEnumType(Enum.GetUnderlyingType(type).ToString())}}
enum CS{{type.Name}} : {{Util.GetCType(Enum.GetUnderlyingType(type))}}
{
""");
foreach (var enumValue in enumValues)
Expand Down Expand Up @@ -86,10 +86,14 @@ class ECS{{type.Name}}
};
""");
}

_duplicateChecker.Add(type.Name, type.FullName!);
return true;
public void Flush(string dirPath)
{
foreach (var pair in _types)
Generate(pair.Value);

File.WriteAllText(Path.Combine(dirPath, "csharp_enums.h"), _outputText.ToString());
}

public void Flush(string dirPath) => File.WriteAllText(Path.Combine(dirPath, "csharp_enums.h"), _outputText.ToString());
}
Loading

0 comments on commit f66c58e

Please sign in to comment.