[PATCH 4/7] wined3d: Avoid using destroyed context.
Józef Kucia
jkucia at codeweavers.com
Sun Oct 2 17:38:39 CDT 2016
The swapchain can be destroyed by state_unbind_resources()
if the only reference to a swapchain is kept by a shader resource view.
This happens in d3d10core and d3d11 tests when a device is destroyed
in test_swapchain_flip().
Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
---
This snip from a "WINEDEBUG=+d3d,warn+heap" log shows the problem:
trace:d3d:context_enter Entering context 0x17c4c8, level 2.
trace:d3d:context_release Releasing context 0x17c4c8, level 2.
trace:d3d:context_destroy Destroying ctx 0x17c4c8
trace:d3d:context_destroy_fbo_entry Destroy FBO 4.
trace:d3d:context_destroy_fbo_entry Destroy FBO 1.
trace:d3d:context_destroy_fbo_entry Destroy FBO 3.
trace:d3d:context_destroy_fbo_entry Destroy FBO 5.
trace:d3d:context_destroy_fbo_entry Destroy FBO 2.
trace:d3d:device_context_remove Removing context 0x17c4c8.
trace:d3d:context_acquire device 0x150bf0, target (nil).
trace:d3d:context_acquire Rendering onscreen.
trace:d3d:context_enter Entering context 0x16e7d8, level 1.
...
trace:d3d:context_release Releasing context 0x17c4c8, level 4277075694.
warn:d3d:context_release Context 0x17c4c8 is not the current context.
4277075694 is 0xfeeefeee
---
dlls/wined3d/device.c | 21 ++++++++++++---------
dlls/wined3d/stateblock.c | 25 ++++++++++++++++++-------
dlls/wined3d/wined3d_private.h | 1 +
3 files changed, 31 insertions(+), 16 deletions(-)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index b8ac88a..63889af 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -1159,14 +1159,7 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device)
if (device->cursor_texture)
wined3d_texture_decref(device->cursor_texture);
- state_unbind_resources(&device->state);
-
- /* Unload resources */
- LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry)
- {
- TRACE("Unloading resource %p.\n", resource);
- wined3d_cs_emit_unload_resource(device->cs, resource);
- }
+ state_unbind_shaders(&device->state);
wine_rb_clear(&device->samplers, device_free_sampler, NULL);
@@ -1186,11 +1179,20 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device)
destroy_default_samplers(device);
/* Release the context again as soon as possible. In particular,
- * releasing the render target views below may release the last reference
+ * releasing the resource views below may release the last reference
* to the swapchain associated with this context, which in turn will
* destroy the context. */
context_release(context);
+ state_unbind_resources(&device->state);
+
+ /* Unload resources */
+ LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry)
+ {
+ TRACE("Unloading resource %p.\n", resource);
+ wined3d_cs_emit_unload_resource(device->cs, resource);
+ }
+
/* Release the buffers (with sanity checks)*/
if (device->onscreen_depth_stencil)
{
@@ -4659,6 +4661,7 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
device->cursor_texture = NULL;
}
state_unbind_resources(&device->state);
+ state_unbind_shaders(&device->state);
}
if (device->fb.render_targets)
diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c
index 2fbfa2c..122dc0e 100644
--- a/dlls/wined3d/stateblock.c
+++ b/dlls/wined3d/stateblock.c
@@ -429,7 +429,6 @@ void state_unbind_resources(struct wined3d_state *state)
struct wined3d_sampler *sampler;
struct wined3d_texture *texture;
struct wined3d_buffer *buffer;
- struct wined3d_shader *shader;
unsigned int i, j;
if ((decl = state->vertex_declaration))
@@ -473,12 +472,6 @@ void state_unbind_resources(struct wined3d_state *state)
for (i = 0; i < WINED3D_SHADER_TYPE_COUNT; ++i)
{
- if ((shader = state->shader[i]))
- {
- state->shader[i] = NULL;
- wined3d_shader_decref(shader);
- }
-
for (j = 0; j < MAX_CONSTANT_BUFFERS; ++j)
{
if ((buffer = state->cb[i][j]))
@@ -508,12 +501,30 @@ void state_unbind_resources(struct wined3d_state *state)
}
}
+void state_unbind_shaders(struct wined3d_state *state)
+{
+ struct wined3d_shader *shader;
+ unsigned int i;
+
+ for (i = 0; i < WINED3D_SHADER_TYPE_COUNT; ++i)
+ {
+ if ((shader = state->shader[i]))
+ {
+ state->shader[i] = NULL;
+ wined3d_shader_decref(shader);
+ }
+ }
+}
+
void state_cleanup(struct wined3d_state *state)
{
unsigned int counter;
if (!(state->flags & WINED3D_STATE_NO_REF))
+ {
state_unbind_resources(state);
+ state_unbind_shaders(state);
+ }
for (counter = 0; counter < MAX_ACTIVE_LIGHTS; ++counter)
{
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index a968bda..226d55f 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -3017,6 +3017,7 @@ void state_init(struct wined3d_state *state, struct wined3d_fb_state *fb,
const struct wined3d_gl_info *gl_info, const struct wined3d_d3d_info *d3d_info,
DWORD flags) DECLSPEC_HIDDEN;
void state_unbind_resources(struct wined3d_state *state) DECLSPEC_HIDDEN;
+void state_unbind_shaders(struct wined3d_state *state) DECLSPEC_HIDDEN;
enum wined3d_push_constants
{
--
2.7.3
More information about the wine-patches
mailing list