aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/vk/GrVkMemory.h
blob: 77267ab48c47b2d059cb57c7afd7ab0d2bbc9c80 (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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/

#ifndef GrVkMemory_DEFINED
#define GrVkMemory_DEFINED

#include "GrVkBuffer.h"
#include "SkTArray.h"
#include "SkTLList.h"
#include "vk/GrVkDefines.h"
#include "vk/GrVkTypes.h"

class GrVkGpu;

namespace GrVkMemory {
    /**
    * Allocates vulkan device memory and binds it to the gpu's device for the given object.
    * Returns true if allocation succeeded.
    */
    bool AllocAndBindBufferMemory(const GrVkGpu* gpu,
                                  VkBuffer buffer,
                                  GrVkBuffer::Type type,
                                  bool dynamic,
                                  GrVkAlloc* alloc);
    void FreeBufferMemory(const GrVkGpu* gpu, GrVkBuffer::Type type, const GrVkAlloc& alloc);

    bool AllocAndBindImageMemory(const GrVkGpu* gpu,
                                 VkImage image,
                                 bool linearTiling,
                                 GrVkAlloc* alloc);
    void FreeImageMemory(const GrVkGpu* gpu, bool linearTiling, const GrVkAlloc& alloc);

    VkPipelineStageFlags LayoutToPipelineStageFlags(const VkImageLayout layout);

    VkAccessFlags LayoutToSrcAccessMask(const VkImageLayout layout);

    void FlushMappedAlloc(const GrVkGpu* gpu, const GrVkAlloc& alloc);
    void InvalidateMappedAlloc(const GrVkGpu* gpu, const GrVkAlloc& alloc);
}

class GrVkFreeListAlloc {
public:
    GrVkFreeListAlloc(VkDeviceSize size, VkDeviceSize alignment)
        : fSize(size)
        , fAlignment(alignment)
        , fFreeSize(size)
        , fLargestBlockSize(size)
        , fLargestBlockOffset(0) {
        Block* block = fFreeList.addToTail();
        block->fOffset = 0;
        block->fSize = fSize;
    }
    ~GrVkFreeListAlloc() {
        this->reset();
    }

    VkDeviceSize size() const { return fSize; }
    VkDeviceSize alignment() const { return fAlignment; }
    VkDeviceSize freeSize() const { return fFreeSize; }
    VkDeviceSize largestBlockSize() const { return fLargestBlockSize; }

    bool unallocated() const { return fSize == fFreeSize; }

protected:
    bool alloc(VkDeviceSize requestedSize, VkDeviceSize* allocOffset, VkDeviceSize* allocSize);
    void free(VkDeviceSize allocOffset, VkDeviceSize allocSize);

    void reset() {
        fSize = 0;
        fAlignment = 0;
        fFreeSize = 0;
        fLargestBlockSize = 0;
        fFreeList.reset();
    }

    struct Block {
        VkDeviceSize fOffset;
        VkDeviceSize fSize;
    };
    typedef SkTLList<Block, 16> FreeList;

    VkDeviceSize   fSize;
    VkDeviceSize   fAlignment;
    VkDeviceSize   fFreeSize;
    VkDeviceSize   fLargestBlockSize;
    VkDeviceSize   fLargestBlockOffset;
    FreeList       fFreeList;
};

class GrVkSubHeap : public GrVkFreeListAlloc {
public:
    GrVkSubHeap(const GrVkGpu* gpu, uint32_t memoryTypeIndex, uint32_t heapIndex,
                VkDeviceSize size, VkDeviceSize alignment);
    ~GrVkSubHeap();

    uint32_t memoryTypeIndex() const { return fMemoryTypeIndex; }
    VkDeviceMemory memory() { return fAlloc; }

    bool alloc(VkDeviceSize requestedSize, GrVkAlloc* alloc);
    void free(const GrVkAlloc& alloc);

private:
    const GrVkGpu* fGpu;
#ifdef SK_DEBUG
    uint32_t       fHeapIndex;
#endif    
    uint32_t       fMemoryTypeIndex;
    VkDeviceMemory fAlloc;

    typedef GrVkFreeListAlloc INHERITED;
};

class GrVkHeap {
public:
    enum Strategy {
        kSubAlloc_Strategy,       // alloc large subheaps and suballoc within them
        kSingleAlloc_Strategy     // alloc/recycle an individual subheap per object
    };

    GrVkHeap(const GrVkGpu* gpu, Strategy strategy, VkDeviceSize subHeapSize)
        : fGpu(gpu)
        , fSubHeapSize(subHeapSize)
        , fAllocSize(0)
        , fUsedSize(0) {
        if (strategy == kSubAlloc_Strategy) {
            fAllocFunc = &GrVkHeap::subAlloc;
        } else {
            fAllocFunc = &GrVkHeap::singleAlloc;
        }
    }

    ~GrVkHeap() {}

    VkDeviceSize allocSize() const { return fAllocSize; }
    VkDeviceSize usedSize() const { return fUsedSize; }

    bool alloc(VkDeviceSize size, VkDeviceSize alignment, uint32_t memoryTypeIndex,
               uint32_t heapIndex, GrVkAlloc* alloc) {
        SkASSERT(size > 0);
        return (*this.*fAllocFunc)(size, alignment, memoryTypeIndex, heapIndex, alloc);
    }
    bool free(const GrVkAlloc& alloc);

private:
    typedef bool (GrVkHeap::*AllocFunc)(VkDeviceSize size, VkDeviceSize alignment,
                                        uint32_t memoryTypeIndex, uint32_t heapIndex,
                                        GrVkAlloc* alloc);

    bool subAlloc(VkDeviceSize size, VkDeviceSize alignment,
                  uint32_t memoryTypeIndex, uint32_t heapIndex,
                  GrVkAlloc* alloc);
    bool singleAlloc(VkDeviceSize size, VkDeviceSize alignment,
                     uint32_t memoryTypeIndex, uint32_t heapIndex,
                     GrVkAlloc* alloc);

    const GrVkGpu*         fGpu;
    VkDeviceSize           fSubHeapSize;
    VkDeviceSize           fAllocSize;
    VkDeviceSize           fUsedSize;
    AllocFunc              fAllocFunc;
    SkTArray<std::unique_ptr<GrVkSubHeap>> fSubHeaps;
};
#endif