I am hoping someone (Stefan?) will help me with testing/review here, because I don't have the apps and the disk space to test properly. This changes things in drawStridedSlow, which is an important code path, so correctness and performance matter (for non shader apps).
If there is no feedback I'll submit the patch as is. ====================
- split drawStridedSlow into "prepare" and "draw" segments - fixed_prepare_draw (vs swshader_prepare_draw), and draw_vertex.
- do not load or unload attribute arrays for software shaders make software shaders go through the drawStridedSlow code path
- disable VBOs for software shaders
- delete the old (disabled) swshader hook.
--- dlls/wined3d/device.c | 4 dlls/wined3d/drawprim.c | 786 +++++++++++++--------------------------- dlls/wined3d/wined3d_private.h | 9 3 files changed, 267 insertions(+), 532 deletions(-)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 714bb1d..076cc58 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -738,10 +738,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl * dx7 apps. * There is a IDirect3DVertexBuffer7::Optimize call after which the buffer can't be locked any * more. In this call we can convert dx7 buffers too. + * + * Also, disable VBOs for software shaders. */ conv = ((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW ) || (FVF & (D3DFVF_DIFFUSE | D3DFVF_SPECULAR)); if( GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) && Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) && - (dxVersion > 7 || !conv) ) { + (dxVersion > 7 || !conv) && wined3d_settings.vs_selected_mode != SHADER_SW) { CreateVBO(object);
/* DX7 buffers can be locked directly into the VBO(no conversion, see above */ diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c index f81b23d..a98905d 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -791,137 +791,6 @@ #endif } }
-#if 0 /* TODO: Software Shaders */ -/* Draw a single vertex using this information */ -static void draw_vertex(IWineD3DDevice *iface, /* interface */ - BOOL isXYZ, float x, float y, float z, float rhw, /* xyzn position*/ - BOOL isNormal, float nx, float ny, float nz, /* normal */ - BOOL isDiffuse, float *dRGBA, /* 1st colors */ - BOOL isSpecular, float *sRGB, /* 2ndry colors */ - BOOL isPtSize, float ptSize, /* pointSize */ - WINED3DVECTOR_4 *texcoords, int *numcoords) /* texture info */ -{ - unsigned int textureNo; - float s, t, r, q; - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - - /* Diffuse -------------------------------- */ - if (isDiffuse) { - glColor4fv(dRGBA); - VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3])); - } - - /* Specular Colour ------------------------------------------*/ - if (isSpecular) { - if (GL_SUPPORT(EXT_SECONDARY_COLOR)) { - GL_EXTCALL(glSecondaryColor3fvEXT(sRGB)); - VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2])); - } else { - VTRACE(("Specular color extensions not supplied\n")); - } - } - - /* Normal -------------------------------- */ - if (isNormal) { - VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz)); - glNormal3f(nx, ny, nz); - } - - /* Point Size ----------------------------------------------*/ - if (isPtSize) { - - /* no such functionality in the fixed function GL pipeline */ - FIXME("Cannot change ptSize here in openGl\n"); - } - - /* Texture coords --------------------------- */ - for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) { - - if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) { - FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n"); - continue ; - } - - /* Query tex coords */ - if (This->stateBlock->textures[textureNo] != NULL) { - - int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX]; - if (coordIdx >= MAX_TEXTURES) { - VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo)); - continue; - } else if (numcoords[coordIdx] == 0) { - TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo); - continue; - } else { - - /* Initialize vars */ - s = 0.0f; - t = 0.0f; - r = 0.0f; - q = 0.0f; - - switch (numcoords[coordIdx]) { - case 4: q = texcoords[coordIdx].w; /* drop through */ - case 3: r = texcoords[coordIdx].z; /* drop through */ - case 2: t = texcoords[coordIdx].y; /* drop through */ - case 1: s = texcoords[coordIdx].x; - } - - switch (numcoords[coordIdx]) { /* Supply the provided texture coords */ - case D3DTTFF_COUNT1: - VTRACE(("tex:%d, s=%f\n", textureNo, s)); - if (GL_SUPPORT(ARB_MULTITEXTURE)) { - GLMULTITEXCOORD1F(textureNo, s); - } else { - glTexCoord1f(s); - } - break; - case D3DTTFF_COUNT2: - VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t)); - if (GL_SUPPORT(ARB_MULTITEXTURE)) { - GLMULTITEXCOORD2F(textureNo, s, t); - } else { - glTexCoord2f(s, t); - } - break; - case D3DTTFF_COUNT3: - VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r)); - if (GL_SUPPORT(ARB_MULTITEXTURE)) { - GLMULTITEXCOORD3F(textureNo, s, t, r); - } else { - glTexCoord3f(s, t, r); - } - break; - case D3DTTFF_COUNT4: - VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q)); - if (GL_SUPPORT(ARB_MULTITEXTURE)) { - GLMULTITEXCOORD4F(textureNo, s, t, r, q); - } else { - glTexCoord4f(s, t, r, q); - } - break; - default: - FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]); - } - } - } - } /* End of textures */ - - /* Position -------------------------------- */ - if (isXYZ) { - if (1.0f == rhw || rhw < 0.00001f) { - VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z)); - glVertex3f(x, y, z); - } else { - /* Cannot optimize by dividing through by rhw as rhw is required - later for perspective in the GL pipeline for vertex shaders */ - VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw)); - glVertex4f(x,y,z,rhw); - } - } -} -#endif /* TODO: Software shaders */ - void loadNumberedArrays( IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd, @@ -1400,350 +1269,275 @@ #endif return; }
-/* - * Actually draw using the supplied information. - * Slower GL version which extracts info about each vertex in turn - */ - -static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd, - UINT NumVertexes, GLenum glPrimType, - const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) { - - unsigned int textureNo = 0; - unsigned int texture_idx = 0; - const short *pIdxBufS = NULL; - const long *pIdxBufL = NULL; - LONG SkipnStrides = 0; - LONG vx_index; - float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */ - float nx = 0.0f, ny = 0.0, nz = 0.0f; /* normal x,y,z coordinates */ - float rhw = 0.0f; /* rhw */ - float ptSize = 0.0f; /* Point size */ - DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */ - DWORD specularColor = 0; /* Specular Color */ - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - - TRACE("Using slow vertex array code\n"); +static inline void swshader_prepare_draw( + IWineD3DDeviceImpl* This, + WineDirect3DVertexStridedData *strided, + int skip_strides, + draw_context* draw) { + + This = NULL; + strided = NULL; + skip_strides = 0; + draw = NULL; + FIXME("Stub"); +}
- /* Variable Initialization */ - if (idxData != NULL) { - if (idxSize == 2) pIdxBufS = (const short *) idxData; - else pIdxBufL = (const long *) idxData; +static inline void fixed_prepare_draw( + IWineD3DDeviceImpl* This, + WineDirect3DVertexStridedData *strided, + int skip_strides, + draw_context* draw) { + + int i, textureNo; + + const WINED3DSHADERVECTOR def_position = { 0.0f, 0.0f, 0.0f, 0.0f }; + const WINED3DSHADERVECTOR def_diffuse = { 1.0f, 1.0f, 1.0f, 1.0f }; + const WINED3DSHADERVECTOR def_specular = { 0.0f, 0.0f, 0.0f, 1.0f }; + const WINED3DSHADERVECTOR def_normal = { 0.0f, 0.0f, 1.0f, 0.0f }; + const WINED3DSHADERVECTOR def_texcoord = { 0.0f, 0.0f, 0.0f, 1.0f }; + + /* Defaults */ + draw->is_transformed = FALSE; + memcpy(&draw->diffuse, &def_diffuse, sizeof(WINED3DSHADERVECTOR)); + memcpy(&draw->specular, &def_specular, sizeof(WINED3DSHADERVECTOR)); + memcpy(&draw->position, &def_position, sizeof(WINED3DSHADERVECTOR)); + memcpy(&draw->normal, &def_normal, sizeof(WINED3DSHADERVECTOR)); + for (i = 0; i < GL_LIMITS(texture_stages); i++) { + if (This->stateBlock->textures[i] != NULL) + memcpy(&draw->texcoords[i], &def_texcoord, sizeof(WINED3DSHADERVECTOR)); }
- /* Start drawing in GL */ - VTRACE(("glBegin(%x)\n", glPrimType)); - glBegin(glPrimType); + /* Position ---------------------------- */ + if (strided->u.s.position.lpData) { + float *ptrToCoords = + (float *)(strided->u.s.position.lpData + (skip_strides * strided->u.s.position.dwStride));
- /* We shouldn't start this function if any VBO is involved. Should I put a safety check here? - * Guess it's not necessary(we crash then anyway) and would only eat CPU time - */ + draw->position.x = ptrToCoords[0]; + draw->position.y = ptrToCoords[1]; + draw->position.z = ptrToCoords[2]; + draw->position.w = 1.0;
- /* For each primitive */ - for (vx_index = 0; vx_index < NumVertexes; ++vx_index) { + /* Data contains rhw */ + if (strided->u.s.position.dwType == D3DDECLTYPE_FLOAT4) { + float rhw = ptrToCoords[3];
- /* Initialize diffuse color */ - diffuseColor = 0xFFFFFFFF; + draw->is_transformed = TRUE;
- /* For indexed data, we need to go a few more strides in */ - if (idxData != NULL) { + /* FIXUP: divide by rhw */ + if (rhw > eps && rhw < -eps) { + draw->position.w = 1.0 / rhw; + draw->position.x /= rhw; + draw->position.y /= rhw; + draw->position.z /= rhw;
- /* Indexed so work out the number of strides to skip */ - if (idxSize == 2) { - VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index])); - SkipnStrides = pIdxBufS[startIdx + vx_index]; - } else { - VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index])); - SkipnStrides = pIdxBufL[startIdx + vx_index]; - } + } else draw->position.w = rhw; } + VTRACE(("position = { %f, %f, %f, %f }\n", + draw->position.x, draw->position.y, draw->position.z, draw->position.w)); + }
- /* Position Information ------------------ */ - if (sd->u.s.position.lpData != NULL) { + /* Normal --------------------------------- */ + if (strided->u.s.normal.lpData) { + float *ptrToCoords = + (float *)(strided->u.s.normal.lpData + (skip_strides * strided->u.s.normal.dwStride)); + draw->normal.x = ptrToCoords[0]; + draw->normal.y = ptrToCoords[1]; + draw->normal.z = ptrToCoords[2]; + VTRACE(("normal = { %f, %f, %f }\n", draw->normal.x, draw->normal.y, draw->normal.z)); + } + + /* Diffuse -------------------------------- */ + if (strided->u.s.diffuse.lpData) { + + DWORD *ptrToCoords = + (DWORD *)(strided->u.s.diffuse.lpData + (skip_strides * strided->u.s.diffuse.dwStride)); + draw->diffuse.x = D3DCOLOR_B(ptrToCoords[0]); + draw->diffuse.y = D3DCOLOR_G(ptrToCoords[0]); + draw->diffuse.z = D3DCOLOR_R(ptrToCoords[0]); + draw->diffuse.w = D3DCOLOR_A(ptrToCoords[0]); + VTRACE(("diffuse = { %f, %f, %f, %f }\n", + draw->diffuse.x, draw->diffuse.y, draw->diffuse.z, draw->diffuse.w)); + } + /* Specular -------------------------------- */ + if (strided->u.s.specular.lpData) { + + DWORD *ptrToCoords = + (DWORD *)(strided->u.s.specular.lpData + (skip_strides * strided->u.s.specular.dwStride)); + draw->specular.x = D3DCOLOR_B(ptrToCoords[0]); + draw->specular.y = D3DCOLOR_G(ptrToCoords[0]); + draw->specular.z = D3DCOLOR_R(ptrToCoords[0]); + draw->specular.w = D3DCOLOR_A(ptrToCoords[0]); + VTRACE(("specular = { %f, %f, %f, %f }\n", + draw->specular.x, draw->specular.y, draw->specular.z, draw->specular.w)); + }
- float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride)); - x = ptrToCoords[0]; - y = ptrToCoords[1]; - z = ptrToCoords[2]; - rhw = 1.0; - VTRACE(("x,y,z=%f,%f,%f\n", x,y,z)); + /* Blending ---------------------------------- */ + if (strided->u.s.blendWeights.lpData != NULL || + strided->u.s.blendMatrixIndices.lpData != NULL) {
- /* RHW follows, only if transformed, ie 4 floats were provided */ - if (sd->u.s.position.dwType == D3DDECLTYPE_FLOAT4) { - rhw = ptrToCoords[3]; - VTRACE(("rhw=%f\n", rhw)); - } - } + FIXME("Blending not supported yet\n"); + }
- /* Blending data -------------------------- */ - if (sd->u.s.blendWeights.lpData != NULL) { - /* float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride)); */ - FIXME("Blending not supported yet\n"); + /* Point Size -------------------------------- */ + if (strided->u.s.pSize.lpData != NULL) {
- if (sd->u.s.blendMatrixIndices.lpData != NULL) { - /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/ - } - } + FIXME("Point Size not supported yet\n"); + }
- /* Vertex Normal Data (untransformed only)- */ - if (sd->u.s.normal.lpData != NULL) { + /* Texture ---------------------------------- */ + for (textureNo = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
- float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride)); - nx = ptrToCoords[0]; - ny = ptrToCoords[1]; - nz = ptrToCoords[2]; - VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz)); - } + unsigned int idx; + if (This->stateBlock->textures[textureNo] == NULL) + continue;
- /* Point Size ----------------------------- */ - if (sd->u.s.pSize.lpData != NULL) { + idx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX]; + if (strided->u.s.texCoords[idx].lpData) { + + float* ptrToCoords = + (float *)(strided->u.s.texCoords[idx].lpData + (skip_strides * strided->u.s.texCoords[idx].dwStride)); + unsigned int numcoords = strided->u.s.texCoords[idx].dwType + 1; + switch (numcoords) { + case 4: draw->texcoords[textureNo].w = ptrToCoords[3]; /* drop through */ + case 3: draw->texcoords[textureNo].z = ptrToCoords[2]; /* drop through */ + case 2: draw->texcoords[textureNo].y = ptrToCoords[1]; /* drop through */ + case 1: draw->texcoords[textureNo].x = ptrToCoords[0]; + } + + /* Projected is more 'fun' - Move the last coord to the 'q' + * parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */ + if ((This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) && + (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) { + + if (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) { + switch (numcoords) { + case 0: /* Drop Through */ + case 1: + FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n"); + break; + case 2: + draw->texcoords[textureNo].w = draw->texcoords[textureNo].y; + draw->texcoords[textureNo].y = 0.0; + break; + case 3: + draw->texcoords[textureNo].w = draw->texcoords[textureNo].z; + draw->texcoords[textureNo].z = 0.0; + break; + case 4: /* Nop here */ + break; + default: + FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n", + This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & + D3DTTFF_PROJECTED); + } + } + }
- float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride)); - ptSize = ptrToCoords[0]; - VTRACE(("ptSize=%f\n", ptSize)); - FIXME("No support for ptSize yet\n"); - } + VTRACE(("tex: %d (%u coords) = { %f %f %f %f }\n", idx, + numcoords, draw->texcoords[textureNo].x, draw->texcoords[textureNo].y, + draw->texcoords[textureNo].z, draw->texcoords[textureNo].w)); + } + } +}
- /* Diffuse -------------------------------- */ - if (sd->u.s.diffuse.lpData != NULL) { +/* Draw a single vertex using the supplied data */ +static inline void draw_vertex( + IWineD3DDeviceImpl* This, + draw_context* draw) {
- DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride)); - diffuseColor = ptrToCoords[0]; - VTRACE(("diffuseColor=%lx\n", diffuseColor)); - } + unsigned int textureNo, texture_idx;
- /* Specular -------------------------------- */ - if (sd->u.s.specular.lpData != NULL) { + /* Draw Vertex: Texture coords --------------------------- */ + for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
- DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride)); - specularColor = ptrToCoords[0]; - VTRACE(("specularColor=%lx\n", specularColor)); + if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) { + FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n"); + continue ; }
- /* Texture coords --------------------------- */ - for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) { - - if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) { - FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n"); - continue ; - } - - /* Query tex coords */ - if (This->stateBlock->textures[textureNo] != NULL) { - - int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX]; - float *ptrToCoords = NULL; - float s = 0.0, t = 0.0, r = 0.0, q = 0.0; - - if (coordIdx > 7) { - VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo)); - continue; - } else if (coordIdx < 0) { - FIXME("tex: %d - Coord index %d is less than zero, expect a crash.\n", textureNo, coordIdx); - continue; - } - - ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride)); - if (sd->u.s.texCoords[coordIdx].lpData == NULL) { - TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo); - continue; - } else { - - int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DDECLTYPE_FLOAT1 etc */ - - /* The coords to supply depend completely on the fvf / vertex shader */ - switch (coordsToUse) { - case 4: q = ptrToCoords[3]; /* drop through */ - case 3: r = ptrToCoords[2]; /* drop through */ - case 2: t = ptrToCoords[1]; /* drop through */ - case 1: s = ptrToCoords[0]; - } - - /* Projected is more 'fun' - Move the last coord to the 'q' - parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */ - if ((This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) && - (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) { - - if (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) { - switch (coordsToUse) { - case 0: /* Drop Through */ - case 1: - FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n"); - break; - case 2: - q = t; - t = 0.0; - coordsToUse = 4; - break; - case 3: - q = r; - r = 0.0; - coordsToUse = 4; - break; - case 4: /* Nop here */ - break; - default: - FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n", - This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED); - } - } - } - - switch (coordsToUse) { /* Supply the provided texture coords */ - case D3DTTFF_COUNT1: - VTRACE(("tex:%d, s=%f\n", textureNo, s)); - if (GL_SUPPORT(ARB_MULTITEXTURE)) { - GL_EXTCALL(glMultiTexCoord1fARB(texture_idx, s)); - } else { - glTexCoord1f(s); - } - break; - case D3DTTFF_COUNT2: - VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t)); - if (GL_SUPPORT(ARB_MULTITEXTURE)) { - GL_EXTCALL(glMultiTexCoord2fARB(texture_idx, s, t)); - } else { - glTexCoord2f(s, t); - } - break; - case D3DTTFF_COUNT3: - VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r)); - if (GL_SUPPORT(ARB_MULTITEXTURE)) { - GL_EXTCALL(glMultiTexCoord3fARB(texture_idx, s, t, r)); - } else { - glTexCoord3f(s, t, r); - } - break; - case D3DTTFF_COUNT4: - VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q)); - if (GL_SUPPORT(ARB_MULTITEXTURE)) { - GL_EXTCALL(glMultiTexCoord4fARB(texture_idx, s, t, r, q)); - } else { - glTexCoord4f(s, t, r, q); - } - break; - default: - FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse); - } - } - } - if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) ++texture_idx; - } /* End of textures */ - - /* Diffuse -------------------------------- */ - if (sd->u.s.diffuse.lpData != NULL) { - glColor4ub(D3DCOLOR_B_R(diffuseColor), - D3DCOLOR_B_G(diffuseColor), - D3DCOLOR_B_B(diffuseColor), - D3DCOLOR_B_A(diffuseColor)); - VTRACE(("glColor4ub: r,g,b,a=%lu,%lu,%lu,%lu\n", - D3DCOLOR_B_R(diffuseColor), - D3DCOLOR_B_G(diffuseColor), - D3DCOLOR_B_B(diffuseColor), - D3DCOLOR_B_A(diffuseColor))); - } else { - if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - } + if (This->stateBlock->textures[textureNo] != NULL) {
- /* Specular ------------------------------- */ - if (sd->u.s.specular.lpData != NULL) { - /* special case where the fog density is stored in the diffuse alpha channel */ - if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] && - (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] == D3DFOG_NONE || sd->u.s.position.dwType == D3DDECLTYPE_FLOAT4 )&& - This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == D3DFOG_NONE) { - if(GL_SUPPORT(EXT_FOG_COORD)) { - GL_EXTCALL(glFogCoordfEXT(specularColor >> 24)); - } else { - static BOOL warned = FALSE; - if(!warned) { - /* TODO: Use the fog table code from old ddraw */ - FIXME("Implement fog for transformed vertices in software\n"); - warned = TRUE; - } - } - } + float s = draw->texcoords[textureNo].x; + float t = draw->texcoords[textureNo].y; + float r = draw->texcoords[textureNo].z; + float q = draw->texcoords[textureNo].w;
- VTRACE(("glSecondaryColor4ub: r,g,b=%lu,%lu,%lu\n", - D3DCOLOR_B_R(specularColor), - D3DCOLOR_B_G(specularColor), - D3DCOLOR_B_B(specularColor))); - if (GL_SUPPORT(EXT_SECONDARY_COLOR)) { - GL_EXTCALL(glSecondaryColor3ubEXT)( - D3DCOLOR_B_R(specularColor), - D3DCOLOR_B_G(specularColor), - D3DCOLOR_B_B(specularColor)); - } else { - /* Do not worry if specular colour missing and disable request */ - VTRACE(("Specular color extensions not supplied\n")); - } - } else { - if (vx_index == 0) { - if (GL_SUPPORT(EXT_SECONDARY_COLOR)) { - GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0); - } else { - /* Do not worry if specular colour missing and disable request */ - VTRACE(("Specular color extensions not supplied\n")); - } - } + VTRACE(("DRAW tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q)); + if (GL_SUPPORT(ARB_MULTITEXTURE)) + GL_EXTCALL(glMultiTexCoord4fARB(texture_idx, s, t, r, q)); + else + glTexCoord4f(s, t, r, q); } + if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) ++texture_idx; + } /* End of textures */
- /* Normal -------------------------------- */ - if (sd->u.s.normal.lpData != NULL) { - VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz)); - glNormal3f(nx, ny, nz); - } else { - if (vx_index == 0) glNormal3f(0, 0, 1); - } + /* Draw Vertex: Diffuse -------------------------------- */ + glColor4f(draw->diffuse.z, draw->diffuse.y, draw->diffuse.x, draw->diffuse.w); + VTRACE(("DRAW diffuse: r,g,b,a=%f,%f,%f,%f\n", + draw->diffuse.z, draw->diffuse.y, draw->diffuse.x, draw->diffuse.w)); + + /* Draw Vertex: Fog (non-table, non-vertex) ------------------------------- */ + /* special case where the fog density is stored in the diffuse alpha channel */ + /* FIXME: then why is this looking in the specular alpha channel? */ + if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] && + (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] == D3DFOG_NONE || draw->is_transformed ) && + This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == D3DFOG_NONE) { + + if (GL_SUPPORT(EXT_FOG_COORD)) + GL_EXTCALL(glFogCoordfEXT(draw->specular.w)); + + else { + static BOOL warned = FALSE; + if(!warned) { + /* TODO: Use the fog table code from old ddraw */ + FIXME("Implement fog for transformed vertices in software\n"); + warned = TRUE; + } + } + }
- /* Position -------------------------------- */ - if (sd->u.s.position.lpData != NULL) { - if (1.0f == rhw || ((rhw < eps) && (rhw > -eps))) { - VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z)); - glVertex3f(x, y, z); - } else { - GLfloat w = 1.0 / rhw; - VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw)); - glVertex4f(x*w, y*w, z*w, w); - } - } + /* Draw Vertex: Specular ------------------------------- */ + VTRACE(("DRAW specular: r,g,b=%f,%f,%f\n", + draw->specular.z, draw->specular.y, draw->specular.x)); + if (GL_SUPPORT(EXT_SECONDARY_COLOR)) + GL_EXTCALL(glSecondaryColor3fEXT(draw->specular.z, draw->specular.y, draw->specular.x)); + else + /* Do not worry if specular colour missing and disable request */ + VTRACE(("Specular color extensions not supplied\n"));
- /* For non indexed mode, step onto next parts */ - if (idxData == NULL) { - ++SkipnStrides; - } - } + /* Draw Vertex: Normal -------------------------------- */ + VTRACE(("DRAW normal:nx,ny,nz=%f,%f,%f\n", draw->normal.x, draw->normal.y, draw->normal.z)); + glNormal3f(draw->normal.x, draw->normal.y, draw->normal.z);
- glEnd(); - checkGLcall("glEnd and previous calls"); + /* Draw Vertex: Position -------------------------------- */ + VTRACE(("DRAW position: x,y,z,w=%f,%f,%f,%f\n", + draw->position.x, draw->position.y, draw->position.z, draw->position.w)); + glVertex4f(draw->position.x, draw->position.y, draw->position.z, draw->position.w); }
-#if 0 /* TODO: Software/Hardware vertex blending support */ /* - * Draw with emulated vertex shaders - * Note: strided data is uninitialized, as we need to pass the vertex - * shader directly as ordering irs yet + * Actually draw using the supplied information. + * Slower GL version which extracts info about each vertex in turn */ -void drawStridedSoftwareVS(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd, - int PrimitiveType, ULONG NumPrimitives, - const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
- unsigned int textureNo = 0; - GLenum glPrimType = GL_POINTS; - int NumVertexes = NumPrimitives; +static void drawStridedSlow( + IWineD3DDevice *iface, + WineDirect3DVertexStridedData *strided, + UINT NumVertexes, + GLenum glPrimType, + const void *idxData, + short idxSize, + ULONG minIndex, + ULONG startIdx, + BOOL software_shader) { + const short *pIdxBufS = NULL; const long *pIdxBufL = NULL; LONG SkipnStrides = 0; LONG vx_index; - float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */ - float rhw = 0.0f; /* rhw */ - float ptSize = 0.0f; /* Point size */ - D3DVECTOR_4 texcoords[8]; /* Texture Coords */ - int numcoords[8]; /* Number of coords */ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
- IDirect3DVertexShaderImpl* vertexShader = NULL; - - TRACE("Using slow software vertex shader code\n"); + TRACE("Using slow vertex array code\n");
/* Variable Initialization */ if (idxData != NULL) { @@ -1751,115 +1545,44 @@ void drawStridedSoftwareVS(IWineD3DDevic else pIdxBufL = (const long *) idxData; }
- /* Ok, Work out which primitive is requested and how many vertexes that will be */ - NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType); - - /* Retrieve the VS information */ - vertexShader = (IWineD3DVertexShaderImp *)This->stateBlock->VertexShader; - /* Start drawing in GL */ VTRACE(("glBegin(%x)\n", glPrimType)); glBegin(glPrimType);
- /* For each primitive */ - for (vx_index = 0; vx_index < NumVertexes; ++vx_index) { + /* For each primitive */ + for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
- /* For indexed data, we need to go a few more strides in */ - if (idxData != NULL) { + draw_context draw;
- /* Indexed so work out the number of strides to skip */ - if (idxSize == 2) { - VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index])); - SkipnStrides = pIdxBufS[startIdx+vx_index]; - } else { - VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index])); - SkipnStrides = pIdxBufL[startIdx+vx_index]; - } - } + /* For indexed data, we need to go a few more strides in */ + if (idxData != NULL) {
- /* Fill the vertex shader input */ - IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertexShader, SkipnStrides); - - /* Initialize the output fields to the same defaults as it would normally have */ - memset(&vertexShader->output, 0, sizeof(VSHADEROUTPUTDATA8)); - vertexShader->output.oD[0].x = 1.0; - vertexShader->output.oD[0].y = 1.0; - vertexShader->output.oD[0].z = 1.0; - vertexShader->output.oD[0].w = 1.0; - - /* Now execute the vertex shader */ - IDirect3DVertexShaderImpl_ExecuteSW(vertexShader, &vertexShader->input, &vertexShader->output); - - /* - TRACE_VECTOR(vertexShader->output.oPos); - TRACE_VECTOR(vertexShader->output.oD[0]); - TRACE_VECTOR(vertexShader->output.oD[1]); - TRACE_VECTOR(vertexShader->output.oT[0]); - TRACE_VECTOR(vertexShader->output.oT[1]); - TRACE_VECTOR(vertexShader->input.V[0]); - TRACE_VECTOR(vertexShader->data->C[0]); - TRACE_VECTOR(vertexShader->data->C[1]); - TRACE_VECTOR(vertexShader->data->C[2]); - TRACE_VECTOR(vertexShader->data->C[3]); - TRACE_VECTOR(vertexShader->data->C[4]); - TRACE_VECTOR(vertexShader->data->C[5]); - TRACE_VECTOR(vertexShader->data->C[6]); - TRACE_VECTOR(vertexShader->data->C[7]); - */ + /* Indexed so work out the number of strides to skip */ + if (idxSize == 2) { + VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index])); + SkipnStrides = pIdxBufS[startIdx + vx_index]; + } else { + VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index])); + SkipnStrides = pIdxBufL[startIdx + vx_index]; + } + }
- /* Extract out the output */ - /* FIXME: Fog coords? */ - x = vertexShader->output.oPos.x; - y = vertexShader->output.oPos.y; - z = vertexShader->output.oPos.z; - rhw = vertexShader->output.oPos.w; - ptSize = vertexShader->output.oPts.x; /* Fixme - Is this right? */ - - /** Update textures coords using vertexShader->output.oT[0->7] */ - memset(texcoords, 0x00, sizeof(texcoords)); - memset(numcoords, 0x00, sizeof(numcoords)); - for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) { - if (This->stateBlock->textures[textureNo] != NULL) { - texcoords[textureNo].x = vertexShader->output.oT[textureNo].x; - texcoords[textureNo].y = vertexShader->output.oT[textureNo].y; - texcoords[textureNo].z = vertexShader->output.oT[textureNo].z; - texcoords[textureNo].w = vertexShader->output.oT[textureNo].w; - if (This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) { - numcoords[textureNo] = This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED; - } else { - switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) { - case WINED3DRTYPE_TEXTURE: numcoords[textureNo] = 2; break; - case WINED3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break; - default: numcoords[textureNo] = 4; - } - } - } else { - numcoords[textureNo] = 0; - } - } + if (software_shader) + swshader_prepare_draw(This, strided, SkipnStrides, &draw); + else + fixed_prepare_draw(This, strided, SkipnStrides, &draw);
- /* Draw using this information */ - draw_vertex(iface, - TRUE, x, y, z, rhw, - TRUE, 0.0f, 0.0f, 1.0f, - TRUE, (float*) &vertexShader->output.oD[0], - TRUE, (float*) &vertexShader->output.oD[1], - FALSE, ptSize, /* FIXME: Change back when supported */ - texcoords, numcoords); - - /* For non indexed mode, step onto next parts */ - if (idxData == NULL) { - ++SkipnStrides; - } + draw_vertex(This, &draw);
- } /* for each vertex */ + /* For non indexed mode, step onto next parts */ + if (idxData == NULL) + ++SkipnStrides; + }
glEnd(); checkGLcall("glEnd and previous calls"); }
-#endif - static inline void drawPrimitiveDrawStrided( IWineD3DDevice *iface, BOOL useVertexShaderFunction, @@ -1913,8 +1636,8 @@ #undef BUFFER_OR_DATA loadVertexData(iface, dataLocations); useDrawStridedSlow = FALSE;
- /* Shader pipeline - load attribute arrays */ - } else if(useVertexShaderFunction) { + /* Hardware Shader pipeline - load attribute arrays */ + } else if(useVertexShaderFunction && wined3d_settings.vs_selected_mode != SHADER_SW) {
loadNumberedArrays(iface, dataLocations, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->semantics_in); @@ -1983,12 +1706,13 @@ #undef BUFFER_OR_DATA
/* Draw vertex-by-vertex */ if (useDrawStridedSlow) - drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType, idxData, idxSize, minIndex, StartIdx); + drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType, + idxData, idxSize, minIndex, StartIdx, useVertexShaderFunction); else drawStridedFast(iface, numberOfIndicies, glPrimType, idxData, idxSize, minIndex, StartIdx);
/* Cleanup vertex program */ - if (useVertexShaderFunction) { + if (useVertexShaderFunction && wined3d_settings.vs_selected_mode != SHADER_SW) { /* disable any attribs (this is the same for both GLSL and ARB modes) */ GLint maxAttribs; int i; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index a71539a..e70a9a0 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1284,6 +1284,15 @@ #define MAX_CONST_F 256 #define MAX_CONST_I 16 #define MAX_CONST_B 16
+typedef struct draw_context { + WINED3DSHADERVECTOR position; + WINED3DSHADERVECTOR diffuse; + WINED3DSHADERVECTOR specular; + WINED3DSHADERVECTOR texcoords[D3DDP_MAXTEXCOORD]; + WINED3DSHADERVECTOR normal; + BOOL is_transformed; +} draw_context; + typedef struct shader_reg_maps {
char texcoord[MAX_REG_TEXCRD]; /* pixel < 3.0 */
To make it clear, this doesn't implement software shaders - it just moves code around so when they're implemented it would be easier to do.
I already have one more or less working implementation, but it's based on executing small functions for each opcode (like the previous code does), except it goes through central processing with hardware shaders. That's incredibly slow.... so more thought needs to go into how shaders can be implemented. If it was possible to pre-generate the shader code (in asm?) somehow that'd be nice...
However shaders are implemented though, I think they should hook into the rest of the code as shown in the patch.
Am Dienstag 04 Juli 2006 11:17 schrieb Ivan Gyurdiev:
I am hoping someone (Stefan?) will help me with testing/review here, because I don't have the apps and the disk space to test properly. This changes things in drawStridedSlow, which is an important code path, so correctness and performance matter (for non shader apps).
The patch failed to apply when I tried it yesterday. There were some rejected hunks in drawprim.c, after fixing those compiling failed in device.c because some vertex buffer member was missing.
Stefan
Stefan Dösinger wrote:
Am Dienstag 04 Juli 2006 11:17 schrieb Ivan Gyurdiev:
I am hoping someone (Stefan?) will help me with testing/review here, because I don't have the apps and the disk space to test properly. This changes things in drawStridedSlow, which is an important code path, so correctness and performance matter (for non shader apps).
The patch failed to apply when I tried it yesterday. There were some rejected hunks in drawprim.c, after fixing those compiling failed in device.c because some vertex buffer member was missing.
It applies after all the other patches I sent (minus #3 which is broken)