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