Module: wine Branch: master Commit: 287f60a2b20902d5e3b12b5236927e8faf929623 URL: http://source.winehq.org/git/wine.git/?a=commit;h=287f60a2b20902d5e3b12b5236...
Author: Stefan Dösinger stefan@codeweavers.com Date: Sat Mar 29 23:55:09 2008 +0100
wined3d: Implement D3DTA_TEMP in the GL_ATI_fragment_shader codepath.
---
dlls/wined3d/ati_fragment_shader.c | 78 +++++++++++++++++++++++++++++++++++- dlls/wined3d/baseshader.c | 9 ++++ dlls/wined3d/directx.c | 11 +---- dlls/wined3d/utils.c | 3 + dlls/wined3d/wined3d_private.h | 3 + 5 files changed, 94 insertions(+), 10 deletions(-)
diff --git a/dlls/wined3d/ati_fragment_shader.c b/dlls/wined3d/ati_fragment_shader.c index d483c22..cd6f892 100644 --- a/dlls/wined3d/ati_fragment_shader.c +++ b/dlls/wined3d/ati_fragment_shader.c @@ -208,13 +208,73 @@ static GLuint register_for_arg(DWORD arg, WineD3D_GL_Info *gl_info, unsigned int return ret; }
+static GLuint find_tmpreg(struct texture_stage_op op[MAX_TEXTURES]) { + int lowest_read = -1; + int lowest_write = -1; + int i; + BOOL tex_used[MAX_TEXTURES]; + + memset(tex_used, 0, sizeof(tex_used)); + for(i = 0; i < MAX_TEXTURES; i++) { + if(op[i].cop == WINED3DTOP_DISABLE) { + break; + } + + if(lowest_read == -1 && + (op[i].carg1 == WINED3DTA_TEMP || op[i].carg2 == WINED3DTA_TEMP || op[i].carg0 == WINED3DTA_TEMP || + op[i].aarg1 == WINED3DTA_TEMP || op[i].aarg2 == WINED3DTA_TEMP || op[i].aarg0 == WINED3DTA_TEMP)) { + lowest_read = i; + } + + if(lowest_write == -1 && op[i].dst == WINED3DTA_TEMP) { + lowest_write = i; + } + + if(op[i].carg1 == WINED3DTA_TEXTURE || op[i].carg2 == WINED3DTA_TEXTURE || op[i].carg0 == WINED3DTA_TEXTURE || + op[i].aarg1 == WINED3DTA_TEXTURE || op[i].aarg2 == WINED3DTA_TEXTURE || op[i].aarg0 == WINED3DTA_TEXTURE) { + tex_used[i] = TRUE; + } + } + + /* Temp reg not read? We don't need it, return GL_NONE */ + if(lowest_read == -1) return GL_NONE; + + if(lowest_write >= lowest_read) { + FIXME("Temp register read before beeing written\n"); + } + + if(lowest_write == -1) { + /* This needs a test. Maybe we are supposed to return 0.0/0.0/0.0/0.0, or fail drawprim, or whatever */ + FIXME("Temp register read without beeing written\n"); + return GL_REG_1_ATI; + } else if(lowest_write >= 1) { + /* If we're writing to the temp reg at earliest in stage 1, we can use register 1 for the temp result. + * there may be texture data stored in reg 1, but we do not need it any longer since stage 1 already + * read it + */ + return GL_REG_1_ATI; + } else { + /* Search for a free texture register. We have 6 registers available. GL_REG_0_ATI is already used + * for the regular result + */ + for(i = 1; i < 6; i++) { + if(!tex_used[i]) { + return GL_REG_0_ATI + i; + } + } + /* What to do here? Report it in ValidateDevice? */ + FIXME("Could not find a register for the temporary register\n"); + return 0; + } +} + static GLuint gen_ati_shader(struct texture_stage_op op[MAX_TEXTURES], WineD3D_GL_Info *gl_info) { GLuint ret = GL_EXTCALL(glGenFragmentShadersATI(1)); unsigned int stage; GLuint arg0, arg1, arg2, extrarg; GLuint dstmod, argmod0, argmod1, argmod2, argmodextra; GLuint swizzle; - GLuint tmparg = -1; + GLuint tmparg = find_tmpreg(op); GLuint dstreg;
if(!ret) { @@ -358,7 +418,16 @@ static GLuint gen_ati_shader(struct texture_stage_op op[MAX_TEXTURES], WineD3D_G break; }
- dstreg = GL_REG_0_ATI; + if(op[stage].dst == WINED3DTA_TEMP) { + /* If we're writing to D3DTA_TEMP, but never reading from it we don't have to write there in the first place. + * skip the entire stage, this saves some GPU time + */ + if(tmparg == GL_NONE) continue; + + dstreg = tmparg; + } else { + dstreg = GL_REG_0_ATI; + }
arg0 = register_for_arg(op[stage].carg0, gl_info, stage, &argmod0, tmparg); arg1 = register_for_arg(op[stage].carg1, gl_info, stage, &argmod1, tmparg); @@ -803,6 +872,9 @@ static void init_state_table() { ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_ALPHAARG0)].apply = set_tex_op_atifs; ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_ALPHAARG0)].representative = rep;
+ ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_RESULTARG)].apply = set_tex_op_atifs; + ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_RESULTARG)].representative = rep; + ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_BUMPENVMAT00)].apply = set_bumpmat; ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_BUMPENVMAT01)].apply = set_bumpmat; ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_BUMPENVMAT10)].apply = set_bumpmat; @@ -942,6 +1014,8 @@ static void shader_atifs_get_caps(WINED3DDEVTYPE devtype, WineD3D_GL_Info *gl_in WARN("but GL_ATI_fragment_shader limits this to 6\n"); caps->MaxSimultaneousTextures = 6; } + + caps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP; }
static void shader_atifs_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer) { diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c index 678b119..4bb1ee7 100644 --- a/dlls/wined3d/baseshader.c +++ b/dlls/wined3d/baseshader.c @@ -1169,6 +1169,15 @@ static void shader_none_get_caps(WINED3DDEVTYPE devtype, WineD3D_GL_Info *gl_inf pCaps->VertexShaderVersion = 0; pCaps->PixelShaderVersion = 0; pCaps->PixelShader1xMaxValue = 0.0; + + /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */ +#if 0 + if (GL_SUPPORT(NV_REGISTER_COMBINERS)) + pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP; + if (GL_SUPPORT(NV_REGISTER_COMBINERS2)) + pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT; +#endif + } #undef GLINFO_LOCATION
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 6baf8d3..8cb8ca6 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -2791,14 +2791,6 @@ static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, if(GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE) && GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE)) pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_SEPARATEALPHABLEND;
-/* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */ -#if 0 - if (GL_SUPPORT(NV_REGISTER_COMBINERS)) - pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP; - if (GL_SUPPORT(NV_REGISTER_COMBINERS2)) - pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT; -#endif - pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER | WINED3DPRASTERCAPS_PAT | WINED3DPRASTERCAPS_WFOG | @@ -3089,6 +3081,9 @@ static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, shader_backend = select_shader_backend(Adapter, DeviceType); shader_backend->shader_get_caps(DeviceType, &GLINFO_LOCATION, &shader_caps);
+ /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */ + pCaps->PrimitiveMiscCaps |= shader_caps.PrimitiveMiscCaps; + /* This takes care for disabling vertex shader or pixel shader caps while leaving the other one enabled. * Ignore shader model capabilities if disabled in config */ diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index d0285df..f55ca14 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -3271,6 +3271,7 @@ void gen_ffp_op(IWineD3DStateBlockImpl *stateblock, struct texture_stage_op op[M op[i].carg0 = op[i].carg1 = op[i].carg2 = 0xffffffff; op[i].aarg0 = op[i].aarg1 = op[i].aarg2 = 0xffffffff; op[i].color_correction = WINED3DFMT_UNKNOWN; + op[i].dst = 0xffffffff; i++; break; } @@ -3344,6 +3345,8 @@ void gen_ffp_op(IWineD3DStateBlockImpl *stateblock, struct texture_stage_op op[M } else { op[i].projected = proj_none; } + + op[i].dst = stateblock->textureState[i][WINED3DTSS_RESULTARG]; }
/* Clear unsupported stages */ diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index c3f4910..0044bab 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -259,6 +259,8 @@ typedef struct SHADER_BUFFER { } SHADER_BUFFER;
struct shader_caps { + DWORD PrimitiveMiscCaps; + DWORD TextureOpCaps; DWORD MaxTextureBlendStages; DWORD MaxSimultaneousTextures; @@ -730,6 +732,7 @@ struct texture_stage_op DWORD carg1, carg2, carg0; DWORD aarg1, aarg2, aarg0; WINED3DFORMAT color_correction; + DWORD dst; enum projection_types projected; };