Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PAID BOUNTY] A shared base for public and console repos #8309

Draft
wants to merge 4 commits into
base: develop
Choose a base branch
from

Conversation

tomspilman
Copy link
Member

@tomspilman tomspilman commented May 20, 2024

This is a WIP on the shared native base for future platform work.

See #8242

Looking for feedback on the structure of things before i finish the implementation and finalize it.

  • C# to C++ wrapper generator.
  • C# native wrapper.
  • Windows VK setup.
  • C++ native wrapper. (WIP)
  • SDL native backend. (WIP)
  • Vulkan rendering backend. (WIP)
  • Input native backend.

@tomspilman tomspilman changed the title [PAID BOUNTY] A shared base for public and console repos [PAID BOUNTY] [WIP] A shared base for public and console repos May 20, 2024
@tomspilman tomspilman marked this pull request as draft May 20, 2024 13:22
@tomspilman tomspilman changed the title [PAID BOUNTY] [WIP] A shared base for public and console repos [PAID BOUNTY] A shared base for public and console repos May 20, 2024
public int MaxVertexBufferSlots;
}

internal static unsafe partial class MGG
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to wart these with something that works for us in C# and in C++ (don't want conflicts with other native libs).

So i'm thinking:

  • MGG for Graphics.
  • MGA for Audio.
  • MGI for Input.
  • MGF for Framework?

Thoughts?

#include "csharp_structs.h"


struct MGG_GraphicsDevice;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea here is the C++ implementation will define the internals of these pre-declared structures.

For example one for DX could look like:

struct MGG_GraphicsDevice
{
	ID3D12Device* _device;
	ID3D12GraphicsCommandList* _commandList;
	ID3D12CommandQueue* _commandQueue;
       // etc!
}

This would be how native platforms pass along its data across pinvokes.

The C# just passes pointers and the C++ is responsible for allocation and freeing of these types.


#include "csharp_common.h"

enum CSSurfaceFormat : csint
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here... MGSurfaceFormat instead of CSSurfaceFormat ?

//
// So skip these.
//
if (type.GetCustomAttribute<IsReadOnlyAttribute>() == null)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels sloppy depending on the readonly flag to identify our handle types.

Any better ideas?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My idea was to skip the types which names end in Ptr.


