Skip to content

Conversation

Ethereal77
Copy link
Contributor

@Ethereal77 Ethereal77 commented Jul 18, 2023

PR Details

Replace SharpDX bindings for DXGI, Direct3D 11, Direct3D 12, the DirectX Shader Compiler, and any other use of SharpDX with Silk.NET bindings.

Description

SharpDX is the base for all the Direct3D (both 11 and 12) graphics frameworks in Stride. But SharpDX is no longer active nor mantained, the repository is archived, and the NuGets are still (and forever) netstandard2.0. Also, it is based on a class-based abstraction over the DirectX interfaces.

Meanwhile, Silk.NET is a new bindings library created to take advantage of modern .NET, use the modern C# performance-oriented primitives and features (like Span<T>, for example), and it's designed more as a raw bindings as close as possible to the underlying DirectX APIs, without class-based abstractions. Its main drawback however is that it is inherently unsafe (in the context of using pointers and memory management directly) That however is of no importance to Stride as it will be under the hood of the Stride.Graphics framework.

This PR consists of the following points:

  • Convert Direct3D 11 framework to Silk.NET.Direct3D11.
  • Convert Direct3D 12 framework to Silk.NET.Direct3D12.
  • Convert DirectX Shader Compiler to Silk.NET.Direct3D.Compilers.
  • Improve the documentation on DirectX-related methods and types, removing references to SharpDX or to the native constants, types, or functions where appropriate.
  • Introduce small convenience types and helper functions to aid in the implementation of interop improvements like this one, now and in the future.

Related Issue

This PR tries to solve issue #432. It is similar to PR #1123 by ykafia, but that one is pretty out of date at this point, so it was easier to start afresh branching the current master.

Motivation and Context

The motivation for converting to Silk.NET is twofold:

  • The SharpDX libraries are pretty solid and stable at this point. However its design filosophy (more to be used as a framework itself ala XNA) and its age makes us lose opportunities to improve performance, control memory allocations more tightly and take advantage of modern C#. Also it is no longer mantained, so no more bug fixes or improvements of any kind.
  • Silk.NET is actively mantained and uses all the utilities modern C# and .NET has to offer. As it is actively mantained it's easier to get bug fixes and improvements, and more importantly, access to future (and current) technologies we may be interested in (like DirectStorage, DXVA, etc).

If all goes well with this PR, you should not see a difference in Stride. Maybe better performance and memory consumption. The improvement is mainly to be more up to date and more inline with modern .NET.

Types of changes

  • Docs change / refactoring / dependency upgrade
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist

  • My change requires a change to the documentation.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

@Ethereal77 Ethereal77 mentioned this pull request Sep 14, 2023
7 tasks
@ly3027929699
Copy link

i can't build this branch via some errors has not resolve

@Eideren
Copy link
Collaborator

Eideren commented Oct 21, 2023

@ly3027929699 Yeah, the PR is still marked as wip, you shouldn't expect it to work as is yet :P

Comment on lines 38 to 44
HResult result = dxgi.CreateDXGIFactory2(debugFlag, SilkMarshal.GuidPtrOf<IDXGIFactory2>(), (void**) &factory2);

if (result.IsFailure)
result.Throw();

NativeFactory = factory2;
ComPtr<IDXGIFactory2> adapterFactory = new() { Handle = factory2 };
Copy link

Choose a reason for hiding this comment

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

FWIW we have overloads now that can simplify this

ComPtr<IDXGIFactory2> adapterFactory = dxgi.CreateDXGIFactory2<IDXGIFactory2>(debugFlag);

It's mentioned in the 2.17 blog post: https://dotnet.github.io/Silk.NET/blog/apr-2023/silk2170.html

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've seen them. I'm first making it work and checking things, then I'll make it pretty using the overloads.

@ykafia ykafia mentioned this pull request Nov 18, 2023
7 tasks
@Aggror Aggror linked an issue Dec 9, 2024 that may be closed by this pull request
@Kryptos-FR
Copy link
Member

Kryptos-FR commented Feb 24, 2025

@Ethereal77 I'm trying to merge master into this branch to solve the conflicts introduced by #2643. However, I don't seem to have the rights to push to your repo. Could you add me as a contributor?

nvm: I was able to fix the conflicts in the web editor

@Ethereal77
Copy link
Contributor Author

@Kryptos-FR I can indeed add you as a contributor. No problem with that.

However, I still have changes locally that I have not yet pushed. I'm gradually distilling the changes from another repo I have. As this has taken more time than I wanted it to take initially it has been a bit of a mess, where most of the changes I've made to a "prototype" repo where I try things.
My plan is to rebase all this on Stride's master instead of merging master here.

So, with this in mind, if you merge master to this branch now you'll make my life a little miserable right now 😁

What I can do is push some of the changes I want to do today and then do a rebase to the current master. What do you think?

P.D: If you still want me to add you as contributor, as I said above, no problem.

@Kryptos-FR
Copy link
Member

Kryptos-FR commented Feb 24, 2025

@Ethereal77 Oh oh. I saw your comment after merging master. You should be able to rebase on top of the commit before the merge to ignore it.

If you are unsure how to do it (and not want to mess with your local branches), if you add me as a contributor I can restore the remote branch to where it was before the merge.

@Ethereal77
Copy link
Contributor Author

Don't worry. I'll finish some changes I have in progress, rebase on master at the previous commit and force push. That would do it, isn't it?
I know I should have this branch as clean and as merge-ready as possible, but as it is now it's a little mess with more than 100 uncommitted files I'm slowly reviewing, cleaning, and pushing.
I also have many more modified files in which I've added or expanded documentation, but I wanted to add that progressively and on top of the more important changes (the Silk.NET conversion) instead of mixing them, with the hope that reviewing the changes is easier this way.

@Ethereal77
Copy link
Contributor Author

@Kryptos-FR I've rebased on latest master (except the last merge commit). Hope everything went well.

@Kryptos-FR
Copy link
Member

Kryptos-FR commented Feb 24, 2025

@Ethereal77 looks like, except maybe the reference to Silk.NET.D3DCompiler in Directory.Package.props, shouldn't it be Silk.NET.Direct3D.Compilers instead?

@Ethereal77
Copy link
Contributor Author

It looks like the package was named Silk.NET.D3DCompiler but has been renamed recently (?). I've just upgraded to the latest Silk.NET version and now it is indeed named Silk.NET.Direct3D.Compilers.

<PackageReference Include="SharpDX.Direct3D12" Condition="'$(TargetFramework)' == '$(StrideFramework)'" />
<PackageReference Include="SharpDX.D3DCompiler" Condition="'$(TargetFramework)' == '$(StrideFramework)' Or '$(TargetFramework)' == '$(StrideFrameworkUWP)'" />
<PackageReference Include="Vortice.Vulkan" Condition="'$(TargetFramework)' == '$(StrideFramework)'" />
<PackageReference Include="Silk.NET.Direct3D11" Condition="'$(TargetFramework)' == '$(StrideFramework)' Or '$(TargetFramework)' == '$(StrideFrameworkUWP)'" />
Copy link
Member

Choose a reason for hiding this comment

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

UWP might be removed by #2450. Just to keep in mind in case it gets merged. No need to fix it now.

<ItemGroup>
<ProjectReference Include="..\Stride.Shaders.Parser\Stride.Shaders.Parser.csproj" />
<PackageReference Include="SharpDX.D3DCompiler" Condition="'$(TargetFramework)' == '$(StrideFramework)' Or '$(TargetFramework)' == '$(StrideFrameworkUWP)'" />
<PackageReference Include="Silk.NET.Direct3D.Compilers" Condition="'$(TargetFramework)' == '$(StrideFramework)' Or '$(TargetFramework)' == '$(StrideFrameworkUWP)'" />
Copy link
Member

Choose a reason for hiding this comment

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

UWP might be removed by #2450. Just to keep in mind in case it gets merged. No need to fix it now.

<PackageReference Include="SharpDX.MediaFoundation" Condition="'$(TargetFramework)' == '$(StrideFramework)' Or '$(TargetFramework)' == '$(StrideFrameworkUWP)'" />
<PackageReference Include="SharpDX.Direct3D11" Condition="'$(TargetFramework)' == '$(StrideFramework)' Or '$(TargetFramework)' == '$(StrideFrameworkUWP)'" />
<PackageReference Include="SharpDX.Direct3D12" Condition="'$(TargetFramework)' == '$(StrideFramework)'" />
<PackageReference Include="Silk.NET.Direct3D11" Condition="'$(TargetFramework)' == '$(StrideFramework)' Or '$(TargetFramework)' == '$(StrideFrameworkUWP)'" />
Copy link
Member

Choose a reason for hiding this comment

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

UWP might be removed by #2450. Just to keep in mind in case it gets merged. No need to fix it now.

<ProjectReference Include="..\..\engine\Stride.Graphics\Stride.Graphics.csproj" />
<PackageReference Include="Microsoft.Win32.Registry" />
<PackageReference Include="SharpDX.Direct3D11" Condition="'$(TargetFramework)' == '$(StrideFramework)' Or '$(TargetFramework)' == '$(StrideFrameworkUWP)'" />
<PackageReference Include="Silk.NET.Direct3D11" Condition="'$(TargetFramework)' == '$(StrideFramework)' Or '$(TargetFramework)' == '$(StrideFrameworkUWP)'" />
Copy link
Member

Choose a reason for hiding this comment

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

UWP might be removed by #2450. Just to keep in mind in case it gets merged. No need to fix it now.

Copy link
Collaborator

Choose a reason for hiding this comment

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

microsoft/microsoft-ui-xaml#9983 (comment)
there is also the idea to make it available again

@Ethereal77
Copy link
Contributor Author

