aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Gpu/Image/Pool.cs
blob: 7457de198188bda5d6bc36a0b03bfddfa0638b22 (plain)
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
using Ryujinx.Graphics.Gpu.Memory;
using System;

namespace Ryujinx.Graphics.Gpu.Image
{
    abstract class Pool<T> : IDisposable
    {
        protected const int DescriptorSize = 0x20;

        protected GpuContext Context;

        protected T[] Items;

        public ulong Address { get; }
        public ulong Size    { get; }

        public Pool(GpuContext context, ulong address, int maximumId)
        {
            Context = context;

            int count = maximumId + 1;

            ulong size = (ulong)(uint)count * DescriptorSize;;

            Items = new T[count];

            Address = address;
            Size    = size;
        }

        public abstract T Get(int id);

        public void SynchronizeMemory()
        {
            (ulong, ulong)[] modifiedRanges = Context.PhysicalMemory.GetModifiedRanges(Address, Size, ResourceName.TexturePool);

            for (int index = 0; index < modifiedRanges.Length; index++)
            {
                (ulong mAddress, ulong mSize) = modifiedRanges[index];

                if (mAddress < Address)
                {
                    mAddress = Address;
                }

                ulong maxSize = Address + Size - mAddress;

                if (mSize > maxSize)
                {
                    mSize = maxSize;
                }

                InvalidateRangeImpl(mAddress, mSize);
            }
        }

        public void InvalidateRange(ulong address, ulong size)
        {
            ulong endAddress = address + size;

            ulong texturePoolEndAddress = Address + Size;

            // If the range being invalidated is not overlapping the texture pool range,
            // then we don't have anything to do, exit early.
            if (address >= texturePoolEndAddress || endAddress <= Address)
            {
                return;
            }

            if (address < Address)
            {
                address = Address;
            }

            if (endAddress > texturePoolEndAddress)
            {
                endAddress = texturePoolEndAddress;
            }

            InvalidateRangeImpl(address, size);
        }

        protected abstract void InvalidateRangeImpl(ulong address, ulong size);

        protected abstract void Delete(T item);

        public void Dispose()
        {
            if (Items != null)
            {
                for (int index = 0; index < Items.Length; index++)
                {
                    Delete(Items[index]);
                }

                Items = null;
            }
        }
    }
}