-
-
Notifications
You must be signed in to change notification settings - Fork 397
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
Tracking Issue for Bindings Generation & Improvements #887
Comments
Extensions. |
This will be removed in favor of handle groups, but is a pain point in 2.x
This is reasonable feedback, but it's unclear what we can do here, this is effectively upstream khronos naming |
Currently on OpenGL there are several inconsistencies with what enum you can use with what function. I do agree that it may not be a great idea if you generate overloads for every single relevant enum there is with all of the combinations, but I think that being able to use |
There are several instances of methods that have ridiculous amounts of overloads due to the sheer number of parameters and combinations of ptr/ref/span permutations also in combination with for example the GLEnum vs. enum types. TexImage2D for example has 48 different combinations. I've seen certain methods with upwards of 100 overload options. It may be beneficial to limit overloads by a common type - e.g. either all by ptr, all by ref or all by span if possible. This would also solve something I wouldn't mind seeing - which would be allowing the entire api to be usable inside a safe context if so desired. Currently certain methods are completely unavailable outside of unsafe - and arguably there may be certain ones that would be extremely difficult to craft into a safe context. (I'm looking at you, Vulkan!) (e.g all ref/out or span params) |
Would it not be preferable to just eliminate GLEnum and strongly type the correct enum everywhere? |
There has been some discussion about the number of overloads in regard to 3.0 (-> we want to further improve overloads with better overloads) |
For OpenGL specifically, I would not be happy doing this unless someone from our team audited the entire OpenGL specification and ensured that the groups are correct and sane, and committed to reviewing all changes thereafter to ensure that remains the case. The strong typing situation has been a mess ever since the demise of Silicon Graphics, as they stopped being properly maintained at that point. Everything thereafter is best effort. |
I haven't looked at the spec in a really, really long time, but aren't new enums occasionally added specifically for EXT and ARB extensions? I think in cases like that you may want to still use the raw enums instead of encapsulating potentially constantly changing enum definitions. I know I'd personally like the option to use enums for those just-in-case moments. |
Replace |
the ENTIRETY of dx11 |
separation of dsa and non dsa? interface BaseGL {
void UseProgram(uint id);
}
interface DSA {
void NamedBufferData(uint id, ...);
}
interface DSALess {
void BufferData(...);
} |
That’s not helpful feedback :P what’s not ideal about them? |
mostly the UUID shenanigans, see Vortice ID3D11Texture2D backBuffer = this._swapChain.GetBuffer<ID3D11Texture2D>(0); vs Silk.NET ComPtr<ID3D11Texture2D> backBuffer;
_swapChain.Get().GetBuffer(0, SilkMarshal.GuidPtrOf<ID3D11Texture2D>(), ref backBuffer.Handle); //i dont know if this actually compiles, but i yoinked it from a line you posted in discord perskey so im going to assume it does while its usable, its quite less sharpie and a bit harder to read |
i think this little code example of me once trying to use silk.net d3d11 illustrates how to me, unusable they are: void* factoryOut = null;
//you need to get GUIDs for alot of stuff
Guid dxgiGuid = typeof(IDXGIFactory2).GUID;
dxgi.CreateDXGIFactory2(0, ref dxgiGuid, ref factoryOut);
//you need to cast this to be correct aswell..
this._iDxgiFactory = (IDXGIFactory2*) factoryOut;
//then this, this is just horrifying to me, and is the only way i knew how to get a swapchain going
//Gotta get the pointer to a IUnknown pointer for the device because thats what CreateSwapChainForHwnd wants
fixed (IUnknown* device = &this._device) {
this._iDxgiFactory->CreateSwapChainForHwnd(device, window.Native.Win32.Value.Hwnd, ref swapChainDesc, ref fullscreenDesc, null, ref this._swapChain);
} not a huge fan of having to get alot of GUIDs just to be able to create something like a texture or factory, and the pointer shenanigans just make it really unpleasant to use, yes ComPtr exists but it doesn't eliminate almost any of that, its just as if i were writing c++ but with c#, it just doesnt work |
Yeah the DX stuff certainly needs fixing - I think that work is inline with function groups. |
While yes, you can do that, it still feels weird, especially the fixed (IUnknown* device = &this._device) I can live with the UUIDs but thats just ridiculous, and I think alot of the API has that, which is why currently I'm using vortice instead of silk for my d3d11 needs |
Not an DX expert, but I don't see how we can do anything about that? That's just what it looks like when you store IUnknown in a field and need a pointer to it later. |
I mean, I don't know how Vortice does it, but it has to be possible somehow if they've done it right? although I don't know if they regenerate their bindings often, which Silk does, which might hinder smth like this, the thing I'm looking for is making the API more natural, something like vortice, and taking a pointer to a pointer and casting that to a IUnknown pointer then using that is far from natural |
Technically if we're talking native C code, it IS natural to do that with
COM. Nothing wrong with it from the purist standpoint, but you are right
in that it's not exactly intuitive to use even in C++ anymore.
I haven't played with it at all, but how did XNA wrap Direct3D? There may
be some hints there that could be leveraged to making a more sane managed
interface to D3D.
…On Thu, Apr 28, 2022, 5:52 AM Furball ***@***.***> wrote:
I mean, I don't know how Vortice does it, but it has to be possible
somehow if they've done it right? although I don't know if they regenerate
their bindings often, which Silk does, which might hinder smth like this,
the thing I'm looking for is making the API more natural, something like
vortice, and taking a pointer to a pointer and casting that to a IUnknown
pointer then using that is far from natural
—
Reply to this email directly, view it on GitHub
<#887 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AFMMZU2TJUVDFBWDESJRK4DVHJUWPANCNFSM5TUFZQ2A>
.
You are receiving this because you commented.Message ID: <dotnet/Silk.
***@***.***>
|
I entirely agree that we can improve things here, using |
SDL bidings tend to not match up the Enums with their respective functions very well, only doing it sometimes spirattically |
This comment was marked as outdated.
This comment was marked as outdated.
glDebugMessageInsert has no string overload |
the |
OpenAL is missing span overloads in many, many places. BufferData, SourceQueue/UnqueueBuffers in particular are sore spots |
Our OpenAL bindings are completely handwritten in 2.X (and haven't really been updated since the first or second preview of 1.0!) so for 2.X - contributions welcome :), but imo in 3.0 we'd be stupid not to have OpenAL autogenerated as well given our C/C++ toolchain will be a lot more mature. |
It should probably be a Bool32 given that bool is a managed type but I agree otherwise |
D3D9 |
|
D3D9 missing devicecaps enum |
|
D3D9 Missing |
Pretty sure this is a symptom of 2.x having no access to SAL stuff. Talked to @Perksey about this few days ago, and looks like we can make this happen for 3.0 |
D3D11 seems to be missing the DXGI_USAGE enum, well, its not an enum, but it should be in our bindings, maybe there should be a way to define a prefix as being treated as an enum? |
D3Dcolorvalue is named wrong, should likely just be ColorValue |
MapFlag.DONotWait is also named wrong, should be MapFlag.DoNotWait |
|
The GLFW bindings are missing
|
|
Silk.NET.Direct2D.Enum.LawnGreen to D3Dcolorvalue I'm not good at using c++, or even this smart pointer thing. Even though a lot of people say smart pointers are great. For this I now have to switch to SharpDx. |
Thanks for all the feedback, please do keep it coming! We are actively looking into 3.0 now. |
Regarding GLFW, I am not opposed to using it, but I think it should be port(port to pure csharp) instead of binding(wrapper). |
The main one for me is to respect the inheritance chain in bindings. Currently you can't write methods that take a ComPtr, and then pass in a ComPtr, and there's a similar issue around generic functions where the generic constraints won't work. For some interfaces it's not that big a deal, but there's a couple like IUnknown where it would be a lot more convenient. There doesn't seem to be any way to implement a generic TryQueryInterface. There's also quite a few cases where the function seems like it should be simplified, although I'm not totally sure how obvious it is from a code generation perspective. This seems largely to relate to parameters by reference which generates three overloads for pointer, ref, and Span, when they should be generated as being taken by value or returned by value, e.g. ID3D12Device's CreateCommandQueue (input) or IDXGIAdapter's GetDesc() 1/2/3 (output). There's also a few like CreateSwapChainForHwnd where I would have expected at least one overload that returns ComPtr as this is the main output of the function (instead it has 90 overloads). As an extra case, IDXDGIFactory's EnumAdapters could maybe use an extension that simply returns IEnumerable of the given T. Lastly, for the NativeWindow's Win32 property, kindly add a comment in the doc about the HDC. From what I can see, DCs are meant to be used transiently and loaded with GetDC on demand, so I'm not really sure of the semantics. Am I meant to use CS_OWNDC, is the property re-invoked whenever a new DC is needed, or something else? It doesn't seem to fit with the WinAPI design to request that the caller provide an HDC when you're already asking for an HWND and can get your own HDC from that whenever you want. There also eem to be a few missing constants, like DXGI_MWA_NO_ALT_ENTER, DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING, and DXGI_USAGE_RENDER_TARGET_OUTPUT. |
Hi all. I wanted to share my current thoughts on all of the above, and what 3.0 bindings currently look like. See the current prototype 3.0 bindings in action!Khronos-specificGroups (implemented today in #2020)DONE: OpenGL still generates both GLEnum and the stronger group enums. Functions taking enums as parameters are declared as a "duck type" This was the only way we have found so far to prevent alienating certain portions of our userbase by being opinionated in one direction and/or not preferring correctness, without exploding the API surface of Silk.NET like we've seen happen in 2.X. TODO: The IDE experience isn't great for this sort of duck typing thing at the moment, I believe we can rectify it using a Rider/ReSharper extension and/or Roslyn code completion providers. We intend to have a comprehensive documentation page describing all of our esoteric types and how to read function signatures defined in terms of them. An additional improvement we have made is trimming extension vendors from multi-vendor and/or promoted enums e.g. For the avoidance of doubt, fully unsafe overloads are available that do not have any transformations as described in this comment. Extensions (implemented today in #2020)We are moving away from having separate extension projects and extension classes in 3.0 as it currently stands. This thread has proven that it has caused some confusion, and we no longer believe it is necessary for the correctness we would like to achieve. This also aligns us with more traditional bindings libraries. DONE: Essentially, all functions are now stored in the Here's an example of this: [SupportedApiProfile(
"glcore",
["GL_KHR_debug", "GL_VERSION_4_3", "GL_VERSION_4_4", "GL_VERSION_4_5", "GL_VERSION_4_6"],
MinVersion = "4.3"
)]
[SupportedApiProfile(
"gl",
["GL_KHR_debug", "GL_VERSION_4_3", "GL_VERSION_4_4", "GL_VERSION_4_5", "GL_VERSION_4_6"],
MinVersion = "4.3"
)]
[NativeFunction("opengl", EntryPoint = "glDebugMessageCallback")]
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static void DebugMessageCallback(
[NativeTypeName("GLDEBUGPROC")]
delegate* unmanaged<uint, uint, uint, uint, uint, sbyte*, void*, void> callback,
[NativeTypeName("const void *")] void* userParam
) => ThisThread.DebugMessageCallback(callback, userParam); TODO: This DONE: Ignore the Handles (Khronos and COM)Currently in Silk.NET.Vulkan DONE: I believe that we should have these functions take a As for COM, 2.16+ was a great experiment in making our COM bindings more usable. We'd like to take those learnings forward into 3.0 to make our DirectX bindings even better. We've encountered issues with the methods being defined as extension methods atop TODO: In line with the above opaque handle handling, I believe we should do something similar for COM APIs as well. Namely, instead of a TODO: To address a comment raised by #1951 and #408, we should generate an actual interface for each COM type i.e. have a DONE: As discussed in Discord, opaque handles (not COM handles) shall have a Handle suffix. By having a Handle suffix, we won't conflict with user code (e.g. a user-defined type called TODO: Moreover, by creating a differentiated handle type, this opens up future opportunities for opaque handle detection to go further by introducing Object-suffixed classes to enable C# classes to mirror OOP-style C functions. e.g. instead of Addressing Individual Comments
Addressed in the grouping section wrt duck typing.
TODO: This is unsolved and needs to be rectified.
Addressed in the handle section wrt handle types instead of a generic COM pointer type with extension methods.
We will still have some overloads because we have discovered that our userbase has a lot of distinct ways of working with the library (so we don't want to form too much of an opinion to avoid alienating fragments of our userbase), but the duck typing mechanism should help get this number way down. I will be very shocked if any function in the entire library ends up with over 10 overloads. For more information, consult the SilkTouch 3.0 proposal in documentation/proposals. Similar mechanisms are used for Span/string/array parameters. TODO: We are unlikely to make use of
This is complicated. I've made some improvements as of #2020 to the naming prettifier but it's still very hard to get right and close to a "one size fits all" solution. Some sacrifices should be expected to be made somewhere, we are not going to get everything right and I can't promise that these issues will be rectified.
This one is the name translator working as expected! The Type prefix is included because removing it would generate invalid member names.
TODO: Some of this is unfortunately necessary to use the vkLoad*ProcAddr functions correctly. I can't promise that this is going to go away in 3.0. Perhaps we'll make it less complicated and just throw (with a helpful message!) if the user tries to use multiple instance/device combos with one object.
Addressed above.
We're likely to remove our GLFW bindings in 3.0, at least for the initial versions. The team is leaning more towards using SDL3 instead, but we are actively working on establishing a policy that enables the community to add and independently maintain more non-core bindings.
TODO: This is a great idea!
TODO: This should be investigated.
TODO: This is a good idea, but our users are likely to want choice here. Perhaps a
Addressed in the handles section with Object-suffixed types. I can't speak on whether this means everything will be completely safe, but my hope with the duck typing described is that unsafe may be completely avoidable.
TODO: We should investigate these comments once bindings parity with 2.X has been achieved in 3.0. |
The issue description has been updated to reflect the megacomment and is representative of the remaining work in SilkTouch 3.0. Please don't stop suggesting things though, it is not an immutable list! |
Comments
We truly invite everyone to send us reports of any place where our bindings are not ideal. This issue will serve as a list of things we should fix in 3.0.
The following summary comments have been formulated from your feedback, and these comments can be consulted for further information on the specific tasks:
This is a living document! Please do not hesitate to point out any other potential improvements - we may add them to this list. If you would like to work on a task, please contact @Perksey in Discord for a brain dump if it's unclear what is required of a task.
Priority 0 (required for the first 3.0 preview)
Constant<uint, GLEnum>
orConstant<uint, GLEnum, BufferUsage>
, meaning that you can pass in auint
,GLEnum
, orBufferUsage
using implicit casts thereby not requiring an explosion in overloads.GL
class directly.GL
can be used in a static way or as an instance ofIGL
. The static mechanism essentially just forwards to a thread-localIGL
instance, but this won't be true for every binding.VkInstanceT*
orPtr<VkInstanceT>
/Ref<VkInstanceT>
becomesVkInstance
which contains avoid*
- make sure this is generic and can work with any binding.Priority 1 (required for the first 3.0 preview that contains a binding dependent on the task)
void**
and encapsulate these as handle structures for them e.g.ID3D11Device*
becomesD3D11Device
containing avoid***
.IComVtbl
as they do today (aTSelf
generic parameter may be required for codegen in terms of these interfaces) i.e.CreateFactory<T>() -> T
where T : IComVtbl
/IComVtbl<T>
and get aDXGIFactory2
out. These should be generated as they are in 2.X i.e. whereIID_PPV_ARGS
would be used in C/C++.DXGIFactory2
will implicitly cast toDXGIFactory1
for example, to address a comment raised in this thread about polymorphism.HWND
is actuallyHWND__*
but the attribute only shows usHWND
. This is to ensure thatCreateBasicSymbolConstraints
and co works correctly.vkLoad*ProcAddr
functions correctly using handles captured fromvkCreateInstance
/vkCreateDevice
a la 2.X.Priority 2 (required in any 3.0 preview)
nullptr
,AsRef
, etc... Have a comprehensive documentation page describing all of our esoteric types and how to read function signatures defined in terms of them.SupportedApiProfile
by using an analyser similar toSupportedOSPlatform
. The analyser would encourage you to either annotate your function with its own attribute (such that the requirement bubbles up throughout the program) or to check that requirement a laGL.IsExtensionPresent("GL_KHR_debug")
orGL.IsVersionAtLeast(4, 3)
.Pfn
structures for function pointers that marshal invocations of the delegate being marshalled to DSL structures i.e. so users can usePtr<sbyte>
whereas we lower it tosbyte*
implicitly. This is like 2.X but better.SymbolConstraints
. Might be better done in ClangSharp itself and copying code from win32metadata code where possible.in
/out
/ref
as it currently stands for simplicity and keeping the overload count down, but we need to provide ample documentation and utilities for equivalent functionalityPriority 3 (preview 5/initial release)
IGL
for OpenGL, staticSdl
for SDL, etc...ID3D11Device
becomesD3D11Device
representing the actualvoid***
handle (this shall implementIComVtbl
), andID3D11Device
is generated as an actual interface to allow C# types to implement COM types.ComWrappers
, consult @Perksey for a brain dumpThrow
/Assert
/Expect
extension methods on result-like types.Priority 4 (initial release or following initial release)
Constant
.Priority 5 (stretch goal, likely future release)
Object
-suffixed classes to enable C# classes to mirror OOP-style C functions. e.g. instead ofNamedBufferData
, you could doBufferObject.BufferData
.vkEnumerate
, DXGI'sEnumAdapter
etc to return enumerables.The text was updated successfully, but these errors were encountered: