Beispiel #1
0
        public GuiRenderer(IGL owner)
        {
            Owner = owner;

            VertexLayout = owner.CreateVertexLayout();
            VertexLayout.DefineVertexAttribute("aPosition", 0, 2, VertexAttribPointerType.Float, AttributeUsage.Position, false, 32, 0);
            VertexLayout.DefineVertexAttribute("aTexcoord", 1, 2, VertexAttribPointerType.Float, AttributeUsage.Texcoord0, false, 32, 8);
            VertexLayout.DefineVertexAttribute("aColor", 2, 4, VertexAttribPointerType.Float, AttributeUsage.Texcoord1, false, 32, 16);
            VertexLayout.Close();

            _Projection = new MatrixStack();
            _Modelview  = new MatrixStack();

            string psProgram, vsProgram;

            if (owner.API == "D3D9")
            {
                vsProgram = DefaultShader_d3d9;
                psProgram = DefaultShader_d3d9;
            }
            else
            {
                vsProgram = DefaultVertexShader_gl;
                psProgram = DefaultPixelShader_gl;
            }

            var vs = Owner.CreateVertexShader(false, vsProgram, "vsmain", true);
            var ps = Owner.CreateFragmentShader(false, psProgram, "psmain", true);

            CurrPipeline = DefaultPipeline = Owner.CreatePipeline(VertexLayout, vs, ps, true, "xgui");
        }
Beispiel #2
0
 public void Dispose()
 {
     VertexLayout.Dispose();
     VertexLayout = null;
     DefaultPipeline.Dispose();
     DefaultPipeline = null;
 }
Beispiel #3
0
        public Pipeline(IGL owner, object opaque, bool available, VertexLayout vertexLayout, IEnumerable <UniformInfo> uniforms, string memo)
        {
            Memo         = memo;
            Owner        = owner;
            Opaque       = opaque;
            VertexLayout = vertexLayout;
            Available    = available;

            //create the uniforms from the info list we got
            if (!Available)
            {
                return;
            }

            UniformsDictionary = new SpecialWorkingDictionary(this);
            foreach (var ui in uniforms)
            {
                UniformsDictionary[ui.Name] = new PipelineUniform(this);
            }

            foreach (var ui in uniforms)
            {
                UniformsDictionary[ui.Name].AddUniformInfo(ui);
            }
        }
Beispiel #4
0
 void PurgeStateCache()
 {
     sStateCurrentVertexLayout = null;
     sStatePendingVertexLayout = null;
     sVertexAttribEnables.Clear();
     sActiveTexture = -1;
 }
Beispiel #5
0
        public Pipeline(IGL owner, IntPtr id, bool available, VertexLayout vertexLayout, IEnumerable <UniformInfo> uniforms)
        {
            Owner        = owner;
            Id           = id;
            VertexLayout = vertexLayout;
            Available    = available;

            //create the uniforms from the info list we got
            UniformsDictionary = new SpecialWorkingDictionary(this);
            foreach (var ui in uniforms)
            {
                UniformsDictionary[ui.Name] = new PipelineUniform(this, ui);
            }
        }
Beispiel #6
0
        // NOTE: we may need to overhaul uniform-setting infrastructure later.
        // maybe samplers will need to be set by index and not by name (I think the specs don't dictate what the sampler must be named)
        public RetroShader(IGL owner, string source, bool debug = false)
        {
            Owner = owner;

            VertexLayout = owner.CreateVertexLayout();
            VertexLayout.DefineVertexAttribute("position", 0, 4, VertexAttribPointerType.Float, AttributeUsage.Position, false, 40, 0);
            VertexLayout.DefineVertexAttribute("color", 1, 4, VertexAttribPointerType.Float, AttributeUsage.Color0, false, 40, 16);             //just dead weight, i have no idea why this is here. but some old HLSL compilers (used in bizhawk for various reasons) will want it to exist here since it exists in the vertex shader
            VertexLayout.DefineVertexAttribute("tex", 2, 2, VertexAttribPointerType.Float, AttributeUsage.Texcoord0, false, 40, 32);
            VertexLayout.Close();

            string defines  = "";
            string vsSource = $"#define VERTEX\r\n{defines}{source}";
            string psSource = $"#define FRAGMENT\r\n{defines}{source}";
            var    vs       = owner.CreateVertexShader(vsSource, "main_vertex", debug);
            var    ps       = owner.CreateFragmentShader(psSource, "main_fragment", debug);

            Pipeline = Owner.CreatePipeline(VertexLayout, vs, ps, debug, "retro");

            if (!Pipeline.Available)
            {
                Available = false;
                return;
            }

            // retroarch shaders will sometimes not have the right sampler name
            // it's unclear whether we should bind to s_p or sampler0
            // lets bind to sampler0 in case we don't have s_p
            sampler0 = Pipeline.TryGetUniform("s_p");
            if (sampler0 == null)
            {
                //sampler wasn't named correctly. this can happen on some retroarch shaders
                foreach (var u in Pipeline.GetUniforms())
                {
                    if (u.Sole.IsSampler && u.Sole.SamplerIndex == 0)
                    {
                        sampler0 = u;
                        break;
                    }
                }
            }

            //if a sampler isn't available, we can't do much, although this does interfere with debugging (shaders just returning colors will malfunction)
            if (sampler0 == null)
            {
                return;
            }

            Available = true;
        }
Beispiel #7
0
        //NOTE: we may need to overhaul uniform-setting infrastructure later.
        //maybe samplers will need to be set by index and not by name (I think the specs dont dictate what the sampler must be named)

        public RetroShader(IGL owner, string source, bool debug = false)
        {
            Owner = owner;

            VertexLayout = owner.CreateVertexLayout();
            VertexLayout.DefineVertexAttribute("position", 0, 4, VertexAttribPointerType.Float, AttributeUsage.Position, false, 24, 0);
            VertexLayout.DefineVertexAttribute("texCoord1", 1, 2, VertexAttribPointerType.Float, AttributeUsage.Texcoord0, false, 24, 16);
            VertexLayout.Close();

            string defines  = "#define TEXCOORD TEXCOORD0\r\n";            //maybe not safe..
            string vsSource = "#define VERTEX\r\n" + defines + source;
            string psSource = "#define FRAGMENT\r\n" + defines + source;
            var    vs       = owner.CreateVertexShader(true, vsSource, "main_vertex", debug);
            var    ps       = owner.CreateFragmentShader(true, psSource, "main_fragment", debug);

            Pipeline = Owner.CreatePipeline(VertexLayout, vs, ps, debug, "retro");
        }
Beispiel #8
0
        public GuiRenderer(IGL owner)
        {
            Owner = owner;

            VertexLayout = owner.CreateVertexLayout();
            VertexLayout.DefineVertexAttribute("aPosition", 0, 2, VertexAttribPointerType.Float, false, 32, 0);
            VertexLayout.DefineVertexAttribute("aTexcoord", 1, 2, VertexAttribPointerType.Float, false, 32, 8);
            VertexLayout.DefineVertexAttribute("aColor", 2, 4, VertexAttribPointerType.Float, false, 32, 16);
            VertexLayout.Close();

            _Projection = new MatrixStack();
            _Modelview  = new MatrixStack();

            var vs = Owner.CreateVertexShader(DefaultVertexShader, true);
            var ps = Owner.CreateFragmentShader(DefaultPixelShader, true);

            CurrPipeline = DefaultPipeline = Owner.CreatePipeline(VertexLayout, vs, ps, true);
        }
Beispiel #9
0
 public Pipeline CreatePipeline(VertexLayout vertexLayout, Shader vertexShader, Shader fragmentShader, bool required, string memo)
 {
     return(null);
 }
