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 // ContextVk.h:
7 // Defines the class interface for ContextVk, implementing ContextImpl.
8 //
9
10 #ifndef LIBANGLE_RENDERER_VULKAN_CONTEXTVK_H_
11 #define LIBANGLE_RENDERER_VULKAN_CONTEXTVK_H_
12
13 #include <condition_variable>
14
15 #include "common/PackedEnums.h"
16 #include "common/vulkan/vk_headers.h"
17 #include "libANGLE/renderer/ContextImpl.h"
18 #include "libANGLE/renderer/renderer_utils.h"
19 #include "libANGLE/renderer/vulkan/DisplayVk.h"
20 #include "libANGLE/renderer/vulkan/OverlayVk.h"
21 #include "libANGLE/renderer/vulkan/PersistentCommandPool.h"
22 #include "libANGLE/renderer/vulkan/RendererVk.h"
23 #include "libANGLE/renderer/vulkan/vk_helpers.h"
24
25 namespace angle
26 {
27 struct FeaturesVk;
28 } // namespace angle
29
30 namespace rx
31 {
32 class ProgramExecutableVk;
33 class RendererVk;
34 class WindowSurfaceVk;
35 class ShareGroupVk;
36
37 static constexpr uint32_t kMaxGpuEventNameLen = 32;
38 using EventName = std::array<char, kMaxGpuEventNameLen>;
39
40 // If the total size of copyBufferToImage commands in the outside command buffer reaches the
41 // threshold below, the latter is flushed.
42 static constexpr VkDeviceSize kMaxBufferToImageCopySize = 1 << 28;
43
44 using ContextVkDescriptorSetList = angle::PackedEnumMap<PipelineType, uint32_t>;
45
46 enum class GraphicsEventCmdBuf
47 {
48 NotInQueryCmd = 0,
49 InOutsideCmdBufQueryCmd = 1,
50 InRenderPassCmdBufQueryCmd = 2,
51
52 InvalidEnum = 3,
53 EnumCount = 3,
54 };
55
56 enum class QueueSubmitType
57 {
58 PerformQueueSubmit,
59 SkipQueueSubmit,
60 };
61
62 class UpdateDescriptorSetsBuilder final : angle::NonCopyable
63 {
64 public:
65 UpdateDescriptorSetsBuilder();
66 ~UpdateDescriptorSetsBuilder();
67
68 VkDescriptorBufferInfo *allocDescriptorBufferInfos(size_t count);
69 VkDescriptorImageInfo *allocDescriptorImageInfos(size_t count);
70 VkWriteDescriptorSet *allocWriteDescriptorSets(size_t count);
71
allocDescriptorBufferInfo()72 VkDescriptorBufferInfo &allocDescriptorBufferInfo() { return *allocDescriptorBufferInfos(1); }
allocDescriptorImageInfo()73 VkDescriptorImageInfo &allocDescriptorImageInfo() { return *allocDescriptorImageInfos(1); }
allocWriteDescriptorSet()74 VkWriteDescriptorSet &allocWriteDescriptorSet() { return *allocWriteDescriptorSets(1); }
75
76 // Returns the number of written descriptor sets.
77 uint32_t flushDescriptorSetUpdates(VkDevice device);
78
79 private:
80 template <typename T, const T *VkWriteDescriptorSet::*pInfo>
81 T *allocDescriptorInfos(std::vector<T> *descriptorVector, size_t count);
82 template <typename T, const T *VkWriteDescriptorSet::*pInfo>
83 void growDescriptorCapacity(std::vector<T> *descriptorVector, size_t newSize);
84
85 std::vector<VkDescriptorBufferInfo> mDescriptorBufferInfos;
86 std::vector<VkDescriptorImageInfo> mDescriptorImageInfos;
87 std::vector<VkWriteDescriptorSet> mWriteDescriptorSets;
88 };
89
90 // Why depth/stencil feedback loop is being updated. Based on whether it's due to a draw or clear,
91 // different GL state affect depth/stencil write.
92 enum class UpdateDepthFeedbackLoopReason
93 {
94 None,
95 Draw,
96 Clear,
97 };
98
99 class ContextVk : public ContextImpl, public vk::Context, public MultisampleTextureInitializer
100 {
101 public:
102 ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk *renderer);
103 ~ContextVk() override;
104
105 angle::Result initialize() override;
106
107 void onDestroy(const gl::Context *context) override;
108
109 // Flush and finish.
110 angle::Result flush(const gl::Context *context) override;
111 angle::Result finish(const gl::Context *context) override;
112
113 // Drawing methods.
114 angle::Result drawArrays(const gl::Context *context,
115 gl::PrimitiveMode mode,
116 GLint first,
117 GLsizei count) override;
118 angle::Result drawArraysInstanced(const gl::Context *context,
119 gl::PrimitiveMode mode,
120 GLint first,
121 GLsizei count,
122 GLsizei instanceCount) override;
123 angle::Result drawArraysInstancedBaseInstance(const gl::Context *context,
124 gl::PrimitiveMode mode,
125 GLint first,
126 GLsizei count,
127 GLsizei instanceCount,
128 GLuint baseInstance) override;
129
130 angle::Result drawElements(const gl::Context *context,
131 gl::PrimitiveMode mode,
132 GLsizei count,
133 gl::DrawElementsType type,
134 const void *indices) override;
135 angle::Result drawElementsBaseVertex(const gl::Context *context,
136 gl::PrimitiveMode mode,
137 GLsizei count,
138 gl::DrawElementsType type,
139 const void *indices,
140 GLint baseVertex) override;
141 angle::Result drawElementsInstanced(const gl::Context *context,
142 gl::PrimitiveMode mode,
143 GLsizei count,
144 gl::DrawElementsType type,
145 const void *indices,
146 GLsizei instanceCount) override;
147 angle::Result drawElementsInstancedBaseVertex(const gl::Context *context,
148 gl::PrimitiveMode mode,
149 GLsizei count,
150 gl::DrawElementsType type,
151 const void *indices,
152 GLsizei instanceCount,
153 GLint baseVertex) override;
154 angle::Result drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
155 gl::PrimitiveMode mode,
156 GLsizei count,
157 gl::DrawElementsType type,
158 const void *indices,
159 GLsizei instances,
160 GLint baseVertex,
161 GLuint baseInstance) override;
162 angle::Result drawRangeElements(const gl::Context *context,
163 gl::PrimitiveMode mode,
164 GLuint start,
165 GLuint end,
166 GLsizei count,
167 gl::DrawElementsType type,
168 const void *indices) override;
169 angle::Result drawRangeElementsBaseVertex(const gl::Context *context,
170 gl::PrimitiveMode mode,
171 GLuint start,
172 GLuint end,
173 GLsizei count,
174 gl::DrawElementsType type,
175 const void *indices,
176 GLint baseVertex) override;
177 angle::Result drawArraysIndirect(const gl::Context *context,
178 gl::PrimitiveMode mode,
179 const void *indirect) override;
180 angle::Result drawElementsIndirect(const gl::Context *context,
181 gl::PrimitiveMode mode,
182 gl::DrawElementsType type,
183 const void *indirect) override;
184
185 angle::Result multiDrawArrays(const gl::Context *context,
186 gl::PrimitiveMode mode,
187 const GLint *firsts,
188 const GLsizei *counts,
189 GLsizei drawcount) override;
190 angle::Result multiDrawArraysInstanced(const gl::Context *context,
191 gl::PrimitiveMode mode,
192 const GLint *firsts,
193 const GLsizei *counts,
194 const GLsizei *instanceCounts,
195 GLsizei drawcount) override;
196 angle::Result multiDrawArraysIndirect(const gl::Context *context,
197 gl::PrimitiveMode mode,
198 const void *indirect,
199 GLsizei drawcount,
200 GLsizei stride) override;
201 angle::Result multiDrawElements(const gl::Context *context,
202 gl::PrimitiveMode mode,
203 const GLsizei *counts,
204 gl::DrawElementsType type,
205 const GLvoid *const *indices,
206 GLsizei drawcount) override;
207 angle::Result multiDrawElementsInstanced(const gl::Context *context,
208 gl::PrimitiveMode mode,
209 const GLsizei *counts,
210 gl::DrawElementsType type,
211 const GLvoid *const *indices,
212 const GLsizei *instanceCounts,
213 GLsizei drawcount) override;
214 angle::Result multiDrawElementsIndirect(const gl::Context *context,
215 gl::PrimitiveMode mode,
216 gl::DrawElementsType type,
217 const void *indirect,
218 GLsizei drawcount,
219 GLsizei stride) override;
220 angle::Result multiDrawArraysInstancedBaseInstance(const gl::Context *context,
221 gl::PrimitiveMode mode,
222 const GLint *firsts,
223 const GLsizei *counts,
224 const GLsizei *instanceCounts,
225 const GLuint *baseInstances,
226 GLsizei drawcount) override;
227 angle::Result multiDrawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
228 gl::PrimitiveMode mode,
229 const GLsizei *counts,
230 gl::DrawElementsType type,
231 const GLvoid *const *indices,
232 const GLsizei *instanceCounts,
233 const GLint *baseVertices,
234 const GLuint *baseInstances,
235 GLsizei drawcount) override;
236
237 // MultiDrawIndirect helper functions
238 angle::Result multiDrawElementsIndirectHelper(const gl::Context *context,
239 gl::PrimitiveMode mode,
240 gl::DrawElementsType type,
241 const void *indirect,
242 GLsizei drawcount,
243 GLsizei stride);
244 angle::Result multiDrawArraysIndirectHelper(const gl::Context *context,
245 gl::PrimitiveMode mode,
246 const void *indirect,
247 GLsizei drawcount,
248 GLsizei stride);
249
250 // ShareGroup
getShareGroupVk()251 ShareGroupVk *getShareGroupVk() { return mShareGroupVk; }
getPipelineLayoutCache()252 PipelineLayoutCache &getPipelineLayoutCache()
253 {
254 return mShareGroupVk->getPipelineLayoutCache();
255 }
getDescriptorSetLayoutCache()256 DescriptorSetLayoutCache &getDescriptorSetLayoutCache()
257 {
258 return mShareGroupVk->getDescriptorSetLayoutCache();
259 }
260
261 // Device loss
262 gl::GraphicsResetStatus getResetStatus() override;
263
264 // EXT_debug_marker
265 angle::Result insertEventMarker(GLsizei length, const char *marker) override;
266 angle::Result pushGroupMarker(GLsizei length, const char *marker) override;
267 angle::Result popGroupMarker() override;
268
269 void insertEventMarkerImpl(GLenum source, const char *marker);
270
271 // KHR_debug
272 angle::Result pushDebugGroup(const gl::Context *context,
273 GLenum source,
274 GLuint id,
275 const std::string &message) override;
276 angle::Result popDebugGroup(const gl::Context *context) override;
277
278 // Record GL API calls for debuggers
279 void logEvent(const char *eventString);
280 void endEventLog(angle::EntryPoint entryPoint, PipelineType pipelineType);
281 void endEventLogForClearOrQuery();
282
283 bool isViewportFlipEnabledForDrawFBO() const;
284 bool isViewportFlipEnabledForReadFBO() const;
285 // When the device/surface is rotated such that the surface's aspect ratio is different than
286 // the native device (e.g. 90 degrees), the width and height of the viewport, scissor, and
287 // render area must be swapped.
288 bool isRotatedAspectRatioForDrawFBO() const;
289 bool isRotatedAspectRatioForReadFBO() const;
290 SurfaceRotation getRotationDrawFramebuffer() const;
291 SurfaceRotation getRotationReadFramebuffer() const;
292
293 // View port (x, y, w, h) will be determined by a combination of -
294 // 1. clip space origin
295 // 2. isViewportFlipEnabledForDrawFBO
296 // For userdefined FBOs it will be based on the value of isViewportFlipEnabledForDrawFBO.
297 // For default FBOs it will be XOR of ClipOrigin and isViewportFlipEnabledForDrawFBO.
298 // isYFlipEnabledForDrawFBO indicates the rendered image is upside-down.
isYFlipEnabledForDrawFBO()299 ANGLE_INLINE bool isYFlipEnabledForDrawFBO() const
300 {
301 return mState.getClipSpaceOrigin() == gl::ClipSpaceOrigin::UpperLeft
302 ? !isViewportFlipEnabledForDrawFBO()
303 : isViewportFlipEnabledForDrawFBO();
304 }
305
306 // State sync with dirty bits.
307 angle::Result syncState(const gl::Context *context,
308 const gl::State::DirtyBits &dirtyBits,
309 const gl::State::DirtyBits &bitMask,
310 gl::Command command) override;
311
312 // Disjoint timer queries
313 GLint getGPUDisjoint() override;
314 GLint64 getTimestamp() override;
315
316 // Context switching
317 angle::Result onMakeCurrent(const gl::Context *context) override;
318 angle::Result onUnMakeCurrent(const gl::Context *context) override;
319
320 // Native capabilities, unmodified by gl::Context.
321 gl::Caps getNativeCaps() const override;
322 const gl::TextureCapsMap &getNativeTextureCaps() const override;
323 const gl::Extensions &getNativeExtensions() const override;
324 const gl::Limitations &getNativeLimitations() const override;
325
326 // Shader creation
327 CompilerImpl *createCompiler() override;
328 ShaderImpl *createShader(const gl::ShaderState &state) override;
329 ProgramImpl *createProgram(const gl::ProgramState &state) override;
330
331 // Framebuffer creation
332 FramebufferImpl *createFramebuffer(const gl::FramebufferState &state) override;
333
334 // Texture creation
335 TextureImpl *createTexture(const gl::TextureState &state) override;
336
337 // Renderbuffer creation
338 RenderbufferImpl *createRenderbuffer(const gl::RenderbufferState &state) override;
339
340 // Buffer creation
341 BufferImpl *createBuffer(const gl::BufferState &state) override;
342
343 // Vertex Array creation
344 VertexArrayImpl *createVertexArray(const gl::VertexArrayState &state) override;
345
346 // Query and Fence creation
347 QueryImpl *createQuery(gl::QueryType type) override;
348 FenceNVImpl *createFenceNV() override;
349 SyncImpl *createSync() override;
350
351 // Transform Feedback creation
352 TransformFeedbackImpl *createTransformFeedback(
353 const gl::TransformFeedbackState &state) override;
354
355 // Sampler object creation
356 SamplerImpl *createSampler(const gl::SamplerState &state) override;
357
358 // Program Pipeline object creation
359 ProgramPipelineImpl *createProgramPipeline(const gl::ProgramPipelineState &data) override;
360
361 // Memory object creation.
362 MemoryObjectImpl *createMemoryObject() override;
363
364 // Semaphore creation.
365 SemaphoreImpl *createSemaphore() override;
366
367 // Overlay creation.
368 OverlayImpl *createOverlay(const gl::OverlayState &state) override;
369
370 angle::Result dispatchCompute(const gl::Context *context,
371 GLuint numGroupsX,
372 GLuint numGroupsY,
373 GLuint numGroupsZ) override;
374 angle::Result dispatchComputeIndirect(const gl::Context *context, GLintptr indirect) override;
375
376 angle::Result memoryBarrier(const gl::Context *context, GLbitfield barriers) override;
377 angle::Result memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers) override;
378
invalidateTexture(gl::TextureType target)379 ANGLE_INLINE void invalidateTexture(gl::TextureType target) override {}
380
381 // EXT_shader_framebuffer_fetch_non_coherent
382 void framebufferFetchBarrier() override;
383
384 // KHR_blend_equation_advanced
385 void blendBarrier() override;
386
387 // GL_ANGLE_vulkan_image
388 angle::Result acquireTextures(const gl::Context *context,
389 const gl::TextureBarrierVector &textureBarriers) override;
390 angle::Result releaseTextures(const gl::Context *context,
391 gl::TextureBarrierVector *textureBarriers) override;
392
393 VkDevice getDevice() const;
getPriority()394 egl::ContextPriority getPriority() const { return mContextPriority; }
hasProtectedContent()395 bool hasProtectedContent() const { return mState.hasProtectedContent(); }
396
getFeatures()397 ANGLE_INLINE const angle::FeaturesVk &getFeatures() const { return mRenderer->getFeatures(); }
398
invalidateVertexAndIndexBuffers()399 ANGLE_INLINE void invalidateVertexAndIndexBuffers()
400 {
401 mGraphicsDirtyBits |= kIndexAndVertexDirtyBits;
402 }
403
404 angle::Result onVertexBufferChange(const vk::BufferHelper *vertexBuffer);
405
406 angle::Result onVertexAttributeChange(size_t attribIndex,
407 GLuint stride,
408 GLuint divisor,
409 angle::FormatID format,
410 bool compressed,
411 GLuint relativeOffset,
412 const vk::BufferHelper *vertexBuffer);
413
414 void invalidateDefaultAttribute(size_t attribIndex);
415 void invalidateDefaultAttributes(const gl::AttributesMask &dirtyMask);
416 angle::Result onFramebufferChange(FramebufferVk *framebufferVk, gl::Command command);
417 void onDrawFramebufferRenderPassDescChange(FramebufferVk *framebufferVk,
418 bool *renderPassDescChangedOut);
onHostVisibleBufferWrite()419 void onHostVisibleBufferWrite() { mIsAnyHostVisibleBufferWritten = true; }
420
421 void invalidateCurrentTransformFeedbackBuffers();
422 void onTransformFeedbackStateChanged();
423 angle::Result onBeginTransformFeedback(
424 size_t bufferCount,
425 const gl::TransformFeedbackBuffersArray<vk::BufferHelper *> &buffers,
426 const gl::TransformFeedbackBuffersArray<vk::BufferHelper> &counterBuffers);
427 void onEndTransformFeedback();
428 angle::Result onPauseTransformFeedback();
429 void pauseTransformFeedbackIfActiveUnpaused();
430
onColorAccessChange()431 void onColorAccessChange() { mGraphicsDirtyBits |= kColorAccessChangeDirtyBits; }
onDepthStencilAccessChange()432 void onDepthStencilAccessChange() { mGraphicsDirtyBits |= kDepthStencilAccessChangeDirtyBits; }
433
434 // When UtilsVk issues draw or dispatch calls, it binds a new pipeline and descriptor sets that
435 // the context is not aware of. These functions are called to make sure the pipeline and
436 // affected descriptor set bindings are dirtied for the next application draw/dispatch call.
437 void invalidateGraphicsPipelineBinding();
438 void invalidateComputePipelineBinding();
439 void invalidateGraphicsDescriptorSet(DescriptorSetIndex usedDescriptorSet);
440 void invalidateComputeDescriptorSet(DescriptorSetIndex usedDescriptorSet);
441 void invalidateViewportAndScissor();
442 angle::Result updateRenderPassDepthFeedbackLoopMode(
443 UpdateDepthFeedbackLoopReason depthReason,
444 UpdateDepthFeedbackLoopReason stencilReason);
445
446 angle::Result optimizeRenderPassForPresent(VkFramebuffer framebufferHandle,
447 vk::ImageViewHelper *colorImageView,
448 vk::ImageHelper *colorImage,
449 vk::ImageHelper *colorImageMS,
450 VkPresentModeKHR presentMode,
451 bool *imageResolved);
452
453 vk::DynamicQueryPool *getQueryPool(gl::QueryType queryType);
454
455 const VkClearValue &getClearColorValue() const;
456 const VkClearValue &getClearDepthStencilValue() const;
457 gl::BlendStateExt::ColorMaskStorage::Type getClearColorMasks() const;
getScissor()458 const VkRect2D &getScissor() const { return mScissor; }
459 angle::Result getIncompleteTexture(const gl::Context *context,
460 gl::TextureType type,
461 gl::SamplerFormat format,
462 gl::Texture **textureOut);
463 void updateColorMasks();
464 void updateBlendFuncsAndEquations();
465 void updateSampleMaskWithRasterizationSamples(const uint32_t rasterizationSamples);
466
467 void handleError(VkResult errorCode,
468 const char *file,
469 const char *function,
470 unsigned int line) override;
getActiveTextures()471 const gl::ActiveTextureArray<vk::TextureUnit> &getActiveTextures() const
472 {
473 return mActiveTextures;
474 }
getActiveImages()475 const gl::ActiveTextureArray<TextureVk *> &getActiveImages() const { return mActiveImages; }
476
477 angle::Result onIndexBufferChange(const vk::BufferHelper *currentIndexBuffer);
478
479 angle::Result flushImpl(const vk::Semaphore *semaphore,
480 RenderPassClosureReason renderPassClosureReason);
481 angle::Result flushAndGetSerial(const vk::Semaphore *semaphore,
482 Serial *submitSerialOut,
483 RenderPassClosureReason renderPassClosureReason);
484 angle::Result finishImpl(RenderPassClosureReason renderPassClosureReason);
485
486 void addWaitSemaphore(VkSemaphore semaphore, VkPipelineStageFlags stageMask);
487
getLastCompletedQueueSerial()488 Serial getLastCompletedQueueSerial() const { return mRenderer->getLastCompletedQueueSerial(); }
489
490 bool isSerialInUse(Serial serial) const;
491
492 template <typename T>
addGarbage(T * object)493 void addGarbage(T *object)
494 {
495 if (object->valid())
496 {
497 mCurrentGarbage.emplace_back(vk::GetGarbage(object));
498 }
499 }
500
501 // It would be nice if we didn't have to expose this for QueryVk::getResult.
502 angle::Result checkCompletedCommands();
503
504 // Wait for completion of batches until (at least) batch with given serial is finished.
505 angle::Result finishToSerial(Serial serial);
506
507 angle::Result getCompatibleRenderPass(const vk::RenderPassDesc &desc,
508 vk::RenderPass **renderPassOut);
509 angle::Result getRenderPassWithOps(const vk::RenderPassDesc &desc,
510 const vk::AttachmentOpsArray &ops,
511 vk::RenderPass **renderPassOut);
512
getShaderLibrary()513 vk::ShaderLibrary &getShaderLibrary() { return mShaderLibrary; }
getUtils()514 UtilsVk &getUtils() { return mUtils; }
515
516 angle::Result getTimestamp(uint64_t *timestampOut);
517
518 // Create Begin/End/Instant GPU trace events, which take their timestamps from GPU queries.
519 // The events are queued until the query results are available. Possible values for `phase`
520 // are TRACE_EVENT_PHASE_*
traceGpuEvent(vk::OutsideRenderPassCommandBuffer * commandBuffer,char phase,const EventName & name)521 ANGLE_INLINE angle::Result traceGpuEvent(vk::OutsideRenderPassCommandBuffer *commandBuffer,
522 char phase,
523 const EventName &name)
524 {
525 if (mGpuEventsEnabled)
526 return traceGpuEventImpl(commandBuffer, phase, name);
527 return angle::Result::Continue;
528 }
529
getRenderPassCache()530 RenderPassCache &getRenderPassCache() { return mRenderPassCache; }
531
532 vk::DescriptorSetLayoutDesc getDriverUniformsDescriptorSetDesc() const;
533
534 void updateScissor(const gl::State &glState);
535
536 void updateDepthStencil(const gl::State &glState);
537
emulateSeamfulCubeMapSampling()538 bool emulateSeamfulCubeMapSampling() const { return mEmulateSeamfulCubeMapSampling; }
539
getDebug()540 const gl::Debug &getDebug() const { return mState.getDebug(); }
getOverlay()541 const gl::OverlayType *getOverlay() const { return mState.getOverlay(); }
542
getResourceUseList()543 vk::ResourceUseList &getResourceUseList() { return mResourceUseList; }
544
545 angle::Result onBufferReleaseToExternal(const vk::BufferHelper &buffer);
546 angle::Result onImageReleaseToExternal(const vk::ImageHelper &image);
547
onImageRenderPassRead(VkImageAspectFlags aspectFlags,vk::ImageLayout imageLayout,vk::ImageHelper * image)548 void onImageRenderPassRead(VkImageAspectFlags aspectFlags,
549 vk::ImageLayout imageLayout,
550 vk::ImageHelper *image)
551 {
552 ASSERT(mRenderPassCommands->started());
553 mRenderPassCommands->imageRead(this, aspectFlags, imageLayout, image);
554 }
555
onImageRenderPassWrite(gl::LevelIndex level,uint32_t layerStart,uint32_t layerCount,VkImageAspectFlags aspectFlags,vk::ImageLayout imageLayout,vk::ImageHelper * image)556 void onImageRenderPassWrite(gl::LevelIndex level,
557 uint32_t layerStart,
558 uint32_t layerCount,
559 VkImageAspectFlags aspectFlags,
560 vk::ImageLayout imageLayout,
561 vk::ImageHelper *image)
562 {
563 ASSERT(mRenderPassCommands->started());
564 mRenderPassCommands->imageWrite(this, level, layerStart, layerCount, aspectFlags,
565 imageLayout, vk::AliasingMode::Allowed, image);
566 }
567
onColorDraw(gl::LevelIndex level,uint32_t layerStart,uint32_t layerCount,vk::ImageHelper * image,vk::ImageHelper * resolveImage,vk::PackedAttachmentIndex packedAttachmentIndex)568 void onColorDraw(gl::LevelIndex level,
569 uint32_t layerStart,
570 uint32_t layerCount,
571 vk::ImageHelper *image,
572 vk::ImageHelper *resolveImage,
573 vk::PackedAttachmentIndex packedAttachmentIndex)
574 {
575 ASSERT(mRenderPassCommands->started());
576 mRenderPassCommands->colorImagesDraw(&mResourceUseList, level, layerStart, layerCount,
577 image, resolveImage, packedAttachmentIndex);
578 }
onDepthStencilDraw(gl::LevelIndex level,uint32_t layerStart,uint32_t layerCount,vk::ImageHelper * image,vk::ImageHelper * resolveImage)579 void onDepthStencilDraw(gl::LevelIndex level,
580 uint32_t layerStart,
581 uint32_t layerCount,
582 vk::ImageHelper *image,
583 vk::ImageHelper *resolveImage)
584 {
585 ASSERT(mRenderPassCommands->started());
586 mRenderPassCommands->depthStencilImagesDraw(&mResourceUseList, level, layerStart,
587 layerCount, image, resolveImage);
588 }
589
finalizeImageLayout(const vk::ImageHelper * image)590 void finalizeImageLayout(const vk::ImageHelper *image)
591 {
592 if (mRenderPassCommands->started())
593 {
594 mRenderPassCommands->finalizeImageLayout(this, image);
595 }
596 }
597
getOutsideRenderPassCommandBuffer(const vk::CommandBufferAccess & access,vk::OutsideRenderPassCommandBuffer ** commandBufferOut)598 angle::Result getOutsideRenderPassCommandBuffer(
599 const vk::CommandBufferAccess &access,
600 vk::OutsideRenderPassCommandBuffer **commandBufferOut)
601 {
602 ANGLE_TRY(onResourceAccess(access));
603 *commandBufferOut = &mOutsideRenderPassCommands->getCommandBuffer();
604 return angle::Result::Continue;
605 }
606
submitStagedTextureUpdates()607 angle::Result submitStagedTextureUpdates()
608 {
609 // Staged updates are recorded in outside RP cammand buffer, submit them.
610 return flushOutsideRenderPassCommands();
611 }
612
613 angle::Result beginNewRenderPass(const vk::Framebuffer &framebuffer,
614 const gl::Rectangle &renderArea,
615 const vk::RenderPassDesc &renderPassDesc,
616 const vk::AttachmentOpsArray &renderPassAttachmentOps,
617 const vk::PackedAttachmentCount colorAttachmentCount,
618 const vk::PackedAttachmentIndex depthStencilAttachmentIndex,
619 const vk::PackedClearValuesArray &clearValues,
620 vk::RenderPassCommandBuffer **commandBufferOut);
621
622 // Only returns true if we have a started RP and we've run setupDraw.
hasStartedRenderPass()623 bool hasStartedRenderPass() const
624 {
625 // Checking mRenderPassCommandBuffer ensures we've called setupDraw.
626 return mRenderPassCommandBuffer && mRenderPassCommands->started();
627 }
628
hasStartedRenderPassWithFramebuffer(vk::Framebuffer * framebuffer)629 bool hasStartedRenderPassWithFramebuffer(vk::Framebuffer *framebuffer)
630 {
631 return hasStartedRenderPass() &&
632 mRenderPassCommands->getFramebufferHandle() == framebuffer->getHandle();
633 }
634
hasStartedRenderPassWithCommands()635 bool hasStartedRenderPassWithCommands() const
636 {
637 return hasStartedRenderPass() && !mRenderPassCommands->getCommandBuffer().empty();
638 }
639
getStartedRenderPassCommands()640 vk::RenderPassCommandBufferHelper &getStartedRenderPassCommands()
641 {
642 ASSERT(mRenderPassCommands->started());
643 return *mRenderPassCommands;
644 }
645
646 // TODO(https://anglebug.com/4968): Support multiple open render passes.
647 void restoreFinishedRenderPass(vk::Framebuffer *framebuffer);
648
649 uint32_t getCurrentSubpassIndex() const;
650 uint32_t getCurrentViewCount() const;
651
getContextPriority()652 egl::ContextPriority getContextPriority() const override { return mContextPriority; }
653 angle::Result startRenderPass(gl::Rectangle renderArea,
654 vk::RenderPassCommandBuffer **commandBufferOut,
655 bool *renderPassDescChangedOut);
656 angle::Result startNextSubpass();
657 angle::Result flushCommandsAndEndRenderPass(RenderPassClosureReason reason);
658 angle::Result flushCommandsAndEndRenderPassWithoutQueueSubmit(RenderPassClosureReason reason);
659 angle::Result submitOutsideRenderPassCommandsImpl();
660
661 angle::Result syncExternalMemory();
662
663 void addCommandBufferDiagnostics(const std::string &commandBufferDiagnostics);
664
665 VkIndexType getVkIndexType(gl::DrawElementsType glIndexType) const;
666 size_t getVkIndexTypeSize(gl::DrawElementsType glIndexType) const;
667 bool shouldConvertUint8VkIndexType(gl::DrawElementsType glIndexType) const;
668
isBresenhamEmulationEnabled(const gl::PrimitiveMode mode)669 ANGLE_INLINE bool isBresenhamEmulationEnabled(const gl::PrimitiveMode mode)
670 {
671 return getFeatures().basicGLLineRasterization.enabled && gl::IsLineMode(mode);
672 }
673
674 ProgramExecutableVk *getExecutable() const;
675
676 bool isRobustResourceInitEnabled() const;
677
678 // Queries that begin and end automatically with render pass start and end
679 angle::Result beginRenderPassQuery(QueryVk *queryVk);
680 angle::Result endRenderPassQuery(QueryVk *queryVk);
681 void pauseRenderPassQueriesIfActive();
682 angle::Result resumeRenderPassQueriesIfActive();
683 angle::Result resumeXfbRenderPassQueriesIfActive();
684 bool doesPrimitivesGeneratedQuerySupportRasterizerDiscard() const;
685 bool isEmulatingRasterizerDiscardDuringPrimitivesGeneratedQuery(
686 bool isPrimitivesGeneratedQueryActive) const;
687
688 // Used by QueryVk to share query helpers between transform feedback queries.
689 QueryVk *getActiveRenderPassQuery(gl::QueryType queryType) const;
690
691 void syncObjectPerfCounters();
692 void updateOverlayOnPresent();
693 void addOverlayUsedBuffersCount(vk::CommandBufferHelperCommon *commandBuffer);
694
695 // For testing only.
696 void setDefaultUniformBlocksMinSizeForTesting(size_t minSize);
697
getEmptyBuffer()698 vk::BufferHelper &getEmptyBuffer() { return mEmptyBuffer; }
699
700 // Keeping track of the buffer copy size. Used to determine when to submit the outside command
701 // buffer.
702 angle::Result onCopyUpdate(VkDeviceSize size);
resetTotalBufferToImageCopySize()703 void resetTotalBufferToImageCopySize() { mTotalBufferToImageCopySize = 0; }
getTotalBufferToImageCopySize()704 VkDeviceSize getTotalBufferToImageCopySize() const { return mTotalBufferToImageCopySize; }
705
706 // Implementation of MultisampleTextureInitializer
707 angle::Result initializeMultisampleTextureToBlack(const gl::Context *context,
708 gl::Texture *glTexture) override;
709
710 // TODO(http://anglebug.com/5624): rework updateActiveTextures(), createPipelineLayout(),
711 // handleDirtyGraphicsPipeline(), and ProgramPipelineVk::link().
resetCurrentGraphicsPipeline()712 void resetCurrentGraphicsPipeline() { mCurrentGraphicsPipeline = nullptr; }
713
714 void onProgramExecutableReset(ProgramExecutableVk *executableVk);
715
716 angle::Result handleGraphicsEventLog(GraphicsEventCmdBuf queryEventType);
717
718 void flushDescriptorSetUpdates();
719
getDefaultBufferPool(VkDeviceSize size,uint32_t memoryTypeIndex)720 vk::BufferPool *getDefaultBufferPool(VkDeviceSize size, uint32_t memoryTypeIndex)
721 {
722 return mShareGroupVk->getDefaultBufferPool(mRenderer, size, memoryTypeIndex);
723 }
724
allocateStreamedVertexBuffer(size_t attribIndex,size_t bytesToAllocate,vk::BufferHelper ** vertexBufferOut)725 angle::Result allocateStreamedVertexBuffer(size_t attribIndex,
726 size_t bytesToAllocate,
727 vk::BufferHelper **vertexBufferOut)
728 {
729 bool newBufferOut;
730 ANGLE_TRY(mStreamedVertexBuffers[attribIndex].allocate(this, bytesToAllocate,
731 vertexBufferOut, &newBufferOut));
732 if (newBufferOut)
733 {
734 mHasInFlightStreamedVertexBuffers.set(attribIndex);
735 }
736 return angle::Result::Continue;
737 }
738
739 const angle::PerfMonitorCounterGroups &getPerfMonitorCounters() override;
740
741 void resetPerFramePerfCounters();
742
743 private:
744 // Dirty bits.
745 enum DirtyBitType : size_t
746 {
747 // Dirty bits that must be processed before the render pass is started. The handlers for
748 // these dirty bits don't record any commands.
749
750 // A glMemoryBarrier has been called and command buffers may need flushing.
751 DIRTY_BIT_MEMORY_BARRIER,
752 // Update default attribute buffers.
753 DIRTY_BIT_DEFAULT_ATTRIBS,
754 // The pipeline has changed and needs to be recreated. This dirty bit may close the render
755 // pass.
756 DIRTY_BIT_PIPELINE_DESC,
757 // Support for depth/stencil read-only feedback loop. When depth/stencil access changes,
758 // the render pass may need closing.
759 DIRTY_BIT_READ_ONLY_DEPTH_FEEDBACK_LOOP_MODE,
760
761 // Start the render pass.
762 DIRTY_BIT_RENDER_PASS,
763
764 // Dirty bits that must be processed after the render pass is started. Their handlers
765 // record commands.
766 DIRTY_BIT_EVENT_LOG,
767 // Update color and depth/stencil accesses in the render pass.
768 DIRTY_BIT_COLOR_ACCESS,
769 DIRTY_BIT_DEPTH_STENCIL_ACCESS,
770 // Pipeline needs to rebind because a new command buffer has been allocated, or UtilsVk has
771 // changed the binding. The pipeline itself doesn't need to be recreated.
772 DIRTY_BIT_PIPELINE_BINDING,
773 DIRTY_BIT_TEXTURES,
774 DIRTY_BIT_VERTEX_BUFFERS,
775 DIRTY_BIT_INDEX_BUFFER,
776 DIRTY_BIT_UNIFORMS,
777 DIRTY_BIT_DRIVER_UNIFORMS,
778 DIRTY_BIT_DRIVER_UNIFORMS_BINDING,
779 // Shader resources excluding textures, which are handled separately.
780 DIRTY_BIT_SHADER_RESOURCES,
781 DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS,
782 DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME,
783 DIRTY_BIT_DESCRIPTOR_SETS,
784 DIRTY_BIT_FRAMEBUFFER_FETCH_BARRIER,
785 DIRTY_BIT_BLEND_BARRIER,
786 // Dynamic viewport/scissor
787 DIRTY_BIT_VIEWPORT,
788 DIRTY_BIT_SCISSOR,
789 DIRTY_BIT_MAX,
790 };
791
792 // Dirty bit handlers that can break the render pass must always be specified before
793 // DIRTY_BIT_RENDER_PASS.
794 static_assert(
795 DIRTY_BIT_MEMORY_BARRIER < DIRTY_BIT_RENDER_PASS,
796 "Render pass breaking dirty bit must be handled before the render pass dirty bit");
797 static_assert(
798 DIRTY_BIT_DEFAULT_ATTRIBS < DIRTY_BIT_RENDER_PASS,
799 "Render pass breaking dirty bit must be handled before the render pass dirty bit");
800 static_assert(
801 DIRTY_BIT_PIPELINE_DESC < DIRTY_BIT_RENDER_PASS,
802 "Render pass breaking dirty bit must be handled before the render pass dirty bit");
803 static_assert(
804 DIRTY_BIT_READ_ONLY_DEPTH_FEEDBACK_LOOP_MODE < DIRTY_BIT_RENDER_PASS,
805 "Render pass breaking dirty bit must be handled before the render pass dirty bit");
806
807 // Dirty bit handlers that record commands or otherwise expect to manipulate the render pass
808 // that will be used for the draw call must be specified after DIRTY_BIT_RENDER_PASS.
809 static_assert(DIRTY_BIT_EVENT_LOG > DIRTY_BIT_RENDER_PASS,
810 "Render pass using dirty bit must be handled after the render pass dirty bit");
811 static_assert(DIRTY_BIT_COLOR_ACCESS > DIRTY_BIT_RENDER_PASS,
812 "Render pass using dirty bit must be handled after the render pass dirty bit");
813 static_assert(DIRTY_BIT_DEPTH_STENCIL_ACCESS > DIRTY_BIT_RENDER_PASS,
814 "Render pass using dirty bit must be handled after the render pass dirty bit");
815 static_assert(DIRTY_BIT_PIPELINE_BINDING > DIRTY_BIT_RENDER_PASS,
816 "Render pass using dirty bit must be handled after the render pass dirty bit");
817 static_assert(DIRTY_BIT_TEXTURES > DIRTY_BIT_RENDER_PASS,
818 "Render pass using dirty bit must be handled after the render pass dirty bit");
819 static_assert(DIRTY_BIT_VERTEX_BUFFERS > DIRTY_BIT_RENDER_PASS,
820 "Render pass using dirty bit must be handled after the render pass dirty bit");
821 static_assert(DIRTY_BIT_INDEX_BUFFER > DIRTY_BIT_RENDER_PASS,
822 "Render pass using dirty bit must be handled after the render pass dirty bit");
823 static_assert(DIRTY_BIT_DRIVER_UNIFORMS > DIRTY_BIT_RENDER_PASS,
824 "Render pass using dirty bit must be handled after the render pass dirty bit");
825 static_assert(DIRTY_BIT_DRIVER_UNIFORMS_BINDING > DIRTY_BIT_RENDER_PASS,
826 "Render pass using dirty bit must be handled after the render pass dirty bit");
827 static_assert(DIRTY_BIT_SHADER_RESOURCES > DIRTY_BIT_RENDER_PASS,
828 "Render pass using dirty bit must be handled after the render pass dirty bit");
829 static_assert(DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS > DIRTY_BIT_RENDER_PASS,
830 "Render pass using dirty bit must be handled after the render pass dirty bit");
831 static_assert(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME > DIRTY_BIT_RENDER_PASS,
832 "Render pass using dirty bit must be handled after the render pass dirty bit");
833 static_assert(DIRTY_BIT_DESCRIPTOR_SETS > DIRTY_BIT_RENDER_PASS,
834 "Render pass using dirty bit must be handled after the render pass dirty bit");
835 static_assert(DIRTY_BIT_UNIFORMS > DIRTY_BIT_RENDER_PASS,
836 "Render pass using dirty bit must be handled after the render pass dirty bit");
837 static_assert(DIRTY_BIT_FRAMEBUFFER_FETCH_BARRIER > DIRTY_BIT_RENDER_PASS,
838 "Render pass using dirty bit must be handled after the render pass dirty bit");
839 static_assert(DIRTY_BIT_BLEND_BARRIER > DIRTY_BIT_RENDER_PASS,
840 "Render pass using dirty bit must be handled after the render pass dirty bit");
841 static_assert(DIRTY_BIT_VIEWPORT > DIRTY_BIT_RENDER_PASS,
842 "Render pass using dirty bit must be handled after the render pass dirty bit");
843 static_assert(DIRTY_BIT_SCISSOR > DIRTY_BIT_RENDER_PASS,
844 "Render pass using dirty bit must be handled after the render pass dirty bit");
845
846 using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
847
848 using GraphicsDirtyBitHandler = angle::Result (
849 ContextVk::*)(DirtyBits::Iterator *dirtyBitsIterator, DirtyBits dirtyBitMask);
850 using ComputeDirtyBitHandler = angle::Result (ContextVk::*)();
851
852 struct DriverUniformsDescriptorSet
853 {
854 vk::DynamicBuffer dynamicBuffer;
855 VkDescriptorSet descriptorSet;
856 vk::BufferHelper *currentBuffer;
857 vk::BindingPointer<vk::DescriptorSetLayout> descriptorSetLayout;
858 vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
859 DriverUniformsDescriptorSetCache descriptorSetCache;
860
861 DriverUniformsDescriptorSet();
862 ~DriverUniformsDescriptorSet();
863
864 void init(RendererVk *rendererVk);
865 void destroy(RendererVk *rendererVk);
866 };
867
868 // The GpuEventQuery struct holds together a timestamp query and enough data to create a
869 // trace event based on that. Use traceGpuEvent to insert such queries. They will be readback
870 // when the results are available, without inserting a GPU bubble.
871 //
872 // - eventName will be the reported name of the event
873 // - phase is either 'B' (duration begin), 'E' (duration end) or 'i' (instant // event).
874 // See Google's "Trace Event Format":
875 // https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU
876 // - serial is the serial of the batch the query was submitted on. Until the batch is
877 // submitted, the query is not checked to avoid incuring a flush.
878 struct GpuEventQuery final
879 {
880 EventName name;
881 char phase;
882 vk::QueryHelper queryHelper;
883 };
884
885 // Once a query result is available, the timestamp is read and a GpuEvent object is kept until
886 // the next clock sync, at which point the clock drift is compensated in the results before
887 // handing them off to the application.
888 struct GpuEvent final
889 {
890 uint64_t gpuTimestampCycles;
891 std::array<char, kMaxGpuEventNameLen> name;
892 char phase;
893 };
894
895 struct GpuClockSyncInfo
896 {
897 double gpuTimestampS;
898 double cpuTimestampS;
899 };
900
901 class ScopedDescriptorSetUpdates;
902
903 angle::Result setupDraw(const gl::Context *context,
904 gl::PrimitiveMode mode,
905 GLint firstVertexOrInvalid,
906 GLsizei vertexOrIndexCount,
907 GLsizei instanceCount,
908 gl::DrawElementsType indexTypeOrInvalid,
909 const void *indices,
910 DirtyBits dirtyBitMask);
911
912 angle::Result setupIndexedDraw(const gl::Context *context,
913 gl::PrimitiveMode mode,
914 GLsizei indexCount,
915 GLsizei instanceCount,
916 gl::DrawElementsType indexType,
917 const void *indices);
918 angle::Result setupIndirectDraw(const gl::Context *context,
919 gl::PrimitiveMode mode,
920 DirtyBits dirtyBitMask,
921 vk::BufferHelper *indirectBuffer);
922 angle::Result setupIndexedIndirectDraw(const gl::Context *context,
923 gl::PrimitiveMode mode,
924 gl::DrawElementsType indexType,
925 vk::BufferHelper *indirectBuffer);
926
927 angle::Result setupLineLoopIndexedIndirectDraw(const gl::Context *context,
928 gl::PrimitiveMode mode,
929 gl::DrawElementsType indexType,
930 vk::BufferHelper *srcIndirectBuf,
931 VkDeviceSize indirectBufferOffset,
932 vk::BufferHelper **indirectBufferOut);
933 angle::Result setupLineLoopIndirectDraw(const gl::Context *context,
934 gl::PrimitiveMode mode,
935 vk::BufferHelper *indirectBuffer,
936 VkDeviceSize indirectBufferOffset,
937 vk::BufferHelper **indirectBufferOut);
938
939 angle::Result setupLineLoopDraw(const gl::Context *context,
940 gl::PrimitiveMode mode,
941 GLint firstVertex,
942 GLsizei vertexOrIndexCount,
943 gl::DrawElementsType indexTypeOrInvalid,
944 const void *indices,
945 uint32_t *numIndicesOut);
946
947 angle::Result setupDispatch(const gl::Context *context);
948
949 gl::Rectangle getCorrectedViewport(const gl::Rectangle &viewport) const;
950 void updateViewport(FramebufferVk *framebufferVk,
951 const gl::Rectangle &viewport,
952 float nearPlane,
953 float farPlane);
954 void updateDepthRange(float nearPlane, float farPlane);
955 void updateFlipViewportDrawFramebuffer(const gl::State &glState);
956 void updateFlipViewportReadFramebuffer(const gl::State &glState);
957 void updateSurfaceRotationDrawFramebuffer(const gl::State &glState);
958 void updateSurfaceRotationReadFramebuffer(const gl::State &glState);
959
960 angle::Result updateActiveTextures(const gl::Context *context, gl::Command command);
961 template <typename CommandBufferHelperT>
962 angle::Result updateActiveImages(CommandBufferHelperT *commandBufferHelper);
963
invalidateCurrentGraphicsPipeline()964 ANGLE_INLINE void invalidateCurrentGraphicsPipeline()
965 {
966 // Note: DIRTY_BIT_PIPELINE_BINDING will be automatically set if pipeline bind is necessary.
967 mGraphicsDirtyBits.set(DIRTY_BIT_PIPELINE_DESC);
968 }
969
invalidateCurrentComputePipeline()970 ANGLE_INLINE void invalidateCurrentComputePipeline()
971 {
972 mComputeDirtyBits |= kPipelineDescAndBindingDirtyBits;
973 mCurrentComputePipeline = nullptr;
974 }
975
976 angle::Result invalidateProgramExecutableHelper(const gl::Context *context);
977 angle::Result checkAndUpdateFramebufferFetchStatus(const gl::ProgramExecutable *executable);
978
979 void invalidateCurrentDefaultUniforms();
980 angle::Result invalidateCurrentTextures(const gl::Context *context, gl::Command command);
981 angle::Result invalidateCurrentShaderResources(gl::Command command);
982 void invalidateGraphicsDriverUniforms();
983 void invalidateDriverUniforms();
984
985 angle::Result handleNoopDrawEvent() override;
986
987 // Handlers for graphics pipeline dirty bits.
988 angle::Result handleDirtyGraphicsMemoryBarrier(DirtyBits::Iterator *dirtyBitsIterator,
989 DirtyBits dirtyBitMask);
990 angle::Result handleDirtyGraphicsDefaultAttribs(DirtyBits::Iterator *dirtyBitsIterator,
991 DirtyBits dirtyBitMask);
992 angle::Result handleDirtyGraphicsPipelineDesc(DirtyBits::Iterator *dirtyBitsIterator,
993 DirtyBits dirtyBitMask);
994 angle::Result handleDirtyGraphicsReadOnlyDepthFeedbackLoopMode(
995 DirtyBits::Iterator *dirtyBitsIterator,
996 DirtyBits dirtyBitMask);
997 angle::Result handleDirtyGraphicsRenderPass(DirtyBits::Iterator *dirtyBitsIterator,
998 DirtyBits dirtyBitMask);
999 angle::Result handleDirtyGraphicsEventLog(DirtyBits::Iterator *dirtyBitsIterator,
1000 DirtyBits dirtyBitMask);
1001 angle::Result handleDirtyGraphicsColorAccess(DirtyBits::Iterator *dirtyBitsIterator,
1002 DirtyBits dirtyBitMask);
1003 angle::Result handleDirtyGraphicsDepthStencilAccess(DirtyBits::Iterator *dirtyBitsIterator,
1004 DirtyBits dirtyBitMask);
1005 angle::Result handleDirtyGraphicsPipelineBinding(DirtyBits::Iterator *dirtyBitsIterator,
1006 DirtyBits dirtyBitMask);
1007 angle::Result handleDirtyGraphicsTextures(DirtyBits::Iterator *dirtyBitsIterator,
1008 DirtyBits dirtyBitMask);
1009 angle::Result handleDirtyGraphicsVertexBuffers(DirtyBits::Iterator *dirtyBitsIterator,
1010 DirtyBits dirtyBitMask);
1011 angle::Result handleDirtyGraphicsIndexBuffer(DirtyBits::Iterator *dirtyBitsIterator,
1012 DirtyBits dirtyBitMask);
1013 angle::Result handleDirtyGraphicsDriverUniforms(DirtyBits::Iterator *dirtyBitsIterator,
1014 DirtyBits dirtyBitMask);
1015 angle::Result handleDirtyGraphicsDriverUniformsBinding(DirtyBits::Iterator *dirtyBitsIterator,
1016 DirtyBits dirtyBitMask);
1017 angle::Result handleDirtyGraphicsShaderResources(DirtyBits::Iterator *dirtyBitsIterator,
1018 DirtyBits dirtyBitMask);
1019 angle::Result handleDirtyGraphicsFramebufferFetchBarrier(DirtyBits::Iterator *dirtyBitsIterator,
1020 DirtyBits dirtyBitMask);
1021 angle::Result handleDirtyGraphicsBlendBarrier(DirtyBits::Iterator *dirtyBitsIterator,
1022 DirtyBits dirtyBitMask);
1023 angle::Result handleDirtyGraphicsTransformFeedbackBuffersEmulation(
1024 DirtyBits::Iterator *dirtyBitsIterator,
1025 DirtyBits dirtyBitMask);
1026 angle::Result handleDirtyGraphicsTransformFeedbackBuffersExtension(
1027 DirtyBits::Iterator *dirtyBitsIterator,
1028 DirtyBits dirtyBitMask);
1029 angle::Result handleDirtyGraphicsTransformFeedbackResume(DirtyBits::Iterator *dirtyBitsIterator,
1030 DirtyBits dirtyBitMask);
1031 angle::Result handleDirtyGraphicsDescriptorSets(DirtyBits::Iterator *dirtyBitsIterator,
1032 DirtyBits dirtyBitMask);
1033 angle::Result handleDirtyGraphicsUniforms(DirtyBits::Iterator *dirtyBitsIterator,
1034 DirtyBits dirtyBitMask);
1035 angle::Result handleDirtyGraphicsViewport(DirtyBits::Iterator *dirtyBitsIterator,
1036 DirtyBits dirtyBitMask);
1037 angle::Result handleDirtyGraphicsScissor(DirtyBits::Iterator *dirtyBitsIterator,
1038 DirtyBits dirtyBitMask);
1039
1040 // Handlers for compute pipeline dirty bits.
1041 angle::Result handleDirtyComputeMemoryBarrier();
1042 angle::Result handleDirtyComputeEventLog();
1043 angle::Result handleDirtyComputePipelineDesc();
1044 angle::Result handleDirtyComputePipelineBinding();
1045 angle::Result handleDirtyComputeTextures();
1046 angle::Result handleDirtyComputeDriverUniforms();
1047 angle::Result handleDirtyComputeDriverUniformsBinding();
1048 angle::Result handleDirtyComputeShaderResources();
1049 angle::Result handleDirtyComputeDescriptorSets();
1050 angle::Result handleDirtyComputeUniforms();
1051
1052 // Common parts of the common dirty bit handlers.
1053 angle::Result handleDirtyUniformsImpl();
1054 angle::Result handleDirtyMemoryBarrierImpl(DirtyBits::Iterator *dirtyBitsIterator,
1055 DirtyBits dirtyBitMask);
1056 template <typename CommandBufferT>
1057 angle::Result handleDirtyEventLogImpl(CommandBufferT *commandBuffer);
1058 template <typename CommandBufferHelperT>
1059 angle::Result handleDirtyTexturesImpl(CommandBufferHelperT *commandBufferHelper,
1060 PipelineType pipelineType);
1061 template <typename CommandBufferHelperT>
1062 angle::Result handleDirtyShaderResourcesImpl(CommandBufferHelperT *commandBufferHelper,
1063 PipelineType pipelineType);
1064 void handleDirtyShaderBufferResourcesImpl(vk::CommandBufferHelperCommon *commandBufferHelper);
1065 template <typename CommandBufferT>
1066 void handleDirtyDriverUniformsBindingImpl(CommandBufferT *commandBuffer,
1067 VkPipelineBindPoint bindPoint,
1068 DriverUniformsDescriptorSet *driverUniforms);
1069 template <typename CommandBufferT>
1070 angle::Result handleDirtyDescriptorSetsImpl(CommandBufferT *commandBuffer,
1071 PipelineType pipelineType);
1072 void handleDirtyGraphicsScissorImpl(bool isPrimitivesGeneratedQueryActive);
1073
1074 angle::Result allocateDriverUniforms(size_t driverUniformsSize,
1075 DriverUniformsDescriptorSet *driverUniforms,
1076 uint8_t **ptrOut,
1077 bool *newBufferOut);
1078 angle::Result updateDriverUniformsDescriptorSet(bool newBuffer,
1079 size_t driverUniformsSize,
1080 PipelineType pipelineType);
1081
1082 void writeAtomicCounterBufferDriverUniformOffsets(uint32_t *offsetsOut, size_t offsetsSize);
1083
1084 angle::Result submitFrame(const vk::Semaphore *signalSemaphore, Serial *submitSerialOut);
1085 angle::Result submitFrameOutsideCommandBufferOnly(Serial *submitSerialOut);
1086 angle::Result submitCommands(const vk::Semaphore *signalSemaphore, Serial *submitSerialOut);
1087
1088 angle::Result synchronizeCpuGpuTime();
1089 angle::Result traceGpuEventImpl(vk::OutsideRenderPassCommandBuffer *commandBuffer,
1090 char phase,
1091 const EventName &name);
1092 angle::Result checkCompletedGpuEvents();
1093 void flushGpuEvents(double nextSyncGpuTimestampS, double nextSyncCpuTimestampS);
1094 void handleDeviceLost();
1095 bool shouldEmulateSeamfulCubeMapSampling() const;
1096 void clearAllGarbage();
1097 void dumpCommandStreamDiagnostics();
1098 angle::Result flushOutsideRenderPassCommands();
1099 // Flush commands and end render pass without setting any dirty bits.
1100 // flushCommandsAndEndRenderPass() and flushDirtyGraphicsRenderPass() will set the dirty bits
1101 // directly or through the iterator respectively. Outside those two functions, this shouldn't
1102 // be called directly.
1103 angle::Result flushCommandsAndEndRenderPassImpl(QueueSubmitType queueSubmit,
1104 RenderPassClosureReason reason);
1105 angle::Result flushDirtyGraphicsRenderPass(DirtyBits::Iterator *dirtyBitsIterator,
1106 DirtyBits dirtyBitMask,
1107 RenderPassClosureReason reason);
1108
1109 void onRenderPassFinished(RenderPassClosureReason reason);
1110
1111 void initIndexTypeMap();
1112
1113 VertexArrayVk *getVertexArray() const;
1114 FramebufferVk *getDrawFramebuffer() const;
1115 ProgramVk *getProgram() const;
1116 ProgramPipelineVk *getProgramPipeline() const;
1117
1118 // Read-after-write hazards are generally handled with |glMemoryBarrier| when the source of
1119 // write is storage output. When the write is outside render pass, the natural placement of the
1120 // render pass after the current outside render pass commands ensures that the memory barriers
1121 // and image layout transitions automatically take care of such synchronizations.
1122 //
1123 // There are a number of read-after-write cases that require breaking the render pass however to
1124 // preserve the order of operations:
1125 //
1126 // - Transform feedback write (in render pass), then vertex/index read (in render pass)
1127 // - Transform feedback write (in render pass), then ubo read (outside render pass)
1128 // - Framebuffer attachment write (in render pass), then texture sample (outside render pass)
1129 // * Note that texture sampling inside render pass would cause a feedback loop
1130 //
1131 angle::Result endRenderPassIfTransformFeedbackBuffer(const vk::BufferHelper *buffer);
1132 angle::Result endRenderPassIfComputeReadAfterTransformFeedbackWrite();
1133 angle::Result endRenderPassIfComputeReadAfterAttachmentWrite();
1134
1135 void populateTransformFeedbackBufferSet(
1136 size_t bufferCount,
1137 const gl::TransformFeedbackBuffersArray<vk::BufferHelper *> &buffers);
1138
1139 // Update framebuffer's read-only depth feedback loop mode. Typically called from
1140 // handleDirtyGraphicsReadOnlyDepthFeedbackLoopMode, but can be called from UtilsVk in functions
1141 // that don't necessarily break the render pass.
1142 angle::Result updateRenderPassDepthFeedbackLoopModeImpl(
1143 DirtyBits::Iterator *dirtyBitsIterator,
1144 DirtyBits dirtyBitMask,
1145 UpdateDepthFeedbackLoopReason depthReason,
1146 UpdateDepthFeedbackLoopReason stencilReason);
1147 bool shouldSwitchToReadOnlyDepthFeedbackLoopMode(gl::Texture *texture,
1148 gl::Command command) const;
1149
1150 angle::Result onResourceAccess(const vk::CommandBufferAccess &access);
1151 angle::Result flushCommandBuffersIfNecessary(const vk::CommandBufferAccess &access);
1152 bool renderPassUsesStorageResources() const;
1153
1154 angle::Result pushDebugGroupImpl(GLenum source, GLuint id, const char *message);
1155 angle::Result popDebugGroupImpl();
1156
1157 void updateSampleShadingWithRasterizationSamples(const uint32_t rasterizationSamples);
1158 void updateRasterizationSamples(const uint32_t rasterizationSamples);
1159 void updateRasterizerDiscardEnabled(bool isPrimitivesGeneratedQueryActive);
1160
1161 void updateAdvancedBlendEquations(const gl::ProgramExecutable *executable);
1162
1163 void updateDither();
1164
1165 SpecConstUsageBits getCurrentProgramSpecConstUsageBits() const;
1166 void updateGraphicsPipelineDescWithSpecConstUsageBits(SpecConstUsageBits usageBits);
1167
1168 void updateShaderResourcesDescriptorDesc(PipelineType pipelineType);
1169
1170 std::array<GraphicsDirtyBitHandler, DIRTY_BIT_MAX> mGraphicsDirtyBitHandlers;
1171 std::array<ComputeDirtyBitHandler, DIRTY_BIT_MAX> mComputeDirtyBitHandlers;
1172
1173 vk::RenderPassCommandBuffer *mRenderPassCommandBuffer;
1174
1175 vk::PipelineHelper *mCurrentGraphicsPipeline;
1176 vk::PipelineHelper *mCurrentComputePipeline;
1177 gl::PrimitiveMode mCurrentDrawMode;
1178
1179 WindowSurfaceVk *mCurrentWindowSurface;
1180 // Records the current rotation of the surface (draw/read) framebuffer, derived from
1181 // mCurrentWindowSurface->getPreTransform().
1182 SurfaceRotation mCurrentRotationDrawFramebuffer;
1183 SurfaceRotation mCurrentRotationReadFramebuffer;
1184
1185 // Keep a cached pipeline description structure that can be used to query the pipeline cache.
1186 // Kept in a pointer so allocations can be aligned, and structs can be portably packed.
1187 std::unique_ptr<vk::GraphicsPipelineDesc> mGraphicsPipelineDesc;
1188 vk::GraphicsPipelineTransitionBits mGraphicsPipelineTransition;
1189
1190 // These pools are externally synchronized, so cannot be accessed from different
1191 // threads simultaneously. Hence, we keep them in the ContextVk instead of the RendererVk.
1192 // Note that this implementation would need to change in shared resource scenarios. Likely
1193 // we'd instead share a single set of pools between the share groups.
1194 angle::PackedEnumMap<PipelineType, vk::DynamicDescriptorPool> mDriverUniformsDescriptorPools;
1195 gl::QueryTypeMap<vk::DynamicQueryPool> mQueryPools;
1196
1197 // Queries that need to be closed and reopened with the render pass:
1198 //
1199 // - Occlusion queries
1200 // - Transform feedback queries, if not emulated
1201 gl::QueryTypeMap<QueryVk *> mActiveRenderPassQueries;
1202
1203 // Dirty bits.
1204 DirtyBits mGraphicsDirtyBits;
1205 DirtyBits mComputeDirtyBits;
1206 DirtyBits mNonIndexedDirtyBitsMask;
1207 DirtyBits mIndexedDirtyBitsMask;
1208 DirtyBits mNewGraphicsCommandBufferDirtyBits;
1209 DirtyBits mNewComputeCommandBufferDirtyBits;
1210 static constexpr DirtyBits kColorAccessChangeDirtyBits{DIRTY_BIT_COLOR_ACCESS};
1211 static constexpr DirtyBits kDepthStencilAccessChangeDirtyBits{
1212 DIRTY_BIT_READ_ONLY_DEPTH_FEEDBACK_LOOP_MODE, DIRTY_BIT_DEPTH_STENCIL_ACCESS};
1213 static constexpr DirtyBits kIndexAndVertexDirtyBits{DIRTY_BIT_VERTEX_BUFFERS,
1214 DIRTY_BIT_INDEX_BUFFER};
1215 static constexpr DirtyBits kPipelineDescAndBindingDirtyBits{DIRTY_BIT_PIPELINE_DESC,
1216 DIRTY_BIT_PIPELINE_BINDING};
1217 static constexpr DirtyBits kTexturesAndDescSetDirtyBits{DIRTY_BIT_TEXTURES,
1218 DIRTY_BIT_DESCRIPTOR_SETS};
1219 static constexpr DirtyBits kResourcesAndDescSetDirtyBits{DIRTY_BIT_SHADER_RESOURCES,
1220 DIRTY_BIT_DESCRIPTOR_SETS};
1221 static constexpr DirtyBits kXfbBuffersAndDescSetDirtyBits{DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS,
1222 DIRTY_BIT_DESCRIPTOR_SETS};
1223 static constexpr DirtyBits kDriverUniformsAndBindingDirtyBits{
1224 DIRTY_BIT_DRIVER_UNIFORMS, DIRTY_BIT_DRIVER_UNIFORMS_BINDING};
1225
1226 // The offset we had the last time we bound the index buffer.
1227 const GLvoid *mLastIndexBufferOffset;
1228 VkDeviceSize mCurrentIndexBufferOffset;
1229 gl::DrawElementsType mCurrentDrawElementsType;
1230 angle::PackedEnumMap<gl::DrawElementsType, VkIndexType> mIndexTypeMap;
1231
1232 // Cache the current draw call's firstVertex to be passed to
1233 // TransformFeedbackVk::getBufferOffsets. Unfortunately, gl_BaseVertex support in Vulkan is
1234 // not yet ubiquitous, which would have otherwise removed the need for this value to be passed
1235 // as a uniform.
1236 GLint mXfbBaseVertex;
1237 // Cache the current draw call's vertex count as well to support instanced draw calls
1238 GLuint mXfbVertexCountPerInstance;
1239
1240 // Cached clear value/mask for color and depth/stencil.
1241 VkClearValue mClearColorValue;
1242 VkClearValue mClearDepthStencilValue;
1243 gl::BlendStateExt::ColorMaskStorage::Type mClearColorMasks;
1244
1245 IncompleteTextureSet mIncompleteTextures;
1246
1247 // If the current surface bound to this context wants to have all rendering flipped vertically.
1248 // Updated on calls to onMakeCurrent.
1249 bool mFlipYForCurrentSurface;
1250 bool mFlipViewportForDrawFramebuffer;
1251 bool mFlipViewportForReadFramebuffer;
1252
1253 // If any host-visible buffer is written by the GPU since last submission, a barrier is inserted
1254 // at the end of the command buffer to make that write available to the host.
1255 bool mIsAnyHostVisibleBufferWritten;
1256
1257 // Whether this context should do seamful cube map sampling emulation.
1258 bool mEmulateSeamfulCubeMapSampling;
1259
1260 angle::PackedEnumMap<PipelineType, DriverUniformsDescriptorSet> mDriverUniforms;
1261
1262 // This cache should also probably include the texture index (shader location) and array
1263 // index (also in the shader). This info is used in the descriptor update step.
1264 gl::ActiveTextureArray<vk::TextureUnit> mActiveTextures;
1265
1266 // We use textureSerial to optimize texture binding updates. Each permutation of a
1267 // {VkImage/VkSampler} generates a unique serial. These object ids are combined to form a unique
1268 // signature for each descriptor set. This allows us to keep a cache of descriptor sets and
1269 // avoid calling vkAllocateDesctiporSets each texture update.
1270 vk::DescriptorSetDesc mActiveTexturesDesc;
1271
1272 vk::DescriptorSetDesc mShaderBuffersDescriptorDesc;
1273
1274 gl::ActiveTextureArray<TextureVk *> mActiveImages;
1275
1276 // "Current Value" aka default vertex attribute state.
1277 gl::AttributesMask mDirtyDefaultAttribsMask;
1278
1279 // DynamicBuffers for streaming vertex data from client memory pointer as well as for default
1280 // attributes. mHasInFlightStreamedVertexBuffers indicates if the dynamic buffer has any
1281 // inflight buffer or not that we need to release at submission time.
1282 gl::AttribArray<vk::DynamicBuffer> mStreamedVertexBuffers;
1283 gl::AttributesMask mHasInFlightStreamedVertexBuffers;
1284
1285 // We use a single pool for recording commands. We also keep a free list for pool recycling.
1286 vk::SecondaryCommandPools mCommandPools;
1287
1288 vk::GarbageList mCurrentGarbage;
1289
1290 RenderPassCache mRenderPassCache;
1291
1292 vk::OutsideRenderPassCommandBufferHelper *mOutsideRenderPassCommands;
1293 vk::RenderPassCommandBufferHelper *mRenderPassCommands;
1294
1295 // The following is used when creating debug-util markers for graphics debuggers (e.g. AGI). A
1296 // given gl{Begin|End}Query command may result in commands being submitted to the outside or
1297 // render-pass command buffer. The ContextVk::handleGraphicsEventLog() method records the
1298 // appropriate command buffer for use by ContextVk::endEventLogForQuery(). The knowledge of
1299 // which command buffer to use depends on the particular type of query (e.g. samples
1300 // vs. timestamp), and is only known by the query code, which is what calls
1301 // ContextVk::handleGraphicsEventLog(). After all back-end processing of the gl*Query command
1302 // is complete, the front-end calls ContextVk::endEventLogForQuery(), which needs to know which
1303 // command buffer to call endDebugUtilsLabelEXT() for.
1304 GraphicsEventCmdBuf mQueryEventType;
1305
1306 // Transform feedback buffers.
1307 angle::FlatUnorderedSet<const vk::BufferHelper *,
1308 gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS>
1309 mCurrentTransformFeedbackBuffers;
1310
1311 // Internal shader library.
1312 vk::ShaderLibrary mShaderLibrary;
1313 UtilsVk mUtils;
1314
1315 bool mGpuEventsEnabled;
1316 vk::DynamicQueryPool mGpuEventQueryPool;
1317 // A list of queries that have yet to be turned into an event (their result is not yet
1318 // available).
1319 std::vector<GpuEventQuery> mInFlightGpuEventQueries;
1320 // A list of gpu events since the last clock sync.
1321 std::vector<GpuEvent> mGpuEvents;
1322
1323 // Cached value of the color attachment mask of the current draw framebuffer. This is used to
1324 // know which attachment indices have their blend state set in |mGraphicsPipelineDesc|, and
1325 // subsequently is used to clear the blend state for attachments that no longer exist when a new
1326 // framebuffer is bound.
1327 gl::DrawBufferMask mCachedDrawFramebufferColorAttachmentMask;
1328
1329 bool mHasDeferredFlush;
1330
1331 // The size of copy commands issued between buffers and images. Used to submit the command
1332 // buffer for the outside render pass.
1333 VkDeviceSize mTotalBufferToImageCopySize = 0;
1334
1335 // Semaphores that must be waited on in the next submission.
1336 std::vector<VkSemaphore> mWaitSemaphores;
1337 std::vector<VkPipelineStageFlags> mWaitSemaphoreStageMasks;
1338
1339 // Hold information from the last gpu clock sync for future gpu-to-cpu timestamp conversions.
1340 GpuClockSyncInfo mGpuClockSync;
1341
1342 // The very first timestamp queried for a GPU event is used as origin, so event timestamps would
1343 // have a value close to zero, to avoid losing 12 bits when converting these 64 bit values to
1344 // double.
1345 uint64_t mGpuEventTimestampOrigin;
1346
1347 // A mix of per-frame and per-run counters.
1348 angle::PerfMonitorCounterGroups mPerfMonitorCounters;
1349
1350 gl::State::DirtyBits mPipelineDirtyBitsMask;
1351
1352 // List of all resources currently being used by this ContextVk's recorded commands.
1353 vk::ResourceUseList mResourceUseList;
1354
1355 egl::ContextPriority mContextPriority;
1356
1357 // Storage for vkUpdateDescriptorSets
1358 UpdateDescriptorSetsBuilder mUpdateDescriptorSetsBuilder;
1359
1360 ShareGroupVk *mShareGroupVk;
1361
1362 // This is a special "empty" placeholder buffer for use when we just need a placeholder buffer
1363 // but not the data. Examples are shader that has no uniform or doesn't use all slots in the
1364 // atomic counter buffer array, or places where there is no vertex buffer since Vulkan does not
1365 // allow binding a null vertex buffer.
1366 vk::BufferHelper mEmptyBuffer;
1367
1368 // Storage for default uniforms of ProgramVks and ProgramPipelineVks.
1369 vk::DynamicBuffer mDefaultUniformStorage;
1370
1371 std::vector<std::string> mCommandBufferDiagnostics;
1372
1373 // Record GL API calls for debuggers
1374 std::vector<std::string> mEventLog;
1375
1376 // Viewport and scissor are handled as dynamic state.
1377 VkViewport mViewport;
1378 VkRect2D mScissor;
1379 };
1380
endRenderPassIfTransformFeedbackBuffer(const vk::BufferHelper * buffer)1381 ANGLE_INLINE angle::Result ContextVk::endRenderPassIfTransformFeedbackBuffer(
1382 const vk::BufferHelper *buffer)
1383 {
1384 if (!buffer || !mCurrentTransformFeedbackBuffers.contains(buffer))
1385 {
1386 return angle::Result::Continue;
1387 }
1388
1389 return flushCommandsAndEndRenderPass(RenderPassClosureReason::XfbWriteThenVertexIndexBuffer);
1390 }
1391
onIndexBufferChange(const vk::BufferHelper * currentIndexBuffer)1392 ANGLE_INLINE angle::Result ContextVk::onIndexBufferChange(
1393 const vk::BufferHelper *currentIndexBuffer)
1394 {
1395 mGraphicsDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
1396 mLastIndexBufferOffset = reinterpret_cast<const void *>(angle::DirtyPointer);
1397 return endRenderPassIfTransformFeedbackBuffer(currentIndexBuffer);
1398 }
1399
onVertexBufferChange(const vk::BufferHelper * vertexBuffer)1400 ANGLE_INLINE angle::Result ContextVk::onVertexBufferChange(const vk::BufferHelper *vertexBuffer)
1401 {
1402 mGraphicsDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS);
1403 return endRenderPassIfTransformFeedbackBuffer(vertexBuffer);
1404 }
1405
onVertexAttributeChange(size_t attribIndex,GLuint stride,GLuint divisor,angle::FormatID format,bool compressed,GLuint relativeOffset,const vk::BufferHelper * vertexBuffer)1406 ANGLE_INLINE angle::Result ContextVk::onVertexAttributeChange(size_t attribIndex,
1407 GLuint stride,
1408 GLuint divisor,
1409 angle::FormatID format,
1410 bool compressed,
1411 GLuint relativeOffset,
1412 const vk::BufferHelper *vertexBuffer)
1413 {
1414 invalidateCurrentGraphicsPipeline();
1415 // Set divisor to 1 for attribs with emulated divisor
1416 mGraphicsPipelineDesc->updateVertexInput(
1417 &mGraphicsPipelineTransition, static_cast<uint32_t>(attribIndex), stride,
1418 divisor > mRenderer->getMaxVertexAttribDivisor() ? 1 : divisor, format, compressed,
1419 relativeOffset);
1420 return onVertexBufferChange(vertexBuffer);
1421 }
1422
UseLineRaster(const ContextVk * contextVk,gl::PrimitiveMode mode)1423 ANGLE_INLINE bool UseLineRaster(const ContextVk *contextVk, gl::PrimitiveMode mode)
1424 {
1425 return contextVk->getFeatures().basicGLLineRasterization.enabled && gl::IsLineMode(mode);
1426 }
1427 } // namespace rx
1428
1429 // Generate a perf warning, and insert an event marker in the command buffer.
1430 #define ANGLE_VK_PERF_WARNING(contextVk, severity, ...) \
1431 do \
1432 { \
1433 char ANGLE_MESSAGE[100]; \
1434 snprintf(ANGLE_MESSAGE, sizeof(ANGLE_MESSAGE), __VA_ARGS__); \
1435 ANGLE_PERF_WARNING(contextVk->getDebug(), severity, ANGLE_MESSAGE); \
1436 \
1437 contextVk->insertEventMarkerImpl(GL_DEBUG_SOURCE_OTHER, ANGLE_MESSAGE); \
1438 } while (0)
1439
1440 // Generate a trace event for graphics profiler, and insert an event marker in the command buffer.
1441 #define ANGLE_VK_TRACE_EVENT_AND_MARKER(contextVk, ...) \
1442 do \
1443 { \
1444 char ANGLE_MESSAGE[100]; \
1445 snprintf(ANGLE_MESSAGE, sizeof(ANGLE_MESSAGE), __VA_ARGS__); \
1446 ANGLE_TRACE_EVENT0("gpu.angle", ANGLE_MESSAGE); \
1447 \
1448 contextVk->insertEventMarkerImpl(GL_DEBUG_SOURCE_OTHER, ANGLE_MESSAGE); \
1449 } while (0)
1450
1451 #endif // LIBANGLE_RENDERER_VULKAN_CONTEXTVK_H_
1452