예제 #1
0
        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);
                    }
                }
            }
        }
예제 #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
        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);
                }
            }
        }