[PATCH 3/7] wined3d: Evict system memory for complete textures.

Henri Verbeet hverbeet at codeweavers.com
Wed Apr 20 12:29:11 CDT 2016


Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
 dlls/wined3d/surface.c         | 25 ------------------
 dlls/wined3d/texture.c         | 60 +++++++++++++++++++++++++++++++++++++-----
 dlls/wined3d/volume.c          | 25 ------------------
 dlls/wined3d/wined3d_private.h |  1 +
 4 files changed, 55 insertions(+), 56 deletions(-)

diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 7a71193..075de5f 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -33,8 +33,6 @@
 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
 WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
 
-#define MAXLOCKCOUNT 50 /* After this amount of locks do not free the sysmem copy. */
-
 static const DWORD surface_simple_locations = WINED3D_LOCATION_SYSMEM
         | WINED3D_LOCATION_USER_MEMORY | WINED3D_LOCATION_BUFFER;
 
@@ -429,19 +427,6 @@ HRESULT wined3d_surface_create_dc(struct wined3d_surface *surface)
     return WINED3D_OK;
 }
 
-static void surface_evict_sysmem(struct wined3d_surface *surface)
-{
-    unsigned int sub_resource_idx = surface_get_sub_resource_idx(surface);
-    struct wined3d_texture *texture = surface->container;
-
-    if (texture->sub_resources[sub_resource_idx].map_count || texture->download_count > MAXLOCKCOUNT
-            || texture->flags & (WINED3D_TEXTURE_CONVERTED | WINED3D_TEXTURE_PIN_SYSMEM))
-        return;
-
-    wined3d_resource_free_sysmem(&surface->resource);
-    wined3d_texture_invalidate_location(texture, sub_resource_idx, WINED3D_LOCATION_SYSMEM);
-}
-
 static BOOL surface_is_full_rect(const struct wined3d_surface *surface, const RECT *r)
 {
     unsigned int t;
@@ -2531,8 +2516,6 @@ static HRESULT surface_blt_special(struct wined3d_surface *dst_surface, const RE
             fb_copy_to_texture_hwstretch(dst_surface, src_surface, src_rect, dst_rect, filter);
         }
 
-        surface_evict_sysmem(dst_surface);
-
         return WINED3D_OK;
     }
 
@@ -3153,9 +3136,6 @@ done:
         surface->ds_current_size.cy = surface_h;
     }
 
-    if (location != WINED3D_LOCATION_SYSMEM && (sub_resource->locations & WINED3D_LOCATION_SYSMEM))
-        surface_evict_sysmem(surface);
-
     return WINED3D_OK;
 }
 
@@ -4332,7 +4312,6 @@ cpu:
 HRESULT wined3d_surface_init(struct wined3d_surface *surface, struct wined3d_texture *container,
         const struct wined3d_resource_desc *desc, GLenum target, unsigned int level, unsigned int layer)
 {
-    unsigned int sub_resource_idx = layer * container->level_count + level;
     struct wined3d_device *device = container->resource.device;
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
     const struct wined3d_format *format = wined3d_get_format(gl_info, desc->format);
@@ -4361,10 +4340,6 @@ HRESULT wined3d_surface_init(struct wined3d_surface *surface, struct wined3d_tex
     list_init(&surface->renderbuffers);
     list_init(&surface->overlays);
 
-    wined3d_texture_validate_location(container, sub_resource_idx, WINED3D_LOCATION_SYSMEM);
-    if (container->resource.usage & WINED3DUSAGE_DEPTHSTENCIL)
-        container->sub_resources[sub_resource_idx].locations = WINED3D_LOCATION_DISCARDED;
-
     return hr;
 }
 
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index ada571c..047e12d 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -28,6 +28,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d);
 WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
 WINE_DECLARE_DEBUG_CHANNEL(winediag);
 
+#define WINED3D_TEXTURE_DYNAMIC_MAP_THRESHOLD 50
+
 static BOOL wined3d_texture_use_pbo(const struct wined3d_texture *texture, const struct wined3d_gl_info *gl_info)
 {
     return texture->resource.pool == WINED3D_POOL_DEFAULT
@@ -69,16 +71,47 @@ GLenum wined3d_texture_get_gl_buffer(const struct wined3d_texture *texture)
     return GL_BACK;
 }
 
+static void wined3d_texture_evict_sysmem(struct wined3d_texture *texture)
+{
+    struct wined3d_texture_sub_resource *sub_resource;
+    unsigned int i, sub_count;
+
+    if (texture->flags & (WINED3D_TEXTURE_CONVERTED | WINED3D_TEXTURE_PIN_SYSMEM)
+            || texture->download_count > WINED3D_TEXTURE_DYNAMIC_MAP_THRESHOLD)
+    {
+        TRACE("Not evicting system memory for texture %p.\n", texture);
+        return;
+    }
+
+    TRACE("Evicting system memory for texture %p.\n", texture);
+
+    sub_count = texture->level_count * texture->layer_count;
+    for (i = 0; i < sub_count; ++i)
+    {
+        sub_resource = &texture->sub_resources[i];
+        if (sub_resource->locations == WINED3D_LOCATION_SYSMEM)
+            ERR("WINED3D_LOCATION_SYSMEM is the only location for sub-resource %u of texture %p.\n",
+                    i, texture);
+        sub_resource->locations &= ~WINED3D_LOCATION_SYSMEM;
+        wined3d_resource_free_sysmem(sub_resource->resource);
+    }
+}
+
 void wined3d_texture_validate_location(struct wined3d_texture *texture,
         unsigned int sub_resource_idx, DWORD location)
 {
     struct wined3d_texture_sub_resource *sub_resource;
+    DWORD previous_locations;
 
     TRACE("texture %p, sub_resource_idx %u, location %s.\n",
             texture, sub_resource_idx, wined3d_debug_location(location));
 
     sub_resource = &texture->sub_resources[sub_resource_idx];
+    previous_locations = sub_resource->locations;
     sub_resource->locations |= location;
+    if (previous_locations == WINED3D_LOCATION_SYSMEM && location != WINED3D_LOCATION_SYSMEM
+            && !--texture->sysmem_count)
+        wined3d_texture_evict_sysmem(texture);
 
     TRACE("New locations flags are %s.\n", wined3d_debug_location(sub_resource->locations));
 }
@@ -96,6 +129,8 @@ void wined3d_texture_invalidate_location(struct wined3d_texture *texture,
 
     sub_resource = &texture->sub_resources[sub_resource_idx];
     sub_resource->locations &= ~location;
+    if (sub_resource->locations == WINED3D_LOCATION_SYSMEM)
+        ++texture->sysmem_count;
 
     TRACE("New locations flags are %s.\n", wined3d_debug_location(sub_resource->locations));
 
@@ -970,6 +1005,7 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
     sub_resource->resource->width = width;
     sub_resource->resource->height = height;
     sub_resource->resource->size = texture->slice_pitch;
+    sub_resource->locations = WINED3D_LOCATION_DISCARDED;
 
     if (((width & (width - 1)) || (height & (height - 1))) && !gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]
             && !gl_info->supported[ARB_TEXTURE_RECTANGLE] && !gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT])
@@ -988,8 +1024,6 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
         texture->pow2_height = height;
     }
 
-    sub_resource->locations = 0;
-
     if ((texture->user_memory = mem))
     {
         texture->resource.map_binding = WINED3D_LOCATION_USER_MEMORY;
@@ -1009,6 +1043,7 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
         texture->resource.map_binding = WINED3D_LOCATION_SYSMEM;
 
     wined3d_texture_validate_location(texture, 0, valid_location);
+    wined3d_texture_invalidate_location(texture, 0, ~valid_location);
 
     if (create_dib)
         wined3d_surface_create_dc(surface);
@@ -1849,6 +1884,7 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3
                 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
             };
             GLenum target = desc->usage & WINED3DUSAGE_LEGACY_CUBEMAP ? cube_targets[j] : texture->target;
+            struct wined3d_texture_sub_resource *sub_resource;
             unsigned int idx = j * texture->level_count + i;
             struct wined3d_surface *surface;
 
@@ -1862,6 +1898,16 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3
                 return hr;
             }
 
