Beispiel #1
0
        private static void ApplyScalingNoInterpolation(CodeGenContext context, SpvInstruction output, SpvInstruction vector, SpvInstruction scale)
        {
            if (context.Config.Stage == ShaderStage.Vertex)
            {
                scale = context.GlslFAbs(context.TypeFP32(), scale);
            }

            var vector2Type = context.TypeVector(context.TypeFP32(), 2);

            var vectorFloat  = context.ConvertSToF(vector2Type, vector);
            var vectorScaled = context.VectorTimesScalar(vector2Type, vectorFloat, scale);

            context.Store(output, context.ConvertFToS(context.TypeVector(context.TypeS32(), 2), vectorScaled));
        }
Beispiel #2
0
        private static void ApplyScalingInterpolated(CodeGenContext context, SpvInstruction output, SpvInstruction vector, SpvInstruction scale)
        {
            var vector2Type = context.TypeVector(context.TypeFP32(), 2);

            var scaleNegated = context.FNegate(context.TypeFP32(), scale);
            var scaleVector  = context.CompositeConstruct(vector2Type, scaleNegated, scaleNegated);

            var vectorFloat  = context.ConvertSToF(vector2Type, vector);
            var vectorScaled = context.VectorTimesScalar(vector2Type, vectorFloat, scaleNegated);

            var fragCoordPointer = context.Inputs[AttributeConsts.PositionX];
            var fragCoord        = context.Load(context.TypeVector(context.TypeFP32(), 4), fragCoordPointer);
            var fragCoordXY      = context.VectorShuffle(vector2Type, fragCoord, fragCoord, 0, 1);

            var scaleMod           = context.FMod(vector2Type, fragCoordXY, scaleVector);
            var vectorInterpolated = context.FAdd(vector2Type, vectorScaled, scaleMod);

            context.Store(output, context.ConvertFToS(context.TypeVector(context.TypeS32(), 2), vectorInterpolated));
        }
Beispiel #3
0
        private static void Generate(CodeGenContext context, StructuredProgramInfo info, int funcIndex)
        {
            var function = info.Functions[funcIndex];

            (_, var spvFunc) = context.GetFunction(funcIndex);

            context.AddFunction(spvFunc);
            context.StartFunction();

            Declarations.DeclareParameters(context, function);

            context.EnterBlock(function.MainBlock);

            Declarations.DeclareLocals(context, function);
            Declarations.DeclareLocalForArgs(context, info.Functions);

            if (funcIndex == 0)
            {
                var v4Type = context.TypeVector(context.TypeFP32(), 4);
                var zero   = context.Constant(context.TypeFP32(), 0f);
                var one    = context.Constant(context.TypeFP32(), 1f);

                // Some games will leave some elements of gl_Position uninitialized,
                // in those cases, the elements will contain undefined values according
                // to the spec, but on NVIDIA they seems to be always initialized to (0, 0, 0, 1),
                // so we do explicit initialization to avoid UB on non-NVIDIA gpus.
                if (context.Config.Stage == ShaderStage.Vertex)
                {
                    var elemPointer = context.GetAttributeVectorPointer(new AstOperand(OperandType.Attribute, AttributeConsts.PositionX), true);
                    context.Store(elemPointer, context.CompositeConstruct(v4Type, zero, zero, zero, one));
                }

                // Ensure that unused attributes are set, otherwise the downstream
                // compiler may eliminate them.
                // (Not needed for fragment shader as it is the last stage).
                if (context.Config.Stage != ShaderStage.Compute &&
                    context.Config.Stage != ShaderStage.Fragment &&
                    !context.Config.GpPassthrough)
                {
                    for (int attr = 0; attr < Declarations.MaxAttributes; attr++)
                    {
                        if (info.Outputs.Contains(attr))
                        {
                            continue;
                        }

                        if (context.Config.Options.Flags.HasFlag(TranslationFlags.Feedback))
                        {
                            throw new NotImplementedException();
                        }
                        else
                        {
                            int currAttr    = AttributeConsts.UserAttributeBase + attr * 16;
                            var elemPointer = context.GetAttributeVectorPointer(new AstOperand(OperandType.Attribute, currAttr), true);
                            context.Store(elemPointer, context.CompositeConstruct(v4Type, zero, zero, zero, one));
                        }
                    }
                }
            }

            Generate(context, function.MainBlock);

            context.FunctionEnd();

            if (funcIndex == 0)
            {
                context.AddEntryPoint(context.Config.Stage.Convert(), spvFunc, "main", context.GetMainInterface());

                if (context.Config.Stage == ShaderStage.Fragment)
                {
                    context.AddExecutionMode(spvFunc, context.Config.Options.TargetApi == TargetApi.Vulkan
                        ? ExecutionMode.OriginUpperLeft
                        : ExecutionMode.OriginLowerLeft);
                }
                else if (context.Config.Stage == ShaderStage.Compute)
                {
                    var localSizeX = (SpvLiteralInteger)context.Config.GpuAccessor.QueryComputeLocalSizeX();
                    var localSizeY = (SpvLiteralInteger)context.Config.GpuAccessor.QueryComputeLocalSizeY();
                    var localSizeZ = (SpvLiteralInteger)context.Config.GpuAccessor.QueryComputeLocalSizeZ();

                    context.AddExecutionMode(
                        spvFunc,
                        ExecutionMode.LocalSize,
                        localSizeX,
                        localSizeY,
                        localSizeZ);
                }
            }
        }
