[D3D8 Patch] vertex shader integration + fixes - VS3

Raphaël Junqueira fenix at club-internet.fr
Wed Dec 18 18:38:47 CST 2002


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi again,
 this patch enable pixel shader rendering into D3D8 (and correct some stupid bugs i have)

Changelog:
 - intergration with DrawPrimitive
 - remove non-esthetic c++ comments into c comments block ;)
 - more more debug

Problems:
 - very slow
 - i have problem with textures, if people can look at code ...

TODO:
 - better integrate vertex shader with draw primitive (maybe we have to splt DrawPrimitive)
 - optimize software emulation
 - hardware vertex shader program support (using auto-detect caps)
 - syntax validity of vertex shader declaration and vexter shader function code (Validate*Shader functions)
 - vertex shader compilator (in D3DX8)
 - pixel shaders

can people test this, using simple shaders programs please ?


thx, Raphael
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (GNU/Linux)

iD8DBQE+ARUYp7NA3AmQTU4RAn+QAJ0V2R3CugfcYJlygJUMAOhJXj68bQCfQxfH
txo29ZkJSbuudmaxhYGUJSw=
=Hw4m
-----END PGP SIGNATURE-----
-------------- next part --------------
? tmp.diff
Index: d3d8_private.h
===================================================================
RCS file: /home/wine/wine/dlls/d3d8/d3d8_private.h,v
retrieving revision 1.8
diff -u -r1.8 d3d8_private.h
--- d3d8_private.h	18 Dec 2002 05:05:41 -0000	1.8
+++ d3d8_private.h	19 Dec 2002 00:28:25 -0000
@@ -198,6 +198,25 @@
   SHADER8Data* data;
 } PIXELSHADER8;
 
+/** temporary here waiting for buffer code */
+typedef struct vshader_input_data {
+  /*SHADER8Vector V[16];//0-15*/
+  SHADER8Vector V[16];
+} vshader_input_data;
+
+/** temporary here waiting for buffer code */
+typedef struct vshader_output_data {
+  SHADER8Vector oPos;
+  /*SHADER8Vector oD[2];//0-1*/
+  SHADER8Vector oD[2];
+  /*SHADER8Vector oT[4];//0-3*/
+  SHADER8Vector oT[4];
+  /*SHADER8Scalar oFog;*/
+  /*SHADER8Scalar oPts;*/
+  SHADER8Vector oFog;
+  SHADER8Vector oPts;
+} vshader_output_data;
+
 /*
  * External prototypes
  */
@@ -912,6 +931,6 @@
  */
 DWORD vshader_decl_parse(VERTEXSHADER8* vshader);
 DWORD vshader_program_parse(VERTEXSHADER8* vshader);
-
+BOOL  vshader_program_execute_SW(VERTEXSHADER8* vshader, vshader_input_data* input, vshader_output_data* output);
 
 #endif /* __WINE_D3DX8_PRIVATE_H */
Index: device.c
===================================================================
RCS file: /home/wine/wine/dlls/d3d8/device.c,v
retrieving revision 1.16
diff -u -r1.16 device.c
--- device.c	18 Dec 2002 05:05:41 -0000	1.16
+++ device.c	19 Dec 2002 00:28:40 -0000
@@ -53,6 +53,11 @@
     memcpy(gl_mat, (mat), 16 * sizeof(float));      \
 };
 
+#define VERTEX_SHADER(Handle) \
+  ((Handle <= VS_HIGHESTFIXEDFXF) ? ((Handle >= sizeof(VertexShaders) / sizeof(VERTEXSHADER8*)) ? NULL : VertexShaders[Handle]) : VertexShaders[Handle - VS_HIGHESTFIXEDFXF])
+
+#define TRACE_VECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w);
+
 /*
  * Globals
  */
@@ -68,6 +73,7 @@
     0.0, 0.0, 0.0, 1.0
 };
 
+
 /* Routine common to the draw primitive and draw indexed primitive routines
    Doesnt use gl pointer arrays as I dont believe we can support the blending
    coordinates that way.                                                      */
@@ -89,17 +95,38 @@
 
     int vx_index;
     int NumVertexes = NumPrimitives;
+    VERTEXSHADER8* vertex_shader = NULL;
+    vshader_input_data vertex_shader_input;
 
     ICOM_THIS(IDirect3DDevice8Impl,iface);
 
     /* Dont understand how to handle multiple streams, but if a fixed
        FVF is passed in rather than a handle, it must use stream 0 */
-
+    
+    /*
     if (This->StateBlock.VertexShader > VS_HIGHESTFIXEDFXF) {
         FIXME("Cant handle created shaders yet\n");
         return;
-    } else {
+    } else
+    */
+
 
+    if (This->StateBlock.VertexShader > VS_HIGHESTFIXEDFXF) {
+      vertex_shader = VERTEX_SHADER(This->StateBlock.VertexShader);
+      if (NULL == vertex_shader) {
+	ERR("trying to use unitialised vertex shader: %lu\n", This->StateBlock.VertexShader);
+	return;
+      }
+      if (NULL == vertex_shader->function) {
+	TRACE("vertex shader declared without program, using FVF pure mode\n");
+      }
+      fvf = (D3DFORMAT) vertex_shader->fvf;
+      TRACE("vertex shader declared FVF: %x\n", vertex_shader->fvf);
+      memset(&vertex_shader_input, 0, sizeof(vshader_input_data));
+    }
+
+
+    {
         int                         skip = This->StateBlock.stream_stride[0];
 
         BOOL                        normal;
@@ -136,7 +163,7 @@
         isPtSize      = fvf & D3DFVF_PSIZE;
         isDiffuse     = fvf & D3DFVF_DIFFUSE;
         isSpecular    = fvf & D3DFVF_SPECULAR;
-        numTextures =  (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
+        numTextures   = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
 
         TRACE("Drawing with FVF = %x, (n?%d, rhw?%d, ptSize(%d), diffuse?%d, specular?%d, numTextures=%d)\n",
               fvf, normal, isRHW, isPtSize, isDiffuse, isSpecular, numTextures);
@@ -155,10 +182,10 @@
             double height, width, minZ, maxZ;
 
             /*
-	         * Already transformed vertex do not need transform
-	         * matrices. Reset all matrices to identity.
-	         * Leave the default matrix in world mode.
-	        */
+	     * Already transformed vertex do not need transform
+	     * matrices. Reset all matrices to identity.
+	     * Leave the default matrix in world mode.
+	     */
             glMatrixMode(GL_PROJECTION);
             checkGLcall("glMatrixMode");
             glLoadIdentity();
@@ -259,11 +286,22 @@
             curPos = curPos + sizeof(float);
             TRACE("x,y,z=%f,%f,%f\n", x,y,z);
 
+	    if (NULL != vertex_shader && NULL != vertex_shader->function) {
+	      vertex_shader_input.V[D3DVSDE_POSITION].x = x;
+	      vertex_shader_input.V[D3DVSDE_POSITION].y = y;
+	      vertex_shader_input.V[D3DVSDE_POSITION].z = z;
+	      vertex_shader_input.V[D3DVSDE_POSITION].w = 1.0f;
+	    }
+
             /* RHW follows, only if transformed */
             if (isRHW) {
                 rhw = *(float *)curPos;
                 curPos = curPos + sizeof(float);
                 TRACE("rhw=%f\n", rhw);
+
+		if (NULL != vertex_shader && NULL != vertex_shader->function) {
+		  vertex_shader_input.V[D3DVSDE_POSITION].w = rhw;
+		}
             }
 
 
@@ -278,71 +316,173 @@
                 nz = *(float *)curPos;
                 curPos = curPos + sizeof(float);
                 TRACE("nx,ny,nz=%f,%f,%f\n", nx,ny,nz);
-            }
+            
+		if (NULL != vertex_shader && NULL != vertex_shader->function) {
+		  vertex_shader_input.V[D3DVSDE_NORMAL].x = nx;
+		  vertex_shader_input.V[D3DVSDE_NORMAL].y = ny;
+		  vertex_shader_input.V[D3DVSDE_NORMAL].z = nz;
+		  vertex_shader_input.V[D3DVSDE_NORMAL].w = 1.0f;
+		}		
+	    }
 
             if (isPtSize) {
                 ptSize = *(float *)curPos;
                 curPos = curPos + sizeof(float);
                 TRACE("ptSize=%f\n", ptSize);
+
+		if (NULL != vertex_shader && NULL != vertex_shader->function) {
+		  vertex_shader_input.V[D3DVSDE_PSIZE].x = ptSize;
+		  vertex_shader_input.V[D3DVSDE_PSIZE].y = 0.0f;
+		  vertex_shader_input.V[D3DVSDE_PSIZE].z = 0.0f;
+		  vertex_shader_input.V[D3DVSDE_PSIZE].w = 1.0f;
+		}
             }
             if (isDiffuse) {
                 diffuseColor = *(DWORD *)curPos;
                 TRACE("diffuseColor=%lx\n", diffuseColor);
                 curPos = curPos + sizeof(DWORD);
+
+		if (NULL != vertex_shader && NULL != vertex_shader->function) {
+		  vertex_shader_input.V[D3DVSDE_DIFFUSE].x = (float) (((diffuseColor >> 16) & 0xFF) / 255.0f);
+		  vertex_shader_input.V[D3DVSDE_DIFFUSE].y = (float) (((diffuseColor >>  8) & 0xFF) / 255.0f);
+		  vertex_shader_input.V[D3DVSDE_DIFFUSE].z = (float) (((diffuseColor >>  0) & 0xFF) / 255.0f);
+		  vertex_shader_input.V[D3DVSDE_DIFFUSE].w = (float) (((diffuseColor >> 24) & 0xFF) / 255.0f);
+		}
             }
             if (isSpecular) {
                 specularColor = *(DWORD *)curPos;
                 TRACE("specularColor=%lx\n", specularColor);
                 curPos = curPos + sizeof(DWORD);
+
+		if (NULL != vertex_shader && NULL != vertex_shader->function) {
+		  vertex_shader_input.V[D3DVSDE_SPECULAR].x = (float) (((specularColor >> 16) & 0xFF) / 255.0f);
+		  vertex_shader_input.V[D3DVSDE_SPECULAR].y = (float) (((specularColor >>  8) & 0xFF) / 255.0f);
+		  vertex_shader_input.V[D3DVSDE_SPECULAR].z = (float) (((specularColor >>  0) & 0xFF) / 255.0f);
+		  vertex_shader_input.V[D3DVSDE_SPECULAR].w = (float) (((specularColor >> 24) & 0xFF) / 255.0f);
+		}
             }
 
             /* ToDo: Texture coords */
-            for (textureNo = 0;textureNo<numTextures; textureNo++) {
+            for (textureNo = 0; textureNo < numTextures; ++textureNo) {
 
                 float s,t,r,q;
 
                 /* Query tex coords */
                 if (This->StateBlock.textures[textureNo] != NULL) {
-                    switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->StateBlock.textures[textureNo])) {
-                    case D3DRTYPE_TEXTURE:
-                        s = *(float *)curPos;
-                        curPos = curPos + sizeof(float);
-                        t = *(float *)curPos;
-                        curPos = curPos + sizeof(float);
-                        TRACE("tex:%d, s,t=%f,%f\n", textureNo, s,t);
-                        glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
-                        break;
-
-                    case D3DRTYPE_VOLUMETEXTURE:
-                        s = *(float *)curPos;
-                        curPos = curPos + sizeof(float);
-                        t = *(float *)curPos;
-                        curPos = curPos + sizeof(float);
-                        r = *(float *)curPos;
-                        curPos = curPos + sizeof(float);
-                        TRACE("tex:%d, s,t,r=%f,%f,%f\n", textureNo, s,t,r);
-                        glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r);
-                        break;
-
-                    default:
-                        r=0;q=0; /* Avoid compiler warnings, need these vars later for other textures */
-                        FIXME("Unhandled texture type\n");
-                    }
+		  switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->StateBlock.textures[textureNo])) {
+		  case D3DRTYPE_TEXTURE:
+		    s = *(float *)curPos;
+		    curPos = curPos + sizeof(float);
+		    t = *(float *)curPos;
+		    curPos = curPos + sizeof(float);
+		    TRACE("tex:%d, s,t=%f,%f\n", textureNo, s,t);
+
+		    if (NULL != vertex_shader && NULL != vertex_shader->function) {
+		      vertex_shader_input.V[D3DVSDE_TEXCOORD0 + textureNo].x = s;
+		      vertex_shader_input.V[D3DVSDE_TEXCOORD0 + textureNo].y = t;
+		      vertex_shader_input.V[D3DVSDE_TEXCOORD0 + textureNo].z = 0.0f;
+		      vertex_shader_input.V[D3DVSDE_TEXCOORD0 + textureNo].w = 1.0f;
+		    } else {
+		      glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
+		    }
+		    break;
+		    
+		  case D3DRTYPE_VOLUMETEXTURE:
+		    s = *(float *)curPos;
+		    curPos = curPos + sizeof(float);
+		    t = *(float *)curPos;
+		    curPos = curPos + sizeof(float);
+		    r = *(float *)curPos;
+		    curPos = curPos + sizeof(float);
+		    TRACE("tex:%d, s,t,r=%f,%f,%f\n", textureNo, s,t,r);
+		    
+		    if (NULL != vertex_shader && NULL != vertex_shader->function) {
+		      vertex_shader_input.V[D3DVSDE_TEXCOORD0 + textureNo].x = s;
+		      vertex_shader_input.V[D3DVSDE_TEXCOORD0 + textureNo].y = t;
+		      vertex_shader_input.V[D3DVSDE_TEXCOORD0 + textureNo].z = r;
+		      vertex_shader_input.V[D3DVSDE_TEXCOORD0 + textureNo].w = 1.0f;
+		    } else {
+		      glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r);
+		    }
+		    break;
+		    
+		  default:
+		    r = 0.0f; q = 0.0f; /* Avoid compiler warnings, need these vars later for other textures */
+		    FIXME("Unhandled texture type\n");
+		  }
                 } else {
-                    /* Note I have seen a program actually do this, so just hide it and continue */
-                    TRACE("Very odd - texture requested in FVF but not bound!\n");
+		  /* Note I have seen a program actually do this, so just hide it and continue */
+		  TRACE("Very odd - texture requested in FVF but not bound!\n");
                 }
 
             }
 
+	    /** if vertex shader specified ... using it */
+	    if (NULL != vertex_shader && NULL != vertex_shader->function) {
+	      vshader_output_data vs_o;
+	      memset(&vs_o, 0, sizeof(vshader_output_data));
+	      vshader_program_execute_SW(vertex_shader, &vertex_shader_input, &vs_o);
+	      
+	      x = vs_o.oPos.x;
+	      y = vs_o.oPos.y;
+	      z = vs_o.oPos.z;
+	      
+	      if (isRHW) {
+		rhw = vs_o.oPos.w;
+	      }
+	      TRACE_VECTOR(vs_o.oPos);
+	      if (isDiffuse) {
+		diffuseColor = D3DCOLOR_COLORVALUE(vs_o.oD[0].x, vs_o.oD[0].y, vs_o.oD[0].z, vs_o.oD[0].w);
+		TRACE_VECTOR(vs_o.oD[0]);
+	      }
+	      if (isSpecular) {
+		specularColor = D3DCOLOR_COLORVALUE(vs_o.oD[1].x, vs_o.oD[1].y, vs_o.oD[1].z, vs_o.oD[1].w);
+		TRACE_VECTOR(vs_o.oD[1]);
+	      }
+	      
+	      /** TODO: reupdate textures coords binding using vs_o.oT[0->3] */  
+	      for (textureNo = 0; textureNo < min(numTextures, 4); ++textureNo) {
+		float s, t, r, q;
+                /* Query tex coords */
+                if (This->StateBlock.textures[textureNo] != NULL) {
+		  switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->StateBlock.textures[textureNo])) {
+		  case D3DRTYPE_TEXTURE:
+		    TRACE_VECTOR(vs_o.oT[textureNo]);
+		    s = vs_o.oT[textureNo].x;
+		    t = vs_o.oT[textureNo].y;
+		    TRACE("tex:%d, s,t=%f,%f\n", textureNo, s,t);
+		    glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
+		    break;
+		    
+		  case D3DRTYPE_VOLUMETEXTURE:
+		    TRACE_VECTOR(vs_o.oT[textureNo]);
+		    s = vs_o.oT[textureNo].x;
+		    t = vs_o.oT[textureNo].y;
+		    r = vs_o.oT[textureNo].z;
+		    TRACE("tex:%d, s,t,r=%f,%f,%f\n", textureNo, s,t,r);
+		    glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r);		   
+		    break;
+		    
+		  default:
+		    /* Avoid compiler warnings, need these vars later for other textures */
+		    r = 0.0f; q = 0.0f; 
+		    FIXME("Unhandled texture type\n");
+		  }
+		}
+	      }
+	    }
+	      
             /* Handle these vertexes */
             if (isDiffuse) {
                 glColor4f(((diffuseColor >> 16) & 0xFF) / 255.0,
                           ((diffuseColor >>  8) & 0xFF) / 255.0,
                           ((diffuseColor >>  0) & 0xFF) / 255.0,
                           ((diffuseColor >> 24) & 0xFF) / 255.0);
-                TRACE("glColor4f: r,g,b,a=%f,%f,%f,%f\n", ((diffuseColor >> 16) & 0xFF) / 255.0, ((diffuseColor >>  8) & 0xFF) / 255.0,
-                       ((diffuseColor >>  0) & 0xFF) / 255.0, ((diffuseColor >> 24) & 0xFF) / 255.0);
+                TRACE("glColor4f: r,g,b,a=%f,%f,%f,%f\n", 
+		      ((diffuseColor >> 16) & 0xFF) / 255.0, 
+		      ((diffuseColor >>  8) & 0xFF) / 255.0,
+		      ((diffuseColor >>  0) & 0xFF) / 255.0, 
+		      ((diffuseColor >> 24) & 0xFF) / 255.0);
             }
 
             if (normal) {
@@ -3152,19 +3292,14 @@
     object->decl = pDeclaration;
     object->function = pFunction;
 
-    /*
-    for (i = 0; 0xFFFFFFFF != pDeclaration[i]; ++i) ;
-    object->declLength = i + 1;
-    if (NULL != pFunction) {
-      for (i = 0; 0xFFFFFFFF != pFunction[i]; ++i) ;
-      object->functionLength = i + 1;
-    } else {
-      object->functionLength = 1; // no Function defined use fixed function vertex processing
-    }
-    */
     vshader_decl_parse(object);
     vshader_program_parse(object);
 
+    /* copy the function ... because it will certainly be released by application */
+    if (NULL != pFunction) {
+      object->function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->functionLength);
+      memcpy(object->function, pFunction, object->functionLength);
+    }
     return D3D_OK;
 }
 HRESULT  WINAPI  IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
@@ -3212,8 +3347,6 @@
     VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
     return D3D_OK;
 }
-
-#define VERTEX_SHADER(Handle) ((Handle <= VS_HIGHESTFIXEDFXF) ? ((Handle >= sizeof(VertexShaders) / sizeof(VERTEXSHADER8*)) ? NULL : VertexShaders[Handle]) : VertexShaders[Handle - VS_HIGHESTFIXEDFXF])
 
 HRESULT  WINAPI  IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
   ICOM_THIS(IDirect3DDevice8Impl,iface);
Index: directx.c
===================================================================
RCS file: /home/wine/wine/dlls/d3d8/directx.c,v
retrieving revision 1.8
diff -u -r1.8 directx.c
--- directx.c	18 Dec 2002 05:05:41 -0000	1.8
+++ directx.c	19 Dec 2002 00:28:42 -0000
@@ -584,11 +584,13 @@
 
     LEAVE_GL();
 
