wined3d: Implement D3DTA_TEMP in the GL_ATI_fragment_shader codepath.

This commit is contained in:
Stefan Dösinger 2008-03-29 23:55:09 +01:00 committed by Alexandre Julliard
parent 8f9a14e312
commit 287f60a2b2
5 changed files with 94 additions and 10 deletions

View File

@ -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) {

View File

@ -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

View File

@ -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
*/

View File

@ -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 */

View File

@ -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;
};