WineD3D: Implement bem shader instruction

Stefan Dösinger stefan at codeweavers.com
Sat Mar 24 09:17:20 CDT 2007


-------------- next part --------------
From 8795515311238b15ec9b0a39c27a006da10b713b Mon Sep 17 00:00:00 2001
From: Stefan Doesinger <stefan at codeweavers.com>
Date: Sat, 24 Mar 2007 15:16:07 +0100
Subject: [PATCH] WineD3D: Implement bem shader instruction

---
 dlls/wined3d/arb_program_shader.c |   32 ++++++++++++++++++++++++++++++--
 dlls/wined3d/baseshader.c         |   14 ++++++++++++--
 dlls/wined3d/glsl_shader.c        |   17 +++++++++++++++--
 dlls/wined3d/pixelshader.c        |    2 +-
 dlls/wined3d/wined3d_private.h    |    2 ++
 5 files changed, 60 insertions(+), 7 deletions(-)

diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 1e7f826..b5bea19 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -177,7 +177,7 @@ void shader_generate_arb_declarations(
             shader_addline(buffer, "MOV T%u, fragment.texcoord[%u];\n", i, i);
     }
 
-    if(reg_maps->bumpmat /* Only  a pshader can use texbem */) {
+    if(reg_maps->bumpmat != -1 /* Only a pshader can use texbem */) {
         /* If the shader does not use all available constants, use the next free constant to load the bump mapping environment matrix from
          * the stateblock into the shader. If no constant is available don't load, texbem will then just sample the texture without applying
          * bump mapping.
@@ -510,6 +510,34 @@ static inline void pshader_gen_output_modifier_line(
         regstr, write_mask, regstr, shift_tab[shift]);
 }
 
+void pshader_hw_bem(SHADER_OPCODE_ARG* arg) {
+    IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
+
+    SHADER_BUFFER* buffer = arg->buffer;
+    char dst_name[50];
+    char src_name[2][50];
+    char dst_wmask[20];
+
+    pshader_get_register_name(arg->dst, dst_name);
+    shader_arb_get_write_mask(arg->dst, dst_wmask);
+    strcat(dst_name, dst_wmask);
+
+    pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src_name[0]);
+    pshader_gen_input_modifier_line(buffer, arg->src[1], 1, src_name[1]);
+
+    if(This->bumpenvmatconst != -1) {
+        /* Sampling the perturbation map in Tsrc was done already, including the signedness correction if needed */
+        shader_addline(buffer, "SWZ TMP2, bumpenvmat, x, z, 0, 0;\n");
+        shader_addline(buffer, "DP3 TMP.r, TMP2, %s;\n", src_name[1]);
+        shader_addline(buffer, "SWZ TMP2, bumpenvmat, y, w, 0, 0;\n");
+        shader_addline(buffer, "DP3 TMP.g, TMP2, %s;\n", src_name[1]);
+
+        shader_addline(buffer, "ADD %s, %s, TMP;\n", dst_name, src_name[0]);
+    } else {
+        shader_addline(buffer, "MOV %s, %s;\n", dst_name, src_name[0]);
+    }
+}
+
 void pshader_hw_cnd(SHADER_OPCODE_ARG* arg) {
 
     SHADER_BUFFER* buffer = arg->buffer;
@@ -729,7 +757,7 @@ void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) {
     /* Can directly use the name because texbem is only valid for <= 1.3 shaders */
     pshader_get_register_name(dst, reg_coord);
 
-    if(This->bumpenvmatconst) {
+    if(This->bumpenvmatconst != -1) {
         /* Sampling the perturbation map in Tsrc was done already, including the signedness correction if needed */
 
         shader_addline(buffer, "SWZ TMP2, bumpenvmat, x, z, 0, 0;\n");
diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c
index 3508835..3446570 100644
--- a/dlls/wined3d/baseshader.c
+++ b/dlls/wined3d/baseshader.c
@@ -197,6 +197,8 @@ HRESULT shader_get_registers_used(
     /* There are some minor differences between pixel and vertex shaders */
     char pshader = shader_is_pshader_version(This->baseShader.hex_version);
 
+    reg_maps->bumpmat = -1;
+
     if (pToken == NULL)
         return WINED3D_OK;
 
@@ -295,7 +297,15 @@ HRESULT shader_get_registers_used(
             DWORD snum = *pToken & WINED3DSP_REGNUM_MASK; 
             reg_maps->labels[snum] = 1;
             pToken += curOpcode->num_params;
- 
+
+        } else if(WINED3DSIO_BEM == curOpcode->opcode) {
+            DWORD regnum = *pToken & WINED3DSP_REGNUM_MASK;
+            if(reg_maps->bumpmat != -1 && reg_maps->bumpmat != regnum) {
+                FIXME("Pixel shader uses bem or texbem instruction on more than 1 sampler\n");
+            } else {
+                reg_maps->bumpmat = regnum;
+            }
+
         /* Set texture, address, temporary registers */
         } else {
             int i, limit;
@@ -347,7 +357,7 @@ HRESULT shader_get_registers_used(
 
                 /* texbem is only valid with < 1.4 pixel shaders */
                 if(WINED3DSIO_TEXBEM == curOpcode->opcode) {
-                    if(reg_maps->bumpmat != 0 && reg_maps->bumpmat != sampler_code) {
+                    if(reg_maps->bumpmat != -1 && reg_maps->bumpmat != sampler_code) {
                         FIXME("Pixel shader uses texbem instruction on more than 1 sampler\n");
                     } else {
                         reg_maps->bumpmat = sampler_code;
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 598f589..8af9e82 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -355,7 +355,7 @@ void shader_glsl_load_constants(
         /* Upload the environment bump map matrix if needed. The needsbumpmat member specifies the texture stage to load the matrix from.
          * It can't be 0 for a valid texbem instruction.
          */
-        if(((IWineD3DPixelShaderImpl *) pshader)->needsbumpmat != 0) {
+        if(((IWineD3DPixelShaderImpl *) pshader)->needsbumpmat != -1) {
             float *data = (float *) &stateBlock->textureState[(int) ((IWineD3DPixelShaderImpl *) pshader)->needsbumpmat][WINED3DTSS_BUMPENVMAT00];
             pos = GL_EXTCALL(glGetUniformLocationARB(programId, "bumpenvmat"));
             checkGLcall("glGetUniformLocationARB");
@@ -400,7 +400,7 @@ void shader_generate_glsl_declarations(
 
     if(!pshader)
         shader_addline(buffer, "uniform vec4 posFixup;\n");
-    else if(reg_maps->bumpmat)
+    else if(reg_maps->bumpmat != -1)
         shader_addline(buffer, "uniform mat2 bumpenvmat;\n");
 
     /* Declare texture samplers */ 
@@ -1824,6 +1824,19 @@ void pshader_glsl_texbem(SHADER_OPCODE_ARG* arg) {
                    sample_function.name, sampler_idx, sampler_idx, coord_mask, coord_param.param_str, coord_mask, dst_swizzle);
 }
 
+void pshader_glsl_bem(SHADER_OPCODE_ARG* arg) {
+    char dst_mask[6];
+    glsl_src_param_t src0_param, src1_param;
+
+    shader_glsl_get_write_mask(arg->dst, dst_mask);
+    shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_ALL, &src0_param);
+    shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], WINED3DSP_WRITEMASK_0|WINED3DSP_WRITEMASK_1, &src1_param);
+
+    shader_glsl_append_dst(arg->buffer, arg);
+    shader_addline(arg->buffer, "(%s + vec4(bumpenvmat * %s.rg, 0.0, 0.0))%s);\n",
+                   src0_param.reg_name, src1_param.reg_name, dst_mask);
+}
+
 /** Process the WINED3DSIO_TEXREG2AR instruction in GLSL
  * Sample 2D texture at dst using the alpha & red (wx) components of src as texture coordinates */
 void pshader_glsl_texreg2ar(SHADER_OPCODE_ARG* arg) {
diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c
index b74734d..962b3d5 100644
--- a/dlls/wined3d/pixelshader.c
+++ b/dlls/wined3d/pixelshader.c
@@ -239,7 +239,7 @@ CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[] = {
     {WINED3DSIO_TEXDP3,   "texdp3",   GLNAME_REQUIRE_GLSL, 1, 2, NULL, pshader_glsl_texdp3, WINED3DPS_VERSION(1,2), WINED3DPS_VERSION(1,3)},
     {WINED3DSIO_TEXM3x3,  "texm3x3",  GLNAME_REQUIRE_GLSL, 1, 2, NULL, pshader_glsl_texm3x3, WINED3DPS_VERSION(1,2), WINED3DPS_VERSION(1,3)},
     {WINED3DSIO_TEXDEPTH, "texdepth", GLNAME_REQUIRE_GLSL, 1, 1, NULL, pshader_glsl_texdepth, WINED3DPS_VERSION(1,4), WINED3DPS_VERSION(1,4)},
-    {WINED3DSIO_BEM,      "bem",      GLNAME_REQUIRE_GLSL, 1, 3, NULL, NULL, WINED3DPS_VERSION(1,4), WINED3DPS_VERSION(1,4)},
+    {WINED3DSIO_BEM,      "bem",      "undefined",         1, 3, pshader_hw_bem, pshader_glsl_bem, WINED3DPS_VERSION(1,4), WINED3DPS_VERSION(1,4)},
     {WINED3DSIO_DSX,      "dsx",      GLNAME_REQUIRE_GLSL, 1, 2, NULL, NULL, 0, 0},
     {WINED3DSIO_DSY,      "dsy",      GLNAME_REQUIRE_GLSL, 1, 2, NULL, NULL, 0, 0},
     {WINED3DSIO_TEXLDD,   "texldd",   GLNAME_REQUIRE_GLSL, 1, 5, NULL, NULL, WINED3DPS_VERSION(2,1), -1},
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 5de125b..123afab 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1626,6 +1626,7 @@ extern void shader_arb_load_constants(
 extern void shader_hw_def(SHADER_OPCODE_ARG *arg);
 
 /* ARB pixel shader prototypes */
+extern void pshader_hw_bem(SHADER_OPCODE_ARG* arg);
 extern void pshader_hw_cnd(SHADER_OPCODE_ARG* arg);
 extern void pshader_hw_cmp(SHADER_OPCODE_ARG* arg);
 extern void pshader_hw_map2gl(SHADER_OPCODE_ARG* arg);
@@ -1701,6 +1702,7 @@ extern void pshader_glsl_texm3x3spec(SHADER_OPCODE_ARG* arg);
 extern void pshader_glsl_texm3x3vspec(SHADER_OPCODE_ARG* arg);
 extern void pshader_glsl_texkill(SHADER_OPCODE_ARG* arg);
 extern void pshader_glsl_texbem(SHADER_OPCODE_ARG* arg);
+extern void pshader_glsl_bem(SHADER_OPCODE_ARG* arg);
 extern void pshader_glsl_texreg2ar(SHADER_OPCODE_ARG* arg);
 extern void pshader_glsl_texreg2gb(SHADER_OPCODE_ARG* arg);
 extern void pshader_glsl_texreg2rgb(SHADER_OPCODE_ARG* arg);
-- 
1.4.4.3



More information about the wine-patches mailing list