-    {
+
+    { /* Print some caps infos */
         GLint gl_max_texture_units_arb;
         glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max_texture_units_arb);
         TRACE("GLCaps: GL_MAX_TEXTURE_UNITS_ARB=%d\n", gl_max_texture_units_arb);
     }
+
 
     { /* Set a default viewport */
        D3DVIEWPORT8 vp;
Index: shader.c
===================================================================
RCS file: /home/wine/wine/dlls/d3d8/shader.c,v
retrieving revision 1.2
diff -u -r1.2 shader.c
--- shader.c	18 Dec 2002 05:05:41 -0000	1.2
+++ shader.c	19 Dec 2002 00:28:45 -0000
@@ -63,22 +63,39 @@
   */
 } shader_opcode;
 
-typedef struct vshader_input_data {
-  /*SHADER8Vector V[16];//0-15*/
-  SHADER8Vector V[16];
-} vshader_input_data;
-
-typedef struct vshader_output_data {
-  SHADER8Vector oPos;
-  /*SHADER8Vector oD[2];//0-1*/
-  SHADER8Vector oD[2];
-  /*SHADER8Vector oT[4];//0-3*/
-  SHADER8Vector oT[4];
-  /*SHADER8Scalar oFog;*/
-  /*SHADER8Scalar oPts;*/
-  SHADER8Vector oFog;
-  SHADER8Vector oPts;
-} vshader_output_data;
+/** Vertex Shader Declaration data types tokens */
+static CONST char* VertexShaderDeclDataTypes [] = {
+  "D3DVSDT_FLOAT1",
+  "D3DVSDT_FLOAT2",
+  "D3DVSDT_FLOAT3",
+  "D3DVSDT_FLOAT4",
+  "D3DVSDT_D3DCOLOR",
+  "D3DVSDT_UBYTE4",
+  "D3DVSDT_SHORT2",
+  "D3DVSDT_SHORT4",
+  NULL
+};
+
+static CONST char* VertexShaderDeclRegister [] = {
+  "D3DVSDE_POSITION",
+  "D3DVSDE_BLENDWEIGHT",
+  "D3DVSDE_BLENDINDICES",
+  "D3DVSDE_NORMAL",
+  "D3DVSDE_PSIZE",
+  "D3DVSDE_DIFFUSE",
+  "D3DVSDE_SPECULAR",
+  "D3DVSDE_TEXCOORD0",
+  "D3DVSDE_TEXCOORD1",
+  "D3DVSDE_TEXCOORD2",
+  "D3DVSDE_TEXCOORD3",
+  "D3DVSDE_TEXCOORD4",
+  "D3DVSDE_TEXCOORD5",
+  "D3DVSDE_TEXCOORD6",
+  "D3DVSDE_TEXCOORD7",
+  "D3DVSDE_POSITION2",
+  "D3DVSDE_NORMAL2",
+  NULL
+};
 
 /*******************************
  * vshader functions software VM
@@ -97,6 +114,11 @@
 
 void vshader_dp4(SHADER8Vector* d, SHADER8Vector* s0, SHADER8Vector* s1) {
   d->x = d->y = d->z = d->w = s0->x * s1->x + s0->y * s1->y + s0->z * s1->z + s0->w * s1->w;
+
+  /*
+  DPRINTF("executing dp4: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
+	  s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w);
+  */
 }
 
 void vshader_dst(SHADER8Vector* d, SHADER8Vector* s0, SHADER8Vector* s1) {
@@ -104,6 +126,11 @@
   d->y = s0->y * s1->y;
   d->z = s0->z;
   d->w = s1->w;
+
+  /*
+  DPRINTF("executing dst: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
+	  s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w);
+  */
 }
 
 void vshader_expp(SHADER8Vector* d, SHADER8Vector* s0) {
@@ -112,6 +139,11 @@
   d->y = s0->w - tmp_f;
   d->z = pow(2, s0->w);
   d->w = 1;
+
+  /*
+  DPRINTF("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
+          s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w);
+  */
 }
 
 void vshader_lit(SHADER8Vector* d, SHADER8Vector* s0) {
@@ -119,6 +151,11 @@
   d->y = (0 < s0->x) ? s0->x : 0;
   d->z = (0 < s0->x && 0 < s0->y) ? pow(s0->y, s0->w) : 0;
   d->w = 1;
+
+  /*
+  DPRINTF("executing lit: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
+	  s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w);
+  */
 }
 
 void vshader_logp(SHADER8Vector* d, SHADER8Vector* s0) {
@@ -151,6 +188,11 @@
   d->y = s0->y;
   d->z = s0->z;
   d->w = s0->w;
+
+  /*
+  DPRINTF("executing mov: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
+	  s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w);
+  */
 }
 
 void vshader_mul(SHADER8Vector* d, SHADER8Vector* s0, SHADER8Vector* s1) {
@@ -158,6 +200,11 @@
   d->y = s0->y * s1->y;
   d->z = s0->z * s1->z;
   d->w = s0->w * s1->w;
+
+  /*
+  DPRINTF("executing mul: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
+          s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w);
+  */
 }
 
 void vshader_nop(void) {
@@ -223,6 +270,7 @@
 
 const shader_opcode* vshader_program_get_opcode(const DWORD code) {
   DWORD i = 0;
+  /** TODO: use dichotomic search */
   while (NULL != vshader_ins[i].name) {
     if ((code & D3DSI_OPCODE_MASK) == vshader_ins[i].opcode) {
       return &vshader_ins[i];
@@ -339,7 +387,7 @@
 	DPRINTF("\n");
       }
     }
-    vshader->functionLength = len * sizeof(DWORD);
+    vshader->functionLength = (len + 1) * sizeof(DWORD);
   } else {
     vshader->functionLength = 1; /* no Function defined use fixed function vertex processing */
   }
@@ -347,7 +395,7 @@
 }
 
 BOOL vshader_program_execute_HAL(VERTEXSHADER8* vshader,
-				 const vshader_input_data* input,
+				 vshader_input_data* input,
 				 vshader_output_data* output) {
   /** 
    * TODO: use the NV_vertex_program (or 1_1) extension 
@@ -356,6 +404,8 @@
   return TRUE;
 }
 
+#define TRACE_VECTOR(name) DPRINTF( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w)
+
 BOOL vshader_program_execute_SW(VERTEXSHADER8* vshader,
 				vshader_input_data* input,
 				vshader_output_data* output) {
@@ -372,35 +422,52 @@
   /** functions parameters */
   SHADER8Vector* p[4];
   SHADER8Vector* p_send[4];
-
   DWORD i;
 
+  /* vshader_program_parse(vshader); */
+  /*
+  TRACE_VECTOR(vshader->data->C[0]);
+  TRACE_VECTOR(vshader->data->C[1]);
+  TRACE_VECTOR(vshader->data->C[2]);
+  TRACE_VECTOR(vshader->data->C[3]);
+  TRACE_VECTOR(input->V[D3DVSDE_POSITION]);
+  TRACE_VECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
+  TRACE_VECTOR(input->V[D3DVSDE_BLENDINDICES]);
+  TRACE_VECTOR(input->V[D3DVSDE_NORMAL]);
+  TRACE_VECTOR(input->V[D3DVSDE_PSIZE]);
+  TRACE_VECTOR(input->V[D3DVSDE_DIFFUSE]);
+  TRACE_VECTOR(input->V[D3DVSDE_SPECULAR]);
+  TRACE_VECTOR(input->V[D3DVSDE_TEXCOORD0]);
+  TRACE_VECTOR(input->V[D3DVSDE_TEXCOORD1]);
+  */
+
   /* the first dword is the version tag */
   /* TODO: parse it */
   
-  ++pToken;
   while (D3DVS_END() != *pToken) {
     curOpcode = vshader_program_get_opcode(*pToken);
     ++pToken;
     if (NULL == curOpcode) {
       /* unkown current opcode ... */
       while (*pToken & 0x80000000) {
-	DPRINTF("unrecognized opcode: %08lX\n", *pToken);
+	DPRINTF("unrecognized opcode: pos=%d token=%08lX\n", pToken - vshader->function, *pToken);
 	++pToken;
       }
       /*return FALSE;*/
     } else {     
-      if (curOpcode->num_params > 0) {
-	
+      if (curOpcode->num_params > 0) {	
+	/*DPRINTF(">> execting opcode: pos=%lu opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken);*/
 	for (i = 0; i < curOpcode->num_params; ++i) {
 	  DWORD reg = pToken[i] & 0x00001FFF;
 	  DWORD regtype = ((pToken[i] & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
 
 	  switch (regtype << D3DSP_REGTYPE_SHIFT) {
 	  case D3DSPR_TEMP:
+	    /*DPRINTF("p[%d]=R[%d]\n", i, reg);*/
 	    p[i] = &R[reg];
 	    break;
 	  case D3DSPR_INPUT:
+	    /*DPRINTF("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]);*/
 	    p[i] = &input->V[reg];
 	    break;
 	  case D3DSPR_CONST:
@@ -411,8 +478,11 @@
 	    }
 	    break;
 	  case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
-	    if (0 != reg)
-	      ERR("cannot handle address registers != a0");
+	    if (0 != reg) {
+	      ERR("cannot handle address registers != a0, forcing use of a0\n");
+	      reg = 0;
+	    }
+	    /*DPRINTF("p[%d]=A[%d]\n", i, reg);*/
 	    p[i] = &A[reg];
 	    break;
 	  case D3DSPR_RASTOUT:
@@ -429,30 +499,45 @@
 	    }
 	    break;
 	  case D3DSPR_ATTROUT:
+	    /*DPRINTF("p[%d]=oD[%d]\n", i, reg);*/
 	    p[i] = &output->oD[reg];
 	    break;
 	  case D3DSPR_TEXCRDOUT:
+	    /*DPRINTF("p[%d]=oT[%d]\n", i, reg);*/
 	    p[i] = &output->oT[reg];
 	    break;
 	  default:
 	    break;
 	  }
 	  
-	  if (i > 1) { /* input reg */
+	  if (i > 0) { /* input reg */
 	    DWORD swizzle = (pToken[i] & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
 	    DWORD swizzle_x = swizzle & 0x03;
 	    DWORD swizzle_y = (swizzle >> 2) & 0x03;
 	    DWORD swizzle_z = (swizzle >> 4) & 0x03;
 	    DWORD swizzle_w = (swizzle >> 6) & 0x03;
 	    if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) {
+	      /*DPRINTF("p[%d] not swizzled\n", i);*/
 	      p_send[i] = p[i];
 	    } else {
-	      float* tt = (float*) p[i];
-	      s[i].x = tt[swizzle_x];
-	      s[i].y = tt[swizzle_y];
-	      s[i].z = tt[swizzle_z];
-	      s[i].w = tt[swizzle_w];
-	      p_send[i] = &s[i];
+	      /*DPRINTF("p[%d] swizzled\n", i);*/
+	      if (swizzle_x == swizzle_y && 
+		  swizzle_x == swizzle_z && 
+		  swizzle_x == swizzle_w) {
+		float* tt = (float*) p[i];
+		s[i].x = tt[swizzle_x];
+		s[i].y = 0.0f;
+		s[i].z = 0.0f;
+		s[i].w = 0.0f;
+		p_send[i] = &s[i];
+	      } else {
+		float* tt = (float*) p[i];
+		s[i].x = tt[swizzle_x];
+		s[i].y = tt[swizzle_y];
+		s[i].z = tt[swizzle_z];
+		s[i].w = tt[swizzle_w];
+		p_send[i] = &s[i];
+	      }
 	    }
 	  } else { /* output reg */
 	    if ((pToken[i] & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) {
@@ -491,7 +576,20 @@
 	if (pToken[0] & D3DSP_WRITEMASK_2) p[0]->z = d.z; 
 	if (pToken[0] & D3DSP_WRITEMASK_3) p[0]->w = d.w; 
       }
-      
+
+      /*
+      TRACE_VECTOR(output->oPos);
+      TRACE_VECTOR(output->oD[0]);
+      TRACE_VECTOR(output->oD[1]);
+      TRACE_VECTOR(output->oT[0]);
+      TRACE_VECTOR(output->oT[1]);
+      TRACE_VECTOR(R[0]);
+      TRACE_VECTOR(R[1]);
+      TRACE_VECTOR(R[2]);
+      TRACE_VECTOR(R[3]);
+      TRACE_VECTOR(R[4]);
+      */
+
       /* to next opcode token */
       pToken += curOpcode->num_params;
     }
@@ -503,41 +601,6 @@
  * Vertex Shader Declaration Parser First draft ...
  */
 
-/** Vertex Shader Declaration data types tokens */
-static CONST char* VertexShaderDeclDataTypes [] = {
-  "D3DVSDT_FLOAT1",
-  "D3DVSDT_FLOAT2",
-  "D3DVSDT_FLOAT3",
-  "D3DVSDT_FLOAT4",
-  "D3DVSDT_D3DCOLOR",
-  "D3DVSDT_UBYTE4",
-  "D3DVSDT_SHORT2",
-  "D3DVSDT_SHORT4",
-  NULL
-};
-
-static CONST char* VertexShaderDeclRegister [] = {
-  "D3DVSDE_POSITION",
-  "D3DVSDE_BLENDWEIGHT",
-  "D3DVSDE_BLENDINDICES",
-  "D3DVSDE_NORMAL",
-  "D3DVSDE_PSIZE",
-  "D3DVSDE_DIFFUSE",
-  "D3DVSDE_SPECULAR",
-  "D3DVSDE_TEXCOORD0",
-  "D3DVSDE_TEXCOORD1",
-  "D3DVSDE_TEXCOORD2",
-  "D3DVSDE_TEXCOORD3",
-  "D3DVSDE_TEXCOORD4",
-  "D3DVSDE_TEXCOORD5",
-  "D3DVSDE_TEXCOORD6",
-  "D3DVSDE_TEXCOORD7",
-  "D3DVSDE_POSITION2",
-  "D3DVSDE_NORMAL2",
-  NULL
-};
-
-
 /** todo check decl validity */
 DWORD vshader_decl_parse_token(const DWORD* pToken) {
   const DWORD token = *pToken;
@@ -622,6 +685,7 @@
   DWORD token;
   DWORD tokenlen;
   DWORD tokentype;
+  DWORD tex = D3DFVF_TEX0;
 
   while (D3DVSD_END() != *pToken) {
     token = *pToken;
@@ -632,8 +696,17 @@
     if (D3DVSD_TOKEN_STREAMDATA == tokentype && 0 == (0x10000000 & tokentype)) {
       DWORD type = ((token & D3DVSD_DATATYPEMASK)  >> D3DVSD_DATATYPESHIFT);
       DWORD reg  = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT);
+
       switch (reg) {
-      case D3DVSDE_POSITION:     fvf |= D3DFVF_XYZ;             break;
+      case D3DVSDE_POSITION:     
+	switch (type) {
+	case D3DVSDT_FLOAT3:     fvf |= D3DFVF_XYZ;             break;
+	case D3DVSDT_FLOAT4:     fvf |= D3DFVF_XYZRHW;          break;
+	default:
+	  /** errooooorr what to do ? */
+	  ERR("Error in VertexShader declaration of D3DVSDE_POSITION register: unsupported type %lu\n", type);	  
+	}
+	break;
       case D3DVSDE_BLENDWEIGHT:
 	switch (type) {
 	case D3DVSDT_FLOAT1:     fvf |= D3DFVF_XYZB1;           break;
@@ -646,31 +719,40 @@
 	}
 	break;
 
-      case D3DVSDE_BLENDINDICES: fvf |= D3DFVF_LASTBETA_UBYTE4; break;
-      case D3DVSDE_NORMAL:       fvf |= D3DFVF_NORMAL;          break;
-      case D3DVSDE_PSIZE:        fvf |= D3DFVF_PSIZE;           break;
-      case D3DVSDE_DIFFUSE:      fvf |= D3DFVF_DIFFUSE;         break;
-      case D3DVSDE_SPECULAR:     fvf |= D3DFVF_SPECULAR;        break;
-      case D3DVSDE_TEXCOORD0:    fvf |= D3DFVF_TEX1;            break;
-      case D3DVSDE_TEXCOORD1:    fvf |= D3DFVF_TEX2;            break;
-      case D3DVSDE_TEXCOORD2:    fvf |= D3DFVF_TEX3;            break;
-      case D3DVSDE_TEXCOORD3:    fvf |= D3DFVF_TEX4;            break;
-      case D3DVSDE_TEXCOORD4:    fvf |= D3DFVF_TEX5;            break;
-      case D3DVSDE_TEXCOORD5:    fvf |= D3DFVF_TEX6;            break;
-      case D3DVSDE_TEXCOORD6:    fvf |= D3DFVF_TEX7;            break;
-      case D3DVSDE_TEXCOORD7:    fvf |= D3DFVF_TEX8;            break;
+      case D3DVSDE_BLENDINDICES: fvf |= D3DFVF_LASTBETA_UBYTE4; break; /* TODO: undertand ;( */
+      case D3DVSDE_NORMAL:       fvf |= D3DFVF_NORMAL;          break; /* TODO: only FLOAT3 supported ... another choice possible ? */
+      case D3DVSDE_PSIZE:        fvf |= D3DFVF_PSIZE;           break; /* TODO: only FLOAT1 supported ... another choice possible ? */
+      case D3DVSDE_DIFFUSE:      fvf |= D3DFVF_DIFFUSE;         break; /* TODO: only FLOAT1 supported */
+      case D3DVSDE_SPECULAR:     fvf |= D3DFVF_SPECULAR;        break; /* TODO: only FLOAT1 supported */
+	/**
+	 * TODO: for TEX* only FLOAT2 supported
+	 *  by default using texture type info
+	 */
+      case D3DVSDE_TEXCOORD0:    tex = max(tex, D3DFVF_TEX1);   break; 
+      case D3DVSDE_TEXCOORD1:    tex = max(tex, D3DFVF_TEX2);   break;
+      case D3DVSDE_TEXCOORD2:    tex = max(tex, D3DFVF_TEX3);   break;
+      case D3DVSDE_TEXCOORD3:    tex = max(tex, D3DFVF_TEX4);   break;
+      case D3DVSDE_TEXCOORD4:    tex = max(tex, D3DFVF_TEX5);   break;
+      case D3DVSDE_TEXCOORD5:    tex = max(tex, D3DFVF_TEX6);   break;
+      case D3DVSDE_TEXCOORD6:    tex = max(tex, D3DFVF_TEX7);   break;
+      case D3DVSDE_TEXCOORD7:    tex = max(tex, D3DFVF_TEX8);   break;
       case D3DVSDE_POSITION2:   /* maybe D3DFVF_XYZRHW instead D3DFVF_XYZ (of D3DVDE_POSITION) ... to see */
       case D3DVSDE_NORMAL2:     /* FIXME i don't know what to do here ;( */
 	FIXME("[%lu] registers in VertexShader declaration not supported yet (token:0x%08lx)\n", reg, token);
 	break;
       }
+      /*TRACE("VertexShader declaration define %x as current FVF\n", fvf);*/
     }
     len += tokenlen;
     pToken += tokenlen;
   }
+  if (tex > 0) {
+    /*TRACE("VertexShader declaration define %x as texture level\n", tex);*/
+    fvf |= tex;
+  }   
   /* here D3DVSD_END() */
   len += vshader_decl_parse_token(pToken);
-  if (NULL == vshader->function) vshader->fvf = fvf;
+  vshader->fvf = fvf;
   vshader->declLength = len * sizeof(DWORD);
   return len * sizeof(DWORD);
 }
@@ -684,3 +766,4 @@
   FIXME("(void): stub\n");
   return 0;
 }
+


More information about the wine-devel mailing list