wined3d: Delay vertex shader compilation until the shader is first used.
This commit is contained in:
parent
e548d40831
commit
ef87a40c72
|
@ -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(®_maps, 0, sizeof(shader_reg_maps));
|
||||
hr = shader_get_registers_used((IWineD3DBaseShader*) This, ®_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, ®_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(®_maps, 0, sizeof(shader_reg_maps));
|
||||
hr = shader_get_registers_used((IWineD3DBaseShader*) This, ®_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, ®_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)
|
||||
|
|
Loading…
Reference in New Issue