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

wined3d: Disable vertex shaders when transformed vertices are used.

parent ee09e8bf
...@@ -161,6 +161,17 @@ void primitiveDeclarationConvertToStridedData( ...@@ -161,6 +161,17 @@ void primitiveDeclarationConvertToStridedData(
memset(isPreLoaded, 0, sizeof(isPreLoaded)); memset(isPreLoaded, 0, sizeof(isPreLoaded));
/* Check for transformed vertices, disable vertex shader if present */
strided->u.s.position_transformed = FALSE;
for (i = 0; i < vertexDeclaration->declarationWNumElements - 1; ++i) {
element = vertexDeclaration->pDeclarationWine + i;
if (element->Usage == WINED3DDECLUSAGE_POSITIONT) {
strided->u.s.position_transformed = TRUE;
useVertexShaderFunction = FALSE;
}
}
/* Translate the declaration into strided data */ /* Translate the declaration into strided data */
for (i = 0 ; i < vertexDeclaration->declarationWNumElements - 1; ++i) { for (i = 0 ; i < vertexDeclaration->declarationWNumElements - 1; ++i) {
GLint streamVBO = 0; GLint streamVBO = 0;
...@@ -188,7 +199,7 @@ void primitiveDeclarationConvertToStridedData( ...@@ -188,7 +199,7 @@ void primitiveDeclarationConvertToStridedData(
data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0, &streamVBO); data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0, &streamVBO);
if(fixup) { if(fixup) {
if( streamVBO != 0) *fixup = TRUE; if( streamVBO != 0) *fixup = TRUE;
else if(*fixup && This->stateBlock->vertexShader == NULL) { else if(*fixup && !useVertexShaderFunction) {
/* This may be bad with the fixed function pipeline */ /* This may be bad with the fixed function pipeline */
FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n"); FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
} }
...@@ -218,12 +229,6 @@ void primitiveDeclarationConvertToStridedData( ...@@ -218,12 +229,6 @@ void primitiveDeclarationConvertToStridedData(
strided->u.input[idx].dwStride = stride; strided->u.input[idx].dwStride = stride;
strided->u.input[idx].VBO = streamVBO; strided->u.input[idx].VBO = streamVBO;
strided->u.input[idx].streamNo = element->Stream; strided->u.input[idx].streamNo = element->Stream;
if (!useVertexShaderFunction) {
if (element->Usage == WINED3DDECLUSAGE_POSITION)
strided->u.s.position_transformed = FALSE;
else if (element->Usage == WINED3DDECLUSAGE_POSITIONT)
strided->u.s.position_transformed = TRUE;
}
} }
} }
/* Now call PreLoad on all the vertex buffers. In the very rare case /* Now call PreLoad on all the vertex buffers. In the very rare case
...@@ -796,9 +801,7 @@ static void depth_blt(IWineD3DDevice *iface, GLuint texture) { ...@@ -796,9 +801,7 @@ static void depth_blt(IWineD3DDevice *iface, GLuint texture) {
* and this seems easier and more efficient than providing the shader backend with a private * and this seems easier and more efficient than providing the shader backend with a private
* storage to read and restore the old shader settings * storage to read and restore the old shader settings
*/ */
This->shader_backend->shader_select(iface, This->shader_backend->shader_select(iface, use_ps(This), use_vs(This));
This->stateBlock->pixelShader && ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.function,
This->stateBlock->vertexShader && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.function);
} }
static void depth_copy(IWineD3DDevice *iface) { static void depth_copy(IWineD3DDevice *iface) {
......
...@@ -2049,7 +2049,7 @@ void delete_glsl_program_entry(IWineD3DDevice *iface, struct glsl_shader_prog_li ...@@ -2049,7 +2049,7 @@ void delete_glsl_program_entry(IWineD3DDevice *iface, struct glsl_shader_prog_li
* the program in the hash table. If it creates a program, it will link the * the program in the hash table. If it creates a program, it will link the
* given objects, too. * given objects, too.
*/ */
static void set_glsl_shader_program(IWineD3DDevice *iface) { static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use_vs) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
WineD3D_GL_Info *gl_info = &((IWineD3DImpl *)(This->wineD3D))->gl_info; WineD3D_GL_Info *gl_info = &((IWineD3DImpl *)(This->wineD3D))->gl_info;
IWineD3DPixelShader *pshader = This->stateBlock->pixelShader; IWineD3DPixelShader *pshader = This->stateBlock->pixelShader;
...@@ -2059,8 +2059,8 @@ static void set_glsl_shader_program(IWineD3DDevice *iface) { ...@@ -2059,8 +2059,8 @@ static void set_glsl_shader_program(IWineD3DDevice *iface) {
int i; int i;
char glsl_name[8]; char glsl_name[8];
GLhandleARB vshader_id = (vshader && This->vs_selected_mode == SHADER_GLSL) ? ((IWineD3DBaseShaderImpl*)vshader)->baseShader.prgId : 0; GLhandleARB vshader_id = use_vs ? ((IWineD3DBaseShaderImpl*)vshader)->baseShader.prgId : 0;
GLhandleARB pshader_id = (pshader && This->ps_selected_mode == SHADER_GLSL) ? ((IWineD3DBaseShaderImpl*)pshader)->baseShader.prgId : 0; GLhandleARB pshader_id = use_ps ? ((IWineD3DBaseShaderImpl*)pshader)->baseShader.prgId : 0;
entry = get_glsl_program_entry(This, vshader_id, pshader_id); entry = get_glsl_program_entry(This, vshader_id, pshader_id);
if (entry) { if (entry) {
This->stateBlock->glsl_program = entry; This->stateBlock->glsl_program = entry;
...@@ -2179,7 +2179,7 @@ static void shader_glsl_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) { ...@@ -2179,7 +2179,7 @@ static void shader_glsl_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {
WineD3D_GL_Info *gl_info = &((IWineD3DImpl *)(This->wineD3D))->gl_info; WineD3D_GL_Info *gl_info = &((IWineD3DImpl *)(This->wineD3D))->gl_info;
GLhandleARB program_id = 0; GLhandleARB program_id = 0;
if (useVS || usePS) set_glsl_shader_program(iface); if (useVS || usePS) set_glsl_shader_program(iface, usePS, useVS);
else This->stateBlock->glsl_program = NULL; else This->stateBlock->glsl_program = NULL;
program_id = This->stateBlock->glsl_program ? This->stateBlock->glsl_program->programId : 0; program_id = This->stateBlock->glsl_program ? This->stateBlock->glsl_program->programId : 0;
......
...@@ -395,7 +395,7 @@ static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine ...@@ -395,7 +395,7 @@ static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine
DWORD enable = 0xFFFFFFFF; DWORD enable = 0xFFFFFFFF;
DWORD disable = 0x00000000; DWORD disable = 0x00000000;
if(stateblock->vertexShader) { if (use_vs(stateblock->wineD3DDevice)) {
/* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't, /* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't,
* so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some * so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some
* contitions I got sick of tracking down. The shader state handler disables all clip planes because * contitions I got sick of tracking down. The shader state handler disables all clip planes because
...@@ -709,8 +709,8 @@ static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo ...@@ -709,8 +709,8 @@ static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo
fogend = tmpvalue.f; fogend = tmpvalue.f;
/* Activate when vertex shaders are in the state table */ /* Activate when vertex shaders are in the state table */
if(stateblock->vertexShader && ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.function && if (use_vs(stateblock->wineD3DDevice)
((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->usesFog) { && ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->usesFog) {
glFogi(GL_FOG_MODE, GL_LINEAR); glFogi(GL_FOG_MODE, GL_LINEAR);
checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)"); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
if (stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) { if (stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
...@@ -1977,17 +1977,16 @@ static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine ...@@ -1977,17 +1977,16 @@ static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine
return; return;
} }
device->shader_backend->shader_load_constants((IWineD3DDevice *) device, device->shader_backend->shader_load_constants((IWineD3DDevice *) device, use_ps(device), use_vs(device));
stateblock->pixelShader && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function,
stateblock->vertexShader && ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.function);
} }
static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
BOOL use_ps = stateblock->pixelShader && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function != NULL; IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
BOOL use_vs = stateblock->vertexShader && ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.function != NULL; BOOL use_pshader = use_ps(device);
BOOL use_vshader = use_vs(device);
int i; int i;
if (use_ps) { if (use_pshader) {
if(!context->last_was_pshader) { if(!context->last_was_pshader) {
/* Former draw without a pixel shader, some samplers /* Former draw without a pixel shader, some samplers
* may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE * may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE
...@@ -2018,14 +2017,14 @@ static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D ...@@ -2018,14 +2017,14 @@ static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D
} }
if(!isStateDirty(context, StateTable[STATE_VSHADER].representative)) { if(!isStateDirty(context, StateTable[STATE_VSHADER].representative)) {
stateblock->wineD3DDevice->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_ps, use_vs); device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_pshader, use_vshader);
if(!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vs || use_ps)) { if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) {
shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context); shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
} }
} }
context->last_was_pshader = use_ps; context->last_was_pshader = use_pshader;
} }
static void tex_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { static void tex_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
...@@ -2827,6 +2826,10 @@ static inline void handleStreams(IWineD3DStateBlockImpl *stateblock, BOOL useVer ...@@ -2827,6 +2826,10 @@ static inline void handleStreams(IWineD3DStateBlockImpl *stateblock, BOOL useVer
} }
} }
if (dataLocations->u.s.position_transformed) {
useVertexShaderFunction = FALSE;
}
/* Unload the old arrays before loading the new ones to get old junk out */ /* Unload the old arrays before loading the new ones to get old junk out */
if(context->numberedArraysLoaded) { if(context->numberedArraysLoaded) {
unloadNumberedArrays(stateblock); unloadNumberedArrays(stateblock);
...@@ -2906,6 +2909,7 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W ...@@ -2906,6 +2909,7 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W
transformed = ((device->strided_streams.u.s.position.lpData != NULL || transformed = ((device->strided_streams.u.s.position.lpData != NULL ||
device->strided_streams.u.s.position.VBO != 0) && device->strided_streams.u.s.position.VBO != 0) &&
device->strided_streams.u.s.position_transformed) ? TRUE : FALSE; device->strided_streams.u.s.position_transformed) ? TRUE : FALSE;
if (transformed) useVertexShaderFunction = FALSE;
if(transformed != context->last_was_rhw && !useVertexShaderFunction) { if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
updateFog = TRUE; updateFog = TRUE;
...@@ -2916,7 +2920,7 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W ...@@ -2916,7 +2920,7 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W
state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context); state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context);
} }
if (!useVertexShaderFunction && transformed) { if (transformed) {
context->last_was_rhw = TRUE; context->last_was_rhw = TRUE;
} else { } else {
......
...@@ -197,7 +197,7 @@ inline BOOL WINAPI IWineD3DVertexBufferImpl_FindDecl(IWineD3DVertexBufferImpl *T ...@@ -197,7 +197,7 @@ inline BOOL WINAPI IWineD3DVertexBufferImpl_FindDecl(IWineD3DVertexBufferImpl *T
* FALSE: otherwise * FALSE: otherwise
*/ */
if(device->stateBlock->vertexShader && ((IWineD3DVertexShaderImpl *) device->stateBlock->vertexShader)->baseShader.function) { if (use_vs(device)) {
/* Assume no conversion */ /* Assume no conversion */
memset(&strided, 0, sizeof(strided)); memset(&strided, 0, sizeof(strided));
} else { } else {
......
...@@ -1936,4 +1936,18 @@ typedef struct { ...@@ -1936,4 +1936,18 @@ typedef struct {
} PixelFormatDesc; } PixelFormatDesc;
const PixelFormatDesc *getFormatDescEntry(WINED3DFORMAT fmt); const PixelFormatDesc *getFormatDescEntry(WINED3DFORMAT fmt);
inline static BOOL use_vs(IWineD3DDeviceImpl *device) {
return (device->vs_selected_mode != SHADER_NONE
&& device->stateBlock->vertexShader
&& ((IWineD3DVertexShaderImpl *)device->stateBlock->vertexShader)->baseShader.function
&& !device->strided_streams.u.s.position_transformed);
}
inline static BOOL use_ps(IWineD3DDeviceImpl *device) {
return (device->ps_selected_mode != SHADER_NONE
&& device->stateBlock->pixelShader
&& ((IWineD3DPixelShaderImpl *)device->stateBlock->pixelShader)->baseShader.function);
}
#endif #endif
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