Skip to content

Commit 714eb63

Browse files
authored
fix: crash when resizing render window and at the same time creating textures in a background thread (#2842)
A relevant lock statement on the internal GraphicsDevice.Resources collection was missing.
1 parent a0f949c commit 714eb63

File tree

2 files changed

+65
-46
lines changed

2 files changed

+65
-46
lines changed

sources/engine/Stride.Graphics/Direct3D/SwapChainGraphicsPresenter.Direct3D.cs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -336,13 +336,17 @@ protected override void ResizeDepthStencilBuffer(int width, int height, PixelFor
336336
private FastList<Texture> DestroyChildrenTextures(Texture parentTexture)
337337
{
338338
var fastList = new FastList<Texture>();
339-
foreach (var resource in GraphicsDevice.Resources)
339+
var resources = GraphicsDevice.Resources;
340+
lock (resources)
340341
{
341-
var texture = resource as Texture;
342-
if (texture != null && texture.ParentTexture == parentTexture)
342+
foreach (var resource in resources)
343343
{
344-
texture.OnDestroyed();
345-
fastList.Add(texture);
344+
var texture = resource as Texture;
345+
if (texture != null && texture.ParentTexture == parentTexture)
346+
{
347+
texture.OnDestroyed();
348+
fastList.Add(texture);
349+
}
346350
}
347351
}
348352

sources/engine/Stride.Graphics/ResumeManager.cs

Lines changed: 56 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -41,22 +41,28 @@ public void OnRender()
4141

4242
public void Pause()
4343
{
44-
foreach (var resource in graphicsDevice.Resources)
44+
lock (graphicsDevice.Resources)
4545
{
46-
if (resource.OnPause())
47-
resource.LifetimeState = GraphicsResourceLifetimeState.Paused;
46+
foreach (var resource in graphicsDevice.Resources)
47+
{
48+
if (resource.OnPause())
49+
resource.LifetimeState = GraphicsResourceLifetimeState.Paused;
50+
}
4851
}
4952
}
5053

5154
public void OnResume()
5255
{
53-
foreach (var resource in graphicsDevice.Resources)
56+
lock (graphicsDevice.Resources)
5457
{
55-
if (resource.LifetimeState == GraphicsResourceLifetimeState.Paused)
58+
foreach (var resource in graphicsDevice.Resources)
5659
{
57-
resource.OnResume();
58-
resource.LifetimeState = GraphicsResourceLifetimeState.Active;
59-
}
60+
if (resource.LifetimeState == GraphicsResourceLifetimeState.Paused)
61+
{
62+
resource.OnResume();
63+
resource.LifetimeState = GraphicsResourceLifetimeState.Active;
64+
}
65+
}
6066
}
6167
}
6268

@@ -68,47 +74,53 @@ public void OnRecreate()
6874
bool wasSomethingRecreated = true;
6975
bool hasDestroyedObjects = true;
7076

71-
// Only continue if we made some progress, otherwise that means we reached something that could not be solved
72-
// This allows for dependencies to still be handled without some complex system
73-
// (we don't really care of recreation performance/complexity).
74-
while (wasSomethingRecreated && hasDestroyedObjects)
77+
lock (graphicsDevice.Resources)
7578
{
76-
// Let's track if something happened during this loop
77-
wasSomethingRecreated = false;
78-
hasDestroyedObjects = false;
79-
80-
foreach (var resource in graphicsDevice.Resources)
79+
// Only continue if we made some progress, otherwise that means we reached something that could not be solved
80+
// This allows for dependencies to still be handled without some complex system
81+
// (we don't really care of recreation performance/complexity).
82+
while (wasSomethingRecreated && hasDestroyedObjects)
8183
{
82-
if (resource.LifetimeState == GraphicsResourceLifetimeState.Destroyed)
84+
// Let's track if something happened during this loop
85+
wasSomethingRecreated = false;
86+
hasDestroyedObjects = false;
87+
88+
foreach (var resource in graphicsDevice.Resources)
8389
{
84-
if (resource.OnRecreate())
85-
{
86-
wasSomethingRecreated = true;
87-
resource.LifetimeState = GraphicsResourceLifetimeState.Active;
88-
}
89-
else
90+
if (resource.LifetimeState == GraphicsResourceLifetimeState.Destroyed)
9091
{
91-
// Couldn't be recreated?
92-
hasDestroyedObjects = true;
92+
if (resource.OnRecreate())
93+
{
94+
wasSomethingRecreated = true;
95+
resource.LifetimeState = GraphicsResourceLifetimeState.Active;
96+
}
97+
else
98+
{
99+
// Couldn't be recreated?
100+
hasDestroyedObjects = true;
101+
}
93102
}
94103
}
95104
}
96-
}
97105

98-
if (hasDestroyedObjects)
99-
{
100-
// Attach the list of objects that could not be recreated to the exception.
101-
var destroyedObjects = graphicsDevice.Resources.Where(x => x.LifetimeState == GraphicsResourceLifetimeState.Destroyed).ToList();
102-
throw new InvalidOperationException("Could not recreate all objects.") { Data = { { "DestroyedObjects", destroyedObjects } } };
106+
if (hasDestroyedObjects)
107+
{
108+
// Attach the list of objects that could not be recreated to the exception.
109+
var destroyedObjects = graphicsDevice.Resources.Where(x => x.LifetimeState == GraphicsResourceLifetimeState.Destroyed).ToList();
110+
throw new InvalidOperationException("Could not recreate all objects.") { Data = { { "DestroyedObjects", destroyedObjects } } };
111+
}
103112
}
104113
}
105114

106115
public void OnDestroyed()
107116
{
108-
foreach (var resource in graphicsDevice.Resources)
117+
lock (graphicsDevice.Resources)
109118
{
110-
resource.OnDestroyed();
111-
resource.LifetimeState = GraphicsResourceLifetimeState.Destroyed;
119+
foreach (var resource in graphicsDevice.Resources)
120+
{
121+
resource.OnDestroyed();
122+
resource.LifetimeState = GraphicsResourceLifetimeState.Destroyed;
123+
}
112124
}
113125

114126
// Clear various graphics device internal states (input layouts, FBOs, etc...)
@@ -117,16 +129,19 @@ public void OnDestroyed()
117129

118130
public void OnReload()
119131
{
120-
foreach (var resource in graphicsDevice.Resources)
132+
lock (graphicsDevice.Resources)
121133
{
122-
if (resource.LifetimeState == GraphicsResourceLifetimeState.Destroyed)
134+
foreach (var resource in graphicsDevice.Resources)
123135
{
124-
if (resource.Reload != null)
136+
if (resource.LifetimeState == GraphicsResourceLifetimeState.Destroyed)
125137
{
126-
resource.Reload(resource, services);
127-
resource.LifetimeState = GraphicsResourceLifetimeState.Active;
138+
if (resource.Reload != null)
139+
{
140+
resource.Reload(resource, services);
141+
resource.LifetimeState = GraphicsResourceLifetimeState.Active;
142+
}
128143
}
129-
}
144+
}
130145
}
131146
}
132147
}

0 commit comments

Comments
 (0)