Hash :
5e6be1d6
Author :
Date :
2019-10-11T11:29:22
Provoking vertex feature support enabled Added support in ANGLE for the provoking vertex feature, which allows to choose the provoking vertex convention (first or last) for flat shading. Just copying the vk_ext_provoking_vertex.h file into ANGLE src tree for now. When the extension lands in the vulkan header we'll migrate to that and remove this file from ANGLE. With this, all these tests pass with SwANGLE: dEQP-GLES3.functional.fragment_out.* (fixes 526 failures) dEQP-GLES3.functional.rasterization.flatshading.* (fixes 6 failures) dEQP-GLES3.functional.shaders.linkage.varying.* (already passing before, still passing) Bug: angleproject:3430 Bug: angleproject:3677 Bug: angleproject:4063 Change-Id: Icc361f567072c12472398e37a94a61d7f95007ad Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1855681 Commit-Queue: Alexis Hétu <sugoi@chromium.org> Reviewed-by: Alexis Hétu <sugoi@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
//
// 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.
//
// RendererVk.h:
// Defines the class interface for RendererVk.
//
#ifndef LIBANGLE_RENDERER_VULKAN_RENDERERVK_H_
#define LIBANGLE_RENDERER_VULKAN_RENDERERVK_H_
#include <vulkan/vulkan.h>
#include <memory>
#include <mutex>
#include "vk_ext_provoking_vertex.h"
#include "common/PoolAlloc.h"
#include "common/angleutils.h"
#include "libANGLE/BlobCache.h"
#include "libANGLE/Caps.h"
#include "libANGLE/renderer/vulkan/CommandGraph.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"
namespace egl
{
class Display;
class BlobCache;
} // namespace egl
namespace rx
{
class DisplayVk;
class FramebufferVk;
namespace vk
{
struct Format;
} // namespace vk
// Supports one semaphore from current surface, and one semaphore passed to
// glSignalSemaphoreEXT.
using SignalSemaphoreVector = angle::FixedVector<VkSemaphore, 2>;
inline void CollectGarbage(std::vector<vk::GarbageObject> *garbageOut) {}
template <typename ArgT, typename... ArgsT>
void CollectGarbage(std::vector<vk::GarbageObject> *garbageOut, ArgT object, ArgsT... objectsIn)
{
if (object->valid())
{
garbageOut->emplace_back(vk::GarbageObject::Get(object));
}
CollectGarbage(garbageOut, objectsIn...);
}
class RendererVk : angle::NonCopyable
{
public:
RendererVk();
~RendererVk();
angle::Result initialize(DisplayVk *displayVk,
egl::Display *display,
const char *wsiExtension,
const char *wsiLayer);
void onDestroy(vk::Context *context);
void notifyDeviceLost();
bool isDeviceLost() const;
std::string getVendorString() const;
std::string getRendererDescription() const;
gl::Version getMaxSupportedESVersion() const;
gl::Version getMaxConformantESVersion() const;
VkInstance getInstance() const { return mInstance; }
VkPhysicalDevice getPhysicalDevice() const { return mPhysicalDevice; }
const VkPhysicalDeviceProperties &getPhysicalDeviceProperties() const
{
return mPhysicalDeviceProperties;
}
const VkPhysicalDeviceSubgroupProperties &getPhysicalDeviceSubgroupProperties() const
{
return mPhysicalDeviceSubgroupProperties;
}
const VkPhysicalDeviceFeatures &getPhysicalDeviceFeatures() const
{
return mPhysicalDeviceFeatures;
}
VkDevice getDevice() const { return mDevice; }
angle::Result selectPresentQueueForSurface(DisplayVk *displayVk,
VkSurfaceKHR surface,
uint32_t *presentQueueOut);
const gl::Caps &getNativeCaps() const;
const gl::TextureCapsMap &getNativeTextureCaps() const;
const gl::Extensions &getNativeExtensions() const;
const gl::Limitations &getNativeLimitations() const;
uint32_t getQueueFamilyIndex() const { return mCurrentQueueFamilyIndex; }
const vk::MemoryProperties &getMemoryProperties() const { return mMemoryProperties; }
// TODO(jmadill): We could pass angle::FormatID here.
const vk::Format &getFormat(GLenum internalFormat) const
{
return mFormatTable[internalFormat];
}
const vk::Format &getFormat(angle::FormatID formatID) const { return mFormatTable[formatID]; }
// Queries the descriptor set layout cache. Creates the layout if not present.
angle::Result getDescriptorSetLayout(
vk::Context *context,
const vk::DescriptorSetLayoutDesc &desc,
vk::BindingPointer<vk::DescriptorSetLayout> *descriptorSetLayoutOut);
// Queries the pipeline layout cache. Creates the layout if not present.
angle::Result getPipelineLayout(vk::Context *context,
const vk::PipelineLayoutDesc &desc,
const vk::DescriptorSetLayoutPointerArray &descriptorSetLayouts,
vk::BindingPointer<vk::PipelineLayout> *pipelineLayoutOut);
angle::Result getPipelineCacheSize(DisplayVk *displayVk, size_t *pipelineCacheSizeOut);
angle::Result syncPipelineCacheVk(DisplayVk *displayVk);
// Issues a new serial for linked shader modules. Used in the pipeline cache.
Serial issueShaderSerial();
const angle::FeaturesVk &getFeatures() const
{
ASSERT(mFeaturesInitialized);
return mFeatures;
}
uint32_t getMaxVertexAttribDivisor() const { return mMaxVertexAttribDivisor; }
bool isMockICDEnabled() const { return mEnabledICD == 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(VkFormat format, const VkFormatFeatureFlags featureBits);
VkFormatFeatureFlags getImageFormatFeatureBits(VkFormat format,
const VkFormatFeatureFlags featureBits);
bool hasImageFormatFeatureBits(VkFormat format, const VkFormatFeatureFlags featureBits);
bool hasBufferFormatFeatureBits(VkFormat format, const VkFormatFeatureFlags featureBits);
angle::Result queueSubmit(vk::Context *context,
const VkSubmitInfo &submitInfo,
const vk::Fence &fence,
Serial *serialOut);
angle::Result queueWaitIdle(vk::Context *context);
VkResult queuePresent(const VkPresentInfoKHR &presentInfo);
angle::Result newSharedFence(vk::Context *context, vk::Shared<vk::Fence> *sharedFenceOut);
inline void resetSharedFence(vk::Shared<vk::Fence> *sharedFenceIn)
{
sharedFenceIn->resetAndRecycle(&mFenceRecycler);
}
template <typename... ArgsT>
void collectGarbageAndReinit(vk::SharedResourceUse *use, ArgsT... garbageIn)
{
std::vector<vk::GarbageObject> sharedGarbage;
CollectGarbage(&sharedGarbage, garbageIn...);
if (!sharedGarbage.empty())
{
collectGarbage(std::move(*use), std::move(sharedGarbage));
}
else
{
// Force releasing "use" even if no garbage was created.
use->release();
}
// Keep "use" valid.
use->init();
}
void collectGarbage(vk::SharedResourceUse &&use, std::vector<vk::GarbageObject> &&sharedGarbage)
{
mSharedGarbage.emplace_back(std::move(use), std::move(sharedGarbage));
}
static constexpr size_t kMaxExtensionNames = 200;
using ExtensionNameList = angle::FixedVector<const char *, kMaxExtensionNames>;
angle::Result getPipelineCache(vk::PipelineCache **pipelineCache);
void onNewGraphicsPipeline() { mPipelineCacheDirty = true; }
void onNewValidationMessage(const std::string &message);
std::string getAndClearLastValidationMessage(uint32_t *countSinceLastClear);
uint64_t getMaxFenceWaitTimeNs() const;
Serial getCurrentQueueSerial() const { return mCurrentQueueSerial; }
Serial getLastSubmittedQueueSerial() const { return mLastSubmittedQueueSerial; }
Serial getLastCompletedQueueSerial() const { return mLastCompletedQueueSerial; }
void onCompletedSerial(Serial serial);
bool shouldCleanupGarbage()
{
return (mSharedGarbage.size() > mGarbageCollectionFlushThreshold);
}
private:
angle::Result initializeDevice(DisplayVk *displayVk, uint32_t queueFamilyIndex);
void ensureCapsInitialized() const;
void initFeatures(const ExtensionNameList &extensions);
void initPipelineCacheVkKey();
angle::Result initPipelineCache(DisplayVk *display,
vk::PipelineCache *pipelineCache,
bool *success);
template <VkFormatFeatureFlags VkFormatProperties::*features>
VkFormatFeatureFlags getFormatFeatureBits(VkFormat format,
const VkFormatFeatureFlags featureBits);
template <VkFormatFeatureFlags VkFormatProperties::*features>
bool hasFormatFeatureBits(VkFormat format, const VkFormatFeatureFlags featureBits);
angle::Result cleanupGarbage(vk::Context *context, bool block);
egl::Display *mDisplay;
mutable bool mCapsInitialized;
mutable gl::Caps mNativeCaps;
mutable gl::TextureCapsMap mNativeTextureCaps;
mutable gl::Extensions mNativeExtensions;
mutable gl::Limitations mNativeLimitations;
mutable bool mFeaturesInitialized;
mutable angle::FeaturesVk mFeatures;
VkInstance mInstance;
bool mEnableValidationLayers;
vk::ICD mEnabledICD;
VkDebugUtilsMessengerEXT mDebugUtilsMessenger;
VkDebugReportCallbackEXT mDebugReportCallback;
VkPhysicalDevice mPhysicalDevice;
VkPhysicalDeviceProperties mPhysicalDeviceProperties;
VkPhysicalDeviceSubgroupProperties mPhysicalDeviceSubgroupProperties;
VkPhysicalDeviceFeatures mPhysicalDeviceFeatures;
VkPhysicalDeviceLineRasterizationFeaturesEXT mLineRasterizationFeatures;
VkPhysicalDeviceProvokingVertexFeaturesEXT mProvokingVertexFeatures;
std::vector<VkQueueFamilyProperties> mQueueFamilyProperties;
std::mutex mQueueMutex;
VkQueue mQueue;
uint32_t mCurrentQueueFamilyIndex;
uint32_t mMaxVertexAttribDivisor;
VkDevice mDevice;
AtomicSerialFactory mQueueSerialFactory;
AtomicSerialFactory mShaderSerialFactory;
Serial mLastCompletedQueueSerial;
Serial mLastSubmittedQueueSerial;
Serial mCurrentQueueSerial;
bool mDeviceLost;
vk::Recycler<vk::Fence> mFenceRecycler;
std::mutex mGarbageMutex;
vk::SharedGarbageList mSharedGarbage;
vk::MemoryProperties mMemoryProperties;
vk::FormatTable mFormatTable;
// All access to the pipeline cache is done through EGL objects so it is thread safe to not use
// a lock.
vk::PipelineCache mPipelineCache;
egl::BlobCache::Key mPipelineCacheVkBlobKey;
uint32_t mPipelineCacheVkUpdateTimeout;
bool mPipelineCacheDirty;
bool mPipelineCacheInitialized;
// A cache of VkFormatProperties as queried from the device over time.
std::array<VkFormatProperties, vk::kNumVkFormats> mFormatProperties;
// ANGLE uses a PipelineLayout cache to store compatible pipeline layouts.
std::mutex mPipelineLayoutCacheMutex;
PipelineLayoutCache mPipelineLayoutCache;
// DescriptorSetLayouts are also managed in a cache.
std::mutex mDescriptorSetLayoutCacheMutex;
DescriptorSetLayoutCache mDescriptorSetLayoutCache;
// Latest validation data for debug overlay.
std::string mLastValidationMessage;
uint32_t mValidationMessageCount;
// 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;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_RENDERERVK_H_