[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