private string ProcessTechniqueVS(SourceShader shader, HlslTechnique technique, AsmTechnique asmTechnique, ShaderExtension extension, Platform platform) { HlslMethod vs = shader.GetMethod(technique.VertexShaderMethodName, platform); HlslMethod ps = shader.GetMethod(technique.PixelShaderMethodName, platform); if (vs == null) throw new CompileException(string.Format("Unabled to find declaration for vertex shader method '{0}'", technique.VertexShaderMethodName)); if (ps == null) throw new CompileException(string.Format("Unabled to find declaration for pixel shader method '{0}'", technique.PixelShaderMethodName)); string nameAppend = "_" + Guid.NewGuid().ToString("N") + "_" + extension.ToString(); string blendName = "__blend_weights__GEN"; string indicesName = "__blend_indices__GEN"; //generated merged matrices StringBuilder matrixGen = new StringBuilder(); foreach (var remap in matrixRemap.Values) { if (remap.BaseName != null) // this will be null for the world matrix { //find the matching register in the technique string matrixType; string matrixExpansion = GetMatrixRankExpansion(remap.Name, asmTechnique, out matrixType); if (extension == ShaderExtension.Instancing) matrixGen.AppendFormat("\tfloat4x4 {0} = float4x4(({4})mul({1},{2}){3});", remap.RemapTo, worldMatrixName, remap.BaseName, matrixExpansion, matrixType); if (extension == ShaderExtension.Blending) matrixGen.AppendFormat("\tfloat4x4 {0} = float4x4(({4})mul({1},{2}){3});", remap.RemapTo, worldMatrixName, remap.Name, matrixExpansion, matrixType); matrixGen.AppendLine(); } } //create the method signatures footer.AppendLine(); bool multiArg = false; StringBuilder argList = new StringBuilder(); int argIndex = -1; bool transposeWorldMatrix = false; foreach (var element in vs.HlslShader.Elements) { if (element.Statement == vs.Name) { footer.Append(vs.Name); footer.Append(nameAppend); } else { if (element.Statement == "(" || element.Statement == ",") argIndex = 0; else { argIndex++; if (element.Statement == "out" || element.Statement == "in" || element.Statement == "inout" || element.Statement == "uniform" || element.Statement == "const") argIndex--; if (argIndex != -1 && argIndex == 2) { if (argList.Length > 0) argList.Append(", "); argList.Append(element.Statement); } } if (element.Statement == ")") { argIndex = -1; if (methodNames.TryGetValue(vs.Name, out multiArg) && multiArg) footer.Append(", "); if (extension == ShaderExtension.Instancing) { footer.Append("float4x4 " + worldMatrixName + "_transpose : POSITION12"); transposeWorldMatrix = true; } if (extension == ShaderExtension.Blending) { footer.AppendFormat("float4 {0} : BLENDWEIGHT, int4 {1} : BLENDINDICES", blendName, indicesName); } } footer.Append(element); footer.Append(' '); } } footer.AppendLine(); footer.AppendLine("{"); if (transposeWorldMatrix) { footer.AppendLine("\tfloat4x4 " + worldMatrixName + " = transpose(" + worldMatrixName + "_transpose);"); } if (extension == ShaderExtension.Blending) { string calculation = @" float4x4 {3} = transpose(float4x4( {0}[{1}.x * 3 + 0] * {2}.x + {0}[{1}.y * 3 + 0] * {2}.y + {0}[{1}.z * 3 + 0] * {2}.z + {0}[{1}.w * 3 + 0] * {2}.w, {0}[{1}.x * 3 + 1] * {2}.x + {0}[{1}.y * 3 + 1] * {2}.y + {0}[{1}.z * 3 + 1] * {2}.z + {0}[{1}.w * 3 + 1] * {2}.w, {0}[{1}.x * 3 + 2] * {2}.x + {0}[{1}.y * 3 + 2] * {2}.y + {0}[{1}.z * 3 + 2] * {2}.z + {0}[{1}.w * 3 + 2] * {2}.w, float4(0,0,0,1)));"; footer.AppendFormat(calculation, blendMatricesName, indicesName, blendName, worldMatrixName); footer.AppendLine(); } footer.Append(matrixGen); footer.AppendFormat("\t{4}{0}({1}{2}{3});", ToInternalMethodName(vs.Name, extension), methodCallAppend, multiArg ? ", " : "", argList, vs.HasReturnValue ? "return " : ""); footer.AppendLine(); footer.AppendLine("}"); return vs.Name + nameAppend; }
void TranslateMatrices(HlslStructure.ShaderStatement[] elements, int callDepth, ShaderExtension extension) { bool isInstancing = extension == ShaderExtension.Instancing; List<int> skipFinalRemappingIndices = new List<int>(); int processingMul = 0, depth = 0, arg = 0; int argStart = 0, argEnd = 0; int remapArg = -1; int remapIndex = 0; MatrixMapping remapping = new MatrixMapping(); Stack<int> mulStart = new Stack<int>(); Stack<int> mulDepth = new Stack<int>(); Stack<int> mulArg = new Stack<int>(); Stack<int> mulArgStart = new Stack<int>(); Stack<int> mulArgEnd = new Stack<int>(); Stack<int> mulRemap = new Stack<int>(); Stack<int> mulRemapIdx = new Stack<int>(); Stack<MatrixMapping> mulRemapping = new Stack<MatrixMapping>(); for (int i = 0; i < elements.Length; i++) { string line = elements[i].Statement; if (line == "mul") { processingMul++; mulStart.Push(i); mulDepth.Push(depth); mulArg.Push(arg); mulArgEnd.Push(argEnd); mulArgStart.Push(argStart); mulRemap.Push(remapArg); mulRemapping.Push(remapping); mulRemapIdx.Push(remapIndex); depth = 0; arg = 0; argStart = 0; argEnd = 0; remapArg = -1; remapIndex = 0; remapping = new MatrixMapping(); } MatrixMapping mapping; if (processingMul > 0 && depth == 1 && matrixRemap.TryGetValue(line, out mapping) && (mapping.BaseName != null || !isInstancing)) { remapArg = arg; remapping = mapping; remapIndex = i; } if (processingMul > 0 && line == "(") { if (depth == 0) argStart = i; depth++; } if (processingMul > 0 && depth == 1 && line == ",") { if (depth == 1) argEnd = i; arg++; } if (processingMul > 0 && line == ")") { depth--; if (depth == 0) { string baseMatrix = remapping.Name; if (isInstancing) baseMatrix = remapping.BaseName; string prefix = ""; int startPrefix = -1; if (remapArg == 1) startPrefix = argEnd; if (remapArg == 0) startPrefix = argStart; if (remapIndex > startPrefix && startPrefix != -1) { for (int p = startPrefix + 1; p < remapIndex; p++) prefix += elements[p].Statement + " "; } //right, see if the args need modifying. if (remapArg == 1) { //a known remapping matrix was used. var element = elements[remapIndex]; elements[remapIndex] = new HlslStructure.ShaderStatement(baseMatrix, element.Line); element = elements[argStart]; elements[argStart] = new HlslStructure.ShaderStatement("(mul(", element.Line); element = elements[argEnd]; elements[argEnd] = new HlslStructure.ShaderStatement("," + prefix + worldMatrixName + "),", element.Line); if (!isInstancing) skipFinalRemappingIndices.Add(remapIndex); } if (remapArg == 0) // transpose { //a known remapping matrix was used. var element = elements[remapIndex]; elements[remapIndex] = new HlslStructure.ShaderStatement(baseMatrix, element.Line); element = elements[argEnd]; elements[argEnd] = new HlslStructure.ShaderStatement(",mul(" + prefix + worldMatrixName + ",", element.Line); element = elements[i]; elements[i] = new HlslStructure.ShaderStatement("))", element.Line); if (!isInstancing) skipFinalRemappingIndices.Add(remapIndex); } processingMul--; mulStart.Pop(); depth = mulDepth.Pop(); arg = mulArg.Pop(); argEnd = mulArgEnd.Pop(); argStart = mulArgStart.Pop(); remapArg = mulRemap.Pop(); remapping = mulRemapping.Pop(); remapIndex = mulRemapIdx.Pop(); } } } //find unremapped matrices if (callDepth > 0) { for (int i = 0; i < elements.Length; i++) { //it is intended that this matrix reference is not modified. if (!isInstancing && skipFinalRemappingIndices.Contains(i)) continue; MatrixMapping mapping; if (matrixRemap.TryGetValue(elements[i].Statement, out mapping)) elements[i] = new HlslStructure.ShaderStatement(mapping.RemapTo, elements[i].Line); } } }
void TranslateMethodNames(HlslStructure.ShaderStatement[] elements, int callDepth, ShaderExtension extension) { for (int i = 0; i < elements.Length; i++) { string methodName = elements[i].Statement; bool multArg; if (methodNames.TryGetValue(methodName, out multArg)) { BuildMethod(methodName, extension); //find the method start for (int n = i+1; n < elements.Length; n++) { if (elements[n] == "(") { string argAppend = multArg ? ", " : ""; //append the method signatures if (callDepth == 0) elements[n] = new HlslStructure.ShaderStatement("(" + this.methodSignatureAppend + argAppend, elements[n].Line); else elements[n] = new HlslStructure.ShaderStatement("(" + this.methodCallAppend + argAppend, elements[n].Line); elements[i] = new HlslStructure.ShaderStatement(ToInternalMethodName(methodName,extension), elements[i].Line); break; } } } } }
void BuildMethod(string methodName, ShaderExtension extension) { if (methodBuilt.ContainsKey(methodName) == false) return; if (methodBuilt[methodName]) return; StringBuilder sb = new StringBuilder(); foreach (var method in methodList) { if (method.Name == methodName) { methodBuilt[methodName] = true; method.HlslShader.ToString(sb, 0, this, null, false, false); } } this.builtShader.Append(sb); }
private void BuildTechniqueMethod(SourceShader shader, ShaderExtension extension) { methodExtractionExtension = extension; foreach (var method in methodList) { if (methodBuilt.ContainsKey(method.Name) == false) methodBuilt.Add(method.Name, false); } foreach (var tech in shader.GetAllTechniques()) { BuildMethod(tech.VertexShaderMethodName, extension); } methodBuilt.Clear(); UnwindBackup(shader.HlslShader); }
static string ToInternalMethodName(string name, ShaderExtension extension) { return string.Format("__{0}__{1}_GENCALL", name, extension); }