[WINED3D 4] Fix cmp instruction for GLSL

Ivan Gyurdiev ivg231 at gmail.com
Thu Jul 13 21:31:00 CDT 2006


The current GLSL cmp instruction is incorrect, because:

- it ignores destination write mask
- it ignores source swizzle
- it ignores other source modifiers.
- it works incorrectly for src0 = 0

The attached replacement implementation was unit-tested, and seems 
correct (matches spec examples).
It fixes graphical glitches in the Hair demo, and makes the 
TransparentShadowMapping demo work for the most part (previously black 
screen).

Unfortunately, it causes demos: 3Dc, and PhongLighting, to go completely 
black, and causes glitches in ASCII and SelfShadowBump demos.

However, I much prefer an implementation which is supposed to be 
correct, and makes a few demos work, than one which is known to be 
wrong, and makes more (other) demos work by chance. Note that all uses 
of cmp that I've seen use replicate swizzle and write mask, which means 
that they will not work properly with the old implementation. The 
black-screen regression is caused because the demos do a z-buffer test 
to see if something's in shadow, and apparently everything's in shadow - 
must investigate z-buffers further, and find out why things aren't working.

Note that cmp is a shader model 2 instruction, and most users will not 
be affected (requires GLSL).
-------------- next part --------------
---
 dlls/wined3d/glsl_shader.c |   11 +++++------
 1 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 223a8e0..23f944c 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -987,20 +987,19 @@ void shader_glsl_compare(SHADER_OPCODE_A
 /** Process CMP instruction in GLSL (dst = src0.x > 0.0 ? src1.x : src2.x), per channel */
 void shader_glsl_cmp(SHADER_OPCODE_ARG* arg) {
 
+    char tmpLine[256];
     char dst_str[100], src0_str[100], src1_str[100], src2_str[100];
     char dst_reg[50], src0_reg[50], src1_reg[50], src2_reg[50];
     char dst_mask[6], src0_mask[6], src1_mask[6], src2_mask[6];
-    
+   
     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, src0_reg, src0_mask, src0_str);
     shader_glsl_add_param(arg, arg->src[1], arg->src_addr[1], TRUE, src1_reg, src1_mask, src1_str);
     shader_glsl_add_param(arg, arg->src[2], arg->src_addr[2], TRUE, src2_reg, src2_mask, src2_str);
 
-    /* FIXME: This isn't correct - doesn't take the dst's swizzle into account. */
-    shader_addline(arg->buffer, "%s.x = (%s.x > 0.0) ? %s.x : %s.x;\n", dst_reg, src0_reg, src1_reg, src2_reg);
-    shader_addline(arg->buffer, "%s.y = (%s.y > 0.0) ? %s.y : %s.y;\n", dst_reg, src0_reg, src1_reg, src2_reg);
-    shader_addline(arg->buffer, "%s.z = (%s.z > 0.0) ? %s.z : %s.z;\n", dst_reg, src0_reg, src1_reg, src2_reg);
-    shader_addline(arg->buffer, "%s.w = (%s.w > 0.0) ? %s.w : %s.w;\n", dst_reg, src0_reg, src1_reg, src2_reg);
+    shader_glsl_add_dst(arg->dst, dst_reg, dst_mask, tmpLine);
+    shader_addline(arg->buffer, "%smix(vec4(%s), vec4(%s), vec4(lessThan(vec4(%s), vec4(0.0)))))%s;\n",
+        tmpLine, src1_str, src2_str, src0_str, dst_mask);
 }
 
 /** Process the CND opcode in GLSL (dst = (src0 < 0.5) ? src1 : src2) */
-- 
1.4.0



More information about the wine-patches mailing list