wined3d: Implement D3DTA_TEMP in the GL_ATI_fragment_shader codepath.
This commit is contained in:
parent
8f9a14e312
commit
287f60a2b2
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue