wined3d: Initialize output texcoord .w to 1.0 if needed.

The GL_ARB_vertex_program extension does not define a standard value for
output texture coordinates. This makes problems when using vertex
shaders with fixed function fragment processing because fffp divides the
texture coords by its .w component. This means that gl shaders have to
write to the .w component of texture coords. Direct3D shaders however
do not.
This commit is contained in:
Stefan Dösinger 2007-12-06 22:10:11 +01:00 committed by Alexandre Julliard
parent 6cdbb96b27
commit 54fa712981
6 changed files with 62 additions and 5 deletions

View File

@ -463,6 +463,15 @@ HRESULT shader_get_registers_used(
reg_maps->usesrelconstF = TRUE;
}
}
/* WINED3DSPR_TEXCRDOUT is the same as WINED3DSPR_OUTPUT. _OUTPUT can be > MAX_REG_TEXCRD and is used
* in >= 3.0 shaders. Filter 3.0 shaders to prevent overflows, and also filter pixel shaders because TECRDOUT
* isn't used in them, but future register types might cause issues
*/
else if(WINED3DSPR_TEXCRDOUT == regtype && i == 0 /* Only look at writes */ &&
!pshader && WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) < 3) {
reg_maps->texcoord_mask[reg] |= shader_get_writemask(param);
}
}
}
}

View File

@ -2860,6 +2860,20 @@ static void fixup_extensions(WineD3D_GL_Info *gl_info) {
gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
}
}
/* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
* with fixed function fragment processing. Ideally this flag should be detected with a test shader
* and opengl feedback mode, but some GL implementations(MacOS ATI at least, propably all macos ones)
* do not like vertex shaders in feedback mode and return an error, even though it should be valid
* according to the spec.
*
* We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
* makes the shader slower and eats instruction slots which should be available to the d3d app.
*/
if(gl_info->gl_vendor == VENDOR_INTEL) {
TRACE("Enabling vertex texture coord fixes in vertex shaders\n");
gl_info->set_texcoord_w = TRUE;
}
}
}

View File

@ -2870,7 +2870,7 @@ static GLhandleARB generate_param_reorder_function(IWineD3DVertexShader *vertexs
SHADER_BUFFER buffer;
DWORD usage_token;
DWORD register_token;
DWORD usage, usage_idx;
DWORD usage, usage_idx, writemask;
char reg_mask[6];
semantic *semantics_out, *semantics_in;
@ -2880,8 +2880,21 @@ static GLhandleARB generate_param_reorder_function(IWineD3DVertexShader *vertexs
buffer.newline = TRUE;
if(vs_major < 3 && ps_major < 3) {
/* That one is easy: The vertex shader writes to the builtin varyings, the pixel shader reads from them */
shader_addline(&buffer, "void order_ps_input() { /* do nothing */ }\n");
/* That one is easy: The vertex shader writes to the builtin varyings, the pixel shader reads from them.
* Take care about the texcoord .w fixup though if we're using the fixed function fragment pipeline
*/
if((GLINFO_LOCATION).set_texcoord_w && ps_major == 0 && vs_major > 0) {
shader_addline(&buffer, "void order_ps_input() {\n");
for(i = 0; i < min(8, MAX_REG_TEXCRD); i++) {
if(vs->baseShader.reg_maps.texcoord_mask[i] != 0 &&
vs->baseShader.reg_maps.texcoord_mask[i] != WINED3DSP_WRITEMASK_ALL) {
shader_addline(&buffer, "gl_TexCoord[%u].w = 1.0;\n", i);
}
}
shader_addline(&buffer, "}\n");
} else {
shader_addline(&buffer, "void order_ps_input() { /* do nothing */ }\n");
}
} else if(ps_major < 3 && vs_major >= 3) {
/* The vertex shader writes to its own varyings, the pixel shader needs them in the builtin ones */
semantics_out = vs->semantics_out;
@ -2894,7 +2907,7 @@ static GLhandleARB generate_param_reorder_function(IWineD3DVertexShader *vertexs
usage = (usage_token & WINED3DSP_DCL_USAGE_MASK) >> WINED3DSP_DCL_USAGE_SHIFT;
usage_idx = (usage_token & WINED3DSP_DCL_USAGEINDEX_MASK) >> WINED3DSP_DCL_USAGEINDEX_SHIFT;
shader_glsl_get_write_mask(register_token, reg_mask);
writemask = shader_glsl_get_write_mask(register_token, reg_mask);
switch(usage) {
case WINED3DDECLUSAGE_COLOR:
@ -2910,8 +2923,13 @@ static GLhandleARB generate_param_reorder_function(IWineD3DVertexShader *vertexs
case WINED3DDECLUSAGE_TEXCOORD:
if (usage_idx < 8) {
if(!(GLINFO_LOCATION).set_texcoord_w || ps_major > 0) writemask |= WINED3DSP_WRITEMASK_3;
shader_addline(&buffer, "gl_TexCoord[%u]%s = OUT[%u]%s;\n",
usage_idx, reg_mask, i, reg_mask);
usage_idx, reg_mask, i, reg_mask);
if(!(writemask & WINED3DSP_WRITEMASK_3)) {
shader_addline(&buffer, "gl_TexCoord[%u].w = 1.0;\n", usage_idx);
}
}
break;

View File

@ -455,6 +455,16 @@ static VOID IWineD3DVertexShaderImpl_GenerateShader(
/* We need a constant to fixup the final position */
shader_addline(&buffer, "PARAM posFixup = program.env[%d];\n", ARB_SHADER_PRIVCONST_POS);
if((GLINFO_LOCATION).set_texcoord_w) {
int i;
for(i = 0; i < min(8, MAX_REG_TEXCRD); i++) {
if(This->baseShader.reg_maps.texcoord_mask[i] != 0 &&
This->baseShader.reg_maps.texcoord_mask[i] != WINED3DSP_WRITEMASK_ALL) {
shader_addline(&buffer, "MOV result.texcoord[%u].w, -helper_const.y;\n", i);
}
}
}
/* Base Shader Body */
shader_generate_main( (IWineD3DBaseShader*) This, &buffer, reg_maps, pFunction);

View File

@ -1672,6 +1672,7 @@ typedef struct shader_reg_maps {
char packed_output[MAX_REG_OUTPUT]; /* vertex >= 3.0 */
char attributes[MAX_ATTRIBS]; /* vertex */
char labels[MAX_LABELS]; /* pixel, vertex */
DWORD texcoord_mask[MAX_REG_TEXCRD]; /* vertex < 3.0 */
/* Sampler usage tokens
* Use 0 as default (bit 31 is always 1 on a valid token) */
@ -2012,6 +2013,10 @@ static inline int shader_get_regtype(const DWORD param) {
((param & WINED3DSP_REGTYPE_MASK2) >> WINED3DSP_REGTYPE_SHIFT2));
}
static inline int shader_get_writemask(const DWORD param) {
return param & WINED3DSP_WRITEMASK_ALL;
}
extern unsigned int shader_get_float_offset(const DWORD reg);
static inline BOOL shader_is_pshader_version(DWORD token) {

View File

@ -3685,6 +3685,7 @@ typedef struct _WineD3D_GL_Info {
GL_VSVersion vs_ati_version;
BOOL arb_vs_offset_limit;
BOOL set_texcoord_w;
BOOL supported[OPENGL_SUPPORTED_EXT_END + 1];