Commit ef87a40c authored by H. Verbeet's avatar H. Verbeet Committed by Alexandre Julliard

wined3d: Delay vertex shader compilation until the shader is first used.

parent e548d408
......@@ -1780,6 +1780,10 @@ inline static void drawPrimitiveDrawStrided(
loadNumberedArrays(iface, This->stateBlock->vertexShader, dataLocations);
useDrawStridedSlow = FALSE;
/* We compile the shader here because we need the vertex declaration
* in order to determine if we need to do any swizzling for D3DCOLOR
* registers. If the shader is already compiled this call will do nothing. */
IWineD3DVertexShader_CompileShader(This->stateBlock->vertexShader);
/* Draw vertex by vertex */
} else {
TRACE("Not loading vertex data\n");
......
......@@ -913,7 +913,7 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *i
IWineD3DPixelShaderImpl *This =(IWineD3DPixelShaderImpl *)iface;
HRESULT hr;
shader_reg_maps reg_maps;
shader_reg_maps *reg_maps = &This->baseShader.reg_maps;
TRACE("(%p) : pFunction %p\n", iface, pFunction);
......@@ -927,18 +927,13 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *i
list_init(&This->baseShader.constantsI);
/* Second pass: figure out which registers are used, what the semantics are, etc.. */
memset(&reg_maps, 0, sizeof(shader_reg_maps));
hr = shader_get_registers_used((IWineD3DBaseShader*) This, &reg_maps,
memset(reg_maps, 0, sizeof(shader_reg_maps));
hr = shader_get_registers_used((IWineD3DBaseShader*) This, reg_maps,
This->semantics_in, NULL, pFunction);
if (hr != WINED3D_OK) return hr;
/* FIXME: validate reg_maps against OpenGL */
/* Generate HW shader in needed */
This->baseShader.shader_mode = wined3d_settings.ps_selected_mode;
if (NULL != pFunction && This->baseShader.shader_mode != SHADER_SW) {
TRACE("(%p) : Generating hardware program\n", This);
IWineD3DPixelShaderImpl_GenerateShader(iface, &reg_maps, pFunction);
}
TRACE("(%p) : Copying the function\n", This);
if (NULL != pFunction) {
......@@ -949,6 +944,33 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *i
This->baseShader.function = NULL;
}
/* Compile the shader. */
IWineD3DPixelShader_CompileShader(iface);
return WINED3D_OK;
}
static HRESULT WINAPI IWineD3DPixelShaderImpl_CompileShader(IWineD3DPixelShader *iface) {
IWineD3DPixelShaderImpl *This =(IWineD3DPixelShaderImpl *)iface;
CONST DWORD *function = This->baseShader.function;
TRACE("(%p) : function %p\n", iface, function);
/* We're already compiled. */
if (This->baseShader.is_compiled) return WINED3D_OK;
/* We don't need to compile */
if (!function || This->baseShader.shader_mode == SHADER_SW) {
This->baseShader.is_compiled = TRUE;
return WINED3D_OK;
}
/* Generate the HW shader */
TRACE("(%p) : Generating hardware program\n", This);
IWineD3DPixelShaderImpl_GenerateShader(iface, &This->baseShader.reg_maps, function);
This->baseShader.is_compiled = TRUE;
return WINED3D_OK;
}
......@@ -962,6 +984,7 @@ const IWineD3DPixelShaderVtbl IWineD3DPixelShader_Vtbl =
IWineD3DPixelShaderImpl_GetParent,
/*** IWineD3DBaseShader methods ***/
IWineD3DPixelShaderImpl_SetFunction,
IWineD3DPixelShaderImpl_CompileShader,
/*** IWineD3DPixelShader methods ***/
IWineD3DPixelShaderImpl_GetDevice,
IWineD3DPixelShaderImpl_GetFunction
......
......@@ -1131,11 +1131,15 @@ static HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader*
return WINED3D_OK;
}
/* Note that for vertex shaders CompileShader isn't called until the
* shader is first used. The reason for this is that we need the vertex
* declaration the shader will be used with in order to determine if
* the data in a register is of type D3DCOLOR, and needs swizzling. */
static HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, CONST DWORD *pFunction) {
IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
HRESULT hr;
shader_reg_maps reg_maps;
shader_reg_maps *reg_maps = &This->baseShader.reg_maps;
TRACE("(%p) : pFunction %p\n", iface, pFunction);
......@@ -1159,15 +1163,12 @@ static HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader
}
/* Second pass: figure out registers used, semantics, etc.. */
memset(&reg_maps, 0, sizeof(shader_reg_maps));
hr = shader_get_registers_used((IWineD3DBaseShader*) This, &reg_maps,
memset(reg_maps, 0, sizeof(shader_reg_maps));
hr = shader_get_registers_used((IWineD3DBaseShader*) This, reg_maps,
This->semantics_in, This->semantics_out, pFunction);
if (hr != WINED3D_OK) return hr;
/* Generate HW shader in needed */
This->baseShader.shader_mode = wined3d_settings.vs_selected_mode;
if (NULL != pFunction && This->baseShader.shader_mode != SHADER_SW)
IWineD3DVertexShaderImpl_GenerateShader(iface, &reg_maps, pFunction);
/* copy the function ... because it will certainly be released by application */
if (NULL != pFunction) {
......@@ -1181,6 +1182,30 @@ static HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader
return WINED3D_OK;
}
static HRESULT WINAPI IWineD3DVertexShaderImpl_CompileShader(IWineD3DVertexShader *iface) {
IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
CONST DWORD *function = This->baseShader.function;
TRACE("(%p) : function %p\n", iface, function);
/* We're already compiled. */
if (This->baseShader.is_compiled) return WINED3D_OK;
/* We don't need to compile */
if (!function || This->baseShader.shader_mode == SHADER_SW) {
This->baseShader.is_compiled = TRUE;
return WINED3D_OK;
}
/* Generate the HW shader */
TRACE("(%p) : Generating hardware program\n", This);
IWineD3DVertexShaderImpl_GenerateShader(iface, &This->baseShader.reg_maps, function);
This->baseShader.is_compiled = TRUE;
return WINED3D_OK;
}
const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
{
/*** IUnknown methods ***/
......@@ -1191,6 +1216,7 @@ const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
IWineD3DVertexShaderImpl_GetParent,
/*** IWineD3DBaseShader methods ***/
IWineD3DVertexShaderImpl_SetFunction,
IWineD3DVertexShaderImpl_CompileShader,
/*** IWineD3DVertexShader methods ***/
IWineD3DVertexShaderImpl_GetDevice,
IWineD3DVertexShaderImpl_GetFunction
......
......@@ -1552,6 +1552,7 @@ typedef struct IWineD3DBaseShaderClass
CONST DWORD *function;
UINT functionLength;
GLuint prgId;
BOOL is_compiled;
/* Type of shader backend */
int shader_mode;
......@@ -1560,6 +1561,7 @@ typedef struct IWineD3DBaseShaderClass
struct list constantsB;
struct list constantsF;
struct list constantsI;
shader_reg_maps reg_maps;
} IWineD3DBaseShaderClass;
......
......@@ -1424,6 +1424,7 @@ DECLARE_INTERFACE_(IWineD3DBaseShader,IWineD3DBase)
STDMETHOD(GetParent)(THIS_ IUnknown **pParent) PURE;
/*** IWineD3DBaseShader methods ***/
STDMETHOD(SetFunction)(THIS_ CONST DWORD *pFunction) PURE;
STDMETHOD(CompileShader)(THIS) PURE;
};
#undef INTERFACE
......@@ -1436,6 +1437,7 @@ DECLARE_INTERFACE_(IWineD3DBaseShader,IWineD3DBase)
#define IWineD3DBaseShader_GetParent(p,a) (p)->lpVtbl->GetParent(p,a)
/*** IWineD3DBaseShader methods ***/
#define IWineD3DBaseShader_SetFunction(p,a) (p)->lpVtbl->SetFunction(p,a)
#define IWineD3DBaseShader_CompileShader(p) (p)->lpVtbl->CompileShader(p)
#endif
/*****************************************************************************
......@@ -1452,6 +1454,7 @@ DECLARE_INTERFACE_(IWineD3DVertexShader,IWineD3DBaseShader)
STDMETHOD(GetParent)(THIS_ IUnknown **pParent) PURE;
/*** IWineD3DBaseShader methods ***/
STDMETHOD(SetFunction)(THIS_ CONST DWORD *pFunction) PURE;
STDMETHOD(CompileShader)(THIS) PURE;
/*** IWineD3DVertexShader methods ***/
STDMETHOD(GetDevice)(THIS_ IWineD3DDevice** ppDevice) PURE;
STDMETHOD(GetFunction)(THIS_ VOID *pData, UINT *pSizeOfData) PURE;
......@@ -1475,6 +1478,7 @@ DECLARE_INTERFACE_(IWineD3DVertexShader,IWineD3DBaseShader)
#define IWineD3DVertexShader_GetParent(p,a) (p)->lpVtbl->GetParent(p,a)
/*** IWineD3DBaseShader methods ***/
#define IWineD3DVertexShader_SetFunction(p,a) (p)->lpVtbl->SetFunction(p,a)
#define IWineD3DVertexShader_CompileShader(p) (p)->lpVtbl->CompileShader(p)
/*** IWineD3DVertexShader methods ***/
#define IWineD3DVertexShader_GetDevice(p,a) (p)->lpVtbl->GetDevice(p,a)
#define IWineD3DVertexShader_GetFunction(p,a,b) (p)->lpVtbl->GetFunction(p,a,b)
......@@ -1501,6 +1505,7 @@ DECLARE_INTERFACE_(IWineD3DPixelShader,IWineD3DBaseShader)
STDMETHOD(GetParent)(THIS_ IUnknown **pParent) PURE;
/*** IWineD3DBaseShader methods ***/
STDMETHOD(SetFunction)(THIS_ CONST DWORD *pFunction) PURE;
STDMETHOD(CompileShader)(THIS) PURE;
/*** IWineD3DPixelShader methods ***/
STDMETHOD(GetDevice)(THIS_ IWineD3DDevice** ppDevice) PURE;
STDMETHOD(GetFunction)(THIS_ VOID* pData, UINT* pSizeOfData) PURE;
......@@ -1516,6 +1521,7 @@ DECLARE_INTERFACE_(IWineD3DPixelShader,IWineD3DBaseShader)
#define IWineD3DPixelShader_GetParent(p,a) (p)->lpVtbl->GetParent(p,a)
/*** IWineD3DBaseShader methods ***/
#define IWineD3DPixelShader_SetFunction(p,a) (p)->lpVtbl->SetFunction(p,a)
#define IWineD3DPixelShader_CompileShader(p) (p)->lpVtbl->CompileShader(p)
/*** IWineD3DPixelShader methods ***/
#define IWineD3DPixelShader_GetDevice(p,a) (p)->lpVtbl->GetDevice(p,a)
#define IWineD3DPixelShader_GetFunction(p,a,b) (p)->lpVtbl->GetFunction(p,a,b)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment