WineD3D: Avoid wasting a shader constant

Stefan Dösinger stefan at codeweavers.com
Tue Aug 29 15:16:05 CDT 2006


My previous half pixel correction patch loaded an extra row from the transform 
matrix into a new constant to access one float value, altough the already 
loaded 2nd row had 2 unused floats. This patch puts the x offset into the z 
value of the 2nd row and loads only that row. This doesn't look nice, but it 
doesn't require an additional shader parameter, so the constant is available 
for use by the game. Of course comments are added to document this :-)
-------------- next part --------------
From b641f2df35aaf7453f557a99d26586d5f07f2cf4 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Stefan_D=F6singer?= <stefan at codeweavers.com>
Date: Tue, 29 Aug 2006 21:46:49 +0200
Subject: [PATCH] WineD3D: Avoid wasting a uniform
---
 dlls/wined3d/drawprim.c     |   28 ++++++++++++++++++++++------
 dlls/wined3d/vertexshader.c |   24 ++++++++++--------------
 2 files changed, 32 insertions(+), 20 deletions(-)

diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index aa022e2..d29d0b8 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -311,20 +311,36 @@ static void primitiveInitState(
 
         /* Vertex Shader output is already transformed, so set up identity matrices */
         if (useVS) {
+            GLfloat myMat[4][4] = { { 1.0, 0.0, 0.0, 0.0 },
+                                    { 0.0, 1.0, 0.0, 0.0 },
+                                    { 0.0, 0.0, 1.0, 0.0 },
+                                    { 0.0, 0.0, 0.0, 1.0 } };
+
             glMatrixMode(GL_MODELVIEW);
             checkGLcall("glMatrixMode");
             glLoadIdentity();
             glMatrixMode(GL_PROJECTION);
             checkGLcall("glMatrixMode");
-            glLoadIdentity();
+            /* No need to load the idendity, we load our own matrix below */
+
             /* Window Coord 0 is the middle of the first pixel, so translate by half
-               a pixel (See comment above glTranslate above)                         */
-            glTranslatef(0.9 / This->stateBlock->viewport.Width, -0.9 / This->stateBlock->viewport.Height, 0);
-            checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
+             * a pixel (See comment above glTranslate above)
+             *
+             * The 2nd row of the matrix is used for the invymat y multiplication, glTranslate
+             * would set the x offset to [0][3] and y to [1][3]. That way a free uniform in the
+             * shader would be lost to load the first row. To avoid this set the offsets manually
+             * in the 2nd row and use them in the shader.
+             *
+             */
+            myMat[1][2] = 0.9 / This->stateBlock->viewport.Width;
+            myMat[1][3] = -0.9 / This->stateBlock->viewport.Height;
+            /* Turn around the y axis for offscreen rendering */
             if (This->renderUpsideDown) {
-                glMultMatrixf(invymat);
-                checkGLcall("glMultMatrixf(invymat)");
+                myMat[1][1] = -1.0;
             }
+            glLoadMatrixf(&myMat[0][0]);
+            checkGLcall("glLoadMatrix");
+
             This->modelview_valid = FALSE;
             This->proj_valid = FALSE;
         }
diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c
index 9719264..cf42d68 100644
--- a/dlls/wined3d/vertexshader.c
+++ b/dlls/wined3d/vertexshader.c
@@ -737,12 +737,11 @@ #endif
         /* Write the final position.
          *
          * OpenGL coordinates specify the center of the pixel while d3d coords specify
-         * the corner. For that reason a translation is done with the projection matrix,
-         * which sets the offsets to move in the w coords of the matrix(see glTranslate manpage)
-         * Add the w coordinates to x and y, this avoids the need for a full matrix
-         * multiplication. The matrix is set up in drawprim.c, primitiveInitState.
+         * the corner. The offsets are stored in z and w in the 2nd row of the projection
+         * matrix to avoid wasting a free shader constant. Add them to the w and z coord
+         * of the 2nd row
          */
-        shader_addline(&buffer, "gl_Position.x = gl_Position.x + gl_ProjectionMatrix[3][0];\n");
+        shader_addline(&buffer, "gl_Position.x = gl_Position.x + gl_ProjectionMatrix[2][1];\n");
         shader_addline(&buffer, "gl_Position.y = gl_Position.y + gl_ProjectionMatrix[3][1];\n");
         /* Account for any inverted textures (render to texture case) by reversing the y coordinate
          *  (this is handled in drawPrim() when it sets the MODELVIEW and PROJECTION matrices)
@@ -773,8 +772,7 @@ #endif
         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 PROJECTIONX = state.matrix.projection.row[0];\n");
-        shader_addline(&buffer, "PARAM PROJECTIONY = state.matrix.projection.row[1];\n");
+        shader_addline(&buffer, "PARAM PROJECTION = state.matrix.projection.row[1];\n");
 
         if (reg_maps->fog) {
             This->usesFog = 1;
@@ -792,17 +790,15 @@ #endif
         /* Write the final position.
          *
          * OpenGL coordinates specify the center of the pixel while d3d coords specify
-         * the corner. For that reason a translation is done with the projection matrix,
-         * which sets the offsets to move in the w coords of the matrix(see glTranslate manpage)
-         * Add the w coordinates to x and y, this avoids the need for a full matrix
-         * multiplication. The matrix is set up in drawprim.c, primitiveInitState.
+         * the corner. The offsets are stored in the 2nd row of the projection matrix,
+         * the x offset in z and the y offset in w. Add them to the resulting position
          */
-        shader_addline(&buffer, "ADD result.position.x, TMP_OUT.x, PROJECTIONX.w;\n");
-        shader_addline(&buffer, "ADD result.position.y, TMP_OUT.y, PROJECTIONY.w;\n");
+        shader_addline(&buffer, "ADD result.position.x, TMP_OUT.x, PROJECTION.z;\n");
+        shader_addline(&buffer, "ADD result.position.y, TMP_OUT.y, PROJECTION.w;\n");
         /* Account for any inverted textures (render to texture case) by reversing the y coordinate
          *  (this is handled in drawPrim() when it sets the MODELVIEW and PROJECTION matrices)
          */
-        shader_addline(&buffer, "MUL result.position.y, TMP_OUT.y, PROJECTIONY.y;\n");
+        shader_addline(&buffer, "MUL result.position.y, TMP_OUT.y, PROJECTION.y;\n");
         
         shader_addline(&buffer, "END\n\0"); 
 
-- 
1.4.1.1



More information about the wine-patches mailing list