public static uint GetCBVarSize(this ShaderTypeMember member, bool wholeArraySize = false) { uint size; if (member.Type.VariableClass == ShaderVariableClass.Struct) { var last = member.Type.Members.Last(); size = last.Offset + GetCBVarSize(last, true); } else if (member.Type.VariableClass == ShaderVariableClass.MatrixRows) { var columns = (uint)member.Type.Columns; var rows = (uint)member.Type.Rows; size = (rows - 1) * 16 + columns * 4; } else if (member.Type.VariableClass == ShaderVariableClass.MatrixColumns) { var columns = (uint)member.Type.Columns; var rows = (uint)member.Type.Rows; size = (columns - 1) * 16 + rows * 4; } else { size = (uint)member.Type.Columns * (uint)member.Type.Rows * 4; } if (wholeArraySize && member.Type.ElementCount > 1) { uint paddedSize = ((size + 15) / 16) * 16; // Arrays are padded to float4 size size = ((uint)member.Type.ElementCount - 1) * paddedSize + size; // Except the last element } return(size); }
static IrShaderTypeMember ParseShaderTypeMember(ShaderTypeMember member) { return(new IrShaderTypeMember() { Name = member.Name, Offset = member.Offset, Type = ParseShaderType(member.Type) }); }
string GetShaderMemberDeclaration(ShaderTypeMember member, int indent) { string declaration = GetShaderTypeDeclaration(member.Type, indent, root: false) + " " + member.Name; if (member.Type.ElementCount > 0) { declaration += string.Format("[{0}]", member.Type.ElementCount); } declaration += ";"; declaration += $" // Offset {member.Offset} CBSize {member.GetCBVarSize(true)}"; return(declaration); }
internal ShaderTypeMember IsOffsetInType(ShaderTypeMember member, uint parentOffset, uint offsetToFind, out string fullName, out bool isArray) { uint thisOffset = parentOffset + member.Offset; uint thisSize = member.GetCBVarSize(); uint paddedSize = ((thisSize + 15) / 16) * 16; uint arraySize = thisSize; fullName = null; if (member.Type.ElementCount > 1) { arraySize = (paddedSize * ((uint)member.Type.ElementCount - 1)) + thisSize; } isArray = false; if (offsetToFind < thisOffset || offsetToFind >= (thisOffset + arraySize)) { return(null); } string arrayIndex = ""; if (member.Type.VariableClass == ShaderVariableClass.Struct) { uint offsetInStruct = (offsetToFind - thisOffset) % paddedSize; foreach (var child in member.Type.Members) { var foundType = IsOffsetInType(child, thisOffset, thisOffset + offsetInStruct, out string childName, out isArray); if (foundType != null) { if (child.Type.ElementCount > 1) { arrayIndex = $"[{(offsetToFind - thisOffset) / thisSize}]"; } fullName = $"{member.Name}{arrayIndex}.{childName}"; return(foundType); } } } else if ((member.Type.VariableClass == ShaderVariableClass.MatrixRows || member.Type.VariableClass == ShaderVariableClass.MatrixColumns) || ((member.Type.VariableClass == ShaderVariableClass.Scalar || member.Type.VariableClass == ShaderVariableClass.Vector) && member.Type.ElementCount > 1)) { isArray = true; arrayIndex = $"[{(offsetToFind - thisOffset) / 16}]"; } else if (member.Type.VariableClass == ShaderVariableClass.Vector) { //Check for vector starting at a non-vec4 offset. } fullName = $"{member.Name}{arrayIndex}"; return(member); }
void InitMember(ShaderTypeMember member, string registerName, uint bindPoint, uint parentOffset = 0, string prefix = "") { uint thisOffset = parentOffset + member.Offset; uint thisSize = member.GetCBVarSize(); var elementCount = member.Type.ElementCount == 0 ? 1 : member.Type.ElementCount; for (uint i = 0; i < elementCount; i++) { string arrayIndex = member.Type.ElementCount > 1 ? $"[{i}]" : ""; if (member.Type.VariableClass == ShaderVariableClass.MatrixColumns) { for (int j = 0; j < member.Type.Columns; j++) { var key = $"{registerName}{bindPoint}[{thisOffset / 16 + i * member.Type.Columns + j}]"; AddRegister(key, new Register($"{prefix}{member.Name}{arrayIndex}[{j}]")); } } else if (member.Type.VariableClass == ShaderVariableClass.MatrixRows) { for (int j = 0; j < member.Type.Rows; j++) { var key = $"{registerName}{bindPoint}[{thisOffset / 16 + i * member.Type.Rows + j}]"; AddRegister(key, new Register($"{prefix}{member.Name}{arrayIndex}[{j}]")); } } else if (member.Type.VariableClass == ShaderVariableClass.Struct) { uint paddedSize = ((thisSize + 15) / 16) * 16; uint structOffset = thisOffset + paddedSize * i; foreach (var child in member.Type.Members) { InitMember(child, registerName, bindPoint, structOffset, $"{prefix}{member.Name}{arrayIndex}."); } } else { var key = $"{registerName}{bindPoint}[{thisOffset / 16 + i}]"; AddRegister(key, new Register($"{prefix}{member.Name}{arrayIndex}")); } } }
void WriteCBInnerStructs(ShaderTypeMember member, ref HashSet <string> seen) { if (member.Type.VariableClass != ShaderVariableClass.Struct) { return; } if (seen.Contains(member.Type.BaseTypeName)) { return; } foreach (var child in member.Type.Members) { WriteCBInnerStructs(child, ref seen); } if (member.Type.BaseTypeName == null || member.Type.BaseTypeName.EndsWith("<unnamed>")) { return; } seen.Add(member.Type.BaseTypeName); Output.AppendFormat("{0};\n", GetShaderTypeDeclaration(member.Type)); }