diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index e4d7e4d26ab..a8f92fcbcc9 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -340,18 +340,9 @@ static void vshader_program_add_param(SHADER_OPCODE_ARG *arg, const DWORD param, break; case D3DSPR_INPUT: - if (This->semantics_in[WINED3DSHADERDECLUSAGE_DIFFUSE] && - reg == (This->semantics_in[WINED3DSHADERDECLUSAGE_DIFFUSE] & D3DSP_REGNUM_MASK)) + if (vshader_input_is_color((IWineD3DVertexShader*) This, reg)) is_color = TRUE; - if (This->semantics_in[WINED3DSHADERDECLUSAGE_SPECULAR] && - reg == (This->semantics_in[WINED3DSHADERDECLUSAGE_SPECULAR] & D3DSP_REGNUM_MASK)) - is_color = TRUE; - - /* FIXME: Shaders in 8.1 appear to not require a dcl statement - use - * the reg value from the vertex declaration. However, semantics are not initialized - * in that case - how can we know if an input contains color data or not? */ - sprintf(tmpReg, "vertex.attrib[%lu]", reg); strcat(hwLine, tmpReg); break; diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c index 8ed85efa63c..b7aa45f0ffb 100644 --- a/dlls/wined3d/baseshader.c +++ b/dlls/wined3d/baseshader.c @@ -171,132 +171,14 @@ unsigned int shader_get_float_offset(const DWORD reg) { } } -static void shader_parse_decl_usage( - DWORD *semantics_map, - DWORD usage_token, DWORD param) { - - unsigned int usage = (usage_token & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT; - unsigned int usage_idx = (usage_token & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT; - unsigned int regnum = param & D3DSP_REGNUM_MASK; - - switch(usage) { - case D3DDECLUSAGE_POSITION: - if (usage_idx == 0) { /* tween data */ - TRACE("Setting position to %d\n", regnum); - semantics_map[WINED3DSHADERDECLUSAGE_POSITION] = param; - } else { - /* TODO: position indexes go from 0-8!!*/ - TRACE("Setting position 2 to %d because usage_idx = %d\n", regnum, usage_idx); - /* robots uses positions up to 8, the position arrays are just packed.*/ - if (usage_idx > 1) { - TRACE("Loaded for position %d (greater than 2)\n", usage_idx); - } - semantics_map[WINED3DSHADERDECLUSAGE_POSITION2 + usage_idx-1] = param; - } - break; - - case D3DDECLUSAGE_BLENDINDICES: - TRACE("Setting BLENDINDICES to %d\n", regnum); - semantics_map[WINED3DSHADERDECLUSAGE_BLENDINDICES] = param; - if (usage_idx != 0) FIXME("Extended BLENDINDICES\n"); - break; - - case D3DDECLUSAGE_BLENDWEIGHT: - TRACE("Setting BLENDWEIGHT to %d\n", regnum); - semantics_map[WINED3DSHADERDECLUSAGE_BLENDWEIGHT] = param; - if (usage_idx != 0) FIXME("Extended blend weights\n"); - break; - - case D3DDECLUSAGE_NORMAL: - if (usage_idx == 0) { /* tween data */ - TRACE("Setting normal to %d\n", regnum); - semantics_map[WINED3DSHADERDECLUSAGE_NORMAL] = param; - } else { - TRACE("Setting normal 2 to %d because usage = %d\n", regnum, usage_idx); - semantics_map[WINED3DSHADERDECLUSAGE_NORMAL2] = param; - } - break; - - case D3DDECLUSAGE_PSIZE: - TRACE("Setting PSIZE to %d\n", regnum); - semantics_map[WINED3DSHADERDECLUSAGE_PSIZE] = param; - if (usage_idx != 0) FIXME("Extended PSIZE\n"); - break; - - case D3DDECLUSAGE_COLOR: - if (usage_idx == 0) { - TRACE("Setting DIFFUSE to %d\n", regnum); - semantics_map[WINED3DSHADERDECLUSAGE_DIFFUSE] = param; - } else { - TRACE("Setting SPECULAR to %d\n", regnum); - semantics_map[WINED3DSHADERDECLUSAGE_SPECULAR] = param; - } - break; - - case D3DDECLUSAGE_TEXCOORD: - if (usage_idx > 7) { - FIXME("Program uses texture coordinate %d but only 0-7 have been " - "implemented\n", usage_idx); - } else { - TRACE("Setting TEXCOORD %d to %d\n", usage_idx, regnum); - semantics_map[WINED3DSHADERDECLUSAGE_TEXCOORD0 + usage_idx] = param; - } - break; - - case D3DDECLUSAGE_TANGENT: - TRACE("Setting TANGENT to %d\n", regnum); - semantics_map[WINED3DSHADERDECLUSAGE_TANGENT] = param; - break; - - case D3DDECLUSAGE_BINORMAL: - TRACE("Setting BINORMAL to %d\n", regnum); - semantics_map[WINED3DSHADERDECLUSAGE_BINORMAL] = param; - break; - - case D3DDECLUSAGE_TESSFACTOR: - TRACE("Setting TESSFACTOR to %d\n", regnum); - semantics_map[WINED3DSHADERDECLUSAGE_TESSFACTOR] = param; - break; - - case D3DDECLUSAGE_POSITIONT: - if (usage_idx == 0) { /* tween data */ - FIXME("Setting positiont to %d\n", regnum); - semantics_map[WINED3DSHADERDECLUSAGE_POSITIONT] = param; - } else { - FIXME("Setting positiont 2 to %d because usage = %d\n", regnum, usage_idx); - semantics_map[WINED3DSHADERDECLUSAGE_POSITIONT2] = param; - if (usage_idx != 0) FIXME("Extended positiont\n"); - } - break; - - case D3DDECLUSAGE_FOG: - TRACE("Setting FOG to %d\n", regnum); - semantics_map[WINED3DSHADERDECLUSAGE_FOG] = param; - break; - - case D3DDECLUSAGE_DEPTH: - TRACE("Setting DEPTH to %d\n", regnum); - semantics_map[WINED3DSHADERDECLUSAGE_DEPTH] = param; - break; - - case D3DDECLUSAGE_SAMPLE: - TRACE("Setting SAMPLE to %d\n", regnum); - semantics_map[WINED3DSHADERDECLUSAGE_SAMPLE] = param; - break; - - default: - FIXME("Unrecognised dcl %#x", usage); - } -} - /* Note that this does not count the loop register * as an address register. */ void shader_get_registers_used( IWineD3DBaseShader *iface, shader_reg_maps* reg_maps, - DWORD* semantics_in, - DWORD* semantics_out, + semantic* semantics_in, + semantic* semantics_out, CONST DWORD* pToken) { IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface; @@ -350,12 +232,14 @@ void shader_get_registers_used( else reg_maps->packed_input[regnum] = 1; - shader_parse_decl_usage(semantics_in, usage, param); + semantics_in[regnum].usage = usage; + semantics_in[regnum].reg = param; /* Vshader: mark 3.0 output registers used, save token */ } else if (D3DSPR_OUTPUT == regtype) { reg_maps->packed_output[regnum] = 1; - shader_parse_decl_usage(semantics_out, usage, param); + semantics_out[regnum].usage = usage; + semantics_out[regnum].reg = param; /* Save sampler usage token */ } else if (D3DSPR_SAMPLER == regtype) diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c index 67efd03697d..25e2c1e0332 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -464,7 +464,12 @@ void primitiveDeclarationConvertToStridedData( checkGLcall("glEnableVertexAttribArrayARB"); } - stride_used = fixed_get_input(element->Usage, element->UsageIndex, &idx); + if (useVertexShaderFunction) + stride_used = vshader_get_input(This->stateBlock->vertexShader, + element->Usage, element->UsageIndex, &idx); + else + stride_used = fixed_get_input(element->Usage, element->UsageIndex, &idx); + if (stride_used) { TRACE("Loaded %s array %u [usage=%s, usage_idx=%u, " "stream=%u, offset=%u, stride=%lu, VBO=%u]\n", @@ -476,10 +481,12 @@ void primitiveDeclarationConvertToStridedData( strided->u.input[idx].dwType = element->Type; strided->u.input[idx].dwStride = stride; strided->u.input[idx].VBO = streamVBO; - if (element->Usage == D3DDECLUSAGE_POSITION) - strided->u.s.position_transformed = FALSE; - else if (element->Usage == D3DDECLUSAGE_POSITIONT) - strided->u.s.position_transformed = TRUE; + if (!useVertexShaderFunction) { + if (element->Usage == D3DDECLUSAGE_POSITION) + strided->u.s.position_transformed = FALSE; + else if (element->Usage == D3DDECLUSAGE_POSITIONT) + strided->u.s.position_transformed = TRUE; + } } }; } @@ -794,105 +801,35 @@ static void draw_vertex(IWineD3DDevice *iface, /* interf } #endif /* TODO: Software shaders */ -void loadNumberedArrays( - IWineD3DDevice *iface, - WineDirect3DVertexStridedData *sd, - DWORD arrayUsageMap[WINED3DSHADERDECLUSAGE_MAX_USAGE]) { +static void loadNumberedArrays( + IWineD3DDevice *iface, + IWineD3DVertexShader *shader, + WineDirect3DVertexStridedData *strided) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; GLint curVBO = -1; + int i; -#define LOAD_NUMBERED_ARRAY(_arrayName, _lookupName) \ - if ((sd->u.s._arrayName.lpData != NULL || sd->u.s._arrayName.VBO != 0) && arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName]) { \ - unsigned int idx = arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName] & D3DSP_REGNUM_MASK; \ - TRACE_(d3d_shader)("Loading array %u with data from %s\n", idx, #_arrayName); \ - if(curVBO != sd->u.s._arrayName.VBO) { \ - GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s._arrayName.VBO)); \ - checkGLcall("glBindBufferARB"); \ - curVBO = sd->u.s._arrayName.VBO; \ - } \ - GL_EXTCALL(glVertexAttribPointerARB(idx, \ - WINED3D_ATR_SIZE(sd->u.s._arrayName.dwType), \ - WINED3D_ATR_GLTYPE(sd->u.s._arrayName.dwType), \ - WINED3D_ATR_NORMALIZED(sd->u.s._arrayName.dwType), \ - sd->u.s._arrayName.dwStride, \ - sd->u.s._arrayName.lpData)); \ - GL_EXTCALL(glEnableVertexAttribArrayARB(idx)); \ - } + for (i = 0; i < MAX_ATTRIBS; i++) { + if (!strided->u.input[i].lpData && !strided->u.input[i].VBO) + continue; -#define LOAD_NUMBERED_POSITION_ARRAY(_lookupNumber) \ - if ((sd->u.s.position2.lpData != NULL || sd->u.s.position2.VBO != 0)&& arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber]) { \ - unsigned int idx = arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber] & D3DSP_REGNUM_MASK; \ - TRACE_(d3d_shader)("Loading array %u with data from %s\n", idx, "position2"); \ - if(curVBO != sd->u.s.position2.VBO) { \ - GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position2.VBO)); \ - checkGLcall("glBindBufferARB"); \ - curVBO = sd->u.s.position2.VBO; \ - } \ - GL_EXTCALL(glVertexAttribPointerARB(idx, \ - WINED3D_ATR_SIZE(sd->u.s.position2.dwType), \ - WINED3D_ATR_GLTYPE(sd->u.s.position2.dwType), \ - WINED3D_ATR_NORMALIZED(sd->u.s.position2.dwType), \ - sd->u.s.position2.dwStride, \ - ((char *)sd->u.s.position2.lpData) + \ - WINED3D_ATR_SIZE(sd->u.s.position2.dwType) * \ - WINED3D_ATR_TYPESIZE(sd->u.s.position2.dwType) * _lookupNumber)); \ - GL_EXTCALL(glEnableVertexAttribArrayARB(idx)); \ - } + TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, strided->u.input[i].VBO); -/* Generate some lookup tables */ - /* drop the RHW coord, there must be a nicer way of doing this. */ - sd->u.s.position.dwType = min(D3DDECLTYPE_FLOAT3, sd->u.s.position.dwType); - sd->u.s.position2.dwType = min(D3DDECLTYPE_FLOAT3, sd->u.s.position2.dwType); - - LOAD_NUMBERED_ARRAY(blendWeights,BLENDWEIGHT); - LOAD_NUMBERED_ARRAY(blendMatrixIndices,BLENDINDICES); - LOAD_NUMBERED_ARRAY(position,POSITION); - LOAD_NUMBERED_ARRAY(normal,NORMAL); - LOAD_NUMBERED_ARRAY(pSize,PSIZE); - LOAD_NUMBERED_ARRAY(diffuse,DIFFUSE); - LOAD_NUMBERED_ARRAY(specular,SPECULAR); - LOAD_NUMBERED_ARRAY(texCoords[0],TEXCOORD0); - LOAD_NUMBERED_ARRAY(texCoords[1],TEXCOORD1); - LOAD_NUMBERED_ARRAY(texCoords[2],TEXCOORD2); - LOAD_NUMBERED_ARRAY(texCoords[3],TEXCOORD3); - LOAD_NUMBERED_ARRAY(texCoords[4],TEXCOORD4); - LOAD_NUMBERED_ARRAY(texCoords[5],TEXCOORD5); - LOAD_NUMBERED_ARRAY(texCoords[6],TEXCOORD6); - LOAD_NUMBERED_ARRAY(texCoords[7],TEXCOORD7); -#if 0 /* TODO: Samplers may allow for more texture coords */ - LOAD_NUMBERED_ARRAY(texCoords[8],TEXCOORD8); - LOAD_NUMBERED_ARRAY(texCoords[9],TEXCOORD9); - LOAD_NUMBERED_ARRAY(texCoords[10],TEXCOORD10); - LOAD_NUMBERED_ARRAY(texCoords[11],TEXCOORD11); - LOAD_NUMBERED_ARRAY(texCoords[12],TEXCOORD12); - LOAD_NUMBERED_ARRAY(texCoords[13],TEXCOORD13); - LOAD_NUMBERED_ARRAY(texCoords[14],TEXCOORD14); - LOAD_NUMBERED_ARRAY(texCoords[15],TEXCOORD15); -#endif - LOAD_NUMBERED_ARRAY(position,POSITIONT); - /* d3d9 types */ - LOAD_NUMBERED_ARRAY(tangent,TANGENT); - LOAD_NUMBERED_ARRAY(binormal,BINORMAL); - LOAD_NUMBERED_ARRAY(tessFactor,TESSFACTOR); - LOAD_NUMBERED_ARRAY(position2,POSITION2); - /* there can be lots of position arrays */ - LOAD_NUMBERED_POSITION_ARRAY(0); - LOAD_NUMBERED_POSITION_ARRAY(1); - LOAD_NUMBERED_POSITION_ARRAY(2); - LOAD_NUMBERED_POSITION_ARRAY(3); - LOAD_NUMBERED_POSITION_ARRAY(4); - LOAD_NUMBERED_POSITION_ARRAY(5); - LOAD_NUMBERED_POSITION_ARRAY(6); - LOAD_NUMBERED_POSITION_ARRAY(7); - LOAD_NUMBERED_ARRAY(position2,POSITIONT2); - LOAD_NUMBERED_ARRAY(normal2,NORMAL2); - LOAD_NUMBERED_ARRAY(fog,FOG); - LOAD_NUMBERED_ARRAY(depth,DEPTH); - LOAD_NUMBERED_ARRAY(sample,SAMPLE); - -#undef LOAD_NUMBERED_ARRAY + if(curVBO != strided->u.input[i].VBO) { + GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, strided->u.input[i].VBO)); + checkGLcall("glBindBufferARB"); + curVBO = strided->u.input[i].VBO; + } + GL_EXTCALL(glVertexAttribPointerARB(i, + WINED3D_ATR_SIZE(strided->u.input[i].dwType), + WINED3D_ATR_GLTYPE(strided->u.input[i].dwType), + WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType), + strided->u.input[i].dwStride, + strided->u.input[i].lpData)); + GL_EXTCALL(glEnableVertexAttribArrayARB(i)); + } } static void loadVertexData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd) { @@ -1803,8 +1740,7 @@ inline static void drawPrimitiveDrawStrided( /* Shader pipeline - load attribute arrays */ } else if(useVertexShaderFunction) { - loadNumberedArrays(iface, dataLocations, - ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->semantics_in); + loadNumberedArrays(iface, This->stateBlock->vertexShader, dataLocations); useDrawStridedSlow = FALSE; /* Draw vertex by vertex */ @@ -2147,11 +2083,21 @@ void drawPrimitive(IWineD3DDevice *iface, ENTER_GL(); if(DrawPrimStrideData) { + + /* Note: this is a ddraw fixed-function code path */ + TRACE("================ Strided Input ===================\n"); dataLocations = DrawPrimStrideData; + drawPrimitiveTraceDataLocations(dataLocations); fixup = FALSE; } - else if (This->stateBlock->vertexDecl != NULL || (useVertexShaderFunction && NULL != ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration)) { + + else if (This->stateBlock->vertexDecl != NULL || useVertexShaderFunction) { + + /* Note: This is a fixed function or shader codepath. + * This means it must handle both types of strided data. + * Shaders must go through here to zero the strided data, even if they + * don't set any declaration at all */ TRACE("================ Vertex Declaration ===================\n"); dataLocations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dataLocations)); @@ -2159,9 +2105,19 @@ void drawPrimitive(IWineD3DDevice *iface, ERR("Out of memory!\n"); return; } - primitiveDeclarationConvertToStridedData(iface, useVertexShaderFunction, dataLocations, StartVertexIndex, &fixup); + + if (This->stateBlock->vertexDecl != NULL || + ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration != NULL) + + primitiveDeclarationConvertToStridedData(iface, useVertexShaderFunction, + dataLocations, StartVertexIndex, &fixup); } else { + + /* Note: This codepath is not reachable from d3d9 (see fvf->decl9 conversion) + * It is reachable through d3d8, but only for fixed-function. + * It will not work properly for shaders. */ + TRACE("================ FVF ===================\n"); dataLocations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dataLocations)); if(!dataLocations) { @@ -2169,11 +2125,9 @@ void drawPrimitive(IWineD3DDevice *iface, return; } primitiveConvertToStridedData(iface, dataLocations, StartVertexIndex, &fixup); + drawPrimitiveTraceDataLocations(dataLocations); } - /* write out some debug information*/ - drawPrimitiveTraceDataLocations(dataLocations); - /* Setup transform matrices and sort out */ primitiveInitState(iface, dataLocations, useVertexShaderFunction, &lighting_changed, &lighting_original); diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index e7ba3493651..215090c9b13 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -501,20 +501,8 @@ static void shader_glsl_get_register_name( strcpy(tmpStr, "gl_SecondaryColor"); } } else { - IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl*) arg->shader; - - if (This->semantics_in[WINED3DSHADERDECLUSAGE_DIFFUSE] && - reg == (This->semantics_in[WINED3DSHADERDECLUSAGE_DIFFUSE] & D3DSP_REGNUM_MASK)) - *is_color = TRUE; - - if (This->semantics_in[WINED3DSHADERDECLUSAGE_SPECULAR] && - reg == (This->semantics_in[WINED3DSHADERDECLUSAGE_SPECULAR] & D3DSP_REGNUM_MASK)) - *is_color = TRUE; - - /* FIXME: Shaders in 8.1 appear to not require a dcl statement - use - * the reg value from the vertex declaration. However, semantics are not initialized - * in that case - how can we know if an input contains color data or not? */ - + if (vshader_input_is_color((IWineD3DVertexShader*) This, reg)) + *is_color = TRUE; sprintf(tmpStr, "attrib%lu", reg); } break; @@ -1390,53 +1378,50 @@ void pshader_glsl_dp2add(SHADER_OPCODE_ARG* arg) { void pshader_glsl_input_pack( SHADER_BUFFER* buffer, - DWORD* semantics_in) { + semantic* semantics_in) { unsigned int i; - for (i = 0; i < WINED3DSHADERDECLUSAGE_MAX_USAGE; i++) { + for (i = 0; i < MAX_REG_INPUT; i++) { - DWORD reg = semantics_in[i]; - unsigned int regnum = reg & D3DSP_REGNUM_MASK; + DWORD usage_token = semantics_in[i].usage; + DWORD register_token = semantics_in[i].reg; + DWORD usage, usage_idx; char reg_mask[6]; /* Uninitialized */ - if (!reg) continue; + if (!usage_token) continue; + usage = (usage_token & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT; + usage_idx = (usage_token & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT; + shader_glsl_get_output_register_swizzle(register_token, reg_mask); - shader_glsl_get_output_register_swizzle(reg, reg_mask); + switch(usage) { - switch(i) { - - case WINED3DSHADERDECLUSAGE_DIFFUSE: - shader_addline(buffer, "IN%lu%s = vec4(gl_Color)%s;\n", - regnum, reg_mask, reg_mask); + case D3DDECLUSAGE_COLOR: + if (usage_idx == 0) + shader_addline(buffer, "IN%lu%s = vec4(gl_Color)%s;\n", + i, reg_mask, reg_mask); + if (usage_idx == 1) + shader_addline(buffer, "IN%lu%s = vec4(gl_SecondaryColor)%s;\n", + i, reg_mask, reg_mask); + else + shader_addline(buffer, "IN%lu%s = vec4(unsupported_color_input)%s;\n", + i, reg_mask, reg_mask); break; - case WINED3DSHADERDECLUSAGE_SPECULAR: - shader_addline(buffer, "IN%lu%s = vec4(gl_SecondaryColor)%s;\n", - regnum, reg_mask, reg_mask); - break; - - case WINED3DSHADERDECLUSAGE_TEXCOORD0: - case WINED3DSHADERDECLUSAGE_TEXCOORD1: - case WINED3DSHADERDECLUSAGE_TEXCOORD2: - case WINED3DSHADERDECLUSAGE_TEXCOORD3: - case WINED3DSHADERDECLUSAGE_TEXCOORD4: - case WINED3DSHADERDECLUSAGE_TEXCOORD5: - case WINED3DSHADERDECLUSAGE_TEXCOORD6: - case WINED3DSHADERDECLUSAGE_TEXCOORD7: + case D3DDECLUSAGE_TEXCOORD: shader_addline(buffer, "IN%lu%s = vec4(gl_TexCoord[%lu])%s;\n", - regnum, reg_mask, i - WINED3DSHADERDECLUSAGE_TEXCOORD0, reg_mask ); + i, reg_mask, usage_idx, reg_mask ); break; - case WINED3DSHADERDECLUSAGE_FOG: + case D3DDECLUSAGE_FOG: shader_addline(buffer, "IN%lu%s = vec4(gl_FogFragCoord)%s;\n", - regnum, reg_mask, reg_mask); + i, reg_mask, reg_mask); break; default: shader_addline(buffer, "IN%lu%s = vec4(unsupported_input)%s;\n", - regnum, reg_mask, reg_mask); + i, reg_mask, reg_mask); } } } @@ -1447,57 +1432,54 @@ void pshader_glsl_input_pack( void vshader_glsl_output_unpack( SHADER_BUFFER* buffer, - DWORD* semantics_out) { + semantic* semantics_out) { unsigned int i; - for (i = 0; i < WINED3DSHADERDECLUSAGE_MAX_USAGE; i++) { + for (i = 0; i < MAX_REG_OUTPUT; i++) { - DWORD reg = semantics_out[i]; - unsigned int regnum = reg & D3DSP_REGNUM_MASK; + DWORD usage_token = semantics_out[i].usage; + DWORD register_token = semantics_out[i].reg; + DWORD usage, usage_idx; char reg_mask[6]; /* Uninitialized */ - if (!reg) continue; + if (!usage_token) continue; - shader_glsl_get_output_register_swizzle(reg, reg_mask); + usage = (usage_token & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT; + usage_idx = (usage_token & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT; + shader_glsl_get_output_register_swizzle(register_token, reg_mask); - switch(i) { + switch(usage) { - case WINED3DSHADERDECLUSAGE_DIFFUSE: - shader_addline(buffer, "gl_FrontColor%s = OUT%lu%s;\n", reg_mask, regnum, reg_mask); + case D3DDECLUSAGE_COLOR: + if (usage_idx == 0) + shader_addline(buffer, "gl_FrontColor%s = OUT%lu%s;\n", reg_mask, i, reg_mask); + else if (usage_idx == 1) + shader_addline(buffer, "gl_FrontSecondaryColor%s = OUT%lu%s;\n", reg_mask, i, reg_mask); + else + shader_addline(buffer, "unsupported_color_output%s = OUT%lu%s;\n", reg_mask, i, reg_mask); break; - case WINED3DSHADERDECLUSAGE_SPECULAR: - shader_addline(buffer, "gl_FrontSecondaryColor%s = OUT%lu%s;\n", reg_mask, regnum, reg_mask); + case D3DDECLUSAGE_POSITION: + shader_addline(buffer, "gl_Position%s = OUT%lu%s;\n", reg_mask, i, reg_mask); break; - - case WINED3DSHADERDECLUSAGE_POSITION: - shader_addline(buffer, "gl_Position%s = OUT%lu%s;\n", reg_mask, regnum, reg_mask); - break; - - case WINED3DSHADERDECLUSAGE_TEXCOORD0: - case WINED3DSHADERDECLUSAGE_TEXCOORD1: - case WINED3DSHADERDECLUSAGE_TEXCOORD2: - case WINED3DSHADERDECLUSAGE_TEXCOORD3: - case WINED3DSHADERDECLUSAGE_TEXCOORD4: - case WINED3DSHADERDECLUSAGE_TEXCOORD5: - case WINED3DSHADERDECLUSAGE_TEXCOORD6: - case WINED3DSHADERDECLUSAGE_TEXCOORD7: + + case D3DDECLUSAGE_TEXCOORD: shader_addline(buffer, "gl_TexCoord[%lu]%s = OUT%lu%s;\n", - i - WINED3DSHADERDECLUSAGE_TEXCOORD0, reg_mask, regnum, reg_mask); + usage_idx, reg_mask, i, reg_mask); break; case WINED3DSHADERDECLUSAGE_PSIZE: - shader_addline(buffer, "gl_PointSize = OUT%lu.x;\n", regnum); + shader_addline(buffer, "gl_PointSize = OUT%lu.x;\n", i); break; case WINED3DSHADERDECLUSAGE_FOG: - shader_addline(buffer, "gl_FogFragCoord%s = OUT%lu%s;\n", reg_mask, regnum, reg_mask); + shader_addline(buffer, "gl_FogFragCoord%s = OUT%lu%s;\n", reg_mask, i, reg_mask); break; default: - shader_addline(buffer, "unsupported_output%s = OUT%lu%s;\n", reg_mask, regnum, reg_mask); - } - } + shader_addline(buffer, "unsupported_output%s = OUT%lu%s;\n", reg_mask, i, reg_mask); + } + } } diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c index df0fd9945ab..7d452d2f144 100644 --- a/dlls/wined3d/vertexshader.c +++ b/dlls/wined3d/vertexshader.c @@ -609,6 +609,37 @@ static void vshader_set_limits( } } +BOOL vshader_get_input( + IWineD3DVertexShader* iface, + BYTE usage_req, BYTE usage_idx_req, + unsigned int* regnum) { + + IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl*) iface; + int i; + + for (i = 0; i < MAX_ATTRIBS; i++) { + DWORD usage_token = This->semantics_in[i].usage; + DWORD usage = (usage_token & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT; + DWORD usage_idx = (usage_token & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT; + + if (usage_token && (usage == usage_req && usage_idx == usage_idx_req)) { + *regnum = i; + return TRUE; + } + } + 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 & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT; + return usage == D3DDECLUSAGE_COLOR; +} + /** Generate a vertex shader string using either GL_VERTEX_PROGRAM_ARB or GLSL and send it to the card */ static VOID IWineD3DVertexShaderImpl_GenerateShader( diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index b8a7c03001d..0f6d85e56ea 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1283,6 +1283,11 @@ struct glsl_shader_prog_link { #define MAX_CONST_I 16 #define MAX_CONST_B 16 +typedef struct semantic { + DWORD usage; + DWORD reg; +} semantic; + typedef struct shader_reg_maps { char texcoord[MAX_REG_TEXCRD]; /* pixel < 3.0 */ @@ -1367,6 +1372,16 @@ extern const SHADER_OPCODE* shader_get_opcode( IWineD3DBaseShader *iface, const DWORD code); +/* Vertex shader utility functions */ +extern BOOL vshader_get_input( + IWineD3DVertexShader* iface, + BYTE usage_req, BYTE usage_idx_req, + unsigned int* regnum); + +extern BOOL vshader_input_is_color( + IWineD3DVertexShader* iface, + unsigned int regnum); + /* ARB_[vertex/fragment]_program helper functions */ extern void shader_arb_load_constants( IWineD3DStateBlock* iface, @@ -1437,12 +1452,12 @@ extern void pshader_glsl_texbem(SHADER_OPCODE_ARG* arg); extern void pshader_glsl_dp2add(SHADER_OPCODE_ARG* arg); extern void pshader_glsl_input_pack( SHADER_BUFFER* buffer, - DWORD* semantics_out); + semantic* semantics_out); /** GLSL Vertex Shader Prototypes */ extern void vshader_glsl_output_unpack( SHADER_BUFFER* buffer, - DWORD* semantics_out); + semantic* semantics_out); /***************************************************************************** * IDirect3DBaseShader implementation structure @@ -1474,8 +1489,8 @@ typedef struct IWineD3DBaseShaderImpl { extern void shader_get_registers_used( IWineD3DBaseShader *iface, shader_reg_maps* reg_maps, - DWORD* semantics_in, - DWORD* semantics_out, + semantic* semantics_in, + semantic* semantics_out, CONST DWORD* pToken); extern void shader_generate_glsl_declarations( @@ -1558,8 +1573,8 @@ typedef struct IWineD3DVertexShaderImpl { DWORD usage; /* Vertex shader input and output semantics */ - DWORD semantics_in [WINED3DSHADERDECLUSAGE_MAX_USAGE]; - DWORD semantics_out [WINED3DSHADERDECLUSAGE_MAX_USAGE]; + semantic semantics_in [MAX_ATTRIBS]; + semantic semantics_out [MAX_REG_OUTPUT]; /* run time datas... */ VSHADERDATA *data; @@ -1589,7 +1604,7 @@ typedef struct IWineD3DPixelShaderImpl { IWineD3DDeviceImpl *wineD3DDevice; /* Pixel shader input semantics */ - DWORD semantics_in [WINED3DSHADERDECLUSAGE_MAX_USAGE]; + semantic semantics_in [MAX_REG_INPUT]; /* run time data */ PSHADERDATA *data;