+            sub_resource = &texture->sub_resources[idx];
+            sub_resource->locations = WINED3D_LOCATION_DISCARDED;
+            sub_resource->resource = &surface->resource;
+            sub_resource->u.surface = surface;
+            if (!(texture->resource.usage & WINED3DUSAGE_DEPTHSTENCIL))
+            {
+                wined3d_texture_validate_location(texture, idx, WINED3D_LOCATION_SYSMEM);
+                wined3d_texture_invalidate_location(texture, idx, ~WINED3D_LOCATION_SYSMEM);
+            }
+
             if (FAILED(hr = device_parent->ops->surface_created(device_parent,
                     texture, idx, &parent, &parent_ops)))
             {
@@ -1875,8 +1921,6 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3
 
             surface->resource.parent = parent;
             surface->resource.parent_ops = parent_ops;
-            texture->sub_resources[idx].resource = &surface->resource;
-            texture->sub_resources[idx].u.surface = surface;
             TRACE("Created surface level %u, layer %u @ %p.\n", i, j, surface);
 
             if (((desc->usage & WINED3DUSAGE_OWNDC) || (device->wined3d->flags & WINED3D_NO3D))
@@ -2097,6 +2141,7 @@ static HRESULT volumetexture_init(struct wined3d_texture *texture, const struct
     volume_desc.resource_type = WINED3D_RTYPE_VOLUME;
     for (i = 0; i < texture->level_count; ++i)
     {
+        struct wined3d_texture_sub_resource *sub_resource;
         struct wined3d_volume *volume;
 
         volume = &volumes[i];
@@ -2109,6 +2154,11 @@ static HRESULT volumetexture_init(struct wined3d_texture *texture, const struct
             return hr;
         }
 
+        sub_resource = &texture->sub_resources[i];
+        sub_resource->locations = WINED3D_LOCATION_DISCARDED;
+        sub_resource->resource = &volume->resource;
+        sub_resource->u.volume = volume;
+
         if (FAILED(hr = device_parent->ops->volume_created(device_parent,
                 texture, i, &parent, &parent_ops)))
         {
@@ -2122,8 +2172,6 @@ static HRESULT volumetexture_init(struct wined3d_texture *texture, const struct
 
         volume->resource.parent = parent;
         volume->resource.parent_ops = parent_ops;
-        texture->sub_resources[i].resource = &volume->resource;
-        texture->sub_resources[i].u.volume = volume;
         TRACE("Created volume level %u @ %p.\n", i, volume);
 
         /* Calculate the next mipmap level. */
diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c
index ce3809f..6a92211 100644
--- a/dlls/wined3d/volume.c
+++ b/dlls/wined3d/volume.c
@@ -121,12 +121,6 @@ static void wined3d_volume_download_data(struct wined3d_volume *volume,
 
 }
 
-static void wined3d_volume_evict_sysmem(struct wined3d_volume *volume)
-{
-    wined3d_resource_free_sysmem(&volume->resource);
-    wined3d_texture_invalidate_location(volume->container, volume->texture_level, WINED3D_LOCATION_SYSMEM);
-}
-
 static DWORD volume_access_from_location(DWORD location)
 {
     switch (location)
@@ -174,20 +168,6 @@ static void wined3d_volume_srgb_transfer(struct wined3d_volume *volume,
     HeapFree(GetProcessHeap(), 0, data.addr);
 }
 
-static BOOL wined3d_volume_can_evict(const struct wined3d_volume *volume)
-{
-    struct wined3d_texture *texture = volume->container;
-
-    if (texture->resource.pool != WINED3D_POOL_MANAGED)
-        return FALSE;
-    if (texture->download_count >= 10)
-        return FALSE;
-    if (texture->resource.format->convert)
-        return FALSE;
-
-    return TRUE;
-}
-
 /* Context activation is done by the caller. */
 BOOL wined3d_volume_load_location(struct wined3d_volume *volume,
         struct wined3d_context *context, DWORD location)
@@ -308,9 +288,6 @@ BOOL wined3d_volume_load_location(struct wined3d_volume *volume,
 done:
     wined3d_texture_validate_location(texture, sub_resource_idx, location);
 
-    if (location != WINED3D_LOCATION_SYSMEM && wined3d_volume_can_evict(volume))
-        wined3d_volume_evict_sysmem(volume);
-
     return TRUE;
 }
 
@@ -387,8 +364,6 @@ HRESULT wined3d_volume_init(struct wined3d_volume *volume, struct wined3d_textur
         wined3d_resource_free_sysmem(&volume->resource);
 
     volume->texture_level = level;
-    container->sub_resources[level].locations = WINED3D_LOCATION_DISCARDED;
-
     volume->container = container;
 
     return WINED3D_OK;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index f630223..4f06796 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2467,6 +2467,7 @@ struct wined3d_texture
     UINT layer_count;
     UINT level_count;
     unsigned int download_count;
+    unsigned int sysmem_count;
     float pow2_matrix[16];
     UINT lod;
     enum wined3d_texture_filter_type filter_type;
-- 
2.1.4




More information about the wine-patches mailing list