Beispiel #1
0
 public static bool TryGetValue <T>(this Dict dict, string key, out T obj,
                                    Compiler.Block block, CompileException err)
     where T : GLObject
 {
     return(dict.TryGetValue(key, out obj, block.LineInFile, block.Filename, err));
 }
Beispiel #2
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));
 }
Beispiel #3
0
        /// <summary>
        /// Create OpenGL object. Standard object constructor for ProtoFX.
        /// </summary>
        /// <param name="block"></param>
        /// <param name="scene"></param>
        /// <param name="genDebugInfo"></param>
        public GLPass(Compiler.Block block, Dict scene, bool genDebugInfo)
            : base(block.Name, block.Anno, 309, genDebugInfo)
        {
            var err = new CompileException($"pass '{Name}'");

            GenDebugInfo = genDebugInfo;

            /// PARSE COMMANDS AND CONVERT THEM TO CLASS FIELDS

            Cmds2Fields(block, err);

            /// PARSE COMMANDS

            foreach (var cmd in block)
            {
                // ignore class fields
                var field = GetType().GetField(cmd.Name, Instance | Public | NonPublic);
                var attr  = field?.GetCustomAttributes(typeof(FxField), false);
                if (attr?.Length > 0)
                {
                    continue;
                }

                using (var e = err | $"command '{cmd.Name}' line {cmd.LineInFile}")
                {
                    switch (cmd.Name)
                    {
                    case "draw": ParseDrawCall(cmd, scene, e); break;

                    case "compute": ParseComputeCall(cmd, scene, e); break;

                    case "tex": ParseTexCmd(cmd, scene, e); break;

                    case "img": ParseImgCmd(cmd, scene, e); break;

                    case "samp": ParseSampCmd(cmd, scene, e); break;

                    case "exec": ParseCsharpExec(cmd, scene, e); break;

                    case "vertout": vertoutput = new Vertoutput(cmd, scene, e);  break;

                    case "fragout": scene.TryGetValue(cmd[0].Text, out fragoutput, cmd, e); break;

                    default: ParseOpenGLCall(cmd, e); break;
                    }
                }
            }

            if (err.HasErrors)
            {
                throw err;
            }

            /// CREATE OPENGL OBJECT

            if (Vert != null || Comp != null)
            {
                GL.CreateProgramPipelines(1, out glname);

                // Attach shader objects.
                // First try attaching a compute shader. If that
                // fails, try attaching the default shader pipeline.
                if ((glcomp = Attach(block, Comp, scene, err)) == null)
                {
                    glvert = Attach(block, Vert, scene, err);
                    gltess = Attach(block, Tess, scene, err);
                    gleval = Attach(block, Eval, scene, err);
                    glgeom = Attach(block, Geom, scene, err);
                    glfrag = Attach(block, Frag, scene, err);
                }

                // get debug shaders
                if (GenDebugInfo)
                {
                    if (glcomp != null)
                    {
                        dbgcomp = (CompShader)glcomp.DebugShader;
                    }
                    else
                    {
                        Shader prev =
                            dbgvert = (VertShader)glvert.DebugShader;
                        dbgtess     = (TessShader)gltess?.DebugShader;
                        dbgeval     = (EvalShader)gleval?.DebugShader;
                        dbggeom     = (GeomShader)glgeom?.DebugShader;
                        dbgfrag     = (FragShader)glfrag?.DebugShader;
                        if (dbgtess != null)
                        {
                            dbgtess.Prev = prev;
                            prev         = dbgtess;
                        }
                        if (dbgeval != null)
                        {
                            dbgeval.Prev = prev;
                            prev         = dbgeval;
                        }
                        if (dbggeom != null)
                        {
                            dbggeom.Prev = prev;
                            prev         = dbggeom;
                        }
                    }
                }
            }

            /// CHECK FOR ERRORS

            if (GL.GetError() != ErrorCode.NoError)
            {
                err.Add($"OpenGL error '{GL.GetError()}' occurred " +
                        "during shader program creation.", block);
            }
            if (err.HasErrors)
            {
                throw err;
            }
        }
Beispiel #4
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);
        }
Beispiel #5
0
 /// <summary>
 /// Create OpenGL object. Standard object constructor for ProtoFX.
 /// </summary>
 /// <param name="block"></param>
 /// <param name="scene"></param>
 /// <param name="debugging"></param>
 public GLTexture(Compiler.Block block, Dict scene, bool debugging)
     : this(block, scene, null, null)
 {
 }
Beispiel #6
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,
            });
        }