Hash :
5bca4fed
Author :
Date :
2019-01-09T17:07:06
Vulkan: Switch to EXT_debug_utils EXT_debug_utils is a (relatively) new extension that subsumes EXT_debug_report and EXT_debug_marker extensions. This change uses EXT_debut_utils (if available) to receive debug messages, keeping EXT_debug_report as fallback. Bug: angleproject:2798 Change-Id: Ia6767604548704e18f8150a54d2533c0b1197841 Reviewed-on: https://chromium-review.googlesource.com/c/1403955 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Yuly Novikov <ynovikov@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 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
//
// 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 "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;
}
class RendererVk : angle::NonCopyable
{
public:
RendererVk();
~RendererVk();
angle::Result initialize(DisplayVk *displayVk, egl::Display *display, const char *wsiName);
void onDestroy(vk::Context *context);
void notifyDeviceLost();
bool isDeviceLost() const;
std::string getVendorString() const;
std::string getRendererDescription() const;
gl::Version getMaxSupportedESVersion() const;
VkInstance getInstance() const { return mInstance; }
VkPhysicalDevice getPhysicalDevice() const { return mPhysicalDevice; }
const VkPhysicalDeviceProperties &getPhysicalDeviceProperties() const
{
return mPhysicalDeviceProperties;
}
const VkPhysicalDeviceFeatures &getPhysicalDeviceFeatures() const
{
return mPhysicalDeviceFeatures;
}
VkQueue getQueue() const { return mQueue; }
VkDevice getDevice() const { return mDevice; }
angle::Result selectPresentQueueForSurface(DisplayVk *displayVk,
VkSurfaceKHR surface,
uint32_t *presentQueueOut);
angle::Result finish(vk::Context *context);
angle::Result flush(vk::Context *context);
const vk::CommandPool &getCommandPool() const;
const gl::Caps &getNativeCaps() const;
const gl::TextureCapsMap &getNativeTextureCaps() const;
const gl::Extensions &getNativeExtensions() const;
const gl::Limitations &getNativeLimitations() const;
uint32_t getMaxActiveTextures();
Serial getCurrentQueueSerial() const { return mCurrentQueueSerial; }
Serial getLastSubmittedQueueSerial() const { return mLastSubmittedQueueSerial; }
Serial getLastCompletedQueueSerial() const { return mLastCompletedQueueSerial; }
bool isSerialInUse(Serial serial) const;
template <typename T>
void releaseObject(Serial resourceSerial, T *object)
{
if (!isSerialInUse(resourceSerial))
{
object->destroy(mDevice);
}
else
{
object->dumpResources(resourceSerial, &mGarbage);
}
}
// Check to see which batches have finished completion (forward progress for
// mLastCompletedQueueSerial, for example for when the application busy waits on a query
// result).
angle::Result checkCompletedCommands(vk::Context *context);
// Wait for completion of batches until (at least) batch with given serial is finished.
angle::Result finishToSerial(vk::Context *context, Serial serial);
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]; }
angle::Result getCompatibleRenderPass(vk::Context *context,
const vk::RenderPassDesc &desc,
vk::RenderPass **renderPassOut);
angle::Result getRenderPassWithOps(vk::Context *context,
const vk::RenderPassDesc &desc,
const vk::AttachmentOpsArray &ops,
vk::RenderPass **renderPassOut);
// 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 syncPipelineCacheVk(DisplayVk *displayVk);
vk::DynamicSemaphorePool *getDynamicSemaphorePool() { return &mSubmitSemaphorePool; }
// Request a semaphore, that is expected to be signaled externally. The next submission will
// wait on it.
angle::Result allocateSubmitWaitSemaphore(vk::Context *context,
const vk::Semaphore **outSemaphore);
// Get the last signaled semaphore to wait on externally. The semaphore will not be waited on
// by next submission.
const vk::Semaphore *getSubmitLastSignaledSemaphore(vk::Context *context);
// This should only be called from ResourceVk.
// TODO(jmadill): Keep in ContextVk to enable threaded rendering.
vk::CommandGraph *getCommandGraph();
// Issues a new serial for linked shader modules. Used in the pipeline cache.
Serial issueShaderSerial();
vk::ShaderLibrary &getShaderLibrary() { return mShaderLibrary; }
UtilsVk &getUtils() { return mUtils; }
const angle::FeaturesVk &getFeatures() const
{
ASSERT(mFeaturesInitialized);
return mFeatures;
}
angle::Result getTimestamp(vk::Context *context, uint64_t *timestampOut);
// Create Begin/End/Instant GPU trace events, which take their timestamps from GPU queries.
// The events are queued until the query results are available. Possible values for `phase`
// are TRACE_EVENT_PHASE_*
ANGLE_INLINE angle::Result traceGpuEvent(vk::Context *context,
vk::CommandBuffer *commandBuffer,
char phase,
const char *name)
{
if (mGpuEventsEnabled)
return traceGpuEventImpl(context, commandBuffer, phase, name);
return angle::Result::Continue;
}
bool isMockICDEnabled() const { return mEnableMockICD; }
RenderPassCache &getRenderPassCache() { return mRenderPassCache; }
const vk::PipelineCache &getPipelineCache() const { return mPipelineCache; }
// 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 hasLinearTextureFormatFeatureBits(VkFormat format, const VkFormatFeatureFlags featureBits);
bool hasTextureFormatFeatureBits(VkFormat format, const VkFormatFeatureFlags featureBits);
bool hasBufferFormatFeatureBits(VkFormat format, const VkFormatFeatureFlags featureBits);
private:
// Number of semaphores for external entities to renderer to issue a wait, such as surface's
// image acquire.
static constexpr size_t kMaxExternalSemaphores = 64;
// Total possible number of semaphores a submission can wait on. +1 is for the semaphore
// signaled in the last submission.
static constexpr size_t kMaxWaitSemaphores = kMaxExternalSemaphores + 1;
angle::Result initializeDevice(DisplayVk *displayVk, uint32_t queueFamilyIndex);
void ensureCapsInitialized() const;
void getSubmitWaitSemaphores(
vk::Context *context,
angle::FixedVector<VkSemaphore, kMaxWaitSemaphores> *waitSemaphores,
angle::FixedVector<VkPipelineStageFlags, kMaxWaitSemaphores> *waitStageMasks);
angle::Result submitFrame(vk::Context *context,
const VkSubmitInfo &submitInfo,
vk::CommandBuffer &&commandBuffer);
void freeAllInFlightResources();
angle::Result flushCommandGraph(vk::Context *context, vk::CommandBuffer *commandBatch);
void initFeatures(const std::vector<VkExtensionProperties> &deviceExtensionProps);
void initPipelineCacheVkKey();
angle::Result initPipelineCache(DisplayVk *display);
angle::Result synchronizeCpuGpuTime(vk::Context *context);
angle::Result traceGpuEventImpl(vk::Context *context,
vk::CommandBuffer *commandBuffer,
char phase,
const char *name);
angle::Result checkCompletedGpuEvents(vk::Context *context);
void flushGpuEvents(double nextSyncGpuTimestampS, double nextSyncCpuTimestampS);
template <VkFormatFeatureFlags VkFormatProperties::*features>
bool hasFormatFeatureBits(VkFormat format, const VkFormatFeatureFlags featureBits);
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;
bool mEnableMockICD;
VkDebugUtilsMessengerEXT mDebugUtilsMessenger;
VkDebugReportCallbackEXT mDebugReportCallback;
VkPhysicalDevice mPhysicalDevice;
VkPhysicalDeviceProperties mPhysicalDeviceProperties;
VkPhysicalDeviceFeatures mPhysicalDeviceFeatures;
std::vector<VkQueueFamilyProperties> mQueueFamilyProperties;
VkQueue mQueue;
uint32_t mCurrentQueueFamilyIndex;
VkDevice mDevice;
vk::CommandPool mCommandPool;
SerialFactory mQueueSerialFactory;
SerialFactory mShaderSerialFactory;
Serial mLastCompletedQueueSerial;
Serial mLastSubmittedQueueSerial;
Serial mCurrentQueueSerial;
bool mDeviceLost;
struct CommandBatch final : angle::NonCopyable
{
CommandBatch();
~CommandBatch();
CommandBatch(CommandBatch &&other);
CommandBatch &operator=(CommandBatch &&other);
void destroy(VkDevice device);
vk::CommandPool commandPool;
vk::Fence fence;
Serial serial;
};
std::vector<CommandBatch> mInFlightCommands;
std::vector<vk::GarbageObject> mGarbage;
vk::MemoryProperties mMemoryProperties;
vk::FormatTable mFormatTable;
RenderPassCache mRenderPassCache;
vk::PipelineCache mPipelineCache;
egl::BlobCache::Key mPipelineCacheVkBlobKey;
uint32_t mPipelineCacheVkUpdateTimeout;
// A cache of VkFormatProperties as queried from the device over time.
std::array<VkFormatProperties, vk::kNumVkFormats> mFormatProperties;
// mSubmitWaitSemaphores is a list of specifically requested semaphores to be waited on before a
// command buffer submission, for example, semaphores signaled by vkAcquireNextImageKHR.
// After first use, the list is automatically cleared. This is a vector to support concurrent
// rendering to multiple surfaces.
//
// Note that with multiple contexts present, this may result in a context waiting on image
// acquisition even if it doesn't render to that surface. If CommandGraphs are separated by
// context or share group for example, this could be moved to the one that actually uses the
// image.
angle::FixedVector<vk::SemaphoreHelper, kMaxExternalSemaphores> mSubmitWaitSemaphores;
// mSubmitLastSignaledSemaphore shows which semaphore was last signaled by submission. This can
// be set to nullptr if retrieved to be waited on outside RendererVk, such
// as by the surface before presentation. Each submission waits on the
// previously signaled semaphore (as well as any in mSubmitWaitSemaphores)
// and allocates a new semaphore to signal.
vk::SemaphoreHelper mSubmitLastSignaledSemaphore;
// A pool of semaphores used to support the aforementioned mid-frame submissions.
vk::DynamicSemaphorePool mSubmitSemaphorePool;
// See CommandGraph.h for a desription of the Command Graph.
vk::CommandGraph mCommandGraph;
// ANGLE uses a PipelineLayout cache to store compatible pipeline layouts.
PipelineLayoutCache mPipelineLayoutCache;
// DescriptorSetLayouts are also managed in a cache.
DescriptorSetLayoutCache mDescriptorSetLayoutCache;
// Internal shader library.
vk::ShaderLibrary mShaderLibrary;
UtilsVk mUtils;
// The GpuEventQuery struct holds together a timestamp query and enough data to create a
// trace event based on that. Use traceGpuEvent to insert such queries. They will be readback
// when the results are available, without inserting a GPU bubble.
//
// - eventName will be the reported name of the event
// - phase is either 'B' (duration begin), 'E' (duration end) or 'i' (instant // event).
// See Google's "Trace Event Format":
// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU
// - serial is the serial of the batch the query was submitted on. Until the batch is
// submitted, the query is not checked to avoid incuring a flush.
struct GpuEventQuery final
{
const char *name;
char phase;
uint32_t queryIndex;
size_t queryPoolIndex;
Serial serial;
};
// Once a query result is available, the timestamp is read and a GpuEvent object is kept until
// the next clock sync, at which point the clock drift is compensated in the results before
// handing them off to the application.
struct GpuEvent final
{
uint64_t gpuTimestampCycles;
const char *name;
char phase;
};
bool mGpuEventsEnabled;
vk::DynamicQueryPool mGpuEventQueryPool;
// A list of queries that have yet to be turned into an event (their result is not yet
// available).
std::vector<GpuEventQuery> mInFlightGpuEventQueries;
// A list of gpu events since the last clock sync.
std::vector<GpuEvent> mGpuEvents;
// Hold information from the last gpu clock sync for future gpu-to-cpu timestamp conversions.
struct GpuClockSyncInfo
{
double gpuTimestampS;
double cpuTimestampS;
};
GpuClockSyncInfo mGpuClockSync;
// The very first timestamp queried for a GPU event is used as origin, so event timestamps would
// have a value close to zero, to avoid losing 12 bits when converting these 64 bit values to
// double.
uint64_t mGpuEventTimestampOrigin;
};
uint32_t GetUniformBufferDescriptorCount();
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_RENDERERVK_H_