From 6791e6b752413a4d0e08e84fa565873b922cb1de Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Thu, 8 Jan 2009 10:19:17 +0100 Subject: [PATCH] wined3d: Simplify handling of swizzled attributes. This should also be a little bit faster. --- dlls/wined3d/arb_program_shader.c | 3 +- dlls/wined3d/drawprim.c | 3 + dlls/wined3d/glsl_shader.c | 3 +- dlls/wined3d/vertexdeclaration.c | 36 +------ dlls/wined3d/vertexshader.c | 166 +----------------------------- dlls/wined3d/wined3d_private.h | 17 +-- include/wine/wined3d.idl | 2 + 7 files changed, 18 insertions(+), 212 deletions(-) diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index efb3cb8007e..cd6ba29a0b9 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -510,8 +510,7 @@ static void vshader_program_add_param(const SHADER_OPCODE_ARG *arg, const DWORD break; case WINED3DSPR_INPUT: - if (vshader_input_is_color((IWineD3DVertexShader*) This, reg)) - is_color = TRUE; + if (This->swizzle_map & (1 << reg)) is_color = TRUE; sprintf(tmpReg, "vertex.attrib[%u]", reg); strcat(hwLine, tmpReg); diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c index 7d87ca15fef..70ba80b1af3 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -158,6 +158,7 @@ void primitiveDeclarationConvertToStridedData( } /* Translate the declaration into strided data */ + strided->swizzle_map = 0; for (i = 0 ; i < vertexDeclaration->declarationWNumElements - 1; ++i) { GLint streamVBO = 0; BOOL stride_used; @@ -234,6 +235,8 @@ void primitiveDeclarationConvertToStridedData( strided->u.input[idx].dwStride = stride; strided->u.input[idx].VBO = streamVBO; strided->u.input[idx].streamNo = element->Stream; + if (element->Type == WINED3DDECLTYPE_D3DCOLOR) strided->swizzle_map |= 1 << idx; + strided->use_map |= 1 << idx; } } } diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index eb169e0ef9c..0acdcad5457 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -1030,8 +1030,7 @@ static void shader_glsl_get_register_name(const DWORD param, const DWORD addr_to strcpy(tmpStr, "gl_SecondaryColor"); } } else { - if (vshader_input_is_color((IWineD3DVertexShader*) This, reg)) - *is_color = TRUE; + if (((IWineD3DVertexShaderImpl *)This)->swizzle_map & (1 << reg)) *is_color = TRUE; sprintf(tmpStr, "attrib%u", reg); } break; diff --git a/dlls/wined3d/vertexdeclaration.c b/dlls/wined3d/vertexdeclaration.c index 7fc711b4521..f63e2e7ed23 100644 --- a/dlls/wined3d/vertexdeclaration.c +++ b/dlls/wined3d/vertexdeclaration.c @@ -207,7 +207,7 @@ static HRESULT WINAPI IWineD3DVertexDeclarationImpl_SetDeclaration(IWineD3DVerte const WINED3DVERTEXELEMENT *elements, UINT element_count) { IWineD3DVertexDeclarationImpl *This = (IWineD3DVertexDeclarationImpl *)iface; HRESULT hr = WINED3D_OK; - int i, j; + int i; char isPreLoaded[MAX_STREAMS]; TRACE("(%p) : d3d version %d\n", This, ((IWineD3DImpl *)This->wineD3DDevice->wineD3D)->dxVersion); @@ -263,39 +263,13 @@ static HRESULT WINAPI IWineD3DVertexDeclarationImpl_SetDeclaration(IWineD3DVerte isPreLoaded[This->pDeclarationWine[i].Stream] = 1; } - /* Create a sorted array containing the attribute declarations that are of type - * D3DCOLOR. D3DCOLOR requires swizzling of the r and b component, and if the - * declaration of one attribute changes the vertex shader needs recompilation. - * Having a sorted array of the attributes allows efficient comparison of the - * declaration against a shader - */ - if(This->pDeclarationWine[i].Type == WINED3DDECLTYPE_D3DCOLOR) { - for(j = 0; j < This->num_swizzled_attribs; j++) { - if(This->swizzled_attribs[j].usage > This->pDeclarationWine[i].Usage || - (This->swizzled_attribs[j].usage == This->pDeclarationWine[i].Usage && - This->swizzled_attribs[j].idx > This->pDeclarationWine[i].UsageIndex)) { - memmove(&This->swizzled_attribs[j + 1], &This->swizzled_attribs[j], - sizeof(This->swizzled_attribs) - (sizeof(This->swizzled_attribs[0]) * (j + 1))); - break; - } - } - - This->swizzled_attribs[j].usage = This->pDeclarationWine[i].Usage; - This->swizzled_attribs[j].idx = This->pDeclarationWine[i].UsageIndex; - This->num_swizzled_attribs++; - } else if(This->pDeclarationWine[i].Type == WINED3DDECLTYPE_FLOAT16_2 || - This->pDeclarationWine[i].Type == WINED3DDECLTYPE_FLOAT16_4) { - if(!GL_SUPPORT(NV_HALF_FLOAT)) { - This->half_float_conv_needed = TRUE; - } + if (This->pDeclarationWine[i].Type == WINED3DDECLTYPE_FLOAT16_2 + || This->pDeclarationWine[i].Type == WINED3DDECLTYPE_FLOAT16_4) + { + if (!GL_SUPPORT(NV_HALF_FLOAT)) This->half_float_conv_needed = TRUE; } } - TRACE("Swizzled attributes found:\n"); - for(i = 0; i < This->num_swizzled_attribs; i++) { - TRACE("%u: %s%d\n", i, - debug_d3ddeclusage(This->swizzled_attribs[i].usage), This->swizzled_attribs[i].idx); - } TRACE("Returning\n"); return hr; } diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c index 9091c8a9968..339d955e230 100644 --- a/dlls/wined3d/vertexshader.c +++ b/dlls/wined3d/vertexshader.c @@ -218,113 +218,15 @@ BOOL vshader_get_input( return FALSE; } -BOOL vshader_input_is_color( - IWineD3DVertexShader* iface, - unsigned int regnum) { - - IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl*) iface; - - DWORD usage_token = This->semantics_in[regnum].usage; - DWORD usage = (usage_token & WINED3DSP_DCL_USAGE_MASK) >> WINED3DSP_DCL_USAGE_SHIFT; - DWORD usage_idx = (usage_token & WINED3DSP_DCL_USAGEINDEX_MASK) >> WINED3DSP_DCL_USAGEINDEX_SHIFT; - - int i; - - for(i = 0; i < This->num_swizzled_attribs; i++) { - if(This->swizzled_attribs[i].usage == usage && - This->swizzled_attribs[i].idx == usage_idx) { - return TRUE; - } - } - return FALSE; -} - -static inline void find_swizzled_attribs(IWineD3DVertexDeclaration *declaration, IWineD3DVertexShaderImpl *This) { - UINT num = 0, i, j; - UINT numoldswizzles = This->num_swizzled_attribs; - IWineD3DVertexDeclarationImpl *decl = (IWineD3DVertexDeclarationImpl *) declaration; - - DWORD usage_token, usage, usage_idx; - BOOL found; - - attrib_declaration oldswizzles[sizeof(This->swizzled_attribs) / sizeof(This->swizzled_attribs[0])]; - - /* Back up the old swizzles to keep attributes that are undefined in the current declaration */ - memcpy(oldswizzles, This->swizzled_attribs, sizeof(oldswizzles)); - - memset(This->swizzled_attribs, 0, sizeof(This->swizzled_attribs[0]) * MAX_ATTRIBS); - - for(i = 0; i < decl->num_swizzled_attribs; i++) { - for(j = 0; j < MAX_ATTRIBS; j++) { - - if(!This->baseShader.reg_maps.attributes[j]) continue; - - usage_token = This->semantics_in[j].usage; - usage = (usage_token & WINED3DSP_DCL_USAGE_MASK) >> WINED3DSP_DCL_USAGE_SHIFT; - usage_idx = (usage_token & WINED3DSP_DCL_USAGEINDEX_MASK) >> WINED3DSP_DCL_USAGEINDEX_SHIFT; - - if(decl->swizzled_attribs[i].usage == usage && - decl->swizzled_attribs[i].idx == usage_idx) { - This->swizzled_attribs[num].usage = usage; - This->swizzled_attribs[num].idx = usage_idx; - num++; - } - } - } - - /* Add previously converted attributes back in if they are not defined in the current declaration */ - for(i = 0; i < numoldswizzles; i++) { - - found = FALSE; - for(j = 0; j < decl->declarationWNumElements; j++) { - if(oldswizzles[i].usage == decl->pDeclarationWine[j].Usage && - oldswizzles[i].idx == decl->pDeclarationWine[j].UsageIndex) { - found = TRUE; - } - } - if(found) { - /* This previously converted attribute is declared in the current declaration. Either it is - * already in the new array, or it should not be there. Skip it - */ - continue; - } - /* We have a previously swizzled attribute that is not defined by the current vertex declaration. - * Insert it into the new conversion array to keep it in the old defined state. Otherwise we end up - * recompiling if the old decl is used again because undefined attributes are reset to no swizzling. - * In the reverse way(attribute was not swizzled and is not declared in new declaration) the attrib - * stays unswizzled as well because it isn't found in the oldswizzles array - */ - for(j = 0; j < num; j++) { - if(oldswizzles[i].usage > This->swizzled_attribs[j].usage || ( - oldswizzles[i].usage == This->swizzled_attribs[j].usage && - oldswizzles[i].idx > This->swizzled_attribs[j].idx)) { - memmove(&This->swizzled_attribs[j + 1], &This->swizzled_attribs[j], - sizeof(This->swizzled_attribs) - (sizeof(This->swizzled_attribs[0]) * (j + 1))); - break; - } - } - This->swizzled_attribs[j].usage = oldswizzles[i].usage; - This->swizzled_attribs[j].idx = oldswizzles[i].idx; - num++; - } - - TRACE("New swizzled attributes array\n"); - for(i = 0; i < num; i++) { - TRACE("%d: %s(%d), %d\n", i, debug_d3ddeclusage(This->swizzled_attribs[i].usage), - This->swizzled_attribs[i].usage, This->swizzled_attribs[i].idx); - } - This->num_swizzled_attribs = num; -} /** Generate a vertex shader string using either GL_VERTEX_PROGRAM_ARB or GLSL and send it to the card */ static void IWineD3DVertexShaderImpl_GenerateShader(IWineD3DVertexShader *iface, const struct shader_reg_maps* reg_maps, const DWORD *pFunction) { IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface; - IWineD3DVertexDeclaration *decl = ((IWineD3DDeviceImpl *) This->baseShader.device)->stateBlock->vertexDecl; SHADER_BUFFER buffer; - find_swizzled_attribs(decl, This); + This->swizzle_map = ((IWineD3DDeviceImpl *)This->baseShader.device)->strided_streams.swizzle_map; shader_buffer_init(&buffer); ((IWineD3DDeviceImpl *)This->baseShader.device)->shader_backend->shader_generate_vshader(iface, &buffer); @@ -516,56 +418,8 @@ static HRESULT WINAPI IWIneD3DVertexShaderImpl_SetLocalConstantsF(IWineD3DVertex return WINED3D_OK; } -static inline BOOL swizzled_attribs_differ(IWineD3DVertexShaderImpl *This, IWineD3DVertexDeclarationImpl *vdecl) { - UINT i, j, k; - BOOL found; - - DWORD usage_token; - DWORD usage; - DWORD usage_idx; - - for(i = 0; i < vdecl->declarationWNumElements; i++) { - /* Ignore tesselated streams and the termination entry(position0, stream 255, unused) */ - if(vdecl->pDeclarationWine[i].Stream >= MAX_STREAMS || - vdecl->pDeclarationWine[i].Type == WINED3DDECLTYPE_UNUSED) continue; - - for(j = 0; j < MAX_ATTRIBS; j++) { - if(!This->baseShader.reg_maps.attributes[j]) continue; - - usage_token = This->semantics_in[j].usage; - usage = (usage_token & WINED3DSP_DCL_USAGE_MASK) >> WINED3DSP_DCL_USAGE_SHIFT; - usage_idx = (usage_token & WINED3DSP_DCL_USAGEINDEX_MASK) >> WINED3DSP_DCL_USAGEINDEX_SHIFT; - - if(vdecl->pDeclarationWine[i].Usage != usage || - vdecl->pDeclarationWine[i].UsageIndex != usage_idx) { - continue; - } - - found = FALSE; - for(k = 0; k < This->num_swizzled_attribs; k++) { - if(This->swizzled_attribs[k].usage == usage && - This->swizzled_attribs[k].idx == usage_idx) { - found = TRUE; - } - } - if(!found && vdecl->pDeclarationWine[i].Type == WINED3DDECLTYPE_D3DCOLOR) { - TRACE("Attribute %s%d is D3DCOLOR now but wasn't before\n", - debug_d3ddeclusage(usage), usage_idx); - return TRUE; - } - if( found && vdecl->pDeclarationWine[i].Type != WINED3DDECLTYPE_D3DCOLOR) { - TRACE("Attribute %s%d was D3DCOLOR before but is not any more\n", - debug_d3ddeclusage(usage), usage_idx); - return TRUE; - } - } - } - return FALSE; -} - HRESULT IWineD3DVertexShaderImpl_CompileShader(IWineD3DVertexShader *iface) { IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface; - IWineD3DVertexDeclarationImpl *vdecl; CONST DWORD *function = This->baseShader.function; IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *) This->baseShader.device; @@ -573,20 +427,10 @@ HRESULT IWineD3DVertexShaderImpl_CompileShader(IWineD3DVertexShader *iface) { /* We're already compiled. */ if (This->baseShader.is_compiled) { - vdecl = (IWineD3DVertexDeclarationImpl *) deviceImpl->stateBlock->vertexDecl; - - if(This->num_swizzled_attribs != vdecl->num_swizzled_attribs || - memcmp(This->swizzled_attribs, vdecl->swizzled_attribs, sizeof(vdecl->swizzled_attribs[0]) * This->num_swizzled_attribs) != 0) { - - /* The swizzled attributes differ between shader and declaration. This doesn't necessarily mean - * we have to recompile, but we have to take a deeper look at see if the attribs that differ - * are declared in the decl and used in the shader - */ - if(swizzled_attribs_differ(This, vdecl)) { - WARN("Recompiling vertex shader %p due to D3DCOLOR input changes\n", This); - goto recompile; - } - WARN("Swizzled attribute validation required an expensive comparison\n"); + if ((This->swizzle_map & deviceImpl->strided_streams.use_map) != deviceImpl->strided_streams.swizzle_map) + { + WARN("Recompiling vertex shader %p due to D3DCOLOR input changes\n", This); + goto recompile; } return WINED3D_OK; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index cab2b20755e..89c5d7769b1 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1711,11 +1711,6 @@ BOOL palette9_changed(IWineD3DSurfaceImpl *This); /***************************************************************************** * IWineD3DVertexDeclaration implementation structure */ -typedef struct attrib_declaration { - DWORD usage; - DWORD idx; -} attrib_declaration; - #define MAX_ATTRIBS 16 typedef struct IWineD3DVertexDeclarationImpl { @@ -1734,10 +1729,6 @@ typedef struct IWineD3DVertexDeclarationImpl { UINT num_streams; BOOL position_transformed; BOOL half_float_conv_needed; - - /* Ordered array of declaration types that need swizzling in a vshader */ - attrib_declaration swizzled_attribs[MAX_ATTRIBS]; - UINT num_swizzled_attribs; } IWineD3DVertexDeclarationImpl; extern const IWineD3DVertexDeclarationVtbl IWineD3DVertexDeclaration_Vtbl; @@ -2182,10 +2173,6 @@ extern BOOL vshader_get_input( BYTE usage_req, BYTE usage_idx_req, unsigned int* regnum); -extern BOOL vshader_input_is_color( - IWineD3DVertexShader* iface, - unsigned int regnum); - extern HRESULT allocate_shader_constants(IWineD3DStateBlockImpl* object); /* GLSL helper functions */ @@ -2337,9 +2324,7 @@ typedef struct IWineD3DVertexShaderImpl { semantic semantics_in [MAX_ATTRIBS]; semantic semantics_out [MAX_REG_OUTPUT]; - /* Ordered array of attributes that are swizzled */ - attrib_declaration swizzled_attribs [MAX_ATTRIBS]; - UINT num_swizzled_attribs; + WORD swizzle_map; /* MAX_ATTRIBS, 16 */ UINT min_rel_offset, max_rel_offset; UINT rel_offset; diff --git a/include/wine/wined3d.idl b/include/wine/wined3d.idl index 0ee7b1f8f0d..b43a8e75b6d 100644 --- a/include/wine/wined3d.idl +++ b/include/wine/wined3d.idl @@ -1884,6 +1884,8 @@ typedef struct WineDirect3DVertexStridedData } u; BOOL position_transformed; + WORD swizzle_map; /* MAX_ATTRIBS, 16 */ + WORD use_map; /* MAX_ATTRIBS, 16 */ } WineDirect3DVertexStridedData; typedef struct _WINED3DVSHADERCAPS2_0