d3d8: Improve shader handle management.
This commit is contained in:
parent
bda6d092a5
commit
4a48e38e7d
|
@ -37,7 +37,7 @@
|
||||||
#include "wine/wined3d_interface.h"
|
#include "wine/wined3d_interface.h"
|
||||||
|
|
||||||
/* Device caps */
|
/* Device caps */
|
||||||
#define MAX_SHADERS 64
|
#define INITIAL_SHADER_HANDLE_TABLE_SIZE 64
|
||||||
|
|
||||||
/* CreateVertexShader can return > 0xFFFF */
|
/* CreateVertexShader can return > 0xFFFF */
|
||||||
#define VS_HIGHESTFIXEDFXF 0xF0000000
|
#define VS_HIGHESTFIXEDFXF 0xF0000000
|
||||||
|
@ -162,6 +162,9 @@ extern const IDirect3DDevice8Vtbl Direct3DDevice8_Vtbl;
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* IDirect3DDevice8 implementation structure
|
* IDirect3DDevice8 implementation structure
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
typedef void * shader_handle;
|
||||||
|
|
||||||
struct IDirect3DDevice8Impl
|
struct IDirect3DDevice8Impl
|
||||||
{
|
{
|
||||||
/* IUnknown fields */
|
/* IUnknown fields */
|
||||||
|
@ -169,7 +172,11 @@ struct IDirect3DDevice8Impl
|
||||||
LONG ref;
|
LONG ref;
|
||||||
/* But what about baseVertexIndex in state blocks? hmm... it may be a better idea to pass this to wined3d */
|
/* But what about baseVertexIndex in state blocks? hmm... it may be a better idea to pass this to wined3d */
|
||||||
IWineD3DDevice *WineD3DDevice;
|
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 */
|
/* FIXME: Move *baseVertexIndex somewhere sensible like wined3d */
|
||||||
UINT baseVertexIndex;
|
UINT baseVertexIndex;
|
||||||
};
|
};
|
||||||
|
@ -531,6 +538,7 @@ struct IDirect3DVertexShader8Impl {
|
||||||
const IDirect3DVertexShader8Vtbl *lpVtbl;
|
const IDirect3DVertexShader8Vtbl *lpVtbl;
|
||||||
LONG ref;
|
LONG ref;
|
||||||
|
|
||||||
|
shader_handle *handle;
|
||||||
IWineD3DVertexShader *wineD3DVertexShader;
|
IWineD3DVertexShader *wineD3DVertexShader;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,31 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(d3d8);
|
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: */
|
/* IDirect3D IUnknown parts follow: */
|
||||||
static HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(LPDIRECT3DDEVICE8 iface,REFIID riid,LPVOID *ppobj)
|
static HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(LPDIRECT3DDEVICE8 iface,REFIID riid,LPVOID *ppobj)
|
||||||
{
|
{
|
||||||
|
@ -1082,17 +1107,18 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8
|
||||||
*ppShader = 0;
|
*ppShader = 0;
|
||||||
} else {
|
} else {
|
||||||
/* TODO: Store the VS declarations locally so that they can be derefferenced with a value higher than VS_HIGHESTFIXEDFXF */
|
/* TODO: Store the VS declarations locally so that they can be derefferenced with a value higher than VS_HIGHESTFIXEDFXF */
|
||||||
DWORD i = 0;
|
shader_handle *handle = alloc_shader_handle(This);
|
||||||
while(This->vShaders[i] != NULL && i < MAX_SHADERS) ++i;
|
if (!handle) {
|
||||||
if (MAX_SHADERS == i) {
|
ERR("Failed to allocate shader handle\n");
|
||||||
FIXME("(%p) : Number of shaders exceeds the maximum number of possible shaders\n", This);
|
IDirect3DVertexShader8_Release((IUnknown *)object);
|
||||||
hrc = E_OUTOFMEMORY;
|
hrc = E_OUTOFMEMORY;
|
||||||
} else {
|
} else {
|
||||||
This->vShaders[i] = object;
|
object->handle = handle;
|
||||||
*ppShader = i + VS_HIGHESTFIXEDFXF + 1;
|
*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;
|
return hrc;
|
||||||
}
|
}
|
||||||
|
@ -1110,11 +1136,11 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 ifa
|
||||||
IWineD3DDevice_SetVertexShader(This->WineD3DDevice, NULL);
|
IWineD3DDevice_SetVertexShader(This->WineD3DDevice, NULL);
|
||||||
} else {
|
} else {
|
||||||
TRACE("Setting shader\n");
|
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);
|
FIXME("(%p) : Number of shaders exceeds the maximum number of possible shaders\n", This);
|
||||||
hrc = D3DERR_INVALIDCALL;
|
hrc = D3DERR_INVALIDCALL;
|
||||||
} else {
|
} 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);
|
hrc = IWineD3DDevice_SetVertexShader(This->WineD3DDevice, 0 == shader ? NULL : shader->wineD3DVertexShader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1132,16 +1158,10 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 ifa
|
||||||
hrc = IWineD3DDevice_GetVertexShader(This->WineD3DDevice, &pShader);
|
hrc = IWineD3DDevice_GetVertexShader(This->WineD3DDevice, &pShader);
|
||||||
if (D3D_OK == hrc) {
|
if (D3D_OK == hrc) {
|
||||||
if(0 != pShader) {
|
if(0 != pShader) {
|
||||||
DWORD i = 0;
|
IDirect3DVertexShader8Impl *d3d8_shader;
|
||||||
hrc = IWineD3DVertexShader_GetParent(pShader, (IUnknown **)ppShader);
|
hrc = IWineD3DVertexShader_GetParent(pShader, (IUnknown **)&d3d8_shader);
|
||||||
IWineD3DVertexShader_Release(pShader);
|
IWineD3DVertexShader_Release(pShader);
|
||||||
while(This->vShaders[i] != (IDirect3DVertexShader8Impl *)ppShader && i < MAX_SHADERS) ++i;
|
*ppShader = (d3d8_shader->handle - This->shader_handles) + (VS_HIGHESTFIXEDFXF + 1);
|
||||||
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;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
WARN("(%p) : The shader has been set to NULL\n", This);
|
WARN("(%p) : The shader has been set to NULL\n", This);
|
||||||
|
|
||||||
|
@ -1152,29 +1172,27 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 ifa
|
||||||
} else {
|
} else {
|
||||||
WARN("(%p) : Call to IWineD3DDevice_GetVertexShader failed %lu (device %p)\n", This, hrc, This->WineD3DDevice);
|
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;
|
return hrc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD pShader) {
|
static HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD pShader) {
|
||||||
IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
|
IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
|
||||||
HRESULT hrc = D3D_OK;
|
|
||||||
TRACE("(%p) Relay\n", This);
|
TRACE("(%p) : pShader %#lx\n", This, pShader);
|
||||||
if (pShader <= VS_HIGHESTFIXEDFXF) {
|
|
||||||
WARN("(%p) : Caller passed a shader below the value of VS_HIGHESTFIXEDFXF\n", This);
|
if (pShader <= VS_HIGHESTFIXEDFXF || This->allocated_shader_handles <= pShader - (VS_HIGHESTFIXEDFXF + 1)) {
|
||||||
hrc = D3DERR_INVALIDCALL;
|
ERR("(%p) : Trying to delete an invalid handle\n", This);
|
||||||
} else if (MAX_SHADERS <= pShader - (VS_HIGHESTFIXEDFXF + 1)) {
|
return D3DERR_INVALIDCALL;
|
||||||
FIXME("(%p) : Caller passed a shader greater than the maximum number of shaders\n", This);
|
|
||||||
hrc = D3DERR_INVALIDCALL;
|
|
||||||
} else {
|
} 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));
|
while(IUnknown_Release((IUnknown *)shader));
|
||||||
This->vShaders[pShader - (VS_HIGHESTFIXEDFXF + 1)] = NULL;
|
free_shader_handle(This, handle);
|
||||||
hrc = D3D_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return hrc;
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
|
static HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
|
||||||
|
|
|
@ -311,6 +311,8 @@ static HRESULT WINAPI IDirect3D8Impl_CreateDevice(LPDIRECT3D8 iface, UINT Adapte
|
||||||
|
|
||||||
object->lpVtbl = &Direct3DDevice8_Vtbl;
|
object->lpVtbl = &Direct3DDevice8_Vtbl;
|
||||||
object->ref = 1;
|
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;
|
*ppReturnedDeviceInterface = (IDirect3DDevice8 *)object;
|
||||||
|
|
||||||
/* Allocate an associated WineD3DDevice object */
|
/* Allocate an associated WineD3DDevice object */
|
||||||
|
|
Loading…
Reference in New Issue