microsoft / angle

ANGLE: OpenGL ES to DirectX translation
Other
615 stars 166 forks source link

Multithreaded support/Shared contexts question #61

Closed MihaiBairac closed 8 years ago

MihaiBairac commented 8 years ago

Hello guys,

Will Angle support shared contexts?

I am asking this question, because am working on a project which uses a graphics engine and I am integrating ANGLE into it.The engine already supports: opengles and directx11, but I want to see if it's gonna work with Angle on windows(win32 for starters, then see if metro app will work). The engine uses mutliple threads for doing stuff like: rendering, streaming, skinning and so on.

I haven't used shared contexts before, I mean like ever. Neither in OpenGL/DirectX nor in OpenGLES. I read somewhere that OpenGLES support for shared contexts is limited.

I know there was an issue related to this: #45 (Crash when using multithreaded on Windows 10 pc app).

I have found this great article explaining stuff about OpenGL contexts: https://blog.gvnott.com/some-usefull-facts-about-multipul-opengl-contexts/

It was very enlighting for me, hope it's gonna help others too!

Thanks, Mihai

MihaiBairac commented 8 years ago

Hello,

In my previous post I explained why I need this. The error I receive when using Angle with the engine is: D3D11 CORRUPTION: ID3D11DeviceContext::CopySubresourceRegion: Two threads were found to be executing functions associated with the same Device[Context] at the same time. This will cause corruption of memory. Appropriate thread synchronization needs to occur external to the Direct3D API (or through the ID3D10Multithread interface). 2808 and 8152 are the implicated thread ids. [ MISCELLANEOUS CORRUPTION #28: CORRUPTED_MULTITHREADING]

So DirectX 11 complains about this and it has all the rights to do so.

I have found a workaround for shared contexts in Angle: https://gitlab.com/pteam/pteam-qtbase/commit/6b52e6ead90d718c2704590472d34adbbea86548

I applied the fix above and I no longer receive this message.

I'll keep this thread up to date on how things go along.

Thanks, Mihai

MihaiBairac commented 8 years ago

Hi again,

Well, up to this point ANGLE seems to behave ok with that fix. Are going to add it to master branch?

Thanks, Mihai

austinkinross commented 8 years ago

Hi Mihai,

Unfortunately, using ID3D10Multithread::SetMultithreadProtected isn't sufficient here.

SetMultithreadProtected essentially puts a lock around each call on the D3D11 context. This means that the context calls will be performed one-at-a-time in the order they're received, and it will prevent you from seeing the D3D SDK layers corruption warnings.

However, putting a lock around each individual D3D11 context call isn't sufficient because the D3D11 context has state that can be set by one call, and used or retrieved by another (for example: the viewport or shader resources). As a simplified example, say you have two separate threads, with one performing this:

ID3D11DeviceContext::RSSetViewports(Foo); // Thread 1
ID3D11DeviceContext::RSGetViewports(...); // Thread 1

And the other performing this at the same time:

ID3D11DeviceContext::RSSetViewports(Bar); // Thread 2
ID3D11DeviceContext::RSGetViewports(...); // Thread 2

These may be performed in this order:

ID3D11DeviceContext::RSSetViewports(Foo); // Thread 1
ID3D11DeviceContext::RSSetViewports(Bar); // Thread 2
ID3D11DeviceContext::RSGetViewports(...); // Thread 1 - This will return Bar when Foo was expected!
ID3D11DeviceContext::RSGetViewports(...); // Thread 2

So while SetMultithreadProtected has fixed the corruption warnings, the problem has just been shifted into ANGLE. This could easily lead to ANGLE performing unexpected or invalid rendering.

Instead of using SetMultithreadProtected, a better fix would be to put a lock in ANGLE around groups of D3D11 calls, but this is very complicated to get right.

There are other issues involved in supporting shared contexts:

  1. Other (non-D3D) code in ANGLE isn't thread-safe.
  2. DXGI isn't thread-safe, so there needs to be a lock around DXGI calls in ANGLE too.
  3. Using locks around D3D/DXGI would allow multiple contexts to work, but there wouldn't be any major perf win for the ANGLE user since the majority of ANGLE would be serialized under the hood. The locks would also make ANGLE slower for single-threaded users.

We don't have plans to add support for multiple contexts in the near future. You may wish to ask over on the master ANGLE repository discussion forums whether anyone else is planning to add support in the future.

Hope this helps! Austin

MihaiBairac commented 8 years ago

Hello Austin,

thank you for your comprehensive answer!

It seems I made DirectX thread-safe, but not Angle.

So this means even if I remove ID3D10Multithread::SetMultithreadProtected() from Angle and try to use locks in the engine code (that uses Angle) I still won't be able to have a stable environment? or if the locks would make it stable all would be serialized and because of the context switch it would be suboptimal?

Ok, so what can I do if I want to use Angle and need to use shared contexts?

Regards, Mihai

MihaiBairac commented 8 years ago

Hello again,

I have stumbled upon this: http://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-ANGLE.pdf

In that doc they speak about a verison of Angle which is based on DirectX9.

The point of interest is "39.3.11 Multiple Contexts and Resource Sharing" (page 561).

From what I know DirectX9 and 11 are different so, even if context sharing was ready in that version of Angle it's not gonna be too soon in this one....

I saw that in this version of Angle directx9 is still present in source code, but doesn't work. I tested with EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE instead of EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.

I just hope to find a stable workaround for shared contexts ...

Thanks, Mihai

austinkinross commented 8 years ago

ANGLE does support multiple contexts in both D3D9 and D3D11, but it doesn't support accessing them from different threads simultaneously. Putting locks in your engine code around appropriate groups of ANGLE calls should work, albeit sub-optimally as you say due to serialization.

DirectX 9 isn't supported in UWP apps since many version of Windows that support UWP apps don't have DirectX 9 drivers.

shahmeeresmail commented 8 years ago

Just like OpenGL, multithreading is only actually supported in D3D for a few number of operations (ex resource creation/destruction). Outside of this, you'll get runtime errors unless access as serialized (as some have already pointed out or encountered).

So there is really no benefit to even enabling multithreading on DX11 unless you would like to do some of these supported operations in parallel. As Austin pointed out, you'll have to serialize access to the context for other operations (since the gfx drivers are not thread safe for these items) and so all that will happen is that additional overhead will be generated from managing access to the context.

austinkinross commented 8 years ago

Hi all, I'm closing this issue since I believe the original question has been answered. Feel free to reactivate it if you have further questions on this subject.

Thanks!