| // |
| // Copyright 2016 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| // vk_renderer.h: |
| // Defines the class interface for Renderer. |
| // |
| |
| #ifndef LIBANGLE_RENDERER_VULKAN_RENDERERVK_H_ |
| #define LIBANGLE_RENDERER_VULKAN_RENDERERVK_H_ |
| |
| #include <condition_variable> |
| #include <deque> |
| #include <memory> |
| #include <mutex> |
| #include <queue> |
| #include <thread> |
| |
| #include "common/PackedEnums.h" |
| #include "common/SimpleMutex.h" |
| #include "common/WorkerThread.h" |
| #include "common/angleutils.h" |
| #include "common/vulkan/vk_headers.h" |
| #include "common/vulkan/vulkan_icd.h" |
| #include "libANGLE/Caps.h" |
| #include "libANGLE/renderer/vulkan/CommandQueue.h" |
| #include "libANGLE/renderer/vulkan/DebugAnnotatorVk.h" |
| #include "libANGLE/renderer/vulkan/MemoryTracking.h" |
| #include "libANGLE/renderer/vulkan/QueryVk.h" |
| #include "libANGLE/renderer/vulkan/UtilsVk.h" |
| #include "libANGLE/renderer/vulkan/vk_format_utils.h" |
| #include "libANGLE/renderer/vulkan/vk_helpers.h" |
| #include "libANGLE/renderer/vulkan/vk_internal_shaders_autogen.h" |
| #include "libANGLE/renderer/vulkan/vk_mem_alloc_wrapper.h" |
| #include "libANGLE/renderer/vulkan/vk_resource.h" |
| |
| namespace angle |
| { |
| class Library; |
| struct FrontendFeatures; |
| } // namespace angle |
| |
| namespace rx |
| { |
| class FramebufferVk; |
| |
| namespace vk |
| { |
| class Format; |
| |
| static constexpr size_t kMaxExtensionNames = 400; |
| using ExtensionNameList = angle::FixedVector<const char *, kMaxExtensionNames>; |
| |
| static constexpr size_t kMaxSyncValExtraProperties = 9; |
| // Information used to accurately skip known synchronization issues in ANGLE. |
| // TODO: remove messageContents1 and messageContents2 fields after all |
| // supressions have transitioned to using extraProperties. |
| struct SkippedSyncvalMessage |
| { |
| const char *messageId; |
| const char *messageContents1; |
| const char *messageContents2 = ""; |
| bool isDueToNonConformantCoherentColorFramebufferFetch = false; |
| const char *extraProperties[kMaxSyncValExtraProperties] = {}; |
| }; |
| |
| class ImageMemorySuballocator : angle::NonCopyable |
| { |
| public: |
| ImageMemorySuballocator(); |
| ~ImageMemorySuballocator(); |
| |
| void destroy(vk::Renderer *renderer); |
| |
| // Allocates memory for the image and binds it. |
| VkResult allocateAndBindMemory(ErrorContext *context, |
| Image *image, |
| const VkImageCreateInfo *imageCreateInfo, |
| VkMemoryPropertyFlags requiredFlags, |
| VkMemoryPropertyFlags preferredFlags, |
| const VkMemoryRequirements *memoryRequirements, |
| const bool allocateDedicatedMemory, |
| MemoryAllocationType memoryAllocationType, |
| Allocation *allocationOut, |
| VkMemoryPropertyFlags *memoryFlagsOut, |
| uint32_t *memoryTypeIndexOut, |
| VkDeviceSize *sizeOut); |
| |
| // Maps the memory to initialize with non-zero value. |
| VkResult mapMemoryAndInitWithNonZeroValue(vk::Renderer *renderer, |
| Allocation *allocation, |
| VkDeviceSize size, |
| int value, |
| VkMemoryPropertyFlags flags); |
| |
| // Determines if dedicated memory is required for the allocation. |
| bool needsDedicatedMemory(VkDeviceSize size) const; |
| }; |
| |
| // Supports one semaphore from current surface, and one semaphore passed to |
| // glSignalSemaphoreEXT. |
| using SignalSemaphoreVector = angle::FixedVector<VkSemaphore, 2>; |
| |
| class OneOffCommandPool : angle::NonCopyable |
| { |
| public: |
| OneOffCommandPool(); |
| void init(vk::ProtectionType protectionType); |
| angle::Result getCommandBuffer(vk::ErrorContext *context, |
| vk::ScopedPrimaryCommandBuffer *commandBufferOut); |
| void releaseCommandBuffer(const QueueSerial &submitQueueSerial, |
| vk::PrimaryCommandBuffer &&primary); |
| void destroy(VkDevice device); |
| |
| private: |
| vk::ProtectionType mProtectionType; |
| angle::SimpleMutex mMutex; |
| vk::CommandPool mCommandPool; |
| struct PendingOneOffCommands |
| { |
| vk::ResourceUse use; |
| vk::PrimaryCommandBuffer commandBuffer; |
| }; |
| std::deque<PendingOneOffCommands> mPendingCommands; |
| }; |
| |
| enum class UseDebugLayers |
| { |
| Yes, |
| YesIfAvailable, |
| No, |
| }; |
| |
| enum class UseVulkanSwapchain |
| { |
| Yes, |
| No, |
| }; |
| |
| class Renderer : angle::NonCopyable |
| { |
| public: |
| Renderer(); |
| ~Renderer(); |
| |
| angle::Result initialize(vk::ErrorContext *context, |
| vk::GlobalOps *globalOps, |
| angle::vk::ICD desiredICD, |
| uint32_t preferredVendorId, |
| uint32_t preferredDeviceId, |
| const uint8_t *preferredDeviceUuid, |
| const uint8_t *preferredDriverUuid, |
| VkDriverId preferredDriverId, |
| UseDebugLayers useDebugLayers, |
| const char *wsiExtension, |
| const char *wsiLayer, |
| angle::NativeWindowSystem nativeWindowSystem, |
| const angle::FeatureOverrides &featureOverrides); |
| |
| // Reload volk vk* function ptrs if needed for an already initialized Renderer |
| void reloadVolkIfNeeded() const; |
| void onDestroy(vk::ErrorContext *context); |
| |
| void notifyDeviceLost(); |
| bool isDeviceLost() const; |
| bool hasSharedGarbage(); |
| |
| std::string getVendorString() const; |
| std::string getRendererDescription() const; |
| std::string getVersionString(bool includeFullVersion) const; |
| |
| gl::Version getMaxSupportedESVersion() const; |
| gl::Version getMaxConformantESVersion() const; |
| |
| uint32_t getDeviceVersion() const; |
| VkInstance getInstance() const { return mInstance; } |
| VkPhysicalDevice getPhysicalDevice() const { return mPhysicalDevice; } |
| const VkPhysicalDeviceProperties &getPhysicalDeviceProperties() const |
| { |
| return mPhysicalDeviceProperties; |
| } |
| const VkPhysicalDeviceDrmPropertiesEXT &getPhysicalDeviceDrmProperties() const |
| { |
| return mDrmProperties; |
| } |
| const VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT & |
| getPhysicalDevicePrimitivesGeneratedQueryFeatures() const |
| { |
| return mPrimitivesGeneratedQueryFeatures; |
| } |
| const VkPhysicalDeviceHostImageCopyPropertiesEXT &getPhysicalDeviceHostImageCopyProperties() |
| const |
| { |
| return mHostImageCopyProperties; |
| } |
| const VkPhysicalDeviceFeatures &getPhysicalDeviceFeatures() const |
| { |
| return mPhysicalDeviceFeatures; |
| } |
| const VkPhysicalDeviceFeatures2KHR &getEnabledFeatures() const { return mEnabledFeatures; } |
| VkDevice getDevice() const { return mDevice; } |
| |
| const vk::Allocator &getAllocator() const { return mAllocator; } |
| vk::ImageMemorySuballocator &getImageMemorySuballocator() { return mImageMemorySuballocator; } |
| |
| angle::Result checkQueueForSurfacePresent(vk::ErrorContext *context, |
| VkSurfaceKHR surface, |
| bool *supportedOut); |
| |
| const gl::Caps &getNativeCaps() const; |
| const gl::TextureCapsMap &getNativeTextureCaps() const; |
| const gl::Extensions &getNativeExtensions() const; |
| const gl::Limitations &getNativeLimitations() const; |
| const ShPixelLocalStorageOptions &getNativePixelLocalStorageOptions() const; |
| void initializeFrontendFeatures(angle::FrontendFeatures *features) const; |
| |
| uint32_t getQueueFamilyIndex() const { return mCurrentQueueFamilyIndex; } |
| const VkQueueFamilyProperties &getQueueFamilyProperties() const |
| { |
| return mQueueFamilyProperties[mCurrentQueueFamilyIndex]; |
| } |
| const DeviceQueueIndex getDeviceQueueIndex(egl::ContextPriority priority) const |
| { |
| return mCommandQueue.getDeviceQueueIndex(priority); |
| } |
| const DeviceQueueIndex getDefaultDeviceQueueIndex() const |
| { |
| // By default it will always use medium priority |
| return mCommandQueue.getDeviceQueueIndex(egl::ContextPriority::Medium); |
| } |
| |
| const vk::MemoryProperties &getMemoryProperties() const { return mMemoryProperties; } |
| |
| const vk::Format &getFormat(GLenum internalFormat) const |
| { |
| return mFormatTable[internalFormat]; |
| } |
| |
| const vk::Format &getFormat(angle::FormatID formatID) const { return mFormatTable[formatID]; } |
| |
| // Get the pipeline cache data after retrieving the size, but only if the size is increased |
| // since last query. This function should be called with the |mPipelineCacheMutex| lock already |
| // held. |
| angle::Result getLockedPipelineCacheDataIfNew(vk::ErrorContext *context, |
| size_t *pipelineCacheSizeOut, |
| size_t lastSyncSize, |
| std::vector<uint8_t> *pipelineCacheDataOut); |
| angle::Result syncPipelineCacheVk(vk::ErrorContext *context, |
| vk::GlobalOps *globalOps, |
| const gl::Context *contextGL); |
| |
| const angle::FeaturesVk &getFeatures() const { return mFeatures; } |
| uint32_t getMaxVertexAttribDivisor() const { return mMaxVertexAttribDivisor; } |
| VkDeviceSize getMaxVertexAttribStride() const { return mMaxVertexAttribStride; } |
| uint32_t getMaxColorInputAttachmentCount() const { return mMaxColorInputAttachmentCount; } |
| ANGLE_INLINE bool isInFlightCommandsEmpty() const |
| { |
| return mCommandQueue.isInFlightCommandsEmpty(); |
| } |
| |
| uint32_t getDefaultUniformBufferSize() const { return mDefaultUniformBufferSize; } |
| |
| angle::vk::ICD getEnabledICD() const { return mEnabledICD; } |
| bool isMockICDEnabled() const { return mEnabledICD == angle::vk::ICD::Mock; } |
| |
| // Query the format properties for select bits (linearTilingFeatures, optimalTilingFeatures |
| // and bufferFeatures). Looks through mandatory features first, and falls back to querying |
| // the device (first time only). |
| bool hasLinearImageFormatFeatureBits(angle::FormatID format, |
| const VkFormatFeatureFlags featureBits) const; |
| VkFormatFeatureFlags getLinearImageFormatFeatureBits( |
| angle::FormatID format, |
| const VkFormatFeatureFlags featureBits) const; |
| VkFormatFeatureFlags getImageFormatFeatureBits(angle::FormatID format, |
| const VkFormatFeatureFlags featureBits) const; |
| bool hasImageFormatFeatureBits(angle::FormatID format, |
| const VkFormatFeatureFlags featureBits) const; |
| bool hasBufferFormatFeatureBits(angle::FormatID format, |
| const VkFormatFeatureFlags featureBits) const; |
| |
| bool isAsyncCommandBufferResetAndGarbageCleanupEnabled() const |
| { |
| return mFeatures.asyncCommandBufferResetAndGarbageCleanup.enabled; |
| } |
| |
| ANGLE_INLINE egl::ContextPriority getDriverPriority(egl::ContextPriority priority) |
| { |
| return mCommandQueue.getDriverPriority(priority); |
| } |
| |
| VkQueue getQueue(egl::ContextPriority priority) { return mCommandQueue.getQueue(priority); } |
| // Helpers to implement the functionality of EGL_ANGLE_device_vulkan |
| void lockVulkanQueueForExternalAccess() { mCommandQueue.lockVulkanQueueForExternalAccess(); } |
| void unlockVulkanQueueForExternalAccess() |
| { |
| mCommandQueue.unlockVulkanQueueForExternalAccess(); |
| } |
| |
| // This command buffer should be submitted immediately via queueSubmitOneOff. |
| angle::Result getCommandBufferOneOff(vk::ErrorContext *context, |
| vk::ProtectionType protectionType, |
| vk::ScopedPrimaryCommandBuffer *commandBufferOut) |
| { |
| return mOneOffCommandPoolMap[protectionType].getCommandBuffer(context, commandBufferOut); |
| } |
| |
| // Fire off a single command buffer immediately with default priority. |
| // Command buffer must be allocated with getCommandBufferOneOff and is reclaimed. |
| angle::Result queueSubmitOneOff(vk::ErrorContext *context, |
| vk::ScopedPrimaryCommandBuffer &&scopedCommandBuffer, |
| vk::ProtectionType protectionType, |
| egl::ContextPriority priority, |
| VkSemaphore waitSemaphore, |
| VkPipelineStageFlags waitSemaphoreStageMasks, |
| QueueSerial *queueSerialOut); |
| |
| angle::Result queueSubmitWaitSemaphore(vk::ErrorContext *context, |
| egl::ContextPriority priority, |
| const vk::Semaphore &waitSemaphore, |
| VkPipelineStageFlags waitSemaphoreStageMasks, |
| QueueSerial submitQueueSerial); |
| |
| template <typename ArgT> |
| void collectGarbage(const vk::ResourceUse &use, ArgT garbageIn) |
| { |
| if (!garbageIn->valid()) |
| { |
| return; |
| } |
| |
| if (hasResourceUseFinished(use)) |
| { |
| garbageIn->destroy(mDevice); |
| } |
| else |
| { |
| std::vector<vk::GarbageObject> sharedGarbage; |
| sharedGarbage.emplace_back(vk::GarbageObject::Get(garbageIn)); |
| collectGarbage(use, std::move(sharedGarbage)); |
| } |
| } |
| |
| void collectGarbage(const vk::ResourceUse &use, vk::GarbageObjects &&sharedGarbage) |
| { |
| ASSERT(!sharedGarbage.empty()); |
| if (hasResourceUseFinished(use)) |
| { |
| for (auto &garbage : sharedGarbage) |
| { |
| garbage.destroy(this); |
| } |
| sharedGarbage.clear(); |
| } |
| else |
| { |
| vk::SharedGarbage garbage(use, std::move(sharedGarbage)); |
| mSharedGarbageList.add(this, std::move(garbage)); |
| } |
| } |
| |
| void collectSuballocationGarbage(const vk::ResourceUse &use, |
| vk::BufferSuballocation &&suballocation, |
| vk::Buffer &&buffer) |
| { |
| vk::BufferSuballocationGarbage garbage(use, std::move(suballocation), std::move(buffer)); |
| mSuballocationGarbageList.add(this, std::move(garbage)); |
| } |
| |
| size_t getNextPipelineCacheBlobCacheSlotIndex(size_t *previousSlotIndexOut); |
| size_t updatePipelineCacheChunkCount(size_t chunkCount); |
| angle::Result getPipelineCache(vk::ErrorContext *context, |
| vk::PipelineCacheAccess *pipelineCacheOut); |
| angle::Result mergeIntoPipelineCache(vk::ErrorContext *context, |
| const vk::PipelineCache &pipelineCache); |
| |
| void onNewValidationMessage(const std::string &message); |
| std::string getAndClearLastValidationMessage(uint32_t *countSinceLastClear); |
| |
| const std::vector<const char *> &getSkippedValidationMessages() const |
| { |
| return mSkippedValidationMessages; |
| } |
| const std::vector<vk::SkippedSyncvalMessage> &getSkippedSyncvalMessages() const |
| { |
| return mSkippedSyncvalMessages; |
| } |
| |
| bool isCoherentColorFramebufferFetchEmulated() const |
| { |
| return mFeatures.supportsShaderFramebufferFetch.enabled && |
| !mIsColorFramebufferFetchCoherent; |
| } |
| |
| void onColorFramebufferFetchUse() { mIsColorFramebufferFetchUsed = true; } |
| bool isColorFramebufferFetchUsed() const { return mIsColorFramebufferFetchUsed; } |
| |
| uint64_t getMaxFenceWaitTimeNs() const; |
| |
| ANGLE_INLINE bool isCommandQueueBusy() { return mCommandQueue.isBusy(this); } |
| |
| angle::VulkanPerfCounters getCommandQueuePerfCounters() |
| { |
| return mCommandQueue.getPerfCounters(); |
| } |
| void resetCommandQueuePerFrameCounters() { mCommandQueue.resetPerFramePerfCounters(); } |
| |
| vk::GlobalOps *getGlobalOps() const { return mGlobalOps; } |
| |
| bool enableDebugUtils() const { return mEnableDebugUtils; } |
| bool angleDebuggerMode() const { return mAngleDebuggerMode; } |
| |
| SamplerCache &getSamplerCache() { return mSamplerCache; } |
| SamplerYcbcrConversionCache &getYuvConversionCache() { return mYuvConversionCache; } |
| |
| void onAllocateHandle(vk::HandleType handleType); |
| void onDeallocateHandle(vk::HandleType handleType, uint32_t count); |
| |
| bool getEnableValidationLayers() const { return mEnableValidationLayers; } |
| |
| vk::ResourceSerialFactory &getResourceSerialFactory() { return mResourceSerialFactory; } |
| |
| void setGlobalDebugAnnotator(bool *installedAnnotatorOut); |
| |
| void outputVmaStatString(); |
| |
| bool haveSameFormatFeatureBits(angle::FormatID formatID1, angle::FormatID formatID2) const; |
| |
| void cleanupGarbage(bool *anyGarbageCleanedOut); |
| void cleanupPendingSubmissionGarbage(); |
| |
| angle::Result submitCommands(vk::ErrorContext *context, |
| vk::ProtectionType protectionType, |
| egl::ContextPriority contextPriority, |
| const vk::Semaphore *signalSemaphore, |
| const vk::SharedExternalFence *externalFence, |
| std::vector<VkImageMemoryBarrier> &&imagesToTransitionToForeign, |
| const QueueSerial &submitQueueSerial); |
| |
| angle::Result submitPriorityDependency(vk::ErrorContext *context, |
| vk::ProtectionTypes protectionTypes, |
| egl::ContextPriority srcContextPriority, |
| egl::ContextPriority dstContextPriority, |
| SerialIndex index); |
| |
| void handleDeviceLost(); |
| angle::Result finishResourceUse(vk::ErrorContext *context, const vk::ResourceUse &use); |
| angle::Result finishQueueSerial(vk::ErrorContext *context, const QueueSerial &queueSerial); |
| angle::Result waitForResourceUseToFinishWithUserTimeout(vk::ErrorContext *context, |
| const vk::ResourceUse &use, |
| uint64_t timeout, |
| VkResult *result); |
| angle::Result checkCompletedCommands(vk::ErrorContext *context); |
| |
| angle::Result checkCompletedCommandsAndCleanup(vk::ErrorContext *context); |
| angle::Result releaseFinishedCommands(vk::ErrorContext *context); |
| |
| angle::Result flushWaitSemaphores(vk::ProtectionType protectionType, |
| egl::ContextPriority priority, |
| std::vector<VkSemaphore> &&waitSemaphores, |
| std::vector<VkPipelineStageFlags> &&waitSemaphoreStageMasks); |
| angle::Result flushRenderPassCommands(vk::Context *context, |
| vk::ProtectionType protectionType, |
| egl::ContextPriority priority, |
| const vk::RenderPass &renderPass, |
| VkFramebuffer framebufferOverride, |
| vk::RenderPassCommandBufferHelper **renderPassCommands); |
| angle::Result flushOutsideRPCommands( |
| vk::Context *context, |
| vk::ProtectionType protectionType, |
| egl::ContextPriority priority, |
| vk::OutsideRenderPassCommandBufferHelper **outsideRPCommands); |
| |
| VkResult queuePresent(vk::ErrorContext *context, |
| egl::ContextPriority priority, |
| const VkPresentInfoKHR &presentInfo); |
| |
| angle::Result getOutsideRenderPassCommandBufferHelper( |
| vk::ErrorContext *context, |
| vk::SecondaryCommandPool *commandPool, |
| vk::SecondaryCommandMemoryAllocator *commandsAllocator, |
| vk::OutsideRenderPassCommandBufferHelper **commandBufferHelperOut); |
| angle::Result getRenderPassCommandBufferHelper( |
| vk::ErrorContext *context, |
| vk::SecondaryCommandPool *commandPool, |
| vk::SecondaryCommandMemoryAllocator *commandsAllocator, |
| vk::RenderPassCommandBufferHelper **commandBufferHelperOut); |
| |
| void recycleOutsideRenderPassCommandBufferHelper( |
| vk::OutsideRenderPassCommandBufferHelper **commandBuffer); |
| void recycleRenderPassCommandBufferHelper(vk::RenderPassCommandBufferHelper **commandBuffer); |
| |
| // Process GPU memory reports |
| void processMemoryReportCallback(const VkDeviceMemoryReportCallbackDataEXT &callbackData) |
| { |
| bool logCallback = getFeatures().logMemoryReportCallbacks.enabled; |
| mMemoryReport.processCallback(callbackData, logCallback); |
| } |
| |
| // Accumulate cache stats for a specific cache |
| void accumulateCacheStats(VulkanCacheType cache, const CacheStats &stats) |
| { |
| std::unique_lock<angle::SimpleMutex> localLock(mCacheStatsMutex); |
| mVulkanCacheStats[cache].accumulate(stats); |
| } |
| // Log cache stats for all caches |
| void logCacheStats() const; |
| |
| VkPipelineStageFlags getSupportedBufferWritePipelineStageMask() const |
| { |
| return mSupportedBufferWritePipelineStageMask; |
| } |
| |
| VkPipelineStageFlags getPipelineStageMask(EventStage eventStage) const |
| { |
| return mEventStageToPipelineStageFlagsMap[eventStage]; |
| } |
| |
| const ImageMemoryBarrierData &getImageMemoryBarrierData(ImageLayout layout) const |
| { |
| return mImageLayoutAndMemoryBarrierDataMap[layout]; |
| } |
| |
| VkShaderStageFlags getSupportedVulkanShaderStageMask() const |
| { |
| return mSupportedVulkanShaderStageMask; |
| } |
| |
| angle::Result getFormatDescriptorCountForVkFormat(vk::ErrorContext *context, |
| VkFormat format, |
| uint32_t *descriptorCountOut); |
| |
| angle::Result getFormatDescriptorCountForExternalFormat(vk::ErrorContext *context, |
| uint64_t format, |
| uint32_t *descriptorCountOut); |
| |
| VkDeviceSize getMaxCopyBytesUsingCPUWhenPreservingBufferData() const |
| { |
| return mMaxCopyBytesUsingCPUWhenPreservingBufferData; |
| } |
| |
| const vk::ExtensionNameList &getEnabledInstanceExtensions() const |
| { |
| return mEnabledInstanceExtensions; |
| } |
| |
| const vk::ExtensionNameList &getEnabledDeviceExtensions() const |
| { |
| return mEnabledDeviceExtensions; |
| } |
| |
| VkDeviceSize getPreferedBufferBlockSize(uint32_t memoryTypeIndex) const; |
| |
| size_t getDefaultBufferAlignment() const { return mDefaultBufferAlignment; } |
| |
| uint32_t getStagingBufferMemoryTypeIndex(vk::MemoryCoherency coherency) const |
| { |
| return mStagingBufferMemoryTypeIndex[coherency]; |
| } |
| size_t getStagingBufferAlignment() const { return mStagingBufferAlignment; } |
| |
| uint32_t getVertexConversionBufferMemoryTypeIndex(MemoryHostVisibility hostVisibility) const |
| { |
| return hostVisibility == MemoryHostVisibility::Visible |
| ? mHostVisibleVertexConversionBufferMemoryTypeIndex |
| : mDeviceLocalVertexConversionBufferMemoryTypeIndex; |
| } |
| size_t getVertexConversionBufferAlignment() const { return mVertexConversionBufferAlignment; } |
| |
| uint32_t getDeviceLocalMemoryTypeIndex() const |
| { |
| return mDeviceLocalVertexConversionBufferMemoryTypeIndex; |
| } |
| |
| bool isShadingRateSupported(gl::ShadingRate shadingRate) const |
| { |
| return mSupportedFragmentShadingRates.test(shadingRate); |
| } |
| |
| VkExtent2D getMaxFragmentShadingRateAttachmentTexelSize() const |
| { |
| ASSERT(mFeatures.supportsFoveatedRendering.enabled); |
| return mFragmentShadingRateProperties.maxFragmentShadingRateAttachmentTexelSize; |
| } |
| |
| void addBufferBlockToOrphanList(vk::BufferBlock *block) { mOrphanedBufferBlockList.add(block); } |
| |
| VkDeviceSize getSuballocationDestroyedSize() const |
| { |
| return mSuballocationGarbageList.getDestroyedGarbageSize(); |
| } |
| void onBufferPoolPrune() { mSuballocationGarbageList.resetDestroyedGarbageSize(); } |
| VkDeviceSize getSuballocationGarbageSize() const |
| { |
| return mSuballocationGarbageList.getSubmittedGarbageSize(); |
| } |
| VkDeviceSize getPendingSuballocationGarbageSize() |
| { |
| return mSuballocationGarbageList.getUnsubmittedGarbageSize(); |
| } |
| |
| VkDeviceSize getPendingSubmissionGarbageSize() const |
| { |
| return mSharedGarbageList.getUnsubmittedGarbageSize(); |
| } |
| |
| ANGLE_INLINE VkFilter getPreferredFilterForYUV(VkFilter defaultFilter) |
| { |
| return getFeatures().preferLinearFilterForYUV.enabled ? VK_FILTER_LINEAR : defaultFilter; |
| } |
| |
| angle::Result allocateScopedQueueSerialIndex(vk::ScopedQueueSerialIndex *indexOut); |
| angle::Result allocateQueueSerialIndex(SerialIndex *serialIndexOut); |
| size_t getLargestQueueSerialIndexEverAllocated() const |
| { |
| return mQueueSerialIndexAllocator.getLargestIndexEverAllocated(); |
| } |
| void releaseQueueSerialIndex(SerialIndex index); |
| Serial generateQueueSerial(SerialIndex index); |
| void reserveQueueSerials(SerialIndex index, |
| size_t count, |
| RangedSerialFactory *rangedSerialFactory); |
| |
| // Return true if all serials in ResourceUse have been submitted. |
| bool hasResourceUseSubmitted(const vk::ResourceUse &use) const; |
| bool hasQueueSerialSubmitted(const QueueSerial &queueSerial) const; |
| Serial getLastSubmittedSerial(SerialIndex index) const; |
| // Return true if all serials in ResourceUse have been finished. |
| bool hasResourceUseFinished(const vk::ResourceUse &use) const; |
| bool hasQueueSerialFinished(const QueueSerial &queueSerial) const; |
| |
| // Memory statistics can be updated on allocation and deallocation. |
| template <typename HandleT> |
| void onMemoryAlloc(vk::MemoryAllocationType allocType, |
| VkDeviceSize size, |
| uint32_t memoryTypeIndex, |
| HandleT handle) |
| { |
| mMemoryAllocationTracker.onMemoryAllocImpl(allocType, size, memoryTypeIndex, |
| reinterpret_cast<void *>(handle)); |
| } |
| |
| template <typename HandleT> |
| void onMemoryDealloc(vk::MemoryAllocationType allocType, |
| VkDeviceSize size, |
| uint32_t memoryTypeIndex, |
| HandleT handle) |
| { |
| mMemoryAllocationTracker.onMemoryDeallocImpl(allocType, size, memoryTypeIndex, |
| reinterpret_cast<void *>(handle)); |
| } |
| |
| MemoryAllocationTracker *getMemoryAllocationTracker() { return &mMemoryAllocationTracker; } |
| |
| VkDeviceSize getPendingGarbageSizeLimit() const { return mPendingGarbageSizeLimit; } |
| |
| void requestAsyncCommandsAndGarbageCleanup(vk::ErrorContext *context); |
| |
| VkDeviceSize getMaxMemoryAllocationSize() const |
| { |
| return mMaintenance3Properties.maxMemoryAllocationSize; |
| } |
| |
| // Cleanup garbage and finish command batches from the queue if necessary in the event of an OOM |
| // error. |
| angle::Result cleanupSomeGarbage(ErrorContext *context, bool *anyGarbageCleanedOut); |
| |
| // Static function to get Vulkan object type name. |
| static const char *GetVulkanObjectTypeName(VkObjectType type); |
| |
| bool nullColorAttachmentWithExternalFormatResolve() const |
| { |
| #if defined(ANGLE_PLATFORM_ANDROID) |
| ASSERT(mFeatures.supportsExternalFormatResolve.enabled); |
| return mExternalFormatResolveProperties.nullColorAttachmentWithExternalFormatResolve; |
| #else |
| return false; |
| #endif |
| } |
| |
| vk::ExternalFormatTable *getExternalFormatTable() { return &mExternalFormatTable; } |
| |
| std::ostringstream &getPipelineCacheGraphStream() { return mPipelineCacheGraph; } |
| bool isPipelineCacheGraphDumpEnabled() const { return mDumpPipelineCacheGraph; } |
| const char *getPipelineCacheGraphDumpPath() const |
| { |
| return mPipelineCacheGraphDumpPath.c_str(); |
| } |
| |
| vk::RefCountedEventRecycler *getRefCountedEventRecycler() { return &mRefCountedEventRecycler; } |
| |
| std::thread::id getCleanUpThreadId() const { return mCleanUpThread.getThreadId(); } |
| |
| const vk::DescriptorSetLayoutPtr &getEmptyDescriptorLayout() const |
| { |
| ASSERT(mPlaceHolderDescriptorSetLayout); |
| ASSERT(mPlaceHolderDescriptorSetLayout->valid()); |
| return mPlaceHolderDescriptorSetLayout; |
| } |
| |
| // VK_EXT_device_fault allows gathering more info if the device is lost. |
| VkResult retrieveDeviceLostDetails() const; |
| |
| private: |
| angle::Result setupDevice(vk::ErrorContext *context, |
| const angle::FeatureOverrides &featureOverrides, |
| const char *wsiLayer, |
| UseVulkanSwapchain useVulkanSwapchain, |
| angle::NativeWindowSystem nativeWindowSystem); |
| angle::Result createDeviceAndQueue(vk::ErrorContext *context, uint32_t queueFamilyIndex); |
| void ensureCapsInitialized() const; |
| void initializeValidationMessageSuppressions(); |
| |
| void queryDeviceExtensionFeatures(const vk::ExtensionNameList &deviceExtensionNames); |
| void appendDeviceExtensionFeaturesNotPromoted(const vk::ExtensionNameList &deviceExtensionNames, |
| VkPhysicalDeviceFeatures2KHR *deviceFeatures, |
| VkPhysicalDeviceProperties2 *deviceProperties); |
| void appendDeviceExtensionFeaturesPromotedTo11( |
| const vk::ExtensionNameList &deviceExtensionNames, |
| VkPhysicalDeviceFeatures2KHR *deviceFeatures, |
| VkPhysicalDeviceProperties2 *deviceProperties); |
| void appendDeviceExtensionFeaturesPromotedTo12( |
| const vk::ExtensionNameList &deviceExtensionNames, |
| VkPhysicalDeviceFeatures2KHR *deviceFeatures, |
| VkPhysicalDeviceProperties2 *deviceProperties); |
| void appendDeviceExtensionFeaturesPromotedTo13( |
| const vk::ExtensionNameList &deviceExtensionNames, |
| VkPhysicalDeviceFeatures2KHR *deviceFeatures, |
| VkPhysicalDeviceProperties2 *deviceProperties); |
| |
| angle::Result enableInstanceExtensions(vk::ErrorContext *context, |
| const VulkanLayerVector &enabledInstanceLayerNames, |
| const char *wsiExtension, |
| UseVulkanSwapchain useVulkanSwapchain, |
| bool canLoadDebugUtils); |
| angle::Result enableDeviceExtensions(vk::ErrorContext *context, |
| const angle::FeatureOverrides &featureOverrides, |
| UseVulkanSwapchain useVulkanSwapchain, |
| angle::NativeWindowSystem nativeWindowSystem); |
| |
| void enableDeviceExtensionsNotPromoted(const vk::ExtensionNameList &deviceExtensionNames); |
| void enableDeviceExtensionsPromotedTo11(const vk::ExtensionNameList &deviceExtensionNames); |
| void enableDeviceExtensionsPromotedTo12(const vk::ExtensionNameList &deviceExtensionNames); |
| void enableDeviceExtensionsPromotedTo13(const vk::ExtensionNameList &deviceExtensionNames); |
| |
| void initDeviceExtensionEntryPoints(); |
| // Initialize extension entry points from core ones if needed |
| void initializeInstanceExtensionEntryPointsFromCore() const; |
| void initializeDeviceExtensionEntryPointsFromCore() const; |
| |
| void initFeatures(const vk::ExtensionNameList &extensions, |
| const angle::FeatureOverrides &featureOverrides, |
| UseVulkanSwapchain useVulkanSwapchain, |
| angle::NativeWindowSystem nativeWindowSystem); |
| void appBasedFeatureOverrides(const vk::ExtensionNameList &extensions); |
| // TODO (b/372694741): Remove once run-time control is supported. |
| void appBasedFeatureOverridesAndroidDesktop(const vk::ExtensionNameList &extensions); |
| angle::Result initPipelineCache(vk::ErrorContext *context, |
| vk::PipelineCache *pipelineCache, |
| bool *success); |
| angle::Result ensurePipelineCacheInitialized(vk::ErrorContext *context); |
| |
| template <VkFormatFeatureFlags VkFormatProperties::*features> |
| VkFormatFeatureFlags getFormatFeatureBits(angle::FormatID formatID, |
| const VkFormatFeatureFlags featureBits) const; |
| |
| template <VkFormatFeatureFlags VkFormatProperties::*features> |
| bool hasFormatFeatureBits(angle::FormatID formatID, |
| const VkFormatFeatureFlags featureBits) const; |
| |
| // Initialize VMA allocator and buffer suballocator related data. |
| angle::Result initializeMemoryAllocator(vk::ErrorContext *context); |
| |
| // Query and cache supported fragment shading rates |
| void queryAndCacheFragmentShadingRates(); |
| // Determine support for shading rate based rendering |
| bool canSupportFragmentShadingRate() const; |
| // Determine support for foveated rendering |
| bool canSupportFoveatedRendering() const; |
| // Prefer host visible device local via device local based on device type and heap size. |
| bool canPreferDeviceLocalMemoryHostVisible(VkPhysicalDeviceType deviceType); |
| |
| // Find the threshold for pending suballocation and image garbage sizes before the context |
| // should be flushed. |
| void calculatePendingGarbageSizeLimit(); |
| |
| template <typename CommandBufferHelperT, typename RecyclerT> |
| angle::Result getCommandBufferImpl(vk::ErrorContext *context, |
| vk::SecondaryCommandPool *commandPool, |
| vk::SecondaryCommandMemoryAllocator *commandsAllocator, |
| RecyclerT *recycler, |
| CommandBufferHelperT **commandBufferHelperOut); |
| |
| vk::GlobalOps *mGlobalOps; |
| |
| void *mLibVulkanLibrary; |
| |
| mutable bool mCapsInitialized; |
| mutable gl::Caps mNativeCaps; |
| mutable gl::TextureCapsMap mNativeTextureCaps; |
| mutable gl::Extensions mNativeExtensions; |
| mutable gl::Limitations mNativeLimitations; |
| mutable ShPixelLocalStorageOptions mNativePLSOptions; |
| mutable angle::FeaturesVk mFeatures; |
| |
| // The instance and device versions. The instance version is the one from the Vulkan loader, |
| // while the device version comes from VkPhysicalDeviceProperties::apiVersion. With instance |
| // version 1.0, only device version 1.0 can be used. If instance version is at least 1.1, any |
| // device version (even higher than that) can be used. Some extensions have been promoted to |
| // Vulkan 1.1 or higher, but the version check must be done against the instance or device |
| // version, depending on whether it's an instance or device extension. |
| // |
| // Note that mDeviceVersion is technically redundant with mPhysicalDeviceProperties.apiVersion, |
| // but ANGLE may use a smaller version with problematic ICDs. |
| uint32_t mInstanceVersion; |
| uint32_t mDeviceVersion; |
| |
| VkInstance mInstance; |
| bool mEnableValidationLayers; |
| // True if ANGLE is enabling the VK_EXT_debug_utils extension. |
| bool mEnableDebugUtils; |
| // True if ANGLE should call the vkCmd*DebugUtilsLabelEXT functions in order to communicate |
| // to debuggers (e.g. AGI) the OpenGL ES commands that the application uses. This is |
| // independent of mEnableDebugUtils, as an external graphics debugger can enable the |
| // VK_EXT_debug_utils extension and cause this to be set true. |
| bool mAngleDebuggerMode; |
| angle::vk::ICD mEnabledICD; |
| VkDebugUtilsMessengerEXT mDebugUtilsMessenger; |
| VkPhysicalDevice mPhysicalDevice; |
| |
| VkPhysicalDeviceProperties2 mPhysicalDeviceProperties2; |
| VkPhysicalDeviceProperties &mPhysicalDeviceProperties; |
| |
| VkPhysicalDeviceIDProperties mPhysicalDeviceIDProperties; |
| VkPhysicalDeviceFeatures mPhysicalDeviceFeatures; |
| VkPhysicalDeviceLineRasterizationFeaturesEXT mLineRasterizationFeatures; |
| VkPhysicalDeviceProvokingVertexFeaturesEXT mProvokingVertexFeatures; |
| VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT mVertexAttributeDivisorFeatures; |
| VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT mVertexAttributeDivisorProperties; |
| VkPhysicalDeviceTransformFeedbackFeaturesEXT mTransformFeedbackFeatures; |
| VkPhysicalDeviceIndexTypeUint8FeaturesEXT mIndexTypeUint8Features; |
| VkPhysicalDeviceSubgroupProperties mSubgroupProperties; |
| VkPhysicalDeviceShaderSubgroupExtendedTypesFeaturesKHR mSubgroupExtendedTypesFeatures; |
| VkPhysicalDeviceDeviceMemoryReportFeaturesEXT mMemoryReportFeatures; |
| VkDeviceDeviceMemoryReportCreateInfoEXT mMemoryReportCallback; |
| VkPhysicalDeviceShaderFloat16Int8FeaturesKHR mShaderFloat16Int8Features; |
| VkPhysicalDeviceDepthStencilResolvePropertiesKHR mDepthStencilResolveProperties; |
| VkPhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT |
| mMultisampledRenderToSingleSampledFeatures; |
| VkPhysicalDeviceImage2DViewOf3DFeaturesEXT mImage2dViewOf3dFeatures; |
| VkPhysicalDeviceMultiviewFeatures mMultiviewFeatures; |
| VkPhysicalDeviceFeatures2KHR mEnabledFeatures; |
| VkPhysicalDeviceMultiviewProperties mMultiviewProperties; |
| VkPhysicalDeviceDriverPropertiesKHR mDriverProperties; |
| VkPhysicalDeviceCustomBorderColorFeaturesEXT mCustomBorderColorFeatures; |
| VkPhysicalDeviceProtectedMemoryFeatures mProtectedMemoryFeatures; |
| VkPhysicalDeviceHostQueryResetFeaturesEXT mHostQueryResetFeatures; |
| VkPhysicalDeviceDepthClampZeroOneFeaturesEXT mDepthClampZeroOneFeatures; |
| VkPhysicalDeviceDepthClipControlFeaturesEXT mDepthClipControlFeatures; |
| VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT mBlendOperationAdvancedFeatures; |
| VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT mPrimitivesGeneratedQueryFeatures; |
| VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT mPrimitiveTopologyListRestartFeatures; |
| VkPhysicalDeviceSamplerYcbcrConversionFeatures mSamplerYcbcrConversionFeatures; |
| VkPhysicalDeviceExtendedDynamicStateFeaturesEXT mExtendedDynamicStateFeatures; |
| VkPhysicalDeviceExtendedDynamicState2FeaturesEXT mExtendedDynamicState2Features; |
| VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT mGraphicsPipelineLibraryFeatures; |
| VkPhysicalDeviceGraphicsPipelineLibraryPropertiesEXT mGraphicsPipelineLibraryProperties; |
| VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT mVertexInputDynamicStateFeatures; |
| VkPhysicalDeviceDynamicRenderingFeaturesKHR mDynamicRenderingFeatures; |
| VkPhysicalDeviceDynamicRenderingLocalReadFeaturesKHR mDynamicRenderingLocalReadFeatures; |
| VkPhysicalDeviceFragmentShadingRateFeaturesKHR mFragmentShadingRateFeatures; |
| VkPhysicalDeviceFragmentShadingRatePropertiesKHR mFragmentShadingRateProperties; |
| VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT mFragmentShaderInterlockFeatures; |
| VkPhysicalDeviceImagelessFramebufferFeaturesKHR mImagelessFramebufferFeatures; |
| VkPhysicalDevicePipelineRobustnessFeaturesEXT mPipelineRobustnessFeatures; |
| VkPhysicalDevicePipelineProtectedAccessFeaturesEXT mPipelineProtectedAccessFeatures; |
| VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT |
| mRasterizationOrderAttachmentAccessFeatures; |
| VkPhysicalDeviceShaderAtomicFloatFeaturesEXT mShaderAtomicFloatFeatures; |
| VkPhysicalDeviceMaintenance5FeaturesKHR mMaintenance5Features; |
| VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT mSwapchainMaintenance1Features; |
| VkPhysicalDeviceLegacyDitheringFeaturesEXT mDitheringFeatures; |
| VkPhysicalDeviceDrmPropertiesEXT mDrmProperties; |
| VkPhysicalDeviceTimelineSemaphoreFeaturesKHR mTimelineSemaphoreFeatures; |
| VkPhysicalDeviceHostImageCopyFeaturesEXT mHostImageCopyFeatures; |
| VkPhysicalDeviceHostImageCopyPropertiesEXT mHostImageCopyProperties; |
| VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT mTextureCompressionASTCHDRFeatures; |
| std::vector<VkImageLayout> mHostImageCopySrcLayoutsStorage; |
| std::vector<VkImageLayout> mHostImageCopyDstLayoutsStorage; |
| VkPhysicalDeviceImageCompressionControlFeaturesEXT mImageCompressionControlFeatures; |
| VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT |
| mImageCompressionControlSwapchainFeatures; |
| #if defined(ANGLE_PLATFORM_ANDROID) |
| VkPhysicalDeviceExternalFormatResolveFeaturesANDROID mExternalFormatResolveFeatures; |
| VkPhysicalDeviceExternalFormatResolvePropertiesANDROID mExternalFormatResolveProperties; |
| #endif |
| VkPhysicalDevice8BitStorageFeatures m8BitStorageFeatures; |
| VkPhysicalDevice16BitStorageFeatures m16BitStorageFeatures; |
| VkPhysicalDeviceSynchronization2Features mSynchronization2Features; |
| VkPhysicalDeviceVariablePointersFeatures mVariablePointersFeatures; |
| VkPhysicalDeviceFloatControlsProperties mFloatControlProperties; |
| VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR mUniformBufferStandardLayoutFeatures; |
| VkPhysicalDeviceMaintenance3Properties mMaintenance3Properties; |
| VkPhysicalDeviceFaultFeaturesEXT mFaultFeatures; |
| |
| uint32_t mLegacyDitheringVersion = 0; |
| |
| angle::PackedEnumBitSet<gl::ShadingRate, uint8_t> mSupportedFragmentShadingRates; |
| angle::PackedEnumMap<gl::ShadingRate, VkSampleCountFlags> |
| mSupportedFragmentShadingRateSampleCounts; |
| std::vector<VkQueueFamilyProperties> mQueueFamilyProperties; |
| uint32_t mCurrentQueueFamilyIndex; |
| uint32_t mMaxVertexAttribDivisor; |
| VkDeviceSize mMaxVertexAttribStride; |
| mutable uint32_t mMaxColorInputAttachmentCount; |
| uint32_t mDefaultUniformBufferSize; |
| VkDevice mDevice; |
| VkDeviceSize mMaxCopyBytesUsingCPUWhenPreservingBufferData; |
| |
| bool mDeviceLost; |
| |
| vk::SharedGarbageList<vk::SharedGarbage> mSharedGarbageList; |
| // Suballocations have its own dedicated garbage list for performance optimization since they |
| // tend to be the most common garbage objects. |
| vk::SharedGarbageList<vk::BufferSuballocationGarbage> mSuballocationGarbageList; |
| // Holds orphaned BufferBlocks when ShareGroup gets destroyed |
| vk::BufferBlockGarbageList mOrphanedBufferBlockList; |
| // Holds RefCountedEvent that are free and ready to reuse |
| vk::RefCountedEventRecycler mRefCountedEventRecycler; |
| |
| VkDeviceSize mPendingGarbageSizeLimit; |
| |
| vk::FormatTable mFormatTable; |
| // A cache of VkFormatProperties as queried from the device over time. |
| mutable angle::FormatMap<VkFormatProperties> mFormatProperties; |
| |
| vk::Allocator mAllocator; |
| |
| // Used to allocate memory for images using VMA, utilizing suballocation. |
| vk::ImageMemorySuballocator mImageMemorySuballocator; |
| |
| vk::MemoryProperties mMemoryProperties; |
| VkDeviceSize mPreferredLargeHeapBlockSize; |
| |
| // The default alignment for BufferVk object |
| size_t mDefaultBufferAlignment; |
| // The memory type index for staging buffer that is host visible. |
| angle::PackedEnumMap<vk::MemoryCoherency, uint32_t> mStagingBufferMemoryTypeIndex; |
| size_t mStagingBufferAlignment; |
| // For vertex conversion buffers |
| uint32_t mHostVisibleVertexConversionBufferMemoryTypeIndex; |
| uint32_t mDeviceLocalVertexConversionBufferMemoryTypeIndex; |
| size_t mVertexConversionBufferAlignment; |
| |
| // The mutex protects - |
| // 1. initialization of the cache |
| // 2. Vulkan driver guarantess synchronization for read and write operations but the spec |
| // requires external synchronization when mPipelineCache is the dstCache of |
| // vkMergePipelineCaches. Lock the mutex if mergeProgramPipelineCachesToGlobalCache is |
| // enabled |
| angle::SimpleMutex mPipelineCacheMutex; |
| vk::PipelineCache mPipelineCache; |
| size_t mCurrentPipelineCacheBlobCacheSlotIndex; |
| size_t mPipelineCacheChunkCount; |
| uint32_t mPipelineCacheVkUpdateTimeout; |
| size_t mPipelineCacheSizeAtLastSync; |
| std::atomic<bool> mPipelineCacheInitialized; |
| |
| // Latest validation data for debug overlay. |
| std::string mLastValidationMessage; |
| uint32_t mValidationMessageCount; |
| |
| // Skipped validation messages. The exact contents of the list depends on the availability |
| // of certain extensions. |
| std::vector<const char *> mSkippedValidationMessages; |
| // Syncval skipped messages. The exact contents of the list depends on the availability of |
| // certain extensions. |
| std::vector<vk::SkippedSyncvalMessage> mSkippedSyncvalMessages; |
| |
| // Whether framebuffer fetch is internally coherent. If framebuffer fetch is not coherent, |
| // technically ANGLE could simply not expose EXT_shader_framebuffer_fetch and instead only |
| // expose EXT_shader_framebuffer_fetch_non_coherent. In practice, too many Android apps assume |
| // EXT_shader_framebuffer_fetch is available and break without it. Others use string matching |
| // to detect when EXT_shader_framebuffer_fetch is available, and accidentally match |
| // EXT_shader_framebuffer_fetch_non_coherent and believe coherent framebuffer fetch is |
| // available. |
| // |
| // For these reasons, ANGLE always exposes EXT_shader_framebuffer_fetch. To ensure coherence |
| // between draw calls, it automatically inserts barriers between draw calls when the program |
| // uses framebuffer fetch. ANGLE does not attempt to guarantee coherence for self-overlapping |
| // geometry, which makes this emulation incorrect per spec, but practically harmless. |
| // |
| // This emulation can also be used to implement coherent advanced blend similarly if needed. |
| bool mIsColorFramebufferFetchCoherent; |
| // Whether framebuffer fetch has been used, for the purposes of more accurate syncval error |
| // filtering. |
| bool mIsColorFramebufferFetchUsed; |
| |
| // How close to VkPhysicalDeviceLimits::maxMemoryAllocationCount we allow ourselves to get |
| static constexpr double kPercentMaxMemoryAllocationCount = 0.3; |
| // How many objects to garbage collect before issuing a flush() |
| uint32_t mGarbageCollectionFlushThreshold; |
| |
| // Only used for "one off" command buffers. |
| angle::PackedEnumMap<vk::ProtectionType, OneOffCommandPool> mOneOffCommandPoolMap; |
| |
| // Command queue |
| vk::CommandQueue mCommandQueue; |
| |
| // Async cleanup thread |
| vk::CleanUpThread mCleanUpThread; |
| |
| // Command buffer pool management. |
| vk::CommandBufferRecycler<vk::OutsideRenderPassCommandBufferHelper> |
| mOutsideRenderPassCommandBufferRecycler; |
| vk::CommandBufferRecycler<vk::RenderPassCommandBufferHelper> mRenderPassCommandBufferRecycler; |
| |
| SamplerCache mSamplerCache; |
| SamplerYcbcrConversionCache mYuvConversionCache; |
| angle::HashMap<VkFormat, uint32_t> mVkFormatDescriptorCountMap; |
| vk::ActiveHandleCounter mActiveHandleCounts; |
| angle::SimpleMutex mActiveHandleCountsMutex; |
| |
| // Tracks resource serials. |
| vk::ResourceSerialFactory mResourceSerialFactory; |
| |
| // QueueSerial generator |
| vk::QueueSerialIndexAllocator mQueueSerialIndexAllocator; |
| std::array<AtomicSerialFactory, kMaxQueueSerialIndexCount> mQueueSerialFactory; |
| |
| // Application executable information |
| VkApplicationInfo mApplicationInfo; |
| // Process GPU memory reports |
| vk::MemoryReport mMemoryReport; |
| // Helpers for adding trace annotations |
| DebugAnnotatorVk mAnnotator; |
| |
| // Stats about all Vulkan object caches |
| VulkanCacheStats mVulkanCacheStats; |
| mutable angle::SimpleMutex mCacheStatsMutex; |
| |
| // A mask to filter out Vulkan pipeline stages that are not supported, applied in situations |
| // where multiple stages are prespecified (for example with image layout transitions): |
| // |
| // - Excludes GEOMETRY if geometry shaders are not supported. |
| // - Excludes TESSELLATION_CONTROL and TESSELLATION_EVALUATION if tessellation shaders are |
| // not |
| // supported. |
| // |
| // Note that this mask can have bits set that don't correspond to valid stages, so it's |
| // strictly only useful for masking out unsupported stages in an otherwise valid set of |
| // stages. |
| VkPipelineStageFlags mSupportedBufferWritePipelineStageMask; |
| VkShaderStageFlags mSupportedVulkanShaderStageMask; |
| // The 1:1 mapping between EventStage and VkPipelineStageFlags |
| EventStageToVkPipelineStageFlagsMap mEventStageToPipelineStageFlagsMap; |
| ImageLayoutToMemoryBarrierDataMap mImageLayoutAndMemoryBarrierDataMap; |
| |
| // Use thread pool to compress cache data. |
| std::shared_ptr<angle::WaitableEvent> mCompressEvent; |
| |
| VulkanLayerVector mEnabledDeviceLayerNames; |
| vk::ExtensionNameList mEnabledInstanceExtensions; |
| vk::ExtensionNameList mEnabledDeviceExtensions; |
| |
| // Memory tracker for allocations and deallocations. |
| MemoryAllocationTracker mMemoryAllocationTracker; |
| |
| vk::ExternalFormatTable mExternalFormatTable; |
| |
| // A graph built from pipeline descs and their transitions. This is not thread-safe, but it's |
| // only a debug feature that's disabled by default. |
| std::ostringstream mPipelineCacheGraph; |
| bool mDumpPipelineCacheGraph; |
| std::string mPipelineCacheGraphDumpPath; |
| |
| // A placeholder descriptor set layout handle for layouts with no bindings. |
| vk::DescriptorSetLayoutPtr mPlaceHolderDescriptorSetLayout; |
| |
| // Cached value for the buffer memory size limit. |
| VkDeviceSize mMaxBufferMemorySizeLimit; |
| }; |
| |
| ANGLE_INLINE Serial Renderer::generateQueueSerial(SerialIndex index) |
| { |
| return mQueueSerialFactory[index].generate(); |
| } |
| |
| ANGLE_INLINE void Renderer::reserveQueueSerials(SerialIndex index, |
| size_t count, |
| RangedSerialFactory *rangedSerialFactory) |
| { |
| mQueueSerialFactory[index].reserve(rangedSerialFactory, count); |
| } |
| |
| ANGLE_INLINE bool Renderer::hasResourceUseSubmitted(const vk::ResourceUse &use) const |
| { |
| return mCommandQueue.hasResourceUseSubmitted(use); |
| } |
| |
| ANGLE_INLINE bool Renderer::hasQueueSerialSubmitted(const QueueSerial &queueSerial) const |
| { |
| return mCommandQueue.hasQueueSerialSubmitted(queueSerial); |
| } |
| |
| ANGLE_INLINE Serial Renderer::getLastSubmittedSerial(SerialIndex index) const |
| { |
| return mCommandQueue.getLastSubmittedSerial(index); |
| } |
| |
| ANGLE_INLINE bool Renderer::hasResourceUseFinished(const vk::ResourceUse &use) const |
| { |
| return mCommandQueue.hasResourceUseFinished(use); |
| } |
| |
| ANGLE_INLINE bool Renderer::hasQueueSerialFinished(const QueueSerial &queueSerial) const |
| { |
| return mCommandQueue.hasQueueSerialFinished(queueSerial); |
| } |
| |
| ANGLE_INLINE void Renderer::requestAsyncCommandsAndGarbageCleanup(vk::ErrorContext *context) |
| { |
| mCleanUpThread.requestCleanUp(); |
| } |
| |
| ANGLE_INLINE angle::Result Renderer::checkCompletedCommands(vk::ErrorContext *context) |
| { |
| return mCommandQueue.checkCompletedCommands(context); |
| } |
| |
| ANGLE_INLINE angle::Result Renderer::checkCompletedCommandsAndCleanup(vk::ErrorContext *context) |
| { |
| return mCommandQueue.checkAndCleanupCompletedCommands(context); |
| } |
| |
| ANGLE_INLINE angle::Result Renderer::releaseFinishedCommands(vk::ErrorContext *context) |
| { |
| return mCommandQueue.releaseFinishedCommands(context); |
| } |
| } // namespace vk |
| } // namespace rx |
| |
| #endif // LIBANGLE_RENDERER_VULKAN_RENDERERVK_H_ |