Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine/Makefile.kmk	(revision 42407)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine/Makefile.kmk	(revision 42408)
@@ -223,5 +223,6 @@
  	VBOX_WITH_WDDM \
 	VBOX_WINE_WITH_SINGLE_CONTEXT \
-	IN_VBOXLIBWINE
+	IN_VBOXLIBWINE \
+	VBOX_WINE_WITH_SHADER_CACHE
  wined3dwddm_INCS           = $(wined3d_INCS) \
  	$(PATH_ROOT)/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/device.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/device.c	(revision 42407)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/device.c	(revision 42408)
@@ -637,4 +637,8 @@
         This->haveHardwareCursor = FALSE;
 
+#ifdef VBOX_WINE_WITH_SHADER_CACHE
+        shader_chaches_term(This);
+#endif
+
         IWineD3D_Release(This->wined3d);
         This->wined3d = NULL;
@@ -1329,4 +1333,8 @@
     }
 
+#ifdef VBOX_WINE_WITH_SHADER_CACHE
+    object = vertexshader_check_cached(This, object);
+#endif
+
     TRACE("Created vertex shader %p.\n", object);
     *ppVertexShader = (IWineD3DVertexShader *)object;
@@ -1388,4 +1396,8 @@
         return hr;
     }
+
+#ifdef VBOX_WINE_WITH_SHADER_CACHE
+    object = pixelshader_check_cached(This, object);
+#endif
 
     TRACE("Created pixel shader %p.\n", object);
@@ -7326,4 +7338,8 @@
     device->blitter = adapter->blitter;
 
+#ifdef VBOX_WINE_WITH_SHADER_CACHE
+    shader_chaches_init(device);
+#endif
+
     return WINED3D_OK;
 }
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/shader.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/shader.c	(revision 42407)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/shader.c	(revision 42408)
@@ -1572,4 +1572,8 @@
 }
 
+#ifdef VBOX_WINE_WITH_SHADER_CACHE
+static void shader_chache_put(PVBOXEXT_HASHCACHE pCache, IWineD3DBaseShaderImpl *pShader);
+#endif
+
 static ULONG STDMETHODCALLTYPE vertexshader_Release(IWineD3DVertexShader *iface)
 {
@@ -1581,7 +1585,11 @@
     if (!refcount)
     {
+#ifdef VBOX_WINE_WITH_SHADER_CACHE
+        shader_chache_put(&((IWineD3DDeviceImpl*)shader->baseShader.device)->vshaderCache, (IWineD3DBaseShaderImpl*)shader);
+#else
         shader_cleanup((IWineD3DBaseShader *)iface);
         shader->baseShader.parent_ops->wined3d_object_destroyed(shader->baseShader.parent);
         HeapFree(GetProcessHeap(), 0, shader);
+#endif
     }
 
@@ -1975,7 +1983,11 @@
     if (!refcount)
     {
+#ifdef VBOX_WINE_WITH_SHADER_CACHE
+        shader_chache_put(&((IWineD3DDeviceImpl*)shader->baseShader.device)->pshaderCache, (IWineD3DBaseShaderImpl*)shader);
+#else
         shader_cleanup((IWineD3DBaseShader *)iface);
         shader->baseShader.parent_ops->wined3d_object_destroyed(shader->baseShader.parent);
         HeapFree(GetProcessHeap(), 0, shader);
+#endif
     }
 
@@ -2311,2 +2323,136 @@
     }
 }
