Esempio n. 1
0
        /// <summary>
        /// Create a new external class instance by processing the specified compiler block.
        /// </summary>
        /// <param name="block"></param>
        /// <param name="cmd"></param>
        /// <param name="err"></param>
        /// <returns></returns>
        private object CreateInstance(Compiler.Block block, Compiler.Command cmd, Dict scene, CompileException err)
        {
            // check if the command is valid
            if (cmd.ArgCount < 2)
            {
                err.Add("'class' command must specify a class name.", block);
                return(null);
            }

            // create OpenGL name lookup dictionary
            var glNames = new Dictionary <string, int>(scene.Count);

            scene.Keys.ForEach(scene.Values, (k, v) => glNames.Add(k, v.glname));

            // create main class from compiled files
            var classname = cmd[1].Text;
            var instance  = CompilerResults.CompiledAssembly.CreateInstance(
                classname, false, BindingFlags.Default, null,
                new object[] { block.Name, ToDict(block), glNames }, CultureInfo.CurrentCulture, null);

            if (instance == null)
            {
                throw err.Add($"Main class '{classname}' could not be found.", cmd);
            }

            InvokeMethod <List <string> >(instance, "GetErrors")?.ForEach(msg => err.Add(msg, cmd));

            return(instance);
        }
Esempio n. 2
0
        private void ParseImgCmd(Compiler.Command cmd, Dict classes, CompileException err)
        {
            if (cmd.ArgCount != 1 && cmd.ArgCount != 6)
            {
                err.Add("Arguments of the 'img' command are invalid.", cmd);
                return;
            }
            // specify argument types
            var types = new[] {
                typeof(GLTexture),
                typeof(int),
                typeof(int),
                typeof(int),
                typeof(TextureAccess),
                typeof(GpuFormat),
                typeof(string)
            };
            // specify mandatory arguments
            var mandatory = new[] {
                new[] { true, true, true, true, true, true, false },
                new[] { false, true, false, false, false, false, false },
            };

            // parse command arguments
            (var values, var unused) = cmd.Parse(types, mandatory, classes, err);
            // if there are no errors, add the object to the pass
            if (!err.HasErrors)
            {
                texImages.Add(new ResTexImg(values));
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Get text from scene structure by processing the specified command.
        /// </summary>
        /// <param name="cmd"></param>
        /// <param name="scene"></param>
        /// <param name="err"></param>
        /// <returns></returns>
        private static byte[] LoadText(Compiler.Command cmd, Dict scene, CompileException err)
        {
            // Get text from file or text object
            var str = GetText(scene, cmd);

            if (str == null)
            {
                err.Add("Could not process command. Second argument must "
                        + "be a name to a text object or a filename.", cmd);
                return(null);
            }

            // Convert text to byte array
            return(str.ToCharArray().ToBytes());
        }
Esempio n. 4
0
        private void ParseCsharpExec(Compiler.Command cmd, Dict classes, CompileException err)
        {
            // check if command provides the correct amount of parameters
            if (cmd.ArgCount == 0)
            {
                err.Add("Not enough arguments for exec command.", cmd);
                return;
            }

            // get instance
            if (!classes.TryGetValue(cmd[0].Text, out GLInstance instance, cmd, err))
            {
                return;
            }

            csexec.Add(instance);
        }
Esempio n. 5
0
        /// <summary>
        /// Get xml text from scene structure by processing the specified command.
        /// </summary>
        /// <param name="cmd"></param>
        /// <param name="scene"></param>
        /// <param name="err"></param>
        /// <returns></returns>
        private static byte[] LoadXml(Compiler.Command cmd, Dict scene, CompileException err)
        {
            // Get text from file or text object
            string str = GetText(scene, cmd);

            if (str == null)
            {
                err.Add("Could not process command. Second argument must "
                        + "be a name to a text object or a filename.", cmd);
                return(null);
            }

            try
            {
                // Parse XML string
                var document = new XmlDocument();
                document.LoadXml(str);

                // Load data from XML
                var filedata = new byte[cmd.ArgCount - 1][];
                for (int i = 1; i < cmd.ArgCount; i++)
                {
                    try
                    {
                        filedata[i - 1] = DataXml.Load(document, cmd[i].Text);
                    }
                    catch (XmlException ex)
                    {
                        err.Add(ex.Message, cmd);
                    }
                }

                // Merge data
                if (!err.HasErrors)
                {
                    return(filedata.Cat().ToArray());
                }
            }
            catch (Exception ex)
            {
                err.Add(ex.GetBaseException().Message, cmd);
            }

            return(null);
        }
Esempio n. 6
0
        private void ParseComputeCall(Compiler.Command cmd, Dict classes, CompileException err)
        {
            // check for errors
            if (cmd.ArgCount < 2 || cmd.ArgCount > 3)
            {
                err.Add("Compute command does not provide enough arguments "
                        + "(e.g., 'compute num_groups_X num_groups_y num_groups_z' or "
                        + "'compute buffer_name indirect_pointer').", cmd);
                return;
            }

            try
            {
                var call = new CompCall();

                // this is an indirect compute call
                if (cmd.ArgCount == 2)
                {
                    // indirect compute call buffer
                    call.numGroupsX = (uint)classes.GetValue <GLBuffer>(cmd[0].Text,
                                                                        "First argument of compute command must be a buffer name").glname;
                    // indirect compute call buffer pointer
                    call.numGroupsY = cmd[1].Text.To <uint>("Argument must be an unsigned integer, "
                                                            + "specifying a pointer into the indirect compute call buffer.");
                }
                // this is a normal compute call
                else
                {
                    // number of compute groups
                    call.numGroupsX = cmd[0].Text.To <uint>("Argument must be an unsigned integer, "
                                                            + "specifying the number of compute groups in X.");
                    call.numGroupsY = cmd[1].Text.To <uint>("Argument must be an unsigned integer, "
                                                            + "specifying the number of compute groups in Y.");
                    call.numGroupsZ = cmd[2].Text.To <uint>("Argument must be an unsigned integer, "
                                                            + "specifying the number of compute groups in Z.");
                }

                compcalls.Add(call);
            }
            catch (CompileException ex)
            {
                err.Add(ex.Message, cmd);
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Set a field of the specified class to the specified value.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="clazz"></param>
        /// <param name="field"></param>
        /// <param name="fieldType"></param>
        /// <param name="cmd"></param>
        /// <param name="err"></param>
        static private void SetValue <T>(T clazz, object field, Type fieldType,
                                         Compiler.Command cmd, CompileException err = null)
        {
            // check for errors
            if (cmd.ArgCount == 0)
            {
                err?.Add($"Command '{cmd.Text}' has no arguments (must have at least one).", cmd);
            }
            if (!fieldType.IsArray && cmd.ArgCount > 1)
            {
                err?.Add($"Command '{cmd.Text}' has too many arguments (more than one).", cmd);
            }
            if (err != null && err.HasErrors)
            {
                return;
            }

            object val = null;

            if (fieldType.IsArray)
            {
                var elType = fieldType.GetElementType();
                var array  = Array.CreateInstance(elType, cmd.Length);
                for (int i = 0; i < cmd.Length; i++)
                {
                    array.SetValue(Convert.ChangeType(cmd[i].Text, elType, CultureInfo.CurrentCulture), i);
                }
                val = array;
            }
            else
            {
                val = fieldType.IsEnum
                      // if this is an enum, convert the string to an enum value
                    ? Convert.ChangeType(Enum.Parse(fieldType, cmd[0].Text, true), fieldType)
                      // else try to convert it to the field type
                    : Convert.ChangeType(cmd[0].Text, fieldType, CultureInfo.CurrentCulture);
            }

            // set value of the field
            field.GetType()
            .GetMethod("SetValue", new[] { typeof(object), typeof(object) })
            .Invoke(field, new object[] { clazz, val });
        }
Esempio n. 8
0
        /// <summary>
        /// Get text from scene objects.
        /// </summary>
        /// <param name="scene"></param>
        /// <param name="cmd"></param>
        /// <returns></returns>
        private static string GetText(Dict scene, Compiler.Command cmd)
        {
            GLText text = null;
            string dir  = Path.GetDirectoryName(cmd.File) + Path.DirectorySeparatorChar;

            if (scene.TryGetValue(cmd[0].Text, ref text))
            {
                return(text.Text.Trim());
            }
            else if (File.Exists(cmd[0].Text))
            {
                return(File.ReadAllText(cmd[0].Text));
            }
            else if (File.Exists(dir + cmd[0].Text))
            {
                return(File.ReadAllText(dir + cmd[0].Text));
            }
            return(null);
        }
Esempio n. 9
0
        private void ParseSampCmd(Compiler.Command cmd, Dict classes, CompileException err)
        {
            if (cmd.ArgCount != 1 && cmd.ArgCount != 2)
            {
                err.Add("Arguments of the 'samp' command are invalid.", cmd);
                return;
            }
            // specify argument types
            var types = new[] { typeof(GLSampler), typeof(int), typeof(string) };
            // specify mandatory arguments
            var mandatory = new[] { new[] { true, true, false }, new[] { false, true, false } };

            // parse command arguments
            (var values, var unused) = cmd.Parse(types, mandatory, classes, err);
            // if there are no errors, add the object to the pass
            if (!err.HasErrors)
            {
                sampler.Add(new Res <GLSampler>(values));
            }
        }
Esempio n. 10
0
        /// <summary>
        /// Create a new external method-call by processing the specified compiler command.
        /// </summary>
        /// <param name="cmd"></param>
        /// <param name="err"></param>
        /// <returns></returns>
        private MethodInfo GetMethod(Compiler.Command cmd, CompileException err)
        {
            // check if the command is valid
            if (cmd.ArgCount < 2)
            {
                err.Add("'class' command must specify a class name.", cmd);
                return(null);
            }
            if (cmd.ArgCount < 3)
            {
                err.Add("'class' command must specify a method name.", cmd);
                return(null);
            }

            var classname  = cmd[1].Text;
            var methodname = cmd[2].Text;
            var type       = CompilerResults.CompiledAssembly.GetType(classname);

            return(type?.GetMethod(methodname, BindingFlags.Public | BindingFlags.Static));
        }
Esempio n. 11
0
        /// <summary>
        /// Create a new external method-call by processing the specified compiler command.
        /// </summary>
        /// <param name="cmd"></param>
        /// <param name="err"></param>
        /// <returns></returns>
        internal static MethodInfo GetMethod(Compiler.Command cmd, Dict scene, CompileException err)
        {
            // check command
            if (cmd.ArgCount < 1)
            {
                err.Add("'class' command must specify a csharp object name.", cmd);
                return(null);
            }

            // FIND CSHARP CLASS DEFINITION
            var csharp = scene.GetValueOrDefault <GLCsharp>(cmd[0].Text);

            if (csharp == null)
            {
                err.Add($"Could not find csharp code '{cmd[0].Text}' of command '{cmd.Text}' ", cmd);
                return(null);
            }

            // INSTANTIATE CSHARP CLASS
            return(csharp.GetMethod(cmd, err));
        }
Esempio n. 12
0
        /// <summary>
        /// Parse command line and attach the buffer object
        /// to the specified unit (output stream).
        /// </summary>
        /// <param name="unit">Vertex output stream unit.</param>
        /// <param name="cmd">Command line to process.</param>
        /// <param name="scene">Dictionary of scene objects.</param>
        /// <param name="err">Compiler exception collector.</param>
        private void Attach(int unit, Compiler.Command cmd, Dict scene, CompileException err)
        {
            if (cmd.ArgCount == 0)
            {
                err.Add("Command buff needs at least one attribute (e.g. 'buff buff_name')", cmd);
                return;
            }

            // get buffer
            var buf = scene.GetValueOrDefault <GLBuffer>(cmd[0].Text);

            if (buf == null)
            {
                err.Add($"The name '{cmd[0]}' does not reference an object of type 'buffer'.", cmd);
                return;
            }

            // parse offset
            int offset = 0;

            if (cmd.ArgCount > 1 && int.TryParse(cmd[1].Text, out offset) == false)
            {
                err.Add($"The second parameter (offset) of buff {unit} is invalid.", cmd);
                return;
            }

            // parse size
            int size = buf.Size;

            if (cmd.ArgCount > 2 && int.TryParse(cmd[2].Text, out size) == false)
            {
                err.Add($"The third parameter (size) of buff {unit} is invalid.", cmd);
                return;
            }

            // bind buffer to transform feedback
            GL.BindBufferRange(BufferRangeTarget.TransformFeedbackBuffer,
                               unit, buf.glname, (IntPtr)offset, (IntPtr)size);
        }
Esempio n. 13
0
        private void ParseOpenGLCall(Compiler.Command cmd, CompileException err)
        {
            // find OpenGL method
            var mname = cmd.Name.StartsWith("gl") ? cmd.Name.Substring(2) : cmd.Name;
            var mtype = FindMethod(mname, cmd.ArgCount);

            if (mtype == null)
            {
                if (GetFxField(mname) == null)
                {
                    err.Add("Unknown command '" + cmd.Text + "'", cmd);
                }
                return;
            }

            // get method parameter types
            var param = mtype.GetParameters();
            var inval = new object[param.Length];

            // convert strings to parameter types
            for (int i = 0; i < param.Length; i++)
            {
                if (param[i].ParameterType.IsEnum)
                {
                    inval[i] = Convert.ChangeType(
                        Enum.Parse(param[i].ParameterType, cmd[i].Text, true),
                        param[i].ParameterType);
                }
                else
                {
                    inval[i] = Convert.ChangeType(cmd[i].Text, param[i].ParameterType, CultureInfo.CurrentCulture);
                }
            }

            glfunc.Add(new GLMethod(mtype, inval));
        }
Esempio n. 14
0
 public static CompileException Add(this CompileException err, string message,
                                    Compiler.Command cmd)
 {
     return(err.Add(message, cmd.File, cmd.LineInFile));
 }
Esempio n. 15
0
 public static bool TryGetValue <T>(this Dict dict, string key, out T obj,
                                    Compiler.Command cmd, CompileException err)
     where T : GLObject
 {
     return(dict.TryGetValue(key, out obj, cmd.LineInFile, cmd.File, err));
 }
Esempio n. 16
0
        /// <summary>
        /// Parse command line and attach the buffer object
        /// to the specified unit (input stream).
        /// </summary>
        /// <param name="unit"></param>
        /// <param name="cmd"></param>
        /// <param name="scene"></param>
        /// <param name="err"></param>
        private void Attach(int unit, Compiler.Command cmd, Dict scene, CompileException err)
        {
            // check commands for errors
            if (cmd.ArgCount < 3)
            {
                err.Add("Command attr needs at least 3 attributes (e.g. 'attr buff_name float 4')", cmd);
                return;
            }

            // parse command arguments
            string buffname = cmd[0].Text;
            string typename = cmd[1].Text;
            int    length   = int.Parse(cmd[2].Text);
            int    stride   = cmd.ArgCount > 3 ? int.Parse(cmd[3].Text) : 0;
            int    offset   = cmd.ArgCount > 4 ? int.Parse(cmd[4].Text) : 0;
            int    divisor  = cmd.ArgCount > 5 ? int.Parse(cmd[5].Text) : 0;

            if (scene.TryGetValue(buffname, out GLBuffer buff, cmd, err) == false)
            {
                err.Add($"Buffer '{buffname}' could not be found.", cmd);
                return;
            }

            // enable vertex array attribute
            GL.BindBuffer(BufferTarget.ArrayBuffer, buff.glname);
            GL.EnableVertexAttribArray(unit);

            // bind buffer to vertex array attribute
            int type = 0;

            if (Enum.TryParse(typename, true, out VertAttrIntType typei))
            {
                GL.VertexAttribIPointer(unit, length, (IntType)(type = (int)typei), stride, (IntPtr)offset);
            }
            else if (Enum.TryParse(typename, true, out VertAttrType typef))
            {
                GL.VertexAttribPointer(unit, length, (PointerType)(type = (int)typef), false, stride, offset);
            }
            else
            {
                err.Add($"Type '{typename}' is not supported.", cmd);
            }

            if (divisor > 0)
            {
                GL.VertexAttribDivisor(unit, divisor);
            }

            GL.BindBuffer(BufferTarget.ArrayBuffer, 0);

            // add vertex attribute
            attributes.Add(new VertAttr()
            {
                buffer  = buff,
                type    = type,
                length  = length,
                stride  = stride,
                offset  = offset,
                divisor = divisor,
            });
        }
Esempio n. 17
0
        private void ParseDrawCall(Compiler.Command cmd, Dict classes, CompileException err)
        {
            var          args      = new List <int>();
            GLVertinput  vertexin  = null;
            GLVertoutput vertout   = null;
            GLBuffer     indexbuf  = null;
            GLBuffer     indirect  = null;
            bool         modeIsSet = false;
            bool         typeIsSet = false;
            PrimType     primitive = 0;
            ElementType  indextype = 0;

            // parse draw call arguments
            foreach (var arg in cmd)
            {
                if (classes.TryGetValue(arg.Text, ref vertexin))
                {
                    continue;
                }
                if (classes.TryGetValue(arg.Text, ref vertout))
                {
                    continue;
                }
                if (classes.TryGetValue(arg.Text, ref indexbuf))
                {
                    continue;
                }
                if (classes.TryGetValue(arg.Text, ref indirect))
                {
                    continue;
                }
                if (int.TryParse(arg.Text, out int val))
                {
                    args.Add(val);
                }
                else if (typeIsSet == false && Enum.TryParse(arg.Text, true, out indextype))
                {
                    typeIsSet = true;
                }
                else if (modeIsSet == false && Enum.TryParse(arg.Text, true, out primitive))
                {
                    modeIsSet = true;
                }
                else
                {
                    err.Add($"Unable to process argument '{arg.Text}'.", cmd);
                }
            }

            if (err.HasErrors)
            {
                return;
            }

            // a draw call must specify a primitive type
            if (modeIsSet == false)
            {
                err.Add("Draw call must specify a primitive type (e.g. triangles, "
                        + "trianglefan, lines, points, ...).", cmd);
                return;
            }

            // determine the right draw call function
            int bits = (vertout != null ? 1 : 0)
                       | (indexbuf != null ? 2 : 0)
                       | (indirect != null ? 4 : 0)
                       | (typeIsSet ? 8 : 0);

            if (!Enum.IsDefined(typeof(DrawFunc), bits))
            {
                err.Add("Draw call function not recognized or ambiguous.", cmd);
                return;
            }

            var drawfunc = (DrawFunc)bits;

            // get index buffer object (if present) and find existing MultiDraw class
            var multidrawcall = drawcalls.Find(
                x => x.vertexin == (vertexin != null ? vertexin.glname : 0) &&
                x.indexbuf == (indexbuf != null ? indexbuf.glname : 0) &&
                x.vertout == (vertout != null ? vertout.glname : 0) &&
                x.indirect == (indirect != null ? indirect.glname : 0))
                                ?? new MultiDrawCall(drawfunc, vertexin, vertout, indexbuf, indirect);

            // add new draw command to the MultiDraw class
            multidrawcall.cmd.Add(new DrawCall(drawfunc, primitive, indextype, args));

            drawcalls.Add(multidrawcall);
        }