MGG_GraphicsDevice* MGG_GraphicsDevice_Create()
{
auto device = new MGG_GraphicsDevice();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@harry-cpp what do you think of having a no op backend that has empty implementations?

Seems it could be good for some cases.

@tomspilman tomspilman force-pushed the native branch 2 times, most recently from 37fb5ff to 5f845ec Compare May 25, 2024 18:43
@tomspilman
Copy link
Member Author

Both projects need to be fully hooked up to the CAKE Frosting build system

@harry-cpp what do i need to do for this?

Is it just building? Or is it also a project generator for C++?

I had assumed we would maintain C++ projects manually on a per-platform basis.

/// <summary>
/// MonoGame image native calls.
/// </summary>
internal static unsafe partial class MGI
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should ditch StbSharp for native stb directly since we have a native library.

This API exposes reading images (jpg/png) from memory as well as writing jpg and png.

We could implement more here in the future.

@tomspilman
Copy link
Member Author

tomspilman commented May 25, 2024

@harry-cpp @mrhelmut

I assume we'll have one Windows C++ project for a monogame.native.dll that depending on build configuration would build Vulkan or DirectX?

Or should we plan on multiple C++ Windows projects?

I assume we won't support runtime swapping of Vulkan or DX12? Especially since we pre-build the effects for the platform. (IMO this is a gimmick and not actually useful in shipping games)

So we will end up with WindowsVK and WindowsDX as platforms sort of like we had before with WindowsGL.

Also i assume WindowsGL is going away.

@mrhelmut
Copy link
Contributor

I assume we'll have one Windows C++ project for a monogame.native.dll that depending on build configuration would build Vulkan or DirectX?

I don't have a strong opinion on this. Whatever seems smooth enough in regard to Linux, macOS, and consoles moving to that too.

I assume we won't support runtime swapping of Vulkan or DX12? Especially since we pre-build the effects for the platform. (IMO this is a gimmick and not actually useful in shipping games)

It doesn't feel useful to me. Not on the C++ at least. Worst case we can manage that on the C# side of things with a simple switch loading either native dll at launch.

@harry-cpp
Copy link
Member

@harry-cpp what do i need to do for this?

It should:

  • build all the generator projects
  • run all the generators
  • ensure no file is now in modified state compared to before running the generators (aka. all the generated files were properly committed)
  • build all the native projects

Is it just building? Or is it also a project generator for C++?

I had assumed we would maintain C++ projects manually on a per-platform basis.

CAKE is just building the projects. But.

We should use some cross platform solution for building the projects as VS projects are Windows only. Some of them even support generating a VS project for you to work in. Good options are meson and cmake.

@@ -74,11 +74,7 @@ protected Texture3D (GraphicsDevice graphicsDevice, int width, int height, int d
{
ValidateParams(level, left, top, right, bottom, front, back, data, startIndex, elementCount);

var width = right - left;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I figured i would fix bad platform apis when i could.

Here it was passing left, top, right, bottom, front, back.... AND width, height, depth.

So i removed the extra data passing that not all platforms need.

@tomspilman tomspilman force-pushed the native branch 2 times, most recently from 73e2947 to 948100b Compare May 27, 2024 16:03

internal SamplerStateCollection(GraphicsDevice device, int maxSamplers, bool applyToVertexStage)
internal SamplerStateCollection(GraphicsDevice device, int maxSamplers, ShaderStage stage)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This felt like a better design moving forward.


#pragma once

#include "csharp_common.h"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The prefix csharp_ feels wrong here. Better ideas? gen_ or api_ or something?

@@ -0,0 +1,19 @@
@echo off
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Decided it was best to keep the generated binary effect files in per-platform folders instead of all in a common place.

This seems like a good direction considering console support.

// Or do we make the native code transform the string?
//
var absolutePath = Path.Combine(Location, safeName);
return File.OpenRead(absolutePath);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will be moving the file path fixup to native code.

@@ -80,7 +80,7 @@ struct VSInputNmTxWeights
float4 Position : POSITION0;
float3 Normal : NORMAL0;
float2 TexCoord : TEXCOORD0;
uint4 Indices : BLENDINDICES0;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works around an issue DXC/Glsl where unsigned int 4 didn't compile. This shouldn't matter as you never have huge numbers for blend indices.

@@ -20,7 +20,7 @@ ColorPair ComputeLights(float3 eyeVector, float3 worldNormal, uniform int numLig
float3x3 lightSpecular = 0;
float3x3 halfVectors = 0;

[unroll]
UNROLL
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using macros here so it can be redefined per-platform.

/// <see cref="InputLayoutCache"/>.
/// </summary>
/// <returns>The <see cref="ImmutableVertexInputLayout"/>.</returns>
internal ImmutableVertexInputLayout ToImmutable()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved this from DirectX specific code to be shared between platforms.

private int _dirty;

internal TextureCollection(GraphicsDevice graphicsDevice, int maxTextures, bool applyToVertexStage)
internal TextureCollection(GraphicsDevice graphicsDevice, int maxTextures, ShaderStage stage)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a better approach considering we may eventually have more shader stages.


LPCSTR id = nullptr;

if (strcmp(name, "AlphaTestEffect") == 0)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we consider making an enum for the stock effects instead of passing around string names here?


static MGG_System* System_Get()
{
if (mgg_system != nullptr)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm debating if we need some object like MGG_System exposed at the C# level to manage graphics state before a graphics device is created... like initializing the Vulkan API (or initializing DX12).

Or should we let the native code manage this internally?

VkApplicationInfo app_info = { VK_STRUCTURE_TYPE_APPLICATION_INFO };
app_info.pNext = nullptr;
app_info.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
app_info.pApplicationName = "None";
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we pass down an application name... i assume this is used by drivers and utilities for optimizing/tweaking settings for specific games.


#ifdef _WIN32

HMONITOR primaryMonitor = MonitorFromPoint(POINT{ 0, 0 }, MONITOR_DEFAULTTOPRIMARY);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably all wrong and needs to be rewritten, but it works for this first pass at Vulkan.



template <class T>
void remove_by_value(std::vector<T>& vector, const T& element)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now i'm depending on STL for vectors, string, queue, maps, etc.

I have seen differences in functionality and performance across platforms over the years.

I wonder if eventually we want our own small common set of native helper collections to use across our native backends?

@@ -34,13 +34,13 @@ public abstract class GameWindow
/// </summary>
public virtual bool AllowAltF4 { get { return _allowAltF4; } set { _allowAltF4 = value; } }

#if (WINDOWS && !WINDOWS_UAP) || DESKTOPGL
Copy link
Member Author

@tomspilman tomspilman Jun 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking we should just expose this on all platforms and let it be ignored on platforms that cannot use it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants