[1/2] WINED3D: Delay vertex shader compilation until the shader is
first used.
H. Verbeet
hverbeet at gmail.com
Sat Aug 5 11:15:35 CDT 2006
This patch delays vertex shader compilation until the shader is first
used. The is required for the next patch, to properly determine what
shader attributes need swizzling.
-------------- next part --------------
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index e337789..434fab9 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -1780,6 +1780,10 @@ #undef BUFFER_OR_DATA
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");
diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c
index 9e7b852..9a8227f 100644
--- a/dlls/wined3d/pixelshader.c
+++ b/dlls/wined3d/pixelshader.c
@@ -913,7 +913,7 @@ static HRESULT WINAPI IWineD3DPixelShade
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 IWineD3DPixelShade
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 IWineD3DPixelShade
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 IWineD3DPi
IWineD3DPixelShaderImpl_GetParent,
/*** IWineD3DBaseShader methods ***/
IWineD3DPixelShaderImpl_SetFunction,
+ IWineD3DPixelShaderImpl_CompileShader,
/*** IWineD3DPixelShader methods ***/
IWineD3DPixelShaderImpl_GetDevice,
IWineD3DPixelShaderImpl_GetFunction
diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c
index 0d4bac6..e837772 100644
--- a/dlls/wined3d/vertexshader.c
+++ b/dlls/wined3d/vertexshader.c
@@ -1131,11 +1131,15 @@ static HRESULT WINAPI IWineD3DVertexShad
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 IWineD3DVertexShad
}
/* 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 IWineD3DVertexShad
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 IWineD3DV
IWineD3DVertexShaderImpl_GetParent,
/*** IWineD3DBaseShader methods ***/
IWineD3DVertexShaderImpl_SetFunction,
+ IWineD3DVertexShaderImpl_CompileShader,
/*** IWineD3DVertexShader methods ***/
IWineD3DVertexShaderImpl_GetDevice,
IWineD3DVertexShaderImpl_GetFunction
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index b3dc283..7ef8877 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -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;
diff --git a/include/wine/wined3d_interface.h b/include/wine/wined3d_interface.h
index 2104aaa..01cc8ef 100644
--- a/include/wine/wined3d_interface.h
+++ b/include/wine/wined3d_interface.h
@@ -1424,6 +1424,7 @@ DECLARE_INTERFACE_(IWineD3DBaseShader,IW
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 @@ #define IWineD3DBaseShader_Release(p)
#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,
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 @@ #define IWineD3DVertexShader_Release(p)
#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,I
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 @@ #define IWineD3DPixelShader_Release(p)
#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)
More information about the wine-patches
mailing list