• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2022 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // AllocatorHelperRing:
7 //    Manages the ring buffer allocators used in the command buffers.
8 //
9 
10 #ifndef LIBANGLE_RENDERER_VULKAN_ALLOCATORHELPERRING_H_
11 #define LIBANGLE_RENDERER_VULKAN_ALLOCATORHELPERRING_H_
12 
13 #include "common/RingBufferAllocator.h"
14 #include "common/vulkan/vk_headers.h"
15 #include "libANGLE/renderer/vulkan/vk_command_buffer_utils.h"
16 #include "libANGLE/renderer/vulkan/vk_wrapper.h"
17 
18 namespace rx
19 {
20 namespace vk
21 {
22 namespace priv
23 {
24 class SecondaryCommandBuffer;
25 }  // namespace priv
26 
27 using SharedCommandMemoryAllocator = angle::SharedRingBufferAllocator;
28 using RingBufferAllocator          = angle::RingBufferAllocator;
29 
30 // Used in CommandBufferHelperCommon
31 class SharedCommandBlockAllocator
32 {
33   public:
SharedCommandBlockAllocator()34     SharedCommandBlockAllocator() : mAllocator(nullptr), mAllocSharedCP(nullptr) {}
35     void resetAllocator();
hasAllocatorLinks()36     bool hasAllocatorLinks() const { return mAllocator || mAllocSharedCP; }
37 
init()38     void init() {}
39 
40     void attachAllocator(SharedCommandMemoryAllocator *allocator);
41     SharedCommandMemoryAllocator *detachAllocator(bool isCommandBufferEmpty);
42 
getAllocator()43     SharedCommandMemoryAllocator *getAllocator() { return mAllocator; }
44 
45   private:
46     // Using a ring buffer allocator for less memory overhead (observed with the async queue
47     // ex-feature)
48     SharedCommandMemoryAllocator *mAllocator;
49     angle::SharedRingBufferAllocatorCheckPoint *mAllocSharedCP;
50     angle::RingBufferAllocatorCheckPoint mAllocReleaseCP;
51 };
52 
53 // Used in SecondaryCommandBuffer
54 class SharedCommandBlockPool final : angle::RingBufferAllocateListener
55 {
56   public:
SharedCommandBlockPool()57     SharedCommandBlockPool()
58         : mLastCommandBlock(nullptr), mFinishedCommandSize(0), mCommandBuffer(nullptr)
59     {}
60 
61     static constexpr size_t kCommandHeaderSize = 4;
62     using CommandHeaderIDType                  = uint16_t;
63     // Make sure the size of command header ID type is less than total command header size.
64     static_assert(sizeof(CommandHeaderIDType) < kCommandHeaderSize, "Check size of CommandHeader");
65 
setCommandBuffer(priv::SecondaryCommandBuffer * commandBuffer)66     void setCommandBuffer(priv::SecondaryCommandBuffer *commandBuffer)
67     {
68         mCommandBuffer = commandBuffer;
69     }
resetCommandBuffer()70     void resetCommandBuffer() { mCommandBuffer = nullptr; }
71 
reset(CommandBufferCommandTracker * commandBufferTracker)72     void reset(CommandBufferCommandTracker *commandBufferTracker)
73     {
74         mLastCommandBlock    = nullptr;
75         mFinishedCommandSize = 0;
76         if (mAllocator.valid())
77         {
78             mAllocator.release(mAllocator.getReleaseCheckPoint());
79             pushNewCommandBlock(mAllocator.allocate(0));
80         }
81     }
82 
initialize(SharedCommandMemoryAllocator * allocator)83     angle::Result initialize(SharedCommandMemoryAllocator *allocator)
84     {
85         return angle::Result::Continue;
86     }
87 
88     // Always valid (even if allocator is detached).
valid()89     bool valid() const { return true; }
empty()90     bool empty() const { return getCommandSize() == 0; }
91 
92     void getMemoryUsageStats(size_t *usedMemoryOut, size_t *allocatedMemoryOut) const;
93 
terminateLastCommandBlock()94     void terminateLastCommandBlock()
95     {
96         if (mLastCommandBlock)
97         {
98             ASSERT(mAllocator.valid());
99             ASSERT(mAllocator.getPointer() >= mLastCommandBlock);
100             ASSERT(mAllocator.getFragmentSize() >= kCommandHeaderSize);
101             reinterpret_cast<CommandHeaderIDType &>(*(mAllocator.getPointer())) = 0;
102         }
103     }
104 
105     // Initialize the SecondaryCommandBuffer by setting the allocator it will use
106     void attachAllocator(SharedCommandMemoryAllocator *source);
107     void detachAllocator(SharedCommandMemoryAllocator *destination);
108 
onNewVariableSizedCommand(const size_t requiredSize,const size_t allocationSize,uint8_t ** headerOut)109     void onNewVariableSizedCommand(const size_t requiredSize,
110                                    const size_t allocationSize,
111                                    uint8_t **headerOut)
112     {
113         *headerOut = allocateCommand(allocationSize);
114     }
onNewCommand(const size_t requiredSize,const size_t allocationSize,uint8_t ** headerOut)115     void onNewCommand(const size_t requiredSize, const size_t allocationSize, uint8_t **headerOut)
116     {
117         *headerOut = allocateCommand(allocationSize);
118     }
119 
120   private:
allocateCommand(size_t allocationSize)121     uint8_t *allocateCommand(size_t allocationSize)
122     {
123         ASSERT(mLastCommandBlock);
124         return mAllocator.allocate(static_cast<uint32_t>(allocationSize));
125     }
126 
127     // The following is used to give the size of the command buffer in bytes
getCommandSize()128     uint32_t getCommandSize() const
129     {
130         uint32_t result = mFinishedCommandSize;
131         if (mLastCommandBlock)
132         {
133             ASSERT(mAllocator.valid());
134             ASSERT(mAllocator.getPointer() >= mLastCommandBlock);
135             result += static_cast<uint32_t>(mAllocator.getPointer() - mLastCommandBlock);
136         }
137         return result;
138     }
139 
140     void pushNewCommandBlock(uint8_t *block);
141     void finishLastCommandBlock();
142 
143     // Functions derived from RingBufferAllocateListener
144     virtual void onRingBufferNewFragment() override;
145     virtual void onRingBufferFragmentEnd() override;
146 
147     // Using a ring buffer allocator for less memory overhead (observed with the async queue
148     // ex-feature)
149     RingBufferAllocator mAllocator;
150     uint8_t *mLastCommandBlock;
151     uint32_t mFinishedCommandSize;
152 
153     // Points to the parent command buffer.
154     priv::SecondaryCommandBuffer *mCommandBuffer;
155 };
156 
157 }  // namespace vk
158 }  // namespace rx
159 
160 #endif  // LIBANGLE_RENDERER_VULKAN_ALLOCATORHELPERRING_H_
161