wined3d: More shader fixes / new instructions

Jason Green jave27 at gmail.com
Fri Jul 28 02:43:54 CDT 2006


- ARB: Move the PROJECTION PARAM into the vertex shader generation
code since pixel shaders don't need it.
- GLSL: Translate oC0-oC3 output registers (multiple render targets)
to gl_FragData[] register.  We don't support draw buffers yet, but
this allows shader programs that use those registers to compile (such
as Settlers 2)
- GLSL: Correct implementation of D3DSIO_EXPP for 1.x shaders (fixes
the Nature test in 3dMark 2001).
- GLSL: Implement D3DSIO_TEXDP3TEX, D3DSIO_TEXDP3,
D3DSIO_TEXM3X2DEPTH, D3DSIO_TEXDEPTH, D3DSIO_TEXM3X3.
- Minor comment cleanups.
-------------- next part --------------
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index a2b07db..6700de3 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -171,7 +171,6 @@ void shader_generate_arb_declarations(
     /* Need to PARAM the environment parameters (constants) so we can use relative addressing */
     shader_addline(buffer, "PARAM C[%d] = { program.env[0..%d] };\n",
                    max_constantsF, max_constantsF - 1);
-    shader_addline(buffer, "PARAM PROJECTION = state.matrix.projection.row[1];\n");
 }
 
 static const char* shift_tab[] = {
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index b3ae5cb..6f280b3 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -643,7 +643,7 @@ static void shader_glsl_get_register_nam
         else {
             /* TODO: See GL_ARB_draw_buffers */
             FIXME("Unsupported write to render target %lu\n", reg);
-            sprintf(tmpStr, "unsupported_register");
+            sprintf(tmpStr, "gl_FragData[%lu]", reg);
         }
     break;
     case D3DSPR_RASTOUT:
@@ -914,7 +914,6 @@ void shader_glsl_map2gl(SHADER_OPCODE_AR
             case D3DSIO_NRM:    strcat(tmpLine, "normalize"); break;
             case D3DSIO_LOGP:
             case D3DSIO_LOG:    strcat(tmpLine, "log2"); break;
-            case D3DSIO_EXPP:
             case D3DSIO_EXP:    strcat(tmpLine, "exp2"); break;
             case D3DSIO_SGE:    strcat(tmpLine, "greaterThanEqual"); break;
             case D3DSIO_SLT:    strcat(tmpLine, "lessThan"); break;
@@ -942,6 +941,39 @@ void shader_glsl_map2gl(SHADER_OPCODE_AR
 
 }
 
+/** Process the D3DSIO_EXPP instruction in GLSL:
+ * For shader model 1.x, do the following (and honor the writemask, so use a temporary variable):
+ *   dst.x = 2^(floor(src))
+ *   dst.y = src - floor(src)
+ *   dst.z = 2^src   (partial precision is allowed, but optional)
+ *   dst.w = 1.0;
+ * For 2.0 shaders, just do this (honoring writemask and swizzle):
+ *   dst = 2^src;    (partial precision is allowed, but optional)
+ */
+void shader_glsl_expp(SHADER_OPCODE_ARG* arg) {
+
+    char tmpLine[256];
+    char dst_str[100], src_str[100];
+    char dst_reg[50], src_reg[50];
+    char dst_mask[6], src_mask[6];
+    IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
+    DWORD hex_version = This->baseShader.hex_version;
+    
+    shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str);
+    shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src_reg, src_mask, src_str);
+    shader_glsl_add_dst(arg->dst, dst_reg, dst_mask, tmpLine);
+
+    if (hex_version < D3DPS_VERSION(2,0)) {
+        shader_addline(arg->buffer, "tmp0.x = vec4(exp2(floor(%s))).x;\n", src_str);
+        shader_addline(arg->buffer, "tmp0.y = vec4(%s - floor(%s)).y;\n", src_str, src_str);
+        shader_addline(arg->buffer, "tmp0.z = vec4(exp2(%s)).x;\n", src_str);
+        shader_addline(arg->buffer, "tmp0.w = 1.0;\n");
+        shader_addline(arg->buffer, "%svec4(tmp0))%s;\n", tmpLine, dst_mask);
+    } else {
+        shader_addline(arg->buffer, "%svec4(exp2(%s)))%s;\n", tmpLine, src_str, dst_mask);
+    }
+}
+
 /** Process the RCP (reciprocal or inverse) opcode in GLSL (dst = 1 / src) */
 void shader_glsl_rcp(SHADER_OPCODE_ARG* arg) {
 
@@ -1354,6 +1386,73 @@ void pshader_glsl_texcoord(SHADER_OPCODE
    }
 }
 
