Ejemplo n.º 1
0
        static public FormatElement[] ParseFormatString(string formatString, bool tightPacking, out string errors)
        {
            var elems = new List<FormatElement>();

            var formatReader = new StringReader(formatString);

            // regex doesn't account for trailing or preceeding whitespace, or comments

            var regExpr = @"^(row_major\s+)?" + // row_major matrix
                          @"(" +
                          @"uintten|unormten" +
                          @"|unormh|unormb" +
                          @"|snormh|snormb" +
                          @"|bool" + // bool is stored as 4-byte int in hlsl
                          @"|byte|short|int" + // signed ints
                          @"|ubyte|ushort|uint" + // unsigned ints
                          @"|xbyte|xshort|xint" + // hex ints
                          @"|half|float|double" + // float types
                          @")" +
                          @"([1-9])?" + // might be a vector
                          @"(x[1-9])?" + // or a matrix
                          @"(\s+[A-Za-z_][A-Za-z0-9_]*)?" + // get identifier name
                          @"(\[[0-9]+\])?" + // optional array dimension
                          @"(\s*:\s*[A-Za-z_][A-Za-z0-9_]*)?" + // optional semantic
                          @"$";

            Regex regParser = new Regex(regExpr, RegexOptions.Compiled);

            bool success = true;
            errors = "";

            var text = formatReader.ReadToEnd();

            text = text.Replace("{", "").Replace("}", "");

            Regex c_comments = new Regex(@"/\*[^*]*\*+(?:[^*/][^*]*\*+)*/", RegexOptions.Compiled);
            text = c_comments.Replace(text, "");

            Regex cpp_comments = new Regex(@"//.*", RegexOptions.Compiled);
            text = cpp_comments.Replace(text, "");

            uint offset = 0;

            // get each line and parse it to determine the format the user wanted
            foreach (var l in text.Split(';'))
            {
                var line = l;
                line = line.Trim();

                if (line == "") continue;

                var match = regParser.Match(line);

                if (!match.Success)
                {
                    errors = "Couldn't parse line:\n" + line;
                    success = false;
                    break;
                }

                var basetype = match.Groups[2].Value;
                bool row_major = match.Groups[1].Success;
                var vectorDim = match.Groups[3].Success ? match.Groups[3].Value : "1";
                var matrixDim = match.Groups[4].Success ? match.Groups[4].Value.Substring(1) : "1";
                var name = match.Groups[5].Success ? match.Groups[5].Value.Trim() : "data";
                var arrayDim = match.Groups[6].Success ? match.Groups[6].Value.Trim() : "[1]";
                arrayDim = arrayDim.Substring(1, arrayDim.Length - 2);

                if (match.Groups[4].Success)
                {
                    var a = vectorDim;
                    vectorDim = matrixDim;
                    matrixDim = a;
                }

                ResourceFormat fmt = new ResourceFormat(FormatComponentType.None, 0, 0);

                bool hex = false;

                FormatComponentType type = FormatComponentType.Float;
                uint count = 0;
                uint arrayCount = 1;
                uint matrixCount = 0;
                uint width = 0;

                // calculate format
                {
                    if (!uint.TryParse(vectorDim, out count))
                    {
                        errors = "Invalid vector dimension on line:\n" + line;
                        success = false;
                        break;
                    }
                    if (!uint.TryParse(arrayDim, out arrayCount))
                    {
                        arrayCount = 1;
                    }
                    arrayCount = Math.Max(0, arrayCount);
                    if (!uint.TryParse(matrixDim, out matrixCount))
                    {
                        errors = "Invalid matrix second dimension on line:\n" + line;
                        success = false;
                        break;
                    }

                    if (basetype == "bool")
                    {
                        type = FormatComponentType.UInt;
                        width = 4;
                    }
                    else if (basetype == "byte")
                    {
                        type = FormatComponentType.SInt;
                        width = 1;
                    }
                    else if (basetype == "ubyte" || basetype == "xbyte")
                    {
                        type = FormatComponentType.UInt;
                        width = 1;
                    }
                    else if (basetype == "short")
                    {
                        type = FormatComponentType.SInt;
                        width = 2;
                    }
                    else if (basetype == "ushort" || basetype == "xshort")
                    {
                        type = FormatComponentType.UInt;
                        width = 2;
                    }
                    else if (basetype == "int")
                    {
                        type = FormatComponentType.SInt;
                        width = 4;
                    }
                    else if (basetype == "uint" || basetype == "xint")
                    {
                        type = FormatComponentType.UInt;
                        width = 4;
                    }
                    else if (basetype == "half")
                    {
                        type = FormatComponentType.Float;
                        width = 2;
                    }
                    else if (basetype == "float")
                    {
                        type = FormatComponentType.Float;
                        width = 4;
                    }
                    else if (basetype == "double")
                    {
                        type = FormatComponentType.Float;
                        width = 8;
                    }
                    else if (basetype == "unormh")
                    {
                        type = FormatComponentType.UNorm;
                        width = 2;
                    }
                    else if (basetype == "unormb")
                    {
                        type = FormatComponentType.UNorm;
                        width = 1;
                    }
                    else if (basetype == "snormh")
                    {
                        type = FormatComponentType.SNorm;
                        width = 2;
                    }
                    else if (basetype == "snormb")
                    {
                        type = FormatComponentType.SNorm;
                        width = 1;
                    }
                    else if (basetype == "uintten")
                    {
                        fmt = new ResourceFormat(FormatComponentType.UInt, 4 * count, 1);
                        fmt.special = true;
                        fmt.specialFormat = SpecialFormat.R10G10B10A2;
                    }
                    else if (basetype == "unormten")
                    {
                        fmt = new ResourceFormat(FormatComponentType.UNorm, 4 * count, 1);
                        fmt.special = true;
                        fmt.specialFormat = SpecialFormat.R10G10B10A2;
                    }
                    else
                    {
                        errors = "Unrecognised basic type on line:\n" + line;
                        success = false;
                        break;
                    }
                }

                if (basetype == "xint" || basetype == "xshort" || basetype == "xbyte")
                    hex = true;

                if (fmt.compType == FormatComponentType.None)
                    fmt = new ResourceFormat(type, count, width);

                if (arrayCount == 1)
                {
                    FormatElement elem = new FormatElement(name, 0, offset, false, row_major, matrixCount, fmt, hex);

                    uint advance = elem.ByteSize;

                    if (!tightPacking)
                    {
                        // cbuffer packing always works in floats
                        advance = (advance + 3U) & (~3U);

                        // cbuffer packing doesn't allow elements to cross float4 boundaries, nudge up if this was the case
                        if (offset / 16 != (offset + elem.ByteSize - 1) / 16)
                        {
                            elem.offset = offset = (offset + 0xFU) & (~0xFU);
                        }
                    }

                    elems.Add(elem);

                    offset += advance;
                }
                else
                {
                    // when cbuffer packing, arrays are always aligned at float4 boundary
                    if (!tightPacking)
                    {
                        if (offset % 16 != 0)
                        {
                            offset = (offset + 0xFU) & (~0xFU);
                        }
                    }

                    for (uint a = 0; a < arrayCount; a++)
                    {
                        FormatElement elem = new FormatElement(String.Format("{0}[{1}]", name, a), 0, offset, false, row_major, matrixCount, fmt, hex);

                        elems.Add(elem);

                        uint advance = elem.ByteSize;

                        // cbuffer packing each array element is always float4 aligned
                        if (!tightPacking)
                        {
                            advance = (advance + 0xFU) & (~0xFU);
                        }

                        offset += advance;
                    }
                }
            }

            if (!success || elems.Count == 0)
            {
                elems.Clear();

                var fmt = new ResourceFormat(FormatComponentType.UInt, 4, 4);

                elems.Add(new FormatElement("data", 0, 0, false, false, 1, fmt, true));
            }

            return elems.ToArray();
        }
Ejemplo n.º 2
0
        static public FormatElement[] ParseFormatString(string formatString, UInt64 maxLen, bool tightPacking, out string errors)
        {
            var elems = new List <FormatElement>();

            var formatReader = new StringReader(formatString);

            // regex doesn't account for trailing or preceeding whitespace, or comments

            var regExpr = @"^(row_major\s+)?" + // row_major matrix
                          @"(" +
                          @"uintten|unormten" +
                          @"|unormh|unormb" +
                          @"|snormh|snormb" +
                          @"|bool" +                            // bool is stored as 4-byte int
                          @"|byte|short|int" +                  // signed ints
                          @"|ubyte|ushort|uint" +               // unsigned ints
                          @"|xbyte|xshort|xint" +               // hex ints
                          @"|half|float|double" +               // float types
                          @"|vec|uvec|ivec" +                   // OpenGL vector types
                          @"|mat|umat|imat" +                   // OpenGL matrix types
                          @")" +
                          @"([1-9])?" +                         // might be a vector
                          @"(x[1-9])?" +                        // or a matrix
                          @"(\s+[A-Za-z_][A-Za-z0-9_]*)?" +     // get identifier name
                          @"(\[[0-9]+\])?" +                    // optional array dimension
                          @"(\s*:\s*[A-Za-z_][A-Za-z0-9_]*)?" + // optional semantic
                          @"$";

            Regex regParser = new Regex(regExpr, RegexOptions.Compiled);

            bool success = true;

            errors = "";

            var text = formatReader.ReadToEnd();

            text = text.Replace("{", "").Replace("}", "");

            Regex c_comments = new Regex(@"/\*[^*]*\*+(?:[^*/][^*]*\*+)*/", RegexOptions.Compiled);

            text = c_comments.Replace(text, "");

            Regex cpp_comments = new Regex(@"//.*", RegexOptions.Compiled);

            text = cpp_comments.Replace(text, "");

            uint offset = 0;

            // get each line and parse it to determine the format the user wanted
            foreach (var l in text.Split(';'))
            {
                var line = l;
                line = line.Trim();

                if (line.Length == 0)
                {
                    continue;
                }

                var match = regParser.Match(line);

                if (!match.Success)
                {
                    errors  = "Couldn't parse line:\n" + line;
                    success = false;
                    break;
                }

                var  basetype  = match.Groups[2].Value;
                bool row_major = match.Groups[1].Success;
                var  vectorDim = match.Groups[3].Success ? match.Groups[3].Value : "1";
                var  matrixDim = match.Groups[4].Success ? match.Groups[4].Value.Substring(1) : "1";
                var  name      = match.Groups[5].Success ? match.Groups[5].Value.Trim() : "data";
                var  arrayDim  = match.Groups[6].Success ? match.Groups[6].Value.Trim() : "[1]";
                arrayDim = arrayDim.Substring(1, arrayDim.Length - 2);

                if (match.Groups[4].Success)
                {
                    var a = vectorDim;
                    vectorDim = matrixDim;
                    matrixDim = a;
                }

                ResourceFormat fmt = new ResourceFormat(FormatComponentType.None, 0, 0);

                bool hex = false;

                FormatComponentType type = FormatComponentType.Float;
                uint count       = 0;
                uint arrayCount  = 1;
                uint matrixCount = 0;
                uint width       = 0;

                // check for square matrix declarations like 'mat4' and 'mat3'
                if (basetype == "mat" && !match.Groups[4].Success)
                {
                    matrixDim = vectorDim;
                }

                // calculate format
                {
                    if (!uint.TryParse(vectorDim, out count))
                    {
                        errors  = "Invalid vector dimension on line:\n" + line;
                        success = false;
                        break;
                    }
                    if (!uint.TryParse(arrayDim, out arrayCount))
                    {
                        arrayCount = 1;
                    }
                    arrayCount = Math.Max(0, arrayCount);
                    if (!uint.TryParse(matrixDim, out matrixCount))
                    {
                        errors  = "Invalid matrix second dimension on line:\n" + line;
                        success = false;
                        break;
                    }

                    if (basetype == "bool")
                    {
                        type  = FormatComponentType.UInt;
                        width = 4;
                    }
                    else if (basetype == "byte")
                    {
                        type  = FormatComponentType.SInt;
                        width = 1;
                    }
                    else if (basetype == "ubyte" || basetype == "xbyte")
                    {
                        type  = FormatComponentType.UInt;
                        width = 1;
                    }
                    else if (basetype == "short")
                    {
                        type  = FormatComponentType.SInt;
                        width = 2;
                    }
                    else if (basetype == "ushort" || basetype == "xshort")
                    {
                        type  = FormatComponentType.UInt;
                        width = 2;
                    }
                    else if (basetype == "int" || basetype == "ivec" || basetype == "imat")
                    {
                        type  = FormatComponentType.SInt;
                        width = 4;
                    }
                    else if (basetype == "uint" || basetype == "xint" || basetype == "uvec" || basetype == "umat")
                    {
                        type  = FormatComponentType.UInt;
                        width = 4;
                    }
                    else if (basetype == "half")
                    {
                        type  = FormatComponentType.Float;
                        width = 2;
                    }
                    else if (basetype == "float" || basetype == "vec" || basetype == "mat")
                    {
                        type  = FormatComponentType.Float;
                        width = 4;
                    }
                    else if (basetype == "double")
                    {
                        type  = FormatComponentType.Double;
                        width = 8;
                    }
                    else if (basetype == "unormh")
                    {
                        type  = FormatComponentType.UNorm;
                        width = 2;
                    }
                    else if (basetype == "unormb")
                    {
                        type  = FormatComponentType.UNorm;
                        width = 1;
                    }
                    else if (basetype == "snormh")
                    {
                        type  = FormatComponentType.SNorm;
                        width = 2;
                    }
                    else if (basetype == "snormb")
                    {
                        type  = FormatComponentType.SNorm;
                        width = 1;
                    }
                    else if (basetype == "uintten")
                    {
                        fmt               = new ResourceFormat(FormatComponentType.UInt, 4 * count, 1);
                        fmt.special       = true;
                        fmt.specialFormat = SpecialFormat.R10G10B10A2;
                    }
                    else if (basetype == "unormten")
                    {
                        fmt               = new ResourceFormat(FormatComponentType.UNorm, 4 * count, 1);
                        fmt.special       = true;
                        fmt.specialFormat = SpecialFormat.R10G10B10A2;
                    }
                    else
                    {
                        errors  = "Unrecognised basic type on line:\n" + line;
                        success = false;
                        break;
                    }
                }

                if (basetype == "xint" || basetype == "xshort" || basetype == "xbyte")
                {
                    hex = true;
                }

                if (fmt.compType == FormatComponentType.None)
                {
                    fmt = new ResourceFormat(type, count, width);
                }

                if (arrayCount == 1)
                {
                    FormatElement elem = new FormatElement(name, 0, offset, false, 1, row_major, matrixCount, fmt, hex);

                    uint advance = elem.ByteSize;

                    if (!tightPacking)
                    {
                        // cbuffer packing always works in floats
                        advance = (advance + 3U) & (~3U);

                        // cbuffer packing doesn't allow elements to cross float4 boundaries, nudge up if this was the case
                        if (offset / 16 != (offset + elem.ByteSize - 1) / 16)
                        {
                            elem.offset = offset = (offset + 0xFU) & (~0xFU);
                        }
                    }

                    elems.Add(elem);

                    offset += advance;
                }
                else
                {
                    // when cbuffer packing, arrays are always aligned at float4 boundary
                    if (!tightPacking)
                    {
                        if (offset % 16 != 0)
                        {
                            offset = (offset + 0xFU) & (~0xFU);
                        }
                    }

                    for (uint a = 0; a < arrayCount; a++)
                    {
                        FormatElement elem = new FormatElement(String.Format("{0}[{1}]", name, a), 0, offset, false, 1, row_major, matrixCount, fmt, hex);

                        elems.Add(elem);

                        uint advance = elem.ByteSize;

                        // cbuffer packing each array element is always float4 aligned
                        if (!tightPacking)
                        {
                            advance = (advance + 0xFU) & (~0xFU);
                        }

                        offset += advance;
                    }
                }
            }

            if (!success || elems.Count == 0)
            {
                elems.Clear();

                var fmt = new ResourceFormat(FormatComponentType.UInt, 4, 4);

                if (maxLen > 0 && maxLen < 16)
                {
                    fmt.compCount = 1;
                }
                if (maxLen > 0 && maxLen < 4)
                {
                    fmt.compByteWidth = 1;
                }

                elems.Add(new FormatElement("data", 0, 0, false, 1, false, 1, fmt, true));
            }

            return(elems.ToArray());
        }