wined3d: Only generate the clipplane emulation KIL if a clipplane is used.
The KIL is quite expensive because it forces drivers to disable early Z
discard. It is cheaper to generate and switch between two shaders.
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index a26950c..848d83d 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -125,7 +125,8 @@
struct arb_ps_compile_args
{
struct ps_compile_args super;
- DWORD bools; /* WORD is enough, use DWORD for alignment */
+ WORD bools;
+ WORD clip; /* only a boolean, use a WORD for alignment */
unsigned char loop_ctrl[MAX_CONST_I][3];
};
@@ -3496,7 +3497,7 @@
next_local += fixup->super.num_consts;
}
- if (shader_priv->clipplane_emulation != ~0U)
+ if (shader_priv->clipplane_emulation != ~0U && args->clip)
{
shader_addline(buffer, "KIL fragment.texcoord[%u];\n", shader_priv->clipplane_emulation);
}
@@ -4128,6 +4129,20 @@
if(stateblock->pixelShaderConstantB[i]) args->bools |= ( 1 << i);
}
+ /* Only enable the clip plane emulation KIL if at least one clipplane is enabled. The KIL instruction
+ * is quite expensive because it forces the driver to disable early Z discards. It is cheaper to
+ * duplicate the shader than have a no-op KIL instruction in every shader
+ */
+ if((!((IWineD3DDeviceImpl *) shader->baseShader.device)->vs_clipping) && use_vs(stateblock) &&
+ stateblock->renderState[WINED3DRS_CLIPPING] && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE])
+ {
+ args->clip = 1;
+ }
+ else
+ {
+ args->clip = 0;
+ }
+
/* Skip if unused or local, or supported natively */
int_skip = ~shader->baseShader.reg_maps.integer_constants | shader->baseShader.reg_maps.local_int_consts;
if(int_skip == 0xffff || GL_SUPPORT(NV_FRAGMENT_PROGRAM_OPTION))
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 3c25ebe..ff81078 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -2531,9 +2531,11 @@
} else {
settings->sRGB_write = 0;
}
- if(device->vs_clipping || !use_vs(stateblock)) {
+ if(device->vs_clipping || !use_vs(stateblock) || !stateblock->renderState[WINED3DRS_CLIPPING] ||
+ !stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
/* No need to emulate clipplanes if GL supports native vertex shader clipping or if
- * the fixed function vertex pipeline is used(which always supports clipplanes)
+ * the fixed function vertex pipeline is used(which always supports clipplanes), or
+ * if no clipplane is enabled
*/
settings->emul_clipplanes = 0;
} else {