1 // 2 // Copyright 2017 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 // ResourceVk: 7 // Resource lifetime tracking in the Vulkan back-end. 8 // 9 10 #ifndef LIBANGLE_RENDERER_VULKAN_RESOURCEVK_H_ 11 #define LIBANGLE_RENDERER_VULKAN_RESOURCEVK_H_ 12 13 #include "libANGLE/renderer/vulkan/vk_utils.h" 14 15 namespace rx 16 { 17 namespace vk 18 { 19 // Tracks how a resource is used by ANGLE and by a VkQueue. The reference count indicates the number 20 // of times a resource is retained by ANGLE. The serial indicates the most recent use of a resource 21 // in the VkQueue. The reference count and serial together can determine if a resource is currently 22 // in use. 23 struct ResourceUse 24 { 25 ResourceUse() = default; 26 27 // The number of times a resource is retained by ANGLE. 28 uint32_t counter = 0; 29 30 // The most recent time of use in a VkQueue. 31 Serial serial; 32 }; 33 34 class SharedResourceUse final : angle::NonCopyable 35 { 36 public: SharedResourceUse()37 SharedResourceUse() : mUse(nullptr) {} ~SharedResourceUse()38 ~SharedResourceUse() { ASSERT(!valid()); } SharedResourceUse(SharedResourceUse && rhs)39 SharedResourceUse(SharedResourceUse &&rhs) : mUse(rhs.mUse) { rhs.mUse = nullptr; } 40 SharedResourceUse &operator=(SharedResourceUse &&rhs) 41 { 42 std::swap(mUse, rhs.mUse); 43 return *this; 44 } 45 valid()46 ANGLE_INLINE bool valid() const { return mUse != nullptr; } 47 init()48 void init() 49 { 50 ASSERT(!mUse); 51 mUse = new ResourceUse; 52 mUse->counter++; 53 } 54 55 // Specifically for use with command buffers that are used as one-offs. updateSerialOneOff(Serial serial)56 void updateSerialOneOff(Serial serial) { mUse->serial = serial; } 57 release()58 ANGLE_INLINE void release() 59 { 60 ASSERT(valid()); 61 ASSERT(mUse->counter > 0); 62 if (--mUse->counter == 0) 63 { 64 delete mUse; 65 } 66 mUse = nullptr; 67 } 68 releaseAndUpdateSerial(Serial serial)69 ANGLE_INLINE void releaseAndUpdateSerial(Serial serial) 70 { 71 ASSERT(valid()); 72 ASSERT(mUse->counter > 0); 73 ASSERT(mUse->serial <= serial); 74 mUse->serial = serial; 75 release(); 76 } 77 set(const SharedResourceUse & rhs)78 ANGLE_INLINE void set(const SharedResourceUse &rhs) 79 { 80 ASSERT(rhs.valid()); 81 ASSERT(!valid()); 82 ASSERT(rhs.mUse->counter < std::numeric_limits<uint32_t>::max()); 83 mUse = rhs.mUse; 84 mUse->counter++; 85 } 86 87 // The base counter value for a live resource is "1". Any value greater than one indicates 88 // the resource is in use by a command buffer. usedInRecordedCommands()89 ANGLE_INLINE bool usedInRecordedCommands() const 90 { 91 ASSERT(valid()); 92 return mUse->counter > 1; 93 } 94 usedInRunningCommands(Serial lastCompletedSerial)95 ANGLE_INLINE bool usedInRunningCommands(Serial lastCompletedSerial) const 96 { 97 ASSERT(valid()); 98 return mUse->serial > lastCompletedSerial; 99 } 100 isCurrentlyInUse(Serial lastCompletedSerial)101 ANGLE_INLINE bool isCurrentlyInUse(Serial lastCompletedSerial) const 102 { 103 return usedInRecordedCommands() || usedInRunningCommands(lastCompletedSerial); 104 } 105 getSerial()106 ANGLE_INLINE Serial getSerial() const 107 { 108 ASSERT(valid()); 109 return mUse->serial; 110 } 111 112 private: 113 ResourceUse *mUse; 114 }; 115 116 class SharedGarbage 117 { 118 public: 119 SharedGarbage(); 120 SharedGarbage(SharedGarbage &&other); 121 SharedGarbage(SharedResourceUse &&use, std::vector<GarbageObject> &&garbage); 122 ~SharedGarbage(); 123 SharedGarbage &operator=(SharedGarbage &&rhs); 124 125 bool destroyIfComplete(RendererVk *renderer, Serial completedSerial); 126 127 private: 128 SharedResourceUse mLifetime; 129 std::vector<GarbageObject> mGarbage; 130 }; 131 132 using SharedGarbageList = std::vector<SharedGarbage>; 133 134 // Mixin to abstract away the resource use tracking. 135 class ResourceUseList final : angle::NonCopyable 136 { 137 public: 138 ResourceUseList(); 139 ResourceUseList(ResourceUseList &&other); 140 virtual ~ResourceUseList(); 141 ResourceUseList &operator=(ResourceUseList &&rhs); 142 143 void add(const SharedResourceUse &resourceUse); 144 145 void releaseResourceUses(); 146 void releaseResourceUsesAndUpdateSerials(Serial serial); 147 empty()148 bool empty() { return mResourceUses.empty(); } 149 150 private: 151 std::vector<SharedResourceUse> mResourceUses; 152 }; 153 add(const SharedResourceUse & resourceUse)154ANGLE_INLINE void ResourceUseList::add(const SharedResourceUse &resourceUse) 155 { 156 SharedResourceUse newUse; 157 newUse.set(resourceUse); 158 mResourceUses.emplace_back(std::move(newUse)); 159 } 160 161 // This is a helper class for back-end objects used in Vk command buffers. They keep a record 162 // of their use in ANGLE and VkQueues via SharedResourceUse. 163 class Resource : angle::NonCopyable 164 { 165 public: 166 virtual ~Resource(); 167 168 // Returns true if the resource is used by ANGLE in an unflushed command buffer. usedInRecordedCommands()169 bool usedInRecordedCommands() const { return mUse.usedInRecordedCommands(); } 170 171 // Determine if the driver has finished execution with this resource. usedInRunningCommands(Serial lastCompletedSerial)172 bool usedInRunningCommands(Serial lastCompletedSerial) const 173 { 174 return mUse.usedInRunningCommands(lastCompletedSerial); 175 } 176 177 // Returns true if the resource is in use by ANGLE or the driver. isCurrentlyInUse(Serial lastCompletedSerial)178 bool isCurrentlyInUse(Serial lastCompletedSerial) const 179 { 180 return mUse.isCurrentlyInUse(lastCompletedSerial); 181 } 182 183 // Ensures the driver is caught up to this resource and it is only in use by ANGLE. 184 angle::Result finishRunningCommands(ContextVk *contextVk); 185 186 // Complete all recorded and in-flight commands involving this resource 187 angle::Result waitForIdle(ContextVk *contextVk, const char *debugMessage); 188 189 // Adds the resource to a resource use list. 190 void retain(ResourceUseList *resourceUseList) const; 191 192 protected: 193 Resource(); 194 Resource(Resource &&other); 195 196 // Current resource lifetime. 197 SharedResourceUse mUse; 198 }; 199 retain(ResourceUseList * resourceUseList)200ANGLE_INLINE void Resource::retain(ResourceUseList *resourceUseList) const 201 { 202 // Store reference in resource list. 203 resourceUseList->add(mUse); 204 } 205 206 } // namespace vk 207 } // namespace rx 208 209 #endif // LIBANGLE_RENDERER_VULKAN_RESOURCEVK_H_ 210