Stefan Dösinger : wined3d: Implement D3DTA_TEMP in the GL_ATI_fragment_shader codepath.
Alexandre Julliard
julliard at winehq.org
Wed Apr 2 16:36:21 CDT 2008
Module: wine
Branch: master
Commit: 287f60a2b20902d5e3b12b5236927e8faf929623
URL: http://source.winehq.org/git/wine.git/?a=commit;h=287f60a2b20902d5e3b12b5236927e8faf929623
Author: Stefan Dösinger <stefan at 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;
};
More information about the wine-cvs
mailing list