H. Verbeet : d3d8: Improve shader handle management.

Alexandre Julliard julliard at wine.codeweavers.com
Mon Aug 28 05:09:26 CDT 2006


Module: wine
Branch: master
Commit: 4a48e38e7da34bb5834f89a91a51b3e5d5b76d86
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=4a48e38e7da34bb5834f89a91a51b3e5d5b76d86

Author: H. Verbeet <hverbeet at gmail.com>
Date:   Sun Aug 27 22:07:09 2006 +0200

d3d8: Improve shader handle management.

---

 dlls/d3d8/d3d8_private.h |   12 ++++++-
 dlls/d3d8/device.c       |   80 ++++++++++++++++++++++++++++------------------
 dlls/d3d8/directx.c      |    2 +
 3 files changed, 61 insertions(+), 33 deletions(-)

diff --git a/dlls/d3d8/d3d8_private.h b/dlls/d3d8/d3d8_private.h
index 6c8a519..b3af102 100644
--- a/dlls/d3d8/d3d8_private.h
+++ b/dlls/d3d8/d3d8_private.h
@@ -37,7 +37,7 @@ #include "ddraw.h"
 #include "wine/wined3d_interface.h"
 
 /* Device caps */
-#define MAX_SHADERS        64
+#define INITIAL_SHADER_HANDLE_TABLE_SIZE        64
 
 /* CreateVertexShader can return > 0xFFFF */
 #define VS_HIGHESTFIXEDFXF 0xF0000000
@@ -162,6 +162,9 @@ extern const IDirect3DDevice8Vtbl Direct
 /*****************************************************************************
  * IDirect3DDevice8 implementation structure
  */
+
+typedef void * shader_handle;
+
 struct IDirect3DDevice8Impl
 {
     /* IUnknown fields */
@@ -169,7 +172,11 @@ struct IDirect3DDevice8Impl
     LONG                         ref;
 /* But what about baseVertexIndex in state blocks? hmm... it may be a better idea to pass this to wined3d */
     IWineD3DDevice               *WineD3DDevice;
-    IDirect3DVertexShader8Impl   *vShaders[MAX_SHADERS];
+    DWORD                         shader_handle_table_size;
+    DWORD                         allocated_shader_handles;
+    shader_handle                *shader_handles;
+    shader_handle                *free_shader_handles;
+
 /* FIXME: Move *baseVertexIndex somewhere sensible like wined3d */
     UINT                          baseVertexIndex;
 };
@@ -531,6 +538,7 @@ struct IDirect3DVertexShader8Impl {
   const IDirect3DVertexShader8Vtbl *lpVtbl;
   LONG ref;
 
+  shader_handle                    *handle;
   IWineD3DVertexShader             *wineD3DVertexShader;
 };
 
diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c
index 1d12290..6997df7 100644
--- a/dlls/d3d8/device.c
+++ b/dlls/d3d8/device.c
@@ -36,6 +36,31 @@ #include "d3d8_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3d8);
 
+/* Shader handle functions */
+static shader_handle *alloc_shader_handle(IDirect3DDevice8Impl *This) {
+    if (This->free_shader_handles) {
+        /* Use a free handle */
+        shader_handle *handle = This->free_shader_handles;
+        This->free_shader_handles = *handle;
+        return handle;
+    }
+    if (!(This->allocated_shader_handles < This->shader_handle_table_size)) {
+        /* Grow the table */
+        DWORD new_size = This->shader_handle_table_size + (This->shader_handle_table_size >> 1);
+        shader_handle *new_handles = HeapReAlloc(GetProcessHeap(), 0, This->shader_handles, new_size * sizeof(shader_handle));
+        if (!new_handles) return NULL;
+        This->shader_handles = new_handles;
+        This->shader_handle_table_size = new_size;
+    }
+
+    return &This->shader_handles[This->allocated_shader_handles++];
+}
+
+static void free_shader_handle(IDirect3DDevice8Impl *This, shader_handle *handle) {
+    *handle = This->free_shader_handles;
+    This->free_shader_handles = handle;
+}
+
 /* IDirect3D IUnknown parts follow: */
 static HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(LPDIRECT3DDEVICE8 iface,REFIID riid,LPVOID *ppobj)
 {
@@ -1082,17 +1107,18 @@ static HRESULT WINAPI IDirect3DDevice8Im
         *ppShader = 0;
     } else {
         /* TODO: Store the VS declarations locally so that they can be derefferenced with a value higher than VS_HIGHESTFIXEDFXF */
-        DWORD i = 0;
-        while(This->vShaders[i] != NULL && i < MAX_SHADERS) ++i;
-        if (MAX_SHADERS == i) {
-            FIXME("(%p) : Number of shaders exceeds the maximum number of possible shaders\n", This);
+        shader_handle *handle = alloc_shader_handle(This);
+        if (!handle) {
+            ERR("Failed to allocate shader handle\n");
+            IDirect3DVertexShader8_Release((IUnknown *)object);
             hrc = E_OUTOFMEMORY;
         } else {
-            This->vShaders[i] = object;
-            *ppShader = i + VS_HIGHESTFIXEDFXF + 1;
+            object->handle = handle;
+            *handle = object;
+            *ppShader = (handle - This->shader_handles) + VS_HIGHESTFIXEDFXF + 1;
         }
     }
-    TRACE("(%p) : returning %p\n", This, object);
+    TRACE("(%p) : returning %p (handle %#lx)\n", This, object, *ppShader);
 
     return hrc;
 }
@@ -1110,11 +1136,11 @@ static HRESULT WINAPI IDirect3DDevice8Im
         IWineD3DDevice_SetVertexShader(This->WineD3DDevice, NULL);
     } else {
         TRACE("Setting shader\n");
-        if (MAX_SHADERS <= pShader - (VS_HIGHESTFIXEDFXF + 1)) {
+        if (This->allocated_shader_handles <= pShader - (VS_HIGHESTFIXEDFXF + 1)) {
             FIXME("(%p) : Number of shaders exceeds the maximum number of possible shaders\n", This);
             hrc = D3DERR_INVALIDCALL;
         } else {
-            IDirect3DVertexShader8Impl *shader = This->vShaders[pShader - (VS_HIGHESTFIXEDFXF + 1)];
+            IDirect3DVertexShader8Impl *shader = This->shader_handles[pShader - (VS_HIGHESTFIXEDFXF + 1)];
             hrc =  IWineD3DDevice_SetVertexShader(This->WineD3DDevice, 0 == shader ? NULL : shader->wineD3DVertexShader);
         }
     }
@@ -1132,16 +1158,10 @@ static HRESULT WINAPI IDirect3DDevice8Im
     hrc = IWineD3DDevice_GetVertexShader(This->WineD3DDevice, &pShader);
     if (D3D_OK == hrc) {
         if(0 != pShader) {
-            DWORD i = 0;
-            hrc = IWineD3DVertexShader_GetParent(pShader, (IUnknown **)ppShader);
+            IDirect3DVertexShader8Impl *d3d8_shader;
+            hrc = IWineD3DVertexShader_GetParent(pShader, (IUnknown **)&d3d8_shader);
             IWineD3DVertexShader_Release(pShader);
-            while(This->vShaders[i] != (IDirect3DVertexShader8Impl *)ppShader && i < MAX_SHADERS) ++i;
-            if (i < MAX_SHADERS) {
-                *ppShader = i + VS_HIGHESTFIXEDFXF + 1;
-            } else {
-                WARN("(%p) : Couldn't find math for shader %p in d3d7 shadres list\n", This, (IDirect3DVertexShader8Impl *)ppShader);
-                *ppShader = 0;
-            }
+            *ppShader = (d3d8_shader->handle - This->shader_handles) + (VS_HIGHESTFIXEDFXF + 1);
         } else {
             WARN("(%p) : The shader has been set to NULL\n", This);
 
@@ -1152,29 +1172,27 @@ static HRESULT WINAPI IDirect3DDevice8Im
     } else {
         WARN("(%p) : Call to IWineD3DDevice_GetVertexShader failed %lu (device %p)\n", This, hrc, This->WineD3DDevice);
     }
-    TRACE("(%p) : returning %p\n", This, (IDirect3DVertexShader8 *)*ppShader);
+    TRACE("(%p) : returning %#lx\n", This, *ppShader);
 
     return hrc;
 }
 
 static HRESULT  WINAPI  IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD pShader) {
     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
-    HRESULT hrc = D3D_OK;
-    TRACE("(%p) Relay\n", This);
-    if (pShader <= VS_HIGHESTFIXEDFXF) {
-        WARN("(%p) : Caller passed a shader below the value of VS_HIGHESTFIXEDFXF\n", This);
-        hrc = D3DERR_INVALIDCALL;
-    } else if (MAX_SHADERS <= pShader - (VS_HIGHESTFIXEDFXF + 1)) {
-        FIXME("(%p) : Caller passed a shader greater than the maximum number of shaders\n", This);
-        hrc = D3DERR_INVALIDCALL;
+
+    TRACE("(%p) : pShader %#lx\n", This, pShader);
+
+    if (pShader <= VS_HIGHESTFIXEDFXF || This->allocated_shader_handles <= pShader - (VS_HIGHESTFIXEDFXF + 1)) {
+        ERR("(%p) : Trying to delete an invalid handle\n", This);
+        return D3DERR_INVALIDCALL;
     } else {
-        IDirect3DVertexShader8Impl *shader = This->vShaders[pShader - (VS_HIGHESTFIXEDFXF + 1)];
+        shader_handle *handle = &This->shader_handles[pShader - (VS_HIGHESTFIXEDFXF + 1)];
+        IDirect3DVertexShader8Impl *shader = *handle;
         while(IUnknown_Release((IUnknown *)shader));
-        This->vShaders[pShader - (VS_HIGHESTFIXEDFXF + 1)] = NULL;
-        hrc = D3D_OK;
+        free_shader_handle(This, handle);
     }
 
-    return hrc;
+    return D3D_OK;
 }
 
 static HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
diff --git a/dlls/d3d8/directx.c b/dlls/d3d8/directx.c
index be4f8c9..c5e7094 100644
--- a/dlls/d3d8/directx.c
+++ b/dlls/d3d8/directx.c
@@ -311,6 +311,8 @@ static HRESULT WINAPI IDirect3D8Impl_Cre
 
     object->lpVtbl = &Direct3DDevice8_Vtbl;
     object->ref = 1;
+    object->shader_handles = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INITIAL_SHADER_HANDLE_TABLE_SIZE * sizeof(shader_handle));
+    object->shader_handle_table_size = INITIAL_SHADER_HANDLE_TABLE_SIZE;
     *ppReturnedDeviceInterface = (IDirect3DDevice8 *)object;
 
     /* Allocate an associated WineD3DDevice object */




More information about the wine-cvs mailing list