wined3d: Make the shader backend call CompileShader.

A number of considerations contribute to this:

1) The shader backend knows best which shader(s) it needs. GLSL needs
both, arb only one
2) The shader backend may pass some parameters to the compilation
code(e.g. which pixel format fixup to use)
3) The structures used in (2) are different in vs and ps, so a
baseshader::Compile won't work
4) The structures in (2) are wined3d-private structures, so
having a public method in the vtable won't work(its a bad idea
anyway).
This commit is contained in:
Stefan Dösinger 2008-11-24 11:52:12 +01:00 committed by Alexandre Julliard
parent 83045e5cc8
commit ff767f4984
8 changed files with 47 additions and 38 deletions

View File

@ -1876,6 +1876,7 @@ static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {
if (useVS) {
TRACE("Using vertex shader\n");
IWineD3DVertexShaderImpl_CompileShader(This->stateBlock->vertexShader);
priv->current_vprogram_id = ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId;
@ -1895,6 +1896,7 @@ static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {
if (usePS) {
TRACE("Using pixel shader\n");
pixelshader_compile(This->stateBlock->pixelShader);
priv->current_fprogram_id = ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId;
@ -3065,9 +3067,7 @@ static void fragment_prog_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock,
unsigned int i;
if(isStateDirty(context, STATE_RENDER(WINED3DRS_FOGENABLE))) {
if(use_pshader) {
IWineD3DPixelShader_CompileShader(stateblock->pixelShader);
} else if(device->shader_backend == &arb_program_shader_backend && context->last_was_pshader) {
if(!use_pshader && device->shader_backend == &arb_program_shader_backend && context->last_was_pshader) {
/* Reload fixed function constants since they collide with the pixel shader constants */
for(i = 0; i < MAX_TEXTURES; i++) {
set_bumpmat_arbfp(STATE_TEXTURESTAGE(i, WINED3DTSS_BUMPENVMAT00), stateblock, context);
@ -3078,9 +3078,7 @@ static void fragment_prog_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock,
return;
}
if(use_pshader) {
IWineD3DPixelShader_CompileShader(stateblock->pixelShader);
} else {
if(!use_pshader) {
/* Find or create a shader implementing the fixed function pipeline settings, then activate it */
gen_ffp_frag_op(stateblock, &settings, FALSE);
desc = (struct arbfp_ffp_desc *) find_ffp_frag_shader(priv->fragment_shaders, &settings);

View File

@ -3854,7 +3854,7 @@ static void device_map_vsamplers(IWineD3DDeviceImpl *This, BOOL ps) {
IWineD3DPixelShaderImpl *pshader = (IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader;
/* Make sure the shader's reg_maps are up to date. This is only relevant for 1.x pixelshaders. */
IWineD3DPixelShader_CompileShader((IWineD3DPixelShader *)pshader);
IWineD3DPixelShader_UpdateSamplers((IWineD3DPixelShader *)pshader);
pshader_sampler_tokens = pshader->baseShader.reg_maps.samplers;
}

View File

@ -3225,9 +3225,20 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use
GLhandleARB reorder_shader_id = 0;
int i;
char glsl_name[8];
GLhandleARB vshader_id, pshader_id;
GLhandleARB vshader_id = use_vs ? ((IWineD3DBaseShaderImpl*)vshader)->baseShader.prgId : 0;
GLhandleARB pshader_id = use_ps ? ((IWineD3DBaseShaderImpl*)pshader)->baseShader.prgId : 0;
if(use_vs) {
IWineD3DVertexShaderImpl_CompileShader(vshader);
vshader_id = ((IWineD3DBaseShaderImpl*)vshader)->baseShader.prgId;
} else {
vshader_id = 0;
}
if(use_ps) {
pixelshader_compile(pshader);
pshader_id = ((IWineD3DBaseShaderImpl*)pshader)->baseShader.prgId;
} else {
pshader_id = 0;
}
entry = get_glsl_program_entry(priv, vshader_id, pshader_id);
if (entry) {
priv->glsl_program = entry;

View File

@ -384,13 +384,14 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *i
return WINED3D_OK;
}
static HRESULT WINAPI IWineD3DPixelShaderImpl_CompileShader(IWineD3DPixelShader *iface) {
HRESULT pixelshader_compile(IWineD3DPixelShader *iface) {
IWineD3DPixelShaderImpl *This =(IWineD3DPixelShaderImpl *)iface;
IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
CONST DWORD *function = This->baseShader.function;
UINT i, sampler;
IWineD3DBaseTextureImpl *texture;
HRESULT hr;
TRACE("(%p) : function %p\n", iface, function);
@ -465,17 +466,8 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_CompileShader(IWineD3DPixelShader
return WINED3D_OK;
}
if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1) {
shader_reg_maps *reg_maps = &This->baseShader.reg_maps;
HRESULT hr;
/* 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,
This->semantics_in, NULL, This->baseShader.function, deviceImpl->stateBlock);
if (FAILED(hr)) return hr;
/* FIXME: validate reg_maps against OpenGL */
}
hr = IWineD3DPixelShader_UpdateSamplers(iface);
if(FAILED(hr)) return hr;
/* Reset fields tracking stateblock values being hardcoded in the shader */
This->baseShader.num_sampled_samplers = 0;
@ -489,6 +481,25 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_CompileShader(IWineD3DPixelShader
return WINED3D_OK;
}
static HRESULT WINAPI IWineD3DPixelShaderImpl_UpdateSamplers(IWineD3DPixelShader *iface) {
IWineD3DPixelShaderImpl *This =(IWineD3DPixelShaderImpl *)iface;
if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1) {
IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
shader_reg_maps *reg_maps = &This->baseShader.reg_maps;
HRESULT hr;
/* 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,
This->semantics_in, NULL, This->baseShader.function, deviceImpl->stateBlock);
return hr;
/* FIXME: validate reg_maps against OpenGL */
} else {
return WINED3D_OK;
}
}
const IWineD3DPixelShaderVtbl IWineD3DPixelShader_Vtbl =
{
/*** IUnknown methods ***/
@ -499,8 +510,8 @@ const IWineD3DPixelShaderVtbl IWineD3DPixelShader_Vtbl =
IWineD3DPixelShaderImpl_GetParent,
/*** IWineD3DBaseShader methods ***/
IWineD3DPixelShaderImpl_SetFunction,
IWineD3DPixelShaderImpl_CompileShader,
/*** IWineD3DPixelShader methods ***/
IWineD3DPixelShaderImpl_UpdateSamplers,
IWineD3DPixelShaderImpl_GetDevice,
IWineD3DPixelShaderImpl_GetFunction
};

View File

@ -3518,9 +3518,6 @@ void apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DC
* if a different texture was bound. I don't have to do anything.
*/
}
/* Compile and bind the shader */
IWineD3DPixelShader_CompileShader(stateblock->pixelShader);
} else {
/* Disabled the pixel shader - color ops weren't applied
* while it was enabled, so re-apply them.
@ -4511,11 +4508,6 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W
state_normalize(STATE_RENDER(WINED3DRS_NORMALIZENORMALS), stateblock, context);
}
} else {
/* 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(stateblock->vertexShader);
if(!context->last_was_vshader) {
int i;
static BOOL warned = FALSE;

View File

@ -563,7 +563,7 @@ static inline BOOL swizzled_attribs_differ(IWineD3DVertexShaderImpl *This, IWine
return FALSE;
}
static HRESULT WINAPI IWineD3DVertexShaderImpl_CompileShader(IWineD3DVertexShader *iface) {
HRESULT IWineD3DVertexShaderImpl_CompileShader(IWineD3DVertexShader *iface) {
IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
IWineD3DVertexDeclarationImpl *vdecl;
CONST DWORD *function = This->baseShader.function;
@ -626,7 +626,6 @@ const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
IWineD3DVertexShaderImpl_GetParent,
/*** IWineD3DBaseShader methods ***/
IWineD3DVertexShaderImpl_SetFunction,
IWineD3DVertexShaderImpl_CompileShader,
/*** IWineD3DVertexShader methods ***/
IWineD3DVertexShaderImpl_GetDevice,
IWineD3DVertexShaderImpl_GetFunction,

View File

@ -2320,6 +2320,7 @@ typedef struct IWineD3DVertexShaderImpl {
} IWineD3DVertexShaderImpl;
extern const SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[];
extern const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl;
HRESULT IWineD3DVertexShaderImpl_CompileShader(IWineD3DVertexShader *iface);
/*****************************************************************************
* IDirect3DPixelShader implementation structure
@ -2368,6 +2369,7 @@ typedef struct IWineD3DPixelShaderImpl {
extern const SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[];
extern const IWineD3DPixelShaderVtbl IWineD3DPixelShader_Vtbl;
HRESULT pixelshader_compile(IWineD3DPixelShader *iface);
/* sRGB correction constants */
static const float srgb_cmp = 0.0031308;

View File

@ -1458,7 +1458,6 @@ 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
@ -1471,7 +1470,6 @@ 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
/*****************************************************************************
@ -1488,7 +1486,6 @@ 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;
@ -1506,7 +1503,6 @@ 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)
@ -1528,8 +1524,8 @@ 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(UpdateSamplers)(THIS) PURE;
STDMETHOD(GetDevice)(THIS_ IWineD3DDevice** ppDevice) PURE;
STDMETHOD(GetFunction)(THIS_ VOID* pData, UINT* pSizeOfData) PURE;
};
@ -1544,8 +1540,8 @@ 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_UpdateSamplers(p) (p)->lpVtbl->UpdateSamplers(p)
#define IWineD3DPixelShader_GetDevice(p,a) (p)->lpVtbl->GetDevice(p,a)
#define IWineD3DPixelShader_GetFunction(p,a,b) (p)->lpVtbl->GetFunction(p,a,b)
#endif