+
+#ifdef VBOX_WINE_WITH_SHADER_CACHE
+
+static void shader_reinit(struct IWineD3DBaseShaderClass *shader, IWineD3DDeviceImpl *device,
+        IUnknown *parent, const struct wined3d_parent_ops *parent_ops)
+{
+    shader->ref = 1;
+    shader->device = (IWineD3DDevice *)device;
+    shader->parent = parent;
+    shader->parent_ops = parent_ops;
+    list_add_head(&device->shaders, &shader->shader_list_entry);
+}
+
+static DECLCALLBACK(uint32_t) shader_cache_hash(void *pvKey)
+{
+    uint32_t u32Hash, i;
+    DWORD *function;
+    IWineD3DBaseShaderImpl *pShader = (IWineD3DBaseShaderImpl *)pvKey;
+    if (pShader->baseShader.u32CacheDataInited)
+        return pShader->baseShader.u32Hash;
+
+    u32Hash = pShader->baseShader.functionLength;
+    function = pShader->baseShader.function;
+    for (i = 0; i < pShader->baseShader.functionLength / 4; ++i)
+    {
+        u32Hash += *function++;
+    }
+
+    for (i = 0; i < pShader->baseShader.functionLength % 4; ++i)
+    {
+        u32Hash += *((uint8_t*)function)++;
+    }
+
+    pShader->baseShader.u32Hash = u32Hash;
+    pShader->baseShader.u32CacheDataInited = TRUE;
+    return pShader->baseShader.u32Hash;
+}
+
+static DECLCALLBACK(bool) shader_cache_equal(void *pvKey1, void *pvKey2)
+{
+    IWineD3DBaseShaderImpl *pShader1 = (IWineD3DBaseShaderImpl *)pvKey1;
+    IWineD3DBaseShaderImpl *pShader2 = (IWineD3DBaseShaderImpl *)pvKey2;
+
+    if (pShader1 == pShader2)
+        return TRUE;
+
+    if (pShader1->baseShader.functionLength != pShader2->baseShader.functionLength)
+        return FALSE;
+
+    if (shader_cache_hash(pvKey1) != shader_cache_hash(pvKey2))
+    {
+#ifdef DEBUG_misha
+        Assert(memcmp(pShader1->baseShader.function, pShader2->baseShader.function, pShader1->baseShader.functionLength));
+#endif
+        return FALSE;
+    }
+
+    return !memcmp(pShader1->baseShader.function, pShader2->baseShader.function, pShader1->baseShader.functionLength);
+}
+
+#define VBOX_SHADER_FROM_CACHE_ENTRY(_pEntry) RT_FROM_MEMBER(RT_FROM_MEMBER((_pEntry), IWineD3DBaseShaderClass, CacheEntry), IWineD3DBaseShaderImpl, baseShader)
+
+static DECLCALLBACK(void) shader_cache_cleanup_entry(void *pvKey, struct VBOXEXT_HASHCACHE_ENTRY *pEntry)
+{
+    IWineD3DBaseShaderImpl *pShader = VBOX_SHADER_FROM_CACHE_ENTRY(pEntry);
+    shader_cleanup((IWineD3DBaseShader *)pShader);
+    if (pShader->baseShader.parent)
+        pShader->baseShader.parent_ops->wined3d_object_destroyed(pShader->baseShader.parent);
+    HeapFree(GetProcessHeap(), 0, pShader);
+}
+
+static void shader_chache_init(PVBOXEXT_HASHCACHE pCache)
+{
+    VBoxExtCacheInit(pCache, 1024, shader_cache_hash, shader_cache_equal, shader_cache_cleanup_entry);
+}
+
+static void shader_chache_term(PVBOXEXT_HASHCACHE pCache)
+{
+    VBoxExtCacheTerm(pCache);
+}
+
+static void shader_chache_put(PVBOXEXT_HASHCACHE pCache, IWineD3DBaseShaderImpl *pShader)
+{
+    if (pShader->baseShader.parent)
+    {
+        pShader->baseShader.parent_ops->wined3d_object_destroyed(pShader->baseShader.parent);
+        pShader->baseShader.parent = NULL;
+    }
+
+    VBoxExtCachePut(pCache, pShader, &pShader->baseShader.CacheEntry);
+}
+
+static IWineD3DBaseShaderImpl* shader_chache_get(PVBOXEXT_HASHCACHE pCache, IWineD3DBaseShaderImpl *pShader)
+{
+    PVBOXEXT_HASHCACHE_ENTRY pEntry = VBoxExtCacheGet(pCache, pShader);
+    IWineD3DBaseShaderImpl *pCachedShader;
+
+    if (!pEntry)
+        return pShader;
+
+    Assert(0);
+
+    pCachedShader = VBOX_SHADER_FROM_CACHE_ENTRY(pEntry);
+    shader_reinit(&pCachedShader->baseShader, (IWineD3DDeviceImpl *)pShader->baseShader.device,
+            pShader->baseShader.parent, pShader->baseShader.parent_ops);
+    pShader->baseShader.parent = NULL;
+    /* we can not do a IWineD3DBaseShader_Release here since this would result in putting a shader to the cache */
+    shader_cleanup((IWineD3DBaseShader *)pShader);
+    HeapFree(GetProcessHeap(), 0, pShader);
+    return pCachedShader;
+}
+
+IWineD3DVertexShaderImpl * vertexshader_check_cached(IWineD3DDeviceImpl *device, IWineD3DVertexShaderImpl *object)
+{
+    return (IWineD3DVertexShaderImpl*)shader_chache_get(&device->vshaderCache, (IWineD3DBaseShaderImpl *)object);
+}
+
+IWineD3DPixelShaderImpl * pixelshader_check_cached(IWineD3DDeviceImpl *device, IWineD3DPixelShaderImpl *object)
+{
+    return (IWineD3DPixelShaderImpl*)shader_chache_get(&device->pshaderCache, (IWineD3DBaseShaderImpl *)object);
+}
+
+void shader_chaches_init(IWineD3DDeviceImpl *device)
+{
+    shader_chache_init(&device->vshaderCache);
+    shader_chache_init(&device->pshaderCache);
+}
+
+void shader_chaches_term(IWineD3DDeviceImpl *device)
+{
+    shader_chache_term(&device->vshaderCache);
+    shader_chache_term(&device->pshaderCache);
+}
+#endif
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/vboxext.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/vboxext.c	(revision 42407)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/vboxext.c	(revision 42408)
@@ -683,2 +683,143 @@
     return S_OK;
 }
