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)); } }
/// <summary> /// Link image or buffer object to the texture. /// </summary> /// <param name="file"></param> /// <param name="line"></param> /// <param name="err"></param> private void Link(string file, int line, CompileException err) { // IN CASE THIS IS A TEXTURE OBJECT if (glImg != null) { glname = glImg.glname; // get internal format GL.GetTextureLevelParameter(glname, 0, GetTextureParameter.TextureInternalFormat, out int f); Format = (GpuFormat)f; } // IN CASE THIS IS A BUFFER OBJECT else if (glBuff != null) { if (Format == 0) { throw err.Add($"No texture buffer format defined for " + "buffer '{buff}' (e.g. format RGBA8).", file, line); } // CREATE OPENGL OBJECT glname = GL.GenTexture(); GL.BindTexture(TextureTarget.TextureBuffer, glname); GL.TexBuffer(TextureBufferTarget.TextureBuffer, (SizedInternalFormat)Format, glBuff.glname); GL.BindTexture(TextureTarget.TextureBuffer, 0); } }
/// <summary> /// Create OpenGL object. Standard object constructor for ProtoFX. /// </summary> /// <param name="block"></param> /// <param name="scene"></param> /// <param name="debugging"></param> public GLSampler(Compiler.Block block, Dict scene, bool debugging) : base(block.Name, block.Anno) { var err = new CompileException($"sampler '{Name}'"); // PARSE ARGUMENTS Cmds2Fields(block, err); // CREATE OPENGL OBJECT glname = GL.GenSampler(); int mini = (int)Minfilter; int magi = (int)Magfilter; int wrapi = (int)Wrap; GL.SamplerParameterI(glname, SamplerParameterName.TextureMinFilter, ref mini); GL.SamplerParameterI(glname, SamplerParameterName.TextureMagFilter, ref magi); GL.SamplerParameterI(glname, SamplerParameterName.TextureWrapR, ref wrapi); GL.SamplerParameterI(glname, SamplerParameterName.TextureWrapS, ref wrapi); GL.SamplerParameterI(glname, SamplerParameterName.TextureWrapT, ref wrapi); HasErrorOrGlError(err, block); if (err.HasErrors) { throw err; } }
/// <summary> /// Create a new external class instance by processing the specified compiler block. /// </summary> /// <param name="block"></param> /// <param name="scene"></param> /// <param name="err"></param> /// <returns></returns> internal static object CreateInstance(Compiler.Block block, Dict scene, CompileException err) { // GET CLASS COMMAND var cmds = block["class"].ToList(); if (cmds.Count == 0) { err.Add("Instance must specify a 'class' command " + "(e.g., class csharp_name class_name).", block); return(null); } var cmd = cmds.First(); // 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.CreateInstance(block, cmd, scene, err)); }
/// <summary> /// Create OpenGL object. Standard object constructor for ProtoFX. /// </summary> /// <param name="block"></param> /// <param name="scene"></param> /// <param name="debugging"></param> public GLVertinput(Compiler.Block block, Dict scene, bool debugging) : base(block.Name, block.Anno) { var err = new CompileException($"vertinput '{Name}'"); // CREATE OPENGL OBJECT glname = GL.GenVertexArray(); GL.BindVertexArray(glname); int numAttr = 0; foreach (var cmd in block["attr"]) { Attach(numAttr++, cmd, scene, err | $"command '{cmd.Text}'"); } // if errors occurred throw exception if (err.HasErrors) { throw err; } // unbind object and check for errors GL.BindVertexArray(0); if (HasErrorOrGlError(err, block)) { throw err; } }
/// <summary> /// Create OpenGL object. Standard object constructor for ProtoFX. /// </summary> /// <param name="block"></param> /// <param name="scene"></param> /// <param name="debugging"></param> public GLVertoutput(Compiler.Block block, Dict scene, bool debugging) : base(block.Name, block.Anno) { var err = new CompileException($"vertoutput '{Name}'"); // PARSE ARGUMENTS Cmds2Fields(block, err); // CREATE OPENGL OBJECT glname = GL.GenTransformFeedback(); GL.BindTransformFeedback(TransformFeedbackTarget.TransformFeedback, glname); // parse commands int numbindings = 0; foreach (var cmd in block["buff"]) { Attach(numbindings++, cmd, scene, err | $"command '{cmd.Text}'"); } // if errors occurred throw exception if (err.HasErrors) { throw err; } // unbind object and check for errors GL.BindTransformFeedback(TransformFeedbackTarget.TransformFeedback, 0); if (HasErrorOrGlError(err, block)) { throw err; } }
/// <summary> /// Check for compiler and OpenGL errors. /// </summary> /// <param name="err"></param> /// <param name="file"></param> /// <param name="line"></param> /// <returns></returns> static protected bool HasErrorOrGlError(CompileException err, string file, int line) { var errcode = GL.GetError(); if (errcode != ErrorCode.NoError) { err.Add($"OpenGL error '{errcode}' occurred.", file, line); return(true); } return(err.HasErrors); }
/// <summary> /// Check for compiler and OpenGL errors. /// </summary> /// <param name="err"></param> /// <param name="block"></param> /// <returns></returns> static protected bool HasErrorOrGlError(CompileException err, Compiler.Block block) { var errcode = GL.GetError(); if (errcode != ErrorCode.NoError) { err.Add($"OpenGL error '{errcode}' occurred.", block); return(true); } return(err.HasErrors); }
private GLShader Attach(Compiler.Block block, string shadername, Dict classes, CompileException err) { GLShader obj = null; // get shader from class list if (shadername != null && classes.TryGetValue(shadername, out obj, block, err)) { GL.UseProgramStages(glname, ShaderType2ShaderBit(obj.ShaderType), obj.glname); } return(obj); }
/// <summary> /// Parse the command and extract arguments as values. /// </summary> /// <param name="types">List of argument types.</param> /// <param name="mandatory">Specifies which of this arguments are mandatory.</param> /// <param name="unusedArgs">List of arguments the where not parsed.</param> /// <param name="scene">Dictionary of scene objects.</param> /// <param name="err"></param> /// <returns>List of objects values. If a value could not be /// parsed, the returned value will be null.</returns> public (object[], string[]) Parse(Type[] types, bool[][] mandatory, Dict scene, CompileException err = null) { var values = new object[types.Length]; // parse command arguments var lastArgUsed = 0; for (var a = 0; a < Length; a++) { var arg = this[a]; var I = values .Zip(Enumerable.Range(0, types.Length), (x, i) => x == null ? i : -1) .Where(x => x >= 0); foreach (var i in I) { try { values[i] = types[i].IsSubclassOf(typeof(GLObject)) ? scene.GetValueOrDefault <GLObject>(arg.Text) : types[i].IsEnum ? Enum.Parse(types[i], arg.Text, true) : Convert.ChangeType(arg.Text, types[i], CultureInfo.CurrentCulture); if (values[i] != null) { lastArgUsed = a; break; } } catch { } } } // return list of unused arguments var unusedArgs = this.Skip(lastArgUsed + 1).Select(x => x.Text).ToArray(); // check for errors var valid = values.Select(x => x != null); for (int i = 0; i < mandatory.Length; i++) { if (mandatory[i].Zip(valid, (m, v) => !m | v).All(x => x)) { return(values, unusedArgs); } } err?.Add("Command has one or more invalid arguments.", this); return(values, unusedArgs); }
/// <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()); }
/// <summary> /// Construct GLBuffer object. /// </summary> /// <param name="name">Name of the object.</param> /// <param name="anno">Annotation of the object.</param> /// <param name="usage">How the buffer should be used by the program.</param> /// <param name="size">The memory size to be allocated in bytes.</param> /// <param name="data">Optionally initialize the buffer object with the specified data.</param> public GLBuffer(string name, string anno, UsageHint usage, int size, byte[] data = null) : base(name, anno) { var err = new CompileException($"buffer '{name}'"); Size = size; Usage = usage; // CREATE OPENGL OBJECT CreateBuffer(data); if (HasErrorOrGlError(err, "", -1)) { throw err; } }
/// <summary> /// Create OpenGL object. Standard object constructor for ProtoFX. /// </summary> /// <param name="block"></param> /// <param name="scene"></param> /// <param name="debugging"></param> public GLCsharp(Compiler.Block block, Dict scene, bool debugging) : base(block.Name, block.Anno) { var err = new CompileException($"csharp '{Name}'"); // PARSE ARGUMENTS Cmds2Fields(block, err); // check for errors if (err.HasErrors) { throw err; } if (File == null || File.Length == 0) { return; } // LOAD ADDITIONAL ASSEMBLIES if (Assembly != null) { foreach (var assemblypath in Assembly) { try { System.Reflection.Assembly.LoadFrom(assemblypath); } catch (FileNotFoundException) { err.Add($"Assembly file '{assemblypath}' cound not be found.", block); } catch (FileLoadException) { err.Add($"Assembly '{assemblypath}' cound not be loaded.", block); } catch { err.Add($"Unknown exception when loading assembly '{assemblypath}'.", block); } } } // replace placeholders with actual path var dir = Path.GetDirectoryName(block.Filename) + Path.DirectorySeparatorChar; var filepath = ProcessPaths(dir, File); // COMPILE FILES CompilerResults = CompileFilesOrSource(filepath.ToArray(), Version, block, err); // check for errors if (err.HasErrors) { throw err; } }
/// <summary> /// Create OpenGL object. Standard object constructor for ProtoFX. /// </summary> /// <param name="block"></param> /// <param name="scene"></param> /// <param name="debugging"></param> public GLTech(Compiler.Block block, Dict scene, bool debugging) : base(block.Name, block.Anno, 309, debugging) { var err = new CompileException($"tech '{Name}'"); // PARSE COMMANDS ParsePasses(ref init, block, scene, err); ParsePasses(ref passes, block, scene, err); ParsePasses(ref uninit, block, scene, err); // IF THERE ARE ERRORS THROW AND EXCEPTION if (err.HasErrors) { throw err; } }
/// <summary> /// Parse commands in block. /// </summary> /// <param name="list"></param> /// <param name="block"></param> /// <param name="scene"></param> /// <param name="err"></param> private void ParsePasses(ref List <GLPass> list, Compiler.Block block, Dict scene, CompileException err) { var cmdName = ReferenceEquals(list, init) ? "init" : ReferenceEquals(list, passes) ? "pass" : "uninit"; foreach (var cmd in block[cmdName]) { if (scene.TryGetValue(cmd[0].Text, out GLPass pass, block, err | $"command '{cmd.Text}'")) { list.Add(pass); } } }
/// <summary> /// Create OpenGL object specifying the texture /// format and referenced scene objects directly. /// </summary> /// <param name="name"></param> /// <param name="anno"></param> /// <param name="format"></param> /// <param name="glbuff"></param> /// <param name="glimg"></param> public GLTexture(string name, string anno, GpuFormat format, GLBuffer glbuff, GLImage glimg) : base(name, anno) { var err = new CompileException($"texture '{name}'"); // set name Format = format; glBuff = glbuff; glImg = glimg; // INCASE THIS IS A TEXTURE OBJECT Link("", -1, err); if (HasErrorOrGlError(err, "", -1)) { throw err; } }
/// <summary> /// Try to find the value to a key. If the key could not be found add an exception message. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key">Key to search for.</param> /// <param name="obj">Output object reference.</param> /// <param name="file">Specify the file identifying an exception if it occurs.</param> /// <param name="line">Specify the file line identifying an exception if it occurs.</param> /// <param name="err">Add new exceptions to this existing one.</param> /// <returns></returns> public bool TryGetValue <T>(string key, out T obj, int line, string file, CompileException err) where T : GLObject { // try to find the object instance if ((obj = GetValueOrDefault <T>(key)) != default(T)) { return(true); } // get class name of object type var classname = typeof(T).Name.Substring(2).ToLower(); err.Add($"The name '{key}' could not be found or does not " + $"reference an object of type '{classname}'.", file, line); return(false); }
/// <summary> /// Create OpenGL object. Standard object constructor for ProtoFX. /// </summary> /// <param name="block"></param> /// <param name="scene"></param> /// <param name="debugging"></param> public GLBuffer(Compiler.Block block, Dict scene, bool debugging) : base(block.Name, block.Anno) { var err = new CompileException($"buffer '{block.Name}'"); // PARSE COMMANDS AND CONVERT THEM TO CLASS FIELDS Cmds2Fields(block, err); // PARSE COMMANDS var datalist = new List <byte[]>(); foreach (var cmd in block["txt"]) { datalist.Add(LoadText(cmd, scene, err | $"command {cmd.Name} 'txt'")); } foreach (var cmd in block["xml"]) { datalist.Add(LoadXml(cmd, scene, err | $"command {cmd.Name} 'xml'")); } // merge data into a single array var iter = datalist.Cat(); var data = iter.Take(Size == 0 ? iter.Count() : Size).ToArray(); if (Size == 0) { Size = data.Length; } // CONVERT DATA var clazz = block["class"].FirstOrDefault(); if (clazz != null && Size > 0) { var converter = GLCsharp.GetMethod(clazz, scene, err); data = (byte[])converter?.Invoke(null, new[] { data }); } // CREATE OPENGL OBJECT CreateBuffer(data); if (HasErrorOrGlError(err, block)) { throw err; } }
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); }
/// <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); }
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); } }
/// <summary> /// Create OpenGL object specifying the referenced scene objects directly. /// </summary> /// <param name="block"></param> /// <param name="scene"></param> /// <param name="glbuff"></param> /// <param name="glimg"></param> public GLTexture(Compiler.Block block, Dict scene, GLBuffer glbuff, GLImage glimg) : base(block.Name, block.Anno) { var err = new CompileException($"texture '{Name}'"); // PARSE ARGUMENTS Cmds2Fields(block, err); // set name glBuff = glbuff; glImg = glimg; // GET REFERENCES if (Buff != null) { scene.TryGetValue(Buff, out glBuff, block, err); } if (Img != null) { scene.TryGetValue(Img, out glImg, block, err); } if (glBuff != null && glImg != null) { err.Add("Only an image or a buffer can be bound to a texture object.", block); } if (glBuff == null && glImg == null) { err.Add("Ether an image or a buffer has to be bound to a texture object.", block); } // IF THERE ARE ERRORS THROW AND EXCEPTION if (err.HasErrors) { throw err; } // INCASE THIS IS A TEXTURE OBJECT Link(block.Filename, block.LineInFile, err); if (HasErrorOrGlError(err, block)) { throw err; } }
/// <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 }); }
/// <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)); }
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)); } }
/// <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)); }
/// <summary> /// Create class instance of a C# class compiled through GLCSharp. /// </summary> /// <param name="params">Input parameters for GLObject creation.</param> public GLInstance(Compiler.Block block, Dict scene, bool debugging) : base(block.Name, block.Anno) { var err = new CompileException($"instance '{Name}'"); // INSTANTIATE CSHARP CLASS FROM CODE BLOCK Instance = GLCsharp.CreateInstance(block, scene, err); if (err.HasErrors) { throw err; } // get Bind method from main class instance update = Instance.GetType().GetMethod("Update", new[] { typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) }); // get Unbind method from main class instance endpass = Instance.GetType().GetMethod("EndPass", new[] { typeof(int) }); // get Delete method from main class instance delete = Instance.GetType().GetMethod("Delete"); // get all public methods and check whether // they can be used as event handlers for glControl var reference = scene.GetValueOrDefault <GLReference>(GraphicControl.nullname); var glControl = (GraphicControl)reference.Reference; var methods = Instance.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance); foreach (var method in methods) { var info = glControl.GetType().GetEvent(method.Name); if (info != null) { var csmethod = Delegate.CreateDelegate(info.EventHandlerType, Instance, method.Name); info.AddEventHandler(glControl, csmethod); } } }
/// <summary> /// Process object block and try to convert commands to class internal fields. /// </summary> /// <param name="block"></param> /// <param name="err"></param> protected void Cmds2Fields(Compiler.Block block, CompileException err = null) { foreach (var cmd in block) { // check if the name is too short for a field if (cmd.Name.Length < 2) { continue; } // get field member info var member = GetFxField(cmd.Name); if (member != null) { // set value of field SetValue(this, member, member is FieldInfo ? (member as FieldInfo).FieldType : (member as PropertyInfo).PropertyType, cmd, err); } } }
/// <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); }
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)); }