コード例 #1
0
        private void SetUsedTextureOrImage(
            Dictionary <TextureInfo, TextureMeta> dict,
            int cbufSlot,
            int handle,
            SamplerType type,
            TextureFormat format,
            bool intCoords,
            bool write,
            bool accurateType)
        {
            var dimensions = type.GetDimensions();
            var isIndexed  = type.HasFlag(SamplerType.Indexed);

            var usageFlags = TextureUsageFlags.None;

            if (intCoords)
            {
                usageFlags |= TextureUsageFlags.NeedsScaleValue;

                var canScale = (Stage == ShaderStage.Fragment || Stage == ShaderStage.Compute) && !isIndexed && !write && dimensions == 2;

                if (!canScale)
                {
                    // Resolution scaling cannot be applied to this texture right now.
                    // Flag so that we know to blacklist scaling on related textures when binding them.
                    usageFlags |= TextureUsageFlags.ResScaleUnsupported;
                }
            }

            if (write)
            {
                usageFlags |= TextureUsageFlags.ImageStore;
            }

            int arraySize = isIndexed ? SamplerArraySize : 1;

            for (int layer = 0; layer < arraySize; layer++)
            {
                var info = new TextureInfo(cbufSlot, handle + layer * 2, isIndexed, format);
                var meta = new TextureMeta()
                {
                    AccurateType = accurateType,
                    Type         = type,
                    UsageFlags   = usageFlags
                };

                if (dict.TryGetValue(info, out var existingMeta))
                {
                    dict[info] = MergeTextureMeta(meta, existingMeta);
                }
                else
                {
                    dict.Add(info, meta);
                }
            }
        }
