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