+
+
+/* hash map impl */
+static void vboxExtHashInitEntries(PVBOXEXT_HASHMAP pMap)
+{
+    uint32_t i;
+    pMap->cEntries = 0;
+    for (i = 0; i < RT_ELEMENTS(pMap->aBuckets); ++i)
+    {
+        RTListInit(&pMap->aBuckets[i].EntryList);
+    }
+}
+
+void VBoxExtHashInit(PVBOXEXT_HASHMAP pMap, PFNVBOXEXT_HASHMAP_HASH pfnHash, PFNVBOXEXT_HASHMAP_EQUAL pfnEqual)
+{
+    pMap->pfnHash = pfnHash;
+    pMap->pfnEqual = pfnEqual;
+    vboxExtHashInitEntries(pMap);
+}
+
+static DECLINLINE(uint32_t) vboxExtHashIdx(uint32_t u32Hash)
+{
+    return u32Hash % VBOXEXT_HASHMAP_NUM_BUCKETS;
+}
+
+#define VBOXEXT_FOREACH_NODE(_pNode, _pList, _op) do { \
+        PRTLISTNODE _pNode; \
+        PRTLISTNODE __pNext; \
+        for (_pNode = (_pList)->pNext; \
+                _pNode != (_pList); \
+                _pNode = __pNext) \
+        { \
+            __pNext = _pNode->pNext; /* <- the _pNode should not be referenced after the _op */ \
+            _op \
+        } \
+    } while (0)
+
+DECLINLINE(PVBOXEXT_HASHMAP_ENTRY) vboxExtHashSearchEntry(PVBOXEXT_HASHMAP pMap, void *pvKey)
+{
+    uint32_t u32Hash = pMap->pfnHash(pvKey);
+    uint32_t u32HashIdx = vboxExtHashIdx(u32Hash);
+    PVBOXEXT_HASHMAP_BUCKET pBucket = &pMap->aBuckets[u32HashIdx];
+    PVBOXEXT_HASHMAP_ENTRY pEntry;
+    VBOXEXT_FOREACH_NODE(pNode, &pBucket->EntryList,
+        pEntry = RT_FROM_MEMBER(pNode, VBOXEXT_HASHMAP_ENTRY, ListNode);
+        if (pEntry->u32Hash != u32Hash)
+            continue;
+
+        if (!pMap->pfnEqual(pvKey, pEntry->pvKey))
+            continue;
+        return pEntry;
+    );
+    return NULL;
+}
+
+void* VBoxExtHashRemoveEntry(PVBOXEXT_HASHMAP pMap, PVBOXEXT_HASHMAP_ENTRY pEntry)
+{
+    RTListNodeRemove(&pEntry->ListNode);
+    --pMap->cEntries;
+    Assert(pMap->cEntries <= UINT32_MAX/2);
+    return pEntry->pvKey;
+}
+
+static void vboxExtHashPutEntry(PVBOXEXT_HASHMAP pMap, PVBOXEXT_HASHMAP_BUCKET pBucket, PVBOXEXT_HASHMAP_ENTRY pEntry)
+{
+    RTListNodeInsertAfter(&pBucket->EntryList, &pEntry->ListNode);
+    ++pMap->cEntries;
+}
+
+PVBOXEXT_HASHMAP_ENTRY VBoxExtHashRemove(PVBOXEXT_HASHMAP pMap, void *pvKey)
+{
+    PVBOXEXT_HASHMAP_ENTRY pEntry = vboxExtHashSearchEntry(pMap, pvKey);
+    if (!pEntry)
+        return NULL;
+
+    VBoxExtHashRemoveEntry(pMap, pEntry);
+    return pEntry;
+}
+
+PVBOXEXT_HASHMAP_ENTRY VBoxExtHashPut(PVBOXEXT_HASHMAP pMap, void *pvKey, PVBOXEXT_HASHMAP_ENTRY pEntry)
+{
+    PVBOXEXT_HASHMAP_ENTRY pOldEntry = VBoxExtHashRemove(pMap, pvKey);
+    uint32_t u32Hash = pMap->pfnHash(pvKey);
+    uint32_t u32HashIdx = vboxExtHashIdx(u32Hash);
+    pEntry->pvKey = pvKey;
+    pEntry->u32Hash = u32Hash;
+    vboxExtHashPutEntry(pMap, &pMap->aBuckets[u32HashIdx], pEntry);
+    return pOldEntry;
+}
+
+
+PVBOXEXT_HASHMAP_ENTRY VBoxExtHashGet(PVBOXEXT_HASHMAP pMap, void *pvKey)
+{
+    return vboxExtHashSearchEntry(pMap, pvKey);
+}
+
+void VBoxExtHashVisit(PVBOXEXT_HASHMAP pMap, PFNVBOXEXT_HASHMAP_VISITOR pfnVisitor, void *pvVisitor)
+{
+    uint32_t iBucket = 0, iEntry = 0;
+    uint32_t cEntries = pMap->cEntries;
+
+    if (!cEntries)
+        return;
+
+    for (; ; ++iBucket)
+    {
+        PVBOXEXT_HASHMAP_ENTRY pEntry;
+        PVBOXEXT_HASHMAP_BUCKET pBucket = &pMap->aBuckets[iBucket];
+        Assert(iBucket < RT_ELEMENTS(pMap->aBuckets));
+        VBOXEXT_FOREACH_NODE(pNode, &pBucket->EntryList,
+            pEntry = RT_FROM_MEMBER(pNode, VBOXEXT_HASHMAP_ENTRY, ListNode);
+            if (!pfnVisitor(pMap, pEntry->pvKey, pEntry, pvVisitor))
+                return;
+
+            if (++iEntry == cEntries)
+                return;
+        );
+    }
+
+    /* should not be here! */
+    AssertFailed();
+}
+
+void VBoxExtHashCleanup(PVBOXEXT_HASHMAP pMap, PFNVBOXEXT_HASHMAP_VISITOR pfnVisitor, void *pvVisitor)
+{
+    VBoxExtHashVisit(pMap, pfnVisitor, pvVisitor);
+    vboxExtHashInitEntries(pMap);
+}
+
+static DECLCALLBACK(bool) vboxExtCacheCleanupCb(struct VBOXEXT_HASHMAP *pMap, void *pvKey, struct VBOXEXT_HASHMAP_ENTRY *pValue, void *pvVisitor)
+{
+    PVBOXEXT_HASHCACHE pCache = VBOXEXT_HASHCACHE_FROM_MAP(pMap);
+    PVBOXEXT_HASHCACHE_ENTRY pCacheEntry = VBOXEXT_HASHCACHE_ENTRY_FROM_MAP(pValue);
+    pCache->pfnCleanupEntry(pvKey, pCacheEntry);
+    return TRUE;
+}
+
+void VBoxExtCacheCleanup(PVBOXEXT_HASHCACHE pCache)
+{
+    VBoxExtHashCleanup(&pCache->Map, vboxExtCacheCleanupCb, NULL);
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/vboxext.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/vboxext.h	(revision 42407)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/vboxext.h	(revision 42408)
@@ -20,4 +20,6 @@
 # include <windows.h>
 #endif
+
+#include <iprt/list.h>
 
 HRESULT VBoxExtCheckInit();
@@ -45,3 +47,107 @@
 HRESULT VBoxExtWndCreate(DWORD width, DWORD height, HWND *phWnd, HDC *phDC);
 
+
+/* hashmap */
+typedef DECLCALLBACK(uint32_t) FNVBOXEXT_HASHMAP_HASH(void *pvKey);
+typedef FNVBOXEXT_HASHMAP_HASH *PFNVBOXEXT_HASHMAP_HASH;
+
+typedef DECLCALLBACK(bool) FNVBOXEXT_HASHMAP_EQUAL(void *pvKey1, void *pvKey2);
+typedef FNVBOXEXT_HASHMAP_EQUAL *PFNVBOXEXT_HASHMAP_EQUAL;
+
+typedef DECLCALLBACK(bool) FNVBOXEXT_HASHMAP_VISITOR(struct VBOXEXT_HASHMAP *pMap, void *pvKey, struct VBOXEXT_HASHMAP_ENTRY *pValue, void *pvVisitor);
+typedef FNVBOXEXT_HASHMAP_VISITOR *PFNVBOXEXT_HASHMAP_VISITOR;
+
+typedef struct VBOXEXT_HASHMAP_ENTRY
+{
+    RTLISTNODE ListNode;
+    void *pvKey;
+    uint32_t u32Hash;
+} VBOXEXT_HASHMAP_ENTRY, *PVBOXEXT_HASHMAP_ENTRY;
+
+typedef struct VBOXEXT_HASHMAP_BUCKET
+{
+    RTLISTNODE EntryList;
+} VBOXEXT_HASHMAP_BUCKET, *PVBOXEXT_HASHMAP_BUCKET;
+
+#define VBOXEXT_HASHMAP_NUM_BUCKETS 29
+
+typedef struct VBOXEXT_HASHMAP
+{
+    PFNVBOXEXT_HASHMAP_HASH pfnHash;
+    PFNVBOXEXT_HASHMAP_EQUAL pfnEqual;
+    uint32_t cEntries;
+    VBOXEXT_HASHMAP_BUCKET aBuckets[VBOXEXT_HASHMAP_NUM_BUCKETS];
+} VBOXEXT_HASHMAP, *PVBOXEXT_HASHMAP;
+
+void VBoxExtHashInit(PVBOXEXT_HASHMAP pMap, PFNVBOXEXT_HASHMAP_HASH pfnHash, PFNVBOXEXT_HASHMAP_EQUAL pfnEqual);
+PVBOXEXT_HASHMAP_ENTRY VBoxExtHashPut(PVBOXEXT_HASHMAP pMap, void *pvKey, PVBOXEXT_HASHMAP_ENTRY pEntry);
+PVBOXEXT_HASHMAP_ENTRY VBoxExtHashGet(PVBOXEXT_HASHMAP pMap, void *pvKey);
+PVBOXEXT_HASHMAP_ENTRY VBoxExtHashRemove(PVBOXEXT_HASHMAP pMap, void *pvKey);
+void* VBoxExtHashRemoveEntry(PVBOXEXT_HASHMAP pMap, PVBOXEXT_HASHMAP_ENTRY pEntry);
+void VBoxExtHashVisit(PVBOXEXT_HASHMAP pMap, PFNVBOXEXT_HASHMAP_VISITOR pfnVisitor, void *pvVisitor);
+void VBoxExtHashCleanup(PVBOXEXT_HASHMAP pMap, PFNVBOXEXT_HASHMAP_VISITOR pfnVisitor, void *pvVisitor);
+
+DECLINLINE(uint32_t) VBoxExtHashSize(PVBOXEXT_HASHMAP pMap)
+{
+    return pMap->cEntries;
+}
+
+DECLINLINE(void*) VBoxExtHashEntryKey(PVBOXEXT_HASHMAP_ENTRY pEntry)
+{
+    return pEntry->pvKey;
+}
+
+typedef DECLCALLBACK(void) FNVBOXEXT_HASHCACHE_CLEANUP_ENTRY(void *pvKey, struct VBOXEXT_HASHCACHE_ENTRY *pEntry);
+typedef FNVBOXEXT_HASHCACHE_CLEANUP_ENTRY *PFNVBOXEXT_HASHCACHE_CLEANUP_ENTRY;
+
+typedef struct VBOXEXT_HASHCACHE_ENTRY
+{
+    VBOXEXT_HASHMAP_ENTRY MapEntry;
+    uint32_t u32Usage;
+} VBOXEXT_HASHCACHE_ENTRY, *PVBOXEXT_HASHCACHE_ENTRY;
+
+typedef struct VBOXEXT_HASHCACHE
+{
+    VBOXEXT_HASHMAP Map;
+    uint32_t cMaxElements;
+    PFNVBOXEXT_HASHCACHE_CLEANUP_ENTRY pfnCleanupEntry;
+} VBOXEXT_HASHCACHE, *PVBOXEXT_HASHCACHE;
+
+#define VBOXEXT_HASHCACHE_FROM_MAP(_pMap) RT_FROM_MEMBER((_pMap), VBOXEXT_HASHCACHE, Map)
+#define VBOXEXT_HASHCACHE_ENTRY_FROM_MAP(_pEntry) RT_FROM_MEMBER((_pEntry), VBOXEXT_HASHCACHE_ENTRY, MapEntry)
+
+DECLINLINE(void) VBoxExtCacheInit(PVBOXEXT_HASHCACHE pCache, uint32_t cMaxElements,
+        PFNVBOXEXT_HASHMAP_HASH pfnHash,
+        PFNVBOXEXT_HASHMAP_EQUAL pfnEqual,
+        PFNVBOXEXT_HASHCACHE_CLEANUP_ENTRY pfnCleanupEntry)
+{
+    VBoxExtHashInit(&pCache->Map, pfnHash, pfnEqual);
+    pCache->cMaxElements = cMaxElements;
+    pCache->pfnCleanupEntry = pfnCleanupEntry;
+}
+
+DECLINLINE(PVBOXEXT_HASHCACHE_ENTRY) VBoxExtCacheGet(PVBOXEXT_HASHCACHE pCache, void *pvKey)
+{
+    PVBOXEXT_HASHMAP_ENTRY pEntry = VBoxExtHashRemove(&pCache->Map, pvKey);
+    return VBOXEXT_HASHCACHE_ENTRY_FROM_MAP(pEntry);
+}
+
+DECLINLINE(void) VBoxExtCachePut(PVBOXEXT_HASHCACHE pCache, void *pvKey, PVBOXEXT_HASHCACHE_ENTRY pEntry)
+{
+    PVBOXEXT_HASHMAP_ENTRY pOldEntry = VBoxExtHashPut(&pCache->Map, pvKey, &pEntry->MapEntry);
+    PVBOXEXT_HASHCACHE_ENTRY pOld;
+    if (!pOldEntry)
+        return;
+    pOld = VBOXEXT_HASHCACHE_ENTRY_FROM_MAP(pOldEntry);
+    if (pOld != pEntry)
+        pCache->pfnCleanupEntry(pvKey, pOld);
+}
+
+void VBoxExtCacheCleanup(PVBOXEXT_HASHCACHE pCache);
+
+DECLINLINE(void) VBoxExtCacheTerm(PVBOXEXT_HASHCACHE pCache)
+{
+    VBoxExtCacheCleanup(pCache);
+}
+
 #endif /* #ifndef ___VBOXEXT_H__*/
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/wined3d_private.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/wined3d_private.h	(revision 42407)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/wined3d_private.h	(revision 42408)
@@ -1801,4 +1801,9 @@
     UINT                    numContexts;
 
+#ifdef VBOX_WINE_WITH_SHADER_CACHE
+    VBOXEXT_HASHCACHE vshaderCache;
+    VBOXEXT_HASHCACHE pshaderCache;
+#endif
+
     /* High level patch management */
 #define PATCHMAP_SIZE 43
@@ -2929,4 +2934,9 @@
     struct list     shader_list_entry;
 
+#ifdef VBOX_WINE_WITH_SHADER_CACHE
+    VBOXEXT_HASHCACHE_ENTRY CacheEntry;
+    uint32_t u32CacheDataInited;
+    uint32_t u32Hash;
+#endif
 } IWineD3DBaseShaderClass;
 
@@ -3095,4 +3105,11 @@
         struct ps_compile_args *args) DECLSPEC_HIDDEN;
 
+#ifdef VBOX_WINE_WITH_SHADER_CACHE
+IWineD3DVertexShaderImpl * vertexshader_check_cached(IWineD3DDeviceImpl *device, IWineD3DVertexShaderImpl *object) DECLSPEC_HIDDEN;
+IWineD3DPixelShaderImpl * pixelshader_check_cached(IWineD3DDeviceImpl *device, IWineD3DPixelShaderImpl *object) DECLSPEC_HIDDEN;
+void shader_chaches_init(IWineD3DDeviceImpl *device) DECLSPEC_HIDDEN;
+void shader_chaches_term(IWineD3DDeviceImpl *device) DECLSPEC_HIDDEN;
+#endif
+
 /* sRGB correction constants */
 static const float srgb_cmp = 0.0031308f;