コード例 #2
0
        private static void EmitTextureSample(EmitterContext context, TextureFlags flags)
        {
            OpCodeTexture op = (OpCodeTexture)context.CurrOp;

            bool isBindless = (flags & TextureFlags.Bindless) != 0;

            if (op.Rd.IsRZ)
            {
                return;
            }

            int raIndex = op.Ra.Index;
            int rbIndex = op.Rb.Index;

            Operand Ra()
            {
                if (raIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(raIndex++, RegisterType.Gpr)));
            }

            Operand Rb()
            {
                if (rbIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(rbIndex++, RegisterType.Gpr)));
            }

            Operand arrayIndex = op.IsArray ? Ra() : null;

            List <Operand> sourcesList = new List <Operand>();

            if (isBindless)
            {
                sourcesList.Add(Rb());
            }

            SamplerType type = ConvertSamplerType(op.Dimensions);

            int coordsCount = type.GetDimensions();

            for (int index = 0; index < coordsCount; index++)
            {
                sourcesList.Add(Ra());
            }

            if (op.IsArray)
            {
                sourcesList.Add(arrayIndex);

                type |= SamplerType.Array;
            }

            bool hasLod = op.LodMode > TextureLodMode.LodZero;

            Operand lodValue = hasLod ? Rb() : ConstF(0);

            Operand packedOffs = op.HasOffset ? Rb() : null;

            if (op.HasDepthCompare)
            {
                sourcesList.Add(Rb());

                type |= SamplerType.Shadow;
            }

            if ((op.LodMode == TextureLodMode.LodZero ||
                 op.LodMode == TextureLodMode.LodLevel ||
                 op.LodMode == TextureLodMode.LodLevelA) && !op.IsMultisample)
            {
                sourcesList.Add(lodValue);

                flags |= TextureFlags.LodLevel;
            }

            if (op.HasOffset)
            {
                for (int index = 0; index < coordsCount; index++)
                {
                    sourcesList.Add(context.BitfieldExtractS32(packedOffs, Const(index * 4), Const(4)));
                }

                flags |= TextureFlags.Offset;
            }

            if (op.LodMode == TextureLodMode.LodBias ||
                op.LodMode == TextureLodMode.LodBiasA)
            {
                sourcesList.Add(lodValue);

                flags |= TextureFlags.LodBias;
            }

            if (op.IsMultisample)
            {
                sourcesList.Add(Rb());

                type |= SamplerType.Multisample;
            }

            Operand[] sources = sourcesList.ToArray();

            int rdIndex = op.Rd.Index;

            Operand GetDest()
            {
                if (rdIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(Register(rdIndex++, RegisterType.Gpr));
            }

            int handle = !isBindless ? op.Immediate : 0;

            for (int compMask = op.ComponentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
            {
                if ((compMask & 1) != 0)
                {
                    Operand dest = GetDest();

                    TextureOperation operation = new TextureOperation(
                        Instruction.TextureSample,
                        type,
                        flags,
                        handle,
                        compIndex,
                        dest,
                        sources);

                    context.Add(operation);
                }
            }
        }
コード例 #3
0
        public static void Txd(EmitterContext context)
        {
            OpCodeTxd op = (OpCodeTxd)context.CurrOp;

            if (op.Rd.IsRZ)
            {
                return;
            }

            int raIndex = op.Ra.Index;
            int rbIndex = op.Rb.Index;

            Operand Ra()
            {
                if (raIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(raIndex++, RegisterType.Gpr)));
            }

            Operand Rb()
            {
                if (rbIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(rbIndex++, RegisterType.Gpr)));
            }

            TextureFlags flags = TextureFlags.Derivatives;

            List <Operand> sourcesList = new List <Operand>();

            if (op.IsBindless)
            {
                sourcesList.Add(Ra());
            }

            SamplerType type = ConvertSamplerType(op.Dimensions);

            int coordsCount = type.GetDimensions();

            for (int index = 0; index < coordsCount; index++)
            {
                sourcesList.Add(Ra());
            }

            Operand packedParams = Ra();

            if (op.IsArray)
            {
                sourcesList.Add(context.BitwiseAnd(packedParams, Const(0xffff)));

                type |= SamplerType.Array;
            }

            // Derivatives (X and Y).
            for (int dIndex = 0; dIndex < 2 * coordsCount; dIndex++)
            {
                sourcesList.Add(Rb());
            }

            if (op.HasOffset)
            {
                for (int index = 0; index < coordsCount; index++)
                {
                    sourcesList.Add(context.BitfieldExtractS32(packedParams, Const(16 + index * 4), Const(4)));
                }

                flags |= TextureFlags.Offset;
            }

            Operand[] sources = sourcesList.ToArray();

            int rdIndex = op.Rd.Index;

            Operand GetDest()
            {
                if (rdIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(Register(rdIndex++, RegisterType.Gpr));
            }

            int handle = !op.IsBindless ? op.Immediate : 0;

            for (int compMask = op.ComponentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
            {
                if ((compMask & 1) != 0)
                {
                    Operand dest = GetDest();

                    TextureOperation operation = new TextureOperation(
                        Instruction.TextureSample,
                        type,
                        flags,
                        handle,
                        compIndex,
                        dest,
                        sources);

                    context.Add(operation);
                }
            }
        }
コード例 #4
0
        public static void Tld4(EmitterContext context)
        {
            IOpCodeTld4 op = (IOpCodeTld4)context.CurrOp;

            if (op.Rd.IsRZ)
            {
                return;
            }

            int raIndex = op.Ra.Index;
            int rbIndex = op.Rb.Index;

            Operand Ra()
            {
                if (raIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(raIndex++, RegisterType.Gpr)));
            }

            Operand Rb()
            {
                if (rbIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(rbIndex++, RegisterType.Gpr)));
            }

            Operand arrayIndex = op.IsArray ? Ra() : null;

            List <Operand> sourcesList = new List <Operand>();

            SamplerType type = ConvertSamplerType(op.Dimensions);

            TextureFlags flags = TextureFlags.Gather;

            if (op.Bindless)
            {
                sourcesList.Add(Rb());

                flags |= TextureFlags.Bindless;
            }

            int coordsCount = type.GetDimensions();

            for (int index = 0; index < coordsCount; index++)
            {
                sourcesList.Add(Ra());
            }

            if (op.IsArray)
            {
                sourcesList.Add(arrayIndex);

                type |= SamplerType.Array;
            }

            Operand[] packedOffs = new Operand[2];

            packedOffs[0] = op.Offset != TextureGatherOffset.None    ? Rb() : null;
            packedOffs[1] = op.Offset == TextureGatherOffset.Offsets ? Rb() : null;

            if (op.HasDepthCompare)
            {
                sourcesList.Add(Rb());

                type |= SamplerType.Shadow;
            }

            if (op.Offset != TextureGatherOffset.None)
            {
                int offsetTexelsCount = op.Offset == TextureGatherOffset.Offsets ? 4 : 1;

                for (int index = 0; index < coordsCount * offsetTexelsCount; index++)
                {
                    Operand packed = packedOffs[(index >> 2) & 1];

                    sourcesList.Add(context.BitfieldExtractS32(packed, Const((index & 3) * 8), Const(6)));
                }

                flags |= op.Offset == TextureGatherOffset.Offsets
                    ? TextureFlags.Offsets
                    : TextureFlags.Offset;
            }

            sourcesList.Add(Const(op.GatherCompIndex));

            Operand[] sources = sourcesList.ToArray();

            int rdIndex = op.Rd.Index;

            Operand GetDest()
            {
                if (rdIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(Register(rdIndex++, RegisterType.Gpr));
            }

            int handle = op.Immediate;

            for (int compMask = op.ComponentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
            {
                if ((compMask & 1) != 0)
                {
                    Operand dest = GetDest();

                    TextureOperation operation = new TextureOperation(
                        Instruction.TextureSample,
                        type,
                        flags,
                        handle,
                        compIndex,
                        dest,
                        sources);

                    context.Add(operation);
                }
            }
        }
コード例 #5
0
        public static void Sust(EmitterContext context)
        {
            OpCodeImage op = (OpCodeImage)context.CurrOp;

            SamplerType type = ConvertSamplerType(op.Dimensions);

            if (type == SamplerType.None)
            {
                context.Config.PrintLog("Invalid image store sampler type.");

                return;
            }

            int raIndex = op.Ra.Index;
            int rbIndex = op.Rb.Index;

            Operand Ra()
            {
                if (raIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(raIndex++, RegisterType.Gpr)));
            }

            Operand Rb()
            {
                if (rbIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(rbIndex++, RegisterType.Gpr)));
            }

            bool isArray = op.Dimensions == ImageDimensions.Image1DArray ||
                           op.Dimensions == ImageDimensions.Image2DArray;

            Operand arrayIndex = isArray ? Ra() : null;

            List <Operand> sourcesList = new List <Operand>();

            if (op.IsBindless)
            {
                sourcesList.Add(context.Copy(Register(op.Rc)));
            }

            int coordsCount = type.GetDimensions();

            for (int index = 0; index < coordsCount; index++)
            {
                sourcesList.Add(Ra());
            }

            if (isArray)
            {
                sourcesList.Add(arrayIndex);

                type |= SamplerType.Array;
            }

            if (op.UseComponents)
            {
                int componentMask = (int)op.Components;

                for (int compMask = componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
                {
                    if ((compMask & 1) != 0)
                    {
                        sourcesList.Add(Rb());
                    }
                }
            }
            else
            {
                context.Config.PrintLog("Unsized image store not supported.");
            }

            Operand[] sources = sourcesList.ToArray();

            int handle = !op.IsBindless ? op.Immediate : 0;

            TextureFlags flags = op.IsBindless ? TextureFlags.Bindless : TextureFlags.None;

            TextureOperation operation = new TextureOperation(
                Instruction.ImageStore,
                type,
                flags,
                handle,
                0,
                null,
                sources);

            context.Add(operation);
        }
コード例 #6
0
        private static void EmitSust(
            EmitterContext context,
            CacheOpSt cacheOp,
            SuDim dimensions,
            SuSize size,
            int imm,
            SuRgba componentMask,
            int srcA,
            int srcB,
            int srcC,
            bool useComponents,
            bool byteAddress,
            bool isBindless)
        {
            SamplerType type = ConvertSamplerType(dimensions);

            if (type == SamplerType.None)
            {
                context.Config.GpuAccessor.Log("Invalid image store sampler type.");
                return;
            }

            Operand Ra()
            {
                if (srcA > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(srcA++, RegisterType.Gpr)));
            }

            Operand Rb()
            {
                if (srcB > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(srcB++, RegisterType.Gpr)));
            }

            List <Operand> sourcesList = new List <Operand>();

            if (isBindless)
            {
                sourcesList.Add(context.Copy(Register(srcC, RegisterType.Gpr)));
            }

            int coordsCount = type.GetDimensions();

            for (int index = 0; index < coordsCount; index++)
            {
                sourcesList.Add(Ra());
            }

            if (Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D)
            {
                sourcesList.Add(Const(0));

                type &= ~SamplerType.Mask;
                type |= SamplerType.Texture2D;
            }

            if (type.HasFlag(SamplerType.Array))
            {
                sourcesList.Add(Ra());
            }

            TextureFormat format = TextureFormat.Unknown;

            if (useComponents)
            {
                for (int compMask = (int)componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
                {
                    if ((compMask & 1) != 0)
                    {
                        sourcesList.Add(Rb());
                    }
                }

                if (!isBindless)
                {
                    format = context.Config.GetTextureFormat(imm);
                }
            }
            else
            {
                if (byteAddress)
                {
                    int xIndex = isBindless ? 1 : 0;

                    sourcesList[xIndex] = context.ShiftRightS32(sourcesList[xIndex], Const(GetComponentSizeInBytesLog2(size)));
                }

                int components = GetComponents(size);

                for (int compIndex = 0; compIndex < components; compIndex++)
                {
                    sourcesList.Add(Rb());
                }

                format = GetTextureFormat(size);
            }

            Operand[] sources = sourcesList.ToArray();

            int handle = imm;

            TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None;

            if (cacheOp == CacheOpSt.Cg)
            {
                flags |= TextureFlags.Coherent;
            }

            TextureOperation operation = context.CreateTextureOperation(
                Instruction.ImageStore,
                type,
                format,
                flags,
                handle,
                0,
                null,
                sources);

            context.Add(operation);
        }
コード例 #7
0
        private static void EmitSured(
            EmitterContext context,
            SuDim dimensions,
            RedOp atomicOp,
            SuatomSize size,
            int imm,
            int srcA,
            int srcB,
            int srcC,
            bool byteAddress,
            bool isBindless)
        {
            SamplerType type = ConvertSamplerType(dimensions);

            if (type == SamplerType.None)
            {
                context.Config.GpuAccessor.Log("Invalid image reduction sampler type.");
                return;
            }

            Operand Ra()
            {
                if (srcA > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(srcA++, RegisterType.Gpr)));
            }

            Operand Rb()
            {
                if (srcB > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(srcB++, RegisterType.Gpr)));
            }

            List <Operand> sourcesList = new List <Operand>();

            if (isBindless)
            {
                sourcesList.Add(context.Copy(GetSrcReg(context, srcC)));
            }

            int coordsCount = type.GetDimensions();

            for (int index = 0; index < coordsCount; index++)
            {
                sourcesList.Add(Ra());
            }

            if (Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D)
            {
                sourcesList.Add(Const(0));

                type &= ~SamplerType.Mask;
                type |= SamplerType.Texture2D;
            }

            if (type.HasFlag(SamplerType.Array))
            {
                sourcesList.Add(Ra());

                type |= SamplerType.Array;
            }

            if (byteAddress)
            {
                int xIndex = isBindless ? 1 : 0;

                sourcesList[xIndex] = context.ShiftRightS32(sourcesList[xIndex], Const(GetComponentSizeInBytesLog2(size)));
            }

            // TODO: FP and 64-bit formats.
            TextureFormat format = size == SuatomSize.Sd32 || size == SuatomSize.Sd64
                ? (isBindless ? TextureFormat.Unknown : context.Config.GetTextureFormatAtomic(imm))
                : GetTextureFormat(size);

            sourcesList.Add(Rb());

            Operand[] sources = sourcesList.ToArray();

            TextureFlags flags = GetAtomicOpFlags((SuatomOp)atomicOp);

            if (isBindless)
            {
                flags |= TextureFlags.Bindless;
            }

            TextureOperation operation = context.CreateTextureOperation(
                Instruction.ImageAtomic,
                type,
                format,
                flags,
                imm,
                0,
                null,
                sources);

            context.Add(operation);
        }
コード例 #8
0
        private static void EmitSuld(
            EmitterContext context,
            CacheOpLd cacheOp,
            SuDim dimensions,
            SuSize size,
            int imm,
            SuRgba componentMask,
            int srcA,
            int srcB,
            int srcC,
            bool useComponents,
            bool byteAddress,
            bool isBindless)
        {
            context.Config.SetUsedFeature(FeatureFlags.IntegerSampling);

            SamplerType type = ConvertSamplerType(dimensions);

            if (type == SamplerType.None)
            {
                context.Config.GpuAccessor.Log("Invalid image store sampler type.");
                return;
            }

            Operand Ra()
            {
                if (srcA > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(srcA++, RegisterType.Gpr)));
            }

            List <Operand> sourcesList = new List <Operand>();

            if (isBindless)
            {
                sourcesList.Add(context.Copy(Register(srcC, RegisterType.Gpr)));
            }

            int coordsCount = type.GetDimensions();

            for (int index = 0; index < coordsCount; index++)
            {
                sourcesList.Add(Ra());
            }

            if (Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D)
            {
                sourcesList.Add(Const(0));

                type &= ~SamplerType.Mask;
                type |= SamplerType.Texture2D;
            }

            if (type.HasFlag(SamplerType.Array))
            {
                sourcesList.Add(Ra());
            }

            Operand[] sources = sourcesList.ToArray();

            int handle = imm;

            TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None;

            if (cacheOp == CacheOpLd.Cg)
            {
                flags |= TextureFlags.Coherent;
            }

            if (useComponents)
            {
                for (int compMask = (int)componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
                {
                    if ((compMask & 1) == 0)
                    {
                        continue;
                    }

                    if (srcB == RegisterConsts.RegisterZeroIndex)
                    {
                        break;
                    }

                    Operand rd = Register(srcB++, RegisterType.Gpr);

                    TextureOperation operation = context.CreateTextureOperation(
                        Instruction.ImageLoad,
                        type,
                        flags,
                        handle,
                        compIndex,
                        rd,
                        sources);

                    if (!isBindless)
                    {
                        operation.Format = context.Config.GetTextureFormat(handle);
                    }

                    context.Add(operation);
                }
            }
            else
            {
                if (byteAddress)
                {
                    int xIndex = isBindless ? 1 : 0;

                    sources[xIndex] = context.ShiftRightS32(sources[xIndex], Const(GetComponentSizeInBytesLog2(size)));
                }

                int components = GetComponents(size);

                for (int compIndex = 0; compIndex < components; compIndex++)
                {
                    if (srcB == RegisterConsts.RegisterZeroIndex)
                    {
                        break;
                    }

                    Operand rd = Register(srcB++, RegisterType.Gpr);

                    TextureOperation operation = context.CreateTextureOperation(
                        Instruction.ImageLoad,
                        type,
                        GetTextureFormat(size),
                        flags,
                        handle,
                        compIndex,
                        rd,
                        sources);

                    context.Add(operation);

                    switch (size)
                    {
                    case SuSize.U8: context.Copy(rd, ZeroExtendTo32(context, rd, 8)); break;

                    case SuSize.U16: context.Copy(rd, ZeroExtendTo32(context, rd, 16)); break;

                    case SuSize.S8: context.Copy(rd, SignExtendTo32(context, rd, 8)); break;

                    case SuSize.S16: context.Copy(rd, SignExtendTo32(context, rd, 16)); break;
                    }
                }
            }
        }
コード例 #9
0
ファイル: InstEmitTexture.cs プロジェクト: ljbatwh/Ryujinx
        private static void EmitTextureMipMapLevel(EmitterContext context, bool isBindless)
        {
            OpCodeTexture op = (OpCodeTexture)context.CurrOp;

            if (op.Rd.IsRZ)
            {
                return;
            }

            int raIndex = op.Ra.Index;
            int rbIndex = op.Rb.Index;

            Operand Ra()
            {
                if (raIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(raIndex++, RegisterType.Gpr)));
            }

            Operand Rb()
            {
                if (rbIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(rbIndex++, RegisterType.Gpr)));
            }

            TextureFlags flags = TextureFlags.None;

            List <Operand> sourcesList = new List <Operand>();

            if (isBindless)
            {
                sourcesList.Add(Rb());

                flags |= TextureFlags.Bindless;
            }

            SamplerType type = ConvertSamplerType(op.Dimensions);

            int coordsCount = type.GetDimensions();

            Operand arrayIndex = op.IsArray ? Ra() : null;

            for (int index = 0; index < coordsCount; index++)
            {
                sourcesList.Add(Ra());
            }

            if (op.IsArray)
            {
                sourcesList.Add(arrayIndex);

                type |= SamplerType.Array;
            }

            Operand[] sources = sourcesList.ToArray();

            int rdIndex = op.Rd.Index;

            Operand GetDest()
            {
                if (rdIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(Register(rdIndex++, RegisterType.Gpr));
            }

            int handle = !isBindless ? op.Immediate : 0;

            for (int compMask = op.ComponentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
            {
                if ((compMask & 1) != 0)
                {
                    Operand dest = GetDest();

                    // Components z and w aren't standard, we return 0 in this case and add a comment.
                    if (compIndex >= 2)
                    {
                        context.Add(new CommentNode("Unsupported component z or w found"));
                        context.Copy(dest, Const(0));
                    }
                    else
                    {
                        Operand tempDest = Local();

                        TextureOperation operation = new TextureOperation(
                            Instruction.Lod,
                            type,
                            flags,
                            handle,
                            compIndex,
                            tempDest,
                            sources);

                        context.Add(operation);

                        tempDest = context.FPMultiply(tempDest, ConstF(256.0f));

                        Operand finalValue = context.FPConvertToS32(tempDest);

                        context.Copy(dest, finalValue);
                    }
                }
            }
        }
コード例 #10
0
ファイル: InstEmitTexture.cs プロジェクト: ljbatwh/Ryujinx
        public static void Sust(EmitterContext context)
        {
            OpCodeImage op = (OpCodeImage)context.CurrOp;

            SamplerType type = ConvertSamplerType(op.Dimensions);

            if (type == SamplerType.None)
            {
                context.Config.GpuAccessor.Log("Invalid image store sampler type.");

                return;
            }

            int raIndex = op.Ra.Index;
            int rbIndex = op.Rb.Index;

            Operand Ra()
            {
                if (raIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(raIndex++, RegisterType.Gpr)));
            }

            Operand Rb()
            {
                if (rbIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(rbIndex++, RegisterType.Gpr)));
            }

            bool isArray = op.Dimensions == ImageDimensions.Image1DArray ||
                           op.Dimensions == ImageDimensions.Image2DArray;

            Operand arrayIndex = isArray ? Ra() : null;

            List <Operand> sourcesList = new List <Operand>();

            if (op.IsBindless)
            {
                sourcesList.Add(context.Copy(Register(op.Rc)));
            }

            int coordsCount = type.GetDimensions();

            for (int index = 0; index < coordsCount; index++)
            {
                sourcesList.Add(Ra());
            }

            if (isArray)
            {
                sourcesList.Add(arrayIndex);

                type |= SamplerType.Array;
            }

            TextureFormat format = TextureFormat.Unknown;

            if (op.UseComponents)
            {
                int componentMask = (int)op.Components;

                for (int compMask = componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
                {
                    if ((compMask & 1) != 0)
                    {
                        sourcesList.Add(Rb());
                    }
                }

                if (!op.IsBindless)
                {
                    format = context.Config.GetTextureFormat(op.Immediate);
                }
            }
            else
            {
                if (op.ByteAddress)
                {
                    int xIndex = op.IsBindless ? 1 : 0;

                    sourcesList[xIndex] = context.ShiftRightS32(sourcesList[xIndex], Const(GetComponentSizeInBytesLog2(op.Size)));
                }

                int components = GetComponents(op.Size);

                for (int compIndex = 0; compIndex < components; compIndex++)
                {
                    sourcesList.Add(Rb());
                }

                format = GetTextureFormat(op.Size);
            }

            Operand[] sources = sourcesList.ToArray();

            int handle = !op.IsBindless ? op.Immediate : 0;

            TextureFlags flags = op.IsBindless ? TextureFlags.Bindless : TextureFlags.None;

            TextureOperation operation = new TextureOperation(
                Instruction.ImageStore,
                type,
                flags,
                handle,
                0,
                null,
                sources)
            {
                Format = format
            };

            context.Add(operation);
        }
コード例 #11
0
ファイル: InstEmitTexture.cs プロジェクト: ljbatwh/Ryujinx
        public static void Suld(EmitterContext context)
        {
            OpCodeImage op = (OpCodeImage)context.CurrOp;

            SamplerType type = ConvertSamplerType(op.Dimensions);

            if (type == SamplerType.None)
            {
                context.Config.GpuAccessor.Log("Invalid image store sampler type.");

                return;
            }

            // Rb is Rd on the SULD instruction.
            int rdIndex = op.Rb.Index;
            int raIndex = op.Ra.Index;

            Operand Ra()
            {
                if (raIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(raIndex++, RegisterType.Gpr)));
            }

            bool isArray = op.Dimensions == ImageDimensions.Image1DArray ||
                           op.Dimensions == ImageDimensions.Image2DArray;

            Operand arrayIndex = isArray ? Ra() : null;

            List <Operand> sourcesList = new List <Operand>();

            if (op.IsBindless)
            {
                sourcesList.Add(context.Copy(Register(op.Rc)));
            }

            int coordsCount = type.GetDimensions();

            for (int index = 0; index < coordsCount; index++)
            {
                sourcesList.Add(Ra());
            }

            if (isArray)
            {
                sourcesList.Add(arrayIndex);

                type |= SamplerType.Array;
            }

            Operand[] sources = sourcesList.ToArray();

            int handle = !op.IsBindless ? op.Immediate : 0;

            TextureFlags flags = op.IsBindless ? TextureFlags.Bindless : TextureFlags.None;

            if (op.UseComponents)
            {
                int componentMask = (int)op.Components;

                for (int compMask = componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
                {
                    if ((compMask & 1) == 0)
                    {
                        continue;
                    }

                    if (rdIndex == RegisterConsts.RegisterZeroIndex)
                    {
                        break;
                    }

                    Operand rd = Register(rdIndex++, RegisterType.Gpr);

                    TextureOperation operation = new TextureOperation(
                        Instruction.ImageLoad,
                        type,
                        flags,
                        handle,
                        compIndex,
                        rd,
                        sources);

                    if (!op.IsBindless)
                    {
                        operation.Format = context.Config.GetTextureFormat(handle);
                    }

                    context.Add(operation);
                }
            }
            else
            {
                if (op.ByteAddress)
                {
                    int xIndex = op.IsBindless ? 1 : 0;

                    sources[xIndex] = context.ShiftRightS32(sources[xIndex], Const(GetComponentSizeInBytesLog2(op.Size)));
                }

                int components = GetComponents(op.Size);

                for (int compIndex = 0; compIndex < components; compIndex++)
                {
                    if (rdIndex == RegisterConsts.RegisterZeroIndex)
                    {
                        break;
                    }

                    Operand rd = Register(rdIndex++, RegisterType.Gpr);

                    TextureOperation operation = new TextureOperation(
                        Instruction.ImageLoad,
                        type,
                        flags,
                        handle,
                        compIndex,
                        rd,
                        sources)
                    {
                        Format = GetTextureFormat(op.Size)
                    };

                    context.Add(operation);

                    switch (op.Size)
                    {
                    case IntegerSize.U8:  context.Copy(rd, ZeroExtendTo32(context, rd, 8));  break;

                    case IntegerSize.U16: context.Copy(rd, ZeroExtendTo32(context, rd, 16)); break;

                    case IntegerSize.S8:  context.Copy(rd, SignExtendTo32(context, rd, 8));  break;

                    case IntegerSize.S16: context.Copy(rd, SignExtendTo32(context, rd, 16)); break;
                    }
                }
            }
        }
