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