Beispiel #4
0
        private static SpvInstruction ApplyScaling2D(CodeGenContext context, SpvInstruction vector, int index)
        {
            var pointerType = context.TypePointer(StorageClass.Uniform, context.TypeFP32());
            var fieldIndex  = context.Constant(context.TypeU32(), 4);
            var scaleIndex  = context.Constant(context.TypeU32(), index);

            if (context.Config.Stage == ShaderStage.Vertex)
            {
                var scaleCountPointerType = context.TypePointer(StorageClass.Uniform, context.TypeS32());
                var scaleCountElemPointer = context.AccessChain(scaleCountPointerType, context.SupportBuffer, context.Constant(context.TypeU32(), 3));
                var scaleCount            = context.Load(context.TypeS32(), scaleCountElemPointer);

                scaleIndex = context.IAdd(context.TypeU32(), scaleIndex, scaleCount);
            }

            scaleIndex = context.IAdd(context.TypeU32(), scaleIndex, context.Constant(context.TypeU32(), 1));

            var scaleElemPointer = context.AccessChain(pointerType, context.SupportBuffer, fieldIndex, scaleIndex);
            var scale            = context.Load(context.TypeFP32(), scaleElemPointer);

            var ivector2Type = context.TypeVector(context.TypeS32(), 2);
            var localVector  = context.CoordTemp;

            var passthrough = context.FOrdEqual(context.TypeBool(), scale, context.Constant(context.TypeFP32(), 1f));

            var mergeLabel = context.Label();

            if (context.Config.Stage == ShaderStage.Fragment)
            {
                var scaledInterpolatedLabel    = context.Label();
                var scaledNoInterpolationLabel = context.Label();

                var needsInterpolation = context.FOrdLessThan(context.TypeBool(), scale, context.Constant(context.TypeFP32(), 0f));

                context.SelectionMerge(mergeLabel, SelectionControlMask.MaskNone);
                context.BranchConditional(needsInterpolation, scaledInterpolatedLabel, scaledNoInterpolationLabel);

                // scale < 0.0
                context.AddLabel(scaledInterpolatedLabel);

                ApplyScalingInterpolated(context, localVector, vector, scale);
                context.Branch(mergeLabel);

                // scale >= 0.0
                context.AddLabel(scaledNoInterpolationLabel);

                ApplyScalingNoInterpolation(context, localVector, vector, scale);
                context.Branch(mergeLabel);

                context.AddLabel(mergeLabel);

                var passthroughLabel = context.Label();
                var finalMergeLabel  = context.Label();

                context.SelectionMerge(finalMergeLabel, SelectionControlMask.MaskNone);
                context.BranchConditional(passthrough, passthroughLabel, finalMergeLabel);

                context.AddLabel(passthroughLabel);

                context.Store(localVector, vector);
                context.Branch(finalMergeLabel);

                context.AddLabel(finalMergeLabel);

                return(context.Load(ivector2Type, localVector));
            }
            else
            {
                var passthroughLabel = context.Label();
                var scaledLabel      = context.Label();

                context.SelectionMerge(mergeLabel, SelectionControlMask.MaskNone);
                context.BranchConditional(passthrough, passthroughLabel, scaledLabel);

                // scale == 1.0
                context.AddLabel(passthroughLabel);

                context.Store(localVector, vector);
                context.Branch(mergeLabel);

                // scale != 1.0
                context.AddLabel(scaledLabel);

                ApplyScalingNoInterpolation(context, localVector, vector, scale);
                context.Branch(mergeLabel);

                context.AddLabel(mergeLabel);

                return(context.Load(ivector2Type, localVector));
            }
        }