Stefan Dösinger : wined3d: Load one bump mapping environment matrix into pixel shaders if needed.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Feb 15 05:27:57 CST 2007


Module: wine
Branch: master
Commit: 49a49fcfec199ce6e972ee339fa28fbbe4643435
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=49a49fcfec199ce6e972ee339fa28fbbe4643435

Author: Stefan Dösinger <stefan at codeweavers.com>
Date:   Thu Feb 15 03:05:17 2007 +0100

wined3d: Load one bump mapping environment matrix into pixel shaders if needed.

---

 dlls/wined3d/baseshader.c      |    9 +++++++++
 dlls/wined3d/directx.c         |    9 ++++++++-
 dlls/wined3d/glsl_shader.c     |   18 ++++++++++++++++--
 dlls/wined3d/pixelshader.c     |    2 ++
 dlls/wined3d/state.c           |   12 ++++++++++++
 dlls/wined3d/wined3d_private.h |    5 +++++
 6 files changed, 52 insertions(+), 3 deletions(-)

diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c
index f13d448..3bbdb45 100644
--- a/dlls/wined3d/baseshader.c
+++ b/dlls/wined3d/baseshader.c
@@ -344,6 +344,15 @@ HRESULT shader_get_registers_used(
                             reg_maps->samplers[sampler_code] = (0x1 << 31) | WINED3DSTT_2D;
                     }
                 }
+
+                /* texbem is only valid with < 1.4 pixel shaders */
+                if(WINED3DSIO_TEXBEM == curOpcode->opcode) {
+                    if(reg_maps->bumpmat != 0 && reg_maps->bumpmat != sampler_code) {
+                        FIXME("Pixel shader uses texbem instruction on more than 1 sampler\n");
+                    } else {
+                        reg_maps->bumpmat = sampler_code;
+                    }
+                }
             }
 
             /* This will loop over all the registers and try to
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 7e2fc05..398aca0 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -284,10 +284,17 @@ void select_shader_max_constants(
 
     switch (ps_selected_mode) {
         case SHADER_GLSL:
-            /* Subtract the other potential uniforms from the max available (bools & ints) */
+            /* Subtract the other potential uniforms from the max available (bools & ints).
+             * In theory the texbem instruction may need one more shader constant too. But lets assume
+             * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
+             * and lets not take away a uniform needlessly from all other shaders.
+             */
             gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - MAX_CONST_B - MAX_CONST_I;
             break;
         case SHADER_ARB:
+            /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
+             * a free constant to do that, so no need to reduce the number of available constants.
+             */
             gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF;
             break;
         case SHADER_SW:
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 9722312..566442b 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -283,7 +283,8 @@ void shader_glsl_load_constants(
     GLhandleARB *constant_locations;
     struct list *constant_list;
     GLhandleARB programId;
-    
+    GLint pos;
+
     if (!stateBlock->glsl_program) {
         /* No GLSL program set - nothing to do. */
         return;
@@ -336,11 +337,22 @@ void shader_glsl_load_constants(
         shader_glsl_load_constantsI(pshader, gl_info, programId, MAX_CONST_I,
                                     stateBlock->pixelShaderConstantI, 
                                     stateBlock->set.pixelShaderConstantsI);
-        
+
         /* Load DirectX 9 boolean constants/uniforms for pixel shader */
         shader_glsl_load_constantsB(pshader, gl_info, programId, MAX_CONST_B,
                                     stateBlock->pixelShaderConstantB, 
                                     stateBlock->set.pixelShaderConstantsB);
+
+        /* 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) {
+            float *data = (float *) &stateBlock->textureState[(int) ((IWineD3DPixelShaderImpl *) pshader)->needsbumpmat][WINED3DTSS_BUMPENVMAT00];
+            pos = GL_EXTCALL(glGetUniformLocationARB(programId, "bumpenvmat"));
+            checkGLcall("glGetUniformLocationARB");
+            GL_EXTCALL(glUniform4fvARB(pos, 1, data));
+            checkGLcall("glUniform4fvARB");
+        }
     }
 }
 
@@ -379,6 +391,8 @@ void shader_generate_glsl_declarations(
 
     if(!pshader)
         shader_addline(buffer, "uniform vec4 posFixup;\n");
+    else if(reg_maps->bumpmat)
+        shader_addline(buffer, "uniform vec4 bumpenvmat;\n");
 
     /* Declare texture samplers */ 
     for (i = 0; i < This->baseShader.limits.sampler; i++) {
diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c
index 8958ee0..e83cab1 100644
--- a/dlls/wined3d/pixelshader.c
+++ b/dlls/wined3d/pixelshader.c
@@ -914,6 +914,8 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateShader(
         }
     }
 
+    This->needsbumpmat = reg_maps->bumpmat;
+
 #if 1 /* if were using the data buffer of device then we don't need to free it */
   HeapFree(GetProcessHeap(), 0, buffer.buffer);
 #endif
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index 769f0d1..438f6f0 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -1951,6 +1951,18 @@ static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D
 }
 
 static void tex_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
+    DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
+
+    if(stateblock->pixelShader && stage != 0 &&
+       ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->needsbumpmat == stage) {
+        /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
+         * anyway
+         */
+        if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
+           !isStateDirty(context, STATE_PIXELSHADER)) {
+            shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
+        }
+    }
 }
 
 static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 6111f53..20c9072 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1468,6 +1468,7 @@ typedef struct shader_reg_maps {
     /* Sampler usage tokens 
      * Use 0 as default (bit 31 is always 1 on a valid token) */
     DWORD samplers[MAX_SAMPLERS];
+    char bumpmat;
 
     /* Whether or not a loop is used in this shader */
     char loop;
@@ -1834,6 +1835,10 @@ typedef struct IWineD3DPixelShaderImpl {
     /* run time data */
     PSHADERDATA                *data;
 
+    /* Some information about the shader behavior */
+    char                        needsbumpmat;
+    UINT                        bumpenvmatconst;
+
 #if 0 /* needs reworking */
     PSHADERINPUTDATA input;
     PSHADEROUTPUTDATA output;




More information about the wine-cvs mailing list