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)); }
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)); }
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); } } }
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)); } }