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 virtual ~ResourceUseList(); 140 141 void add(const SharedResourceUse &resourceUse); 142 143 void releaseResourceUses(); 144 void releaseResourceUsesAndUpdateSerials(Serial serial); 145 146 private: 147 std::vector<SharedResourceUse> mResourceUses; 148 }; 149 add(const SharedResourceUse & resourceUse)150ANGLE_INLINE void ResourceUseList::add(const SharedResourceUse &resourceUse) 151 { 152 SharedResourceUse newUse; 153 newUse.set(resourceUse); 154 mResourceUses.emplace_back(std::move(newUse)); 155 } 156 157 // This is a helper class for back-end objects used in Vk command buffers. They keep a record 158 // of their use in ANGLE and VkQueues via SharedResourceUse. 159 class Resource : angle::NonCopyable 160 { 161 public: 162 virtual ~Resource(); 163 164 // Returns true if the resource is used by ANGLE in an unflushed command buffer. usedInRecordedCommands()165 bool usedInRecordedCommands() const { return mUse.usedInRecordedCommands(); } 166 167 // Determine if the driver has finished execution with this resource. usedInRunningCommands(Serial lastCompletedSerial)168 bool usedInRunningCommands(Serial lastCompletedSerial) const 169 { 170 return mUse.usedInRunningCommands(lastCompletedSerial); 171 } 172 173 // Returns true if the resource is in use by ANGLE or the driver. isCurrentlyInUse(Serial lastCompletedSerial)174 bool isCurrentlyInUse(Serial lastCompletedSerial) const 175 { 176 return mUse.isCurrentlyInUse(lastCompletedSerial); 177 } 178 179 // Ensures the driver is caught up to this resource and it is only in use by ANGLE. 180 angle::Result finishRunningCommands(ContextVk *contextVk); 181 182 // Complete all recorded and in-flight commands involving this resource 183 angle::Result waitForIdle(ContextVk *contextVk); 184 185 // Adds the resource to a resource use list. 186 void retain(ResourceUseList *resourceUseList); 187 188 protected: 189 Resource(); 190 191 // Current resource lifetime. 192 SharedResourceUse mUse; 193 }; 194 retain(ResourceUseList * resourceUseList)195ANGLE_INLINE void Resource::retain(ResourceUseList *resourceUseList) 196 { 197 // Store reference in resource list. 198 resourceUseList->add(mUse); 199 } 200 } // namespace vk 201 } // namespace rx 202 203 #endif // LIBANGLE_RENDERER_VULKAN_RESOURCEVK_H_ 204