aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Shader/Translation/Transforms/SharedAtomicSignedCas.cs
blob: 112b3b197d2efbe9cc1495a9ea9d54a145af139d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.Translation.Optimizations;
using System.Collections.Generic;
using System.Diagnostics;

using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;

namespace Ryujinx.Graphics.Shader.Translation.Transforms
{
    class SharedAtomicSignedCas : ITransformPass
    {
        public static bool IsEnabled(IGpuAccessor gpuAccessor, ShaderStage stage, TargetLanguage targetLanguage, FeatureFlags usedFeatures)
        {
            return targetLanguage != TargetLanguage.Spirv && stage == ShaderStage.Compute && usedFeatures.HasFlag(FeatureFlags.SharedMemory);
        }

        public static LinkedListNode<INode> RunPass(TransformContext context, LinkedListNode<INode> node)
        {
            Operation operation = (Operation)node.Value;
            HelperFunctionName name;

            if (operation.Inst == Instruction.AtomicMaxS32)
            {
                name = HelperFunctionName.SharedAtomicMaxS32;
            }
            else if (operation.Inst == Instruction.AtomicMinS32)
            {
                name = HelperFunctionName.SharedAtomicMinS32;
            }
            else
            {
                return node;
            }

            if (operation.StorageKind != StorageKind.SharedMemory)
            {
                return node;
            }

            Operand result = operation.Dest;
            Operand memoryId = operation.GetSource(0);
            Operand byteOffset = operation.GetSource(1);
            Operand value = operation.GetSource(2);

            Debug.Assert(memoryId.Type == OperandType.Constant);

            int functionId = context.Hfm.GetOrCreateFunctionId(name, memoryId.Value);

            Operand[] callArgs = new Operand[] { Const(functionId), byteOffset, value };

            LinkedListNode<INode> newNode = node.List.AddBefore(node, new Operation(Instruction.Call, 0, result, callArgs));

            Utils.DeleteNode(node, operation);

            return newNode;
        }
    }
}