예제 #1
0
        private void GenInst1u(ShaderProgram Program, uint InstOp)
        {
            ShaderOpCode OpCode = (ShaderOpCode)(InstOp >> 26);

            ShaderInst1 Inst = new ShaderInst1(InstOp);

            string Dest = GetDstReg(Program, Inst.Dest);
            string Src1 = GetSrcReg(Program, Inst.Src1, Inst.Idx1);

            SHBin.GetSwizzles(
                Inst.Desc,
                out string SDst,
                out string[] SSrc,
                out string[] SSrcM);

            string[] Signs = SHBin.GetSrcSigns(Inst.Desc);

            Src1 = Signs[0] + Src1;

            switch (OpCode)
            {
            case ShaderOpCode.Ex2:
                Append($"{Dest}.{SDst} = exp2({Src1}.{SSrcM[0]});");
                break;

            case ShaderOpCode.Lg2:
                Append($"{Dest}.{SDst} = log2({Src1}.{SSrcM[0]});");
                break;

            case ShaderOpCode.LitP:
                GenLitP(Src1, Dest);
                break;

            case ShaderOpCode.Flr:
                Append($"{Dest}.{SDst} = floor({Src1}.{SSrcM[0]});");
                break;

            case ShaderOpCode.Rcp:
                Append($"{Dest}.{SDst} = {GetVecCtor("1", SDst.Length)} / {Src1}.{SSrcM[0]};");
                break;

            case ShaderOpCode.RSq:
                Append($"{Dest}.{SDst} = inversesqrt({Src1}.{SSrcM[0]});");
                break;

            case ShaderOpCode.MovA:
                GenMovA(Src1, SSrcM[0], SDst);
                break;

            case ShaderOpCode.Mov:
                Append($"{Dest}.{SDst} = {Src1}.{SSrcM[0]};");
                break;
            }
        }
예제 #2
0
        private void GenInst3(ShaderProgram Program, uint InstOp)
        {
            ShaderOpCode OpCode = (ShaderOpCode)(InstOp >> 26);

            ShaderInst3 Inst = new ShaderInst3(InstOp);

            switch (OpCode)
            {
            case ShaderOpCode.IfU:   GenIfU(Program, Inst); break;

            case ShaderOpCode.CallU: GenCallU(Program, Inst); break;

            case ShaderOpCode.Loop:  GenLoop(Program, Inst); break;

            case ShaderOpCode.JmpU:  GenJmpU(Program, Inst); break;
            }
        }
예제 #3
0
        private void GenInst2(ShaderProgram Program, uint InstOp)
        {
            ShaderOpCode OpCode = (ShaderOpCode)(InstOp >> 26);

            ShaderInst2 Inst = new ShaderInst2(InstOp);

            switch (OpCode)
            {
            case ShaderOpCode.BreakC: GenBreakC(Program, Inst); break;

            case ShaderOpCode.Call:   GenCall(Program, Inst); break;

            case ShaderOpCode.CallC:  GenCallC(Program, Inst); break;

            case ShaderOpCode.IfC:    GenIfC(Program, Inst); break;

            case ShaderOpCode.JmpC:   GenJmpC(Program, Inst); break;
            }
        }
예제 #4
0
        private void GenInst1i(ShaderProgram Program, uint InstOp)
        {
            ShaderOpCode OpCode = (ShaderOpCode)(InstOp >> 26);

            ShaderInst1i Inst = new ShaderInst1i(InstOp);

            string Dest = GetDstReg(Program, Inst.Dest);
            string Src1 = GetSrcReg(Program, Inst.Src1);
            string Src2 = GetSrcReg(Program, Inst.Src2, Inst.Idx2);

            SHBin.GetSwizzles(
                Inst.Desc,
                out string SDst,
                out string[] SSrc,
                out string[] SSrcM);

            string[] Signs = SHBin.GetSrcSigns(Inst.Desc);

            Src1 = Signs[0] + Src1;
            Src2 = Signs[1] + Src2;

            switch (OpCode)
            {
            case ShaderOpCode.DPHI:
                GenDPH(Src1, Src2, SSrc[0], SSrc[1], Dest, SDst);
                break;

            case ShaderOpCode.DstI:
                Append($"{Dest} = vec4(1, {Src1}.y * {Src1}.y, {Src1}.z, {Src2}.w);");
                break;

            case ShaderOpCode.SGEI:
                GenSGE(Src1, Src1, SSrcM[0], SSrcM[1], Dest, SDst);
                break;

            case ShaderOpCode.SLTI:
                GenSLT(Src1, Src1, SSrcM[0], SSrcM[1], Dest, SDst);
                break;
            }
        }
예제 #5
0
파일: GFShader.cs 프로젝트: yorki00/SPICA
        public GFShader(BinaryReader Reader) : this()
        {
            uint MagicNumber = Reader.ReadUInt32();
            uint ShaderCount = Reader.ReadUInt32();

            GFSection.SkipPadding(Reader.BaseStream);

            GFSection ShaderSection = new GFSection(Reader);

            Name = Reader.ReadPaddedString(0x40);

            uint Hash  = Reader.ReadUInt32();
            uint Count = Reader.ReadUInt32();

            GFSection.SkipPadding(Reader.BaseStream);

            uint CommandsLength = Reader.ReadUInt32();
            uint CommandsCount  = Reader.ReadUInt32();
            uint CommandsHash   = Reader.ReadUInt32();
            uint Padding        = Reader.ReadUInt32();

            string FileName = Reader.ReadPaddedString(0x40);

            uint[] Commands = new uint[CommandsLength >> 2];

            for (int Index = 0; Index < Commands.Length; Index++)
            {
                Commands[Index] = Reader.ReadUInt32();
            }

            uint[] OutMap = new uint[7];

            List <uint>  ShaderExecutable = new List <uint>();
            List <ulong> ShaderSwizzles   = new List <ulong>();

            PICACommandReader CmdReader = new PICACommandReader(Commands);

            while (CmdReader.HasCommand)
            {
                PICACommand Cmd = CmdReader.GetCommand();

                uint Param = Cmd.Parameters[0];

                int Stage = ((int)Cmd.Register >> 3) & 7;

                if (Stage >= 6)
                {
                    Stage -= 2;
                }

                switch (Cmd.Register)
                {
                /* Shader */

                case PICARegister.GPUREG_SH_OUTMAP_O0: OutMap[0] = Param; break;

                case PICARegister.GPUREG_SH_OUTMAP_O1: OutMap[1] = Param; break;

                case PICARegister.GPUREG_SH_OUTMAP_O2: OutMap[2] = Param; break;

                case PICARegister.GPUREG_SH_OUTMAP_O3: OutMap[3] = Param; break;

                case PICARegister.GPUREG_SH_OUTMAP_O4: OutMap[4] = Param; break;

                case PICARegister.GPUREG_SH_OUTMAP_O5: OutMap[5] = Param; break;

                case PICARegister.GPUREG_SH_OUTMAP_O6: OutMap[6] = Param; break;

                /* Fragment Shader */

                case PICARegister.GPUREG_TEXENV0_SOURCE:
                case PICARegister.GPUREG_TEXENV1_SOURCE:
                case PICARegister.GPUREG_TEXENV2_SOURCE:
                case PICARegister.GPUREG_TEXENV3_SOURCE:
                case PICARegister.GPUREG_TEXENV4_SOURCE:
                case PICARegister.GPUREG_TEXENV5_SOURCE:
                    TexEnvStages[Stage].Source = new PICATexEnvSource(Param);
                    break;

                case PICARegister.GPUREG_TEXENV0_OPERAND:
                case PICARegister.GPUREG_TEXENV1_OPERAND:
                case PICARegister.GPUREG_TEXENV2_OPERAND:
                case PICARegister.GPUREG_TEXENV3_OPERAND:
                case PICARegister.GPUREG_TEXENV4_OPERAND:
                case PICARegister.GPUREG_TEXENV5_OPERAND:
                    TexEnvStages[Stage].Operand = new PICATexEnvOperand(Param);
                    break;

                case PICARegister.GPUREG_TEXENV0_COMBINER:
                case PICARegister.GPUREG_TEXENV1_COMBINER:
                case PICARegister.GPUREG_TEXENV2_COMBINER:
                case PICARegister.GPUREG_TEXENV3_COMBINER:
                case PICARegister.GPUREG_TEXENV4_COMBINER:
                case PICARegister.GPUREG_TEXENV5_COMBINER:
                    TexEnvStages[Stage].Combiner = new PICATexEnvCombiner(Param);
                    break;

                case PICARegister.GPUREG_TEXENV0_COLOR:
                case PICARegister.GPUREG_TEXENV1_COLOR:
                case PICARegister.GPUREG_TEXENV2_COLOR:
                case PICARegister.GPUREG_TEXENV3_COLOR:
                case PICARegister.GPUREG_TEXENV4_COLOR:
                case PICARegister.GPUREG_TEXENV5_COLOR:
                    TexEnvStages[Stage].Color = new RGBA(Param);
                    break;

                case PICARegister.GPUREG_TEXENV0_SCALE:
                case PICARegister.GPUREG_TEXENV1_SCALE:
                case PICARegister.GPUREG_TEXENV2_SCALE:
                case PICARegister.GPUREG_TEXENV3_SCALE:
                case PICARegister.GPUREG_TEXENV4_SCALE:
                case PICARegister.GPUREG_TEXENV5_SCALE:
                    TexEnvStages[Stage].Scale = new PICATexEnvScale(Param);
                    break;

                case PICARegister.GPUREG_TEXENV_UPDATE_BUFFER: PICATexEnvStage.SetUpdateBuffer(TexEnvStages, Param); break;

                case PICARegister.GPUREG_TEXENV_BUFFER_COLOR: TexEnvBufferColor = new RGBA(Param); break;

                /* Geometry Shader */

                case PICARegister.GPUREG_GSH_ENTRYPOINT:
                    if (GeoShader == null)
                    {
                        GeoShader = new ShaderProgram();
                    }

                    GeoShader.MainOffset = Param & 0xffff;
                    break;

                /* Vertex Shader */

                case PICARegister.GPUREG_VSH_CODETRANSFER_DATA0:
                case PICARegister.GPUREG_VSH_CODETRANSFER_DATA1:
                case PICARegister.GPUREG_VSH_CODETRANSFER_DATA2:
                case PICARegister.GPUREG_VSH_CODETRANSFER_DATA3:
                case PICARegister.GPUREG_VSH_CODETRANSFER_DATA4:
                case PICARegister.GPUREG_VSH_CODETRANSFER_DATA5:
                case PICARegister.GPUREG_VSH_CODETRANSFER_DATA6:
                case PICARegister.GPUREG_VSH_CODETRANSFER_DATA7:
                    ShaderExecutable.AddRange(Cmd.Parameters);
                    break;

                case PICARegister.GPUREG_VSH_OPDESCS_DATA0:
                case PICARegister.GPUREG_VSH_OPDESCS_DATA1:
                case PICARegister.GPUREG_VSH_OPDESCS_DATA2:
                case PICARegister.GPUREG_VSH_OPDESCS_DATA3:
                case PICARegister.GPUREG_VSH_OPDESCS_DATA4:
                case PICARegister.GPUREG_VSH_OPDESCS_DATA5:
                case PICARegister.GPUREG_VSH_OPDESCS_DATA6:
                case PICARegister.GPUREG_VSH_OPDESCS_DATA7:
                    for (int i = 0; i < Cmd.Parameters.Length; i++)
                    {
                        ShaderSwizzles.Add(Cmd.Parameters[i]);
                    }
                    break;

                case PICARegister.GPUREG_VSH_ENTRYPOINT:
                    if (VtxShader == null)
                    {
                        VtxShader = new ShaderProgram();
                    }

                    VtxShader.MainOffset = Param & 0xffff;
                    break;
                }
            }

            Executable = ShaderExecutable.ToArray();
            Swizzles   = ShaderSwizzles.ToArray();

            for (int i = 0; i < OutMap.Length; i++)
            {
                if (OutMap[i] == 0)
                {
                    continue;
                }

                ShaderOutputReg Reg = new ShaderOutputReg();

                for (int j = 0; j < 4; j++)
                {
                    uint Value = (OutMap[i] >> j * 8) & 0x1f;

                    if (Value != 0x1f)
                    {
                        Reg.Mask |= 1u << j;

                        if (Value < 0x4)
                        {
                            Reg.Name = ShaderOutputRegName.Position;
                        }
                        else if (Value < 0x8)
                        {
                            Reg.Name = ShaderOutputRegName.QuatNormal;
                        }
                        else if (Value < 0xc)
                        {
                            Reg.Name = ShaderOutputRegName.Color;
                        }
                        else if (Value < 0xe)
                        {
                            Reg.Name = ShaderOutputRegName.TexCoord0;
                        }
                        else if (Value < 0x10)
                        {
                            Reg.Name = ShaderOutputRegName.TexCoord1;
                        }
                        else if (Value < 0x11)
                        {
                            Reg.Name = ShaderOutputRegName.TexCoord0W;
                        }
                        else if (Value < 0x12)
                        {
                            Reg.Name = ShaderOutputRegName.Generic;
                        }
                        else if (Value < 0x16)
                        {
                            Reg.Name = ShaderOutputRegName.View;
                        }
                        else if (Value < 0x18)
                        {
                            Reg.Name = ShaderOutputRegName.TexCoord2;
                        }
                        else
                        {
                            Reg.Name = ShaderOutputRegName.Generic;
                        }
                    }
                }

                if (VtxShader != null)
                {
                    VtxShader.OutputRegs[i] = Reg;
                }

                if (GeoShader != null)
                {
                    GeoShader.OutputRegs[i] = Reg;
                }
            }

            HashSet <uint> Dsts = new HashSet <uint>();

            uint LblId = 0;

            for (uint i = 0; i < Executable.Length; i++)
            {
                ShaderOpCode OpCode = (ShaderOpCode)(Executable[i] >> 26);

                if (OpCode == ShaderOpCode.Call ||
                    OpCode == ShaderOpCode.CallC ||
                    OpCode == ShaderOpCode.CallU ||
                    OpCode == ShaderOpCode.JmpC ||
                    OpCode == ShaderOpCode.JmpU)
                {
                    uint Dst = (Executable[i] >> 10) & 0xfff;

                    if (!Dsts.Contains(Dst))
                    {
                        Dsts.Add(Dst);

                        string Name = "label_" + Dst.ToString("x4");

                        ShaderLabel Label = new ShaderLabel()
                        {
                            Id     = LblId++,
                            Offset = Dst,
                            Length = 0,
                            Name   = Name
                        };

                        if (VtxShader != null)
                        {
                            VtxShader.Labels.Add(Label);
                        }

                        if (GeoShader != null)
                        {
                            GeoShader.Labels.Add(Label);
                        }
                    }
                }
            }

            MakeArray(VtxShader?.Vec4Uniforms, "v_c");
            MakeArray(GeoShader?.Vec4Uniforms, "g_c");

            FindProgramEnd(VtxShader, Executable);
            FindProgramEnd(GeoShader, Executable);

            VtxShaderUniforms = CmdReader.GetAllVertexShaderUniforms();
            GeoShaderUniforms = CmdReader.GetAllGeometryShaderUniforms();
        }
예제 #6
0
        private void GenInst1(ShaderProgram Program, uint InstOp)
        {
            ShaderOpCode OpCode = (ShaderOpCode)(InstOp >> 26);

            ShaderInst1 Inst = new ShaderInst1(InstOp);

            string Dest = GetDstReg(Program, Inst.Dest);
            string Src1 = GetSrcReg(Program, Inst.Src1, Inst.Idx1);
            string Src2 = GetSrcReg(Program, Inst.Src2);

            SHBin.GetSwizzles(
                Inst.Desc,
                out string SDst,
                out string[] SSrc,
                out string[] SSrcM);

            string[] Signs = SHBin.GetSrcSigns(Inst.Desc);

            Src1 = Signs[0] + Src1;
            Src2 = Signs[1] + Src2;

            switch (OpCode)
            {
            case ShaderOpCode.Add:
                Append($"{Dest}.{SDst} = {Src1}.{SSrcM[0]} + {Src2}.{SSrcM[1]};");
                break;

            case ShaderOpCode.DP3:
                GenDP3(Src1, Src2, SSrc[0], SSrc[1], Dest, SDst);
                break;

            case ShaderOpCode.DP4:
                Append($"{Dest}.{SDst} = {GetVecCtor($"dot({Src1}.{SSrc[0]}, {Src2}.{SSrc[1]})", SDst.Length)};");
                break;

            case ShaderOpCode.DPH:
                GenDPH(Src1, Src2, SSrc[0], SSrc[1], Dest, SDst);
                break;

            case ShaderOpCode.Dst:
                Append($"{Dest} = vec4(1, {Src1}.y * {Src1}.y, {Src1}.z, {Src2}.w);");
                break;

            case ShaderOpCode.Mul:
                Append($"{Dest}.{SDst} = {Src1}.{SSrcM[0]} * {Src2}.{SSrcM[1]};");
                break;

            case ShaderOpCode.SGE:
                GenSGE(Src1, Src1, SSrcM[0], SSrcM[1], Dest, SDst);
                break;

            case ShaderOpCode.SLT:
                GenSLT(Src1, Src1, SSrcM[0], SSrcM[1], Dest, SDst);
                break;

            case ShaderOpCode.Max:
                Append($"{Dest}.{SDst} = max({Src1}.{SSrcM[0]}, {Src2}.{SSrcM[1]});");
                break;

            case ShaderOpCode.Min:
                Append($"{Dest}.{SDst} = min({Src1}.{SSrcM[0]}, {Src2}.{SSrcM[1]});");
                break;
            }
        }