1 //
2 // Copyright 2016 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 // RendererVk.h:
7 // Defines the class interface for RendererVk.
8 //
9
10 #ifndef LIBANGLE_RENDERER_VULKAN_RENDERERVK_H_
11 #define LIBANGLE_RENDERER_VULKAN_RENDERERVK_H_
12
13 #include <deque>
14 #include <memory>
15 #include <mutex>
16
17 #include "vk_ext_provoking_vertex.h"
18 #include "volk.h"
19
20 #include "common/PackedEnums.h"
21 #include "common/PoolAlloc.h"
22 #include "common/angleutils.h"
23 #include "libANGLE/BlobCache.h"
24 #include "libANGLE/Caps.h"
25 #include "libANGLE/renderer/vulkan/QueryVk.h"
26 #include "libANGLE/renderer/vulkan/ResourceVk.h"
27 #include "libANGLE/renderer/vulkan/UtilsVk.h"
28 #include "libANGLE/renderer/vulkan/vk_format_utils.h"
29 #include "libANGLE/renderer/vulkan/vk_helpers.h"
30 #include "libANGLE/renderer/vulkan/vk_internal_shaders_autogen.h"
31 #include "libANGLE/renderer/vulkan/vk_mem_alloc_wrapper.h"
32
33 namespace egl
34 {
35 class Display;
36 class BlobCache;
37 } // namespace egl
38
39 namespace rx
40 {
41 class DisplayVk;
42 class FramebufferVk;
43
44 namespace vk
45 {
46 struct Format;
47 } // namespace vk
48
49 // Supports one semaphore from current surface, and one semaphore passed to
50 // glSignalSemaphoreEXT.
51 using SignalSemaphoreVector = angle::FixedVector<VkSemaphore, 2>;
52
CollectGarbage(std::vector<vk::GarbageObject> * garbageOut)53 inline void CollectGarbage(std::vector<vk::GarbageObject> *garbageOut) {}
54
55 template <typename ArgT, typename... ArgsT>
CollectGarbage(std::vector<vk::GarbageObject> * garbageOut,ArgT object,ArgsT...objectsIn)56 void CollectGarbage(std::vector<vk::GarbageObject> *garbageOut, ArgT object, ArgsT... objectsIn)
57 {
58 if (object->valid())
59 {
60 garbageOut->emplace_back(vk::GarbageObject::Get(object));
61 }
62 CollectGarbage(garbageOut, objectsIn...);
63 }
64
65 class RendererVk : angle::NonCopyable
66 {
67 public:
68 RendererVk();
69 ~RendererVk();
70
71 angle::Result initialize(DisplayVk *displayVk,
72 egl::Display *display,
73 const char *wsiExtension,
74 const char *wsiLayer);
75 // Reload volk vk* function ptrs if needed for an already initialized RendererVk
76 void reloadVolkIfNeeded() const;
77 void onDestroy();
78
79 void notifyDeviceLost();
80 bool isDeviceLost() const;
81
82 std::string getVendorString() const;
83 std::string getRendererDescription() const;
84
85 gl::Version getMaxSupportedESVersion() const;
86 gl::Version getMaxConformantESVersion() const;
87
getInstance()88 VkInstance getInstance() const { return mInstance; }
getPhysicalDevice()89 VkPhysicalDevice getPhysicalDevice() const { return mPhysicalDevice; }
getPhysicalDeviceProperties()90 const VkPhysicalDeviceProperties &getPhysicalDeviceProperties() const
91 {
92 return mPhysicalDeviceProperties;
93 }
getPhysicalDeviceSubgroupProperties()94 const VkPhysicalDeviceSubgroupProperties &getPhysicalDeviceSubgroupProperties() const
95 {
96 return mPhysicalDeviceSubgroupProperties;
97 }
getPhysicalDeviceFeatures()98 const VkPhysicalDeviceFeatures &getPhysicalDeviceFeatures() const
99 {
100 return mPhysicalDeviceFeatures;
101 }
getDevice()102 VkDevice getDevice() const { return mDevice; }
103
getAllocator()104 const VmaAllocator &getAllocator() const { return mAllocator; }
105
106 angle::Result selectPresentQueueForSurface(DisplayVk *displayVk,
107 VkSurfaceKHR surface,
108 uint32_t *presentQueueOut);
109
110 const gl::Caps &getNativeCaps() const;
111 const gl::TextureCapsMap &getNativeTextureCaps() const;
112 const gl::Extensions &getNativeExtensions() const;
113 const gl::Limitations &getNativeLimitations() const;
114
getQueueFamilyIndex()115 uint32_t getQueueFamilyIndex() const { return mCurrentQueueFamilyIndex; }
getQueueFamilyProperties()116 const VkQueueFamilyProperties &getQueueFamilyProperties() const
117 {
118 return mQueueFamilyProperties[mCurrentQueueFamilyIndex];
119 }
120
getMemoryProperties()121 const vk::MemoryProperties &getMemoryProperties() const { return mMemoryProperties; }
122
getFormat(GLenum internalFormat)123 const vk::Format &getFormat(GLenum internalFormat) const
124 {
125 return mFormatTable[internalFormat];
126 }
127
getFormat(angle::FormatID formatID)128 const vk::Format &getFormat(angle::FormatID formatID) const { return mFormatTable[formatID]; }
129
130 // Queries the descriptor set layout cache. Creates the layout if not present.
131 angle::Result getDescriptorSetLayout(
132 vk::Context *context,
133 const vk::DescriptorSetLayoutDesc &desc,
134 vk::BindingPointer<vk::DescriptorSetLayout> *descriptorSetLayoutOut);
135
136 // Queries the pipeline layout cache. Creates the layout if not present.
137 angle::Result getPipelineLayout(vk::Context *context,
138 const vk::PipelineLayoutDesc &desc,
139 const vk::DescriptorSetLayoutPointerArray &descriptorSetLayouts,
140 vk::BindingPointer<vk::PipelineLayout> *pipelineLayoutOut);
141
142 angle::Result getPipelineCacheSize(DisplayVk *displayVk, size_t *pipelineCacheSizeOut);
143 angle::Result syncPipelineCacheVk(DisplayVk *displayVk);
144
145 // Issues a new serial for linked shader modules. Used in the pipeline cache.
146 Serial issueShaderSerial();
147
getFeatures()148 const angle::FeaturesVk &getFeatures() const { return mFeatures; }
getMaxVertexAttribDivisor()149 uint32_t getMaxVertexAttribDivisor() const { return mMaxVertexAttribDivisor; }
getMaxVertexAttribStride()150 VkDeviceSize getMaxVertexAttribStride() const { return mMaxVertexAttribStride; }
151
getMinImportedHostPointerAlignment()152 VkDeviceSize getMinImportedHostPointerAlignment() const
153 {
154 return mMinImportedHostPointerAlignment;
155 }
156
isMockICDEnabled()157 bool isMockICDEnabled() const { return mEnabledICD == vk::ICD::Mock; }
158
159 // Query the format properties for select bits (linearTilingFeatures, optimalTilingFeatures and
160 // bufferFeatures). Looks through mandatory features first, and falls back to querying the
161 // device (first time only).
162 bool hasLinearImageFormatFeatureBits(VkFormat format, const VkFormatFeatureFlags featureBits);
163 VkFormatFeatureFlags getImageFormatFeatureBits(VkFormat format,
164 const VkFormatFeatureFlags featureBits);
165 bool hasImageFormatFeatureBits(VkFormat format, const VkFormatFeatureFlags featureBits);
166 bool hasBufferFormatFeatureBits(VkFormat format, const VkFormatFeatureFlags featureBits);
167
getDriverPriority(egl::ContextPriority priority)168 ANGLE_INLINE egl::ContextPriority getDriverPriority(egl::ContextPriority priority)
169 {
170 return mPriorities[priority];
171 }
172
173 angle::Result queueSubmit(vk::Context *context,
174 egl::ContextPriority priority,
175 const VkSubmitInfo &submitInfo,
176 const vk::Fence *fence,
177 Serial *serialOut);
178 angle::Result queueWaitIdle(vk::Context *context, egl::ContextPriority priority);
179 angle::Result deviceWaitIdle(vk::Context *context);
180 VkResult queuePresent(egl::ContextPriority priority, const VkPresentInfoKHR &presentInfo);
181
182 // This command buffer should be submitted immediately via queueSubmitOneOff.
183 angle::Result getCommandBufferOneOff(vk::Context *context,
184 vk::PrimaryCommandBuffer *commandBufferOut);
185
186 // Fire off a single command buffer immediately with default priority.
187 // Command buffer must be allocated with getCommandBufferOneOff and is reclaimed.
188 angle::Result queueSubmitOneOff(vk::Context *context,
189 vk::PrimaryCommandBuffer &&primary,
190 egl::ContextPriority priority,
191 Serial *serialOut);
192
193 angle::Result newSharedFence(vk::Context *context, vk::Shared<vk::Fence> *sharedFenceOut);
resetSharedFence(vk::Shared<vk::Fence> * sharedFenceIn)194 inline void resetSharedFence(vk::Shared<vk::Fence> *sharedFenceIn)
195 {
196 sharedFenceIn->resetAndRecycle(&mFenceRecycler);
197 }
198
199 template <typename... ArgsT>
collectGarbageAndReinit(vk::SharedResourceUse * use,ArgsT...garbageIn)200 void collectGarbageAndReinit(vk::SharedResourceUse *use, ArgsT... garbageIn)
201 {
202 std::vector<vk::GarbageObject> sharedGarbage;
203 CollectGarbage(&sharedGarbage, garbageIn...);
204 if (!sharedGarbage.empty())
205 {
206 collectGarbage(std::move(*use), std::move(sharedGarbage));
207 }
208 else
209 {
210 // Force releasing "use" even if no garbage was created.
211 use->release();
212 }
213 // Keep "use" valid.
214 use->init();
215 }
216
collectGarbage(vk::SharedResourceUse && use,std::vector<vk::GarbageObject> && sharedGarbage)217 void collectGarbage(vk::SharedResourceUse &&use, std::vector<vk::GarbageObject> &&sharedGarbage)
218 {
219 if (!sharedGarbage.empty())
220 {
221 mSharedGarbage.emplace_back(std::move(use), std::move(sharedGarbage));
222 }
223 }
224
225 static constexpr size_t kMaxExtensionNames = 200;
226 using ExtensionNameList = angle::FixedVector<const char *, kMaxExtensionNames>;
227
228 angle::Result getPipelineCache(vk::PipelineCache **pipelineCache);
onNewGraphicsPipeline()229 void onNewGraphicsPipeline() { mPipelineCacheDirty = true; }
230
231 void onNewValidationMessage(const std::string &message);
232 std::string getAndClearLastValidationMessage(uint32_t *countSinceLastClear);
233
234 uint64_t getMaxFenceWaitTimeNs() const;
getCurrentQueueSerial()235 Serial getCurrentQueueSerial() const { return mCurrentQueueSerial; }
getLastSubmittedQueueSerial()236 Serial getLastSubmittedQueueSerial() const { return mLastSubmittedQueueSerial; }
getLastCompletedQueueSerial()237 Serial getLastCompletedQueueSerial() const { return mLastCompletedQueueSerial; }
238
239 void onCompletedSerial(Serial serial);
240
shouldCleanupGarbage()241 bool shouldCleanupGarbage()
242 {
243 return (mSharedGarbage.size() > mGarbageCollectionFlushThreshold);
244 }
245
enableDebugUtils()246 bool enableDebugUtils() const { return mEnableDebugUtils; }
247
248 private:
249 angle::Result initializeDevice(DisplayVk *displayVk, uint32_t queueFamilyIndex);
250 void ensureCapsInitialized() const;
251
252 void queryDeviceExtensionFeatures(const ExtensionNameList &deviceExtensionNames);
253
254 void initFeatures(DisplayVk *display, const ExtensionNameList &extensions);
255 void initPipelineCacheVkKey();
256 angle::Result initPipelineCache(DisplayVk *display,
257 vk::PipelineCache *pipelineCache,
258 bool *success);
259
260 template <VkFormatFeatureFlags VkFormatProperties::*features>
261 VkFormatFeatureFlags getFormatFeatureBits(VkFormat format,
262 const VkFormatFeatureFlags featureBits);
263
264 template <VkFormatFeatureFlags VkFormatProperties::*features>
265 bool hasFormatFeatureBits(VkFormat format, const VkFormatFeatureFlags featureBits);
266
267 angle::Result cleanupGarbage(bool block);
268
269 egl::Display *mDisplay;
270
271 mutable bool mCapsInitialized;
272 mutable gl::Caps mNativeCaps;
273 mutable gl::TextureCapsMap mNativeTextureCaps;
274 mutable gl::Extensions mNativeExtensions;
275 mutable gl::Limitations mNativeLimitations;
276 mutable angle::FeaturesVk mFeatures;
277
278 VkInstance mInstance;
279 bool mEnableValidationLayers;
280 bool mEnableDebugUtils;
281 vk::ICD mEnabledICD;
282 VkDebugUtilsMessengerEXT mDebugUtilsMessenger;
283 VkDebugReportCallbackEXT mDebugReportCallback;
284 VkPhysicalDevice mPhysicalDevice;
285 VkPhysicalDeviceProperties mPhysicalDeviceProperties;
286 VkPhysicalDeviceFeatures mPhysicalDeviceFeatures;
287 VkPhysicalDeviceLineRasterizationFeaturesEXT mLineRasterizationFeatures;
288 VkPhysicalDeviceProvokingVertexFeaturesEXT mProvokingVertexFeatures;
289 VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT mVertexAttributeDivisorFeatures;
290 VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT mVertexAttributeDivisorProperties;
291 VkPhysicalDeviceTransformFeedbackFeaturesEXT mTransformFeedbackFeatures;
292 VkPhysicalDeviceIndexTypeUint8FeaturesEXT mIndexTypeUint8Features;
293 VkPhysicalDeviceSubgroupProperties mPhysicalDeviceSubgroupProperties;
294 VkPhysicalDeviceExternalMemoryHostPropertiesEXT mPhysicalDeviceExternalMemoryHostProperties;
295 std::vector<VkQueueFamilyProperties> mQueueFamilyProperties;
296 std::mutex mQueueMutex;
297 angle::PackedEnumMap<egl::ContextPriority, VkQueue> mQueues;
298 angle::PackedEnumMap<egl::ContextPriority, egl::ContextPriority> mPriorities;
299 uint32_t mCurrentQueueFamilyIndex;
300 uint32_t mMaxVertexAttribDivisor;
301 VkDeviceSize mMaxVertexAttribStride;
302 VkDeviceSize mMinImportedHostPointerAlignment;
303 VkDevice mDevice;
304 AtomicSerialFactory mQueueSerialFactory;
305 AtomicSerialFactory mShaderSerialFactory;
306
307 Serial mLastCompletedQueueSerial;
308 Serial mLastSubmittedQueueSerial;
309 Serial mCurrentQueueSerial;
310
311 bool mDeviceLost;
312
313 vk::Recycler<vk::Fence> mFenceRecycler;
314
315 std::mutex mGarbageMutex;
316 vk::SharedGarbageList mSharedGarbage;
317
318 vk::MemoryProperties mMemoryProperties;
319 vk::FormatTable mFormatTable;
320
321 // All access to the pipeline cache is done through EGL objects so it is thread safe to not use
322 // a lock.
323 vk::PipelineCache mPipelineCache;
324 egl::BlobCache::Key mPipelineCacheVkBlobKey;
325 uint32_t mPipelineCacheVkUpdateTimeout;
326 bool mPipelineCacheDirty;
327 bool mPipelineCacheInitialized;
328
329 // A cache of VkFormatProperties as queried from the device over time.
330 std::array<VkFormatProperties, vk::kNumVkFormats> mFormatProperties;
331
332 // ANGLE uses a PipelineLayout cache to store compatible pipeline layouts.
333 std::mutex mPipelineLayoutCacheMutex;
334 PipelineLayoutCache mPipelineLayoutCache;
335
336 // DescriptorSetLayouts are also managed in a cache.
337 std::mutex mDescriptorSetLayoutCacheMutex;
338 DescriptorSetLayoutCache mDescriptorSetLayoutCache;
339
340 // Latest validation data for debug overlay.
341 std::string mLastValidationMessage;
342 uint32_t mValidationMessageCount;
343
344 // How close to VkPhysicalDeviceLimits::maxMemoryAllocationCount we allow ourselves to get
345 static constexpr double kPercentMaxMemoryAllocationCount = 0.3;
346 // How many objects to garbage collect before issuing a flush()
347 uint32_t mGarbageCollectionFlushThreshold;
348
349 // Only used for "one off" command buffers.
350 vk::CommandPool mOneOffCommandPool;
351
352 struct PendingOneOffCommands
353 {
354 Serial serial;
355 vk::PrimaryCommandBuffer commandBuffer;
356 };
357 std::deque<PendingOneOffCommands> mPendingOneOffCommands;
358
359 // track whether we initialized (or released) glslang
360 bool mGlslangInitialized;
361
362 VmaAllocator mAllocator;
363 };
364
365 } // namespace rx
366
367 #endif // LIBANGLE_RENDERER_VULKAN_RENDERERVK_H_
368