BOOL ShaderProcessor::ProcessShader(CTSTR input) { String curToken; BOOL bError = FALSE; SetCodeStart(input); TSTR lpLastPos = lpTemp; DWORD curInsideCount = 0; BOOL bNewCodeLine = TRUE; while(GetNextToken(curToken)) { TSTR lpCurPos = lpTemp-curToken.Length(); if(curToken[0] == '{') ++curInsideCount; else if(curToken[0] == '}') --curInsideCount; else if(curToken[0] == '(') ++curInsideCount; else if(curToken[0] == ')') --curInsideCount; else if(!curInsideCount && bNewCodeLine) //not inside any code, so this is some sort of declaration (function/struct/var) { if(curToken == TEXT("struct")) { //try to see if this is the vertex definition structure bool bFoundDefinitionStruct = false; HandMeAToken(curToken); ExpectTokenIgnore(TEXT("{")); curInsideCount = 1; do { HandMeAToken(curToken); if(curToken.Length() <= 6 && scmpi_n(curToken, TEXT("float"), 5) == 0) { String strType = curToken; String strName; HandMeAToken(strName); HandMeAToken(curToken); if(curToken[0] != ':') //cancel if not a vertex definition structure { bFoundDefinitionStruct = false; break; } String strSemantic; HandMeAToken(strSemantic); SemanticInfo semanticInfo; if(!GetSemanticInfo(strSemantic, semanticInfo)) { bFoundDefinitionStruct = false; break; } D3D10_INPUT_ELEMENT_DESC inputElement; inputElement.SemanticName = semanticInfo.lpName; inputElement.SemanticIndex = semanticInfo.index; inputElement.InputSlot = 0; inputElement.AlignedByteOffset = 0; inputElement.InputSlotClass = D3D10_INPUT_PER_VERTEX_DATA; inputElement.InstanceDataStepRate = 0; if(strSemantic.CompareI(TEXT("color"))) inputElement.Format = DXGI_FORMAT_R8G8B8A8_UNORM; else { switch(strType[5]) { case 0: inputElement.Format = DXGI_FORMAT_R32_FLOAT; break; case '2': inputElement.Format = DXGI_FORMAT_R32G32_FLOAT; break; case '3': inputElement.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; break; //todo: check this some time case '4': inputElement.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; break; } } ExpectToken(TEXT(";"), TEXT(";")); PeekAtAToken(curToken); generatedLayout << inputElement; bFoundDefinitionStruct = true; } else { bFoundDefinitionStruct = false; break; //vertex definition structures should really only ever have float values } } while (curToken[0] != '}'); //set up the slots so they match up with vertex buffers if(bFoundDefinitionStruct) { UINT curSlot = 0; for(UINT i=0; i<generatedLayout.Num(); i++) { if(stricmp(generatedLayout[i].SemanticName, "SV_Position") == 0) { generatedLayout[i].InputSlot = curSlot++; break; } } for(UINT i=0; i<generatedLayout.Num(); i++) { if(stricmp(generatedLayout[i].SemanticName, "NORMAL") == 0) { generatedLayout[i].InputSlot = curSlot++; bHasNormals = true; break; } } for(UINT i=0; i<generatedLayout.Num(); i++) { if(stricmp(generatedLayout[i].SemanticName, "COLOR") == 0) { generatedLayout[i].InputSlot = curSlot++; bHasColors = true; break; } } for(UINT i=0; i<generatedLayout.Num(); i++) { if(stricmp(generatedLayout[i].SemanticName, "TANGENT") == 0) { generatedLayout[i].InputSlot = curSlot++; bHasTangents = true; break; } } bool bFoundTexCoord; do { bFoundTexCoord = false; for(UINT i=0; i<generatedLayout.Num(); i++) { if(generatedLayout[i].SemanticIndex == numTextureCoords && stricmp(generatedLayout[i].SemanticName, "TEXCOORD") == 0) { generatedLayout[i].InputSlot = curSlot++; numTextureCoords++; bFoundTexCoord = true; break; } } } while(bFoundTexCoord); } } else if( (curToken != TEXT("const")) && (curToken != TEXT("void")) && (curToken != TEXT(";")) ) { TSTR lpSavedPos = lpTemp; String savedToken = curToken; if(curToken == TEXT("uniform")) HandMeAToken(curToken); String strType = curToken; String strName; HandMeAToken(strName); PeekAtAToken(curToken); if(curToken[0] != '(') //verified variable { if(strType.CompareI(TEXT("samplerstate"))) { ShaderSampler &curSampler = *Samplers.CreateNew(); curSampler.name = strName; SamplerInfo info; ExpectToken(TEXT("{"), TEXT(";")); PeekAtAToken(curToken); while(curToken != TEXT("}")) { String strState; HandMeAToken(strState); ExpectToken(TEXT("="), TEXT(";")); String strValue; HandMeAToken(strValue); if(!AddState(info, strState, strValue)) EscapeLikeTheWind(TEXT(";")); ExpectToken(TEXT(";"), TEXT(";")); PeekAtAToken(curToken); } curSampler.sampler = CreateSamplerState(info); ExpectToken(TEXT("}"), TEXT("}")); ExpectTokenIgnore(TEXT(";")); //---------------------------------------- lpLastPos = lpTemp; continue; } else { ShaderParam *param = Params.CreateNew(); param->name = strName; if(curToken[0] == '[') { HandMeAToken(curToken); HandMeAToken(curToken); param->arrayCount = tstoi(curToken); ExpectToken(TEXT("]"), TEXT(";")); PeekAtAToken(curToken); } if(scmpi_n(strType, TEXT("texture"), 7) == 0) { TSTR lpType = strType.Array()+7; supr(lpType); if (!*lpType || (scmp(lpType, TEXT("1D")) && scmp(lpType, TEXT("2D")) && scmp(lpType, TEXT("3D")) && scmp(lpType, TEXT("CUBE"))) ) { bError = TRUE; } param->textureID = nTextures++; param->type = Parameter_Texture; strType = TEXT("sampler"); } else if(scmp_n(strType, TEXT("float"), 5) == 0) { CTSTR lpType = strType.Array()+5; if(*lpType == 0) param->type = Parameter_Float; else if(scmpi(lpType, TEXT("2")) == 0) param->type = Parameter_Vector2; else if(scmpi(lpType, TEXT("3")) == 0) param->type = Parameter_Vector3; else if(scmpi(lpType, TEXT("4")) == 0) param->type = Parameter_Vector4; else if(scmpi(lpType, TEXT("3x3")) == 0) param->type = Parameter_Matrix3x3; else if(scmpi(lpType, TEXT("4x4")) == 0) param->type = Parameter_Matrix; } else if(scmp(strType, TEXT("int")) == 0) param->type = Parameter_Int; else if(scmp(strType, TEXT("bool")) == 0) param->type = Parameter_Bool; if(curToken == TEXT("=")) { HandMeAToken(curToken); BufferOutputSerializer sOut(param->defaultValue); if(scmp(strType, TEXT("float")) == 0) { HandMeAToken(curToken); if(!ValidFloatString(curToken)) bError = TRUE; float fValue = (float)tstof(curToken); sOut << fValue; } else if(scmp(strType, TEXT("int")) == 0) { HandMeAToken(curToken); if(!ValidIntString(curToken)) bError = TRUE; int iValue = tstoi(curToken); sOut << iValue; } else if(scmp_n(strType, TEXT("float"), 5) == 0) { CTSTR lpFloatType = strType.Array()+5; int floatCount = 0; if(lpFloatType[0] == '1') floatCount = 1; else if(lpFloatType[0] == '2') floatCount = 2; else if(lpFloatType[0] == '3') floatCount = 3; else if(lpFloatType[0] == '4') floatCount = 4; else bError = TRUE; if(lpFloatType[1] == 'x') { if(lpFloatType[2] != '1') { if(lpFloatType[2] == '2') floatCount *= 2; else if(lpFloatType[2] == '3') floatCount *= 3; else if(lpFloatType[2] == '4') floatCount *= 4; else bError = TRUE; } } if(floatCount > 1) {ExpectToken(TEXT("{"), TEXT(";"));} int j; for(j=0; j<floatCount; j++) { if(j) { HandMeAToken(curToken); if(curToken[0] != ',') { bError = TRUE; break; } } HandMeAToken(curToken); if(!ValidFloatString(curToken)) { bError = TRUE; break; } float fValue = (float)tstof(curToken); sOut << fValue; } if(j != floatCount) //processing error occured { GotoToken(TEXT(";")); continue; } if(floatCount > 1) {ExpectToken(TEXT("}"), TEXT(";"));} } PeekAtAToken(curToken); } } //-------------------------- lpLastPos = lpTemp; bNewCodeLine = FALSE; continue; } lpTemp = lpSavedPos; curToken = savedToken; } } lpLastPos = lpTemp; bNewCodeLine = (curToken.IsValid() && ((curToken[0] == ';') || (curToken[0] == '}'))); } return !bError; }
BOOL CodeTokenizer::GetNextTokenEval(String &token, BOOL *bFloatOccurance, int curPrecedence) { TSTR lpLastSafePos = lpTemp; String curVal, curToken; BOOL bFoundNumber = FALSE; BOOL bUsedBracers = FALSE; if(!GetNextToken(curToken)) return FALSE; if(curToken == TEXT("(")) { TSTR lpPrevPos = lpTemp; int newPrecedence = GetTokenPrecedence(curToken); if(!GetNextTokenEval(curToken, bFloatOccurance, newPrecedence)) return FALSE; if(!ValidFloatString(curToken)) { lpTemp = lpPrevPos; token = TEXT("("); return TRUE; } String nextToken; if(!GetNextToken(nextToken)) return FALSE; if(nextToken != TEXT(")")) { lpTemp = lpPrevPos; token = TEXT("("); return TRUE; } bUsedBracers = TRUE; } if(curToken == TEXT("-") && iswdigit(*lpTemp)) { String nextToken; if(!GetNextToken(nextToken)) return FALSE; curToken << nextToken; } if(ValidFloatString(curToken)) { bFoundNumber = TRUE; curVal = curToken; if(!ValidIntString(curVal) && bFloatOccurance) *bFloatOccurance = TRUE; } else { if(bFoundNumber) { lpTemp = lpLastSafePos; token = curVal; return TRUE; } else { token = curToken; return TRUE; } } lpLastSafePos = lpTemp; String operatorToken; while(GetNextToken(operatorToken)) { int newPrecedence = GetTokenPrecedence(operatorToken); if(newPrecedence <= curPrecedence) { lpTemp = lpLastSafePos; token = curVal; return TRUE; } String nextVal; if(!GetNextTokenEval(nextVal, bFloatOccurance, newPrecedence)) return FALSE; if(!ValidFloatString(nextVal)) { lpTemp = lpLastSafePos; token = curVal; return TRUE; } if(operatorToken == TEXT("<<")) { int val1 = tstoi(curVal); int val2 = tstoi(nextVal); val1 <<= val2; curVal = IntString(val1); } else if(operatorToken == TEXT(">>")) { int val1 = tstoi(curVal); int val2 = tstoi(nextVal); val1 >>= val2; curVal = IntString(val1); } else if(operatorToken == TEXT("*"))
BOOL ShaderProcessor::AddState(SamplerInfo &info, String &stateName, String &stateVal) { if(scmpi_n(stateName, TEXT("Address"), 7) == 0) { int type = stateName[7]-'U'; GSAddressMode *mode; switch(type) { case 0: mode = &info.addressU; break; case 1: mode = &info.addressV; break; case 2: mode = &info.addressW; break; default: CrashError(TEXT("Invalid shader address type %d"), type); } if(stateVal.CompareI(TEXT("Wrap")) || stateVal.CompareI(TEXT("Repeat"))) *mode = GS_ADDRESS_WRAP; else if(stateVal.CompareI(TEXT("Clamp")) || stateVal.CompareI(TEXT("None"))) *mode = GS_ADDRESS_CLAMP; else if(stateVal.CompareI(TEXT("Mirror"))) *mode = GS_ADDRESS_MIRROR; else if(stateVal.CompareI(TEXT("Border"))) *mode = GS_ADDRESS_BORDER; else if(stateVal.CompareI(TEXT("MirrorOnce"))) *mode = GS_ADDRESS_MIRRORONCE; } else if(stateName.CompareI(TEXT("MaxAnisotropy"))) { info.maxAnisotropy = tstoi(stateVal); } else if(stateName.CompareI(TEXT("Filter"))) { if(stateVal.CompareI(TEXT("Anisotropic"))) info.filter = GS_FILTER_ANISOTROPIC; else if(stateVal.CompareI(TEXT("Point")) || stateVal.CompareI(TEXT("MIN_MAG_MIP_POINT"))) info.filter = GS_FILTER_POINT; else if(stateVal.CompareI(TEXT("Linear")) || stateVal.CompareI(TEXT("MIN_MAG_MIP_LINEAR"))) info.filter = GS_FILTER_LINEAR; else if(stateVal.CompareI(TEXT("MIN_MAG_POINT_MIP_LINEAR"))) info.filter = GS_FILTER_MIN_MAG_POINT_MIP_LINEAR; else if(stateVal.CompareI(TEXT("MIN_POINT_MAG_LINEAR_MIP_POINT"))) info.filter = GS_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT; else if(stateVal.CompareI(TEXT("MIN_POINT_MAG_MIP_LINEAR"))) info.filter = GS_FILTER_MIN_POINT_MAG_MIP_LINEAR; else if(stateVal.CompareI(TEXT("MIN_LINEAR_MAG_MIP_POINT"))) info.filter = GS_FILTER_MIN_LINEAR_MAG_MIP_POINT; else if(stateVal.CompareI(TEXT("MIN_LINEAR_MAG_POINT_MIP_LINEAR"))) info.filter = GS_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR; else if(stateVal.CompareI(TEXT("MIN_MAG_LINEAR_MIP_POINT"))) info.filter = GS_FILTER_MIN_MAG_LINEAR_MIP_POINT; } else if(stateName.CompareI(TEXT("BorderColor"))) { if(stateVal[0] == '{') { String curToken; HandMeAToken(curToken); if(!ValidFloatString(curToken)) {return FALSE;} info.borderColor.x = (float)tstof(curToken); //------------------------------- ExpectToken(TEXT(",")); //------------------------------- HandMeAToken(curToken); if(!ValidFloatString(curToken)) {return FALSE;} info.borderColor.y = (float)tstof(curToken); //------------------------------- ExpectToken(TEXT(",")); //------------------------------- HandMeAToken(curToken); if(!ValidFloatString(curToken)) {return FALSE;} info.borderColor.z = (float)tstof(curToken); //------------------------------- ExpectToken(TEXT(",")); //------------------------------- HandMeAToken(curToken); if(!ValidFloatString(curToken)) {return FALSE;} info.borderColor.w = (float)tstof(curToken); //------------------------------- ExpectToken(TEXT("}")); } else if(ValidIntString(stateVal)) info.borderColor = Color4().MakeFromRGBA(tstoi(stateVal)); } return TRUE; }