コード例 #12
0
ファイル: InstEmitTexture.cs プロジェクト: ljbatwh/Ryujinx
        private static void EmitTextureSample(EmitterContext context, TextureFlags flags)
        {
            OpCodeTexture op = (OpCodeTexture)context.CurrOp;

            bool isBindless = (flags & TextureFlags.Bindless) != 0;

            if (op.Rd.IsRZ)
            {
                return;
            }

            int raIndex = op.Ra.Index;
            int rbIndex = op.Rb.Index;

            Operand Ra()
            {
                if (raIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(raIndex++, RegisterType.Gpr)));
            }

            Operand Rb()
            {
                if (rbIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(rbIndex++, RegisterType.Gpr)));
            }

            Operand arrayIndex = op.IsArray ? Ra() : null;

            List <Operand> sourcesList = new List <Operand>();

            if (isBindless)
            {
                sourcesList.Add(Rb());
            }

            SamplerType type = ConvertSamplerType(op.Dimensions);

            bool hasLod = op.LodMode > TextureLodMode.LodZero;

            if (type == SamplerType.Texture1D && (flags & ~TextureFlags.Bindless) == TextureFlags.IntCoords && !(hasLod ||
                                                                                                                 op.HasDepthCompare ||
                                                                                                                 op.HasOffset ||
                                                                                                                 op.IsArray ||
                                                                                                                 op.IsMultisample))
            {
                // For bindless, we don't have any way to know the texture type,
                // so we assume it's texture buffer when the sampler type is 1D, since that's more common.
                bool isTypeBuffer = isBindless || context.Config.GpuAccessor.QueryIsTextureBuffer(op.Immediate);

                if (isTypeBuffer)
                {
                    type = SamplerType.TextureBuffer;
                }
            }

            int coordsCount = type.GetDimensions();

            for (int index = 0; index < coordsCount; index++)
            {
                sourcesList.Add(Ra());
            }

            if (op.IsArray)
            {
                sourcesList.Add(arrayIndex);

                type |= SamplerType.Array;
            }

            Operand lodValue = hasLod ? Rb() : ConstF(0);

            Operand packedOffs = op.HasOffset ? Rb() : null;

            if (op.HasDepthCompare)
            {
                sourcesList.Add(Rb());

                type |= SamplerType.Shadow;
            }

            if ((op.LodMode == TextureLodMode.LodZero ||
                 op.LodMode == TextureLodMode.LodLevel ||
                 op.LodMode == TextureLodMode.LodLevelA) && !op.IsMultisample && type != SamplerType.TextureBuffer)
            {
                sourcesList.Add(lodValue);

                flags |= TextureFlags.LodLevel;
            }

            if (op.HasOffset)
            {
                for (int index = 0; index < coordsCount; index++)
                {
                    sourcesList.Add(context.BitfieldExtractS32(packedOffs, Const(index * 4), Const(4)));
                }

                flags |= TextureFlags.Offset;
            }

            if (op.LodMode == TextureLodMode.LodBias ||
                op.LodMode == TextureLodMode.LodBiasA)
            {
                sourcesList.Add(lodValue);

                flags |= TextureFlags.LodBias;
            }

            if (op.IsMultisample)
            {
                sourcesList.Add(Rb());

                type |= SamplerType.Multisample;
            }

            Operand[] sources = sourcesList.ToArray();

            int rdIndex = op.Rd.Index;

            Operand GetDest()
            {
                if (rdIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(Register(rdIndex++, RegisterType.Gpr));
            }

            int handle = !isBindless ? op.Immediate : 0;

            for (int compMask = op.ComponentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
            {
                if ((compMask & 1) != 0)
                {
                    Operand dest = GetDest();

                    TextureOperation operation = new TextureOperation(
                        Instruction.TextureSample,
                        type,
                        flags,
                        handle,
                        compIndex,
                        dest,
                        sources);

                    context.Add(operation);
                }
            }
        }
コード例 #13
0
ファイル: ShaderConfig.cs プロジェクト: Fengyee/Ryujinx
        private static void SetUsedTextureOrImage(
            Dictionary <TextureInfo, TextureMeta> dict,
            int cbufSlot,
            int handle,
            SamplerType type,
            TextureFormat format,
            bool intCoords,
            bool write,
            bool accurateType)
        {
            var dimensions = type.GetDimensions();
            var isArray    = type.HasFlag(SamplerType.Array);
            var isIndexed  = type.HasFlag(SamplerType.Indexed);

            var usageFlags = TextureUsageFlags.None;

            if (intCoords)
            {
                usageFlags |= TextureUsageFlags.NeedsScaleValue;

                var canScale = (dimensions == 2 && !isArray) || (dimensions == 3 && isArray);
                if (!canScale)
                {
                    // Resolution scaling cannot be applied to this texture right now.
                    // Flag so that we know to blacklist scaling on related textures when binding them.
                    usageFlags |= TextureUsageFlags.ResScaleUnsupported;
                }
            }

            if (write)
            {
                usageFlags |= TextureUsageFlags.ImageStore;
            }

            int arraySize = isIndexed ? SamplerArraySize : 1;

            for (int layer = 0; layer < arraySize; layer++)
            {
                var info = new TextureInfo(cbufSlot, handle + layer * 2, isIndexed, format);
                var meta = new TextureMeta()
                {
                    AccurateType = accurateType,
                    Type         = type,
                    UsageFlags   = usageFlags
                };

                if (dict.TryGetValue(info, out var existingMeta))
                {
                    meta.UsageFlags |= existingMeta.UsageFlags;

                    // If the texture we have has inaccurate type information, then
                    // we prefer the most accurate one.
                    if (existingMeta.AccurateType)
                    {
                        meta.AccurateType = true;
                        meta.Type         = existingMeta.Type;
                    }

                    dict[info] = meta;
                }
                else
                {
                    dict.Add(info, meta);
                }
            }
        }