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