Yeah, I'm following the issue on UWP support. Will remove any reference entirely if not needed anymore.

@Ethereal77
Copy link
Contributor Author

I'm starting to upload most of the changes that I think are mostly ready.

As Direct3D 11 and 12 share a common way of doing things, I'm pushing just D3D 11 and DXGI for now. D3D 12 will come a bit later when I get feedback on D3D11.

I've just started with the Buffer class with the code changes. I have ready the added/improved documentation I've also writing, and I want to push it in a separate commit.

The question is: Should I do the documentation pass now? Or postpone it for a later time?
I ask this because the documentation is hugely verbose and will make more difficult reviewing the changes. There are a lot of additions also, so it will appear as a lot of green in diffs.

@VaclavElias
Copy link
Contributor

Thank you @Ethereal77. Lots of updates here. I would be ok with docs later but in this case I woud like a feedback from @Eideren or @Kryptos-FR regarding the docs because in some cases it might be very important.

@Kryptos-FR
Copy link
Member

Kryptos-FR commented Feb 26, 2025

I think it's fine to push the documentation here. As long as it's on a separate commit, it's always possible to do an offline review that ignore that particular commit.

But let's wait for @Eideren's point of view. I'm not a graphics expert so my review will be a bit more superficial, and is less likely to be encumbered by lots of comments 😅.

@Eideren
Copy link
Collaborator

Eideren commented Mar 1, 2025

Yep, I agree with @Kryptos-FR, if you already have the docs, might as well include it. My thinking is that it may also help the reviewer

@Ethereal77 Ethereal77 force-pushed the directx-silk branch 2 times, most recently from 6641453 to 40b9fcd Compare July 13, 2025 19:18
@anpin anpin mentioned this pull request Jul 17, 2025
* Also add the ability to set a name for a Graphics Resource in construction
* Also improves some of the debug facilities to better identify resources in logs and debugger
* Improve the documentation on Stride.Core types related to memory / disposables / reference counting
* Improve the documentation on platform type enums
@xen2
Copy link
Member

xen2 commented Sep 18, 2025

@Ethereal77 Curious, what's the state of this PR? (seeing it's still marked as draft)
Are there still unfinished parts? Or it's mostly testing from now on?
I was wondering if this could be part of 4.3 release (which will also contain .NET 10 upgrade)

@xen2
Copy link
Member

xen2 commented Sep 18, 2025

@Ethereal77 Also, considering the huge amount of effort, we would like to offer a bounty of $1500 (at least) once this task is completed.
I have just added money to the OpenCollective project: https://opencollective.com/stride3d/projects/stride3d-silknet
https://opencollective.com/stride3d/projects/stride3d-silknet

@Ethereal77
Copy link
Contributor Author

The PR is almost done. I'm running the test projects and correcting / fixing some small quirks. My intent is to have it ready as soon as possible. I can rebase it and push the current state if people want to start testing / reviewing.

I'm currently tracking down some tests that fail with invalid output (wrong alpha blending due to some zeroed-out description struct), or produce exceptions due to wrong parameters, but right now ~90% of the graphics tests pass with resulting images similar to reference.

Also, considering the huge amount of effort, we would like to offer a bounty of $1500 (at least) once this task is completed.

Thank you. I appreciate it.

@Ethereal77
Copy link
Contributor Author

Btw, tests are quite difficult to debug with RenderDoc since the migration to Avalonia (it throwns an exception inside the MicroCom interop layer of AvaloniaUI). Attach to running process doesn't work either for some reason. That is making finding some problems a little hard.

Do someone know how to make it work? I've seen GameTestBase have some mechanism to dump RenderDoc captures, but don't know how it works exactly.

@Ethereal77
Copy link
Contributor Author

Oh, and another thing that crossed my mind the other day @xen2 (for a different PR, not this one)

Would it make sense to, for the graphics tests when the platform is Direct3D, to use WARP as the adapter? If the goal is to test the renderer and catch regressions, the GPU is not very important, just the results of the rendering. WARP is always present, it is slower, but for tests ran sporadically it won't matter much, and it would make the need to still count with that GTX 960 redundant. Finally, as WARP is software based, everyone that runs the tests will get a consistent 1:1 output unless there are true regressions or changes.

(with WARP I mean the Windows Advanced Rasterization Platform)

@Eideren
Copy link
Collaborator

Eideren commented Sep 19, 2025

We have this section in the manual about render doc https://doc.stride3d.net/latest/en/manual/troubleshooting/profiling.html?q=renderdoc#use-renderdoc not sure how useful that could be in your particular case but might as well share just in case

@Ethereal77
Copy link
Contributor Author

I've managed to get the tests to generate a RenderDoc capture by forcing it in GameTestBase (although it can also be done via an environment variable). With this, I can now review the tests that are behaving strangely.

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

Successfully merging this pull request may close these issues.

Convert from SharpDX to Silk.NET
9 participants