wined3d: Disable vertex shaders when transformed vertices are used.

This commit is contained in:
H. Verbeet 2007-03-12 23:22:00 +01:00 committed by Alexandre Julliard
parent ee09e8bfd6
commit 30ee071eb9
5 changed files with 49 additions and 28 deletions

View File

@ -161,6 +161,17 @@ void primitiveDeclarationConvertToStridedData(
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 */
for (i = 0 ; i < vertexDeclaration->declarationWNumElements - 1; ++i) {
GLint streamVBO = 0;
@ -188,7 +199,7 @@ void primitiveDeclarationConvertToStridedData(
data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0, &streamVBO);
if(fixup) {
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 */
FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
}
@ -218,12 +229,6 @@ void primitiveDeclarationConvertToStridedData(
strided->u.input[idx].dwStride = stride;
strided->u.input[idx].VBO = streamVBO;
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
@ -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
* storage to read and restore the old shader settings
*/
This->shader_backend->shader_select(iface,
This->stateBlock->pixelShader && ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.function,
This->stateBlock->vertexShader && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.function);
This->shader_backend->shader_select(iface, use_ps(This), use_vs(This));
}
static void depth_copy(IWineD3DDevice *iface) {

View File

@ -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
* 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;
WineD3D_GL_Info *gl_info = &((IWineD3DImpl *)(This->wineD3D))->gl_info;
IWineD3DPixelShader *pshader = This->stateBlock->pixelShader;
@ -2059,8 +2059,8 @@ static void set_glsl_shader_program(IWineD3DDevice *iface) {
int i;
char glsl_name[8];
GLhandleARB vshader_id = (vshader && This->vs_selected_mode == SHADER_GLSL) ? ((IWineD3DBaseShaderImpl*)vshader)->baseShader.prgId : 0;
GLhandleARB pshader_id = (pshader && This->ps_selected_mode == SHADER_GLSL) ? ((IWineD3DBaseShaderImpl*)pshader)->baseShader.prgId : 0;
GLhandleARB vshader_id = use_vs ? ((IWineD3DBaseShaderImpl*)vshader)->baseShader.prgId : 0;
GLhandleARB pshader_id = use_ps ? ((IWineD3DBaseShaderImpl*)pshader)->baseShader.prgId : 0;
entry = get_glsl_program_entry(This, vshader_id, pshader_id);
if (entry) {
This->stateBlock->glsl_program = entry;
@ -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;
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;
program_id = This->stateBlock->glsl_program ? This->stateBlock->glsl_program->programId : 0;

View File

@ -395,7 +395,7 @@ static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine
DWORD enable = 0xFFFFFFFF;
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,
* 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
@ -709,8 +709,8 @@ static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo
fogend = tmpvalue.f;
/* Activate when vertex shaders are in the state table */
if(stateblock->vertexShader && ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.function &&
((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->usesFog) {
if (use_vs(stateblock->wineD3DDevice)
&& ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->usesFog) {
glFogi(GL_FOG_MODE, GL_LINEAR);
checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
if (stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
@ -1977,17 +1977,16 @@ static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine
return;
}
device->shader_backend->shader_load_constants((IWineD3DDevice *) device,
stateblock->pixelShader && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function,
stateblock->vertexShader && ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.function);
device->shader_backend->shader_load_constants((IWineD3DDevice *) device, use_ps(device), use_vs(device));
}
static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
BOOL use_ps = stateblock->pixelShader && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function != NULL;
BOOL use_vs = stateblock->vertexShader && ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.function != NULL;
IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
BOOL use_pshader = use_ps(device);
BOOL use_vshader = use_vs(device);
int i;
if (use_ps) {
if (use_pshader) {
if(!context->last_was_pshader) {
/* Former draw without a pixel shader, some samplers
* may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE
@ -2018,14 +2017,14 @@ static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D
}
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);
}
}
context->last_was_pshader = use_ps;
context->last_was_pshader = use_pshader;
}
static void tex_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
@ -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 */
if(context->numberedArraysLoaded) {
unloadNumberedArrays(stateblock);
@ -2906,6 +2909,7 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W
transformed = ((device->strided_streams.u.s.position.lpData != NULL ||
device->strided_streams.u.s.position.VBO != 0) &&
device->strided_streams.u.s.position_transformed) ? TRUE : FALSE;
if (transformed) useVertexShaderFunction = FALSE;
if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
updateFog = TRUE;
@ -2916,7 +2920,7 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W
state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context);
}
if (!useVertexShaderFunction && transformed) {
if (transformed) {
context->last_was_rhw = TRUE;
} else {

View File

@ -197,7 +197,7 @@ inline BOOL WINAPI IWineD3DVertexBufferImpl_FindDecl(IWineD3DVertexBufferImpl *T
* FALSE: otherwise
*/
if(device->stateBlock->vertexShader && ((IWineD3DVertexShaderImpl *) device->stateBlock->vertexShader)->baseShader.function) {
if (use_vs(device)) {
/* Assume no conversion */
memset(&strided, 0, sizeof(strided));
} else {

View File

@ -1936,4 +1936,18 @@ typedef struct {
} PixelFormatDesc;
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