public static void SaveTo(string outPath, bool binary, ShaderInfo info)
 {
     if (binary)
     {
         SaveBinary(outPath, info);
     }
     else
     {
         SaveText(outPath, info);
     }
 }
        private static void SaveText(string outPath, ShaderInfo info)
        {
            StringBuilder sb = new StringBuilder(1024);

            sb.AppendLine($"SSL Reflection Dump");
            sb.AppendLine($"Compiler Version: v{info.CompilerVersion.Major}.{info.CompilerVersion.Minor}.{info.CompilerVersion.Build}");
            sb.AppendLine($"Source Version: v{info.SourceVersion.Major}.{info.SourceVersion.Minor}.{info.SourceVersion.Build}");
            sb.AppendLine();

            // General shader info
            var stagestr = "Vertex";

            for (int stage = 1; stage < 5; ++stage)
            {
                var ss = (ShaderStages)(0x01 << stage);
                if ((info.Stages & ss) > 0)
                {
                    stagestr += $", {ss}";
                }
            }
            sb.AppendLine($"Stages = {stagestr}");
            sb.AppendLine();

            // Write the uniforms
            sb.AppendLine("Uniforms");
            sb.AppendLine("--------");
            uint uidx = 0;

            foreach (var uni in info.Uniforms)
            {
                var qualstr =
                    uni.IsArray ? $"[{uni.ArraySize}]" :
                    uni.Type.IsSubpassInput() ? $"<{uni.SubpassIndex.Value}>" :
                    uni.Type.IsImageType() ? $"<{uni.ImageFormat.Value.ToSSLKeyword()}>" : "";
                var tstr = $"{uni.Type}{qualstr}";
                var bstr = "";
                if (uni.Type.IsValueType())                 // It will be in a block
                {
                    bstr = $"Block={uni.Location,-3} Idx={uni.Index,-3} Off={uni.Offset,-3}";
                }
                sb.AppendLine($"{uni.Name,-20} {tstr,-20} Loc={uni.Location,-3} Size={uni.Size,-3} {bstr}");
                ++uidx;
            }
            sb.AppendLine();
            if (!info.AreUniformsContiguous())
            {
                sb.AppendLine("Warning: The uniforms are not contiguous!");
                sb.AppendLine();
            }

            // Write the vertex attributes
            sb.AppendLine("Attributes");
            sb.AppendLine("----------");
            foreach (var attr in info.Attributes)
            {
                var tstr = $"{attr.Type}{(attr.IsArray ? $"[{attr.ArraySize}]" : "")}";
                sb.AppendLine($"{attr.Name,-20} {tstr,-20} Loc={attr.Location,-3} Size={attr.Size,-3} Slots={attr.SlotCount,-3}");
            }
            sb.AppendLine();

            // Write the outputs
            sb.AppendLine("Outputs");
            sb.AppendLine("-------");
            foreach (var output in info.Outputs)
            {
                sb.AppendLine($"{output.Name,-20} {output.Type,-20}");
            }
            sb.AppendLine();

            // Write the spec constants
            sb.AppendLine("Specialization Constants");
            sb.AppendLine("------------------------");
            foreach (var spec in info.Specializations)
            {
                sb.AppendLine($"{spec.Name,-20} {spec.Type,-20} Idx={spec.Index,-3}");
            }
            sb.AppendLine();

            // Write the file
            try
            {
                using (var file = File.Open(outPath, FileMode.Create, FileAccess.Write, FileShare.None))
                    using (var writer = new StreamWriter(file))
                        writer.Write(sb.ToString());
            }
            catch (PathTooLongException)
            {
                throw new Exception("The output path is too long.");
            }
            catch (DirectoryNotFoundException)
            {
                throw new Exception("The output directory could not be found, or does not exist.");
            }
        }
        private static void SaveBinary(string outPath, ShaderInfo info)
        {
            using (MemoryStream buffer = new MemoryStream(1024))
                using (BinaryWriter writer = new BinaryWriter(buffer))
                {
                    // Write the header and tool version
                    writer.Write(Encoding.ASCII.GetBytes("SSLR"));
                    writer.Write((byte)info.CompilerVersion.Major);
                    writer.Write((byte)info.CompilerVersion.Minor);
                    writer.Write((byte)info.CompilerVersion.Build);
                    writer.Write((byte)info.SourceVersion.Major);
                    writer.Write((byte)info.SourceVersion.Minor);
                    writer.Write((byte)info.SourceVersion.Build);

                    // Write shader info
                    writer.Write((byte)info.Stages);             // Stage mask

                    // Write the uniform
                    info.Sort();
                    writer.Write((byte)info.Uniforms.Count);
                    writer.Write(info.AreUniformsContiguous());
                    writer.Write((byte)info.Blocks.Count);
                    foreach (var block in info.Blocks)
                    {
                        writer.Write((byte)block.Location);
                    }
                    foreach (var uni in info.Uniforms)
                    {
                        writer.Write((byte)uni.Name.Length);
                        writer.Write(Encoding.ASCII.GetBytes(uni.Name));
                        writer.Write((byte)uni.Type);
                        writer.Write(uni.IsArray ? (byte)uni.ArraySize : (byte)0);
                        writer.Write(uni.Type.IsSubpassInput() ? (byte)uni.SubpassIndex : uni.Type.IsImageType() ? (byte)uni.ImageFormat : (byte)0xFF);
                        writer.Write((byte)uni.Location);
                        writer.Write((byte)uni.Index);
                    }

                    // Write the vertex attributes
                    writer.Write((byte)info.Attributes.Count);
                    foreach (var attr in info.Attributes)
                    {
                        writer.Write((byte)attr.Name.Length);
                        writer.Write(Encoding.ASCII.GetBytes(attr.Name));
                        writer.Write((byte)attr.Type);
                        writer.Write(attr.IsArray ? (byte)attr.ArraySize : (byte)0);
                        writer.Write((byte)attr.Location);
                    }

                    // Write the outputs
                    writer.Write((byte)info.Outputs.Count);
                    foreach (var output in info.Outputs)
                    {
                        writer.Write((byte)output.Name.Length);
                        writer.Write(Encoding.ASCII.GetBytes(output.Name));
                        writer.Write((byte)output.Type);
                    }

                    // Write the specialization constants
                    writer.Write((byte)info.Specializations.Count);
                    foreach (var spec in info.Specializations)
                    {
                        writer.Write((byte)spec.Name.Length);
                        writer.Write(Encoding.ASCII.GetBytes(spec.Name));
                        writer.Write((byte)spec.Type);
                        writer.Write((byte)spec.Index);
                    }

                    // Write the file
                    try
                    {
                        writer.Flush();
                        using (var file = File.Open(outPath, FileMode.Create, FileAccess.Write, FileShare.None))
                            file.Write(buffer.GetBuffer(), 0, (int)buffer.Position);
                    }
                    catch (PathTooLongException)
                    {
                        throw new Exception("The output path is too long.");
                    }
                    catch (DirectoryNotFoundException)
                    {
                        throw new Exception("The output directory could not be found, or does not exist.");
                    }
                }
        }
Ejemplo n.º 4
0
        public static ShaderInfo LoadFrom(BinaryReader reader, Version cVer, Version sVer)
        {
            if (cVer > TOOL_VERSION)
            {
                throw new InvalidOperationException($"The file version {cVer} cannot be loaded by this version of the library ({TOOL_VERSION}).");
            }

            ShaderInfo info = new ShaderInfo();

            info.CompilerVersion = cVer;
            info.SourceVersion   = sVer;

            // Load the stages
            var stages = reader.ReadByte();

            info.Stages = (ShaderStages)stages;

            // Load the uniforms (note that this assumes that the uniforms are sorted when written)
            var ucount = reader.ReadByte();
            var cont   = reader.ReadBoolean();
            var bcount = reader.ReadByte();

            info._blocks.AddRange(reader.ReadBytes(bcount).Select(b => new UniformBlock(b)));
            while (ucount > 0)
            {
                var slen  = reader.ReadByte();
                var uname = Encoding.ASCII.GetString(reader.ReadBytes(slen));
                var type  = (ShaderType)reader.ReadByte();
                var asize = reader.ReadByte();
                var extra = reader.ReadByte();
                var loc   = reader.ReadByte();
                var idx   = reader.ReadByte();

                UniformBlock b   = (idx != 0xFF) ? info._blocks.Find(blk => blk.Location == loc) : null;
                var          uni = new Uniform(uname, type, asize == 0 ? (uint?)null : asize, loc, b, idx, b?.Size ?? 0);
                if (type == ShaderType.SubpassInput)
                {
                    uni.SubpassIndex = extra;
                }
                else if (type.IsImageType())
                {
                    uni.ImageFormat = (ImageFormat)extra;
                }
                b?.AddMember(uni);
                info._uniforms.Add(uni);

                --ucount;
            }

            // Load the attributes
            var acount = reader.ReadByte();

            while (acount > 0)
            {
                var slen  = reader.ReadByte();
                var aname = Encoding.ASCII.GetString(reader.ReadBytes(slen));
                var type  = (ShaderType)reader.ReadByte();
                var asize = reader.ReadByte();
                var loc   = reader.ReadByte();

                info._attributes.Add(new VertexAttribute(aname, type, asize == 0 ? (uint?)null : asize, loc));

                --acount;
            }

            // Load the outputs
            var ocount = reader.ReadByte();

            for (uint i = 0; i < ocount; ++i)
            {
                var slen  = reader.ReadByte();
                var oname = Encoding.ASCII.GetString(reader.ReadBytes(slen));
                var type  = (ShaderType)reader.ReadByte();

                info._outputs.Add(new FragmentOutput(oname, type, i));
            }

            // Load the specialization constants
            var scount = reader.ReadByte();

            while (scount > 0)
            {
                var slen  = reader.ReadByte();
                var aname = Encoding.ASCII.GetString(reader.ReadBytes(slen));
                var type  = (ShaderType)reader.ReadByte();
                var idx   = reader.ReadByte();

                info._specializations.Add(new SpecConstant(aname, type, idx));

                --scount;
            }

            // Return
            info.Sort();
            return(info);
        }