Beispiel #10
0
        unsafe void MyBindArrayData(VertexLayout layout, void *pData)
        {
            UnbindVertexAttributes();

            //HAMNUTS (continued)
            var currBindings = sVertexAttribEnables;

            sStateCurrentVertexLayout = sStatePendingVertexLayout;

            if (layout == null)
            {
                return;
            }

            //disable all the client states.. a lot of overhead right now, to be sure
            GL.DisableClientState(ArrayCap.VertexArray);
            GL.DisableClientState(ArrayCap.ColorArray);
            for (int i = 0; i < 8; i++)
            {
                GL.DisableVertexAttribArray(i);
            }
            for (int i = 0; i < 8; i++)
            {
                GL.ClientActiveTexture(TextureUnit.Texture0 + i);
                GL.DisableClientState(ArrayCap.TextureCoordArray);
            }
            GL.ClientActiveTexture(TextureUnit.Texture0);

            foreach (var kvp in layout.Items)
            {
                if (_CurrPipeline.Memo == "gui")
                {
                    GL.VertexAttribPointer(kvp.Key, kvp.Value.Components, (VertexAttribPointerType)kvp.Value.AttribType, kvp.Value.Normalized, kvp.Value.Stride, new IntPtr(pData) + kvp.Value.Offset);
                    GL.EnableVertexAttribArray(kvp.Key);
                    currBindings.Add(kvp.Key);
                }
                else
                {
                    var pw = _CurrPipeline.Opaque as PipelineWrapper;

                    //comment SNACKPANTS
                    switch (kvp.Value.Usage)
                    {
                    case AttributeUsage.Position:
                        GL.EnableClientState(ArrayCap.VertexArray);
                        GL.VertexPointer(kvp.Value.Components, VertexPointerType.Float, kvp.Value.Stride, new IntPtr(pData) + kvp.Value.Offset);
                        break;

                    case AttributeUsage.Texcoord0:
                        GL.ClientActiveTexture(TextureUnit.Texture0);
                        GL.EnableClientState(ArrayCap.TextureCoordArray);
                        GL.TexCoordPointer(kvp.Value.Components, TexCoordPointerType.Float, kvp.Value.Stride, new IntPtr(pData) + kvp.Value.Offset);
                        break;

                    case AttributeUsage.Texcoord1:
                        GL.ClientActiveTexture(TextureUnit.Texture1);
                        GL.EnableClientState(ArrayCap.TextureCoordArray);
                        GL.TexCoordPointer(kvp.Value.Components, TexCoordPointerType.Float, kvp.Value.Stride, new IntPtr(pData) + kvp.Value.Offset);
                        GL.ClientActiveTexture(TextureUnit.Texture0);
                        break;

                    case AttributeUsage.Color0:
                        break;
                    }
                }
            }
        }
Beispiel #11
0
        /// <exception cref="InvalidOperationException">
        /// <paramref name="required"/> is <see langword="true"/> and either <paramref name="vertexShader"/> or <paramref name="fragmentShader"/> is unavailable (their <see cref="Shader.Available"/> property is <see langword="false"/>), or
        /// <c>glLinkProgram</c> call did not produce expected result
        /// </exception>
        public Pipeline CreatePipeline(VertexLayout vertexLayout, Shader vertexShader, Shader fragmentShader, bool required, string memo)
        {
            //if the shaders arent available, the pipeline isn't either
            if (!vertexShader.Available || !fragmentShader.Available)
            {
                string errors = $"Vertex Shader:\r\n {vertexShader.Errors} \r\n-------\r\nFragment Shader:\r\n{fragmentShader.Errors}";
                if (required)
                {
                    throw new InvalidOperationException($"Couldn't build required GL pipeline:\r\n{errors}");
                }
                var pipeline = new Pipeline(this, null, false, null, null, null);
                pipeline.Errors = errors;
                return(pipeline);
            }

            bool success = true;

            var vsw = vertexShader.Opaque as ShaderWrapper;
            var fsw = fragmentShader.Opaque as ShaderWrapper;
            var sws = new[] { vsw, fsw };

            bool mapVariables = vsw.MapCodeToNative != null || fsw.MapCodeToNative != null;

            ErrorCode errcode;
            int       pid = GL.CreateProgram();

            GL.AttachShader(pid, vsw.sid);
            errcode = GL.GetError();
            GL.AttachShader(pid, fsw.sid);
            errcode = GL.GetError();

            //NOT BEING USED NOW: USING SEMANTICS INSTEAD
            ////bind the attribute locations from the vertex layout
            ////as we go, look for attribute mappings (CGC will happily reorder and rename our attribute mappings)
            ////what's more it will _RESIZE_ them but this seems benign..somehow..
            ////WELLLLLLL we wish we could do that by names
            ////but the shaders dont seem to be adequate quality (oddly named attributes.. texCoord vs texCoord1). need to use semantics instead.
            //foreach (var kvp in vertexLayout.Items)
            //{
            //  string name = kvp.Value.Name;
            //  //if (mapVariables)
            //  //{
            //  //  foreach (var sw in sws)
            //  //  {
            //  //    if (sw.MapNativeToCode.ContainsKey(name))
            //  //    {
            //  //      name = sw.MapNativeToCode[name];
            //  //      break;
            //  //    }
            //  //  }
            //  //}

            //  if(mapVariables) {
            //    ////proxy for came-from-cgc
            //    //switch (kvp.Value.Usage)
            //    //{
            //    //  case AttributeUsage.Position:
            //    //}
            //  }

            //  //GL.BindAttribLocation(pid, kvp.Key, name);
            //}


            GL.LinkProgram(pid);
            errcode = GL.GetError();

            string resultLog = GL.GetProgramInfoLog(pid);

            if (errcode != ErrorCode.NoError)
            {
                if (required)
                {
                    throw new InvalidOperationException($"Error creating pipeline (error returned from glLinkProgram): {errcode}\r\n\r\n{resultLog}");
                }
                else
                {
                    success = false;
                }
            }

            int linkStatus;

            GL.GetProgram(pid, GetProgramParameterName.LinkStatus, out linkStatus);
            if (linkStatus == 0)
            {
                if (required)
                {
                    throw new InvalidOperationException($"Error creating pipeline (link status false returned from glLinkProgram): \r\n\r\n{resultLog}");
                }
                else
                {
                    success = false;
                }
            }

            //need to work on validation. apparently there are some weird caveats to glValidate which make it complicated and possibly excuses (barely) the intel drivers' dysfunctional operation
            //"A sampler points to a texture unit used by fixed function with an incompatible target"
            //
            //info:
            //http://www.opengl.org/sdk/docs/man/xhtml/glValidateProgram.xml
            //This function mimics the validation operation that OpenGL implementations must perform when rendering commands are issued while programmable shaders are part of current state.
            //glValidateProgram checks to see whether the executables contained in program can execute given the current OpenGL state
            //This function is typically useful only during application development.
            //
            //So, this is no big deal. we shouldnt be calling validate right now anyway.
            //conclusion: glValidate is very complicated and is of virtually no use unless your draw calls are returning errors and you want to know why
            //GL.ValidateProgram(pid);
            //errcode = GL.GetError();
            //resultLog = GL.GetProgramInfoLog(pid);
            //if (errcode != ErrorCode.NoError)
            //  throw new InvalidOperationException($"Error creating pipeline (error returned from glValidateProgram): {errcode}\r\n\r\n{resultLog}");
            //int validateStatus;
            //GL.GetProgram(pid, GetProgramParameterName.ValidateStatus, out validateStatus);
            //if (validateStatus == 0)
            //  throw new InvalidOperationException($"Error creating pipeline (validateStatus status false returned from glValidateProgram): \r\n\r\n{resultLog}");

            //set the program to active, in case we need to set sampler uniforms on it
            GL.UseProgram(pid);

            //get all the attributes (not needed)
            List <AttributeInfo> attributes = new List <AttributeInfo>();
            int nAttributes;

            GL.GetProgram(pid, GetProgramParameterName.ActiveAttributes, out nAttributes);
            for (int i = 0; i < nAttributes; i++)
            {
                int              size, length;
                string           name = new System.Text.StringBuilder(1024).ToString();
                ActiveAttribType type;
                GL.GetActiveAttrib(pid, i, 1024, out length, out size, out type, out name);
                attributes.Add(new AttributeInfo()
                {
                    Handle = new IntPtr(i), Name = name
                });
            }

            //get all the uniforms
            List <UniformInfo> uniforms = new List <UniformInfo>();
            int nUniforms;

            GL.GetProgram(pid, GetProgramParameterName.ActiveUniforms, out nUniforms);
            List <int> samplers = new List <int>();

            for (int i = 0; i < nUniforms; i++)
            {
                int size, length;
                ActiveUniformType type;
                string            name = new System.Text.StringBuilder(1024).ToString();
                GL.GetActiveUniform(pid, i, 1024, out length, out size, out type, out name);
                errcode = GL.GetError();
                int loc = GL.GetUniformLocation(pid, name);

                //translate name if appropriate
                //not sure how effective this approach will be, due to confusion of vertex and fragment uniforms
                if (mapVariables)
                {
                    if (vsw.MapCodeToNative.ContainsKey(name))
                    {
                        name = vsw.MapCodeToNative[name];
                    }
                    if (fsw.MapCodeToNative.ContainsKey(name))
                    {
                        name = fsw.MapCodeToNative[name];
                    }
                }

                var ui = new UniformInfo();
                ui.Name   = name;
                ui.Opaque = loc;

                if (type == ActiveUniformType.Sampler2D)
                {
                    ui.IsSampler    = true;
                    ui.SamplerIndex = samplers.Count;
                    ui.Opaque       = loc | (samplers.Count << 24);
                    samplers.Add(loc);
                }

                uniforms.Add(ui);
            }

            //deactivate the program, so we dont accidentally use it
            GL.UseProgram(0);

            if (!vertexShader.Available)
            {
                success = false;
            }
            if (!fragmentShader.Available)
            {
                success = false;
            }

            var pw = new PipelineWrapper()
            {
                pid = pid, VertexShader = vertexShader, FragmentShader = fragmentShader, SamplerLocs = samplers
            };

            return(new Pipeline(this, pw, success, vertexLayout, uniforms, memo));
        }