+/** Process the D3DSIO_TEXDP3TEX instruction in GLSL:
+ * Take a 3-component dot product of the TexCoord[dstreg] and src,
+ * then perform a 1D texture lookup from stage dstregnum, place into dst. */
+void pshader_glsl_texdp3tex(SHADER_OPCODE_ARG* arg) {
+
+    DWORD dstreg = arg->dst & D3DSP_REGNUM_MASK;
+    char src0_str[100], dst_str[100];
+    char src0_name[50], dst_name[50];
+    char src0_mask[6],  dst_mask[6];
+
+    shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_name, dst_mask, dst_str);
+    shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_name, src0_mask, src0_str);
+
+    shader_addline(arg->buffer, "tmp0.x = dot(vec3(gl_TexCoord[%lu]), vec3(%s));\n", dstreg, src0_str);
+    shader_addline(arg->buffer, "%s = vec4(texture1D(Psampler%lu, tmp0.x))%s;\n", dst_str, dstreg, dst_mask);
+}
+
+/** Process the D3DSIO_TEXDP3 instruction in GLSL:
+ * Take a 3-component dot product of the TexCoord[dstreg] and src. */
+void pshader_glsl_texdp3(SHADER_OPCODE_ARG* arg) {
+
+    DWORD dstreg = arg->dst & D3DSP_REGNUM_MASK;
+    char src0_str[100], dst_str[100];
+    char src0_name[50], dst_name[50];
+    char src0_mask[6],  dst_mask[6];
+
+    shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_name, dst_mask, dst_str);
+    shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_name, src0_mask, src0_str);
+
+    shader_addline(arg->buffer, "%s = vec4(dot(vec3(T%lu), vec3(%s)))%s;\n",
+            dst_str, dstreg, src0_str, dst_mask);
+}
+
+/** Process the D3DSIO_TEXDEPTH instruction in GLSL:
+ * Calculate the depth as dst.x / dst.y   */
+void pshader_glsl_texdepth(SHADER_OPCODE_ARG* arg) {
+    
+    char dst_str[100];
+    char dst_reg[50];
+    char dst_mask[6];
+   
+    shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str);
+
+    shader_addline(arg->buffer, "gl_FragDepth = %s.x / %s.y;\n", dst_reg, dst_reg);
+}
+
+/** Process the D3DSIO_TEXM3X2DEPTH instruction in GLSL:
+ * Last row of a 3x2 matrix multiply, use the result to calculate the depth:
+ * Calculate tmp0.y = TexCoord[dstreg] . src.xyz;  (tmp0.x has already been calculated)
+ * depth = (tmp0.y == 0.0) ? 1.0 : tmp0.x / tmp0.y
+ */
+void pshader_glsl_texm3x2depth(SHADER_OPCODE_ARG* arg) {
+    
+    DWORD dstreg = arg->dst & D3DSP_REGNUM_MASK;
+    char src0_str[100], dst_str[100];
+    char src0_name[50], dst_name[50];
+    char src0_mask[6],  dst_mask[6];
+
+    shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_name, dst_mask, dst_str);
+    shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_name, src0_mask, src0_str);
+
+    shader_addline(arg->buffer, "tmp0.y = dot(vec3(T%lu), vec3(%s));\n", dstreg, src0_str);
+    shader_addline(arg->buffer, "gl_FragDepth = vec4((tmp0.y == 0.0) ? 1.0 : tmp0.x / tmp0.y)%s;\n", dst_str, dst_name);
+}
+
+/** Process the D3DSIO_TEXM3X2PAD instruction in GLSL
+ * Calculate the 1st of a 2-row matrix multiplication. */
 void pshader_glsl_texm3x2pad(SHADER_OPCODE_ARG* arg) {
 
     DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
@@ -1363,7 +1462,7 @@ void pshader_glsl_texm3x2pad(SHADER_OPCO
     char src0_mask[6];
 
     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_name, src0_mask, src0_str);
-    shader_addline(buffer, "tmp0.x = dot(vec3(T%lu), vec3(%s));\n", reg, src0_name, src0_str);
+    shader_addline(buffer, "tmp0.x = dot(vec3(T%lu), vec3(%s));\n", reg, src0_str);
 }
 
 /** Process the D3DSIO_TEXM3X3PAD instruction in GLSL
@@ -1429,6 +1528,24 @@ void pshader_glsl_texm3x3tex(SHADER_OPCO
     current_state->current_row = 0;
 }
 
+/** Process the D3DSIO_TEXM3X3 instruction in GLSL
+ * Perform the 3rd row of a 3x3 matrix multiply */
+void pshader_glsl_texm3x3(SHADER_OPCODE_ARG* arg) {
+
+    char src0_str[100];
+    char src0_name[50];
+    char src0_mask[6];
+    DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
+    IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
+    SHADER_PARSE_STATE* current_state = &This->baseShader.parse_state;
+    
+    shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_name, src0_mask, src0_str);
+    
+    shader_addline(arg->buffer, "tmp0.z = dot(vec3(T%lu), vec3(%s));\n", reg, src0_str);
+    shader_addline(arg->buffer, "T%lu = vec4(tmp0.x, tmp0.y, tmp0.z, 1.0);\n", reg);
+    current_state->current_row = 0;
+}
+
 /** Process the D3DSIO_TEXM3X3SPEC instruction in GLSL 
  * Peform the final texture lookup based on the previous 2 3x3 matrix multiplies */
 void pshader_glsl_texm3x3spec(SHADER_OPCODE_ARG* arg) {
diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c
index 7e11c47..2774c4d 100644
--- a/dlls/wined3d/pixelshader.c
+++ b/dlls/wined3d/pixelshader.c
@@ -618,9 +618,6 @@ static void pshader_texldl(WINED3DSHADER
     FIXME(" : Stub\n");
 }
 
-/**
- * log, exp, frc, m*x* seems to be macros ins ... to see
- */
 CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[] = {
 
     /* Arithmethic */
@@ -641,7 +638,7 @@ CONST SHADER_OPCODE IWineD3DPixelShaderI
     {D3DSIO_ABS,  "abs",  "ABS", 1, 2, pshader_abs, pshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
     {D3DSIO_EXP,  "exp",  "EX2", 1, 2, pshader_exp, pshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
     {D3DSIO_LOG,  "log",  "LG2", 1, 2, pshader_log, pshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
-    {D3DSIO_EXPP, "expp", "EXP", 1, 2, pshader_expp, pshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
+    {D3DSIO_EXPP, "expp", "EXP", 1, 2, pshader_expp, pshader_hw_map2gl, shader_glsl_expp, 0, 0},
     {D3DSIO_LOGP, "logp", "LOG", 1, 2, pshader_logp, pshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
     {D3DSIO_DST,  "dst",  "DST", 1, 3, pshader_dst, pshader_hw_map2gl, shader_glsl_dst, 0, 0},
     {D3DSIO_LRP,  "lrp",  "LRP", 1, 4, pshader_lrp, pshader_hw_map2gl, shader_glsl_lrp, 0, 0},
@@ -717,13 +714,12 @@ CONST SHADER_OPCODE IWineD3DPixelShaderI
     {D3DSIO_TEXM3x3SPEC,  "texm3x3spec",  "undefined", 1, 3, pshader_texm3x3spec,  pshader_hw_texm3x3spec, pshader_glsl_texm3x3spec, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
     {D3DSIO_TEXM3x3VSPEC, "texm3x3vspec",  "undefined", 1, 2, pshader_texm3x3vspec, pshader_hw_texm3x3vspec, pshader_glsl_texm3x3vspec, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
     {D3DSIO_TEXM3x3TEX,   "texm3x3tex",   "undefined", 1, 2, pshader_texm3x3tex,   pshader_hw_texm3x3tex, pshader_glsl_texm3x3tex, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
-    {D3DSIO_TEXDP3TEX,    "texdp3tex",    GLNAME_REQUIRE_GLSL, 1, 2, pshader_texdp3tex,   NULL, NULL, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
-    {D3DSIO_TEXM3x2DEPTH, "texm3x2depth", GLNAME_REQUIRE_GLSL, 1, 2, pshader_texm3x2depth, NULL, NULL, D3DPS_VERSION(1,3), D3DPS_VERSION(1,3)},
-    {D3DSIO_TEXDP3,   "texdp3",   GLNAME_REQUIRE_GLSL, 1, 2, pshader_texdp3,   NULL, NULL, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
-    {D3DSIO_TEXM3x3,  "texm3x3",  GLNAME_REQUIRE_GLSL, 1, 2, pshader_texm3x3,  NULL, NULL, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
-    {D3DSIO_TEXDEPTH, "texdepth", GLNAME_REQUIRE_GLSL, 1, 1, pshader_texdepth, NULL, NULL, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
+    {D3DSIO_TEXDP3TEX,    "texdp3tex",    GLNAME_REQUIRE_GLSL, 1, 2, pshader_texdp3tex,   NULL, pshader_glsl_texdp3tex, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
+    {D3DSIO_TEXM3x2DEPTH, "texm3x2depth", GLNAME_REQUIRE_GLSL, 1, 2, pshader_texm3x2depth, NULL, pshader_glsl_texm3x2depth, D3DPS_VERSION(1,3), D3DPS_VERSION(1,3)},
+    {D3DSIO_TEXDP3,   "texdp3",   GLNAME_REQUIRE_GLSL, 1, 2, pshader_texdp3,   NULL, pshader_glsl_texdp3, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
+    {D3DSIO_TEXM3x3,  "texm3x3",  GLNAME_REQUIRE_GLSL, 1, 2, pshader_texm3x3,  NULL, pshader_glsl_texm3x3, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
+    {D3DSIO_TEXDEPTH, "texdepth", GLNAME_REQUIRE_GLSL, 1, 1, pshader_texdepth, NULL, pshader_glsl_texdepth, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
     {D3DSIO_BEM,      "bem",      GLNAME_REQUIRE_GLSL, 1, 3, pshader_bem,      NULL, NULL, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
-    /* TODO: dp2add can be made out of multiple instuctions */
     {D3DSIO_DSX,      "dsx",      GLNAME_REQUIRE_GLSL, 1, 2, pshader_dsx,     NULL, NULL, 0, 0},
     {D3DSIO_DSY,      "dsy",      GLNAME_REQUIRE_GLSL, 1, 2, pshader_dsy,     NULL, NULL, 0, 0},
     {D3DSIO_TEXLDD,   "texldd",   GLNAME_REQUIRE_GLSL, 1, 5, pshader_texldd,  NULL, NULL, D3DPS_VERSION(2,1), -1},
diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c
index 7e29e72..0d4bac6 100644
--- a/dlls/wined3d/vertexshader.c
+++ b/dlls/wined3d/vertexshader.c
@@ -472,9 +472,6 @@ static void vshader_texldl(WINED3DSHADER
     FIXME(" : Stub\n");
 }
 
-/**
- * log, exp, frc, m*x* seems to be macros ins ... to see
- */
 CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = {
 
     /* Arithmetic */ 
@@ -495,7 +492,7 @@ CONST SHADER_OPCODE IWineD3DVertexShader
     {D3DSIO_ABS,  "abs",  "ABS", 1, 2, vshader_abs,  vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
     {D3DSIO_EXP,  "exp",  "EX2", 1, 2, vshader_exp,  vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
     {D3DSIO_LOG,  "log",  "LG2", 1, 2, vshader_log,  vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
-    {D3DSIO_EXPP, "expp", "EXP", 1, 2, vshader_expp, vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
+    {D3DSIO_EXPP, "expp", "EXP", 1, 2, vshader_expp, vshader_hw_map2gl, shader_glsl_expp, 0, 0},
     {D3DSIO_LOGP, "logp", "LOG", 1, 2, vshader_logp, vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
     {D3DSIO_LIT,  "lit",  "LIT", 1, 2, vshader_lit,  vshader_hw_map2gl, shader_glsl_lit, 0, 0},
     {D3DSIO_DST,  "dst",  "DST", 1, 3, vshader_dst,  vshader_hw_map2gl, shader_glsl_dst, 0, 0},
@@ -746,6 +743,9 @@ #endif
 
         /* Base Declarations */
         shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, &buffer, &GLINFO_LOCATION);
+        
+        /* We need the projection matrix to correctly render upside-down objects (render to texture) */
+        shader_addline(&buffer, "PARAM PROJECTION = state.matrix.projection.row[1];\n");
 
         if (reg_maps->fog) {
             This->usesFog = 1;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index f4ae19d..31041a4 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1492,6 +1492,7 @@ extern void shader_glsl_compare(SHADER_O
 extern void shader_glsl_def(SHADER_OPCODE_ARG* arg);
 extern void shader_glsl_defi(SHADER_OPCODE_ARG* arg);
 extern void shader_glsl_defb(SHADER_OPCODE_ARG* arg);
+extern void shader_glsl_expp(SHADER_OPCODE_ARG* arg);
 extern void shader_glsl_cmp(SHADER_OPCODE_ARG* arg);
 extern void shader_glsl_lit(SHADER_OPCODE_ARG* arg);
 extern void shader_glsl_dst(SHADER_OPCODE_ARG* arg);
@@ -1511,8 +1512,13 @@ extern void shader_glsl_label(SHADER_OPC
 /** GLSL Pixel Shader Prototypes */
 extern void pshader_glsl_tex(SHADER_OPCODE_ARG* arg);
 extern void pshader_glsl_texcoord(SHADER_OPCODE_ARG* arg);
+extern void pshader_glsl_texdp3tex(SHADER_OPCODE_ARG* arg);
+extern void pshader_glsl_texdp3(SHADER_OPCODE_ARG* arg);
+extern void pshader_glsl_texdepth(SHADER_OPCODE_ARG* arg);
+extern void pshader_glsl_texm3x2depth(SHADER_OPCODE_ARG* arg);
 extern void pshader_glsl_texm3x2pad(SHADER_OPCODE_ARG* arg);
 extern void pshader_glsl_texm3x2tex(SHADER_OPCODE_ARG* arg);
+extern void pshader_glsl_texm3x3(SHADER_OPCODE_ARG* arg);
 extern void pshader_glsl_texm3x3pad(SHADER_OPCODE_ARG* arg);
 extern void pshader_glsl_texm3x3tex(SHADER_OPCODE_ARG* arg);
 extern void pshader_glsl_texm3x3spec(SHADER_OPCODE_ARG* arg);


More information about the wine-patches mailing list