• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2018 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 // vk_cache_utils.cpp:
7 //    Contains the classes for the Pipeline State Object cache as well as the RenderPass cache.
8 //    Also contains the structures for the packed descriptions for the RenderPass and Pipeline.
9 //
10 
11 #include "libANGLE/renderer/vulkan/vk_cache_utils.h"
12 
13 #include "common/aligned_memory.h"
14 #include "common/system_utils.h"
15 #include "libANGLE/BlobCache.h"
16 #include "libANGLE/VertexAttribute.h"
17 #include "libANGLE/renderer/vulkan/DisplayVk.h"
18 #include "libANGLE/renderer/vulkan/FramebufferVk.h"
19 #include "libANGLE/renderer/vulkan/ProgramVk.h"
20 #include "libANGLE/renderer/vulkan/TextureVk.h"
21 #include "libANGLE/renderer/vulkan/VertexArrayVk.h"
22 #include "libANGLE/renderer/vulkan/vk_format_utils.h"
23 #include "libANGLE/renderer/vulkan/vk_helpers.h"
24 #include "libANGLE/renderer/vulkan/vk_renderer.h"
25 
26 #include <type_traits>
27 
28 namespace rx
29 {
30 #if defined(ANGLE_DUMP_PIPELINE_CACHE_GRAPH)
31 constexpr bool kDumpPipelineCacheGraph = true;
32 #else
33 constexpr bool kDumpPipelineCacheGraph = false;
34 #endif  // ANGLE_DUMP_PIPELINE_CACHE_GRAPH
35 
36 template <typename T>
AllCacheEntriesHaveUniqueReference(const T & payload)37 bool AllCacheEntriesHaveUniqueReference(const T &payload)
38 {
39     bool unique = true;
40     for (auto &item : payload)
41     {
42         if (!item.second.unique())
43         {
44             unique = false;
45         }
46     }
47     return unique;
48 }
49 
50 namespace vk
51 {
52 namespace
53 {
54 static_assert(static_cast<uint32_t>(RenderPassLoadOp::Load) == VK_ATTACHMENT_LOAD_OP_LOAD,
55               "ConvertRenderPassLoadOpToVkLoadOp must be updated");
56 static_assert(static_cast<uint32_t>(RenderPassLoadOp::Clear) == VK_ATTACHMENT_LOAD_OP_CLEAR,
57               "ConvertRenderPassLoadOpToVkLoadOp must be updated");
58 static_assert(static_cast<uint32_t>(RenderPassLoadOp::DontCare) == VK_ATTACHMENT_LOAD_OP_DONT_CARE,
59               "ConvertRenderPassLoadOpToVkLoadOp must be updated");
60 static_assert(static_cast<uint32_t>(RenderPassLoadOp::None) == 3,
61               "ConvertRenderPassLoadOpToVkLoadOp must be updated");
62 
63 static_assert(static_cast<uint32_t>(RenderPassStoreOp::Store) == VK_ATTACHMENT_STORE_OP_STORE,
64               "ConvertRenderPassStoreOpToVkStoreOp must be updated");
65 static_assert(static_cast<uint32_t>(RenderPassStoreOp::DontCare) ==
66                   VK_ATTACHMENT_STORE_OP_DONT_CARE,
67               "ConvertRenderPassStoreOpToVkStoreOp must be updated");
68 static_assert(static_cast<uint32_t>(RenderPassStoreOp::None) == 2,
69               "ConvertRenderPassStoreOpToVkStoreOp must be updated");
70 
71 constexpr uint16_t kMinSampleShadingScale = angle::BitMask<uint16_t>(8);
72 
ConvertRenderPassLoadOpToVkLoadOp(RenderPassLoadOp loadOp)73 VkAttachmentLoadOp ConvertRenderPassLoadOpToVkLoadOp(RenderPassLoadOp loadOp)
74 {
75     return loadOp == RenderPassLoadOp::None ? VK_ATTACHMENT_LOAD_OP_NONE_EXT
76                                             : static_cast<VkAttachmentLoadOp>(loadOp);
77 }
ConvertRenderPassStoreOpToVkStoreOp(RenderPassStoreOp storeOp)78 VkAttachmentStoreOp ConvertRenderPassStoreOpToVkStoreOp(RenderPassStoreOp storeOp)
79 {
80     return storeOp == RenderPassStoreOp::None ? VK_ATTACHMENT_STORE_OP_NONE_EXT
81                                               : static_cast<VkAttachmentStoreOp>(storeOp);
82 }
83 
TransitionBits(size_t size)84 constexpr size_t TransitionBits(size_t size)
85 {
86     return size / kGraphicsPipelineDirtyBitBytes;
87 }
88 
89 constexpr size_t kPipelineShadersDescOffset = 0;
90 constexpr size_t kPipelineShadersDescSize =
91     kGraphicsPipelineShadersStateSize + kGraphicsPipelineSharedNonVertexInputStateSize;
92 
93 constexpr size_t kPipelineFragmentOutputDescOffset = kGraphicsPipelineShadersStateSize;
94 constexpr size_t kPipelineFragmentOutputDescSize =
95     kGraphicsPipelineSharedNonVertexInputStateSize + kGraphicsPipelineFragmentOutputStateSize;
96 
97 constexpr size_t kPipelineVertexInputDescOffset =
98     kGraphicsPipelineShadersStateSize + kPipelineFragmentOutputDescSize;
99 constexpr size_t kPipelineVertexInputDescSize = kGraphicsPipelineVertexInputStateSize;
100 
101 static_assert(kPipelineShadersDescOffset % kGraphicsPipelineDirtyBitBytes == 0);
102 static_assert(kPipelineShadersDescSize % kGraphicsPipelineDirtyBitBytes == 0);
103 
104 static_assert(kPipelineFragmentOutputDescOffset % kGraphicsPipelineDirtyBitBytes == 0);
105 static_assert(kPipelineFragmentOutputDescSize % kGraphicsPipelineDirtyBitBytes == 0);
106 
107 static_assert(kPipelineVertexInputDescOffset % kGraphicsPipelineDirtyBitBytes == 0);
108 static_assert(kPipelineVertexInputDescSize % kGraphicsPipelineDirtyBitBytes == 0);
109 
110 constexpr GraphicsPipelineTransitionBits kPipelineShadersTransitionBitsMask =
111     GraphicsPipelineTransitionBits::Mask(TransitionBits(kPipelineShadersDescSize) +
112                                          TransitionBits(kPipelineShadersDescOffset)) &
113     ~GraphicsPipelineTransitionBits::Mask(TransitionBits(kPipelineShadersDescOffset));
114 
GraphicsPipelineHasVertexInput(GraphicsPipelineSubset subset)115 bool GraphicsPipelineHasVertexInput(GraphicsPipelineSubset subset)
116 {
117     return subset == GraphicsPipelineSubset::Complete;
118 }
119 
GraphicsPipelineHasShaders(GraphicsPipelineSubset subset)120 bool GraphicsPipelineHasShaders(GraphicsPipelineSubset subset)
121 {
122     return subset == GraphicsPipelineSubset::Complete || subset == GraphicsPipelineSubset::Shaders;
123 }
124 
GraphicsPipelineHasShadersOrFragmentOutput(GraphicsPipelineSubset subset)125 bool GraphicsPipelineHasShadersOrFragmentOutput(GraphicsPipelineSubset subset)
126 {
127     return true;
128 }
129 
GraphicsPipelineHasFragmentOutput(GraphicsPipelineSubset subset)130 bool GraphicsPipelineHasFragmentOutput(GraphicsPipelineSubset subset)
131 {
132     return subset == GraphicsPipelineSubset::Complete;
133 }
134 
PackGLBlendOp(gl::BlendEquationType blendOp)135 uint8_t PackGLBlendOp(gl::BlendEquationType blendOp)
136 {
137     switch (blendOp)
138     {
139         case gl::BlendEquationType::Add:
140             return static_cast<uint8_t>(VK_BLEND_OP_ADD);
141         case gl::BlendEquationType::Subtract:
142             return static_cast<uint8_t>(VK_BLEND_OP_SUBTRACT);
143         case gl::BlendEquationType::ReverseSubtract:
144             return static_cast<uint8_t>(VK_BLEND_OP_REVERSE_SUBTRACT);
145         case gl::BlendEquationType::Min:
146             return static_cast<uint8_t>(VK_BLEND_OP_MIN);
147         case gl::BlendEquationType::Max:
148             return static_cast<uint8_t>(VK_BLEND_OP_MAX);
149         case gl::BlendEquationType::Multiply:
150             return static_cast<uint8_t>(VK_BLEND_OP_MULTIPLY_EXT - VK_BLEND_OP_ZERO_EXT);
151         case gl::BlendEquationType::Screen:
152             return static_cast<uint8_t>(VK_BLEND_OP_SCREEN_EXT - VK_BLEND_OP_ZERO_EXT);
153         case gl::BlendEquationType::Overlay:
154             return static_cast<uint8_t>(VK_BLEND_OP_OVERLAY_EXT - VK_BLEND_OP_ZERO_EXT);
155         case gl::BlendEquationType::Darken:
156             return static_cast<uint8_t>(VK_BLEND_OP_DARKEN_EXT - VK_BLEND_OP_ZERO_EXT);
157         case gl::BlendEquationType::Lighten:
158             return static_cast<uint8_t>(VK_BLEND_OP_LIGHTEN_EXT - VK_BLEND_OP_ZERO_EXT);
159         case gl::BlendEquationType::Colordodge:
160             return static_cast<uint8_t>(VK_BLEND_OP_COLORDODGE_EXT - VK_BLEND_OP_ZERO_EXT);
161         case gl::BlendEquationType::Colorburn:
162             return static_cast<uint8_t>(VK_BLEND_OP_COLORBURN_EXT - VK_BLEND_OP_ZERO_EXT);
163         case gl::BlendEquationType::Hardlight:
164             return static_cast<uint8_t>(VK_BLEND_OP_HARDLIGHT_EXT - VK_BLEND_OP_ZERO_EXT);
165         case gl::BlendEquationType::Softlight:
166             return static_cast<uint8_t>(VK_BLEND_OP_SOFTLIGHT_EXT - VK_BLEND_OP_ZERO_EXT);
167         case gl::BlendEquationType::Difference:
168             return static_cast<uint8_t>(VK_BLEND_OP_DIFFERENCE_EXT - VK_BLEND_OP_ZERO_EXT);
169         case gl::BlendEquationType::Exclusion:
170             return static_cast<uint8_t>(VK_BLEND_OP_EXCLUSION_EXT - VK_BLEND_OP_ZERO_EXT);
171         case gl::BlendEquationType::HslHue:
172             return static_cast<uint8_t>(VK_BLEND_OP_HSL_HUE_EXT - VK_BLEND_OP_ZERO_EXT);
173         case gl::BlendEquationType::HslSaturation:
174             return static_cast<uint8_t>(VK_BLEND_OP_HSL_SATURATION_EXT - VK_BLEND_OP_ZERO_EXT);
175         case gl::BlendEquationType::HslColor:
176             return static_cast<uint8_t>(VK_BLEND_OP_HSL_COLOR_EXT - VK_BLEND_OP_ZERO_EXT);
177         case gl::BlendEquationType::HslLuminosity:
178             return static_cast<uint8_t>(VK_BLEND_OP_HSL_LUMINOSITY_EXT - VK_BLEND_OP_ZERO_EXT);
179         default:
180             UNREACHABLE();
181             return 0;
182     }
183 }
184 
UnpackBlendOp(uint8_t packedBlendOp)185 VkBlendOp UnpackBlendOp(uint8_t packedBlendOp)
186 {
187     if (packedBlendOp <= VK_BLEND_OP_MAX)
188     {
189         return static_cast<VkBlendOp>(packedBlendOp);
190     }
191     return static_cast<VkBlendOp>(packedBlendOp + VK_BLEND_OP_ZERO_EXT);
192 }
193 
PackGLBlendFactor(gl::BlendFactorType blendFactor)194 uint8_t PackGLBlendFactor(gl::BlendFactorType blendFactor)
195 {
196     switch (blendFactor)
197     {
198         case gl::BlendFactorType::Zero:
199             return static_cast<uint8_t>(VK_BLEND_FACTOR_ZERO);
200         case gl::BlendFactorType::One:
201             return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE);
202         case gl::BlendFactorType::SrcColor:
203             return static_cast<uint8_t>(VK_BLEND_FACTOR_SRC_COLOR);
204         case gl::BlendFactorType::DstColor:
205             return static_cast<uint8_t>(VK_BLEND_FACTOR_DST_COLOR);
206         case gl::BlendFactorType::OneMinusSrcColor:
207             return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR);
208         case gl::BlendFactorType::SrcAlpha:
209             return static_cast<uint8_t>(VK_BLEND_FACTOR_SRC_ALPHA);
210         case gl::BlendFactorType::OneMinusSrcAlpha:
211             return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA);
212         case gl::BlendFactorType::DstAlpha:
213             return static_cast<uint8_t>(VK_BLEND_FACTOR_DST_ALPHA);
214         case gl::BlendFactorType::OneMinusDstAlpha:
215             return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA);
216         case gl::BlendFactorType::OneMinusDstColor:
217             return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR);
218         case gl::BlendFactorType::SrcAlphaSaturate:
219             return static_cast<uint8_t>(VK_BLEND_FACTOR_SRC_ALPHA_SATURATE);
220         case gl::BlendFactorType::ConstantColor:
221             return static_cast<uint8_t>(VK_BLEND_FACTOR_CONSTANT_COLOR);
222         case gl::BlendFactorType::ConstantAlpha:
223             return static_cast<uint8_t>(VK_BLEND_FACTOR_CONSTANT_ALPHA);
224         case gl::BlendFactorType::OneMinusConstantColor:
225             return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR);
226         case gl::BlendFactorType::OneMinusConstantAlpha:
227             return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA);
228         case gl::BlendFactorType::Src1Color:
229             return static_cast<uint8_t>(VK_BLEND_FACTOR_SRC1_COLOR);
230         case gl::BlendFactorType::Src1Alpha:
231             return static_cast<uint8_t>(VK_BLEND_FACTOR_SRC1_ALPHA);
232         case gl::BlendFactorType::OneMinusSrc1Color:
233             return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR);
234         case gl::BlendFactorType::OneMinusSrc1Alpha:
235             return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA);
236         default:
237             UNREACHABLE();
238             return 0;
239     }
240 }
241 
242 // A struct that contains render pass information derived from RenderPassDesc.  It contains dynamic
243 // rendering structs that could be directly used when creating pipelines or starting a render pass.
244 // When using render pass objects, the contents are converted to RenderPassInfo.
245 struct DynamicRenderingInfo : angle::NonCopyable
246 {
247     VkRenderingInfo renderingInfo;
248     // Storage for VkRenderingInfo
249     gl::DrawBuffersArray<VkRenderingAttachmentInfo> colorAttachmentInfo;
250     VkRenderingAttachmentInfo depthAttachmentInfo;
251     VkRenderingAttachmentInfo stencilAttachmentInfo;
252 
253     // Attachment formats for VkPipelineRenderingCreateInfo and
254     // VkCommandBufferInheritanceRenderingInfo.
255     gl::DrawBuffersArray<VkFormat> colorAttachmentFormats;
256     VkFormat depthAttachmentFormat;
257     VkFormat stencilAttachmentFormat;
258 
259     // Attachment and input location mapping for VkRenderingAttachmentLocationInfoKHR and
260     // VkRenderingInputAttachmentIndexInfoKHR respectively.
261     gl::DrawBuffersArray<uint32_t> colorAttachmentLocations;
262 
263     // Support for VK_EXT_multisampled_render_to_single_sampled
264     VkMultisampledRenderToSingleSampledInfoEXT msrtss;
265 
266     // Support for VK_KHR_fragment_shading_rate
267     VkRenderingFragmentShadingRateAttachmentInfoKHR fragmentShadingRateInfo;
268 
269 #if defined(ANGLE_PLATFORM_ANDROID)
270     // For VK_ANDROID_external_format_resolve
271     VkExternalFormatANDROID externalFormat;
272 #endif
273 };
274 
UnpackAttachmentInfo(VkImageLayout layout,RenderPassLoadOp loadOp,RenderPassStoreOp storeOp,VkImageLayout resolveLayout,VkResolveModeFlagBits resolveMode,VkRenderingAttachmentInfo * infoOut)275 void UnpackAttachmentInfo(VkImageLayout layout,
276                           RenderPassLoadOp loadOp,
277                           RenderPassStoreOp storeOp,
278                           VkImageLayout resolveLayout,
279                           VkResolveModeFlagBits resolveMode,
280                           VkRenderingAttachmentInfo *infoOut)
281 {
282     *infoOut                    = {};
283     infoOut->sType              = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
284     infoOut->imageLayout        = layout;
285     infoOut->resolveImageLayout = resolveLayout;
286     infoOut->resolveMode        = resolveMode;
287     infoOut->loadOp             = ConvertRenderPassLoadOpToVkLoadOp(loadOp);
288     infoOut->storeOp            = ConvertRenderPassStoreOpToVkStoreOp(storeOp);
289     // The image views and clear values are specified when starting the render pass itself.
290 }
291 
292 enum class DynamicRenderingInfoSubset
293 {
294     // The complete info as needed by vkCmdBeginRendering.
295     Full,
296     // Only the subset that is needed for pipeline creation / inheritance info.  Equivalent to a
297     // compatible render pass.  Note that parts of renderingInfo may still be filled, such as
298     // viewMask etc.
299     Pipeline,
300 };
301 
DeriveRenderingInfo(Renderer * renderer,const RenderPassDesc & desc,DynamicRenderingInfoSubset subset,const gl::Rectangle & renderArea,VkSubpassContents subpassContents,const FramebufferAttachmentsVector<VkImageView> & attachmentViews,const vk::AttachmentOpsArray & ops,const PackedClearValuesArray & clearValues,uint32_t layerCount,DynamicRenderingInfo * infoOut)302 void DeriveRenderingInfo(Renderer *renderer,
303                          const RenderPassDesc &desc,
304                          DynamicRenderingInfoSubset subset,
305                          const gl::Rectangle &renderArea,
306                          VkSubpassContents subpassContents,
307                          const FramebufferAttachmentsVector<VkImageView> &attachmentViews,
308                          const vk::AttachmentOpsArray &ops,
309                          const PackedClearValuesArray &clearValues,
310                          uint32_t layerCount,
311                          DynamicRenderingInfo *infoOut)
312 {
313     ASSERT(renderer->getFeatures().preferDynamicRendering.enabled);
314     // MSRTT cannot be emulated over dynamic rendering.
315     ASSERT(!renderer->getFeatures().enableMultisampledRenderToTexture.enabled ||
316            renderer->getFeatures().supportsMultisampledRenderToSingleSampled.enabled);
317 
318 #if defined(ANGLE_ENABLE_ASSERTS)
319     // Try to catch errors if the entire struct is not filled but uninitialized data is
320     // retrieved later.
321     memset(infoOut, 0xab, sizeof(*infoOut));
322 #endif
323 
324     const bool hasDitheringThroughExtension = desc.isLegacyDitherEnabled();
325     ASSERT(!hasDitheringThroughExtension ||
326            renderer->getFeatures().supportsLegacyDithering.enabled);
327 
328     // renderArea and layerCount are determined when beginning the render pass
329     infoOut->renderingInfo       = {};
330     infoOut->renderingInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO;
331     infoOut->renderingInfo.flags =
332         hasDitheringThroughExtension ? VK_RENDERING_ENABLE_LEGACY_DITHERING_BIT_EXT : 0;
333     if (subpassContents == VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS)
334     {
335         infoOut->renderingInfo.flags |= VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT;
336     }
337 
338     infoOut->renderingInfo.viewMask =
339         desc.viewCount() > 0 ? angle::BitMask<uint32_t>(desc.viewCount()) : 0;
340 
341     // Pack color attachments
342     vk::PackedAttachmentIndex attachmentCount(0);
343     for (uint32_t colorIndexGL = 0; colorIndexGL < desc.colorAttachmentRange(); ++colorIndexGL)
344     {
345         // For dynamic rendering, the mapping of attachments to shader output locations is given in
346         // VkRenderingAttachmentLocationInfoKHR.
347         //
348         // For render pass objects, the mapping is specified by
349         // VkSubpassDescription2::pColorAttachments.
350 
351         if (!desc.isColorAttachmentEnabled(colorIndexGL))
352         {
353             ASSERT(!desc.hasColorResolveAttachment(colorIndexGL));
354             continue;
355         }
356 
357         infoOut->colorAttachmentLocations[attachmentCount.get()] = colorIndexGL;
358 
359         angle::FormatID attachmentFormatID = desc[colorIndexGL];
360         ASSERT(attachmentFormatID != angle::FormatID::NONE);
361         VkFormat attachmentFormat = GetVkFormatFromFormatID(renderer, attachmentFormatID);
362 
363         const bool isYUVExternalFormat = vk::IsYUVExternalFormat(attachmentFormatID);
364 #if defined(ANGLE_PLATFORM_ANDROID)
365         // if yuv, we're going to chain this on to VkCommandBufferInheritanceRenderingInfo and
366         // VkPipelineRenderingCreateInfo (or some VkAttachmentDescription2 if falling back to render
367         // pass objects).
368         if (isYUVExternalFormat)
369         {
370             infoOut->externalFormat = {VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID, nullptr, 0};
371 
372             const vk::ExternalYuvFormatInfo &externalFormatInfo =
373                 renderer->getExternalFormatTable()->getExternalFormatInfo(attachmentFormatID);
374             infoOut->externalFormat.externalFormat = externalFormatInfo.externalFormat;
375             attachmentFormat                       = externalFormatInfo.colorAttachmentFormat;
376         }
377 #endif
378 
379         ASSERT(attachmentFormat != VK_FORMAT_UNDEFINED);
380         infoOut->colorAttachmentFormats[attachmentCount.get()] = attachmentFormat;
381 
382         if (subset == DynamicRenderingInfoSubset::Full)
383         {
384             ASSERT(static_cast<vk::ImageLayout>(ops[attachmentCount].initialLayout) !=
385                        vk::ImageLayout::SharedPresent ||
386                    static_cast<vk::ImageLayout>(ops[attachmentCount].finalLayout) ==
387                        vk::ImageLayout::SharedPresent);
388             const VkImageLayout layout = vk::ConvertImageLayoutToVkImageLayout(
389                 static_cast<vk::ImageLayout>(ops[attachmentCount].initialLayout));
390             const VkImageLayout resolveImageLayout =
391                 (static_cast<vk::ImageLayout>(ops[attachmentCount].finalResolveLayout) ==
392                          vk::ImageLayout::SharedPresent
393                      ? VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR
394                      : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
395             const VkResolveModeFlagBits resolveMode =
396                 isYUVExternalFormat ? VK_RESOLVE_MODE_EXTERNAL_FORMAT_DOWNSAMPLE_ANDROID
397                 : desc.hasColorResolveAttachment(colorIndexGL) ? VK_RESOLVE_MODE_AVERAGE_BIT
398                                                                : VK_RESOLVE_MODE_NONE;
399             const RenderPassLoadOp loadOp =
400                 static_cast<RenderPassLoadOp>(ops[attachmentCount].loadOp);
401             const RenderPassStoreOp storeOp =
402                 static_cast<RenderPassStoreOp>(ops[attachmentCount].storeOp);
403 
404             UnpackAttachmentInfo(layout, loadOp, storeOp, resolveImageLayout, resolveMode,
405                                  &infoOut->colorAttachmentInfo[attachmentCount.get()]);
406 
407             // See description of RenderPassFramebuffer::mImageViews regarding the layout of the
408             // attachmentViews.  In short, the draw attachments are packed, while the resolve
409             // attachments are not.
410             if (isYUVExternalFormat && renderer->nullColorAttachmentWithExternalFormatResolve())
411             {
412                 // If nullColorAttachmentWithExternalFormatResolve is VK_TRUE, attachmentViews has
413                 // no color attachment imageView and only has resolveImageView.
414                 infoOut->colorAttachmentInfo[attachmentCount.get()].imageView = VK_NULL_HANDLE;
415                 infoOut->colorAttachmentInfo[attachmentCount.get()].resolveImageView =
416                     attachmentViews[attachmentCount.get()];
417                 infoOut->colorAttachmentInfo[attachmentCount.get()].clearValue =
418                     clearValues[attachmentCount];
419 
420                 ++attachmentCount;
421                 continue;
422             }
423             infoOut->colorAttachmentInfo[attachmentCount.get()].imageView =
424                 attachmentViews[attachmentCount.get()];
425             if (resolveMode != VK_RESOLVE_MODE_NONE)
426             {
427                 infoOut->colorAttachmentInfo[attachmentCount.get()].resolveImageView =
428                     attachmentViews[RenderPassFramebuffer::kColorResolveAttachmentBegin +
429                                     colorIndexGL];
430             }
431             infoOut->colorAttachmentInfo[attachmentCount.get()].clearValue =
432                 clearValues[attachmentCount];
433         }
434 
435         ++attachmentCount;
436     }
437 
438     infoOut->renderingInfo.colorAttachmentCount = attachmentCount.get();
439     infoOut->renderingInfo.pColorAttachments    = infoOut->colorAttachmentInfo.data();
440 
441     infoOut->depthAttachmentFormat   = VK_FORMAT_UNDEFINED;
442     infoOut->stencilAttachmentFormat = VK_FORMAT_UNDEFINED;
443 
444     // Depth/stencil attachment, if any
445     if (desc.hasDepthStencilAttachment())
446     {
447         const uint32_t depthStencilIndexGL =
448             static_cast<uint32_t>(desc.depthStencilAttachmentIndex());
449 
450         const angle::FormatID attachmentFormatID = desc[depthStencilIndexGL];
451         ASSERT(attachmentFormatID != angle::FormatID::NONE);
452         const angle::Format &angleFormat = angle::Format::Get(attachmentFormatID);
453         const VkFormat attachmentFormat  = GetVkFormatFromFormatID(renderer, attachmentFormatID);
454 
455         infoOut->depthAttachmentFormat =
456             angleFormat.depthBits == 0 ? VK_FORMAT_UNDEFINED : attachmentFormat;
457         infoOut->stencilAttachmentFormat =
458             angleFormat.stencilBits == 0 ? VK_FORMAT_UNDEFINED : attachmentFormat;
459 
460         if (subset == DynamicRenderingInfoSubset::Full)
461         {
462             const bool resolveDepth =
463                 angleFormat.depthBits != 0 && desc.hasDepthResolveAttachment();
464             const bool resolveStencil =
465                 angleFormat.stencilBits != 0 && desc.hasStencilResolveAttachment();
466 
467             const VkImageLayout layout = ConvertImageLayoutToVkImageLayout(
468                 static_cast<vk::ImageLayout>(ops[attachmentCount].initialLayout));
469             const VkImageLayout resolveImageLayout =
470                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
471             const VkResolveModeFlagBits depthResolveMode =
472                 resolveDepth ? VK_RESOLVE_MODE_SAMPLE_ZERO_BIT : VK_RESOLVE_MODE_NONE;
473             const VkResolveModeFlagBits stencilResolveMode =
474                 resolveStencil ? VK_RESOLVE_MODE_SAMPLE_ZERO_BIT : VK_RESOLVE_MODE_NONE;
475             const RenderPassLoadOp loadOp =
476                 static_cast<RenderPassLoadOp>(ops[attachmentCount].loadOp);
477             const RenderPassStoreOp storeOp =
478                 static_cast<RenderPassStoreOp>(ops[attachmentCount].storeOp);
479             const RenderPassLoadOp stencilLoadOp =
480                 static_cast<RenderPassLoadOp>(ops[attachmentCount].stencilLoadOp);
481             const RenderPassStoreOp stencilStoreOp =
482                 static_cast<RenderPassStoreOp>(ops[attachmentCount].stencilStoreOp);
483 
484             UnpackAttachmentInfo(layout, loadOp, storeOp, resolveImageLayout, depthResolveMode,
485                                  &infoOut->depthAttachmentInfo);
486             UnpackAttachmentInfo(layout, stencilLoadOp, stencilStoreOp, resolveImageLayout,
487                                  stencilResolveMode, &infoOut->stencilAttachmentInfo);
488 
489             infoOut->depthAttachmentInfo.imageView = attachmentViews[attachmentCount.get()];
490             if (resolveDepth)
491             {
492                 infoOut->depthAttachmentInfo.resolveImageView =
493                     attachmentViews[RenderPassFramebuffer::kDepthStencilResolveAttachment];
494             }
495             infoOut->depthAttachmentInfo.clearValue = clearValues[attachmentCount];
496 
497             infoOut->stencilAttachmentInfo.imageView = attachmentViews[attachmentCount.get()];
498             if (resolveStencil)
499             {
500                 infoOut->stencilAttachmentInfo.resolveImageView =
501                     attachmentViews[RenderPassFramebuffer::kDepthStencilResolveAttachment];
502             }
503             infoOut->stencilAttachmentInfo.clearValue = clearValues[attachmentCount];
504 
505             infoOut->renderingInfo.pDepthAttachment =
506                 angleFormat.depthBits == 0 ? nullptr : &infoOut->depthAttachmentInfo;
507             infoOut->renderingInfo.pStencilAttachment =
508                 angleFormat.stencilBits == 0 ? nullptr : &infoOut->stencilAttachmentInfo;
509         }
510 
511         ++attachmentCount;
512     }
513 
514     if (subset == DynamicRenderingInfoSubset::Full)
515     {
516         infoOut->renderingInfo.renderArea.offset.x      = static_cast<uint32_t>(renderArea.x);
517         infoOut->renderingInfo.renderArea.offset.y      = static_cast<uint32_t>(renderArea.y);
518         infoOut->renderingInfo.renderArea.extent.width  = static_cast<uint32_t>(renderArea.width);
519         infoOut->renderingInfo.renderArea.extent.height = static_cast<uint32_t>(renderArea.height);
520         infoOut->renderingInfo.layerCount               = layerCount;
521 
522         if (desc.isRenderToTexture())
523         {
524             ASSERT(renderer->getFeatures().supportsMultisampledRenderToSingleSampled.enabled);
525 
526             infoOut->msrtss = {};
527             infoOut->msrtss.sType =
528                 VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT;
529             infoOut->msrtss.multisampledRenderToSingleSampledEnable = true;
530             infoOut->msrtss.rasterizationSamples                    = gl_vk::GetSamples(
531                 desc.samples(), renderer->getFeatures().limitSampleCountTo2.enabled);
532             AddToPNextChain(&infoOut->renderingInfo, &infoOut->msrtss);
533         }
534 
535         // Fragment shading rate attachment, if any
536         if (desc.hasFragmentShadingAttachment())
537         {
538             infoOut->fragmentShadingRateInfo = {};
539             infoOut->fragmentShadingRateInfo.sType =
540                 VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR;
541             infoOut->fragmentShadingRateInfo.imageView = attachmentViews[attachmentCount.get()];
542             infoOut->fragmentShadingRateInfo.imageLayout =
543                 VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;
544             infoOut->fragmentShadingRateInfo.shadingRateAttachmentTexelSize =
545                 renderer->getMaxFragmentShadingRateAttachmentTexelSize();
546 
547             AddToPNextChain(&infoOut->renderingInfo, &infoOut->fragmentShadingRateInfo);
548         }
549     }
550 }
551 
552 enum class ShadersStateSource
553 {
554     ThisPipeline,
555     PipelineLibrary,
556 };
557 
AttachPipelineRenderingInfo(ErrorContext * context,const RenderPassDesc & desc,const DynamicRenderingInfo & renderingInfo,GraphicsPipelineSubset subset,ShadersStateSource shadersSource,VkPipelineRenderingCreateInfoKHR * pipelineRenderingInfoOut,VkRenderingAttachmentLocationInfoKHR * attachmentLocationsOut,VkRenderingInputAttachmentIndexInfoKHR * inputLocationsOut,VkPipelineCreateFlags2CreateInfoKHR * createFlags2,VkGraphicsPipelineCreateInfo * createInfoOut)558 void AttachPipelineRenderingInfo(ErrorContext *context,
559                                  const RenderPassDesc &desc,
560                                  const DynamicRenderingInfo &renderingInfo,
561                                  GraphicsPipelineSubset subset,
562                                  ShadersStateSource shadersSource,
563                                  VkPipelineRenderingCreateInfoKHR *pipelineRenderingInfoOut,
564                                  VkRenderingAttachmentLocationInfoKHR *attachmentLocationsOut,
565                                  VkRenderingInputAttachmentIndexInfoKHR *inputLocationsOut,
566                                  VkPipelineCreateFlags2CreateInfoKHR *createFlags2,
567                                  VkGraphicsPipelineCreateInfo *createInfoOut)
568 {
569     *pipelineRenderingInfoOut          = {};
570     pipelineRenderingInfoOut->sType    = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO;
571     pipelineRenderingInfoOut->viewMask = renderingInfo.renderingInfo.viewMask;
572     // Note: the formats only affect the fragment output subset.
573     if (GraphicsPipelineHasFragmentOutput(subset))
574     {
575         pipelineRenderingInfoOut->colorAttachmentCount =
576             renderingInfo.renderingInfo.colorAttachmentCount;
577         pipelineRenderingInfoOut->pColorAttachmentFormats =
578             renderingInfo.colorAttachmentFormats.data();
579         pipelineRenderingInfoOut->depthAttachmentFormat   = renderingInfo.depthAttachmentFormat;
580         pipelineRenderingInfoOut->stencilAttachmentFormat = renderingInfo.stencilAttachmentFormat;
581     }
582     AddToPNextChain(createInfoOut, pipelineRenderingInfoOut);
583 
584     *attachmentLocationsOut       = {};
585     attachmentLocationsOut->sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_LOCATION_INFO_KHR;
586     attachmentLocationsOut->colorAttachmentCount = renderingInfo.renderingInfo.colorAttachmentCount;
587     attachmentLocationsOut->pColorAttachmentLocations =
588         renderingInfo.colorAttachmentLocations.data();
589     AddToPNextChain(createInfoOut, attachmentLocationsOut);
590 
591     // Note: VkRenderingInputAttachmentIndexInfoKHR only affects the fragment stage subset, and is
592     // needed only when the shaders stage is not coming from a pipeline library (where this mapping
593     // is already specified).
594     if (desc.hasColorFramebufferFetch() && shadersSource == ShadersStateSource::ThisPipeline &&
595         GraphicsPipelineHasShaders(subset))
596     {
597         *inputLocationsOut       = {};
598         inputLocationsOut->sType = VK_STRUCTURE_TYPE_RENDERING_INPUT_ATTACHMENT_INDEX_INFO_KHR;
599         if (desc.hasColorFramebufferFetch())
600         {
601             inputLocationsOut->colorAttachmentCount =
602                 renderingInfo.renderingInfo.colorAttachmentCount;
603             inputLocationsOut->pColorAttachmentInputIndices =
604                 renderingInfo.colorAttachmentLocations.data();
605         }
606         // Note: for depth/stencil, there is no need to explicitly set |pDepthInputAttachmentIndex|,
607         // |pStencilInputAttachmentIndex|.  When NULL, they automatically map to input attachments
608         // without a |InputAttachmentIndex| decoration, which is exactly how ANGLE produces its
609         // SPIR-V.
610 
611         AddToPNextChain(createInfoOut, inputLocationsOut);
612     }
613 
614     if (desc.hasFragmentShadingAttachment())
615     {
616         createInfoOut->flags |=
617             VK_PIPELINE_CREATE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
618     }
619 
620     if (desc.isLegacyDitherEnabled())
621     {
622         ASSERT(context->getFeatures().supportsMaintenance5.enabled);
623         ASSERT(context->getFeatures().supportsLegacyDithering.enabled);
624 
625         *createFlags2       = {};
626         createFlags2->sType = VK_STRUCTURE_TYPE_PIPELINE_CREATE_FLAGS_2_CREATE_INFO_KHR;
627         createFlags2->flags = createInfoOut->flags;
628         createFlags2->flags |= VK_PIPELINE_CREATE_2_ENABLE_LEGACY_DITHERING_BIT_EXT;
629         createInfoOut->flags = 0;
630 
631         AddToPNextChain(createInfoOut, createFlags2);
632     }
633 }
634 
UnpackAttachmentDesc(Renderer * renderer,VkAttachmentDescription2 * desc,angle::FormatID formatID,uint8_t samples,const PackedAttachmentOpsDesc & ops)635 void UnpackAttachmentDesc(Renderer *renderer,
636                           VkAttachmentDescription2 *desc,
637                           angle::FormatID formatID,
638                           uint8_t samples,
639                           const PackedAttachmentOpsDesc &ops)
640 {
641     *desc         = {};
642     desc->sType   = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2;
643     desc->format  = GetVkFormatFromFormatID(renderer, formatID);
644     desc->samples = gl_vk::GetSamples(samples, renderer->getFeatures().limitSampleCountTo2.enabled);
645     desc->loadOp  = ConvertRenderPassLoadOpToVkLoadOp(static_cast<RenderPassLoadOp>(ops.loadOp));
646     desc->storeOp =
647         ConvertRenderPassStoreOpToVkStoreOp(static_cast<RenderPassStoreOp>(ops.storeOp));
648     desc->stencilLoadOp =
649         ConvertRenderPassLoadOpToVkLoadOp(static_cast<RenderPassLoadOp>(ops.stencilLoadOp));
650     desc->stencilStoreOp =
651         ConvertRenderPassStoreOpToVkStoreOp(static_cast<RenderPassStoreOp>(ops.stencilStoreOp));
652     desc->initialLayout =
653         ConvertImageLayoutToVkImageLayout(static_cast<ImageLayout>(ops.initialLayout));
654     desc->finalLayout =
655         ConvertImageLayoutToVkImageLayout(static_cast<ImageLayout>(ops.finalLayout));
656 }
657 
658 struct AttachmentInfo
659 {
660     bool usedAsInputAttachment;
661     bool isInvalidated;
662     // If only one aspect of a depth/stencil image is resolved, the following is used to retain the
663     // other aspect.
664     bool isUnused;
665 };
666 
UnpackColorResolveAttachmentDesc(Renderer * renderer,VkAttachmentDescription2 * desc,angle::FormatID formatID,const AttachmentInfo & info,VkImageLayout initialLayout,VkImageLayout finalLayout)667 void UnpackColorResolveAttachmentDesc(Renderer *renderer,
668                                       VkAttachmentDescription2 *desc,
669                                       angle::FormatID formatID,
670                                       const AttachmentInfo &info,
671                                       VkImageLayout initialLayout,
672                                       VkImageLayout finalLayout)
673 {
674     *desc        = {};
675     desc->sType  = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2;
676     desc->format = GetVkFormatFromFormatID(renderer, formatID);
677 
678     // This function is for color resolve attachments.
679     const angle::Format &angleFormat = angle::Format::Get(formatID);
680     ASSERT(angleFormat.depthBits == 0 && angleFormat.stencilBits == 0);
681 
682     // Resolve attachments always have a sample count of 1.
683     //
684     // If the corresponding color attachment needs to take its initial value from the resolve
685     // attachment (i.e. needs to be unresolved), loadOp needs to be set to LOAD, otherwise it should
686     // be DONT_CARE as it gets overwritten during resolve.
687     //
688     // storeOp should be STORE.  If the attachment is invalidated, it is set to DONT_CARE.
689     desc->samples = VK_SAMPLE_COUNT_1_BIT;
690     desc->loadOp =
691         info.usedAsInputAttachment ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE;
692     desc->storeOp =
693         info.isInvalidated ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE;
694     desc->stencilLoadOp  = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
695     desc->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
696     desc->initialLayout  = initialLayout;
697     desc->finalLayout    = finalLayout;
698 }
699 
UnpackDepthStencilResolveAttachmentDesc(vk::ErrorContext * context,VkAttachmentDescription2 * desc,angle::FormatID formatID,const AttachmentInfo & depthInfo,const AttachmentInfo & stencilInfo)700 void UnpackDepthStencilResolveAttachmentDesc(vk::ErrorContext *context,
701                                              VkAttachmentDescription2 *desc,
702                                              angle::FormatID formatID,
703                                              const AttachmentInfo &depthInfo,
704                                              const AttachmentInfo &stencilInfo)
705 {
706     vk::Renderer *renderer = context->getRenderer();
707     *desc                  = {};
708     desc->sType            = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2;
709     desc->format           = GetVkFormatFromFormatID(renderer, formatID);
710 
711     // This function is for depth/stencil resolve attachment.
712     const angle::Format &angleFormat = angle::Format::Get(formatID);
713     ASSERT(angleFormat.depthBits != 0 || angleFormat.stencilBits != 0);
714 
715     // Missing aspects are folded in isInvalidate parameters, so no need to double check.
716     ASSERT(angleFormat.depthBits > 0 || depthInfo.isInvalidated);
717     ASSERT(angleFormat.stencilBits > 0 || stencilInfo.isInvalidated);
718 
719     const bool supportsLoadStoreOpNone =
720         context->getFeatures().supportsRenderPassLoadStoreOpNone.enabled;
721     const bool supportsStoreOpNone =
722         supportsLoadStoreOpNone || context->getFeatures().supportsRenderPassStoreOpNone.enabled;
723 
724     const VkAttachmentLoadOp preserveLoadOp =
725         supportsLoadStoreOpNone ? VK_ATTACHMENT_LOAD_OP_NONE_EXT : VK_ATTACHMENT_LOAD_OP_LOAD;
726     const VkAttachmentStoreOp preserveStoreOp =
727         supportsStoreOpNone ? VK_ATTACHMENT_STORE_OP_NONE : VK_ATTACHMENT_STORE_OP_STORE;
728 
729     // Similarly to color resolve attachments, sample count is 1, loadOp is LOAD or DONT_CARE based
730     // on whether unresolve is required, and storeOp is STORE or DONT_CARE based on whether the
731     // attachment is invalidated or the aspect exists.
732     desc->samples = VK_SAMPLE_COUNT_1_BIT;
733     if (depthInfo.isUnused)
734     {
735         desc->loadOp  = preserveLoadOp;
736         desc->storeOp = preserveStoreOp;
737     }
738     else
739     {
740         desc->loadOp  = depthInfo.usedAsInputAttachment ? VK_ATTACHMENT_LOAD_OP_LOAD
741                                                         : VK_ATTACHMENT_LOAD_OP_DONT_CARE;
742         desc->storeOp = depthInfo.isInvalidated ? VK_ATTACHMENT_STORE_OP_DONT_CARE
743                                                 : VK_ATTACHMENT_STORE_OP_STORE;
744     }
745     if (stencilInfo.isUnused)
746     {
747         desc->stencilLoadOp  = preserveLoadOp;
748         desc->stencilStoreOp = preserveStoreOp;
749     }
750     else
751     {
752         desc->stencilLoadOp  = stencilInfo.usedAsInputAttachment ? VK_ATTACHMENT_LOAD_OP_LOAD
753                                                                  : VK_ATTACHMENT_LOAD_OP_DONT_CARE;
754         desc->stencilStoreOp = stencilInfo.isInvalidated ? VK_ATTACHMENT_STORE_OP_DONT_CARE
755                                                          : VK_ATTACHMENT_STORE_OP_STORE;
756     }
757     desc->initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
758     desc->finalLayout   = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
759 }
760 
UnpackFragmentShadingRateAttachmentDesc(VkAttachmentDescription2 * desc)761 void UnpackFragmentShadingRateAttachmentDesc(VkAttachmentDescription2 *desc)
762 {
763     *desc                = {};
764     desc->sType          = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2;
765     desc->flags          = 0;
766     desc->format         = VK_FORMAT_R8_UINT;
767     desc->samples        = VK_SAMPLE_COUNT_1_BIT;
768     desc->loadOp         = VK_ATTACHMENT_LOAD_OP_LOAD;
769     desc->storeOp        = VK_ATTACHMENT_STORE_OP_NONE;
770     desc->stencilLoadOp  = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
771     desc->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
772     desc->initialLayout  = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;
773     desc->finalLayout    = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;
774 }
775 
UnpackStencilState(const PackedStencilOpState & packedState,VkStencilOpState * stateOut,bool writeMaskWorkaround)776 void UnpackStencilState(const PackedStencilOpState &packedState,
777                         VkStencilOpState *stateOut,
778                         bool writeMaskWorkaround)
779 {
780     // Any non-zero value works for the purposes of the useNonZeroStencilWriteMaskStaticState driver
781     // bug workaround.
782     constexpr uint32_t kNonZeroWriteMaskForWorkaround = 1;
783 
784     stateOut->failOp      = static_cast<VkStencilOp>(packedState.fail);
785     stateOut->passOp      = static_cast<VkStencilOp>(packedState.pass);
786     stateOut->depthFailOp = static_cast<VkStencilOp>(packedState.depthFail);
787     stateOut->compareOp   = static_cast<VkCompareOp>(packedState.compare);
788     stateOut->compareMask = 0;
789     stateOut->writeMask   = writeMaskWorkaround ? kNonZeroWriteMaskForWorkaround : 0;
790     stateOut->reference   = 0;
791 }
792 
UnpackBlendAttachmentState(const PackedColorBlendAttachmentState & packedState,VkPipelineColorBlendAttachmentState * stateOut)793 void UnpackBlendAttachmentState(const PackedColorBlendAttachmentState &packedState,
794                                 VkPipelineColorBlendAttachmentState *stateOut)
795 {
796     stateOut->srcColorBlendFactor = static_cast<VkBlendFactor>(packedState.srcColorBlendFactor);
797     stateOut->dstColorBlendFactor = static_cast<VkBlendFactor>(packedState.dstColorBlendFactor);
798     stateOut->colorBlendOp        = UnpackBlendOp(packedState.colorBlendOp);
799     stateOut->srcAlphaBlendFactor = static_cast<VkBlendFactor>(packedState.srcAlphaBlendFactor);
800     stateOut->dstAlphaBlendFactor = static_cast<VkBlendFactor>(packedState.dstAlphaBlendFactor);
801     stateOut->alphaBlendOp        = UnpackBlendOp(packedState.alphaBlendOp);
802 }
803 
SetPipelineShaderStageInfo(const VkStructureType type,const VkShaderStageFlagBits stage,const VkShaderModule module,const VkSpecializationInfo & specializationInfo,VkPipelineShaderStageCreateInfo * shaderStage)804 void SetPipelineShaderStageInfo(const VkStructureType type,
805                                 const VkShaderStageFlagBits stage,
806                                 const VkShaderModule module,
807                                 const VkSpecializationInfo &specializationInfo,
808                                 VkPipelineShaderStageCreateInfo *shaderStage)
809 {
810     shaderStage->sType               = type;
811     shaderStage->flags               = 0;
812     shaderStage->stage               = stage;
813     shaderStage->module              = module;
814     shaderStage->pName               = "main";
815     shaderStage->pSpecializationInfo = &specializationInfo;
816 }
817 
818 // Defines a subpass that uses the resolve attachments as input attachments to initialize color and
819 // depth/stencil attachments that need to be "unresolved" at the start of the render pass.  The
820 // subpass will only contain the attachments that need to be unresolved to simplify the shader that
821 // performs the operations.
InitializeUnresolveSubpass(const RenderPassDesc & desc,const gl::DrawBuffersVector<VkAttachmentReference2> & drawSubpassColorAttachmentRefs,const gl::DrawBuffersVector<VkAttachmentReference2> & drawSubpassResolveAttachmentRefs,const VkAttachmentReference2 & depthStencilAttachmentRef,const VkAttachmentReference2 & depthStencilResolveAttachmentRef,gl::DrawBuffersVector<VkAttachmentReference2> * unresolveColorAttachmentRefs,VkAttachmentReference2 * unresolveDepthStencilAttachmentRef,FramebufferAttachmentsVector<VkAttachmentReference2> * unresolveInputAttachmentRefs,FramebufferAttachmentsVector<uint32_t> * unresolvePreserveAttachmentRefs,VkSubpassDescription2 * subpassDesc)822 void InitializeUnresolveSubpass(
823     const RenderPassDesc &desc,
824     const gl::DrawBuffersVector<VkAttachmentReference2> &drawSubpassColorAttachmentRefs,
825     const gl::DrawBuffersVector<VkAttachmentReference2> &drawSubpassResolveAttachmentRefs,
826     const VkAttachmentReference2 &depthStencilAttachmentRef,
827     const VkAttachmentReference2 &depthStencilResolveAttachmentRef,
828     gl::DrawBuffersVector<VkAttachmentReference2> *unresolveColorAttachmentRefs,
829     VkAttachmentReference2 *unresolveDepthStencilAttachmentRef,
830     FramebufferAttachmentsVector<VkAttachmentReference2> *unresolveInputAttachmentRefs,
831     FramebufferAttachmentsVector<uint32_t> *unresolvePreserveAttachmentRefs,
832     VkSubpassDescription2 *subpassDesc)
833 {
834     // Assume the GL Framebuffer has the following attachments enabled:
835     //
836     //     GL Color 0
837     //     GL Color 3
838     //     GL Color 4
839     //     GL Color 6
840     //     GL Color 7
841     //     GL Depth/Stencil
842     //
843     // Additionally, assume Color 0, 4 and 6 are multisampled-render-to-texture (or for any other
844     // reason) have corresponding resolve attachments.  Furthermore, say Color 4 and 6 require an
845     // initial unresolve operation.
846     //
847     // In the above example, the render pass is created with the following attachments:
848     //
849     //     RP Attachment[0] <- corresponding to GL Color 0
850     //     RP Attachment[1] <- corresponding to GL Color 3
851     //     RP Attachment[2] <- corresponding to GL Color 4
852     //     RP Attachment[3] <- corresponding to GL Color 6
853     //     RP Attachment[4] <- corresponding to GL Color 7
854     //     RP Attachment[5] <- corresponding to GL Depth/Stencil
855     //     RP Attachment[6] <- corresponding to resolve attachment of GL Color 0
856     //     RP Attachment[7] <- corresponding to resolve attachment of GL Color 4
857     //     RP Attachment[8] <- corresponding to resolve attachment of GL Color 6
858     //
859     // If the depth/stencil attachment is to be resolved, the following attachment would also be
860     // present:
861     //
862     //     RP Attachment[9] <- corresponding to resolve attachment of GL Depth/Stencil
863     //
864     // The subpass that takes the application draw calls has the following attachments, creating the
865     // mapping from the Vulkan attachment indices (i.e. RP attachment indices) to GL indices as
866     // indicated by the GL shaders:
867     //
868     //     Subpass[1] Color[0] -> RP Attachment[0]
869     //     Subpass[1] Color[1] -> VK_ATTACHMENT_UNUSED
870     //     Subpass[1] Color[2] -> VK_ATTACHMENT_UNUSED
871     //     Subpass[1] Color[3] -> RP Attachment[1]
872     //     Subpass[1] Color[4] -> RP Attachment[2]
873     //     Subpass[1] Color[5] -> VK_ATTACHMENT_UNUSED
874     //     Subpass[1] Color[6] -> RP Attachment[3]
875     //     Subpass[1] Color[7] -> RP Attachment[4]
876     //     Subpass[1] Depth/Stencil -> RP Attachment[5]
877     //     Subpass[1] Resolve[0] -> RP Attachment[6]
878     //     Subpass[1] Resolve[1] -> VK_ATTACHMENT_UNUSED
879     //     Subpass[1] Resolve[2] -> VK_ATTACHMENT_UNUSED
880     //     Subpass[1] Resolve[3] -> VK_ATTACHMENT_UNUSED
881     //     Subpass[1] Resolve[4] -> RP Attachment[7]
882     //     Subpass[1] Resolve[5] -> VK_ATTACHMENT_UNUSED
883     //     Subpass[1] Resolve[6] -> RP Attachment[8]
884     //     Subpass[1] Resolve[7] -> VK_ATTACHMENT_UNUSED
885     //
886     // With depth/stencil resolve attachment:
887     //
888     //     Subpass[1] Depth/Stencil Resolve -> RP Attachment[9]
889     //
890     // The initial subpass that's created here is (remember that in the above example Color 4 and 6
891     // need to be unresolved):
892     //
893     //     Subpass[0] Input[0] -> RP Attachment[7] = Subpass[1] Resolve[4]
894     //     Subpass[0] Input[1] -> RP Attachment[8] = Subpass[1] Resolve[6]
895     //     Subpass[0] Color[0] -> RP Attachment[2] = Subpass[1] Color[4]
896     //     Subpass[0] Color[1] -> RP Attachment[3] = Subpass[1] Color[6]
897     //
898     // The trick here therefore is to use the color attachment refs already created for the
899     // application draw subpass indexed with colorIndexGL.
900     //
901     // If depth/stencil needs to be unresolved (note that as input attachment, it's inserted before
902     // the color attachments.  See UtilsVk::unresolve()):
903     //
904     //     Subpass[0] Input[0]      -> RP Attachment[9] = Subpass[1] Depth/Stencil Resolve
905     //     Subpass[0] Depth/Stencil -> RP Attachment[5] = Subpass[1] Depth/Stencil
906     //
907     // As an additional note, the attachments that are not used in the unresolve subpass must be
908     // preserved.  That is color attachments and the depth/stencil attachment if any.  Resolve
909     // attachments are rewritten by the next subpass, so they don't need to be preserved.  Note that
910     // there's no need to preserve attachments whose loadOp is DONT_CARE.  For simplicity, we
911     // preserve those as well.  The driver would ideally avoid preserving attachments with
912     // loadOp=DONT_CARE.
913     //
914     // With the above example:
915     //
916     //     Subpass[0] Preserve[0] -> RP Attachment[0] = Subpass[1] Color[0]
917     //     Subpass[0] Preserve[1] -> RP Attachment[1] = Subpass[1] Color[3]
918     //     Subpass[0] Preserve[2] -> RP Attachment[4] = Subpass[1] Color[7]
919     //
920     // If depth/stencil is not unresolved:
921     //
922     //     Subpass[0] Preserve[3] -> RP Attachment[5] = Subpass[1] Depth/Stencil
923     //
924     // Again, the color attachment refs already created for the application draw subpass can be used
925     // indexed with colorIndexGL.
926     if (desc.hasDepthStencilUnresolveAttachment())
927     {
928         ASSERT(desc.hasDepthStencilAttachment());
929         ASSERT(desc.hasDepthStencilResolveAttachment());
930 
931         *unresolveDepthStencilAttachmentRef = depthStencilAttachmentRef;
932 
933         VkAttachmentReference2 unresolveDepthStencilInputAttachmentRef = {};
934         unresolveDepthStencilInputAttachmentRef.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2;
935         unresolveDepthStencilInputAttachmentRef.attachment =
936             depthStencilResolveAttachmentRef.attachment;
937         unresolveDepthStencilInputAttachmentRef.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
938 
939         unresolveDepthStencilInputAttachmentRef.aspectMask = 0;
940         if (desc.hasDepthUnresolveAttachment())
941         {
942             unresolveDepthStencilInputAttachmentRef.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
943         }
944         if (desc.hasStencilUnresolveAttachment())
945         {
946             unresolveDepthStencilInputAttachmentRef.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
947         }
948 
949         unresolveInputAttachmentRefs->push_back(unresolveDepthStencilInputAttachmentRef);
950     }
951     else if (desc.hasDepthStencilAttachment())
952     {
953         // Preserve the depth/stencil attachment if not unresolved.  Again, there's no need to
954         // preserve this attachment if loadOp=DONT_CARE, but we do for simplicity.
955         unresolvePreserveAttachmentRefs->push_back(depthStencilAttachmentRef.attachment);
956     }
957 
958     for (uint32_t colorIndexGL = 0; colorIndexGL < desc.colorAttachmentRange(); ++colorIndexGL)
959     {
960         if (!desc.hasColorUnresolveAttachment(colorIndexGL))
961         {
962             if (desc.isColorAttachmentEnabled(colorIndexGL))
963             {
964                 unresolvePreserveAttachmentRefs->push_back(
965                     drawSubpassColorAttachmentRefs[colorIndexGL].attachment);
966             }
967             continue;
968         }
969         ASSERT(desc.isColorAttachmentEnabled(colorIndexGL));
970         ASSERT(desc.hasColorResolveAttachment(colorIndexGL));
971         ASSERT(drawSubpassColorAttachmentRefs[colorIndexGL].attachment != VK_ATTACHMENT_UNUSED);
972         ASSERT(drawSubpassResolveAttachmentRefs[colorIndexGL].attachment != VK_ATTACHMENT_UNUSED);
973 
974         unresolveColorAttachmentRefs->push_back(drawSubpassColorAttachmentRefs[colorIndexGL]);
975         unresolveInputAttachmentRefs->push_back(drawSubpassResolveAttachmentRefs[colorIndexGL]);
976 
977         // Note the input attachment layout should be shader read-only.  The subpass dependency
978         // will take care of transitioning the layout of the resolve attachment to color attachment
979         // automatically.
980         unresolveInputAttachmentRefs->back().layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
981     }
982 
983     ASSERT(!unresolveColorAttachmentRefs->empty() ||
984            unresolveDepthStencilAttachmentRef->attachment != VK_ATTACHMENT_UNUSED);
985     ASSERT(unresolveColorAttachmentRefs->size() +
986                (desc.hasDepthStencilUnresolveAttachment() ? 1 : 0) ==
987            unresolveInputAttachmentRefs->size());
988 
989     subpassDesc->sType                = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2;
990     subpassDesc->pipelineBindPoint    = VK_PIPELINE_BIND_POINT_GRAPHICS;
991     subpassDesc->inputAttachmentCount = static_cast<uint32_t>(unresolveInputAttachmentRefs->size());
992     subpassDesc->pInputAttachments    = unresolveInputAttachmentRefs->data();
993     subpassDesc->colorAttachmentCount = static_cast<uint32_t>(unresolveColorAttachmentRefs->size());
994     subpassDesc->pColorAttachments    = unresolveColorAttachmentRefs->data();
995     subpassDesc->pDepthStencilAttachment = unresolveDepthStencilAttachmentRef;
996     subpassDesc->preserveAttachmentCount =
997         static_cast<uint32_t>(unresolvePreserveAttachmentRefs->size());
998     subpassDesc->pPreserveAttachments = unresolvePreserveAttachmentRefs->data();
999 }
1000 
1001 // There is normally one subpass, and occasionally another for the unresolve operation.
1002 constexpr size_t kSubpassFastVectorSize = 2;
1003 template <typename T>
1004 using SubpassVector = angle::FastVector<T, kSubpassFastVectorSize>;
1005 
InitializeUnresolveSubpassDependencies(const SubpassVector<VkSubpassDescription2> & subpassDesc,bool unresolveColor,bool unresolveDepthStencil,std::vector<VkSubpassDependency2> * subpassDependencies)1006 void InitializeUnresolveSubpassDependencies(const SubpassVector<VkSubpassDescription2> &subpassDesc,
1007                                             bool unresolveColor,
1008                                             bool unresolveDepthStencil,
1009                                             std::vector<VkSubpassDependency2> *subpassDependencies)
1010 {
1011     ASSERT(subpassDesc.size() >= 2);
1012     ASSERT(unresolveColor || unresolveDepthStencil);
1013 
1014     // The unresolve subpass is the first subpass.  The application draw subpass is the next one.
1015     constexpr uint32_t kUnresolveSubpassIndex = 0;
1016     constexpr uint32_t kDrawSubpassIndex      = 1;
1017 
1018     // A subpass dependency is needed between the unresolve and draw subpasses.  There are two
1019     // hazards here:
1020     //
1021     // - Subpass 0 writes to color/depth/stencil attachments, subpass 1 writes to the same
1022     //   attachments.  This is a WaW hazard (color/depth/stencil write -> color/depth/stencil write)
1023     //   similar to when two subsequent render passes write to the same images.
1024     // - Subpass 0 reads from resolve attachments, subpass 1 writes to the same resolve attachments.
1025     //   This is a WaR hazard (fragment shader read -> color write) which only requires an execution
1026     //   barrier.
1027     //
1028     // Note: the DEPENDENCY_BY_REGION flag is necessary to create a "framebuffer-local" dependency,
1029     // as opposed to "framebuffer-global".  The latter is effectively a render pass break.  The
1030     // former creates a dependency per framebuffer region.  If dependency scopes correspond to
1031     // attachments with:
1032     //
1033     // - Same sample count: dependency is at sample granularity
1034     // - Different sample count: dependency is at pixel granularity
1035     //
1036     // The latter is clarified by the spec as such:
1037     //
1038     // > Practically, the pixel vs sample granularity dependency means that if an input attachment
1039     // > has a different number of samples than the pipeline's rasterizationSamples, then a fragment
1040     // > can access any sample in the input attachment's pixel even if it only uses
1041     // > framebuffer-local dependencies.
1042     //
1043     // The dependency for the first hazard above (attachment write -> attachment write) is on
1044     // same-sample attachments, so it will not allow the use of input attachments as required by the
1045     // unresolve subpass.  As a result, even though the second hazard seems to be subsumed by the
1046     // first (its src stage is earlier and its dst stage is the same), a separate dependency is
1047     // created for it just to obtain a pixel granularity dependency.
1048     //
1049     // Note: depth/stencil resolve is considered to be done in the color write stage:
1050     //
1051     // > Moving to the next subpass automatically performs any multisample resolve operations in the
1052     // > subpass being ended. End-of-subpass multisample resolves are treated as color attachment
1053     // > writes for the purposes of synchronization. This applies to resolve operations for both
1054     // > color and depth/stencil attachments. That is, they are considered to execute in the
1055     // > VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT pipeline stage and their writes are
1056     // > synchronized with VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT.
1057 
1058     subpassDependencies->push_back({});
1059     VkSubpassDependency2 *dependency = &subpassDependencies->back();
1060 
1061     constexpr VkPipelineStageFlags kColorWriteStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1062     constexpr VkPipelineStageFlags kColorReadWriteStage =
1063         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1064     constexpr VkAccessFlags kColorWriteFlags = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1065     constexpr VkAccessFlags kColorReadWriteFlags =
1066         kColorWriteFlags | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
1067 
1068     constexpr VkPipelineStageFlags kDepthStencilWriteStage =
1069         VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
1070     constexpr VkPipelineStageFlags kDepthStencilReadWriteStage =
1071         VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
1072     constexpr VkAccessFlags kDepthStencilWriteFlags = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
1073     constexpr VkAccessFlags kDepthStencilReadWriteFlags =
1074         kDepthStencilWriteFlags | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
1075 
1076     VkPipelineStageFlags attachmentWriteStages     = 0;
1077     VkPipelineStageFlags attachmentReadWriteStages = 0;
1078     VkAccessFlags attachmentWriteFlags             = 0;
1079     VkAccessFlags attachmentReadWriteFlags         = 0;
1080 
1081     if (unresolveColor)
1082     {
1083         attachmentWriteStages |= kColorWriteStage;
1084         attachmentReadWriteStages |= kColorReadWriteStage;
1085         attachmentWriteFlags |= kColorWriteFlags;
1086         attachmentReadWriteFlags |= kColorReadWriteFlags;
1087     }
1088 
1089     if (unresolveDepthStencil)
1090     {
1091         attachmentWriteStages |= kDepthStencilWriteStage;
1092         attachmentReadWriteStages |= kDepthStencilReadWriteStage;
1093         attachmentWriteFlags |= kDepthStencilWriteFlags;
1094         attachmentReadWriteFlags |= kDepthStencilReadWriteFlags;
1095     }
1096 
1097     dependency->sType           = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2;
1098     dependency->srcSubpass      = kUnresolveSubpassIndex;
1099     dependency->dstSubpass      = kDrawSubpassIndex;
1100     dependency->srcStageMask    = attachmentWriteStages;
1101     dependency->dstStageMask    = attachmentReadWriteStages;
1102     dependency->srcAccessMask   = attachmentWriteFlags;
1103     dependency->dstAccessMask   = attachmentReadWriteFlags;
1104     dependency->dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
1105 
1106     subpassDependencies->push_back({});
1107     dependency = &subpassDependencies->back();
1108 
1109     // Note again that depth/stencil resolve is considered to be done in the color output stage.
1110     dependency->sType           = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2;
1111     dependency->srcSubpass      = kUnresolveSubpassIndex;
1112     dependency->dstSubpass      = kDrawSubpassIndex;
1113     dependency->srcStageMask    = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
1114     dependency->dstStageMask    = kColorWriteStage;
1115     dependency->srcAccessMask   = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
1116     dependency->dstAccessMask   = kColorWriteFlags;
1117     dependency->dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
1118 }
1119 
1120 // glFramebufferFetchBarrierEXT and glBlendBarrierKHR require a pipeline barrier to be inserted in
1121 // the render pass.  This requires a subpass self-dependency.
1122 //
1123 // For framebuffer fetch:
1124 //
1125 //     srcStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
1126 //     dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
1127 //     srcAccess = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
1128 //     dstAccess = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
1129 //
1130 // For advanced blend:
1131 //
1132 //     srcStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
1133 //     dstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
1134 //     srcAccess = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
1135 //     dstAccess = VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT
1136 //
1137 // Subpass dependencies cannot be added after the fact at the end of the render pass due to render
1138 // pass compatibility rules.  ANGLE specifies a subpass self-dependency with the above stage/access
1139 // masks in preparation of potential framebuffer fetch and advanced blend barriers.  This is known
1140 // not to add any overhead on any hardware we have been able to gather information from.
InitializeDefaultSubpassSelfDependencies(ErrorContext * context,const RenderPassDesc & desc,uint32_t subpassIndex,std::vector<VkSubpassDependency2> * subpassDependencies)1141 void InitializeDefaultSubpassSelfDependencies(
1142     ErrorContext *context,
1143     const RenderPassDesc &desc,
1144     uint32_t subpassIndex,
1145     std::vector<VkSubpassDependency2> *subpassDependencies)
1146 {
1147     Renderer *renderer = context->getRenderer();
1148     const bool hasRasterizationOrderAttachmentAccess =
1149         renderer->getFeatures().supportsRasterizationOrderAttachmentAccess.enabled;
1150     const bool hasBlendOperationAdvanced =
1151         renderer->getFeatures().supportsBlendOperationAdvanced.enabled;
1152     const bool hasCoherentBlendOperationAdvanced =
1153         renderer->getFeatures().supportsBlendOperationAdvancedCoherent.enabled;
1154 
1155     if (hasRasterizationOrderAttachmentAccess &&
1156         (!hasBlendOperationAdvanced || hasCoherentBlendOperationAdvanced))
1157     {
1158         // No need to specify a subpass dependency if VK_EXT_rasterization_order_attachment_access
1159         // is enabled, as that extension makes this subpass dependency implicit.
1160         return;
1161     }
1162 
1163     subpassDependencies->push_back({});
1164     VkSubpassDependency2 *dependency = &subpassDependencies->back();
1165 
1166     dependency->sType         = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2;
1167     dependency->srcSubpass    = subpassIndex;
1168     dependency->dstSubpass    = subpassIndex;
1169     dependency->srcStageMask  = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1170     dependency->dstStageMask  = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1171     dependency->srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1172     dependency->dstAccessMask = 0;
1173     if (!hasRasterizationOrderAttachmentAccess)
1174     {
1175         dependency->dstStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
1176         dependency->dstAccessMask |= VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
1177     }
1178     if (hasBlendOperationAdvanced && !hasCoherentBlendOperationAdvanced)
1179     {
1180         dependency->dstAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT;
1181     }
1182     dependency->dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
1183     if (desc.viewCount() > 0)
1184     {
1185         dependency->dependencyFlags |= VK_DEPENDENCY_VIEW_LOCAL_BIT;
1186     }
1187 }
1188 
InitializeMSRTSS(ErrorContext * context,uint8_t renderToTextureSamples,VkSubpassDescription2 * subpass,VkSubpassDescriptionDepthStencilResolve * msrtssResolve,VkMultisampledRenderToSingleSampledInfoEXT * msrtss)1189 void InitializeMSRTSS(ErrorContext *context,
1190                       uint8_t renderToTextureSamples,
1191                       VkSubpassDescription2 *subpass,
1192                       VkSubpassDescriptionDepthStencilResolve *msrtssResolve,
1193                       VkMultisampledRenderToSingleSampledInfoEXT *msrtss)
1194 {
1195     Renderer *renderer = context->getRenderer();
1196 
1197     ASSERT(renderer->getFeatures().supportsMultisampledRenderToSingleSampled.enabled);
1198 
1199     *msrtssResolve                    = {};
1200     msrtssResolve->sType              = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE;
1201     msrtssResolve->depthResolveMode   = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
1202     msrtssResolve->stencilResolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
1203 
1204     *msrtss       = {};
1205     msrtss->sType = VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT;
1206     msrtss->pNext = msrtssResolve;
1207     msrtss->multisampledRenderToSingleSampledEnable = true;
1208     msrtss->rasterizationSamples                    = gl_vk::GetSamples(
1209         renderToTextureSamples, context->getFeatures().limitSampleCountTo2.enabled);
1210 
1211     // msrtss->pNext is not null so can't use AddToPNextChain
1212     AppendToPNextChain(subpass, msrtss);
1213 }
1214 
SetRenderPassViewMask(ErrorContext * context,const uint32_t * viewMask,VkRenderPassCreateInfo2 * createInfo,SubpassVector<VkSubpassDescription2> * subpassDesc)1215 void SetRenderPassViewMask(ErrorContext *context,
1216                            const uint32_t *viewMask,
1217                            VkRenderPassCreateInfo2 *createInfo,
1218                            SubpassVector<VkSubpassDescription2> *subpassDesc)
1219 {
1220     for (VkSubpassDescription2 &subpass : *subpassDesc)
1221     {
1222         subpass.viewMask = *viewMask;
1223     }
1224 
1225     // For VR, the views are correlated, so this would be an optimization.  However, an
1226     // application can also use multiview for example to render to all 6 faces of a cubemap, in
1227     // which case the views are actually not so correlated.  In the absence of any hints from
1228     // the application, we have to decide on one or the other.  Since VR is more expensive, the
1229     // views are marked as correlated to optimize that use case.
1230     createInfo->correlatedViewMaskCount = 1;
1231     createInfo->pCorrelatedViewMasks    = viewMask;
1232 }
1233 
ToAttachmentDesciption1(const VkAttachmentDescription2 & desc,VkAttachmentDescription * desc1Out)1234 void ToAttachmentDesciption1(const VkAttachmentDescription2 &desc,
1235                              VkAttachmentDescription *desc1Out)
1236 {
1237     ASSERT(desc.pNext == nullptr);
1238 
1239     *desc1Out                = {};
1240     desc1Out->flags          = desc.flags;
1241     desc1Out->format         = desc.format;
1242     desc1Out->samples        = desc.samples;
1243     desc1Out->loadOp         = desc.loadOp;
1244     desc1Out->storeOp        = desc.storeOp;
1245     desc1Out->stencilLoadOp  = desc.stencilLoadOp;
1246     desc1Out->stencilStoreOp = desc.stencilStoreOp;
1247     desc1Out->initialLayout  = desc.initialLayout;
1248     desc1Out->finalLayout    = desc.finalLayout;
1249 }
1250 
ToAttachmentReference1(const VkAttachmentReference2 & ref,VkAttachmentReference * ref1Out)1251 void ToAttachmentReference1(const VkAttachmentReference2 &ref, VkAttachmentReference *ref1Out)
1252 {
1253     ASSERT(ref.pNext == nullptr);
1254 
1255     *ref1Out            = {};
1256     ref1Out->attachment = ref.attachment;
1257     ref1Out->layout     = ref.layout;
1258 }
1259 
ToSubpassDescription1(const VkSubpassDescription2 & desc,const FramebufferAttachmentsVector<VkAttachmentReference> & inputRefs,const gl::DrawBuffersVector<VkAttachmentReference> & colorRefs,const gl::DrawBuffersVector<VkAttachmentReference> & resolveRefs,const VkAttachmentReference & depthStencilRef,VkSubpassDescription * desc1Out)1260 void ToSubpassDescription1(const VkSubpassDescription2 &desc,
1261                            const FramebufferAttachmentsVector<VkAttachmentReference> &inputRefs,
1262                            const gl::DrawBuffersVector<VkAttachmentReference> &colorRefs,
1263                            const gl::DrawBuffersVector<VkAttachmentReference> &resolveRefs,
1264                            const VkAttachmentReference &depthStencilRef,
1265                            VkSubpassDescription *desc1Out)
1266 {
1267     ASSERT(desc.pNext == nullptr);
1268 
1269     *desc1Out                         = {};
1270     desc1Out->flags                   = desc.flags;
1271     desc1Out->pipelineBindPoint       = desc.pipelineBindPoint;
1272     desc1Out->inputAttachmentCount    = static_cast<uint32_t>(inputRefs.size());
1273     desc1Out->pInputAttachments       = !inputRefs.empty() ? inputRefs.data() : nullptr;
1274     desc1Out->colorAttachmentCount    = static_cast<uint32_t>(colorRefs.size());
1275     desc1Out->pColorAttachments       = !colorRefs.empty() ? colorRefs.data() : nullptr;
1276     desc1Out->pResolveAttachments     = !resolveRefs.empty() ? resolveRefs.data() : nullptr;
1277     desc1Out->pDepthStencilAttachment = desc.pDepthStencilAttachment ? &depthStencilRef : nullptr;
1278     desc1Out->preserveAttachmentCount = desc.preserveAttachmentCount;
1279     desc1Out->pPreserveAttachments    = desc.pPreserveAttachments;
1280 }
1281 
ToSubpassDependency1(const VkSubpassDependency2 & dep,VkSubpassDependency * dep1Out)1282 void ToSubpassDependency1(const VkSubpassDependency2 &dep, VkSubpassDependency *dep1Out)
1283 {
1284     ASSERT(dep.pNext == nullptr);
1285 
1286     *dep1Out                 = {};
1287     dep1Out->srcSubpass      = dep.srcSubpass;
1288     dep1Out->dstSubpass      = dep.dstSubpass;
1289     dep1Out->srcStageMask    = dep.srcStageMask;
1290     dep1Out->dstStageMask    = dep.dstStageMask;
1291     dep1Out->srcAccessMask   = dep.srcAccessMask;
1292     dep1Out->dstAccessMask   = dep.dstAccessMask;
1293     dep1Out->dependencyFlags = dep.dependencyFlags;
1294 }
1295 
ToRenderPassMultiviewCreateInfo(const VkRenderPassCreateInfo2 & createInfo,VkRenderPassCreateInfo * createInfo1,SubpassVector<uint32_t> * viewMasks,VkRenderPassMultiviewCreateInfo * multiviewInfo)1296 void ToRenderPassMultiviewCreateInfo(const VkRenderPassCreateInfo2 &createInfo,
1297                                      VkRenderPassCreateInfo *createInfo1,
1298                                      SubpassVector<uint32_t> *viewMasks,
1299                                      VkRenderPassMultiviewCreateInfo *multiviewInfo)
1300 {
1301     ASSERT(createInfo.correlatedViewMaskCount == 1);
1302     const uint32_t viewMask = createInfo.pCorrelatedViewMasks[0];
1303 
1304     viewMasks->resize(createInfo.subpassCount, viewMask);
1305 
1306     multiviewInfo->sType                = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO;
1307     multiviewInfo->subpassCount         = createInfo.subpassCount;
1308     multiviewInfo->pViewMasks           = viewMasks->data();
1309     multiviewInfo->correlationMaskCount = createInfo.correlatedViewMaskCount;
1310     multiviewInfo->pCorrelationMasks    = createInfo.pCorrelatedViewMasks;
1311 
1312     AddToPNextChain(createInfo1, multiviewInfo);
1313 }
1314 
CreateRenderPass1(ErrorContext * context,const VkRenderPassCreateInfo2 & createInfo,uint8_t viewCount,RenderPass * renderPass)1315 angle::Result CreateRenderPass1(ErrorContext *context,
1316                                 const VkRenderPassCreateInfo2 &createInfo,
1317                                 uint8_t viewCount,
1318                                 RenderPass *renderPass)
1319 {
1320     // Convert the attachments to VkAttachmentDescription.
1321     FramebufferAttachmentArray<VkAttachmentDescription> attachmentDescs;
1322     for (uint32_t index = 0; index < createInfo.attachmentCount; ++index)
1323     {
1324         ToAttachmentDesciption1(createInfo.pAttachments[index], &attachmentDescs[index]);
1325     }
1326 
1327     // Convert subpass attachments to VkAttachmentReference and the subpass description to
1328     // VkSubpassDescription.
1329     SubpassVector<FramebufferAttachmentsVector<VkAttachmentReference>> subpassInputAttachmentRefs(
1330         createInfo.subpassCount);
1331     SubpassVector<gl::DrawBuffersVector<VkAttachmentReference>> subpassColorAttachmentRefs(
1332         createInfo.subpassCount);
1333     SubpassVector<gl::DrawBuffersVector<VkAttachmentReference>> subpassResolveAttachmentRefs(
1334         createInfo.subpassCount);
1335     SubpassVector<VkAttachmentReference> subpassDepthStencilAttachmentRefs(createInfo.subpassCount);
1336     SubpassVector<VkSubpassDescription> subpassDescriptions(createInfo.subpassCount);
1337     for (uint32_t subpass = 0; subpass < createInfo.subpassCount; ++subpass)
1338     {
1339         const VkSubpassDescription2 &desc = createInfo.pSubpasses[subpass];
1340         FramebufferAttachmentsVector<VkAttachmentReference> &inputRefs =
1341             subpassInputAttachmentRefs[subpass];
1342         gl::DrawBuffersVector<VkAttachmentReference> &colorRefs =
1343             subpassColorAttachmentRefs[subpass];
1344         gl::DrawBuffersVector<VkAttachmentReference> &resolveRefs =
1345             subpassResolveAttachmentRefs[subpass];
1346         VkAttachmentReference &depthStencilRef = subpassDepthStencilAttachmentRefs[subpass];
1347 
1348         inputRefs.resize(desc.inputAttachmentCount);
1349         colorRefs.resize(desc.colorAttachmentCount);
1350 
1351         for (uint32_t index = 0; index < desc.inputAttachmentCount; ++index)
1352         {
1353             ToAttachmentReference1(desc.pInputAttachments[index], &inputRefs[index]);
1354         }
1355 
1356         for (uint32_t index = 0; index < desc.colorAttachmentCount; ++index)
1357         {
1358             ToAttachmentReference1(desc.pColorAttachments[index], &colorRefs[index]);
1359         }
1360         if (desc.pResolveAttachments)
1361         {
1362             resolveRefs.resize(desc.colorAttachmentCount);
1363             for (uint32_t index = 0; index < desc.colorAttachmentCount; ++index)
1364             {
1365                 ToAttachmentReference1(desc.pResolveAttachments[index], &resolveRefs[index]);
1366             }
1367         }
1368         if (desc.pDepthStencilAttachment)
1369         {
1370             ToAttachmentReference1(*desc.pDepthStencilAttachment, &depthStencilRef);
1371         }
1372 
1373         // Convert subpass itself.
1374         ToSubpassDescription1(desc, inputRefs, colorRefs, resolveRefs, depthStencilRef,
1375                               &subpassDescriptions[subpass]);
1376     }
1377 
1378     // Convert subpass dependencies to VkSubpassDependency.
1379     std::vector<VkSubpassDependency> subpassDependencies(createInfo.dependencyCount);
1380     for (uint32_t index = 0; index < createInfo.dependencyCount; ++index)
1381     {
1382         ToSubpassDependency1(createInfo.pDependencies[index], &subpassDependencies[index]);
1383     }
1384 
1385     // Convert CreateInfo itself
1386     VkRenderPassCreateInfo createInfo1 = {};
1387     createInfo1.sType                  = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
1388     createInfo1.flags                  = createInfo.flags;
1389     createInfo1.attachmentCount        = createInfo.attachmentCount;
1390     createInfo1.pAttachments           = attachmentDescs.data();
1391     createInfo1.subpassCount           = createInfo.subpassCount;
1392     createInfo1.pSubpasses             = subpassDescriptions.data();
1393     createInfo1.dependencyCount        = static_cast<uint32_t>(subpassDependencies.size());
1394     createInfo1.pDependencies = !subpassDependencies.empty() ? subpassDependencies.data() : nullptr;
1395 
1396     SubpassVector<uint32_t> viewMasks;
1397     VkRenderPassMultiviewCreateInfo multiviewInfo = {};
1398     if (viewCount > 0)
1399     {
1400         ToRenderPassMultiviewCreateInfo(createInfo, &createInfo1, &viewMasks, &multiviewInfo);
1401     }
1402 
1403     // Initialize the render pass.
1404     ANGLE_VK_TRY(context, renderPass->init(context->getDevice(), createInfo1));
1405 
1406     return angle::Result::Continue;
1407 }
1408 
UpdateRenderPassColorPerfCounters(const VkRenderPassCreateInfo2 & createInfo,FramebufferAttachmentMask depthStencilAttachmentIndices,RenderPassPerfCounters * countersOut)1409 void UpdateRenderPassColorPerfCounters(const VkRenderPassCreateInfo2 &createInfo,
1410                                        FramebufferAttachmentMask depthStencilAttachmentIndices,
1411                                        RenderPassPerfCounters *countersOut)
1412 {
1413     for (uint32_t index = 0; index < createInfo.attachmentCount; index++)
1414     {
1415         if (depthStencilAttachmentIndices.test(index))
1416         {
1417             continue;
1418         }
1419 
1420         VkAttachmentLoadOp loadOp   = createInfo.pAttachments[index].loadOp;
1421         VkAttachmentStoreOp storeOp = createInfo.pAttachments[index].storeOp;
1422         countersOut->colorLoadOpClears += loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ? 1 : 0;
1423         countersOut->colorLoadOpLoads += loadOp == VK_ATTACHMENT_LOAD_OP_LOAD ? 1 : 0;
1424         countersOut->colorLoadOpNones += loadOp == VK_ATTACHMENT_LOAD_OP_NONE_EXT ? 1 : 0;
1425         countersOut->colorStoreOpStores += storeOp == VK_ATTACHMENT_STORE_OP_STORE ? 1 : 0;
1426         countersOut->colorStoreOpNones += storeOp == VK_ATTACHMENT_STORE_OP_NONE_EXT ? 1 : 0;
1427     }
1428 }
1429 
UpdateSubpassColorPerfCounters(const VkRenderPassCreateInfo2 & createInfo,const VkSubpassDescription2 & subpass,RenderPassPerfCounters * countersOut)1430 void UpdateSubpassColorPerfCounters(const VkRenderPassCreateInfo2 &createInfo,
1431                                     const VkSubpassDescription2 &subpass,
1432                                     RenderPassPerfCounters *countersOut)
1433 {
1434     // Color resolve counters.
1435     if (subpass.pResolveAttachments == nullptr)
1436     {
1437         return;
1438     }
1439 
1440     for (uint32_t colorSubpassIndex = 0; colorSubpassIndex < subpass.colorAttachmentCount;
1441          ++colorSubpassIndex)
1442     {
1443         uint32_t resolveRenderPassIndex = subpass.pResolveAttachments[colorSubpassIndex].attachment;
1444 
1445         if (resolveRenderPassIndex == VK_ATTACHMENT_UNUSED)
1446         {
1447             continue;
1448         }
1449 
1450         ++countersOut->colorAttachmentResolves;
1451     }
1452 }
1453 
UpdateRenderPassDepthStencilPerfCounters(const VkRenderPassCreateInfo2 & createInfo,size_t renderPassIndex,RenderPassPerfCounters * countersOut)1454 void UpdateRenderPassDepthStencilPerfCounters(const VkRenderPassCreateInfo2 &createInfo,
1455                                               size_t renderPassIndex,
1456                                               RenderPassPerfCounters *countersOut)
1457 {
1458     ASSERT(renderPassIndex != VK_ATTACHMENT_UNUSED);
1459 
1460     // Depth/stencil ops counters.
1461     const VkAttachmentDescription2 &ds = createInfo.pAttachments[renderPassIndex];
1462 
1463     countersOut->depthLoadOpClears += ds.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ? 1 : 0;
1464     countersOut->depthLoadOpLoads += ds.loadOp == VK_ATTACHMENT_LOAD_OP_LOAD ? 1 : 0;
1465     countersOut->depthLoadOpNones += ds.loadOp == VK_ATTACHMENT_LOAD_OP_NONE_EXT ? 1 : 0;
1466     countersOut->depthStoreOpStores += ds.storeOp == VK_ATTACHMENT_STORE_OP_STORE ? 1 : 0;
1467     countersOut->depthStoreOpNones += ds.storeOp == VK_ATTACHMENT_STORE_OP_NONE_EXT ? 1 : 0;
1468 
1469     countersOut->stencilLoadOpClears += ds.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ? 1 : 0;
1470     countersOut->stencilLoadOpLoads += ds.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD ? 1 : 0;
1471     countersOut->stencilLoadOpNones += ds.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_NONE_EXT ? 1 : 0;
1472     countersOut->stencilStoreOpStores += ds.stencilStoreOp == VK_ATTACHMENT_STORE_OP_STORE ? 1 : 0;
1473     countersOut->stencilStoreOpNones +=
1474         ds.stencilStoreOp == VK_ATTACHMENT_STORE_OP_NONE_EXT ? 1 : 0;
1475 
1476     // Depth/stencil read-only mode.
1477     countersOut->readOnlyDepthStencil +=
1478         ds.finalLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL ? 1 : 0;
1479 }
1480 
UpdateRenderPassDepthStencilResolvePerfCounters(const VkRenderPassCreateInfo2 & createInfo,const VkSubpassDescriptionDepthStencilResolve & depthStencilResolve,RenderPassPerfCounters * countersOut)1481 void UpdateRenderPassDepthStencilResolvePerfCounters(
1482     const VkRenderPassCreateInfo2 &createInfo,
1483     const VkSubpassDescriptionDepthStencilResolve &depthStencilResolve,
1484     RenderPassPerfCounters *countersOut)
1485 {
1486     if (depthStencilResolve.pDepthStencilResolveAttachment == nullptr)
1487     {
1488         return;
1489     }
1490 
1491     uint32_t resolveRenderPassIndex =
1492         depthStencilResolve.pDepthStencilResolveAttachment->attachment;
1493 
1494     if (resolveRenderPassIndex == VK_ATTACHMENT_UNUSED)
1495     {
1496         return;
1497     }
1498 
1499     const VkAttachmentDescription2 &dsResolve = createInfo.pAttachments[resolveRenderPassIndex];
1500 
1501     // Resolve depth/stencil ops counters.
1502     countersOut->depthLoadOpClears += dsResolve.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ? 1 : 0;
1503     countersOut->depthLoadOpLoads += dsResolve.loadOp == VK_ATTACHMENT_LOAD_OP_LOAD ? 1 : 0;
1504     countersOut->depthStoreOpStores +=
1505         dsResolve.storeOp == static_cast<uint16_t>(RenderPassStoreOp::Store) ? 1 : 0;
1506 
1507     countersOut->stencilLoadOpClears +=
1508         dsResolve.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ? 1 : 0;
1509     countersOut->stencilLoadOpLoads +=
1510         dsResolve.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD ? 1 : 0;
1511     countersOut->stencilStoreOpStores +=
1512         dsResolve.stencilStoreOp == static_cast<uint16_t>(RenderPassStoreOp::Store) ? 1 : 0;
1513 
1514     // Depth/stencil resolve counters.
1515     countersOut->depthAttachmentResolves +=
1516         depthStencilResolve.depthResolveMode != VK_RESOLVE_MODE_NONE ? 1 : 0;
1517     countersOut->stencilAttachmentResolves +=
1518         depthStencilResolve.stencilResolveMode != VK_RESOLVE_MODE_NONE ? 1 : 0;
1519 }
1520 
UpdateRenderPassPerfCounters(const RenderPassDesc & desc,const VkRenderPassCreateInfo2 & createInfo,const VkSubpassDescriptionDepthStencilResolve & depthStencilResolve,RenderPassPerfCounters * countersOut)1521 void UpdateRenderPassPerfCounters(
1522     const RenderPassDesc &desc,
1523     const VkRenderPassCreateInfo2 &createInfo,
1524     const VkSubpassDescriptionDepthStencilResolve &depthStencilResolve,
1525     RenderPassPerfCounters *countersOut)
1526 {
1527     // Accumulate depth/stencil attachment indices in all subpasses to avoid double-counting
1528     // counters.
1529     FramebufferAttachmentMask depthStencilAttachmentIndices;
1530 
1531     for (uint32_t subpassIndex = 0; subpassIndex < createInfo.subpassCount; ++subpassIndex)
1532     {
1533         const VkSubpassDescription2 &subpass = createInfo.pSubpasses[subpassIndex];
1534 
1535         // Color counters.
1536         // NOTE: For simplicity, this will accumulate counts for all subpasses in the renderpass.
1537         UpdateSubpassColorPerfCounters(createInfo, subpass, countersOut);
1538 
1539         // Record index of depth/stencil attachment.
1540         if (subpass.pDepthStencilAttachment != nullptr)
1541         {
1542             uint32_t attachmentRenderPassIndex = subpass.pDepthStencilAttachment->attachment;
1543             if (attachmentRenderPassIndex != VK_ATTACHMENT_UNUSED)
1544             {
1545                 depthStencilAttachmentIndices.set(attachmentRenderPassIndex);
1546             }
1547         }
1548     }
1549 
1550     UpdateRenderPassColorPerfCounters(createInfo, depthStencilAttachmentIndices, countersOut);
1551 
1552     // Depth/stencil counters.  Currently, both subpasses use the same depth/stencil attachment (if
1553     // any).
1554     ASSERT(depthStencilAttachmentIndices.count() <= 1);
1555     for (size_t attachmentRenderPassIndex : depthStencilAttachmentIndices)
1556     {
1557         UpdateRenderPassDepthStencilPerfCounters(createInfo, attachmentRenderPassIndex,
1558                                                  countersOut);
1559     }
1560 
1561     UpdateRenderPassDepthStencilResolvePerfCounters(createInfo, depthStencilResolve, countersOut);
1562 
1563     // Determine unresolve counters from the render pass desc, to avoid making guesses from subpass
1564     // count etc.
1565     countersOut->colorAttachmentUnresolves += desc.getColorUnresolveAttachmentMask().count();
1566     countersOut->depthAttachmentUnresolves += desc.hasDepthUnresolveAttachment() ? 1 : 0;
1567     countersOut->stencilAttachmentUnresolves += desc.hasStencilUnresolveAttachment() ? 1 : 0;
1568 }
1569 
GetRenderPassAndUpdateCounters(ContextVk * contextVk,bool updatePerfCounters,RenderPassHelper * renderPassHelper,const RenderPass ** renderPassOut)1570 void GetRenderPassAndUpdateCounters(ContextVk *contextVk,
1571                                     bool updatePerfCounters,
1572                                     RenderPassHelper *renderPassHelper,
1573                                     const RenderPass **renderPassOut)
1574 {
1575     *renderPassOut = &renderPassHelper->getRenderPass();
1576     if (updatePerfCounters)
1577     {
1578         angle::VulkanPerfCounters &counters      = contextVk->getPerfCounters();
1579         const RenderPassPerfCounters &rpCounters = renderPassHelper->getPerfCounters();
1580 
1581         counters.colorLoadOpClears += rpCounters.colorLoadOpClears;
1582         counters.colorLoadOpLoads += rpCounters.colorLoadOpLoads;
1583         counters.colorLoadOpNones += rpCounters.colorLoadOpNones;
1584         counters.colorStoreOpStores += rpCounters.colorStoreOpStores;
1585         counters.colorStoreOpNones += rpCounters.colorStoreOpNones;
1586         counters.depthLoadOpClears += rpCounters.depthLoadOpClears;
1587         counters.depthLoadOpLoads += rpCounters.depthLoadOpLoads;
1588         counters.depthLoadOpNones += rpCounters.depthLoadOpNones;
1589         counters.depthStoreOpStores += rpCounters.depthStoreOpStores;
1590         counters.depthStoreOpNones += rpCounters.depthStoreOpNones;
1591         counters.stencilLoadOpClears += rpCounters.stencilLoadOpClears;
1592         counters.stencilLoadOpLoads += rpCounters.stencilLoadOpLoads;
1593         counters.stencilLoadOpNones += rpCounters.stencilLoadOpNones;
1594         counters.stencilStoreOpStores += rpCounters.stencilStoreOpStores;
1595         counters.stencilStoreOpNones += rpCounters.stencilStoreOpNones;
1596         counters.colorAttachmentUnresolves += rpCounters.colorAttachmentUnresolves;
1597         counters.colorAttachmentResolves += rpCounters.colorAttachmentResolves;
1598         counters.depthAttachmentUnresolves += rpCounters.depthAttachmentUnresolves;
1599         counters.depthAttachmentResolves += rpCounters.depthAttachmentResolves;
1600         counters.stencilAttachmentUnresolves += rpCounters.stencilAttachmentUnresolves;
1601         counters.stencilAttachmentResolves += rpCounters.stencilAttachmentResolves;
1602         counters.readOnlyDepthStencilRenderPasses += rpCounters.readOnlyDepthStencil;
1603     }
1604 }
1605 
InitializeSpecializationInfo(const SpecializationConstants & specConsts,SpecializationConstantMap<VkSpecializationMapEntry> * specializationEntriesOut,VkSpecializationInfo * specializationInfoOut)1606 void InitializeSpecializationInfo(
1607     const SpecializationConstants &specConsts,
1608     SpecializationConstantMap<VkSpecializationMapEntry> *specializationEntriesOut,
1609     VkSpecializationInfo *specializationInfoOut)
1610 {
1611     // Collect specialization constants.
1612     for (const sh::vk::SpecializationConstantId id :
1613          angle::AllEnums<sh::vk::SpecializationConstantId>())
1614     {
1615         (*specializationEntriesOut)[id].constantID = static_cast<uint32_t>(id);
1616         switch (id)
1617         {
1618             case sh::vk::SpecializationConstantId::SurfaceRotation:
1619                 (*specializationEntriesOut)[id].offset =
1620                     offsetof(SpecializationConstants, surfaceRotation);
1621                 (*specializationEntriesOut)[id].size = sizeof(specConsts.surfaceRotation);
1622                 break;
1623             case sh::vk::SpecializationConstantId::Dither:
1624                 (*specializationEntriesOut)[id].offset =
1625                     offsetof(vk::SpecializationConstants, dither);
1626                 (*specializationEntriesOut)[id].size = sizeof(specConsts.dither);
1627                 break;
1628             default:
1629                 UNREACHABLE();
1630                 break;
1631         }
1632     }
1633 
1634     specializationInfoOut->mapEntryCount = static_cast<uint32_t>(specializationEntriesOut->size());
1635     specializationInfoOut->pMapEntries   = specializationEntriesOut->data();
1636     specializationInfoOut->dataSize      = sizeof(specConsts);
1637     specializationInfoOut->pData         = &specConsts;
1638 }
1639 
1640 // Utility for setting a value on a packed 4-bit integer array.
1641 template <typename SrcT>
Int4Array_Set(uint8_t * arrayBytes,uint32_t arrayIndex,SrcT value)1642 void Int4Array_Set(uint8_t *arrayBytes, uint32_t arrayIndex, SrcT value)
1643 {
1644     uint32_t byteIndex = arrayIndex >> 1;
1645     ASSERT(value < 16);
1646 
1647     if ((arrayIndex & 1) == 0)
1648     {
1649         arrayBytes[byteIndex] &= 0xF0;
1650         arrayBytes[byteIndex] |= static_cast<uint8_t>(value);
1651     }
1652     else
1653     {
1654         arrayBytes[byteIndex] &= 0x0F;
1655         arrayBytes[byteIndex] |= static_cast<uint8_t>(value) << 4;
1656     }
1657 }
1658 
1659 // Utility for getting a value from a packed 4-bit integer array.
1660 template <typename DestT>
Int4Array_Get(const uint8_t * arrayBytes,uint32_t arrayIndex)1661 DestT Int4Array_Get(const uint8_t *arrayBytes, uint32_t arrayIndex)
1662 {
1663     uint32_t byteIndex = arrayIndex >> 1;
1664 
1665     if ((arrayIndex & 1) == 0)
1666     {
1667         return static_cast<DestT>(arrayBytes[byteIndex] & 0xF);
1668     }
1669     else
1670     {
1671         return static_cast<DestT>(arrayBytes[byteIndex] >> 4);
1672     }
1673 }
1674 
1675 // When converting a byte number to a transition bit index we can shift instead of divide.
1676 constexpr size_t kTransitionByteShift = Log2(kGraphicsPipelineDirtyBitBytes);
1677 
1678 // When converting a number of bits offset to a transition bit index we can also shift.
1679 constexpr size_t kBitsPerByte        = 8;
1680 constexpr size_t kTransitionBitShift = kTransitionByteShift + Log2(kBitsPerByte);
1681 
1682 // Helper macro to map from a PipelineDesc struct and field to a dirty bit index.
1683 // Uses the 'offsetof' macro to compute the offset 'Member' within the PipelineDesc.
1684 // We can optimize the dirty bit setting by computing the shifted dirty bit at compile time instead
1685 // of calling "set".
1686 #define ANGLE_GET_TRANSITION_BIT(Member) \
1687     (offsetof(GraphicsPipelineDesc, Member) >> kTransitionByteShift)
1688 
1689 // Indexed dirty bits cannot be entirely computed at compile time since the index is passed to
1690 // the update function.
1691 #define ANGLE_GET_INDEXED_TRANSITION_BIT(Member, Index, BitWidth) \
1692     (((BitWidth * Index) >> kTransitionBitShift) + ANGLE_GET_TRANSITION_BIT(Member))
1693 
1694 constexpr char kDescriptorTypeNameMap[][30] = {"sampler",
1695                                                "combined image sampler",
1696                                                "sampled image",
1697                                                "storage image",
1698                                                "uniform texel buffer",
1699                                                "storage texel buffer",
1700                                                "uniform buffer",
1701                                                "storage buffer",
1702                                                "uniform buffer dynamic",
1703                                                "storage buffer dynamic",
1704                                                "input attachment"};
1705 
1706 // Helpers for creating a readable dump of the graphics pipeline graph.  Each program generates a
1707 // group of nodes.  The group's description is the common state among all nodes.  Each node contains
1708 // the diff with the shared state.  Arrows between nodes indicate the GraphicsPipelineTransitionBits
1709 // that have caused the transition.  State that is 0 is not output for brevity.
1710 enum class PipelineState
1711 {
1712     VertexAttribFormat,
1713     VertexAttribDivisor             = VertexAttribFormat + gl::MAX_VERTEX_ATTRIBS,
1714     VertexAttribOffset              = VertexAttribDivisor + gl::MAX_VERTEX_ATTRIBS,
1715     VertexAttribStride              = VertexAttribOffset + gl::MAX_VERTEX_ATTRIBS,
1716     VertexAttribCompressed          = VertexAttribStride + gl::MAX_VERTEX_ATTRIBS,
1717     VertexAttribShaderComponentType = VertexAttribCompressed + gl::MAX_VERTEX_ATTRIBS,
1718     RenderPassSamples               = VertexAttribShaderComponentType + gl::MAX_VERTEX_ATTRIBS,
1719     RenderPassColorAttachmentRange,
1720     RenderPassViewCount,
1721     RenderPassSrgbWriteControl,
1722     RenderPassHasColorFramebufferFetch,
1723     RenderPassHasDepthStencilFramebufferFetch,
1724     RenderPassIsRenderToTexture,
1725     RenderPassResolveDepth,
1726     RenderPassResolveStencil,
1727     RenderPassUnresolveDepth,
1728     RenderPassUnresolveStencil,
1729     RenderPassColorResolveMask,
1730     RenderPassColorUnresolveMask,
1731     RenderPassColorFormat,
1732     RenderPassDepthStencilFormat = RenderPassColorFormat + gl::IMPLEMENTATION_MAX_DRAW_BUFFERS,
1733     Subpass,
1734     Topology,
1735     PatchVertices,
1736     PrimitiveRestartEnable,
1737     PolygonMode,
1738     CullMode,
1739     FrontFace,
1740     SurfaceRotation,
1741     ViewportNegativeOneToOne,
1742     SampleShadingEnable,
1743     RasterizationSamples,
1744     MinSampleShading,
1745     SampleMask,
1746     AlphaToCoverageEnable,
1747     AlphaToOneEnable,
1748     LogicOpEnable,
1749     LogicOp,
1750     RasterizerDiscardEnable,
1751     ColorWriteMask,
1752     BlendEnableMask = ColorWriteMask + gl::IMPLEMENTATION_MAX_DRAW_BUFFERS,
1753     MissingOutputsMask,
1754     SrcColorBlendFactor,
1755     DstColorBlendFactor   = SrcColorBlendFactor + gl::IMPLEMENTATION_MAX_DRAW_BUFFERS,
1756     ColorBlendOp          = DstColorBlendFactor + gl::IMPLEMENTATION_MAX_DRAW_BUFFERS,
1757     SrcAlphaBlendFactor   = ColorBlendOp + gl::IMPLEMENTATION_MAX_DRAW_BUFFERS,
1758     DstAlphaBlendFactor   = SrcAlphaBlendFactor + gl::IMPLEMENTATION_MAX_DRAW_BUFFERS,
1759     AlphaBlendOp          = DstAlphaBlendFactor + gl::IMPLEMENTATION_MAX_DRAW_BUFFERS,
1760     EmulatedDitherControl = AlphaBlendOp + gl::IMPLEMENTATION_MAX_DRAW_BUFFERS,
1761     DepthClampEnable,
1762     DepthBoundsTest,
1763     DepthCompareOp,
1764     DepthTest,
1765     DepthWrite,
1766     StencilTest,
1767     DepthBiasEnable,
1768     StencilOpFailFront,
1769     StencilOpPassFront,
1770     StencilOpDepthFailFront,
1771     StencilCompareFront,
1772     StencilOpFailBack,
1773     StencilOpPassBack,
1774     StencilOpDepthFailBack,
1775     StencilCompareBack,
1776 
1777     InvalidEnum,
1778     EnumCount = InvalidEnum,
1779 };
1780 
1781 using UnpackedPipelineState = angle::PackedEnumMap<PipelineState, uint32_t>;
1782 using PipelineStateBitSet   = angle::BitSetArray<angle::EnumSize<PipelineState>()>;
1783 
UnpackPipelineState(const GraphicsPipelineDesc & state,GraphicsPipelineSubset subset,UnpackedPipelineState * valuesOut)1784 [[maybe_unused]] void UnpackPipelineState(const GraphicsPipelineDesc &state,
1785                                           GraphicsPipelineSubset subset,
1786                                           UnpackedPipelineState *valuesOut)
1787 {
1788     const bool hasVertexInput             = GraphicsPipelineHasVertexInput(subset);
1789     const bool hasShaders                 = GraphicsPipelineHasShaders(subset);
1790     const bool hasShadersOrFragmentOutput = GraphicsPipelineHasShadersOrFragmentOutput(subset);
1791     const bool hasFragmentOutput          = GraphicsPipelineHasFragmentOutput(subset);
1792 
1793     valuesOut->fill(0);
1794 
1795     if (hasVertexInput)
1796     {
1797         const PipelineVertexInputState &vertexInputState = state.getVertexInputStateForLog();
1798 
1799         const PackedVertexInputAttributes &vertex = vertexInputState.vertex;
1800         uint32_t *vaFormats    = &(*valuesOut)[PipelineState::VertexAttribFormat];
1801         uint32_t *vaDivisors   = &(*valuesOut)[PipelineState::VertexAttribDivisor];
1802         uint32_t *vaOffsets    = &(*valuesOut)[PipelineState::VertexAttribOffset];
1803         uint32_t *vaStrides    = &(*valuesOut)[PipelineState::VertexAttribStride];
1804         uint32_t *vaCompressed = &(*valuesOut)[PipelineState::VertexAttribCompressed];
1805         uint32_t *vaShaderComponentType =
1806             &(*valuesOut)[PipelineState::VertexAttribShaderComponentType];
1807         for (uint32_t attribIndex = 0; attribIndex < gl::MAX_VERTEX_ATTRIBS; ++attribIndex)
1808         {
1809             vaFormats[attribIndex]    = vertex.attribs[attribIndex].format;
1810             vaDivisors[attribIndex]   = vertex.attribs[attribIndex].divisor;
1811             vaOffsets[attribIndex]    = vertex.attribs[attribIndex].offset;
1812             vaStrides[attribIndex]    = vertex.strides[attribIndex];
1813             vaCompressed[attribIndex] = vertex.attribs[attribIndex].compressed;
1814 
1815             gl::ComponentType componentType = gl::GetComponentTypeMask(
1816                 gl::ComponentTypeMask(vertex.shaderAttribComponentType), attribIndex);
1817             vaShaderComponentType[attribIndex] = componentType == gl::ComponentType::InvalidEnum
1818                                                      ? 0
1819                                                      : static_cast<uint32_t>(componentType);
1820         }
1821 
1822         const PackedInputAssemblyState &inputAssembly = vertexInputState.inputAssembly;
1823         (*valuesOut)[PipelineState::Topology]         = inputAssembly.bits.topology;
1824         (*valuesOut)[PipelineState::PrimitiveRestartEnable] =
1825             inputAssembly.bits.primitiveRestartEnable;
1826     }
1827 
1828     if (hasShaders)
1829     {
1830         const PipelineShadersState &shadersState = state.getShadersStateForLog();
1831 
1832         const PackedPreRasterizationAndFragmentStates &shaders = shadersState.shaders;
1833         (*valuesOut)[PipelineState::ViewportNegativeOneToOne] =
1834             shaders.bits.viewportNegativeOneToOne;
1835         (*valuesOut)[PipelineState::DepthClampEnable]        = shaders.bits.depthClampEnable;
1836         (*valuesOut)[PipelineState::PolygonMode]             = shaders.bits.polygonMode;
1837         (*valuesOut)[PipelineState::CullMode]                = shaders.bits.cullMode;
1838         (*valuesOut)[PipelineState::FrontFace]               = shaders.bits.frontFace;
1839         (*valuesOut)[PipelineState::RasterizerDiscardEnable] = shaders.bits.rasterizerDiscardEnable;
1840         (*valuesOut)[PipelineState::DepthBiasEnable]         = shaders.bits.depthBiasEnable;
1841         (*valuesOut)[PipelineState::PatchVertices]           = shaders.bits.patchVertices;
1842         (*valuesOut)[PipelineState::DepthBoundsTest]         = shaders.bits.depthBoundsTest;
1843         (*valuesOut)[PipelineState::DepthTest]               = shaders.bits.depthTest;
1844         (*valuesOut)[PipelineState::DepthWrite]              = shaders.bits.depthWrite;
1845         (*valuesOut)[PipelineState::StencilTest]             = shaders.bits.stencilTest;
1846         (*valuesOut)[PipelineState::DepthCompareOp]          = shaders.bits.depthCompareOp;
1847         (*valuesOut)[PipelineState::SurfaceRotation]         = shaders.bits.surfaceRotation;
1848         (*valuesOut)[PipelineState::EmulatedDitherControl]   = shaders.emulatedDitherControl;
1849         (*valuesOut)[PipelineState::StencilOpFailFront]      = shaders.front.fail;
1850         (*valuesOut)[PipelineState::StencilOpPassFront]      = shaders.front.pass;
1851         (*valuesOut)[PipelineState::StencilOpDepthFailFront] = shaders.front.depthFail;
1852         (*valuesOut)[PipelineState::StencilCompareFront]     = shaders.front.compare;
1853         (*valuesOut)[PipelineState::StencilOpFailBack]       = shaders.back.fail;
1854         (*valuesOut)[PipelineState::StencilOpPassBack]       = shaders.back.pass;
1855         (*valuesOut)[PipelineState::StencilOpDepthFailBack]  = shaders.back.depthFail;
1856         (*valuesOut)[PipelineState::StencilCompareBack]      = shaders.back.compare;
1857     }
1858 
1859     if (hasShadersOrFragmentOutput)
1860     {
1861         const PipelineSharedNonVertexInputState &sharedNonVertexInputState =
1862             state.getSharedNonVertexInputStateForLog();
1863 
1864         const PackedMultisampleAndSubpassState &multisample = sharedNonVertexInputState.multisample;
1865         (*valuesOut)[PipelineState::SampleMask]             = multisample.bits.sampleMask;
1866         (*valuesOut)[PipelineState::RasterizationSamples] =
1867             multisample.bits.rasterizationSamplesMinusOne + 1;
1868         (*valuesOut)[PipelineState::SampleShadingEnable]   = multisample.bits.sampleShadingEnable;
1869         (*valuesOut)[PipelineState::AlphaToCoverageEnable] = multisample.bits.alphaToCoverageEnable;
1870         (*valuesOut)[PipelineState::AlphaToOneEnable]      = multisample.bits.alphaToOneEnable;
1871         (*valuesOut)[PipelineState::Subpass]               = multisample.bits.subpass;
1872         (*valuesOut)[PipelineState::MinSampleShading]      = multisample.bits.minSampleShading;
1873 
1874         const RenderPassDesc renderPass                = sharedNonVertexInputState.renderPass;
1875         (*valuesOut)[PipelineState::RenderPassSamples] = renderPass.samples();
1876         (*valuesOut)[PipelineState::RenderPassColorAttachmentRange] =
1877             static_cast<uint32_t>(renderPass.colorAttachmentRange());
1878         (*valuesOut)[PipelineState::RenderPassViewCount] = renderPass.viewCount();
1879         (*valuesOut)[PipelineState::RenderPassSrgbWriteControl] =
1880             static_cast<uint32_t>(renderPass.getSRGBWriteControlMode());
1881         (*valuesOut)[PipelineState::RenderPassHasColorFramebufferFetch] =
1882             renderPass.hasColorFramebufferFetch();
1883         (*valuesOut)[PipelineState::RenderPassHasDepthStencilFramebufferFetch] =
1884             renderPass.hasDepthStencilFramebufferFetch();
1885         (*valuesOut)[PipelineState::RenderPassIsRenderToTexture] = renderPass.isRenderToTexture();
1886         (*valuesOut)[PipelineState::RenderPassResolveDepth] =
1887             renderPass.hasDepthResolveAttachment();
1888         (*valuesOut)[PipelineState::RenderPassResolveStencil] =
1889             renderPass.hasStencilResolveAttachment();
1890         (*valuesOut)[PipelineState::RenderPassUnresolveDepth] =
1891             renderPass.hasDepthUnresolveAttachment();
1892         (*valuesOut)[PipelineState::RenderPassUnresolveStencil] =
1893             renderPass.hasStencilUnresolveAttachment();
1894         (*valuesOut)[PipelineState::RenderPassColorResolveMask] =
1895             renderPass.getColorResolveAttachmentMask().bits();
1896         (*valuesOut)[PipelineState::RenderPassColorUnresolveMask] =
1897             renderPass.getColorUnresolveAttachmentMask().bits();
1898 
1899         uint32_t *colorFormats = &(*valuesOut)[PipelineState::RenderPassColorFormat];
1900         for (uint32_t colorIndex = 0; colorIndex < renderPass.colorAttachmentRange(); ++colorIndex)
1901         {
1902             colorFormats[colorIndex] = static_cast<uint32_t>(renderPass[colorIndex]);
1903         }
1904         (*valuesOut)[PipelineState::RenderPassDepthStencilFormat] =
1905             static_cast<uint32_t>(renderPass[renderPass.depthStencilAttachmentIndex()]);
1906     }
1907 
1908     if (hasFragmentOutput)
1909     {
1910         const PipelineFragmentOutputState &fragmentOutputState =
1911             state.getFragmentOutputStateForLog();
1912 
1913         const PackedColorBlendState &blend = fragmentOutputState.blend;
1914         uint32_t *colorWriteMasks          = &(*valuesOut)[PipelineState::ColorWriteMask];
1915         uint32_t *srcColorBlendFactors     = &(*valuesOut)[PipelineState::SrcColorBlendFactor];
1916         uint32_t *dstColorBlendFactors     = &(*valuesOut)[PipelineState::DstColorBlendFactor];
1917         uint32_t *colorBlendOps            = &(*valuesOut)[PipelineState::ColorBlendOp];
1918         uint32_t *srcAlphaBlendFactors     = &(*valuesOut)[PipelineState::SrcAlphaBlendFactor];
1919         uint32_t *dstAlphaBlendFactors     = &(*valuesOut)[PipelineState::DstAlphaBlendFactor];
1920         uint32_t *alphaBlendOps            = &(*valuesOut)[PipelineState::AlphaBlendOp];
1921         for (uint32_t colorIndex = 0; colorIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
1922              ++colorIndex)
1923         {
1924             colorWriteMasks[colorIndex] =
1925                 Int4Array_Get<VkColorComponentFlags>(blend.colorWriteMaskBits, colorIndex);
1926 
1927             srcColorBlendFactors[colorIndex] = blend.attachments[colorIndex].srcColorBlendFactor;
1928             dstColorBlendFactors[colorIndex] = blend.attachments[colorIndex].dstColorBlendFactor;
1929             colorBlendOps[colorIndex]        = blend.attachments[colorIndex].colorBlendOp;
1930             srcAlphaBlendFactors[colorIndex] = blend.attachments[colorIndex].srcAlphaBlendFactor;
1931             dstAlphaBlendFactors[colorIndex] = blend.attachments[colorIndex].dstAlphaBlendFactor;
1932             alphaBlendOps[colorIndex]        = blend.attachments[colorIndex].alphaBlendOp;
1933         }
1934 
1935         const PackedBlendMaskAndLogicOpState &blendMaskAndLogic =
1936             fragmentOutputState.blendMaskAndLogic;
1937         (*valuesOut)[PipelineState::BlendEnableMask]    = blendMaskAndLogic.bits.blendEnableMask;
1938         (*valuesOut)[PipelineState::LogicOpEnable]      = blendMaskAndLogic.bits.logicOpEnable;
1939         (*valuesOut)[PipelineState::LogicOp]            = blendMaskAndLogic.bits.logicOp;
1940         (*valuesOut)[PipelineState::MissingOutputsMask] = blendMaskAndLogic.bits.missingOutputsMask;
1941     }
1942 }
1943 
GetCommonPipelineState(const std::vector<UnpackedPipelineState> & pipelines)1944 [[maybe_unused]] PipelineStateBitSet GetCommonPipelineState(
1945     const std::vector<UnpackedPipelineState> &pipelines)
1946 {
1947     PipelineStateBitSet commonState;
1948     commonState.set();
1949 
1950     ASSERT(!pipelines.empty());
1951     const UnpackedPipelineState &firstPipeline = pipelines[0];
1952 
1953     for (const UnpackedPipelineState &pipeline : pipelines)
1954     {
1955         for (size_t stateIndex = 0; stateIndex < firstPipeline.size(); ++stateIndex)
1956         {
1957             if (pipeline.data()[stateIndex] != firstPipeline.data()[stateIndex])
1958             {
1959                 commonState.reset(stateIndex);
1960             }
1961         }
1962     }
1963 
1964     return commonState;
1965 }
1966 
IsPipelineState(size_t stateIndex,PipelineState pipelineState,size_t range)1967 bool IsPipelineState(size_t stateIndex, PipelineState pipelineState, size_t range)
1968 {
1969     size_t pipelineStateAsInt = static_cast<size_t>(pipelineState);
1970 
1971     return stateIndex >= pipelineStateAsInt && stateIndex < pipelineStateAsInt + range;
1972 }
1973 
GetPipelineStateSubIndex(size_t stateIndex,PipelineState pipelineState)1974 size_t GetPipelineStateSubIndex(size_t stateIndex, PipelineState pipelineState)
1975 {
1976     return stateIndex - static_cast<size_t>(pipelineState);
1977 }
1978 
GetPipelineState(size_t stateIndex,bool * isRangedOut,size_t * subIndexOut)1979 PipelineState GetPipelineState(size_t stateIndex, bool *isRangedOut, size_t *subIndexOut)
1980 {
1981     constexpr PipelineState kRangedStates[] = {
1982         PipelineState::VertexAttribFormat,     PipelineState::VertexAttribDivisor,
1983         PipelineState::VertexAttribOffset,     PipelineState::VertexAttribStride,
1984         PipelineState::VertexAttribCompressed, PipelineState::VertexAttribShaderComponentType,
1985         PipelineState::RenderPassColorFormat,  PipelineState::ColorWriteMask,
1986         PipelineState::SrcColorBlendFactor,    PipelineState::DstColorBlendFactor,
1987         PipelineState::ColorBlendOp,           PipelineState::SrcAlphaBlendFactor,
1988         PipelineState::DstAlphaBlendFactor,    PipelineState::AlphaBlendOp,
1989     };
1990 
1991     for (PipelineState ps : kRangedStates)
1992     {
1993         size_t range;
1994         switch (ps)
1995         {
1996             case PipelineState::VertexAttribFormat:
1997             case PipelineState::VertexAttribDivisor:
1998             case PipelineState::VertexAttribOffset:
1999             case PipelineState::VertexAttribStride:
2000             case PipelineState::VertexAttribCompressed:
2001             case PipelineState::VertexAttribShaderComponentType:
2002                 range = gl::MAX_VERTEX_ATTRIBS;
2003                 break;
2004             default:
2005                 range = gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
2006                 break;
2007         }
2008 
2009         if (IsPipelineState(stateIndex, ps, range))
2010         {
2011             *subIndexOut = GetPipelineStateSubIndex(stateIndex, ps);
2012             *isRangedOut = true;
2013             return ps;
2014         }
2015     }
2016 
2017     *isRangedOut = false;
2018     return static_cast<PipelineState>(stateIndex);
2019 }
2020 
OutputPipelineState(std::ostream & out,size_t stateIndex,uint32_t state)2021 [[maybe_unused]] void OutputPipelineState(std::ostream &out, size_t stateIndex, uint32_t state)
2022 {
2023     size_t subIndex             = 0;
2024     bool isRanged               = false;
2025     PipelineState pipelineState = GetPipelineState(stateIndex, &isRanged, &subIndex);
2026 
2027     constexpr angle::PackedEnumMap<PipelineState, const char *> kStateNames = {{
2028         {PipelineState::VertexAttribFormat, "va_format"},
2029         {PipelineState::VertexAttribDivisor, "va_divisor"},
2030         {PipelineState::VertexAttribOffset, "va_offset"},
2031         {PipelineState::VertexAttribStride, "va_stride"},
2032         {PipelineState::VertexAttribCompressed, "va_compressed"},
2033         {PipelineState::VertexAttribShaderComponentType, "va_shader_component_type"},
2034         {PipelineState::RenderPassSamples, "rp_samples"},
2035         {PipelineState::RenderPassColorAttachmentRange, "rp_color_range"},
2036         {PipelineState::RenderPassViewCount, "rp_views"},
2037         {PipelineState::RenderPassSrgbWriteControl, "rp_srgb"},
2038         {PipelineState::RenderPassHasColorFramebufferFetch, "rp_has_color_framebuffer_fetch"},
2039         {PipelineState::RenderPassHasDepthStencilFramebufferFetch,
2040          "rp_has_depth_stencil_framebuffer_fetch"},
2041         {PipelineState::RenderPassIsRenderToTexture, "rp_is_msrtt"},
2042         {PipelineState::RenderPassResolveDepth, "rp_resolve_depth"},
2043         {PipelineState::RenderPassResolveStencil, "rp_resolve_stencil"},
2044         {PipelineState::RenderPassUnresolveDepth, "rp_unresolve_depth"},
2045         {PipelineState::RenderPassUnresolveStencil, "rp_unresolve_stencil"},
2046         {PipelineState::RenderPassColorResolveMask, "rp_resolve_color"},
2047         {PipelineState::RenderPassColorUnresolveMask, "rp_unresolve_color"},
2048         {PipelineState::RenderPassColorFormat, "rp_color"},
2049         {PipelineState::RenderPassDepthStencilFormat, "rp_depth_stencil"},
2050         {PipelineState::Subpass, "subpass"},
2051         {PipelineState::Topology, "topology"},
2052         {PipelineState::PatchVertices, "patch_vertices"},
2053         {PipelineState::PrimitiveRestartEnable, "primitive_restart"},
2054         {PipelineState::PolygonMode, "polygon_mode"},
2055         {PipelineState::CullMode, "cull_mode"},
2056         {PipelineState::FrontFace, "front_face"},
2057         {PipelineState::SurfaceRotation, "rotated_surface"},
2058         {PipelineState::ViewportNegativeOneToOne, "viewport_depth_[-1,1]"},
2059         {PipelineState::SampleShadingEnable, "sample_shading"},
2060         {PipelineState::RasterizationSamples, "rasterization_samples"},
2061         {PipelineState::MinSampleShading, "min_sample_shading"},
2062         {PipelineState::SampleMask, "sample_mask"},
2063         {PipelineState::AlphaToCoverageEnable, "alpha_to_coverage"},
2064         {PipelineState::AlphaToOneEnable, "alpha_to_one"},
2065         {PipelineState::LogicOpEnable, "logic_op_enable"},
2066         {PipelineState::LogicOp, "logic_op"},
2067         {PipelineState::RasterizerDiscardEnable, "rasterization_discard"},
2068         {PipelineState::ColorWriteMask, "color_write"},
2069         {PipelineState::BlendEnableMask, "blend_mask"},
2070         {PipelineState::MissingOutputsMask, "missing_outputs_mask"},
2071         {PipelineState::SrcColorBlendFactor, "src_color_blend"},
2072         {PipelineState::DstColorBlendFactor, "dst_color_blend"},
2073         {PipelineState::ColorBlendOp, "color_blend"},
2074         {PipelineState::SrcAlphaBlendFactor, "src_alpha_blend"},
2075         {PipelineState::DstAlphaBlendFactor, "dst_alpha_blend"},
2076         {PipelineState::AlphaBlendOp, "alpha_blend"},
2077         {PipelineState::EmulatedDitherControl, "dither"},
2078         {PipelineState::DepthClampEnable, "depth_clamp"},
2079         {PipelineState::DepthBoundsTest, "depth_bounds_test"},
2080         {PipelineState::DepthCompareOp, "depth_compare"},
2081         {PipelineState::DepthTest, "depth_test"},
2082         {PipelineState::DepthWrite, "depth_write"},
2083         {PipelineState::StencilTest, "stencil_test"},
2084         {PipelineState::DepthBiasEnable, "depth_bias"},
2085         {PipelineState::StencilOpFailFront, "stencil_front_fail"},
2086         {PipelineState::StencilOpPassFront, "stencil_front_pass"},
2087         {PipelineState::StencilOpDepthFailFront, "stencil_front_depth_fail"},
2088         {PipelineState::StencilCompareFront, "stencil_front_compare"},
2089         {PipelineState::StencilOpFailBack, "stencil_back_fail"},
2090         {PipelineState::StencilOpPassBack, "stencil_back_pass"},
2091         {PipelineState::StencilOpDepthFailBack, "stencil_back_depth_fail"},
2092         {PipelineState::StencilCompareBack, "stencil_back_compare"},
2093     }};
2094 
2095     out << kStateNames[pipelineState];
2096     if (isRanged)
2097     {
2098         out << "_" << subIndex;
2099     }
2100 
2101     switch (pipelineState)
2102     {
2103         // Given that state == 0 produces no output, binary state doesn't require anything but
2104         // its name specified, as it being enabled would be implied.
2105         case PipelineState::VertexAttribCompressed:
2106         case PipelineState::RenderPassSrgbWriteControl:
2107         case PipelineState::RenderPassHasColorFramebufferFetch:
2108         case PipelineState::RenderPassHasDepthStencilFramebufferFetch:
2109         case PipelineState::RenderPassIsRenderToTexture:
2110         case PipelineState::RenderPassResolveDepth:
2111         case PipelineState::RenderPassResolveStencil:
2112         case PipelineState::RenderPassUnresolveDepth:
2113         case PipelineState::RenderPassUnresolveStencil:
2114         case PipelineState::PrimitiveRestartEnable:
2115         case PipelineState::SurfaceRotation:
2116         case PipelineState::ViewportNegativeOneToOne:
2117         case PipelineState::SampleShadingEnable:
2118         case PipelineState::AlphaToCoverageEnable:
2119         case PipelineState::AlphaToOneEnable:
2120         case PipelineState::LogicOpEnable:
2121         case PipelineState::RasterizerDiscardEnable:
2122         case PipelineState::DepthClampEnable:
2123         case PipelineState::DepthBoundsTest:
2124         case PipelineState::DepthTest:
2125         case PipelineState::DepthWrite:
2126         case PipelineState::StencilTest:
2127         case PipelineState::DepthBiasEnable:
2128             break;
2129 
2130         // Special formatting for some state
2131         case PipelineState::VertexAttribShaderComponentType:
2132             out << "=";
2133             switch (state)
2134             {
2135                 case 0:
2136                     static_assert(static_cast<uint32_t>(gl::ComponentType::Float) == 0);
2137                     out << "float";
2138                     break;
2139                 case 1:
2140                     static_assert(static_cast<uint32_t>(gl::ComponentType::Int) == 1);
2141                     out << "int";
2142                     break;
2143                 case 2:
2144                     static_assert(static_cast<uint32_t>(gl::ComponentType::UnsignedInt) == 2);
2145                     out << "uint";
2146                     break;
2147                 case 3:
2148                     static_assert(static_cast<uint32_t>(gl::ComponentType::NoType) == 3);
2149                     out << "none";
2150                     break;
2151                 default:
2152                     UNREACHABLE();
2153             }
2154             break;
2155         case PipelineState::Topology:
2156             out << "=";
2157             switch (state)
2158             {
2159                 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
2160                     out << "points";
2161                     break;
2162                 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
2163                     out << "lines";
2164                     break;
2165                 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
2166                     out << "line_strip";
2167                     break;
2168                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
2169                     out << "tris";
2170                     break;
2171                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
2172                     out << "tri_strip";
2173                     break;
2174                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
2175                     out << "tri_fan";
2176                     break;
2177                 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
2178                     out << "lines_with_adj";
2179                     break;
2180                 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
2181                     out << "line_strip_with_adj";
2182                     break;
2183                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
2184                     out << "tris_with_adj";
2185                     break;
2186                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
2187                     out << "tri_strip_with_adj";
2188                     break;
2189                 case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
2190                     out << "patches";
2191                     break;
2192                 default:
2193                     UNREACHABLE();
2194             }
2195             break;
2196         case PipelineState::PolygonMode:
2197             out << "=";
2198             switch (state)
2199             {
2200                 case VK_POLYGON_MODE_FILL:
2201                     out << "fill";
2202                     break;
2203                 case VK_POLYGON_MODE_LINE:
2204                     out << "line";
2205                     break;
2206                 case VK_POLYGON_MODE_POINT:
2207                     out << "point";
2208                     break;
2209                 default:
2210                     UNREACHABLE();
2211             }
2212             break;
2213         case PipelineState::CullMode:
2214             out << "=";
2215             if ((state & VK_CULL_MODE_FRONT_BIT) != 0)
2216             {
2217                 out << "front";
2218             }
2219             if (state == VK_CULL_MODE_FRONT_AND_BACK)
2220             {
2221                 out << "+";
2222             }
2223             if ((state & VK_CULL_MODE_BACK_BIT) != 0)
2224             {
2225                 out << "back";
2226             }
2227             break;
2228         case PipelineState::FrontFace:
2229             out << "=" << (state == VK_FRONT_FACE_COUNTER_CLOCKWISE ? "ccw" : "cw");
2230             break;
2231         case PipelineState::MinSampleShading:
2232             out << "=" << (static_cast<float>(state) / kMinSampleShadingScale);
2233             break;
2234         case PipelineState::SrcColorBlendFactor:
2235         case PipelineState::DstColorBlendFactor:
2236         case PipelineState::SrcAlphaBlendFactor:
2237         case PipelineState::DstAlphaBlendFactor:
2238             out << "=";
2239             switch (state)
2240             {
2241                 case VK_BLEND_FACTOR_ZERO:
2242                     out << "0";
2243                     break;
2244                 case VK_BLEND_FACTOR_ONE:
2245                     out << "1";
2246                     break;
2247                 case VK_BLEND_FACTOR_SRC_COLOR:
2248                     out << "sc";
2249                     break;
2250                 case VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR:
2251                     out << "1-sc";
2252                     break;
2253                 case VK_BLEND_FACTOR_DST_COLOR:
2254                     out << "dc";
2255                     break;
2256                 case VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR:
2257                     out << "1-dc";
2258                     break;
2259                 case VK_BLEND_FACTOR_SRC_ALPHA:
2260                     out << "sa";
2261                     break;
2262                 case VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA:
2263                     out << "1-sa";
2264                     break;
2265                 case VK_BLEND_FACTOR_DST_ALPHA:
2266                     out << "da";
2267                     break;
2268                 case VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA:
2269                     out << "1-da";
2270                     break;
2271                 case VK_BLEND_FACTOR_CONSTANT_COLOR:
2272                     out << "const_color";
2273                     break;
2274                 case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR:
2275                     out << "1-const_color";
2276                     break;
2277                 case VK_BLEND_FACTOR_CONSTANT_ALPHA:
2278                     out << "const_alpha";
2279                     break;
2280                 case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA:
2281                     out << "1-const_alpha";
2282                     break;
2283                 case VK_BLEND_FACTOR_SRC_ALPHA_SATURATE:
2284                     out << "sat(sa)";
2285                     break;
2286                 case VK_BLEND_FACTOR_SRC1_COLOR:
2287                     out << "sc1";
2288                     break;
2289                 case VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR:
2290                     out << "1-sc1";
2291                     break;
2292                 case VK_BLEND_FACTOR_SRC1_ALPHA:
2293                     out << "sa1";
2294                     break;
2295                 case VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA:
2296                     out << "1-sa1";
2297                     break;
2298                 default:
2299                     UNREACHABLE();
2300             }
2301             break;
2302         case PipelineState::ColorBlendOp:
2303         case PipelineState::AlphaBlendOp:
2304             out << "=";
2305             switch (UnpackBlendOp(static_cast<uint8_t>(state)))
2306             {
2307                 case VK_BLEND_OP_ADD:
2308                     out << "add";
2309                     break;
2310                 case VK_BLEND_OP_SUBTRACT:
2311                     out << "sub";
2312                     break;
2313                 case VK_BLEND_OP_REVERSE_SUBTRACT:
2314                     out << "reverse_sub";
2315                     break;
2316                 case VK_BLEND_OP_MIN:
2317                     out << "min";
2318                     break;
2319                 case VK_BLEND_OP_MAX:
2320                     out << "max";
2321                     break;
2322                 case VK_BLEND_OP_MULTIPLY_EXT:
2323                     out << "multiply";
2324                     break;
2325                 case VK_BLEND_OP_SCREEN_EXT:
2326                     out << "screen";
2327                     break;
2328                 case VK_BLEND_OP_OVERLAY_EXT:
2329                     out << "overlay";
2330                     break;
2331                 case VK_BLEND_OP_DARKEN_EXT:
2332                     out << "darken";
2333                     break;
2334                 case VK_BLEND_OP_LIGHTEN_EXT:
2335                     out << "lighten";
2336                     break;
2337                 case VK_BLEND_OP_COLORDODGE_EXT:
2338                     out << "dodge";
2339                     break;
2340                 case VK_BLEND_OP_COLORBURN_EXT:
2341                     out << "burn";
2342                     break;
2343                 case VK_BLEND_OP_HARDLIGHT_EXT:
2344                     out << "hardlight";
2345                     break;
2346                 case VK_BLEND_OP_SOFTLIGHT_EXT:
2347                     out << "softlight";
2348                     break;
2349                 case VK_BLEND_OP_DIFFERENCE_EXT:
2350                     out << "difference";
2351                     break;
2352                 case VK_BLEND_OP_EXCLUSION_EXT:
2353                     out << "exclusion";
2354                     break;
2355                 case VK_BLEND_OP_HSL_HUE_EXT:
2356                     out << "hsl_hue";
2357                     break;
2358                 case VK_BLEND_OP_HSL_SATURATION_EXT:
2359                     out << "hsl_sat";
2360                     break;
2361                 case VK_BLEND_OP_HSL_COLOR_EXT:
2362                     out << "hsl_color";
2363                     break;
2364                 case VK_BLEND_OP_HSL_LUMINOSITY_EXT:
2365                     out << "hsl_lum";
2366                     break;
2367                 default:
2368                     UNREACHABLE();
2369             }
2370             break;
2371         case PipelineState::DepthCompareOp:
2372         case PipelineState::StencilCompareFront:
2373         case PipelineState::StencilCompareBack:
2374             out << "=";
2375             switch (state)
2376             {
2377                 case VK_COMPARE_OP_NEVER:
2378                     out << "never";
2379                     break;
2380                 case VK_COMPARE_OP_LESS:
2381                     out << "'<'";
2382                     break;
2383                 case VK_COMPARE_OP_EQUAL:
2384                     out << "'='";
2385                     break;
2386                 case VK_COMPARE_OP_LESS_OR_EQUAL:
2387                     out << "'<='";
2388                     break;
2389                 case VK_COMPARE_OP_GREATER:
2390                     out << "'>'";
2391                     break;
2392                 case VK_COMPARE_OP_NOT_EQUAL:
2393                     out << "'!='";
2394                     break;
2395                 case VK_COMPARE_OP_GREATER_OR_EQUAL:
2396                     out << "'>='";
2397                     break;
2398                 case VK_COMPARE_OP_ALWAYS:
2399                     out << "always";
2400                     break;
2401                 default:
2402                     UNREACHABLE();
2403             }
2404             break;
2405         case PipelineState::StencilOpFailFront:
2406         case PipelineState::StencilOpPassFront:
2407         case PipelineState::StencilOpDepthFailFront:
2408         case PipelineState::StencilOpFailBack:
2409         case PipelineState::StencilOpPassBack:
2410         case PipelineState::StencilOpDepthFailBack:
2411             out << "=";
2412             switch (state)
2413             {
2414                 case VK_STENCIL_OP_KEEP:
2415                     out << "keep";
2416                     break;
2417                 case VK_STENCIL_OP_ZERO:
2418                     out << "0";
2419                     break;
2420                 case VK_STENCIL_OP_REPLACE:
2421                     out << "replace";
2422                     break;
2423                 case VK_STENCIL_OP_INCREMENT_AND_CLAMP:
2424                     out << "clamp++";
2425                     break;
2426                 case VK_STENCIL_OP_DECREMENT_AND_CLAMP:
2427                     out << "clamp--";
2428                     break;
2429                 case VK_STENCIL_OP_INVERT:
2430                     out << "'~'";
2431                     break;
2432                 case VK_STENCIL_OP_INCREMENT_AND_WRAP:
2433                     out << "wrap++";
2434                     break;
2435                 case VK_STENCIL_OP_DECREMENT_AND_WRAP:
2436                     out << "wrap--";
2437                     break;
2438                 default:
2439                     UNREACHABLE();
2440             }
2441             break;
2442 
2443         // Some state output the value as hex because they are bitmasks
2444         case PipelineState::RenderPassColorResolveMask:
2445         case PipelineState::RenderPassColorUnresolveMask:
2446         case PipelineState::SampleMask:
2447         case PipelineState::ColorWriteMask:
2448         case PipelineState::BlendEnableMask:
2449         case PipelineState::MissingOutputsMask:
2450         case PipelineState::EmulatedDitherControl:
2451             out << "=0x" << std::hex << state << std::dec;
2452             break;
2453 
2454         // The rest will simply output the state value
2455         default:
2456             out << "=" << state;
2457             break;
2458     }
2459 
2460     out << "\\n";
2461 }
2462 
OutputAllPipelineState(ErrorContext * context,std::ostream & out,const UnpackedPipelineState & pipeline,GraphicsPipelineSubset subset,const PipelineStateBitSet & include,bool isCommonState)2463 [[maybe_unused]] void OutputAllPipelineState(ErrorContext *context,
2464                                              std::ostream &out,
2465                                              const UnpackedPipelineState &pipeline,
2466                                              GraphicsPipelineSubset subset,
2467                                              const PipelineStateBitSet &include,
2468                                              bool isCommonState)
2469 {
2470     // Default non-existing state to 0, so they are automatically not output as
2471     // UnpackedPipelineState also sets them to 0.
2472     const bool hasVertexInput             = GraphicsPipelineHasVertexInput(subset);
2473     const bool hasShaders                 = GraphicsPipelineHasShaders(subset);
2474     const bool hasShadersOrFragmentOutput = GraphicsPipelineHasShadersOrFragmentOutput(subset);
2475     const bool hasFragmentOutput          = GraphicsPipelineHasFragmentOutput(subset);
2476 
2477     const angle::PackedEnumMap<PipelineState, uint32_t> kDefaultState = {{
2478         // Vertex input state
2479         {PipelineState::VertexAttribFormat,
2480          hasVertexInput
2481              ? static_cast<uint32_t>(GetCurrentValueFormatID(gl::VertexAttribType::Float))
2482              : 0},
2483         {PipelineState::VertexAttribDivisor, 0},
2484         {PipelineState::VertexAttribOffset, 0},
2485         {PipelineState::VertexAttribStride, 0},
2486         {PipelineState::VertexAttribCompressed, 0},
2487         {PipelineState::VertexAttribShaderComponentType, 0},
2488         {PipelineState::Topology, hasVertexInput ? VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST : 0},
2489         {PipelineState::PrimitiveRestartEnable, 0},
2490 
2491         // Shaders state
2492         {PipelineState::ViewportNegativeOneToOne,
2493          hasShaders && context->getFeatures().supportsDepthClipControl.enabled},
2494         {PipelineState::DepthClampEnable, 0},
2495         {PipelineState::PolygonMode, hasShaders ? VK_POLYGON_MODE_FILL : 0},
2496         {PipelineState::CullMode, hasShaders ? VK_CULL_MODE_NONE : 0},
2497         {PipelineState::FrontFace, hasShaders ? VK_FRONT_FACE_COUNTER_CLOCKWISE : 0},
2498         {PipelineState::RasterizerDiscardEnable, 0},
2499         {PipelineState::DepthBiasEnable, 0},
2500         {PipelineState::PatchVertices, hasShaders ? 3 : 0},
2501         {PipelineState::DepthBoundsTest, 0},
2502         {PipelineState::DepthTest, 0},
2503         {PipelineState::DepthWrite, 0},
2504         {PipelineState::StencilTest, 0},
2505         {PipelineState::DepthCompareOp, hasShaders ? VK_COMPARE_OP_LESS : 0},
2506         {PipelineState::SurfaceRotation, 0},
2507         {PipelineState::EmulatedDitherControl, 0},
2508         {PipelineState::StencilOpFailFront, hasShaders ? VK_STENCIL_OP_KEEP : 0},
2509         {PipelineState::StencilOpPassFront, hasShaders ? VK_STENCIL_OP_KEEP : 0},
2510         {PipelineState::StencilOpDepthFailFront, hasShaders ? VK_STENCIL_OP_KEEP : 0},
2511         {PipelineState::StencilCompareFront, hasShaders ? VK_COMPARE_OP_ALWAYS : 0},
2512         {PipelineState::StencilOpFailBack, hasShaders ? VK_STENCIL_OP_KEEP : 0},
2513         {PipelineState::StencilOpPassBack, hasShaders ? VK_STENCIL_OP_KEEP : 0},
2514         {PipelineState::StencilOpDepthFailBack, hasShaders ? VK_STENCIL_OP_KEEP : 0},
2515         {PipelineState::StencilCompareBack, hasShaders ? VK_COMPARE_OP_ALWAYS : 0},
2516 
2517         // Shared shaders and fragment output state
2518         {PipelineState::SampleMask,
2519          hasShadersOrFragmentOutput ? std::numeric_limits<uint16_t>::max() : 0},
2520         {PipelineState::RasterizationSamples, hasShadersOrFragmentOutput ? 1 : 0},
2521         {PipelineState::SampleShadingEnable, 0},
2522         {PipelineState::MinSampleShading, hasShadersOrFragmentOutput ? kMinSampleShadingScale : 0},
2523         {PipelineState::AlphaToCoverageEnable, 0},
2524         {PipelineState::AlphaToOneEnable, 0},
2525         {PipelineState::RenderPassSamples, hasShadersOrFragmentOutput ? 1 : 0},
2526         {PipelineState::RenderPassColorAttachmentRange, 0},
2527         {PipelineState::RenderPassViewCount, 0},
2528         {PipelineState::RenderPassSrgbWriteControl, 0},
2529         {PipelineState::RenderPassHasColorFramebufferFetch, 0},
2530         {PipelineState::RenderPassHasDepthStencilFramebufferFetch, 0},
2531         {PipelineState::RenderPassIsRenderToTexture, 0},
2532         {PipelineState::RenderPassResolveDepth, 0},
2533         {PipelineState::RenderPassResolveStencil, 0},
2534         {PipelineState::RenderPassUnresolveDepth, 0},
2535         {PipelineState::RenderPassUnresolveStencil, 0},
2536         {PipelineState::RenderPassColorResolveMask, 0},
2537         {PipelineState::RenderPassColorUnresolveMask, 0},
2538         {PipelineState::RenderPassColorFormat, 0},
2539         {PipelineState::RenderPassDepthStencilFormat, 0},
2540         {PipelineState::Subpass, 0},
2541 
2542         // Fragment output state
2543         {PipelineState::ColorWriteMask, 0},
2544         {PipelineState::SrcColorBlendFactor, hasFragmentOutput ? VK_BLEND_FACTOR_ONE : 0},
2545         {PipelineState::DstColorBlendFactor, hasFragmentOutput ? VK_BLEND_FACTOR_ZERO : 0},
2546         {PipelineState::ColorBlendOp, hasFragmentOutput ? VK_BLEND_OP_ADD : 0},
2547         {PipelineState::SrcAlphaBlendFactor, hasFragmentOutput ? VK_BLEND_FACTOR_ONE : 0},
2548         {PipelineState::DstAlphaBlendFactor, hasFragmentOutput ? VK_BLEND_FACTOR_ZERO : 0},
2549         {PipelineState::AlphaBlendOp, hasFragmentOutput ? VK_BLEND_OP_ADD : 0},
2550         {PipelineState::BlendEnableMask, 0},
2551         {PipelineState::LogicOpEnable, 0},
2552         {PipelineState::LogicOp, hasFragmentOutput ? VK_LOGIC_OP_COPY : 0},
2553         {PipelineState::MissingOutputsMask, 0},
2554     }};
2555 
2556     bool anyStateOutput = false;
2557     for (size_t stateIndex : include)
2558     {
2559         size_t subIndex             = 0;
2560         bool isRanged               = false;
2561         PipelineState pipelineState = GetPipelineState(stateIndex, &isRanged, &subIndex);
2562 
2563         const uint32_t state = pipeline.data()[stateIndex];
2564         if (state != kDefaultState[pipelineState])
2565         {
2566             OutputPipelineState(out, stateIndex, state);
2567             anyStateOutput = true;
2568         }
2569     }
2570 
2571     if (!isCommonState)
2572     {
2573         out << "(" << (anyStateOutput ? "+" : "") << "common state)\\n";
2574     }
2575 }
2576 
2577 template <typename Hash>
DumpPipelineCacheGraph(ErrorContext * context,const std::unordered_map<GraphicsPipelineDesc,PipelineHelper,Hash,typename GraphicsPipelineCacheTypeHelper<Hash>::KeyEqual> & cache)2578 void DumpPipelineCacheGraph(
2579     ErrorContext *context,
2580     const std::unordered_map<GraphicsPipelineDesc,
2581                              PipelineHelper,
2582                              Hash,
2583                              typename GraphicsPipelineCacheTypeHelper<Hash>::KeyEqual> &cache)
2584 {
2585     constexpr GraphicsPipelineSubset kSubset = GraphicsPipelineCacheTypeHelper<Hash>::kSubset;
2586 
2587     std::ostream &out = context->getRenderer()->getPipelineCacheGraphStream();
2588 
2589     static std::atomic<uint32_t> sCacheSerial(0);
2590     angle::HashMap<GraphicsPipelineDesc, uint32_t, Hash,
2591                    typename GraphicsPipelineCacheTypeHelper<Hash>::KeyEqual>
2592         descToId;
2593 
2594     uint32_t cacheSerial = sCacheSerial.fetch_add(1);
2595     uint32_t descId      = 0;
2596 
2597     // Unpack pipeline states
2598     std::vector<UnpackedPipelineState> pipelines(cache.size());
2599     for (const auto &descAndPipeline : cache)
2600     {
2601         UnpackPipelineState(descAndPipeline.first, kSubset, &pipelines[descId++]);
2602     }
2603 
2604     // Extract common state between all pipelines.
2605     PipelineStateBitSet commonState = GetCommonPipelineState(pipelines);
2606     PipelineStateBitSet nodeState   = ~commonState;
2607 
2608     const char *subsetDescription = "";
2609     const char *subsetTag         = "";
2610     switch (kSubset)
2611     {
2612         case GraphicsPipelineSubset::Shaders:
2613             subsetDescription = "(shaders)\\n";
2614             subsetTag         = "S_";
2615             break;
2616         default:
2617             break;
2618     }
2619 
2620     out << " subgraph cluster_" << subsetTag << cacheSerial << "{\n";
2621     out << "  label=\"Program " << cacheSerial << "\\n"
2622         << subsetDescription << "\\nCommon state:\\n";
2623     OutputAllPipelineState(context, out, pipelines[0], kSubset, commonState, true);
2624     out << "\";\n";
2625 
2626     descId = 0;
2627     for (const auto &descAndPipeline : cache)
2628     {
2629         const GraphicsPipelineDesc &desc = descAndPipeline.first;
2630 
2631         const char *style        = "";
2632         const char *feedbackDesc = "";
2633         switch (descAndPipeline.second.getCacheLookUpFeedback())
2634         {
2635             case CacheLookUpFeedback::Hit:
2636                 // Default is green already
2637                 break;
2638             case CacheLookUpFeedback::Miss:
2639                 style = "[color=red]";
2640                 break;
2641             case CacheLookUpFeedback::LinkedDrawHit:
2642                 // Default is green already
2643                 style        = "[style=dotted]";
2644                 feedbackDesc = "(linked)\\n";
2645                 break;
2646             case CacheLookUpFeedback::LinkedDrawMiss:
2647                 style        = "[style=dotted,color=red]";
2648                 feedbackDesc = "(linked)\\n";
2649                 break;
2650             case CacheLookUpFeedback::WarmUpHit:
2651                 // Default is green already
2652                 style        = "[style=dashed]";
2653                 feedbackDesc = "(warm up)\\n";
2654                 break;
2655             case CacheLookUpFeedback::WarmUpMiss:
2656                 style        = "[style=dashed,color=red]";
2657                 feedbackDesc = "(warm up)\\n";
2658                 break;
2659             case CacheLookUpFeedback::UtilsHit:
2660                 style        = "[color=yellow]";
2661                 feedbackDesc = "(utils)\\n";
2662                 break;
2663             case CacheLookUpFeedback::UtilsMiss:
2664                 style        = "[color=purple]";
2665                 feedbackDesc = "(utils)\\n";
2666                 break;
2667             default:
2668                 // No feedback available
2669                 break;
2670         }
2671 
2672         out << "  p" << subsetTag << cacheSerial << "_" << descId << "[label=\"Pipeline " << descId
2673             << "\\n"
2674             << feedbackDesc << "\\n";
2675         OutputAllPipelineState(context, out, pipelines[descId], kSubset, nodeState, false);
2676         out << "\"]" << style << ";\n";
2677 
2678         descToId[desc] = descId++;
2679     }
2680     for (const auto &descAndPipeline : cache)
2681     {
2682         const GraphicsPipelineDesc &desc     = descAndPipeline.first;
2683         const PipelineHelper &pipelineHelper = descAndPipeline.second;
2684         const std::vector<GraphicsPipelineTransition> &transitions =
2685             pipelineHelper.getTransitions();
2686 
2687         for (const GraphicsPipelineTransition &transition : transitions)
2688         {
2689 #if defined(ANGLE_IS_64_BIT_CPU)
2690             const uint64_t transitionBits = transition.bits.bits();
2691 #else
2692             const uint64_t transitionBits =
2693                 static_cast<uint64_t>(transition.bits.bits(1)) << 32 | transition.bits.bits(0);
2694 #endif
2695             out << "  p" << subsetTag << cacheSerial << "_" << descToId[desc] << " -> p"
2696                 << subsetTag << cacheSerial << "_" << descToId[*transition.desc] << " [label=\"'0x"
2697                 << std::hex << transitionBits << std::dec << "'\"];\n";
2698         }
2699     }
2700     out << " }\n";
2701 }
2702 
2703 // Used by SharedCacheKeyManager
MakeInvalidCachedObject(SharedFramebufferCacheKey * cacheKeyOut)2704 void MakeInvalidCachedObject(SharedFramebufferCacheKey *cacheKeyOut)
2705 {
2706     *cacheKeyOut = SharedFramebufferCacheKey::MakeShared(VK_NULL_HANDLE);
2707     // So that it will mark as invalid.
2708     (*cacheKeyOut)->destroy(VK_NULL_HANDLE);
2709 }
2710 
MakeInvalidCachedObject(SharedDescriptorSetCacheKey * cacheKeyOut)2711 void MakeInvalidCachedObject(SharedDescriptorSetCacheKey *cacheKeyOut)
2712 {
2713     *cacheKeyOut = SharedDescriptorSetCacheKey::MakeShared(VK_NULL_HANDLE);
2714 }
2715 
ShouldDumpPipelineCacheGraph(ErrorContext * context)2716 bool ShouldDumpPipelineCacheGraph(ErrorContext *context)
2717 {
2718     return kDumpPipelineCacheGraph && context->getRenderer()->isPipelineCacheGraphDumpEnabled();
2719 }
2720 }  // anonymous namespace
2721 
GetProgramFramebufferFetchMode(const gl::ProgramExecutable * executable)2722 FramebufferFetchMode GetProgramFramebufferFetchMode(const gl::ProgramExecutable *executable)
2723 {
2724     if (executable == nullptr)
2725     {
2726         return FramebufferFetchMode::None;
2727     }
2728 
2729     const bool hasColorFramebufferFetch = executable->usesColorFramebufferFetch();
2730     const bool hasDepthStencilFramebufferFetch =
2731         executable->usesDepthFramebufferFetch() || executable->usesStencilFramebufferFetch();
2732 
2733     if (hasDepthStencilFramebufferFetch)
2734     {
2735         return hasColorFramebufferFetch ? FramebufferFetchMode::ColorAndDepthStencil
2736                                         : FramebufferFetchMode::DepthStencil;
2737     }
2738     else
2739     {
2740         return hasColorFramebufferFetch ? FramebufferFetchMode::Color : FramebufferFetchMode::None;
2741     }
2742 }
2743 
GetGraphicsPipelineTransitionBitsMask(GraphicsPipelineSubset subset)2744 GraphicsPipelineTransitionBits GetGraphicsPipelineTransitionBitsMask(GraphicsPipelineSubset subset)
2745 {
2746     if (subset == GraphicsPipelineSubset::Shaders)
2747     {
2748         return kPipelineShadersTransitionBitsMask;
2749     }
2750 
2751     ASSERT(subset == GraphicsPipelineSubset::Complete);
2752 
2753     GraphicsPipelineTransitionBits allBits;
2754     allBits.set();
2755 
2756     return allBits;
2757 }
2758 
2759 // RenderPassDesc implementation.
RenderPassDesc()2760 RenderPassDesc::RenderPassDesc()
2761 {
2762     memset(this, 0, sizeof(RenderPassDesc));
2763 }
2764 
2765 RenderPassDesc::~RenderPassDesc() = default;
2766 
RenderPassDesc(const RenderPassDesc & other)2767 RenderPassDesc::RenderPassDesc(const RenderPassDesc &other)
2768 {
2769     memcpy(this, &other, sizeof(RenderPassDesc));
2770 }
2771 
packColorAttachment(size_t colorIndexGL,angle::FormatID formatID)2772 void RenderPassDesc::packColorAttachment(size_t colorIndexGL, angle::FormatID formatID)
2773 {
2774     ASSERT(colorIndexGL < mAttachmentFormats.size());
2775     static_assert(angle::kNumANGLEFormats < std::numeric_limits<uint8_t>::max(),
2776                   "Too many ANGLE formats to fit in uint8_t");
2777     // Force the user to pack the depth/stencil attachment last.
2778     ASSERT(!hasDepthStencilAttachment());
2779     // This function should only be called for enabled GL color attachments.
2780     ASSERT(formatID != angle::FormatID::NONE);
2781 
2782     uint8_t &packedFormat = mAttachmentFormats[colorIndexGL];
2783     SetBitField(packedFormat, formatID);
2784 
2785     // Set color attachment range such that it covers the range from index 0 through last active
2786     // index.  This is the reasons why we need depth/stencil to be packed last.
2787     SetBitField(mColorAttachmentRange, std::max<size_t>(mColorAttachmentRange, colorIndexGL + 1));
2788 }
2789 
packColorAttachmentGap(size_t colorIndexGL)2790 void RenderPassDesc::packColorAttachmentGap(size_t colorIndexGL)
2791 {
2792     ASSERT(colorIndexGL < mAttachmentFormats.size());
2793     static_assert(angle::kNumANGLEFormats < std::numeric_limits<uint8_t>::max(),
2794                   "Too many ANGLE formats to fit in uint8_t");
2795     // Force the user to pack the depth/stencil attachment last.
2796     ASSERT(!hasDepthStencilAttachment());
2797 
2798     // Use NONE as a flag for gaps in GL color attachments.
2799     uint8_t &packedFormat = mAttachmentFormats[colorIndexGL];
2800     SetBitField(packedFormat, angle::FormatID::NONE);
2801 }
2802 
packDepthStencilAttachment(angle::FormatID formatID)2803 void RenderPassDesc::packDepthStencilAttachment(angle::FormatID formatID)
2804 {
2805     ASSERT(!hasDepthStencilAttachment());
2806 
2807     size_t index = depthStencilAttachmentIndex();
2808     ASSERT(index < mAttachmentFormats.size());
2809 
2810     uint8_t &packedFormat = mAttachmentFormats[index];
2811     SetBitField(packedFormat, formatID);
2812 }
2813 
packColorResolveAttachment(size_t colorIndexGL)2814 void RenderPassDesc::packColorResolveAttachment(size_t colorIndexGL)
2815 {
2816     ASSERT(isColorAttachmentEnabled(colorIndexGL));
2817     ASSERT(!mColorResolveAttachmentMask.test(colorIndexGL));
2818     ASSERT(mSamples > 1);
2819     mColorResolveAttachmentMask.set(colorIndexGL);
2820 }
2821 
packYUVResolveAttachment(size_t colorIndexGL)2822 void RenderPassDesc::packYUVResolveAttachment(size_t colorIndexGL)
2823 {
2824     ASSERT(isColorAttachmentEnabled(colorIndexGL));
2825     ASSERT(!mColorResolveAttachmentMask.test(colorIndexGL));
2826     mColorResolveAttachmentMask.set(colorIndexGL);
2827     SetBitField(mIsYUVResolve, 1);
2828 }
2829 
removeColorResolveAttachment(size_t colorIndexGL)2830 void RenderPassDesc::removeColorResolveAttachment(size_t colorIndexGL)
2831 {
2832     ASSERT(mColorResolveAttachmentMask.test(colorIndexGL));
2833     mColorResolveAttachmentMask.reset(colorIndexGL);
2834 }
2835 
packColorUnresolveAttachment(size_t colorIndexGL)2836 void RenderPassDesc::packColorUnresolveAttachment(size_t colorIndexGL)
2837 {
2838     mColorUnresolveAttachmentMask.set(colorIndexGL);
2839 }
2840 
removeColorUnresolveAttachment(size_t colorIndexGL)2841 void RenderPassDesc::removeColorUnresolveAttachment(size_t colorIndexGL)
2842 {
2843     mColorUnresolveAttachmentMask.reset(colorIndexGL);
2844 }
2845 
packDepthResolveAttachment()2846 void RenderPassDesc::packDepthResolveAttachment()
2847 {
2848     ASSERT(hasDepthStencilAttachment());
2849     ASSERT(!hasDepthResolveAttachment());
2850 
2851     mResolveDepth = true;
2852 }
2853 
packStencilResolveAttachment()2854 void RenderPassDesc::packStencilResolveAttachment()
2855 {
2856     ASSERT(hasDepthStencilAttachment());
2857     ASSERT(!hasStencilResolveAttachment());
2858 
2859     mResolveStencil = true;
2860 }
2861 
packDepthUnresolveAttachment()2862 void RenderPassDesc::packDepthUnresolveAttachment()
2863 {
2864     ASSERT(hasDepthStencilAttachment());
2865 
2866     mUnresolveDepth = true;
2867 }
2868 
packStencilUnresolveAttachment()2869 void RenderPassDesc::packStencilUnresolveAttachment()
2870 {
2871     ASSERT(hasDepthStencilAttachment());
2872 
2873     mUnresolveStencil = true;
2874 }
2875 
removeDepthStencilUnresolveAttachment()2876 void RenderPassDesc::removeDepthStencilUnresolveAttachment()
2877 {
2878     mUnresolveDepth   = false;
2879     mUnresolveStencil = false;
2880 }
2881 
getPackedColorAttachmentIndex(size_t colorIndexGL)2882 PackedAttachmentIndex RenderPassDesc::getPackedColorAttachmentIndex(size_t colorIndexGL)
2883 {
2884     ASSERT(colorIndexGL < colorAttachmentRange());
2885     ASSERT(isColorAttachmentEnabled(colorIndexGL));
2886 
2887     vk::PackedAttachmentIndex colorIndexVk(0);
2888     for (uint32_t index = 0; index < colorIndexGL; ++index)
2889     {
2890         if (isColorAttachmentEnabled(index))
2891         {
2892             ++colorIndexVk;
2893         }
2894     }
2895 
2896     return colorIndexVk;
2897 }
2898 
operator =(const RenderPassDesc & other)2899 RenderPassDesc &RenderPassDesc::operator=(const RenderPassDesc &other)
2900 {
2901     memcpy(this, &other, sizeof(RenderPassDesc));
2902     return *this;
2903 }
2904 
setWriteControlMode(gl::SrgbWriteControlMode mode)2905 void RenderPassDesc::setWriteControlMode(gl::SrgbWriteControlMode mode)
2906 {
2907     SetBitField(mSrgbWriteControl, mode);
2908 }
2909 
hash() const2910 size_t RenderPassDesc::hash() const
2911 {
2912     return angle::ComputeGenericHash(*this);
2913 }
2914 
isColorAttachmentEnabled(size_t colorIndexGL) const2915 bool RenderPassDesc::isColorAttachmentEnabled(size_t colorIndexGL) const
2916 {
2917     angle::FormatID formatID = operator[](colorIndexGL);
2918     return formatID != angle::FormatID::NONE;
2919 }
2920 
hasDepthStencilAttachment() const2921 bool RenderPassDesc::hasDepthStencilAttachment() const
2922 {
2923     angle::FormatID formatID = operator[](depthStencilAttachmentIndex());
2924     return formatID != angle::FormatID::NONE;
2925 }
2926 
clearableAttachmentCount() const2927 size_t RenderPassDesc::clearableAttachmentCount() const
2928 {
2929     size_t colorAttachmentCount = 0;
2930     for (size_t i = 0; i < mColorAttachmentRange; ++i)
2931     {
2932         colorAttachmentCount += isColorAttachmentEnabled(i);
2933     }
2934 
2935     // Note that there are no gaps in depth/stencil attachments.  In fact there is a maximum of 1 of
2936     // it + 1 for its resolve attachment.
2937     size_t depthStencilCount        = hasDepthStencilAttachment() ? 1 : 0;
2938     size_t depthStencilResolveCount = hasDepthStencilResolveAttachment() ? 1 : 0;
2939     return colorAttachmentCount + mColorResolveAttachmentMask.count() + depthStencilCount +
2940            depthStencilResolveCount;
2941 }
2942 
attachmentCount() const2943 size_t RenderPassDesc::attachmentCount() const
2944 {
2945     return clearableAttachmentCount() + (hasFragmentShadingAttachment() ? 1 : 0);
2946 }
2947 
setLegacyDither(bool enabled)2948 void RenderPassDesc::setLegacyDither(bool enabled)
2949 {
2950     SetBitField(mLegacyDitherEnabled, enabled ? 1 : 0);
2951 }
2952 
beginRenderPass(ErrorContext * context,PrimaryCommandBuffer * primary,const RenderPass & renderPass,VkFramebuffer framebuffer,const gl::Rectangle & renderArea,VkSubpassContents subpassContents,PackedClearValuesArray & clearValues,const VkRenderPassAttachmentBeginInfo * attachmentBeginInfo) const2953 void RenderPassDesc::beginRenderPass(
2954     ErrorContext *context,
2955     PrimaryCommandBuffer *primary,
2956     const RenderPass &renderPass,
2957     VkFramebuffer framebuffer,
2958     const gl::Rectangle &renderArea,
2959     VkSubpassContents subpassContents,
2960     PackedClearValuesArray &clearValues,
2961     const VkRenderPassAttachmentBeginInfo *attachmentBeginInfo) const
2962 {
2963     VkRenderPassBeginInfo beginInfo    = {};
2964     beginInfo.sType                    = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
2965     beginInfo.pNext                    = attachmentBeginInfo;
2966     beginInfo.renderPass               = renderPass.getHandle();
2967     beginInfo.framebuffer              = framebuffer;
2968     beginInfo.renderArea.offset.x      = static_cast<uint32_t>(renderArea.x);
2969     beginInfo.renderArea.offset.y      = static_cast<uint32_t>(renderArea.y);
2970     beginInfo.renderArea.extent.width  = static_cast<uint32_t>(renderArea.width);
2971     beginInfo.renderArea.extent.height = static_cast<uint32_t>(renderArea.height);
2972     beginInfo.clearValueCount          = static_cast<uint32_t>(clearableAttachmentCount());
2973     beginInfo.pClearValues             = clearValues.data();
2974 
2975     primary->beginRenderPass(beginInfo, subpassContents);
2976 }
2977 
beginRendering(ErrorContext * context,PrimaryCommandBuffer * primary,const gl::Rectangle & renderArea,VkSubpassContents subpassContents,const FramebufferAttachmentsVector<VkImageView> & attachmentViews,const AttachmentOpsArray & ops,PackedClearValuesArray & clearValues,uint32_t layerCount) const2978 void RenderPassDesc::beginRendering(
2979     ErrorContext *context,
2980     PrimaryCommandBuffer *primary,
2981     const gl::Rectangle &renderArea,
2982     VkSubpassContents subpassContents,
2983     const FramebufferAttachmentsVector<VkImageView> &attachmentViews,
2984     const AttachmentOpsArray &ops,
2985     PackedClearValuesArray &clearValues,
2986     uint32_t layerCount) const
2987 {
2988     DynamicRenderingInfo info;
2989     DeriveRenderingInfo(context->getRenderer(), *this, DynamicRenderingInfoSubset::Full, renderArea,
2990                         subpassContents, attachmentViews, ops, clearValues, layerCount, &info);
2991 
2992     primary->beginRendering(info.renderingInfo);
2993 
2994     VkRenderingAttachmentLocationInfoKHR attachmentLocations = {};
2995     attachmentLocations.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_LOCATION_INFO_KHR;
2996     attachmentLocations.colorAttachmentCount      = info.renderingInfo.colorAttachmentCount;
2997     attachmentLocations.pColorAttachmentLocations = info.colorAttachmentLocations.data();
2998 
2999     primary->setRenderingAttachmentLocations(&attachmentLocations);
3000 
3001     if (hasColorFramebufferFetch())
3002     {
3003         VkRenderingInputAttachmentIndexInfoKHR inputLocations = {};
3004         inputLocations.sType = VK_STRUCTURE_TYPE_RENDERING_INPUT_ATTACHMENT_INDEX_INFO_KHR;
3005         inputLocations.colorAttachmentCount         = info.renderingInfo.colorAttachmentCount;
3006         inputLocations.pColorAttachmentInputIndices = info.colorAttachmentLocations.data();
3007 
3008         primary->setRenderingInputAttachmentIndicates(&inputLocations);
3009     }
3010 }
3011 
populateRenderingInheritanceInfo(Renderer * renderer,VkCommandBufferInheritanceRenderingInfo * infoOut,gl::DrawBuffersArray<VkFormat> * colorFormatStorageOut) const3012 void RenderPassDesc::populateRenderingInheritanceInfo(
3013     Renderer *renderer,
3014     VkCommandBufferInheritanceRenderingInfo *infoOut,
3015     gl::DrawBuffersArray<VkFormat> *colorFormatStorageOut) const
3016 {
3017     DynamicRenderingInfo renderingInfo;
3018     DeriveRenderingInfo(renderer, *this, DynamicRenderingInfoSubset::Pipeline, {},
3019                         VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, {}, {}, {}, 0,
3020                         &renderingInfo);
3021     *colorFormatStorageOut = renderingInfo.colorAttachmentFormats;
3022 
3023     *infoOut       = {};
3024     infoOut->sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO;
3025     infoOut->flags = VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT;
3026     if (isLegacyDitherEnabled())
3027     {
3028         ASSERT(renderer->getFeatures().supportsLegacyDithering.enabled);
3029         infoOut->flags |= VK_RENDERING_ENABLE_LEGACY_DITHERING_BIT_EXT;
3030     }
3031     infoOut->viewMask                = renderingInfo.renderingInfo.viewMask;
3032     infoOut->colorAttachmentCount    = renderingInfo.renderingInfo.colorAttachmentCount;
3033     infoOut->pColorAttachmentFormats = colorFormatStorageOut->data();
3034     infoOut->depthAttachmentFormat   = renderingInfo.depthAttachmentFormat;
3035     infoOut->stencilAttachmentFormat = renderingInfo.stencilAttachmentFormat;
3036     infoOut->rasterizationSamples =
3037         gl_vk::GetSamples(samples(), renderer->getFeatures().limitSampleCountTo2.enabled);
3038 }
3039 
updatePerfCounters(ErrorContext * context,const FramebufferAttachmentsVector<VkImageView> & attachmentViews,const AttachmentOpsArray & ops,angle::VulkanPerfCounters * countersOut)3040 void RenderPassDesc::updatePerfCounters(
3041     ErrorContext *context,
3042     const FramebufferAttachmentsVector<VkImageView> &attachmentViews,
3043     const AttachmentOpsArray &ops,
3044     angle::VulkanPerfCounters *countersOut)
3045 {
3046     DynamicRenderingInfo info;
3047     DeriveRenderingInfo(context->getRenderer(), *this, DynamicRenderingInfoSubset::Full, {},
3048                         VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, attachmentViews, ops, {}, 0,
3049                         &info);
3050 
3051     // Note: resolve attachments don't have ops with dynamic rendering and they are implicit.
3052     // Counter-tests should take the |preferDynamicRendering| flag into account.  For color, it's
3053     // trivial to assume DONT_CARE/STORE, but it gets more complicated with depth/stencil when only
3054     // one aspect is resolved.
3055 
3056     for (uint32_t index = 0; index < info.renderingInfo.colorAttachmentCount; ++index)
3057     {
3058         const VkRenderingAttachmentInfo &colorInfo = info.renderingInfo.pColorAttachments[index];
3059         ASSERT(colorInfo.imageView != VK_NULL_HANDLE);
3060 
3061         countersOut->colorLoadOpClears += colorInfo.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ? 1 : 0;
3062         countersOut->colorLoadOpLoads += colorInfo.loadOp == VK_ATTACHMENT_LOAD_OP_LOAD ? 1 : 0;
3063         countersOut->colorLoadOpNones += colorInfo.loadOp == VK_ATTACHMENT_LOAD_OP_NONE_EXT ? 1 : 0;
3064         countersOut->colorStoreOpStores +=
3065             colorInfo.storeOp == VK_ATTACHMENT_STORE_OP_STORE ? 1 : 0;
3066         countersOut->colorStoreOpNones +=
3067             colorInfo.storeOp == VK_ATTACHMENT_STORE_OP_NONE_EXT ? 1 : 0;
3068 
3069         if (colorInfo.resolveMode != VK_RESOLVE_MODE_NONE)
3070         {
3071             countersOut->colorStoreOpStores += 1;
3072             countersOut->colorAttachmentResolves += 1;
3073         }
3074     }
3075 
3076     if (info.renderingInfo.pDepthAttachment != nullptr)
3077     {
3078         ASSERT(info.renderingInfo.pDepthAttachment->imageView != VK_NULL_HANDLE);
3079 
3080         const VkRenderingAttachmentInfo &depthInfo = *info.renderingInfo.pDepthAttachment;
3081 
3082         countersOut->depthLoadOpClears += depthInfo.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ? 1 : 0;
3083         countersOut->depthLoadOpLoads += depthInfo.loadOp == VK_ATTACHMENT_LOAD_OP_LOAD ? 1 : 0;
3084         countersOut->depthLoadOpNones += depthInfo.loadOp == VK_ATTACHMENT_LOAD_OP_NONE_EXT ? 1 : 0;
3085         countersOut->depthStoreOpStores +=
3086             depthInfo.storeOp == VK_ATTACHMENT_STORE_OP_STORE ? 1 : 0;
3087         countersOut->depthStoreOpNones +=
3088             depthInfo.storeOp == VK_ATTACHMENT_STORE_OP_NONE_EXT ? 1 : 0;
3089 
3090         if (depthInfo.resolveMode != VK_RESOLVE_MODE_NONE)
3091         {
3092             countersOut->depthStoreOpStores += 1;
3093             countersOut->depthAttachmentResolves += 1;
3094         }
3095     }
3096 
3097     if (info.renderingInfo.pStencilAttachment != nullptr)
3098     {
3099         ASSERT(info.renderingInfo.pStencilAttachment->imageView != VK_NULL_HANDLE);
3100 
3101         const VkRenderingAttachmentInfo &stencilInfo = *info.renderingInfo.pStencilAttachment;
3102 
3103         countersOut->stencilLoadOpClears +=
3104             stencilInfo.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ? 1 : 0;
3105         countersOut->stencilLoadOpLoads += stencilInfo.loadOp == VK_ATTACHMENT_LOAD_OP_LOAD ? 1 : 0;
3106         countersOut->stencilLoadOpNones +=
3107             stencilInfo.loadOp == VK_ATTACHMENT_LOAD_OP_NONE_EXT ? 1 : 0;
3108         countersOut->stencilStoreOpStores +=
3109             stencilInfo.storeOp == VK_ATTACHMENT_STORE_OP_STORE ? 1 : 0;
3110         countersOut->stencilStoreOpNones +=
3111             stencilInfo.storeOp == VK_ATTACHMENT_STORE_OP_NONE_EXT ? 1 : 0;
3112 
3113         if (stencilInfo.resolveMode != VK_RESOLVE_MODE_NONE)
3114         {
3115             countersOut->stencilStoreOpStores += 1;
3116             countersOut->stencilAttachmentResolves += 1;
3117         }
3118     }
3119 
3120     if (info.renderingInfo.pDepthAttachment != nullptr ||
3121         info.renderingInfo.pStencilAttachment != nullptr)
3122     {
3123         ASSERT(info.renderingInfo.pDepthAttachment == nullptr ||
3124                info.renderingInfo.pStencilAttachment == nullptr ||
3125                info.renderingInfo.pDepthAttachment->imageLayout ==
3126                    info.renderingInfo.pStencilAttachment->imageLayout);
3127 
3128         const VkImageLayout layout = info.renderingInfo.pDepthAttachment != nullptr
3129                                          ? info.renderingInfo.pDepthAttachment->imageLayout
3130                                          : info.renderingInfo.pStencilAttachment->imageLayout;
3131 
3132         countersOut->readOnlyDepthStencilRenderPasses +=
3133             layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL ? 1 : 0;
3134     }
3135 }
3136 
operator ==(const RenderPassDesc & lhs,const RenderPassDesc & rhs)3137 bool operator==(const RenderPassDesc &lhs, const RenderPassDesc &rhs)
3138 {
3139     return memcmp(&lhs, &rhs, sizeof(RenderPassDesc)) == 0;
3140 }
3141 
3142 // Compute Pipeline Description implementation.
3143 // Use aligned allocation and free so we can use the alignas keyword.
operator new(std::size_t size)3144 void *ComputePipelineDesc::operator new(std::size_t size)
3145 {
3146     return angle::AlignedAlloc(size, 32);
3147 }
3148 
operator delete(void * ptr)3149 void ComputePipelineDesc::operator delete(void *ptr)
3150 {
3151     return angle::AlignedFree(ptr);
3152 }
3153 
ComputePipelineDesc()3154 ComputePipelineDesc::ComputePipelineDesc()
3155 {
3156     ASSERT(mPipelineOptions.permutationIndex == 0);
3157     ASSERT(std::all_of(mPadding, mPadding + sizeof(mPadding), [](char c) { return c == 0; }));
3158 }
3159 
ComputePipelineDesc(const ComputePipelineDesc & other)3160 ComputePipelineDesc::ComputePipelineDesc(const ComputePipelineDesc &other)
3161     : mConstantIds{other.getConstantIds()},
3162       mConstants{other.getConstants()},
3163       mPipelineOptions{other.getPipelineOptions()}
3164 {}
3165 
operator =(const ComputePipelineDesc & other)3166 ComputePipelineDesc &ComputePipelineDesc::operator=(const ComputePipelineDesc &other)
3167 {
3168     mPipelineOptions = other.getPipelineOptions();
3169     mConstantIds     = other.getConstantIds();
3170     mConstants       = other.getConstants();
3171     return *this;
3172 }
3173 
ComputePipelineDesc(VkSpecializationInfo * specializationInfo,ComputePipelineOptions pipelineOptions)3174 ComputePipelineDesc::ComputePipelineDesc(VkSpecializationInfo *specializationInfo,
3175                                          ComputePipelineOptions pipelineOptions)
3176     : mConstantIds{}, mConstants{}, mPipelineOptions{pipelineOptions}
3177 {
3178     if (specializationInfo != nullptr && specializationInfo->pMapEntries &&
3179         specializationInfo->mapEntryCount != 0)
3180     {
3181         const VkSpecializationMapEntry *mapEntries = specializationInfo->pMapEntries;
3182         mConstantIds.resize(specializationInfo->mapEntryCount);
3183         for (size_t mapEntryCount = 0; mapEntryCount < mConstantIds.size(); mapEntryCount++)
3184             mConstantIds[mapEntryCount] = mapEntries[mapEntryCount].constantID;
3185     }
3186     if (specializationInfo != nullptr && specializationInfo->pData &&
3187         specializationInfo->dataSize != 0)
3188     {
3189         const uint32_t *constDataEntries = (const uint32_t *)specializationInfo->pData;
3190         mConstants.resize(specializationInfo->dataSize / sizeof(uint32_t));
3191         for (size_t constantEntryCount = 0; constantEntryCount < mConstants.size();
3192              constantEntryCount++)
3193             mConstants[constantEntryCount] = constDataEntries[constantEntryCount];
3194     }
3195 }
3196 
hash() const3197 size_t ComputePipelineDesc::hash() const
3198 {
3199     // Union is static-asserted, just another sanity check here
3200     ASSERT(sizeof(ComputePipelineOptions) == 1);
3201 
3202     size_t paddedPipelineOptions = mPipelineOptions.permutationIndex;
3203     size_t pipelineOptionsHash =
3204         angle::ComputeGenericHash(&paddedPipelineOptions, sizeof(paddedPipelineOptions));
3205 
3206     size_t specializationConstantIDsHash = 0;
3207     if (!mConstantIds.empty())
3208     {
3209         specializationConstantIDsHash =
3210             angle::ComputeGenericHash(mConstantIds.data(), mConstantIds.size() * sizeof(uint32_t));
3211     }
3212 
3213     size_t specializationConstantsHash = 0;
3214     if (!mConstants.empty())
3215     {
3216         specializationConstantsHash =
3217             angle::ComputeGenericHash(mConstants.data(), mConstants.size() * sizeof(uint32_t));
3218     }
3219 
3220     return pipelineOptionsHash ^ specializationConstantIDsHash ^ specializationConstantsHash;
3221 }
3222 
keyEqual(const ComputePipelineDesc & other) const3223 bool ComputePipelineDesc::keyEqual(const ComputePipelineDesc &other) const
3224 {
3225     return mPipelineOptions.permutationIndex == other.getPipelineOptions().permutationIndex &&
3226            mConstantIds == other.getConstantIds() && mConstants == other.getConstants();
3227 }
3228 
3229 // GraphicsPipelineDesc implementation.
3230 // Use aligned allocation and free so we can use the alignas keyword.
operator new(std::size_t size)3231 void *GraphicsPipelineDesc::operator new(std::size_t size)
3232 {
3233     return angle::AlignedAlloc(size, 32);
3234 }
3235 
operator delete(void * ptr)3236 void GraphicsPipelineDesc::operator delete(void *ptr)
3237 {
3238     return angle::AlignedFree(ptr);
3239 }
3240 
GraphicsPipelineDesc()3241 GraphicsPipelineDesc::GraphicsPipelineDesc()
3242 {
3243     memset(this, 0, sizeof(GraphicsPipelineDesc));
3244 }
3245 
3246 GraphicsPipelineDesc::~GraphicsPipelineDesc() = default;
3247 
GraphicsPipelineDesc(const GraphicsPipelineDesc & other)3248 GraphicsPipelineDesc::GraphicsPipelineDesc(const GraphicsPipelineDesc &other)
3249 {
3250     *this = other;
3251 }
3252 
operator =(const GraphicsPipelineDesc & other)3253 GraphicsPipelineDesc &GraphicsPipelineDesc::operator=(const GraphicsPipelineDesc &other)
3254 {
3255     memcpy(this, &other, sizeof(*this));
3256     return *this;
3257 }
3258 
getPipelineSubsetMemory(GraphicsPipelineSubset subset,size_t * sizeOut) const3259 const void *GraphicsPipelineDesc::getPipelineSubsetMemory(GraphicsPipelineSubset subset,
3260                                                           size_t *sizeOut) const
3261 {
3262     // GraphicsPipelineDesc must be laid out such that the three subsets are contiguous.  The layout
3263     // is:
3264     //
3265     //     Shaders State                 \
3266     //                                    )--> Pre-rasterization + fragment subset
3267     //     Shared Non-Vertex-Input State /  \
3268     //                                       )--> fragment output subset
3269     //     Fragment Output State            /
3270     //
3271     //     Vertex Input State            ----> Vertex input subset
3272     static_assert(offsetof(GraphicsPipelineDesc, mShaders) == kPipelineShadersDescOffset);
3273     static_assert(offsetof(GraphicsPipelineDesc, mSharedNonVertexInput) ==
3274                   kPipelineShadersDescOffset + kGraphicsPipelineShadersStateSize);
3275     static_assert(offsetof(GraphicsPipelineDesc, mSharedNonVertexInput) ==
3276                   kPipelineFragmentOutputDescOffset);
3277     static_assert(offsetof(GraphicsPipelineDesc, mFragmentOutput) ==
3278                   kPipelineFragmentOutputDescOffset +
3279                       kGraphicsPipelineSharedNonVertexInputStateSize);
3280     static_assert(offsetof(GraphicsPipelineDesc, mVertexInput) == kPipelineVertexInputDescOffset);
3281 
3282     // Exclude the full vertex or only vertex strides from the hash. It's conveniently placed last,
3283     // so it would be easy to exclude it from hash.
3284     static_assert(offsetof(GraphicsPipelineDesc, mVertexInput.vertex.strides) +
3285                       sizeof(PackedVertexInputAttributes::strides) ==
3286                   sizeof(GraphicsPipelineDesc));
3287     static_assert(offsetof(GraphicsPipelineDesc, mVertexInput.vertex) +
3288                       sizeof(PackedVertexInputAttributes) ==
3289                   sizeof(GraphicsPipelineDesc));
3290 
3291     size_t vertexInputReduceSize = 0;
3292     if (mVertexInput.inputAssembly.bits.useVertexInputBindingStrideDynamicState)
3293     {
3294         vertexInputReduceSize = sizeof(PackedVertexInputAttributes::strides);
3295     }
3296     else if (mVertexInput.inputAssembly.bits.useVertexInputDynamicState)
3297     {
3298         vertexInputReduceSize = sizeof(PackedVertexInputAttributes);
3299     }
3300 
3301     switch (subset)
3302     {
3303         case GraphicsPipelineSubset::Shaders:
3304             *sizeOut = kPipelineShadersDescSize;
3305             return &mShaders;
3306 
3307         case GraphicsPipelineSubset::Complete:
3308         default:
3309             *sizeOut = sizeof(*this) - vertexInputReduceSize;
3310             return this;
3311     }
3312 }
3313 
hash(GraphicsPipelineSubset subset) const3314 size_t GraphicsPipelineDesc::hash(GraphicsPipelineSubset subset) const
3315 {
3316     size_t keySize  = 0;
3317     const void *key = getPipelineSubsetMemory(subset, &keySize);
3318 
3319     return angle::ComputeGenericHash(key, keySize);
3320 }
3321 
keyEqual(const GraphicsPipelineDesc & other,GraphicsPipelineSubset subset) const3322 bool GraphicsPipelineDesc::keyEqual(const GraphicsPipelineDesc &other,
3323                                     GraphicsPipelineSubset subset) const
3324 {
3325     size_t keySize  = 0;
3326     const void *key = getPipelineSubsetMemory(subset, &keySize);
3327 
3328     size_t otherKeySize  = 0;
3329     const void *otherKey = other.getPipelineSubsetMemory(subset, &otherKeySize);
3330 
3331     // Compare the relevant part of the desc memory.  Note that due to workarounds (e.g.
3332     // useVertexInputBindingStrideDynamicState), |this| or |other| may produce different key sizes.
3333     // In that case, comparing the minimum of the two is sufficient; if the workarounds are
3334     // different, the comparison would fail anyway.
3335     return memcmp(key, otherKey, std::min(keySize, otherKeySize)) == 0;
3336 }
3337 
3338 // Initialize PSO states, it is consistent with initial value of gl::State.
3339 //
3340 // Some states affect the pipeline, but they are not derived from the GL state, but rather the
3341 // properties of the Vulkan device or the context itself; such as whether a workaround is in
3342 // effect, or the context is robust.  For VK_EXT_graphics_pipeline_library, such state that affects
3343 // multiple subsets of the pipeline is duplicated in each subset (for example, there are two
3344 // copies of isRobustContext, one for vertex input and one for shader stages).
initDefaults(const ErrorContext * context,GraphicsPipelineSubset subset,PipelineRobustness pipelineRobustness,PipelineProtectedAccess pipelineProtectedAccess)3345 void GraphicsPipelineDesc::initDefaults(const ErrorContext *context,
3346                                         GraphicsPipelineSubset subset,
3347                                         PipelineRobustness pipelineRobustness,
3348                                         PipelineProtectedAccess pipelineProtectedAccess)
3349 {
3350     if (GraphicsPipelineHasVertexInput(subset))
3351     {
3352         // Set all vertex input attributes to default, the default format is Float
3353         angle::FormatID defaultFormat = GetCurrentValueFormatID(gl::VertexAttribType::Float);
3354         for (PackedAttribDesc &packedAttrib : mVertexInput.vertex.attribs)
3355         {
3356             SetBitField(packedAttrib.divisor, 0);
3357             SetBitField(packedAttrib.format, defaultFormat);
3358             SetBitField(packedAttrib.compressed, 0);
3359             SetBitField(packedAttrib.offset, 0);
3360         }
3361         mVertexInput.vertex.shaderAttribComponentType = 0;
3362         memset(mVertexInput.vertex.strides, 0, sizeof(mVertexInput.vertex.strides));
3363 
3364         SetBitField(mVertexInput.inputAssembly.bits.topology, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
3365         mVertexInput.inputAssembly.bits.primitiveRestartEnable = 0;
3366         mVertexInput.inputAssembly.bits.useVertexInputBindingStrideDynamicState =
3367             context->getFeatures().useVertexInputBindingStrideDynamicState.enabled;
3368         mVertexInput.inputAssembly.bits.useVertexInputDynamicState =
3369             context->getFeatures().supportsVertexInputDynamicState.enabled;
3370         mVertexInput.inputAssembly.bits.padding = 0;
3371     }
3372 
3373     if (GraphicsPipelineHasShaders(subset))
3374     {
3375         mShaders.shaders.bits.viewportNegativeOneToOne =
3376             context->getFeatures().supportsDepthClipControl.enabled;
3377         mShaders.shaders.bits.depthClampEnable = 0;
3378         SetBitField(mShaders.shaders.bits.polygonMode, VK_POLYGON_MODE_FILL);
3379         SetBitField(mShaders.shaders.bits.cullMode, VK_CULL_MODE_NONE);
3380         SetBitField(mShaders.shaders.bits.frontFace, VK_FRONT_FACE_COUNTER_CLOCKWISE);
3381         mShaders.shaders.bits.rasterizerDiscardEnable = 0;
3382         mShaders.shaders.bits.depthBiasEnable         = 0;
3383         SetBitField(mShaders.shaders.bits.patchVertices, 3);
3384         mShaders.shaders.bits.depthBoundsTest                   = 0;
3385         mShaders.shaders.bits.depthTest                         = 0;
3386         mShaders.shaders.bits.depthWrite                        = 0;
3387         mShaders.shaders.bits.stencilTest                       = 0;
3388         mShaders.shaders.bits.nonZeroStencilWriteMaskWorkaround = 0;
3389         SetBitField(mShaders.shaders.bits.depthCompareOp, VK_COMPARE_OP_LESS);
3390         mShaders.shaders.bits.surfaceRotation  = 0;
3391         mShaders.shaders.emulatedDitherControl = 0;
3392         mShaders.shaders.padding               = 0;
3393         SetBitField(mShaders.shaders.front.fail, VK_STENCIL_OP_KEEP);
3394         SetBitField(mShaders.shaders.front.pass, VK_STENCIL_OP_KEEP);
3395         SetBitField(mShaders.shaders.front.depthFail, VK_STENCIL_OP_KEEP);
3396         SetBitField(mShaders.shaders.front.compare, VK_COMPARE_OP_ALWAYS);
3397         SetBitField(mShaders.shaders.back.fail, VK_STENCIL_OP_KEEP);
3398         SetBitField(mShaders.shaders.back.pass, VK_STENCIL_OP_KEEP);
3399         SetBitField(mShaders.shaders.back.depthFail, VK_STENCIL_OP_KEEP);
3400         SetBitField(mShaders.shaders.back.compare, VK_COMPARE_OP_ALWAYS);
3401     }
3402 
3403     if (GraphicsPipelineHasShadersOrFragmentOutput(subset))
3404     {
3405         mSharedNonVertexInput.multisample.bits.sampleMask = std::numeric_limits<uint16_t>::max();
3406         mSharedNonVertexInput.multisample.bits.rasterizationSamplesMinusOne = 0;
3407         mSharedNonVertexInput.multisample.bits.sampleShadingEnable          = 0;
3408         mSharedNonVertexInput.multisample.bits.alphaToCoverageEnable        = 0;
3409         mSharedNonVertexInput.multisample.bits.alphaToOneEnable             = 0;
3410         mSharedNonVertexInput.multisample.bits.subpass                      = 0;
3411         mSharedNonVertexInput.multisample.bits.minSampleShading = kMinSampleShadingScale;
3412     }
3413 
3414     if (GraphicsPipelineHasFragmentOutput(subset))
3415     {
3416         constexpr VkFlags kAllColorBits = (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
3417                                            VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
3418 
3419         for (uint32_t colorIndexGL = 0; colorIndexGL < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
3420              ++colorIndexGL)
3421         {
3422             Int4Array_Set(mFragmentOutput.blend.colorWriteMaskBits, colorIndexGL, kAllColorBits);
3423         }
3424 
3425         PackedColorBlendAttachmentState blendAttachmentState;
3426         SetBitField(blendAttachmentState.srcColorBlendFactor, VK_BLEND_FACTOR_ONE);
3427         SetBitField(blendAttachmentState.dstColorBlendFactor, VK_BLEND_FACTOR_ZERO);
3428         SetBitField(blendAttachmentState.colorBlendOp, VK_BLEND_OP_ADD);
3429         SetBitField(blendAttachmentState.srcAlphaBlendFactor, VK_BLEND_FACTOR_ONE);
3430         SetBitField(blendAttachmentState.dstAlphaBlendFactor, VK_BLEND_FACTOR_ZERO);
3431         SetBitField(blendAttachmentState.alphaBlendOp, VK_BLEND_OP_ADD);
3432 
3433         std::fill(&mFragmentOutput.blend.attachments[0],
3434                   &mFragmentOutput.blend.attachments[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS],
3435                   blendAttachmentState);
3436 
3437         mFragmentOutput.blendMaskAndLogic.bits.blendEnableMask = 0;
3438         mFragmentOutput.blendMaskAndLogic.bits.logicOpEnable   = 0;
3439         SetBitField(mFragmentOutput.blendMaskAndLogic.bits.logicOp, VK_LOGIC_OP_COPY);
3440         mFragmentOutput.blendMaskAndLogic.bits.padding = 0;
3441     }
3442 
3443     // Context robustness affects vertex input and shader stages.
3444     mVertexInput.inputAssembly.bits.isRobustContext = mShaders.shaders.bits.isRobustContext =
3445         pipelineRobustness == PipelineRobustness::Robust;
3446 
3447     // Context protected-ness affects all subsets.
3448     mVertexInput.inputAssembly.bits.isProtectedContext = mShaders.shaders.bits.isProtectedContext =
3449         mFragmentOutput.blendMaskAndLogic.bits.isProtectedContext =
3450             pipelineProtectedAccess == PipelineProtectedAccess::Protected;
3451 }
3452 
initializePipeline(ErrorContext * context,PipelineCacheAccess * pipelineCache,GraphicsPipelineSubset subset,const RenderPass & compatibleRenderPass,const PipelineLayout & pipelineLayout,const GraphicsPipelineShadersInfo & shaders,Pipeline * pipelineOut,CacheLookUpFeedback * feedbackOut) const3453 VkResult GraphicsPipelineDesc::initializePipeline(ErrorContext *context,
3454                                                   PipelineCacheAccess *pipelineCache,
3455                                                   GraphicsPipelineSubset subset,
3456                                                   const RenderPass &compatibleRenderPass,
3457                                                   const PipelineLayout &pipelineLayout,
3458                                                   const GraphicsPipelineShadersInfo &shaders,
3459                                                   Pipeline *pipelineOut,
3460                                                   CacheLookUpFeedback *feedbackOut) const
3461 {
3462     GraphicsPipelineVertexInputVulkanStructs vertexInputState;
3463     GraphicsPipelineShadersVulkanStructs shadersState;
3464     GraphicsPipelineSharedNonVertexInputVulkanStructs sharedNonVertexInputState;
3465     GraphicsPipelineFragmentOutputVulkanStructs fragmentOutputState;
3466     GraphicsPipelineDynamicStateList dynamicStateList;
3467 
3468     // With dynamic rendering, there are no render pass objects.
3469     ASSERT(!compatibleRenderPass.valid() || !context->getFeatures().preferDynamicRendering.enabled);
3470 
3471     VkGraphicsPipelineCreateInfo createInfo = {};
3472     createInfo.sType                        = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
3473     createInfo.flags                        = 0;
3474     createInfo.renderPass                   = compatibleRenderPass.getHandle();
3475     createInfo.subpass                      = mSharedNonVertexInput.multisample.bits.subpass;
3476 
3477     const bool hasVertexInput             = GraphicsPipelineHasVertexInput(subset);
3478     const bool hasShaders                 = GraphicsPipelineHasShaders(subset);
3479     const bool hasShadersOrFragmentOutput = GraphicsPipelineHasShadersOrFragmentOutput(subset);
3480     const bool hasFragmentOutput          = GraphicsPipelineHasFragmentOutput(subset);
3481 
3482     if (hasVertexInput)
3483     {
3484         initializePipelineVertexInputState(context, &vertexInputState, &dynamicStateList);
3485 
3486         createInfo.pVertexInputState   = &vertexInputState.vertexInputState;
3487         createInfo.pInputAssemblyState = &vertexInputState.inputAssemblyState;
3488     }
3489 
3490     VkPipeline shadersPipeline                        = VK_NULL_HANDLE;
3491     VkPipelineLibraryCreateInfoKHR shadersLibraryInfo = {};
3492     shadersLibraryInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR;
3493 
3494     if (hasShaders)
3495     {
3496         // If the shaders state comes from a library, use the library instead.
3497         if (shaders.usePipelineLibrary())
3498         {
3499             shadersPipeline = shaders.mPipelineLibrary->getPipeline().getHandle();
3500 
3501             shadersLibraryInfo.libraryCount = 1;
3502             shadersLibraryInfo.pLibraries   = &shadersPipeline;
3503 
3504             AddToPNextChain(&createInfo, &shadersLibraryInfo);
3505         }
3506         else
3507         {
3508             initializePipelineShadersState(context, *shaders.mShaders, *shaders.mSpecConsts,
3509                                            &shadersState, &dynamicStateList);
3510 
3511             createInfo.stageCount         = static_cast<uint32_t>(shadersState.shaderStages.size());
3512             createInfo.pStages            = shadersState.shaderStages.data();
3513             createInfo.pTessellationState = &shadersState.tessellationState;
3514             createInfo.pViewportState     = &shadersState.viewportState;
3515             createInfo.pRasterizationState = &shadersState.rasterState;
3516             createInfo.pDepthStencilState  = &shadersState.depthStencilState;
3517         }
3518 
3519         createInfo.layout              = pipelineLayout.getHandle();
3520     }
3521 
3522     if (hasShadersOrFragmentOutput)
3523     {
3524         initializePipelineSharedNonVertexInputState(context, &sharedNonVertexInputState,
3525                                                     &dynamicStateList);
3526 
3527         createInfo.pMultisampleState = &sharedNonVertexInputState.multisampleState;
3528     }
3529 
3530     if (hasFragmentOutput)
3531     {
3532         initializePipelineFragmentOutputState(context, &fragmentOutputState, &dynamicStateList);
3533 
3534         createInfo.pColorBlendState = &fragmentOutputState.blendState;
3535     }
3536 
3537     VkPipelineDynamicStateCreateInfo dynamicState = {};
3538     dynamicState.sType             = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
3539     dynamicState.dynamicStateCount = static_cast<uint32_t>(dynamicStateList.size());
3540     dynamicState.pDynamicStates    = dynamicStateList.data();
3541     createInfo.pDynamicState       = dynamicStateList.empty() ? nullptr : &dynamicState;
3542 
3543     // If not a complete pipeline, specify which subset is being created
3544     VkGraphicsPipelineLibraryCreateInfoEXT libraryInfo = {};
3545     libraryInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT;
3546 
3547     if (subset == GraphicsPipelineSubset::Shaders)
3548     {
3549         libraryInfo.flags = VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT |
3550                             VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT;
3551 
3552         createInfo.flags |= VK_PIPELINE_CREATE_LIBRARY_BIT_KHR;
3553 
3554         AddToPNextChain(&createInfo, &libraryInfo);
3555     }
3556     else if (hasShaders && shaders.usePipelineLibrary())
3557     {
3558         libraryInfo.flags = VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT |
3559                             VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT;
3560 
3561         AddToPNextChain(&createInfo, &libraryInfo);
3562     }
3563 
3564     VkPipelineRobustnessCreateInfoEXT robustness = {};
3565     robustness.sType = VK_STRUCTURE_TYPE_PIPELINE_ROBUSTNESS_CREATE_INFO_EXT;
3566 
3567     // Enable robustness on the pipeline if needed.  Note that the global robustBufferAccess feature
3568     // must be disabled by default.
3569     if ((hasVertexInput && mVertexInput.inputAssembly.bits.isRobustContext) ||
3570         (hasShaders && mShaders.shaders.bits.isRobustContext))
3571     {
3572         ASSERT(context->getFeatures().supportsPipelineRobustness.enabled);
3573 
3574         robustness.storageBuffers = VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_EXT;
3575         robustness.uniformBuffers = VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_EXT;
3576         robustness.vertexInputs   = VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_EXT;
3577         robustness.images         = VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DEVICE_DEFAULT_EXT;
3578 
3579         AddToPNextChain(&createInfo, &robustness);
3580     }
3581 
3582     if ((hasVertexInput && mVertexInput.inputAssembly.bits.isProtectedContext) ||
3583         (hasShaders && mShaders.shaders.bits.isProtectedContext) ||
3584         (hasFragmentOutput && mFragmentOutput.blendMaskAndLogic.bits.isProtectedContext))
3585     {
3586         ASSERT(context->getFeatures().supportsPipelineProtectedAccess.enabled);
3587         createInfo.flags |= VK_PIPELINE_CREATE_PROTECTED_ACCESS_ONLY_BIT_EXT;
3588     }
3589     else if (context->getFeatures().supportsPipelineProtectedAccess.enabled)
3590     {
3591         createInfo.flags |= VK_PIPELINE_CREATE_NO_PROTECTED_ACCESS_BIT_EXT;
3592     }
3593 
3594     VkPipelineCreationFeedback feedback = {};
3595     gl::ShaderMap<VkPipelineCreationFeedback> perStageFeedback;
3596 
3597     VkPipelineCreationFeedbackCreateInfo feedbackInfo = {};
3598     feedbackInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO;
3599 
3600     const bool supportsFeedback = context->getFeatures().supportsPipelineCreationFeedback.enabled;
3601     if (supportsFeedback)
3602     {
3603         feedbackInfo.pPipelineCreationFeedback = &feedback;
3604         // Provide some storage for per-stage data, even though it's not used.  This first works
3605         // around a VVL bug that doesn't allow `pipelineStageCreationFeedbackCount=0` despite the
3606         // spec (See https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/4161).  Even
3607         // with fixed VVL, several drivers crash when this storage is missing too.
3608         feedbackInfo.pipelineStageCreationFeedbackCount = createInfo.stageCount;
3609         feedbackInfo.pPipelineStageCreationFeedbacks    = perStageFeedback.data();
3610 
3611         AddToPNextChain(&createInfo, &feedbackInfo);
3612     }
3613 
3614     // Attach dynamic rendering info if needed.  This is done last because the flags may need to
3615     // be transfered to |VkPipelineCreateFlags2CreateInfoKHR|, so it must be done after every
3616     // other flag is set.
3617     DynamicRenderingInfo renderingInfo;
3618     VkPipelineRenderingCreateInfoKHR pipelineRenderingInfo;
3619     VkRenderingAttachmentLocationInfoKHR attachmentLocations;
3620     VkRenderingInputAttachmentIndexInfoKHR inputLocations;
3621     VkPipelineCreateFlags2CreateInfoKHR createFlags2;
3622     if (hasShadersOrFragmentOutput && context->getFeatures().preferDynamicRendering.enabled)
3623     {
3624         DeriveRenderingInfo(context->getRenderer(), getRenderPassDesc(),
3625                             DynamicRenderingInfoSubset::Pipeline, {}, VK_SUBPASS_CONTENTS_INLINE,
3626                             {}, {}, {}, 0, &renderingInfo);
3627         AttachPipelineRenderingInfo(context, getRenderPassDesc(), renderingInfo, subset,
3628                                     shaders.usePipelineLibrary()
3629                                         ? ShadersStateSource::PipelineLibrary
3630                                         : ShadersStateSource::ThisPipeline,
3631                                     &pipelineRenderingInfo, &attachmentLocations, &inputLocations,
3632                                     &createFlags2, &createInfo);
3633     }
3634 
3635     VkResult result = pipelineCache->createGraphicsPipeline(context, createInfo, pipelineOut);
3636 
3637     if (supportsFeedback)
3638     {
3639         const bool cacheHit =
3640             (feedback.flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT) !=
3641             0;
3642 
3643         *feedbackOut = cacheHit ? CacheLookUpFeedback::Hit : CacheLookUpFeedback::Miss;
3644         ApplyPipelineCreationFeedback(context, feedback);
3645     }
3646 
3647     return result;
3648 }
3649 
patchVertexAttribComponentType(angle::FormatID format,gl::ComponentType vsInputType)3650 angle::FormatID patchVertexAttribComponentType(angle::FormatID format,
3651                                                gl::ComponentType vsInputType)
3652 {
3653     const gl::VertexFormat &vertexFormat = gl::GetVertexFormatFromID(format);
3654     // For normalized format, keep the same ?
3655     EGLBoolean normalized = vertexFormat.normalized;
3656     if (normalized)
3657     {
3658         return format;
3659     }
3660     gl::VertexAttribType attribType = gl::FromGLenum<gl::VertexAttribType>(vertexFormat.type);
3661     if (vsInputType != gl::ComponentType::Float)
3662     {
3663         ASSERT(vsInputType == gl::ComponentType::Int ||
3664                vsInputType == gl::ComponentType::UnsignedInt);
3665         switch (attribType)
3666         {
3667             case gl::VertexAttribType::Float:
3668             case gl::VertexAttribType::Fixed:
3669             case gl::VertexAttribType::UnsignedInt:
3670             case gl::VertexAttribType::Int:
3671                 attribType = vsInputType == gl::ComponentType::Int
3672                                  ? gl::VertexAttribType::Int
3673                                  : gl::VertexAttribType::UnsignedInt;
3674                 break;
3675             case gl::VertexAttribType::HalfFloat:
3676             case gl::VertexAttribType::HalfFloatOES:
3677             case gl::VertexAttribType::Short:
3678             case gl::VertexAttribType::UnsignedShort:
3679                 attribType = vsInputType == gl::ComponentType::Int
3680                                  ? gl::VertexAttribType::Short
3681                                  : gl::VertexAttribType::UnsignedShort;
3682                 break;
3683             case gl::VertexAttribType::Byte:
3684             case gl::VertexAttribType::UnsignedByte:
3685                 attribType = vsInputType == gl::ComponentType::Int
3686                                  ? gl::VertexAttribType::Byte
3687                                  : gl::VertexAttribType::UnsignedByte;
3688                 break;
3689             case gl::VertexAttribType::UnsignedInt2101010:
3690             case gl::VertexAttribType::Int2101010:
3691                 attribType = vsInputType == gl::ComponentType::Int
3692                                  ? gl::VertexAttribType::Int2101010
3693                                  : gl::VertexAttribType::UnsignedInt2101010;
3694                 break;
3695             case gl::VertexAttribType::UnsignedInt1010102:
3696             case gl::VertexAttribType::Int1010102:
3697                 attribType = vsInputType == gl::ComponentType::Int
3698                                  ? gl::VertexAttribType::Int1010102
3699                                  : gl::VertexAttribType::UnsignedInt1010102;
3700                 break;
3701             default:
3702                 ASSERT(0);
3703                 break;
3704         }
3705     }
3706     return gl::GetVertexFormatID(attribType, vertexFormat.normalized, vertexFormat.components,
3707                                  !vertexFormat.pureInteger);
3708 }
3709 
getPipelineVertexInputStateFormat(ErrorContext * context,angle::FormatID formatID,bool compressed,const gl::ComponentType programAttribType,uint32_t attribIndex)3710 VkFormat GraphicsPipelineDesc::getPipelineVertexInputStateFormat(
3711     ErrorContext *context,
3712     angle::FormatID formatID,
3713     bool compressed,
3714     const gl::ComponentType programAttribType,
3715     uint32_t attribIndex)
3716 {
3717     vk::Renderer *renderer = context->getRenderer();
3718     // Get the corresponding VkFormat for the attrib's format.
3719     const Format &format                = renderer->getFormat(formatID);
3720     const angle::Format &intendedFormat = format.getIntendedFormat();
3721     VkFormat vkFormat                   = format.getActualBufferVkFormat(renderer, compressed);
3722 
3723     const gl::ComponentType attribType = GetVertexAttributeComponentType(
3724         intendedFormat.isPureInt(), intendedFormat.vertexAttribType);
3725 
3726     if (attribType != programAttribType)
3727     {
3728         VkFormat origVkFormat = vkFormat;
3729         if (attribType == gl::ComponentType::Float || programAttribType == gl::ComponentType::Float)
3730         {
3731             angle::FormatID patchFormatID =
3732                 patchVertexAttribComponentType(formatID, programAttribType);
3733             vkFormat =
3734                 renderer->getFormat(patchFormatID).getActualBufferVkFormat(renderer, compressed);
3735         }
3736         else
3737         {
3738             // When converting from an unsigned to a signed format or vice versa, attempt to
3739             // match the bit width.
3740             angle::FormatID convertedFormatID = gl::ConvertFormatSignedness(intendedFormat);
3741             const Format &convertedFormat     = renderer->getFormat(convertedFormatID);
3742             ASSERT(intendedFormat.channelCount == convertedFormat.getIntendedFormat().channelCount);
3743             ASSERT(intendedFormat.redBits == convertedFormat.getIntendedFormat().redBits);
3744             ASSERT(intendedFormat.greenBits == convertedFormat.getIntendedFormat().greenBits);
3745             ASSERT(intendedFormat.blueBits == convertedFormat.getIntendedFormat().blueBits);
3746             ASSERT(intendedFormat.alphaBits == convertedFormat.getIntendedFormat().alphaBits);
3747 
3748             vkFormat = convertedFormat.getActualBufferVkFormat(renderer, compressed);
3749         }
3750         const Format &origFormat  = renderer->getFormat(GetFormatIDFromVkFormat(origVkFormat));
3751         const Format &patchFormat = renderer->getFormat(GetFormatIDFromVkFormat(vkFormat));
3752         ASSERT(origFormat.getIntendedFormat().pixelBytes ==
3753                patchFormat.getIntendedFormat().pixelBytes);
3754         ASSERT(renderer->getNativeExtensions().relaxedVertexAttributeTypeANGLE);
3755     }
3756 
3757     return vkFormat;
3758 }
3759 
initializePipelineVertexInputState(ErrorContext * context,GraphicsPipelineVertexInputVulkanStructs * stateOut,GraphicsPipelineDynamicStateList * dynamicStateListOut) const3760 void GraphicsPipelineDesc::initializePipelineVertexInputState(
3761     ErrorContext *context,
3762     GraphicsPipelineVertexInputVulkanStructs *stateOut,
3763     GraphicsPipelineDynamicStateList *dynamicStateListOut) const
3764 {
3765     // TODO(jmadill): Possibly use different path for ES 3.1 split bindings/attribs.
3766     uint32_t vertexAttribCount = 0;
3767 
3768     stateOut->divisorState.sType =
3769         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
3770     stateOut->divisorState.pVertexBindingDivisors = stateOut->divisorDesc.data();
3771     for (size_t attribIndexSizeT :
3772          gl::AttributesMask(mVertexInput.inputAssembly.bits.programActiveAttributeLocations))
3773     {
3774         const uint32_t attribIndex = static_cast<uint32_t>(attribIndexSizeT);
3775 
3776         VkVertexInputBindingDescription &bindingDesc  = stateOut->bindingDescs[vertexAttribCount];
3777         VkVertexInputAttributeDescription &attribDesc = stateOut->attributeDescs[vertexAttribCount];
3778         const PackedAttribDesc &packedAttrib          = mVertexInput.vertex.attribs[attribIndex];
3779 
3780         bindingDesc.binding = attribIndex;
3781         bindingDesc.stride  = static_cast<uint32_t>(mVertexInput.vertex.strides[attribIndex]);
3782         if (packedAttrib.divisor != 0)
3783         {
3784             bindingDesc.inputRate = static_cast<VkVertexInputRate>(VK_VERTEX_INPUT_RATE_INSTANCE);
3785             stateOut->divisorDesc[stateOut->divisorState.vertexBindingDivisorCount].binding =
3786                 bindingDesc.binding;
3787             stateOut->divisorDesc[stateOut->divisorState.vertexBindingDivisorCount].divisor =
3788                 packedAttrib.divisor;
3789             ++stateOut->divisorState.vertexBindingDivisorCount;
3790         }
3791         else
3792         {
3793             bindingDesc.inputRate = static_cast<VkVertexInputRate>(VK_VERTEX_INPUT_RATE_VERTEX);
3794         }
3795 
3796         // If using dynamic state for stride, the value for stride is unconditionally 0 here.
3797         // |ContextVk::handleDirtyGraphicsVertexBuffers| implements the same fix when setting stride
3798         // dynamically.
3799         ASSERT(!context->getFeatures().useVertexInputBindingStrideDynamicState.enabled ||
3800                bindingDesc.stride == 0);
3801 
3802         // Get the corresponding VkFormat for the attrib's format.
3803         angle::FormatID formatID = static_cast<angle::FormatID>(packedAttrib.format);
3804         const gl::ComponentType programAttribType = gl::GetComponentTypeMask(
3805             gl::ComponentTypeMask(mVertexInput.vertex.shaderAttribComponentType), attribIndex);
3806 
3807         attribDesc.binding = attribIndex;
3808         attribDesc.format  = getPipelineVertexInputStateFormat(
3809             context, formatID, packedAttrib.compressed, programAttribType, attribIndex);
3810         attribDesc.location = static_cast<uint32_t>(attribIndex);
3811         attribDesc.offset   = packedAttrib.offset;
3812 
3813         vertexAttribCount++;
3814     }
3815 
3816     // The binding descriptions are filled in at draw time.
3817     stateOut->vertexInputState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
3818     stateOut->vertexInputState.flags = 0;
3819     stateOut->vertexInputState.vertexBindingDescriptionCount   = vertexAttribCount;
3820     stateOut->vertexInputState.pVertexBindingDescriptions      = stateOut->bindingDescs.data();
3821     stateOut->vertexInputState.vertexAttributeDescriptionCount = vertexAttribCount;
3822     stateOut->vertexInputState.pVertexAttributeDescriptions    = stateOut->attributeDescs.data();
3823     if (stateOut->divisorState.vertexBindingDivisorCount)
3824     {
3825         stateOut->vertexInputState.pNext = &stateOut->divisorState;
3826     }
3827 
3828     const PackedInputAssemblyState &inputAssembly = mVertexInput.inputAssembly;
3829 
3830     // Primitive topology is filled in at draw time.
3831     stateOut->inputAssemblyState.sType =
3832         VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
3833     stateOut->inputAssemblyState.flags = 0;
3834     stateOut->inputAssemblyState.topology =
3835         static_cast<VkPrimitiveTopology>(inputAssembly.bits.topology);
3836     stateOut->inputAssemblyState.primitiveRestartEnable =
3837         static_cast<VkBool32>(inputAssembly.bits.primitiveRestartEnable);
3838 
3839     // Dynamic state
3840     if (context->getFeatures().useVertexInputBindingStrideDynamicState.enabled &&
3841         vertexAttribCount > 0)
3842     {
3843         dynamicStateListOut->push_back(VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE);
3844     }
3845     if (context->getFeatures().usePrimitiveRestartEnableDynamicState.enabled)
3846     {
3847         dynamicStateListOut->push_back(VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE);
3848     }
3849     if (context->getFeatures().supportsVertexInputDynamicState.enabled)
3850     {
3851         dynamicStateListOut->push_back(VK_DYNAMIC_STATE_VERTEX_INPUT_EXT);
3852     }
3853 }
3854 
initializePipelineShadersState(ErrorContext * context,const ShaderModuleMap & shaders,const SpecializationConstants & specConsts,GraphicsPipelineShadersVulkanStructs * stateOut,GraphicsPipelineDynamicStateList * dynamicStateListOut) const3855 void GraphicsPipelineDesc::initializePipelineShadersState(
3856     ErrorContext *context,
3857     const ShaderModuleMap &shaders,
3858     const SpecializationConstants &specConsts,
3859     GraphicsPipelineShadersVulkanStructs *stateOut,
3860     GraphicsPipelineDynamicStateList *dynamicStateListOut) const
3861 {
3862     InitializeSpecializationInfo(specConsts, &stateOut->specializationEntries,
3863                                  &stateOut->specializationInfo);
3864 
3865     // Vertex shader is always expected to be present.
3866     const ShaderModule &vertexModule = *shaders[gl::ShaderType::Vertex];
3867     ASSERT(vertexModule.valid());
3868     VkPipelineShaderStageCreateInfo vertexStage = {};
3869     SetPipelineShaderStageInfo(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
3870                                VK_SHADER_STAGE_VERTEX_BIT, vertexModule.getHandle(),
3871                                stateOut->specializationInfo, &vertexStage);
3872     stateOut->shaderStages.push_back(vertexStage);
3873 
3874     const ShaderModulePtr &tessControlPointer = shaders[gl::ShaderType::TessControl];
3875     if (tessControlPointer)
3876     {
3877         const ShaderModule &tessControlModule            = *tessControlPointer;
3878         VkPipelineShaderStageCreateInfo tessControlStage = {};
3879         SetPipelineShaderStageInfo(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
3880                                    VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
3881                                    tessControlModule.getHandle(), stateOut->specializationInfo,
3882                                    &tessControlStage);
3883         stateOut->shaderStages.push_back(tessControlStage);
3884     }
3885 
3886     const ShaderModulePtr &tessEvaluationPointer = shaders[gl::ShaderType::TessEvaluation];
3887     if (tessEvaluationPointer)
3888     {
3889         const ShaderModule &tessEvaluationModule            = *tessEvaluationPointer;
3890         VkPipelineShaderStageCreateInfo tessEvaluationStage = {};
3891         SetPipelineShaderStageInfo(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
3892                                    VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
3893                                    tessEvaluationModule.getHandle(), stateOut->specializationInfo,
3894                                    &tessEvaluationStage);
3895         stateOut->shaderStages.push_back(tessEvaluationStage);
3896     }
3897 
3898     const ShaderModulePtr &geometryPointer = shaders[gl::ShaderType::Geometry];
3899     if (geometryPointer)
3900     {
3901         const ShaderModule &geometryModule            = *geometryPointer;
3902         VkPipelineShaderStageCreateInfo geometryStage = {};
3903         SetPipelineShaderStageInfo(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
3904                                    VK_SHADER_STAGE_GEOMETRY_BIT, geometryModule.getHandle(),
3905                                    stateOut->specializationInfo, &geometryStage);
3906         stateOut->shaderStages.push_back(geometryStage);
3907     }
3908 
3909     // Fragment shader is optional.
3910     const ShaderModulePtr &fragmentPointer = shaders[gl::ShaderType::Fragment];
3911     if (fragmentPointer && !mShaders.shaders.bits.rasterizerDiscardEnable)
3912     {
3913         const ShaderModule &fragmentModule            = *fragmentPointer;
3914         VkPipelineShaderStageCreateInfo fragmentStage = {};
3915         SetPipelineShaderStageInfo(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
3916                                    VK_SHADER_STAGE_FRAGMENT_BIT, fragmentModule.getHandle(),
3917                                    stateOut->specializationInfo, &fragmentStage);
3918         stateOut->shaderStages.push_back(fragmentStage);
3919     }
3920 
3921     // Set initial viewport and scissor state.
3922     stateOut->viewportState.sType         = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
3923     stateOut->viewportState.flags         = 0;
3924     stateOut->viewportState.viewportCount = 1;
3925     stateOut->viewportState.pViewports    = nullptr;
3926     stateOut->viewportState.scissorCount  = 1;
3927     stateOut->viewportState.pScissors     = nullptr;
3928 
3929     if (context->getFeatures().supportsDepthClipControl.enabled)
3930     {
3931         stateOut->depthClipControl.sType =
3932             VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT;
3933         stateOut->depthClipControl.negativeOneToOne =
3934             static_cast<VkBool32>(mShaders.shaders.bits.viewportNegativeOneToOne);
3935 
3936         stateOut->viewportState.pNext = &stateOut->depthClipControl;
3937     }
3938 
3939     // Rasterizer state.
3940     stateOut->rasterState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
3941     stateOut->rasterState.flags = 0;
3942     stateOut->rasterState.depthClampEnable =
3943         static_cast<VkBool32>(mShaders.shaders.bits.depthClampEnable);
3944     stateOut->rasterState.rasterizerDiscardEnable =
3945         static_cast<VkBool32>(mShaders.shaders.bits.rasterizerDiscardEnable);
3946     stateOut->rasterState.polygonMode =
3947         static_cast<VkPolygonMode>(mShaders.shaders.bits.polygonMode);
3948     stateOut->rasterState.cullMode  = static_cast<VkCullModeFlags>(mShaders.shaders.bits.cullMode);
3949     stateOut->rasterState.frontFace = static_cast<VkFrontFace>(mShaders.shaders.bits.frontFace);
3950     stateOut->rasterState.depthBiasEnable =
3951         static_cast<VkBool32>(mShaders.shaders.bits.depthBiasEnable);
3952     stateOut->rasterState.lineWidth = 0;
3953     const void **pNextPtr           = &stateOut->rasterState.pNext;
3954 
3955     const PackedMultisampleAndSubpassState &multisample = mSharedNonVertexInput.multisample;
3956 
3957     stateOut->rasterLineState.sType =
3958         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT;
3959     // Enable Bresenham line rasterization if available and the following conditions are met:
3960     // 1.) not multisampling
3961     // 2.) VUID-VkGraphicsPipelineCreateInfo-lineRasterizationMode-02766:
3962     // The Vulkan spec states: If the lineRasterizationMode member of a
3963     // VkPipelineRasterizationLineStateCreateInfoEXT structure included in the pNext chain of
3964     // pRasterizationState is VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT or
3965     // VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT and if rasterization is enabled, then the
3966     // alphaToCoverageEnable, alphaToOneEnable, and sampleShadingEnable members of pMultisampleState
3967     // must all be VK_FALSE.
3968     if (multisample.bits.rasterizationSamplesMinusOne == 0 &&
3969         !mShaders.shaders.bits.rasterizerDiscardEnable && !multisample.bits.alphaToCoverageEnable &&
3970         !multisample.bits.alphaToOneEnable && !multisample.bits.sampleShadingEnable &&
3971         context->getFeatures().bresenhamLineRasterization.enabled)
3972     {
3973         stateOut->rasterLineState.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;
3974         *pNextPtr                                       = &stateOut->rasterLineState;
3975         pNextPtr                                        = &stateOut->rasterLineState.pNext;
3976     }
3977 
3978     // Always set provoking vertex mode to last if available.
3979     if (context->getFeatures().provokingVertex.enabled)
3980     {
3981         stateOut->provokingVertexState.sType =
3982             VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT;
3983         stateOut->provokingVertexState.provokingVertexMode =
3984             VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT;
3985         *pNextPtr = &stateOut->provokingVertexState;
3986         pNextPtr  = &stateOut->provokingVertexState.pNext;
3987     }
3988 
3989     if (context->getFeatures().supportsGeometryStreamsCapability.enabled)
3990     {
3991         stateOut->rasterStreamState.sType =
3992             VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT;
3993         stateOut->rasterStreamState.rasterizationStream = 0;
3994         *pNextPtr                                       = &stateOut->rasterStreamState;
3995         pNextPtr                                        = &stateOut->rasterStreamState.pNext;
3996     }
3997 
3998     // Depth/stencil state.
3999     stateOut->depthStencilState.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
4000     stateOut->depthStencilState.flags = 0;
4001     stateOut->depthStencilState.depthTestEnable =
4002         static_cast<VkBool32>(mShaders.shaders.bits.depthTest);
4003     stateOut->depthStencilState.depthWriteEnable =
4004         static_cast<VkBool32>(mShaders.shaders.bits.depthWrite);
4005     stateOut->depthStencilState.depthCompareOp =
4006         static_cast<VkCompareOp>(mShaders.shaders.bits.depthCompareOp);
4007     stateOut->depthStencilState.depthBoundsTestEnable =
4008         static_cast<VkBool32>(mShaders.shaders.bits.depthBoundsTest);
4009     stateOut->depthStencilState.stencilTestEnable =
4010         static_cast<VkBool32>(mShaders.shaders.bits.stencilTest);
4011     UnpackStencilState(mShaders.shaders.front, &stateOut->depthStencilState.front,
4012                        mShaders.shaders.bits.nonZeroStencilWriteMaskWorkaround);
4013     UnpackStencilState(mShaders.shaders.back, &stateOut->depthStencilState.back,
4014                        mShaders.shaders.bits.nonZeroStencilWriteMaskWorkaround);
4015     stateOut->depthStencilState.minDepthBounds = 0;
4016     stateOut->depthStencilState.maxDepthBounds = 0;
4017 
4018     if (getRenderPassDepthStencilFramebufferFetchMode())
4019     {
4020         stateOut->depthStencilState.flags |=
4021             VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT |
4022             VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT;
4023     }
4024 
4025     // tessellation State
4026     if (tessControlPointer && tessEvaluationPointer)
4027     {
4028         stateOut->domainOriginState.sType =
4029             VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO;
4030         stateOut->domainOriginState.pNext        = NULL;
4031         stateOut->domainOriginState.domainOrigin = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT;
4032 
4033         stateOut->tessellationState.sType =
4034             VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
4035         stateOut->tessellationState.flags = 0;
4036         stateOut->tessellationState.pNext = &stateOut->domainOriginState;
4037         stateOut->tessellationState.patchControlPoints =
4038             static_cast<uint32_t>(mShaders.shaders.bits.patchVertices);
4039     }
4040 
4041     // Dynamic state
4042     dynamicStateListOut->push_back(VK_DYNAMIC_STATE_VIEWPORT);
4043     dynamicStateListOut->push_back(VK_DYNAMIC_STATE_SCISSOR);
4044     dynamicStateListOut->push_back(VK_DYNAMIC_STATE_LINE_WIDTH);
4045     dynamicStateListOut->push_back(VK_DYNAMIC_STATE_DEPTH_BIAS);
4046     dynamicStateListOut->push_back(VK_DYNAMIC_STATE_DEPTH_BOUNDS);
4047     dynamicStateListOut->push_back(VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK);
4048     dynamicStateListOut->push_back(VK_DYNAMIC_STATE_STENCIL_WRITE_MASK);
4049     dynamicStateListOut->push_back(VK_DYNAMIC_STATE_STENCIL_REFERENCE);
4050     if (context->getFeatures().useCullModeDynamicState.enabled)
4051     {
4052         dynamicStateListOut->push_back(VK_DYNAMIC_STATE_CULL_MODE_EXT);
4053     }
4054     if (context->getFeatures().useFrontFaceDynamicState.enabled)
4055     {
4056         dynamicStateListOut->push_back(VK_DYNAMIC_STATE_FRONT_FACE_EXT);
4057     }
4058     if (context->getFeatures().useDepthTestEnableDynamicState.enabled)
4059     {
4060         dynamicStateListOut->push_back(VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE);
4061     }
4062     if (context->getFeatures().useDepthWriteEnableDynamicState.enabled)
4063     {
4064         dynamicStateListOut->push_back(VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE);
4065     }
4066     if (context->getFeatures().useDepthCompareOpDynamicState.enabled)
4067     {
4068         dynamicStateListOut->push_back(VK_DYNAMIC_STATE_DEPTH_COMPARE_OP);
4069     }
4070     if (context->getFeatures().useStencilTestEnableDynamicState.enabled)
4071     {
4072         dynamicStateListOut->push_back(VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE);
4073     }
4074     if (context->getFeatures().useStencilOpDynamicState.enabled)
4075     {
4076         dynamicStateListOut->push_back(VK_DYNAMIC_STATE_STENCIL_OP);
4077     }
4078     if (context->getFeatures().useRasterizerDiscardEnableDynamicState.enabled)
4079     {
4080         dynamicStateListOut->push_back(VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE);
4081     }
4082     if (context->getFeatures().useDepthBiasEnableDynamicState.enabled)
4083     {
4084         dynamicStateListOut->push_back(VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE);
4085     }
4086     if (context->getFeatures().supportsFragmentShadingRate.enabled)
4087     {
4088         dynamicStateListOut->push_back(VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR);
4089     }
4090 }
4091 
initializePipelineSharedNonVertexInputState(ErrorContext * context,GraphicsPipelineSharedNonVertexInputVulkanStructs * stateOut,GraphicsPipelineDynamicStateList * dynamicStateListOut) const4092 void GraphicsPipelineDesc::initializePipelineSharedNonVertexInputState(
4093     ErrorContext *context,
4094     GraphicsPipelineSharedNonVertexInputVulkanStructs *stateOut,
4095     GraphicsPipelineDynamicStateList *dynamicStateListOut) const
4096 {
4097     const PackedMultisampleAndSubpassState &multisample = mSharedNonVertexInput.multisample;
4098 
4099     stateOut->sampleMask = multisample.bits.sampleMask;
4100 
4101     // Multisample state.
4102     stateOut->multisampleState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
4103     stateOut->multisampleState.flags = 0;
4104     stateOut->multisampleState.rasterizationSamples =
4105         gl_vk::GetSamples(multisample.bits.rasterizationSamplesMinusOne + 1,
4106                           context->getFeatures().limitSampleCountTo2.enabled);
4107     stateOut->multisampleState.sampleShadingEnable =
4108         static_cast<VkBool32>(multisample.bits.sampleShadingEnable);
4109     stateOut->multisampleState.minSampleShading =
4110         static_cast<float>(multisample.bits.minSampleShading) / kMinSampleShadingScale;
4111     stateOut->multisampleState.pSampleMask = &stateOut->sampleMask;
4112     stateOut->multisampleState.alphaToCoverageEnable =
4113         static_cast<VkBool32>(multisample.bits.alphaToCoverageEnable);
4114     stateOut->multisampleState.alphaToOneEnable =
4115         static_cast<VkBool32>(multisample.bits.alphaToOneEnable);
4116 }
4117 
initializePipelineFragmentOutputState(ErrorContext * context,GraphicsPipelineFragmentOutputVulkanStructs * stateOut,GraphicsPipelineDynamicStateList * dynamicStateListOut) const4118 void GraphicsPipelineDesc::initializePipelineFragmentOutputState(
4119     ErrorContext *context,
4120     GraphicsPipelineFragmentOutputVulkanStructs *stateOut,
4121     GraphicsPipelineDynamicStateList *dynamicStateListOut) const
4122 {
4123     stateOut->blendState.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
4124     stateOut->blendState.flags = 0;
4125     stateOut->blendState.logicOpEnable =
4126         static_cast<VkBool32>(mFragmentOutput.blendMaskAndLogic.bits.logicOpEnable);
4127     stateOut->blendState.logicOp =
4128         static_cast<VkLogicOp>(mFragmentOutput.blendMaskAndLogic.bits.logicOp);
4129     stateOut->blendState.attachmentCount =
4130         static_cast<uint32_t>(mSharedNonVertexInput.renderPass.colorAttachmentRange());
4131     stateOut->blendState.pAttachments = stateOut->blendAttachmentState.data();
4132 
4133     // If this graphics pipeline is for the unresolve operation, correct the color attachment count
4134     // for that subpass.
4135     if ((mSharedNonVertexInput.renderPass.getColorUnresolveAttachmentMask().any() ||
4136          mSharedNonVertexInput.renderPass.hasDepthStencilUnresolveAttachment()) &&
4137         mSharedNonVertexInput.multisample.bits.subpass == 0)
4138     {
4139         stateOut->blendState.attachmentCount = static_cast<uint32_t>(
4140             mSharedNonVertexInput.renderPass.getColorUnresolveAttachmentMask().count());
4141     }
4142 
4143     // Specify rasterization order for color when available and there is framebuffer fetch.  This
4144     // allows implementation of coherent framebuffer fetch / advanced blend.
4145     if (context->getFeatures().supportsRasterizationOrderAttachmentAccess.enabled &&
4146         getRenderPassColorFramebufferFetchMode())
4147     {
4148         stateOut->blendState.flags |=
4149             VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT;
4150     }
4151 
4152     const gl::DrawBufferMask blendEnableMask(
4153         mFragmentOutput.blendMaskAndLogic.bits.blendEnableMask);
4154 
4155     // Zero-init all states.
4156     stateOut->blendAttachmentState = {};
4157 
4158     const PackedColorBlendState &colorBlend = mFragmentOutput.blend;
4159 
4160     // With render pass objects, the blend state is indexed by the subpass-mapped locations.
4161     // With dynamic rendering, it is indexed by the actual attachment index.
4162     uint32_t colorAttachmentIndex = 0;
4163     for (uint32_t colorIndexGL = 0; colorIndexGL < stateOut->blendState.attachmentCount;
4164          ++colorIndexGL)
4165     {
4166         if (context->getFeatures().preferDynamicRendering.enabled &&
4167             !mSharedNonVertexInput.renderPass.isColorAttachmentEnabled(colorIndexGL))
4168         {
4169             continue;
4170         }
4171 
4172         VkPipelineColorBlendAttachmentState &state =
4173             stateOut->blendAttachmentState[colorAttachmentIndex++];
4174 
4175         if (blendEnableMask[colorIndexGL])
4176         {
4177             // To avoid triggering valid usage error, blending must be disabled for formats that do
4178             // not have VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT feature bit set.
4179             // From OpenGL ES clients, this means disabling blending for integer formats.
4180             if (!angle::Format::Get(mSharedNonVertexInput.renderPass[colorIndexGL]).isInt())
4181             {
4182                 ASSERT(!context->getRenderer()
4183                             ->getFormat(mSharedNonVertexInput.renderPass[colorIndexGL])
4184                             .getActualRenderableImageFormat()
4185                             .isInt());
4186 
4187                 // The blend fixed-function is enabled with normal blend as well as advanced blend
4188                 // when the Vulkan extension is present.  When emulating advanced blend in the
4189                 // shader, the blend fixed-function must be disabled.
4190                 const PackedColorBlendAttachmentState &packedBlendState =
4191                     colorBlend.attachments[colorIndexGL];
4192                 if (packedBlendState.colorBlendOp <= static_cast<uint8_t>(VK_BLEND_OP_MAX) ||
4193                     context->getFeatures().supportsBlendOperationAdvanced.enabled)
4194                 {
4195                     state.blendEnable = VK_TRUE;
4196                     UnpackBlendAttachmentState(packedBlendState, &state);
4197                 }
4198             }
4199         }
4200 
4201         ASSERT(context->getRenderer()->getNativeExtensions().robustFragmentShaderOutputANGLE);
4202         if ((mFragmentOutput.blendMaskAndLogic.bits.missingOutputsMask >> colorIndexGL & 1) != 0)
4203         {
4204             state.colorWriteMask = 0;
4205         }
4206         else
4207         {
4208             state.colorWriteMask =
4209                 Int4Array_Get<VkColorComponentFlags>(colorBlend.colorWriteMaskBits, colorIndexGL);
4210         }
4211     }
4212 
4213     if (context->getFeatures().preferDynamicRendering.enabled)
4214     {
4215         stateOut->blendState.attachmentCount = colorAttachmentIndex;
4216     }
4217 
4218     // Dynamic state
4219     dynamicStateListOut->push_back(VK_DYNAMIC_STATE_BLEND_CONSTANTS);
4220     if (context->getFeatures().supportsLogicOpDynamicState.enabled)
4221     {
4222         dynamicStateListOut->push_back(VK_DYNAMIC_STATE_LOGIC_OP_EXT);
4223     }
4224 }
4225 
updateVertexInput(ContextVk * contextVk,GraphicsPipelineTransitionBits * transition,uint32_t attribIndex,GLuint stride,GLuint divisor,angle::FormatID format,bool compressed,GLuint relativeOffset)4226 void GraphicsPipelineDesc::updateVertexInput(ContextVk *contextVk,
4227                                              GraphicsPipelineTransitionBits *transition,
4228                                              uint32_t attribIndex,
4229                                              GLuint stride,
4230                                              GLuint divisor,
4231                                              angle::FormatID format,
4232                                              bool compressed,
4233                                              GLuint relativeOffset)
4234 {
4235     PackedAttribDesc &packedAttrib = mVertexInput.vertex.attribs[attribIndex];
4236 
4237     SetBitField(packedAttrib.divisor, divisor);
4238 
4239     if (format == angle::FormatID::NONE)
4240     {
4241         UNIMPLEMENTED();
4242     }
4243 
4244     SetBitField(packedAttrib.format, format);
4245     SetBitField(packedAttrib.compressed, compressed);
4246     SetBitField(packedAttrib.offset, relativeOffset);
4247 
4248     constexpr size_t kAttribBits = kPackedAttribDescSize * kBitsPerByte;
4249     const size_t kBit =
4250         ANGLE_GET_INDEXED_TRANSITION_BIT(mVertexInput.vertex.attribs, attribIndex, kAttribBits);
4251 
4252     // Each attribute is 4 bytes, so only one transition bit needs to be set.
4253     static_assert(kPackedAttribDescSize == kGraphicsPipelineDirtyBitBytes,
4254                   "Adjust transition bits");
4255     transition->set(kBit);
4256 
4257     if (!contextVk->getFeatures().useVertexInputBindingStrideDynamicState.enabled)
4258     {
4259         SetBitField(mVertexInput.vertex.strides[attribIndex], stride);
4260         transition->set(ANGLE_GET_INDEXED_TRANSITION_BIT(
4261             mVertexInput.vertex.strides, attribIndex,
4262             sizeof(mVertexInput.vertex.strides[0]) * kBitsPerByte));
4263     }
4264 }
4265 
setVertexShaderComponentTypes(gl::AttributesMask activeAttribLocations,gl::ComponentTypeMask componentTypeMask)4266 void GraphicsPipelineDesc::setVertexShaderComponentTypes(gl::AttributesMask activeAttribLocations,
4267                                                          gl::ComponentTypeMask componentTypeMask)
4268 {
4269     SetBitField(mVertexInput.inputAssembly.bits.programActiveAttributeLocations,
4270                 activeAttribLocations.bits());
4271 
4272     const gl::ComponentTypeMask activeComponentTypeMask =
4273         componentTypeMask & gl::GetActiveComponentTypeMask(activeAttribLocations);
4274 
4275     SetBitField(mVertexInput.vertex.shaderAttribComponentType, activeComponentTypeMask.bits());
4276 }
4277 
updateVertexShaderComponentTypes(GraphicsPipelineTransitionBits * transition,gl::AttributesMask activeAttribLocations,gl::ComponentTypeMask componentTypeMask)4278 void GraphicsPipelineDesc::updateVertexShaderComponentTypes(
4279     GraphicsPipelineTransitionBits *transition,
4280     gl::AttributesMask activeAttribLocations,
4281     gl::ComponentTypeMask componentTypeMask)
4282 {
4283     if (mVertexInput.inputAssembly.bits.programActiveAttributeLocations !=
4284         activeAttribLocations.bits())
4285     {
4286         SetBitField(mVertexInput.inputAssembly.bits.programActiveAttributeLocations,
4287                     activeAttribLocations.bits());
4288         transition->set(ANGLE_GET_TRANSITION_BIT(mVertexInput.inputAssembly.bits));
4289     }
4290 
4291     const gl::ComponentTypeMask activeComponentTypeMask =
4292         componentTypeMask & gl::GetActiveComponentTypeMask(activeAttribLocations);
4293 
4294     if (mVertexInput.vertex.shaderAttribComponentType != activeComponentTypeMask.bits())
4295     {
4296         SetBitField(mVertexInput.vertex.shaderAttribComponentType, activeComponentTypeMask.bits());
4297         transition->set(ANGLE_GET_TRANSITION_BIT(mVertexInput.vertex.shaderAttribComponentType));
4298     }
4299 }
4300 
setTopology(gl::PrimitiveMode drawMode)4301 void GraphicsPipelineDesc::setTopology(gl::PrimitiveMode drawMode)
4302 {
4303     VkPrimitiveTopology vkTopology = gl_vk::GetPrimitiveTopology(drawMode);
4304     SetBitField(mVertexInput.inputAssembly.bits.topology, vkTopology);
4305 }
4306 
updateTopology(GraphicsPipelineTransitionBits * transition,gl::PrimitiveMode drawMode)4307 void GraphicsPipelineDesc::updateTopology(GraphicsPipelineTransitionBits *transition,
4308                                           gl::PrimitiveMode drawMode)
4309 {
4310     setTopology(drawMode);
4311     transition->set(ANGLE_GET_TRANSITION_BIT(mVertexInput.inputAssembly.bits));
4312 }
4313 
updateDepthClipControl(GraphicsPipelineTransitionBits * transition,bool negativeOneToOne)4314 void GraphicsPipelineDesc::updateDepthClipControl(GraphicsPipelineTransitionBits *transition,
4315                                                   bool negativeOneToOne)
4316 {
4317     SetBitField(mShaders.shaders.bits.viewportNegativeOneToOne, negativeOneToOne);
4318     transition->set(ANGLE_GET_TRANSITION_BIT(mShaders.shaders.bits));
4319 }
4320 
updatePrimitiveRestartEnabled(GraphicsPipelineTransitionBits * transition,bool primitiveRestartEnabled)4321 void GraphicsPipelineDesc::updatePrimitiveRestartEnabled(GraphicsPipelineTransitionBits *transition,
4322                                                          bool primitiveRestartEnabled)
4323 {
4324     mVertexInput.inputAssembly.bits.primitiveRestartEnable =
4325         static_cast<uint16_t>(primitiveRestartEnabled);
4326     transition->set(ANGLE_GET_TRANSITION_BIT(mVertexInput.inputAssembly.bits));
4327 }
4328 
updatePolygonMode(GraphicsPipelineTransitionBits * transition,gl::PolygonMode polygonMode)4329 void GraphicsPipelineDesc::updatePolygonMode(GraphicsPipelineTransitionBits *transition,
4330                                              gl::PolygonMode polygonMode)
4331 {
4332     mShaders.shaders.bits.polygonMode = gl_vk::GetPolygonMode(polygonMode);
4333     transition->set(ANGLE_GET_TRANSITION_BIT(mShaders.shaders.bits));
4334 }
4335 
updateCullMode(GraphicsPipelineTransitionBits * transition,const gl::RasterizerState & rasterState)4336 void GraphicsPipelineDesc::updateCullMode(GraphicsPipelineTransitionBits *transition,
4337                                           const gl::RasterizerState &rasterState)
4338 {
4339     SetBitField(mShaders.shaders.bits.cullMode, gl_vk::GetCullMode(rasterState));
4340     transition->set(ANGLE_GET_TRANSITION_BIT(mShaders.shaders.bits));
4341 }
4342 
updateFrontFace(GraphicsPipelineTransitionBits * transition,const gl::RasterizerState & rasterState,bool invertFrontFace)4343 void GraphicsPipelineDesc::updateFrontFace(GraphicsPipelineTransitionBits *transition,
4344                                            const gl::RasterizerState &rasterState,
4345                                            bool invertFrontFace)
4346 {
4347     SetBitField(mShaders.shaders.bits.frontFace,
4348                 gl_vk::GetFrontFace(rasterState.frontFace, invertFrontFace));
4349     transition->set(ANGLE_GET_TRANSITION_BIT(mShaders.shaders.bits));
4350 }
4351 
updateRasterizerDiscardEnabled(GraphicsPipelineTransitionBits * transition,bool rasterizerDiscardEnabled)4352 void GraphicsPipelineDesc::updateRasterizerDiscardEnabled(
4353     GraphicsPipelineTransitionBits *transition,
4354     bool rasterizerDiscardEnabled)
4355 {
4356     mShaders.shaders.bits.rasterizerDiscardEnable = static_cast<uint32_t>(rasterizerDiscardEnabled);
4357     transition->set(ANGLE_GET_TRANSITION_BIT(mShaders.shaders.bits));
4358 }
4359 
getRasterizationSamples() const4360 uint32_t GraphicsPipelineDesc::getRasterizationSamples() const
4361 {
4362     return mSharedNonVertexInput.multisample.bits.rasterizationSamplesMinusOne + 1;
4363 }
4364 
setRasterizationSamples(uint32_t rasterizationSamples)4365 void GraphicsPipelineDesc::setRasterizationSamples(uint32_t rasterizationSamples)
4366 {
4367     ASSERT(rasterizationSamples > 0);
4368     mSharedNonVertexInput.multisample.bits.rasterizationSamplesMinusOne = rasterizationSamples - 1;
4369 }
4370 
updateRasterizationSamples(GraphicsPipelineTransitionBits * transition,uint32_t rasterizationSamples)4371 void GraphicsPipelineDesc::updateRasterizationSamples(GraphicsPipelineTransitionBits *transition,
4372                                                       uint32_t rasterizationSamples)
4373 {
4374     setRasterizationSamples(rasterizationSamples);
4375     transition->set(ANGLE_GET_TRANSITION_BIT(mSharedNonVertexInput.multisample.bits));
4376 }
4377 
updateAlphaToCoverageEnable(GraphicsPipelineTransitionBits * transition,bool enable)4378 void GraphicsPipelineDesc::updateAlphaToCoverageEnable(GraphicsPipelineTransitionBits *transition,
4379                                                        bool enable)
4380 {
4381     mSharedNonVertexInput.multisample.bits.alphaToCoverageEnable = enable;
4382     transition->set(ANGLE_GET_TRANSITION_BIT(mSharedNonVertexInput.multisample.bits));
4383 }
4384 
updateAlphaToOneEnable(GraphicsPipelineTransitionBits * transition,bool enable)4385 void GraphicsPipelineDesc::updateAlphaToOneEnable(GraphicsPipelineTransitionBits *transition,
4386                                                   bool enable)
4387 {
4388     mSharedNonVertexInput.multisample.bits.alphaToOneEnable = enable;
4389     transition->set(ANGLE_GET_TRANSITION_BIT(mSharedNonVertexInput.multisample.bits));
4390 }
4391 
updateSampleMask(GraphicsPipelineTransitionBits * transition,uint32_t maskNumber,uint32_t mask)4392 void GraphicsPipelineDesc::updateSampleMask(GraphicsPipelineTransitionBits *transition,
4393                                             uint32_t maskNumber,
4394                                             uint32_t mask)
4395 {
4396     ASSERT(maskNumber == 0);
4397     SetBitField(mSharedNonVertexInput.multisample.bits.sampleMask, mask);
4398 
4399     transition->set(ANGLE_GET_TRANSITION_BIT(mSharedNonVertexInput.multisample.bits));
4400 }
4401 
updateSampleShading(GraphicsPipelineTransitionBits * transition,bool enable,float value)4402 void GraphicsPipelineDesc::updateSampleShading(GraphicsPipelineTransitionBits *transition,
4403                                                bool enable,
4404                                                float value)
4405 {
4406     mSharedNonVertexInput.multisample.bits.sampleShadingEnable = enable;
4407     if (enable)
4408     {
4409         SetBitField(mSharedNonVertexInput.multisample.bits.minSampleShading,
4410                     static_cast<uint16_t>(value * kMinSampleShadingScale));
4411     }
4412     else
4413     {
4414         mSharedNonVertexInput.multisample.bits.minSampleShading = kMinSampleShadingScale;
4415     }
4416 
4417     transition->set(ANGLE_GET_TRANSITION_BIT(mSharedNonVertexInput.multisample.bits));
4418 }
4419 
setSingleBlend(uint32_t colorIndexGL,bool enabled,VkBlendOp op,VkBlendFactor srcFactor,VkBlendFactor dstFactor)4420 void GraphicsPipelineDesc::setSingleBlend(uint32_t colorIndexGL,
4421                                           bool enabled,
4422                                           VkBlendOp op,
4423                                           VkBlendFactor srcFactor,
4424                                           VkBlendFactor dstFactor)
4425 {
4426     mFragmentOutput.blendMaskAndLogic.bits.blendEnableMask |=
4427         static_cast<uint8_t>(1 << colorIndexGL);
4428 
4429     PackedColorBlendAttachmentState &blendAttachmentState =
4430         mFragmentOutput.blend.attachments[colorIndexGL];
4431 
4432     SetBitField(blendAttachmentState.colorBlendOp, op);
4433     SetBitField(blendAttachmentState.alphaBlendOp, op);
4434 
4435     SetBitField(blendAttachmentState.srcColorBlendFactor, srcFactor);
4436     SetBitField(blendAttachmentState.dstColorBlendFactor, dstFactor);
4437     SetBitField(blendAttachmentState.srcAlphaBlendFactor, VK_BLEND_FACTOR_ZERO);
4438     SetBitField(blendAttachmentState.dstAlphaBlendFactor, VK_BLEND_FACTOR_ONE);
4439 }
4440 
updateBlendEnabled(GraphicsPipelineTransitionBits * transition,gl::DrawBufferMask blendEnabledMask)4441 void GraphicsPipelineDesc::updateBlendEnabled(GraphicsPipelineTransitionBits *transition,
4442                                               gl::DrawBufferMask blendEnabledMask)
4443 {
4444     SetBitField(mFragmentOutput.blendMaskAndLogic.bits.blendEnableMask, blendEnabledMask.bits());
4445     transition->set(ANGLE_GET_TRANSITION_BIT(mFragmentOutput.blendMaskAndLogic.bits));
4446 }
4447 
updateBlendEquations(GraphicsPipelineTransitionBits * transition,const gl::BlendStateExt & blendStateExt,gl::DrawBufferMask attachmentMask)4448 void GraphicsPipelineDesc::updateBlendEquations(GraphicsPipelineTransitionBits *transition,
4449                                                 const gl::BlendStateExt &blendStateExt,
4450                                                 gl::DrawBufferMask attachmentMask)
4451 {
4452     constexpr size_t kSizeBits = sizeof(PackedColorBlendAttachmentState) * 8;
4453 
4454     for (size_t attachmentIndex : attachmentMask)
4455     {
4456         PackedColorBlendAttachmentState &blendAttachmentState =
4457             mFragmentOutput.blend.attachments[attachmentIndex];
4458         blendAttachmentState.colorBlendOp =
4459             PackGLBlendOp(blendStateExt.getEquationColorIndexed(attachmentIndex));
4460         blendAttachmentState.alphaBlendOp =
4461             PackGLBlendOp(blendStateExt.getEquationAlphaIndexed(attachmentIndex));
4462         transition->set(ANGLE_GET_INDEXED_TRANSITION_BIT(mFragmentOutput.blend.attachments,
4463                                                          attachmentIndex, kSizeBits));
4464     }
4465 }
4466 
updateBlendFuncs(GraphicsPipelineTransitionBits * transition,const gl::BlendStateExt & blendStateExt,gl::DrawBufferMask attachmentMask)4467 void GraphicsPipelineDesc::updateBlendFuncs(GraphicsPipelineTransitionBits *transition,
4468                                             const gl::BlendStateExt &blendStateExt,
4469                                             gl::DrawBufferMask attachmentMask)
4470 {
4471     constexpr size_t kSizeBits = sizeof(PackedColorBlendAttachmentState) * 8;
4472     for (size_t attachmentIndex : attachmentMask)
4473     {
4474         PackedColorBlendAttachmentState &blendAttachmentState =
4475             mFragmentOutput.blend.attachments[attachmentIndex];
4476         blendAttachmentState.srcColorBlendFactor =
4477             PackGLBlendFactor(blendStateExt.getSrcColorIndexed(attachmentIndex));
4478         blendAttachmentState.dstColorBlendFactor =
4479             PackGLBlendFactor(blendStateExt.getDstColorIndexed(attachmentIndex));
4480         blendAttachmentState.srcAlphaBlendFactor =
4481             PackGLBlendFactor(blendStateExt.getSrcAlphaIndexed(attachmentIndex));
4482         blendAttachmentState.dstAlphaBlendFactor =
4483             PackGLBlendFactor(blendStateExt.getDstAlphaIndexed(attachmentIndex));
4484         transition->set(ANGLE_GET_INDEXED_TRANSITION_BIT(mFragmentOutput.blend.attachments,
4485                                                          attachmentIndex, kSizeBits));
4486     }
4487 }
4488 
resetBlendFuncsAndEquations(GraphicsPipelineTransitionBits * transition,const gl::BlendStateExt & blendStateExt,gl::DrawBufferMask previousAttachmentsMask,gl::DrawBufferMask newAttachmentsMask)4489 void GraphicsPipelineDesc::resetBlendFuncsAndEquations(GraphicsPipelineTransitionBits *transition,
4490                                                        const gl::BlendStateExt &blendStateExt,
4491                                                        gl::DrawBufferMask previousAttachmentsMask,
4492                                                        gl::DrawBufferMask newAttachmentsMask)
4493 {
4494     // A framebuffer with attachments in P was bound, and now one with attachments in N is bound.
4495     // We need to clear blend funcs and equations for attachments in P that are not in N.  That is
4496     // attachments in P&~N.
4497     const gl::DrawBufferMask attachmentsToClear = previousAttachmentsMask & ~newAttachmentsMask;
4498     // We also need to restore blend funcs and equations for attachments in N that are not in P.
4499     const gl::DrawBufferMask attachmentsToAdd = newAttachmentsMask & ~previousAttachmentsMask;
4500     constexpr size_t kSizeBits                = sizeof(PackedColorBlendAttachmentState) * 8;
4501 
4502     for (size_t attachmentIndex : attachmentsToClear)
4503     {
4504         PackedColorBlendAttachmentState &blendAttachmentState =
4505             mFragmentOutput.blend.attachments[attachmentIndex];
4506 
4507         blendAttachmentState.colorBlendOp        = VK_BLEND_OP_ADD;
4508         blendAttachmentState.alphaBlendOp        = VK_BLEND_OP_ADD;
4509         blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_ONE;
4510         blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO;
4511         blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
4512         blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
4513 
4514         transition->set(ANGLE_GET_INDEXED_TRANSITION_BIT(mFragmentOutput.blend.attachments,
4515                                                          attachmentIndex, kSizeBits));
4516     }
4517 
4518     if (attachmentsToAdd.any())
4519     {
4520         updateBlendFuncs(transition, blendStateExt, attachmentsToAdd);
4521         updateBlendEquations(transition, blendStateExt, attachmentsToAdd);
4522     }
4523 }
4524 
setColorWriteMasks(gl::BlendStateExt::ColorMaskStorage::Type colorMasks,const gl::DrawBufferMask & alphaMask,const gl::DrawBufferMask & enabledDrawBuffers)4525 void GraphicsPipelineDesc::setColorWriteMasks(gl::BlendStateExt::ColorMaskStorage::Type colorMasks,
4526                                               const gl::DrawBufferMask &alphaMask,
4527                                               const gl::DrawBufferMask &enabledDrawBuffers)
4528 {
4529     for (uint32_t colorIndexGL = 0; colorIndexGL < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
4530          colorIndexGL++)
4531     {
4532         uint8_t colorMask =
4533             gl::BlendStateExt::ColorMaskStorage::GetValueIndexed(colorIndexGL, colorMasks);
4534 
4535         uint8_t mask = 0;
4536         if (enabledDrawBuffers.test(colorIndexGL))
4537         {
4538             mask = alphaMask[colorIndexGL] ? (colorMask & ~VK_COLOR_COMPONENT_A_BIT) : colorMask;
4539         }
4540         Int4Array_Set(mFragmentOutput.blend.colorWriteMaskBits, colorIndexGL, mask);
4541     }
4542 }
4543 
setSingleColorWriteMask(uint32_t colorIndexGL,VkColorComponentFlags colorComponentFlags)4544 void GraphicsPipelineDesc::setSingleColorWriteMask(uint32_t colorIndexGL,
4545                                                    VkColorComponentFlags colorComponentFlags)
4546 {
4547     uint8_t colorMask = static_cast<uint8_t>(colorComponentFlags);
4548     Int4Array_Set(mFragmentOutput.blend.colorWriteMaskBits, colorIndexGL, colorMask);
4549 }
4550 
updateColorWriteMasks(GraphicsPipelineTransitionBits * transition,gl::BlendStateExt::ColorMaskStorage::Type colorMasks,const gl::DrawBufferMask & alphaMask,const gl::DrawBufferMask & enabledDrawBuffers)4551 void GraphicsPipelineDesc::updateColorWriteMasks(
4552     GraphicsPipelineTransitionBits *transition,
4553     gl::BlendStateExt::ColorMaskStorage::Type colorMasks,
4554     const gl::DrawBufferMask &alphaMask,
4555     const gl::DrawBufferMask &enabledDrawBuffers)
4556 {
4557     setColorWriteMasks(colorMasks, alphaMask, enabledDrawBuffers);
4558 
4559     for (size_t colorIndexGL = 0; colorIndexGL < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
4560          colorIndexGL++)
4561     {
4562         transition->set(ANGLE_GET_INDEXED_TRANSITION_BIT(mFragmentOutput.blend.colorWriteMaskBits,
4563                                                          colorIndexGL, 4));
4564     }
4565 }
4566 
updateMissingOutputsMask(GraphicsPipelineTransitionBits * transition,gl::DrawBufferMask missingOutputsMask)4567 void GraphicsPipelineDesc::updateMissingOutputsMask(GraphicsPipelineTransitionBits *transition,
4568                                                     gl::DrawBufferMask missingOutputsMask)
4569 {
4570     if (mFragmentOutput.blendMaskAndLogic.bits.missingOutputsMask != missingOutputsMask.bits())
4571     {
4572         SetBitField(mFragmentOutput.blendMaskAndLogic.bits.missingOutputsMask,
4573                     missingOutputsMask.bits());
4574         transition->set(ANGLE_GET_TRANSITION_BIT(mFragmentOutput.blendMaskAndLogic.bits));
4575     }
4576 }
4577 
updateLogicOpEnabled(GraphicsPipelineTransitionBits * transition,bool enable)4578 void GraphicsPipelineDesc::updateLogicOpEnabled(GraphicsPipelineTransitionBits *transition,
4579                                                 bool enable)
4580 {
4581     mFragmentOutput.blendMaskAndLogic.bits.logicOpEnable = enable;
4582     transition->set(ANGLE_GET_TRANSITION_BIT(mFragmentOutput.blendMaskAndLogic.bits));
4583 }
4584 
updateLogicOp(GraphicsPipelineTransitionBits * transition,VkLogicOp logicOp)4585 void GraphicsPipelineDesc::updateLogicOp(GraphicsPipelineTransitionBits *transition,
4586                                          VkLogicOp logicOp)
4587 {
4588     SetBitField(mFragmentOutput.blendMaskAndLogic.bits.logicOp, logicOp);
4589     transition->set(ANGLE_GET_TRANSITION_BIT(mFragmentOutput.blendMaskAndLogic.bits));
4590 }
4591 
setDepthTestEnabled(bool enabled)4592 void GraphicsPipelineDesc::setDepthTestEnabled(bool enabled)
4593 {
4594     mShaders.shaders.bits.depthTest = enabled;
4595 }
4596 
setDepthWriteEnabled(bool enabled)4597 void GraphicsPipelineDesc::setDepthWriteEnabled(bool enabled)
4598 {
4599     mShaders.shaders.bits.depthWrite = enabled;
4600 }
4601 
setDepthFunc(VkCompareOp op)4602 void GraphicsPipelineDesc::setDepthFunc(VkCompareOp op)
4603 {
4604     SetBitField(mShaders.shaders.bits.depthCompareOp, op);
4605 }
4606 
setDepthClampEnabled(bool enabled)4607 void GraphicsPipelineDesc::setDepthClampEnabled(bool enabled)
4608 {
4609     mShaders.shaders.bits.depthClampEnable = enabled;
4610 }
4611 
setStencilTestEnabled(bool enabled)4612 void GraphicsPipelineDesc::setStencilTestEnabled(bool enabled)
4613 {
4614     mShaders.shaders.bits.stencilTest = enabled;
4615 }
4616 
setStencilFrontFuncs(VkCompareOp compareOp)4617 void GraphicsPipelineDesc::setStencilFrontFuncs(VkCompareOp compareOp)
4618 {
4619     SetBitField(mShaders.shaders.front.compare, compareOp);
4620 }
4621 
setStencilBackFuncs(VkCompareOp compareOp)4622 void GraphicsPipelineDesc::setStencilBackFuncs(VkCompareOp compareOp)
4623 {
4624     SetBitField(mShaders.shaders.back.compare, compareOp);
4625 }
4626 
setStencilFrontOps(VkStencilOp failOp,VkStencilOp passOp,VkStencilOp depthFailOp)4627 void GraphicsPipelineDesc::setStencilFrontOps(VkStencilOp failOp,
4628                                               VkStencilOp passOp,
4629                                               VkStencilOp depthFailOp)
4630 {
4631     SetBitField(mShaders.shaders.front.fail, failOp);
4632     SetBitField(mShaders.shaders.front.pass, passOp);
4633     SetBitField(mShaders.shaders.front.depthFail, depthFailOp);
4634 }
4635 
setStencilBackOps(VkStencilOp failOp,VkStencilOp passOp,VkStencilOp depthFailOp)4636 void GraphicsPipelineDesc::setStencilBackOps(VkStencilOp failOp,
4637                                              VkStencilOp passOp,
4638                                              VkStencilOp depthFailOp)
4639 {
4640     SetBitField(mShaders.shaders.back.fail, failOp);
4641     SetBitField(mShaders.shaders.back.pass, passOp);
4642     SetBitField(mShaders.shaders.back.depthFail, depthFailOp);
4643 }
4644 
updateDepthTestEnabled(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState,const gl::Framebuffer * drawFramebuffer)4645 void GraphicsPipelineDesc::updateDepthTestEnabled(GraphicsPipelineTransitionBits *transition,
4646                                                   const gl::DepthStencilState &depthStencilState,
4647                                                   const gl::Framebuffer *drawFramebuffer)
4648 {
4649     // Only enable the depth test if the draw framebuffer has a depth buffer.  It's possible that
4650     // we're emulating a stencil-only buffer with a depth-stencil buffer
4651     setDepthTestEnabled(depthStencilState.depthTest && drawFramebuffer->hasDepth());
4652     transition->set(ANGLE_GET_TRANSITION_BIT(mShaders.shaders.bits));
4653 }
4654 
updateDepthFunc(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState)4655 void GraphicsPipelineDesc::updateDepthFunc(GraphicsPipelineTransitionBits *transition,
4656                                            const gl::DepthStencilState &depthStencilState)
4657 {
4658     setDepthFunc(gl_vk::GetCompareOp(depthStencilState.depthFunc));
4659     transition->set(ANGLE_GET_TRANSITION_BIT(mShaders.shaders.bits));
4660 }
4661 
updateDepthClampEnabled(GraphicsPipelineTransitionBits * transition,bool enabled)4662 void GraphicsPipelineDesc::updateDepthClampEnabled(GraphicsPipelineTransitionBits *transition,
4663                                                    bool enabled)
4664 {
4665     setDepthClampEnabled(enabled);
4666     transition->set(ANGLE_GET_TRANSITION_BIT(mShaders.shaders.bits));
4667 }
4668 
updateSurfaceRotation(GraphicsPipelineTransitionBits * transition,bool isRotatedAspectRatio)4669 void GraphicsPipelineDesc::updateSurfaceRotation(GraphicsPipelineTransitionBits *transition,
4670                                                  bool isRotatedAspectRatio)
4671 {
4672     SetBitField(mShaders.shaders.bits.surfaceRotation, isRotatedAspectRatio);
4673     transition->set(ANGLE_GET_TRANSITION_BIT(mShaders.shaders.bits));
4674 }
4675 
updateDepthWriteEnabled(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState,const gl::Framebuffer * drawFramebuffer)4676 void GraphicsPipelineDesc::updateDepthWriteEnabled(GraphicsPipelineTransitionBits *transition,
4677                                                    const gl::DepthStencilState &depthStencilState,
4678                                                    const gl::Framebuffer *drawFramebuffer)
4679 {
4680     // Don't write to depth buffers that should not exist
4681     const bool depthWriteEnabled =
4682         drawFramebuffer->hasDepth() && depthStencilState.depthTest && depthStencilState.depthMask;
4683     if (static_cast<bool>(mShaders.shaders.bits.depthWrite) != depthWriteEnabled)
4684     {
4685         setDepthWriteEnabled(depthWriteEnabled);
4686         transition->set(ANGLE_GET_TRANSITION_BIT(mShaders.shaders.bits));
4687     }
4688 }
4689 
updateStencilTestEnabled(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState,const gl::Framebuffer * drawFramebuffer)4690 void GraphicsPipelineDesc::updateStencilTestEnabled(GraphicsPipelineTransitionBits *transition,
4691                                                     const gl::DepthStencilState &depthStencilState,
4692                                                     const gl::Framebuffer *drawFramebuffer)
4693 {
4694     // Only enable the stencil test if the draw framebuffer has a stencil buffer.  It's possible
4695     // that we're emulating a depth-only buffer with a depth-stencil buffer
4696     setStencilTestEnabled(depthStencilState.stencilTest && drawFramebuffer->hasStencil());
4697     transition->set(ANGLE_GET_TRANSITION_BIT(mShaders.shaders.bits));
4698 }
4699 
updateStencilFrontFuncs(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState)4700 void GraphicsPipelineDesc::updateStencilFrontFuncs(GraphicsPipelineTransitionBits *transition,
4701                                                    const gl::DepthStencilState &depthStencilState)
4702 {
4703     setStencilFrontFuncs(gl_vk::GetCompareOp(depthStencilState.stencilFunc));
4704     transition->set(ANGLE_GET_TRANSITION_BIT(mShaders.shaders.front));
4705 }
4706 
updateStencilBackFuncs(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState)4707 void GraphicsPipelineDesc::updateStencilBackFuncs(GraphicsPipelineTransitionBits *transition,
4708                                                   const gl::DepthStencilState &depthStencilState)
4709 {
4710     setStencilBackFuncs(gl_vk::GetCompareOp(depthStencilState.stencilBackFunc));
4711     transition->set(ANGLE_GET_TRANSITION_BIT(mShaders.shaders.back));
4712 }
4713 
updateStencilFrontOps(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState)4714 void GraphicsPipelineDesc::updateStencilFrontOps(GraphicsPipelineTransitionBits *transition,
4715                                                  const gl::DepthStencilState &depthStencilState)
4716 {
4717     setStencilFrontOps(gl_vk::GetStencilOp(depthStencilState.stencilFail),
4718                        gl_vk::GetStencilOp(depthStencilState.stencilPassDepthPass),
4719                        gl_vk::GetStencilOp(depthStencilState.stencilPassDepthFail));
4720     transition->set(ANGLE_GET_TRANSITION_BIT(mShaders.shaders.front));
4721 }
4722 
updateStencilBackOps(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState)4723 void GraphicsPipelineDesc::updateStencilBackOps(GraphicsPipelineTransitionBits *transition,
4724                                                 const gl::DepthStencilState &depthStencilState)
4725 {
4726     setStencilBackOps(gl_vk::GetStencilOp(depthStencilState.stencilBackFail),
4727                       gl_vk::GetStencilOp(depthStencilState.stencilBackPassDepthPass),
4728                       gl_vk::GetStencilOp(depthStencilState.stencilBackPassDepthFail));
4729     transition->set(ANGLE_GET_TRANSITION_BIT(mShaders.shaders.back));
4730 }
4731 
updatePolygonOffsetEnabled(GraphicsPipelineTransitionBits * transition,bool enabled)4732 void GraphicsPipelineDesc::updatePolygonOffsetEnabled(GraphicsPipelineTransitionBits *transition,
4733                                                       bool enabled)
4734 {
4735     mShaders.shaders.bits.depthBiasEnable = enabled;
4736     transition->set(ANGLE_GET_TRANSITION_BIT(mShaders.shaders.bits));
4737 }
4738 
setRenderPassDesc(const RenderPassDesc & renderPassDesc)4739 void GraphicsPipelineDesc::setRenderPassDesc(const RenderPassDesc &renderPassDesc)
4740 {
4741     mSharedNonVertexInput.renderPass = renderPassDesc;
4742 }
4743 
updateSubpass(GraphicsPipelineTransitionBits * transition,uint32_t subpass)4744 void GraphicsPipelineDesc::updateSubpass(GraphicsPipelineTransitionBits *transition,
4745                                          uint32_t subpass)
4746 {
4747     if (mSharedNonVertexInput.multisample.bits.subpass != subpass)
4748     {
4749         SetBitField(mSharedNonVertexInput.multisample.bits.subpass, subpass);
4750         transition->set(ANGLE_GET_TRANSITION_BIT(mSharedNonVertexInput.multisample.bits));
4751     }
4752 }
4753 
updatePatchVertices(GraphicsPipelineTransitionBits * transition,GLuint value)4754 void GraphicsPipelineDesc::updatePatchVertices(GraphicsPipelineTransitionBits *transition,
4755                                                GLuint value)
4756 {
4757     SetBitField(mShaders.shaders.bits.patchVertices, value);
4758     transition->set(ANGLE_GET_TRANSITION_BIT(mShaders.shaders.bits));
4759 }
4760 
resetSubpass(GraphicsPipelineTransitionBits * transition)4761 void GraphicsPipelineDesc::resetSubpass(GraphicsPipelineTransitionBits *transition)
4762 {
4763     updateSubpass(transition, 0);
4764 }
4765 
nextSubpass(GraphicsPipelineTransitionBits * transition)4766 void GraphicsPipelineDesc::nextSubpass(GraphicsPipelineTransitionBits *transition)
4767 {
4768     updateSubpass(transition, mSharedNonVertexInput.multisample.bits.subpass + 1);
4769 }
4770 
setSubpass(uint32_t subpass)4771 void GraphicsPipelineDesc::setSubpass(uint32_t subpass)
4772 {
4773     SetBitField(mSharedNonVertexInput.multisample.bits.subpass, subpass);
4774 }
4775 
getSubpass() const4776 uint32_t GraphicsPipelineDesc::getSubpass() const
4777 {
4778     return mSharedNonVertexInput.multisample.bits.subpass;
4779 }
4780 
updateEmulatedDitherControl(GraphicsPipelineTransitionBits * transition,uint16_t value)4781 void GraphicsPipelineDesc::updateEmulatedDitherControl(GraphicsPipelineTransitionBits *transition,
4782                                                        uint16_t value)
4783 {
4784     // Make sure we don't waste time resetting this to zero in the common no-dither case.
4785     ASSERT(value != 0 || mShaders.shaders.emulatedDitherControl != 0);
4786 
4787     mShaders.shaders.emulatedDitherControl = value;
4788     transition->set(ANGLE_GET_TRANSITION_BIT(mShaders.shaders.emulatedDitherControl));
4789 }
4790 
updateNonZeroStencilWriteMaskWorkaround(GraphicsPipelineTransitionBits * transition,bool enabled)4791 void GraphicsPipelineDesc::updateNonZeroStencilWriteMaskWorkaround(
4792     GraphicsPipelineTransitionBits *transition,
4793     bool enabled)
4794 {
4795     mShaders.shaders.bits.nonZeroStencilWriteMaskWorkaround = enabled;
4796     transition->set(ANGLE_GET_TRANSITION_BIT(mShaders.shaders.bits));
4797 }
4798 
updateRenderPassDesc(GraphicsPipelineTransitionBits * transition,const angle::FeaturesVk & features,const RenderPassDesc & renderPassDesc,FramebufferFetchMode framebufferFetchMode)4799 void GraphicsPipelineDesc::updateRenderPassDesc(GraphicsPipelineTransitionBits *transition,
4800                                                 const angle::FeaturesVk &features,
4801                                                 const RenderPassDesc &renderPassDesc,
4802                                                 FramebufferFetchMode framebufferFetchMode)
4803 {
4804     setRenderPassDesc(renderPassDesc);
4805 
4806     // Framebuffer fetch mode is an inherent property of the executable.  With dynamic rendering, it
4807     // is not tracked in the framebuffer's render pass desc (the source of |renderPassDesc|), and is
4808     // overriden at this point.
4809     if (features.preferDynamicRendering.enabled)
4810     {
4811         setRenderPassFramebufferFetchMode(framebufferFetchMode);
4812     }
4813 
4814     // The RenderPass is a special case where it spans multiple bits but has no member.
4815     constexpr size_t kFirstBit =
4816         offsetof(GraphicsPipelineDesc, mSharedNonVertexInput.renderPass) >> kTransitionByteShift;
4817     constexpr size_t kBitCount = kRenderPassDescSize >> kTransitionByteShift;
4818     for (size_t bit = 0; bit < kBitCount; ++bit)
4819     {
4820         transition->set(kFirstBit + bit);
4821     }
4822 }
4823 
setRenderPassSampleCount(GLint samples)4824 void GraphicsPipelineDesc::setRenderPassSampleCount(GLint samples)
4825 {
4826     mSharedNonVertexInput.renderPass.setSamples(samples);
4827 }
4828 
setRenderPassFramebufferFetchMode(FramebufferFetchMode framebufferFetchMode)4829 void GraphicsPipelineDesc::setRenderPassFramebufferFetchMode(
4830     FramebufferFetchMode framebufferFetchMode)
4831 {
4832     mSharedNonVertexInput.renderPass.setFramebufferFetchMode(framebufferFetchMode);
4833 }
4834 
setRenderPassColorAttachmentFormat(size_t colorIndexGL,angle::FormatID formatID)4835 void GraphicsPipelineDesc::setRenderPassColorAttachmentFormat(size_t colorIndexGL,
4836                                                               angle::FormatID formatID)
4837 {
4838     mSharedNonVertexInput.renderPass.packColorAttachment(colorIndexGL, formatID);
4839 }
4840 
setRenderPassFoveation(bool isFoveated)4841 void GraphicsPipelineDesc::setRenderPassFoveation(bool isFoveated)
4842 {
4843     mSharedNonVertexInput.renderPass.setFragmentShadingAttachment(isFoveated);
4844 }
4845 
4846 // AttachmentOpsArray implementation.
AttachmentOpsArray()4847 AttachmentOpsArray::AttachmentOpsArray()
4848 {
4849     memset(&mOps, 0, sizeof(PackedAttachmentOpsDesc) * mOps.size());
4850 }
4851 
4852 AttachmentOpsArray::~AttachmentOpsArray() = default;
4853 
AttachmentOpsArray(const AttachmentOpsArray & other)4854 AttachmentOpsArray::AttachmentOpsArray(const AttachmentOpsArray &other)
4855 {
4856     memcpy(&mOps, &other.mOps, sizeof(PackedAttachmentOpsDesc) * mOps.size());
4857 }
4858 
operator =(const AttachmentOpsArray & other)4859 AttachmentOpsArray &AttachmentOpsArray::operator=(const AttachmentOpsArray &other)
4860 {
4861     memcpy(&mOps, &other.mOps, sizeof(PackedAttachmentOpsDesc) * mOps.size());
4862     return *this;
4863 }
4864 
initWithLoadStore(PackedAttachmentIndex index,ImageLayout initialLayout,ImageLayout finalLayout)4865 void AttachmentOpsArray::initWithLoadStore(PackedAttachmentIndex index,
4866                                            ImageLayout initialLayout,
4867                                            ImageLayout finalLayout)
4868 {
4869     setLayouts(index, initialLayout, finalLayout);
4870     setOps(index, RenderPassLoadOp::Load, RenderPassStoreOp::Store);
4871     setStencilOps(index, RenderPassLoadOp::Load, RenderPassStoreOp::Store);
4872 }
4873 
setLayouts(PackedAttachmentIndex index,ImageLayout initialLayout,ImageLayout finalLayout)4874 void AttachmentOpsArray::setLayouts(PackedAttachmentIndex index,
4875                                     ImageLayout initialLayout,
4876                                     ImageLayout finalLayout)
4877 {
4878     PackedAttachmentOpsDesc &ops = mOps[index.get()];
4879     SetBitField(ops.initialLayout, initialLayout);
4880     SetBitField(ops.finalLayout, finalLayout);
4881     SetBitField(ops.finalResolveLayout, finalLayout);
4882 }
4883 
setOps(PackedAttachmentIndex index,RenderPassLoadOp loadOp,RenderPassStoreOp storeOp)4884 void AttachmentOpsArray::setOps(PackedAttachmentIndex index,
4885                                 RenderPassLoadOp loadOp,
4886                                 RenderPassStoreOp storeOp)
4887 {
4888     PackedAttachmentOpsDesc &ops = mOps[index.get()];
4889     SetBitField(ops.loadOp, loadOp);
4890     SetBitField(ops.storeOp, storeOp);
4891     ops.isInvalidated = false;
4892 }
4893 
setStencilOps(PackedAttachmentIndex index,RenderPassLoadOp loadOp,RenderPassStoreOp storeOp)4894 void AttachmentOpsArray::setStencilOps(PackedAttachmentIndex index,
4895                                        RenderPassLoadOp loadOp,
4896                                        RenderPassStoreOp storeOp)
4897 {
4898     PackedAttachmentOpsDesc &ops = mOps[index.get()];
4899     SetBitField(ops.stencilLoadOp, loadOp);
4900     SetBitField(ops.stencilStoreOp, storeOp);
4901     ops.isStencilInvalidated = false;
4902 }
4903 
setClearOp(PackedAttachmentIndex index)4904 void AttachmentOpsArray::setClearOp(PackedAttachmentIndex index)
4905 {
4906     PackedAttachmentOpsDesc &ops = mOps[index.get()];
4907     SetBitField(ops.loadOp, RenderPassLoadOp::Clear);
4908 }
4909 
setClearStencilOp(PackedAttachmentIndex index)4910 void AttachmentOpsArray::setClearStencilOp(PackedAttachmentIndex index)
4911 {
4912     PackedAttachmentOpsDesc &ops = mOps[index.get()];
4913     SetBitField(ops.stencilLoadOp, RenderPassLoadOp::Clear);
4914 }
4915 
hash() const4916 size_t AttachmentOpsArray::hash() const
4917 {
4918     return angle::ComputeGenericHash(mOps);
4919 }
4920 
operator ==(const AttachmentOpsArray & lhs,const AttachmentOpsArray & rhs)4921 bool operator==(const AttachmentOpsArray &lhs, const AttachmentOpsArray &rhs)
4922 {
4923     return memcmp(&lhs, &rhs, sizeof(AttachmentOpsArray)) == 0;
4924 }
4925 
4926 // DescriptorSetLayoutDesc implementation.
DescriptorSetLayoutDesc()4927 DescriptorSetLayoutDesc::DescriptorSetLayoutDesc()
4928     : mImmutableSamplers{}, mDescriptorSetLayoutBindings{}
4929 {}
4930 
4931 DescriptorSetLayoutDesc::~DescriptorSetLayoutDesc() = default;
4932 
4933 DescriptorSetLayoutDesc::DescriptorSetLayoutDesc(const DescriptorSetLayoutDesc &other) = default;
4934 
4935 DescriptorSetLayoutDesc &DescriptorSetLayoutDesc::operator=(const DescriptorSetLayoutDesc &other) =
4936     default;
4937 
hash() const4938 size_t DescriptorSetLayoutDesc::hash() const
4939 {
4940     size_t validDescriptorSetLayoutBindingsCount = mDescriptorSetLayoutBindings.size();
4941     size_t validImmutableSamplersCount           = mImmutableSamplers.size();
4942 
4943     ASSERT(validDescriptorSetLayoutBindingsCount != 0 || validImmutableSamplersCount == 0);
4944 
4945     size_t genericHash = 0;
4946     if (validDescriptorSetLayoutBindingsCount > 0)
4947     {
4948         genericHash = angle::ComputeGenericHash(
4949             mDescriptorSetLayoutBindings.data(),
4950             validDescriptorSetLayoutBindingsCount * sizeof(PackedDescriptorSetBinding));
4951     }
4952 
4953     if (validImmutableSamplersCount > 0)
4954     {
4955         genericHash ^= angle::ComputeGenericHash(mImmutableSamplers.data(),
4956                                                  validImmutableSamplersCount * sizeof(VkSampler));
4957     }
4958 
4959     return genericHash;
4960 }
4961 
operator ==(const DescriptorSetLayoutDesc & other) const4962 bool DescriptorSetLayoutDesc::operator==(const DescriptorSetLayoutDesc &other) const
4963 {
4964     return mDescriptorSetLayoutBindings == other.mDescriptorSetLayoutBindings &&
4965            mImmutableSamplers == other.mImmutableSamplers;
4966 }
4967 
addBinding(uint32_t bindingIndex,VkDescriptorType descriptorType,uint32_t count,VkShaderStageFlags stages,const Sampler * immutableSampler)4968 void DescriptorSetLayoutDesc::addBinding(uint32_t bindingIndex,
4969                                          VkDescriptorType descriptorType,
4970                                          uint32_t count,
4971                                          VkShaderStageFlags stages,
4972                                          const Sampler *immutableSampler)
4973 {
4974     ASSERT(static_cast<uint8_t>(descriptorType) != PackedDescriptorSetBinding::kInvalidType);
4975     ASSERT(static_cast<size_t>(descriptorType) < std::numeric_limits<uint8_t>::max());
4976     ASSERT(count < std::numeric_limits<uint16_t>::max());
4977     ASSERT(bindingIndex < std::numeric_limits<uint16_t>::max());
4978 
4979     if (bindingIndex >= mDescriptorSetLayoutBindings.size())
4980     {
4981         PackedDescriptorSetBinding invalid = {};
4982         invalid.type                       = PackedDescriptorSetBinding::kInvalidType;
4983         mDescriptorSetLayoutBindings.resize(bindingIndex + 1, invalid);
4984     }
4985 
4986     PackedDescriptorSetBinding &packedBinding = mDescriptorSetLayoutBindings[bindingIndex];
4987     ASSERT(packedBinding.type == PackedDescriptorSetBinding::kInvalidType);
4988     SetBitField(packedBinding.type, descriptorType);
4989     SetBitField(packedBinding.count, count);
4990     SetBitField(packedBinding.stages, stages);
4991     SetBitField(packedBinding.hasImmutableSampler, 0);
4992 
4993     if (immutableSampler)
4994     {
4995         if (bindingIndex >= mImmutableSamplers.size())
4996         {
4997             mImmutableSamplers.resize(bindingIndex + 1);
4998         }
4999 
5000         ASSERT(count == 1);
5001         SetBitField(packedBinding.hasImmutableSampler, 1);
5002         mImmutableSamplers[bindingIndex] = immutableSampler->getHandle();
5003     }
5004 }
5005 
unpackBindings(DescriptorSetLayoutBindingVector * bindings) const5006 void DescriptorSetLayoutDesc::unpackBindings(DescriptorSetLayoutBindingVector *bindings) const
5007 {
5008     // Unpack all valid descriptor set layout bindings
5009     for (size_t bindingIndex = 0; bindingIndex < mDescriptorSetLayoutBindings.size();
5010          ++bindingIndex)
5011     {
5012         const PackedDescriptorSetBinding &packedBinding =
5013             mDescriptorSetLayoutBindings[bindingIndex];
5014         if (packedBinding.type == PackedDescriptorSetBinding::kInvalidType)
5015         {
5016             continue;
5017         }
5018 
5019         ASSERT(packedBinding.count != 0);
5020 
5021         VkDescriptorSetLayoutBinding binding = {};
5022         binding.binding                      = static_cast<uint32_t>(bindingIndex);
5023         binding.descriptorCount              = packedBinding.count;
5024         binding.descriptorType               = static_cast<VkDescriptorType>(packedBinding.type);
5025         binding.stageFlags = static_cast<VkShaderStageFlags>(packedBinding.stages);
5026 
5027         if (packedBinding.hasImmutableSampler)
5028         {
5029             ASSERT(packedBinding.count == 1);
5030             binding.pImmutableSamplers = &mImmutableSamplers[bindingIndex];
5031         }
5032 
5033         bindings->push_back(binding);
5034     }
5035 }
5036 
5037 // PipelineLayoutDesc implementation.
PipelineLayoutDesc()5038 PipelineLayoutDesc::PipelineLayoutDesc()
5039     : mDescriptorSetLayouts{}, mPushConstantRange{}, mPadding(0)
5040 {}
5041 
5042 PipelineLayoutDesc::~PipelineLayoutDesc() = default;
5043 
5044 PipelineLayoutDesc::PipelineLayoutDesc(const PipelineLayoutDesc &other) = default;
5045 
operator =(const PipelineLayoutDesc & rhs)5046 PipelineLayoutDesc &PipelineLayoutDesc::operator=(const PipelineLayoutDesc &rhs)
5047 {
5048     mDescriptorSetLayouts = rhs.mDescriptorSetLayouts;
5049     mPushConstantRange    = rhs.mPushConstantRange;
5050     return *this;
5051 }
5052 
hash() const5053 size_t PipelineLayoutDesc::hash() const
5054 {
5055     size_t genericHash = angle::ComputeGenericHash(mPushConstantRange);
5056     for (const DescriptorSetLayoutDesc &descriptorSetLayoutDesc : mDescriptorSetLayouts)
5057     {
5058         genericHash ^= descriptorSetLayoutDesc.hash();
5059     }
5060     return genericHash;
5061 }
5062 
operator ==(const PipelineLayoutDesc & other) const5063 bool PipelineLayoutDesc::operator==(const PipelineLayoutDesc &other) const
5064 {
5065     return mPushConstantRange == other.mPushConstantRange &&
5066            mDescriptorSetLayouts == other.mDescriptorSetLayouts;
5067 }
5068 
updateDescriptorSetLayout(DescriptorSetIndex setIndex,const DescriptorSetLayoutDesc & desc)5069 void PipelineLayoutDesc::updateDescriptorSetLayout(DescriptorSetIndex setIndex,
5070                                                    const DescriptorSetLayoutDesc &desc)
5071 {
5072     mDescriptorSetLayouts[setIndex] = desc;
5073 }
5074 
updatePushConstantRange(VkShaderStageFlags stageMask,uint32_t offset,uint32_t size)5075 void PipelineLayoutDesc::updatePushConstantRange(VkShaderStageFlags stageMask,
5076                                                  uint32_t offset,
5077                                                  uint32_t size)
5078 {
5079     SetBitField(mPushConstantRange.offset, offset);
5080     SetBitField(mPushConstantRange.size, size);
5081     SetBitField(mPushConstantRange.stageMask, stageMask);
5082 }
5083 
5084 // CreateMonolithicPipelineTask implementation.
CreateMonolithicPipelineTask(Renderer * renderer,const PipelineCacheAccess & pipelineCache,const PipelineLayout & pipelineLayout,const ShaderModuleMap & shaders,const SpecializationConstants & specConsts,const GraphicsPipelineDesc & desc)5085 CreateMonolithicPipelineTask::CreateMonolithicPipelineTask(
5086     Renderer *renderer,
5087     const PipelineCacheAccess &pipelineCache,
5088     const PipelineLayout &pipelineLayout,
5089     const ShaderModuleMap &shaders,
5090     const SpecializationConstants &specConsts,
5091     const GraphicsPipelineDesc &desc)
5092     : ErrorContext(renderer),
5093       mPipelineCache(pipelineCache),
5094       mCompatibleRenderPass(nullptr),
5095       mPipelineLayout(pipelineLayout),
5096       mShaders(shaders),
5097       mSpecConsts(specConsts),
5098       mDesc(desc),
5099       mResult(VK_NOT_READY),
5100       mFeedback(CacheLookUpFeedback::None)
5101 {}
5102 
setCompatibleRenderPass(const RenderPass * compatibleRenderPass)5103 void CreateMonolithicPipelineTask::setCompatibleRenderPass(const RenderPass *compatibleRenderPass)
5104 {
5105     mCompatibleRenderPass = compatibleRenderPass;
5106 }
5107 
operator ()()5108 void CreateMonolithicPipelineTask::operator()()
5109 {
5110     const RenderPass unusedRenderPass;
5111     const RenderPass *compatibleRenderPass =
5112         mCompatibleRenderPass ? mCompatibleRenderPass : &unusedRenderPass;
5113 
5114     ANGLE_TRACE_EVENT0("gpu.angle", "CreateMonolithicPipelineTask");
5115     mResult = mDesc.initializePipeline(this, &mPipelineCache, vk::GraphicsPipelineSubset::Complete,
5116                                        *compatibleRenderPass, mPipelineLayout,
5117                                        {&mShaders, &mSpecConsts}, &mPipeline, &mFeedback);
5118 
5119     if (mRenderer->getFeatures().slowDownMonolithicPipelineCreationForTesting.enabled)
5120     {
5121         constexpr double kSlowdownTime = 0.05;
5122 
5123         double startTime = angle::GetCurrentSystemTime();
5124         while (angle::GetCurrentSystemTime() - startTime < kSlowdownTime)
5125         {
5126             // Busy waiting
5127         }
5128     }
5129 }
5130 
handleError(VkResult result,const char * file,const char * function,unsigned int line)5131 void CreateMonolithicPipelineTask::handleError(VkResult result,
5132                                                const char *file,
5133                                                const char *function,
5134                                                unsigned int line)
5135 {
5136     UNREACHABLE();
5137 }
5138 
5139 // WaitableMonolithicPipelineCreationTask implementation
~WaitableMonolithicPipelineCreationTask()5140 WaitableMonolithicPipelineCreationTask::~WaitableMonolithicPipelineCreationTask()
5141 {
5142     ASSERT(!mWaitableEvent);
5143     ASSERT(!mTask);
5144 }
5145 
5146 // PipelineHelper implementation.
PipelineHelper()5147 PipelineHelper::PipelineHelper()
5148 {
5149     mTransitions.reserve(8);
5150 }
5151 
5152 PipelineHelper::~PipelineHelper() = default;
5153 
destroy(VkDevice device)5154 void PipelineHelper::destroy(VkDevice device)
5155 {
5156     mPipeline.destroy(device);
5157     mLinkedPipelineToRelease.destroy(device);
5158 
5159     // If there is a pending task, wait for it before destruction.
5160     if (mMonolithicPipelineCreationTask.isValid())
5161     {
5162         if (mMonolithicPipelineCreationTask.isPosted())
5163         {
5164             mMonolithicPipelineCreationTask.wait();
5165             mMonolithicPipelineCreationTask.getTask()->getPipeline().destroy(device);
5166         }
5167         mMonolithicPipelineCreationTask.reset();
5168     }
5169 
5170     reset();
5171 }
5172 
release(ErrorContext * context)5173 void PipelineHelper::release(ErrorContext *context)
5174 {
5175     Renderer *renderer = context->getRenderer();
5176 
5177     renderer->collectGarbage(mUse, &mPipeline);
5178     renderer->collectGarbage(mUse, &mLinkedPipelineToRelease);
5179 
5180     // If there is a pending task, wait for it before release.
5181     if (mMonolithicPipelineCreationTask.isValid())
5182     {
5183         if (mMonolithicPipelineCreationTask.isPosted())
5184         {
5185             mMonolithicPipelineCreationTask.wait();
5186             renderer->collectGarbage(mUse,
5187                                      &mMonolithicPipelineCreationTask.getTask()->getPipeline());
5188         }
5189         mMonolithicPipelineCreationTask.reset();
5190     }
5191 
5192     reset();
5193 }
5194 
reset()5195 void PipelineHelper::reset()
5196 {
5197     mCacheLookUpFeedback           = CacheLookUpFeedback::None;
5198     mMonolithicCacheLookUpFeedback = CacheLookUpFeedback::None;
5199 
5200     mLinkedShaders = nullptr;
5201 }
5202 
getPreferredPipeline(ContextVk * contextVk,const Pipeline ** pipelineOut)5203 angle::Result PipelineHelper::getPreferredPipeline(ContextVk *contextVk,
5204                                                    const Pipeline **pipelineOut)
5205 {
5206     if (mMonolithicPipelineCreationTask.isValid())
5207     {
5208         // If there is a monolithic task pending, attempt to post it if not already.  Once the task
5209         // is done, retrieve the results and replace the pipeline.
5210         if (!mMonolithicPipelineCreationTask.isPosted())
5211         {
5212             ANGLE_TRY(contextVk->getShareGroup()->scheduleMonolithicPipelineCreationTask(
5213                 contextVk, &mMonolithicPipelineCreationTask));
5214         }
5215         else if (mMonolithicPipelineCreationTask.isReady())
5216         {
5217             CreateMonolithicPipelineTask *task = &*mMonolithicPipelineCreationTask.getTask();
5218             ANGLE_VK_TRY(contextVk, task->getResult());
5219 
5220             mMonolithicCacheLookUpFeedback = task->getFeedback();
5221 
5222             // The pipeline will not be used anymore.  Every context that has used this pipeline has
5223             // already updated the serial.
5224             mLinkedPipelineToRelease = std::move(mPipeline);
5225 
5226             // Replace it with the monolithic one.
5227             mPipeline = std::move(task->getPipeline());
5228 
5229             mLinkedShaders = nullptr;
5230 
5231             mMonolithicPipelineCreationTask.reset();
5232 
5233             ++contextVk->getPerfCounters().monolithicPipelineCreation;
5234         }
5235     }
5236 
5237     *pipelineOut = &mPipeline;
5238 
5239     return angle::Result::Continue;
5240 }
5241 
addTransition(GraphicsPipelineTransitionBits bits,const GraphicsPipelineDesc * desc,PipelineHelper * pipeline)5242 void PipelineHelper::addTransition(GraphicsPipelineTransitionBits bits,
5243                                    const GraphicsPipelineDesc *desc,
5244                                    PipelineHelper *pipeline)
5245 {
5246     mTransitions.emplace_back(bits, desc, pipeline);
5247 }
5248 
setLinkedLibraryReferences(vk::PipelineHelper * shadersPipeline)5249 void PipelineHelper::setLinkedLibraryReferences(vk::PipelineHelper *shadersPipeline)
5250 {
5251     mLinkedShaders = shadersPipeline;
5252 }
5253 
retainInRenderPass(RenderPassCommandBufferHelper * renderPassCommands)5254 void PipelineHelper::retainInRenderPass(RenderPassCommandBufferHelper *renderPassCommands)
5255 {
5256     renderPassCommands->retainResource(this);
5257 
5258     // Keep references to the linked libraries alive.  Note that currently only need to do this for
5259     // the shaders library, as the vertex and fragment libraries live in the context until
5260     // destruction.
5261     if (mLinkedShaders != nullptr)
5262     {
5263         renderPassCommands->retainResource(mLinkedShaders);
5264     }
5265 }
5266 
5267 // FramebufferHelper implementation.
5268 FramebufferHelper::FramebufferHelper() = default;
5269 
5270 FramebufferHelper::~FramebufferHelper() = default;
5271 
FramebufferHelper(FramebufferHelper && other)5272 FramebufferHelper::FramebufferHelper(FramebufferHelper &&other) : Resource(std::move(other))
5273 {
5274     mFramebuffer = std::move(other.mFramebuffer);
5275 }
5276 
operator =(FramebufferHelper && other)5277 FramebufferHelper &FramebufferHelper::operator=(FramebufferHelper &&other)
5278 {
5279     Resource::operator=(std::move(other));
5280     std::swap(mFramebuffer, other.mFramebuffer);
5281     return *this;
5282 }
5283 
init(ErrorContext * context,const VkFramebufferCreateInfo & createInfo)5284 angle::Result FramebufferHelper::init(ErrorContext *context,
5285                                       const VkFramebufferCreateInfo &createInfo)
5286 {
5287     ANGLE_VK_TRY(context, mFramebuffer.init(context->getDevice(), createInfo));
5288     return angle::Result::Continue;
5289 }
5290 
destroy(Renderer * renderer)5291 void FramebufferHelper::destroy(Renderer *renderer)
5292 {
5293     mFramebuffer.destroy(renderer->getDevice());
5294 }
5295 
release(ContextVk * contextVk)5296 void FramebufferHelper::release(ContextVk *contextVk)
5297 {
5298     contextVk->addGarbage(&mFramebuffer);
5299 }
5300 
5301 // DescriptorSetDesc implementation.
hash() const5302 size_t DescriptorSetDesc::hash() const
5303 {
5304     if (mDescriptorInfos.empty())
5305     {
5306         return 0;
5307     }
5308 
5309     return angle::ComputeGenericHash(mDescriptorInfos.data(),
5310                                      sizeof(mDescriptorInfos[0]) * mDescriptorInfos.size());
5311 }
5312 
5313 // FramebufferDesc implementation.
5314 
FramebufferDesc()5315 FramebufferDesc::FramebufferDesc()
5316 {
5317     reset();
5318 }
5319 
5320 FramebufferDesc::~FramebufferDesc()                                       = default;
5321 FramebufferDesc::FramebufferDesc(const FramebufferDesc &other)            = default;
5322 FramebufferDesc &FramebufferDesc::operator=(const FramebufferDesc &other) = default;
5323 
update(uint32_t index,ImageOrBufferViewSubresourceSerial serial)5324 void FramebufferDesc::update(uint32_t index, ImageOrBufferViewSubresourceSerial serial)
5325 {
5326     static_assert(kMaxFramebufferAttachments + 1 < std::numeric_limits<uint8_t>::max(),
5327                   "mMaxIndex size is too small");
5328     ASSERT(index < kMaxFramebufferAttachments);
5329     mSerials[index] = serial;
5330     if (serial.viewSerial.valid())
5331     {
5332         SetBitField(mMaxIndex, std::max(mMaxIndex, static_cast<uint16_t>(index + 1)));
5333     }
5334 }
5335 
updateColor(uint32_t index,ImageOrBufferViewSubresourceSerial serial)5336 void FramebufferDesc::updateColor(uint32_t index, ImageOrBufferViewSubresourceSerial serial)
5337 {
5338     update(kFramebufferDescColorIndexOffset + index, serial);
5339 }
5340 
updateColorResolve(uint32_t index,ImageOrBufferViewSubresourceSerial serial)5341 void FramebufferDesc::updateColorResolve(uint32_t index, ImageOrBufferViewSubresourceSerial serial)
5342 {
5343     update(kFramebufferDescColorResolveIndexOffset + index, serial);
5344 }
5345 
updateUnresolveMask(FramebufferNonResolveAttachmentMask unresolveMask)5346 void FramebufferDesc::updateUnresolveMask(FramebufferNonResolveAttachmentMask unresolveMask)
5347 {
5348     SetBitField(mUnresolveAttachmentMask, unresolveMask.bits());
5349 }
5350 
updateDepthStencil(ImageOrBufferViewSubresourceSerial serial)5351 void FramebufferDesc::updateDepthStencil(ImageOrBufferViewSubresourceSerial serial)
5352 {
5353     update(kFramebufferDescDepthStencilIndex, serial);
5354 }
5355 
updateDepthStencilResolve(ImageOrBufferViewSubresourceSerial serial)5356 void FramebufferDesc::updateDepthStencilResolve(ImageOrBufferViewSubresourceSerial serial)
5357 {
5358     update(kFramebufferDescDepthStencilResolveIndexOffset, serial);
5359 }
5360 
updateFragmentShadingRate(ImageOrBufferViewSubresourceSerial serial)5361 void FramebufferDesc::updateFragmentShadingRate(ImageOrBufferViewSubresourceSerial serial)
5362 {
5363     update(kFramebufferDescFragmentShadingRateAttachmentIndexOffset, serial);
5364 }
5365 
hasFragmentShadingRateAttachment() const5366 bool FramebufferDesc::hasFragmentShadingRateAttachment() const
5367 {
5368     return mSerials[kFramebufferDescFragmentShadingRateAttachmentIndexOffset].viewSerial.valid();
5369 }
5370 
hash() const5371 size_t FramebufferDesc::hash() const
5372 {
5373     return angle::ComputeGenericHash(&mSerials, sizeof(mSerials[0]) * mMaxIndex) ^
5374            mHasColorFramebufferFetch << 26 ^ mIsRenderToTexture << 25 ^ mLayerCount << 16 ^
5375            mUnresolveAttachmentMask;
5376 }
5377 
reset()5378 void FramebufferDesc::reset()
5379 {
5380     mMaxIndex                 = 0;
5381     mHasColorFramebufferFetch = false;
5382     mLayerCount               = 0;
5383     mSrgbWriteControlMode     = 0;
5384     mUnresolveAttachmentMask  = 0;
5385     mIsRenderToTexture        = 0;
5386     // An empty FramebufferDesc is still a valid desc. It becomes invalid when it is explicitly
5387     // destroyed or released by SharedFramebufferCacheKey.
5388     mIsValid = 1;
5389     memset(&mSerials, 0, sizeof(mSerials));
5390 }
5391 
operator ==(const FramebufferDesc & other) const5392 bool FramebufferDesc::operator==(const FramebufferDesc &other) const
5393 {
5394     if (mMaxIndex != other.mMaxIndex || mLayerCount != other.mLayerCount ||
5395         mUnresolveAttachmentMask != other.mUnresolveAttachmentMask ||
5396         mHasColorFramebufferFetch != other.mHasColorFramebufferFetch ||
5397         mSrgbWriteControlMode != other.mSrgbWriteControlMode ||
5398         mIsRenderToTexture != other.mIsRenderToTexture)
5399     {
5400         return false;
5401     }
5402 
5403     size_t validRegionSize = sizeof(mSerials[0]) * mMaxIndex;
5404     return memcmp(&mSerials, &other.mSerials, validRegionSize) == 0;
5405 }
5406 
attachmentCount() const5407 uint32_t FramebufferDesc::attachmentCount() const
5408 {
5409     uint32_t count = 0;
5410     for (const ImageOrBufferViewSubresourceSerial &serial : mSerials)
5411     {
5412         if (serial.viewSerial.valid())
5413         {
5414             count++;
5415         }
5416     }
5417     return count;
5418 }
5419 
getUnresolveAttachmentMask() const5420 FramebufferNonResolveAttachmentMask FramebufferDesc::getUnresolveAttachmentMask() const
5421 {
5422     return FramebufferNonResolveAttachmentMask(mUnresolveAttachmentMask);
5423 }
5424 
updateLayerCount(uint32_t layerCount)5425 void FramebufferDesc::updateLayerCount(uint32_t layerCount)
5426 {
5427     SetBitField(mLayerCount, layerCount);
5428 }
5429 
setColorFramebufferFetchMode(bool hasColorFramebufferFetch)5430 void FramebufferDesc::setColorFramebufferFetchMode(bool hasColorFramebufferFetch)
5431 {
5432     SetBitField(mHasColorFramebufferFetch, hasColorFramebufferFetch);
5433 }
5434 
updateRenderToTexture(bool isRenderToTexture)5435 void FramebufferDesc::updateRenderToTexture(bool isRenderToTexture)
5436 {
5437     SetBitField(mIsRenderToTexture, isRenderToTexture);
5438 }
5439 
destroyCachedObject(Renderer * renderer)5440 void FramebufferDesc::destroyCachedObject(Renderer *renderer)
5441 {
5442     ASSERT(valid());
5443     // Framebuffer cache are implemented in a way that each cache entry tracks GPU progress and we
5444     // always guarantee cache entries are released before calling destroy.
5445     SetBitField(mIsValid, 0);
5446 }
5447 
releaseCachedObject(ContextVk * contextVk)5448 void FramebufferDesc::releaseCachedObject(ContextVk *contextVk)
5449 {
5450     ASSERT(valid());
5451     contextVk->getShareGroup()->getFramebufferCache().erase(contextVk, *this);
5452     SetBitField(mIsValid, 0);
5453 }
5454 
hasValidCachedObject(ContextVk * contextVk) const5455 bool FramebufferDesc::hasValidCachedObject(ContextVk *contextVk) const
5456 {
5457     ASSERT(valid());
5458     Framebuffer framebuffer;
5459     return contextVk->getShareGroup()->getFramebufferCache().get(contextVk, *this, framebuffer);
5460 }
5461 
5462 // YcbcrConversionDesc implementation
YcbcrConversionDesc()5463 YcbcrConversionDesc::YcbcrConversionDesc()
5464 {
5465     reset();
5466 }
5467 
5468 YcbcrConversionDesc::~YcbcrConversionDesc() = default;
5469 
5470 YcbcrConversionDesc::YcbcrConversionDesc(const YcbcrConversionDesc &other) = default;
5471 
5472 YcbcrConversionDesc &YcbcrConversionDesc::operator=(const YcbcrConversionDesc &rhs) = default;
5473 
hash() const5474 size_t YcbcrConversionDesc::hash() const
5475 {
5476     return angle::ComputeGenericHash(*this);
5477 }
5478 
operator ==(const YcbcrConversionDesc & other) const5479 bool YcbcrConversionDesc::operator==(const YcbcrConversionDesc &other) const
5480 {
5481     return memcmp(this, &other, sizeof(YcbcrConversionDesc)) == 0;
5482 }
5483 
reset()5484 void YcbcrConversionDesc::reset()
5485 {
5486     mExternalOrVkFormat    = 0;
5487     mIsExternalFormat      = 0;
5488     mConversionModel       = 0;
5489     mColorRange            = 0;
5490     mXChromaOffset         = 0;
5491     mYChromaOffset         = 0;
5492     mChromaFilter          = 0;
5493     mRSwizzle              = 0;
5494     mGSwizzle              = 0;
5495     mBSwizzle              = 0;
5496     mASwizzle              = 0;
5497     mLinearFilterSupported = 0;
5498     mPadding               = 0;
5499     mReserved              = 0;
5500 }
5501 
update(Renderer * renderer,uint64_t externalFormat,VkSamplerYcbcrModelConversion conversionModel,VkSamplerYcbcrRange colorRange,VkChromaLocation xChromaOffset,VkChromaLocation yChromaOffset,VkFilter chromaFilter,VkComponentMapping components,angle::FormatID intendedFormatID,YcbcrLinearFilterSupport linearFilterSupported)5502 void YcbcrConversionDesc::update(Renderer *renderer,
5503                                  uint64_t externalFormat,
5504                                  VkSamplerYcbcrModelConversion conversionModel,
5505                                  VkSamplerYcbcrRange colorRange,
5506                                  VkChromaLocation xChromaOffset,
5507                                  VkChromaLocation yChromaOffset,
5508                                  VkFilter chromaFilter,
5509                                  VkComponentMapping components,
5510                                  angle::FormatID intendedFormatID,
5511                                  YcbcrLinearFilterSupport linearFilterSupported)
5512 {
5513     const vk::Format &vkFormat = renderer->getFormat(intendedFormatID);
5514     ASSERT(externalFormat != 0 || vkFormat.getIntendedFormat().isYUV);
5515 
5516     SetBitField(mIsExternalFormat, (externalFormat) ? 1 : 0);
5517     SetBitField(mLinearFilterSupported,
5518                 linearFilterSupported == YcbcrLinearFilterSupport::Supported);
5519     mExternalOrVkFormat =
5520         (externalFormat) ? externalFormat
5521                          : vkFormat.getActualImageVkFormat(renderer, vk::ImageAccess::SampleOnly);
5522 
5523     updateChromaFilter(renderer, chromaFilter);
5524 
5525     SetBitField(mConversionModel, conversionModel);
5526     SetBitField(mColorRange, colorRange);
5527     SetBitField(mXChromaOffset, xChromaOffset);
5528     SetBitField(mYChromaOffset, yChromaOffset);
5529     SetBitField(mRSwizzle, components.r);
5530     SetBitField(mGSwizzle, components.g);
5531     SetBitField(mBSwizzle, components.b);
5532     SetBitField(mASwizzle, components.a);
5533 }
5534 
updateChromaFilter(Renderer * renderer,VkFilter filter)5535 bool YcbcrConversionDesc::updateChromaFilter(Renderer *renderer, VkFilter filter)
5536 {
5537     // The app has requested a specific min/mag filter, reconcile that with the filter
5538     // requested by preferLinearFilterForYUV feature.
5539     //
5540     // preferLinearFilterForYUV enforces linear filter while forceNearestFiltering and
5541     // forceNearestMipFiltering enforces nearest filter, enabling one precludes the other.
5542     ASSERT(!renderer->getFeatures().preferLinearFilterForYUV.enabled ||
5543            (!renderer->getFeatures().forceNearestFiltering.enabled &&
5544             !renderer->getFeatures().forceNearestMipFiltering.enabled));
5545 
5546     VkFilter preferredChromaFilter = renderer->getPreferredFilterForYUV(filter);
5547     ASSERT(preferredChromaFilter == VK_FILTER_LINEAR || preferredChromaFilter == VK_FILTER_NEAREST);
5548 
5549     if (preferredChromaFilter == VK_FILTER_LINEAR && !mLinearFilterSupported)
5550     {
5551         // Vulkan implementations may not support linear filtering in all cases. If not supported,
5552         // use nearest filtering instead.
5553         preferredChromaFilter = VK_FILTER_NEAREST;
5554     }
5555 
5556     if (getChromaFilter() != preferredChromaFilter)
5557     {
5558         SetBitField(mChromaFilter, preferredChromaFilter);
5559         return true;
5560     }
5561     return false;
5562 }
5563 
updateConversionModel(VkSamplerYcbcrModelConversion conversionModel)5564 void YcbcrConversionDesc::updateConversionModel(VkSamplerYcbcrModelConversion conversionModel)
5565 {
5566     SetBitField(mConversionModel, conversionModel);
5567 }
5568 
init(ErrorContext * context,SamplerYcbcrConversion * conversionOut) const5569 angle::Result YcbcrConversionDesc::init(ErrorContext *context,
5570                                         SamplerYcbcrConversion *conversionOut) const
5571 {
5572     // Create the VkSamplerYcbcrConversion
5573     VkSamplerYcbcrConversionCreateInfo samplerYcbcrConversionInfo = {};
5574     samplerYcbcrConversionInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO;
5575     samplerYcbcrConversionInfo.format =
5576         getExternalFormat() == 0 ? static_cast<VkFormat>(mExternalOrVkFormat) : VK_FORMAT_UNDEFINED;
5577     samplerYcbcrConversionInfo.xChromaOffset = static_cast<VkChromaLocation>(mXChromaOffset);
5578     samplerYcbcrConversionInfo.yChromaOffset = static_cast<VkChromaLocation>(mYChromaOffset);
5579     samplerYcbcrConversionInfo.ycbcrModel =
5580         static_cast<VkSamplerYcbcrModelConversion>(mConversionModel);
5581     samplerYcbcrConversionInfo.ycbcrRange   = static_cast<VkSamplerYcbcrRange>(mColorRange);
5582     samplerYcbcrConversionInfo.chromaFilter = static_cast<VkFilter>(mChromaFilter);
5583     samplerYcbcrConversionInfo.components   = {
5584         static_cast<VkComponentSwizzle>(mRSwizzle), static_cast<VkComponentSwizzle>(mGSwizzle),
5585         static_cast<VkComponentSwizzle>(mBSwizzle), static_cast<VkComponentSwizzle>(mASwizzle)};
5586 
5587 #ifdef VK_USE_PLATFORM_ANDROID_KHR
5588     VkExternalFormatANDROID externalFormat = {};
5589     if (getExternalFormat() != 0)
5590     {
5591         externalFormat.sType             = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID;
5592         externalFormat.externalFormat    = mExternalOrVkFormat;
5593         samplerYcbcrConversionInfo.pNext = &externalFormat;
5594     }
5595 #else
5596     // We do not support external format for any platform other than Android.
5597     ASSERT(mIsExternalFormat == 0);
5598 #endif  // VK_USE_PLATFORM_ANDROID_KHR
5599 
5600     ANGLE_VK_TRY(context, conversionOut->init(context->getDevice(), samplerYcbcrConversionInfo));
5601     return angle::Result::Continue;
5602 }
5603 
5604 // SamplerDesc implementation.
SamplerDesc()5605 SamplerDesc::SamplerDesc()
5606 {
5607     reset();
5608 }
5609 
5610 SamplerDesc::~SamplerDesc() = default;
5611 
5612 SamplerDesc::SamplerDesc(const SamplerDesc &other) = default;
5613 
5614 SamplerDesc &SamplerDesc::operator=(const SamplerDesc &rhs) = default;
5615 
SamplerDesc(ErrorContext * context,const gl::SamplerState & samplerState,bool stencilMode,const YcbcrConversionDesc * ycbcrConversionDesc,angle::FormatID intendedFormatID)5616 SamplerDesc::SamplerDesc(ErrorContext *context,
5617                          const gl::SamplerState &samplerState,
5618                          bool stencilMode,
5619                          const YcbcrConversionDesc *ycbcrConversionDesc,
5620                          angle::FormatID intendedFormatID)
5621 {
5622     update(context->getRenderer(), samplerState, stencilMode, ycbcrConversionDesc,
5623            intendedFormatID);
5624 }
5625 
reset()5626 void SamplerDesc::reset()
5627 {
5628     mMipLodBias    = 0.0f;
5629     mMaxAnisotropy = 0.0f;
5630     mMinLod        = 0.0f;
5631     mMaxLod        = 0.0f;
5632     mYcbcrConversionDesc.reset();
5633     mMagFilter         = 0;
5634     mMinFilter         = 0;
5635     mMipmapMode        = 0;
5636     mAddressModeU      = 0;
5637     mAddressModeV      = 0;
5638     mAddressModeW      = 0;
5639     mCompareEnabled    = 0;
5640     mCompareOp         = 0;
5641     mPadding           = 0;
5642     mBorderColorType   = 0;
5643     mBorderColor.red   = 0.0f;
5644     mBorderColor.green = 0.0f;
5645     mBorderColor.blue  = 0.0f;
5646     mBorderColor.alpha = 0.0f;
5647     mReserved          = 0;
5648 }
5649 
update(Renderer * renderer,const gl::SamplerState & samplerState,bool stencilMode,const YcbcrConversionDesc * ycbcrConversionDesc,angle::FormatID intendedFormatID)5650 void SamplerDesc::update(Renderer *renderer,
5651                          const gl::SamplerState &samplerState,
5652                          bool stencilMode,
5653                          const YcbcrConversionDesc *ycbcrConversionDesc,
5654                          angle::FormatID intendedFormatID)
5655 {
5656     const angle::FeaturesVk &featuresVk = renderer->getFeatures();
5657     mMipLodBias                         = 0.0f;
5658     if (featuresVk.forceTextureLodOffset1.enabled)
5659     {
5660         mMipLodBias = 1.0f;
5661     }
5662     else if (featuresVk.forceTextureLodOffset2.enabled)
5663     {
5664         mMipLodBias = 2.0f;
5665     }
5666     else if (featuresVk.forceTextureLodOffset3.enabled)
5667     {
5668         mMipLodBias = 3.0f;
5669     }
5670     else if (featuresVk.forceTextureLodOffset4.enabled)
5671     {
5672         mMipLodBias = 4.0f;
5673     }
5674 
5675     mMaxAnisotropy = samplerState.getMaxAnisotropy();
5676     mMinLod        = samplerState.getMinLod();
5677     mMaxLod        = samplerState.getMaxLod();
5678 
5679     GLenum minFilter = samplerState.getMinFilter();
5680     GLenum magFilter = samplerState.getMagFilter();
5681     if (ycbcrConversionDesc && ycbcrConversionDesc->valid())
5682     {
5683         // Update the SamplerYcbcrConversionCache key
5684         mYcbcrConversionDesc = *ycbcrConversionDesc;
5685 
5686         // Reconcile chroma filter and min/mag filters.
5687         //
5688         // VUID-VkSamplerCreateInfo-minFilter-01645
5689         // If sampler YCBCR conversion is enabled and the potential format features of the
5690         // sampler YCBCR conversion do not support
5691         // VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT,
5692         // minFilter and magFilter must be equal to the sampler YCBCR conversions chromaFilter.
5693         //
5694         // For simplicity assume external formats do not support that feature bit.
5695         ASSERT((mYcbcrConversionDesc.getExternalFormat() != 0) ||
5696                (angle::Format::Get(intendedFormatID).isYUV));
5697         const bool filtersMustMatch =
5698             (mYcbcrConversionDesc.getExternalFormat() != 0) ||
5699             !renderer->hasImageFormatFeatureBits(
5700                 intendedFormatID,
5701                 VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT);
5702         if (filtersMustMatch)
5703         {
5704             GLenum glFilter = (mYcbcrConversionDesc.getChromaFilter() == VK_FILTER_LINEAR)
5705                                   ? GL_LINEAR
5706                                   : GL_NEAREST;
5707             minFilter       = glFilter;
5708             magFilter       = glFilter;
5709         }
5710     }
5711 
5712     bool compareEnable    = samplerState.getCompareMode() == GL_COMPARE_REF_TO_TEXTURE;
5713     VkCompareOp compareOp = gl_vk::GetCompareOp(samplerState.getCompareFunc());
5714     // When sampling from stencil, deqp tests expect texture compare to have no effect
5715     // dEQP - GLES31.functional.stencil_texturing.misc.compare_mode_effect
5716     // states: NOTE: Texture compare mode has no effect when reading stencil values.
5717     if (stencilMode)
5718     {
5719         compareEnable = VK_FALSE;
5720         compareOp     = VK_COMPARE_OP_ALWAYS;
5721     }
5722 
5723     if (featuresVk.forceNearestFiltering.enabled)
5724     {
5725         magFilter = gl::ConvertToNearestFilterMode(magFilter);
5726         minFilter = gl::ConvertToNearestFilterMode(minFilter);
5727     }
5728     if (featuresVk.forceNearestMipFiltering.enabled)
5729     {
5730         minFilter = gl::ConvertToNearestMipFilterMode(minFilter);
5731     }
5732 
5733     SetBitField(mMagFilter, gl_vk::GetFilter(magFilter));
5734     SetBitField(mMinFilter, gl_vk::GetFilter(minFilter));
5735     SetBitField(mMipmapMode, gl_vk::GetSamplerMipmapMode(samplerState.getMinFilter()));
5736     SetBitField(mAddressModeU, gl_vk::GetSamplerAddressMode(samplerState.getWrapS()));
5737     SetBitField(mAddressModeV, gl_vk::GetSamplerAddressMode(samplerState.getWrapT()));
5738     SetBitField(mAddressModeW, gl_vk::GetSamplerAddressMode(samplerState.getWrapR()));
5739     SetBitField(mCompareEnabled, compareEnable);
5740     SetBitField(mCompareOp, compareOp);
5741 
5742     if (!gl::IsMipmapFiltered(minFilter))
5743     {
5744         // Per the Vulkan spec, GL_NEAREST and GL_LINEAR do not map directly to Vulkan, so
5745         // they must be emulated (See "Mapping of OpenGL to Vulkan filter modes")
5746         SetBitField(mMipmapMode, VK_SAMPLER_MIPMAP_MODE_NEAREST);
5747         mMinLod = 0.0f;
5748         mMaxLod = 0.25f;
5749     }
5750 
5751     mPadding = 0;
5752 
5753     mBorderColorType =
5754         (samplerState.getBorderColor().type == angle::ColorGeneric::Type::Float) ? 0 : 1;
5755 
5756     // Adjust border color according to intended format
5757     const vk::Format &vkFormat = renderer->getFormat(intendedFormatID);
5758     gl::ColorGeneric adjustedBorderColor =
5759         AdjustBorderColor(samplerState.getBorderColor(), vkFormat.getIntendedFormat(), stencilMode);
5760     mBorderColor = adjustedBorderColor.colorF;
5761 
5762     mReserved = 0;
5763 }
5764 
init(ContextVk * contextVk,Sampler * sampler) const5765 angle::Result SamplerDesc::init(ContextVk *contextVk, Sampler *sampler) const
5766 {
5767     const gl::Extensions &extensions = contextVk->getExtensions();
5768 
5769     bool anisotropyEnable = extensions.textureFilterAnisotropicEXT && mMaxAnisotropy > 1.0f;
5770 
5771     VkSamplerCreateInfo createInfo     = {};
5772     createInfo.sType                   = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
5773     createInfo.flags                   = 0;
5774     createInfo.magFilter               = static_cast<VkFilter>(mMagFilter);
5775     createInfo.minFilter               = static_cast<VkFilter>(mMinFilter);
5776     createInfo.mipmapMode              = static_cast<VkSamplerMipmapMode>(mMipmapMode);
5777     createInfo.addressModeU            = static_cast<VkSamplerAddressMode>(mAddressModeU);
5778     createInfo.addressModeV            = static_cast<VkSamplerAddressMode>(mAddressModeV);
5779     createInfo.addressModeW            = static_cast<VkSamplerAddressMode>(mAddressModeW);
5780     createInfo.mipLodBias              = mMipLodBias;
5781     createInfo.anisotropyEnable        = anisotropyEnable;
5782     createInfo.maxAnisotropy           = mMaxAnisotropy;
5783     createInfo.compareEnable           = mCompareEnabled ? VK_TRUE : VK_FALSE;
5784     createInfo.compareOp               = static_cast<VkCompareOp>(mCompareOp);
5785     createInfo.minLod                  = mMinLod;
5786     createInfo.maxLod                  = mMaxLod;
5787     createInfo.borderColor             = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK;
5788     createInfo.unnormalizedCoordinates = VK_FALSE;
5789 
5790     VkSamplerYcbcrConversionInfo samplerYcbcrConversionInfo = {};
5791     if (mYcbcrConversionDesc.valid())
5792     {
5793         ASSERT((contextVk->getFeatures().supportsYUVSamplerConversion.enabled));
5794         samplerYcbcrConversionInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO;
5795         samplerYcbcrConversionInfo.pNext = nullptr;
5796         ANGLE_TRY(contextVk->getRenderer()->getYuvConversionCache().getSamplerYcbcrConversion(
5797             contextVk, mYcbcrConversionDesc, &samplerYcbcrConversionInfo.conversion));
5798         AddToPNextChain(&createInfo, &samplerYcbcrConversionInfo);
5799 
5800         // Vulkan spec requires these settings:
5801         createInfo.addressModeU            = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
5802         createInfo.addressModeV            = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
5803         createInfo.addressModeW            = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
5804         createInfo.anisotropyEnable        = VK_FALSE;
5805         createInfo.unnormalizedCoordinates = VK_FALSE;
5806     }
5807 
5808     VkSamplerCustomBorderColorCreateInfoEXT customBorderColorInfo = {};
5809     if (createInfo.addressModeU == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER ||
5810         createInfo.addressModeV == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER ||
5811         createInfo.addressModeW == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER)
5812     {
5813         ASSERT((contextVk->getFeatures().supportsCustomBorderColor.enabled));
5814         customBorderColorInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT;
5815 
5816         customBorderColorInfo.customBorderColor.float32[0] = mBorderColor.red;
5817         customBorderColorInfo.customBorderColor.float32[1] = mBorderColor.green;
5818         customBorderColorInfo.customBorderColor.float32[2] = mBorderColor.blue;
5819         customBorderColorInfo.customBorderColor.float32[3] = mBorderColor.alpha;
5820 
5821         if (mBorderColorType == static_cast<uint32_t>(angle::ColorGeneric::Type::Float))
5822         {
5823             createInfo.borderColor = VK_BORDER_COLOR_FLOAT_CUSTOM_EXT;
5824         }
5825         else
5826         {
5827             createInfo.borderColor = VK_BORDER_COLOR_INT_CUSTOM_EXT;
5828         }
5829 
5830         vk::AddToPNextChain(&createInfo, &customBorderColorInfo);
5831     }
5832     ANGLE_VK_TRY(contextVk, sampler->init(contextVk->getDevice(), createInfo));
5833 
5834     return angle::Result::Continue;
5835 }
5836 
hash() const5837 size_t SamplerDesc::hash() const
5838 {
5839     return angle::ComputeGenericHash(*this);
5840 }
5841 
operator ==(const SamplerDesc & other) const5842 bool SamplerDesc::operator==(const SamplerDesc &other) const
5843 {
5844     return memcmp(this, &other, sizeof(SamplerDesc)) == 0;
5845 }
5846 
SamplerHelper(SamplerHelper && samplerHelper)5847 SamplerHelper::SamplerHelper(SamplerHelper &&samplerHelper)
5848 {
5849     *this = std::move(samplerHelper);
5850 }
5851 
operator =(SamplerHelper && rhs)5852 SamplerHelper &SamplerHelper::operator=(SamplerHelper &&rhs)
5853 {
5854     std::swap(mSampler, rhs.mSampler);
5855     std::swap(mSamplerSerial, rhs.mSamplerSerial);
5856     return *this;
5857 }
5858 
init(ErrorContext * context,const VkSamplerCreateInfo & createInfo)5859 angle::Result SamplerHelper::init(ErrorContext *context, const VkSamplerCreateInfo &createInfo)
5860 {
5861     mSamplerSerial = context->getRenderer()->getResourceSerialFactory().generateSamplerSerial();
5862     ANGLE_VK_TRY(context, mSampler.init(context->getDevice(), createInfo));
5863     return angle::Result::Continue;
5864 }
init(ContextVk * contextVk,const SamplerDesc & desc)5865 angle::Result SamplerHelper::init(ContextVk *contextVk, const SamplerDesc &desc)
5866 {
5867     mSamplerSerial = contextVk->getRenderer()->getResourceSerialFactory().generateSamplerSerial();
5868     return desc.init(contextVk, &mSampler);
5869 }
5870 
5871 // RenderPassHelper implementation.
RenderPassHelper()5872 RenderPassHelper::RenderPassHelper() : mPerfCounters{} {}
5873 
5874 RenderPassHelper::~RenderPassHelper() = default;
5875 
RenderPassHelper(RenderPassHelper && other)5876 RenderPassHelper::RenderPassHelper(RenderPassHelper &&other)
5877 {
5878     *this = std::move(other);
5879 }
5880 
operator =(RenderPassHelper && other)5881 RenderPassHelper &RenderPassHelper::operator=(RenderPassHelper &&other)
5882 {
5883     mRenderPass   = std::move(other.mRenderPass);
5884     mPerfCounters = std::move(other.mPerfCounters);
5885     return *this;
5886 }
5887 
destroy(VkDevice device)5888 void RenderPassHelper::destroy(VkDevice device)
5889 {
5890     mRenderPass.destroy(device);
5891 }
5892 
release(ContextVk * contextVk)5893 void RenderPassHelper::release(ContextVk *contextVk)
5894 {
5895     contextVk->addGarbage(&mRenderPass);
5896 }
5897 
getRenderPass() const5898 const RenderPass &RenderPassHelper::getRenderPass() const
5899 {
5900     return mRenderPass;
5901 }
5902 
getRenderPass()5903 RenderPass &RenderPassHelper::getRenderPass()
5904 {
5905     return mRenderPass;
5906 }
5907 
getPerfCounters() const5908 const RenderPassPerfCounters &RenderPassHelper::getPerfCounters() const
5909 {
5910     return mPerfCounters;
5911 }
5912 
getPerfCounters()5913 RenderPassPerfCounters &RenderPassHelper::getPerfCounters()
5914 {
5915     return mPerfCounters;
5916 }
5917 
5918 // WriteDescriptorDescs implementation.
updateWriteDesc(uint32_t bindingIndex,VkDescriptorType descriptorType,uint32_t descriptorCount)5919 void WriteDescriptorDescs::updateWriteDesc(uint32_t bindingIndex,
5920                                            VkDescriptorType descriptorType,
5921                                            uint32_t descriptorCount)
5922 {
5923     if (hasWriteDescAtIndex(bindingIndex))
5924     {
5925         uint32_t infoIndex          = mDescs[bindingIndex].descriptorInfoIndex;
5926         uint32_t oldDescriptorCount = mDescs[bindingIndex].descriptorCount;
5927         if (descriptorCount != oldDescriptorCount)
5928         {
5929             ASSERT(infoIndex + oldDescriptorCount == mCurrentInfoIndex);
5930             ASSERT(descriptorCount > oldDescriptorCount);
5931             uint32_t additionalDescriptors = descriptorCount - oldDescriptorCount;
5932             incrementDescriptorCount(bindingIndex, additionalDescriptors);
5933             mCurrentInfoIndex += additionalDescriptors;
5934         }
5935     }
5936     else
5937     {
5938         WriteDescriptorDesc &writeDesc = mDescs[bindingIndex];
5939         SetBitField(writeDesc.binding, bindingIndex);
5940         SetBitField(writeDesc.descriptorCount, descriptorCount);
5941         SetBitField(writeDesc.descriptorType, descriptorType);
5942         SetBitField(writeDesc.descriptorInfoIndex, mCurrentInfoIndex);
5943         mCurrentInfoIndex += descriptorCount;
5944         ASSERT(writeDesc.descriptorCount > 0);
5945     }
5946 }
5947 
updateShaderBuffers(const ShaderInterfaceVariableInfoMap & variableInfoMap,const std::vector<gl::InterfaceBlock> & blocks,VkDescriptorType descriptorType)5948 void WriteDescriptorDescs::updateShaderBuffers(
5949     const ShaderInterfaceVariableInfoMap &variableInfoMap,
5950     const std::vector<gl::InterfaceBlock> &blocks,
5951     VkDescriptorType descriptorType)
5952 {
5953     // Initialize the descriptor writes in a first pass. This ensures we can pack the structures
5954     // corresponding to array elements tightly.
5955     for (uint32_t blockIndex = 0; blockIndex < blocks.size(); ++blockIndex)
5956     {
5957         const gl::InterfaceBlock &block = blocks[blockIndex];
5958 
5959         if (block.activeShaders().none())
5960         {
5961             continue;
5962         }
5963 
5964         const gl::ShaderType firstShaderType = block.getFirstActiveShaderType();
5965         const ShaderInterfaceVariableInfo &info =
5966             variableInfoMap.getVariableById(firstShaderType, block.getId(firstShaderType));
5967 
5968         if (block.pod.isArray && block.pod.arrayElement > 0)
5969         {
5970             incrementDescriptorCount(info.binding, 1);
5971             mCurrentInfoIndex++;
5972         }
5973         else
5974         {
5975             updateWriteDesc(info.binding, descriptorType, 1);
5976         }
5977     }
5978 }
5979 
updateAtomicCounters(const ShaderInterfaceVariableInfoMap & variableInfoMap,const std::vector<gl::AtomicCounterBuffer> & atomicCounterBuffers)5980 void WriteDescriptorDescs::updateAtomicCounters(
5981     const ShaderInterfaceVariableInfoMap &variableInfoMap,
5982     const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers)
5983 {
5984     if (atomicCounterBuffers.empty())
5985     {
5986         return;
5987     }
5988 
5989     static_assert(!IsDynamicDescriptor(kStorageBufferDescriptorType),
5990                   "This method needs an update to handle dynamic descriptors");
5991 
5992     uint32_t binding = variableInfoMap.getAtomicCounterBufferBinding(
5993         atomicCounterBuffers[0].getFirstActiveShaderType(), 0);
5994 
5995     updateWriteDesc(binding, kStorageBufferDescriptorType,
5996                     gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS);
5997 }
5998 
updateImages(const gl::ProgramExecutable & executable,const ShaderInterfaceVariableInfoMap & variableInfoMap)5999 void WriteDescriptorDescs::updateImages(const gl::ProgramExecutable &executable,
6000                                         const ShaderInterfaceVariableInfoMap &variableInfoMap)
6001 {
6002     const std::vector<gl::ImageBinding> &imageBindings = executable.getImageBindings();
6003     const std::vector<gl::LinkedUniform> &uniforms     = executable.getUniforms();
6004 
6005     if (imageBindings.empty())
6006     {
6007         return;
6008     }
6009 
6010     for (uint32_t imageIndex = 0; imageIndex < imageBindings.size(); ++imageIndex)
6011     {
6012         const gl::ImageBinding &imageBinding = imageBindings[imageIndex];
6013         uint32_t uniformIndex                = executable.getUniformIndexFromImageIndex(imageIndex);
6014         const gl::LinkedUniform &imageUniform = uniforms[uniformIndex];
6015 
6016         if (imageUniform.activeShaders().none())
6017         {
6018             continue;
6019         }
6020 
6021         const gl::ShaderType firstShaderType = imageUniform.getFirstActiveShaderType();
6022         const ShaderInterfaceVariableInfo &info =
6023             variableInfoMap.getVariableById(firstShaderType, imageUniform.getId(firstShaderType));
6024 
6025         uint32_t arraySize       = static_cast<uint32_t>(imageBinding.boundImageUnits.size());
6026         uint32_t descriptorCount = arraySize * imageUniform.getOuterArraySizeProduct();
6027         VkDescriptorType descriptorType = (imageBinding.textureType == gl::TextureType::Buffer)
6028                                               ? VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER
6029                                               : VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
6030 
6031         updateWriteDesc(info.binding, descriptorType, descriptorCount);
6032     }
6033 }
6034 
updateInputAttachments(const gl::ProgramExecutable & executable,const ShaderInterfaceVariableInfoMap & variableInfoMap,FramebufferVk * framebufferVk)6035 void WriteDescriptorDescs::updateInputAttachments(
6036     const gl::ProgramExecutable &executable,
6037     const ShaderInterfaceVariableInfoMap &variableInfoMap,
6038     FramebufferVk *framebufferVk)
6039 {
6040     if (framebufferVk->getDepthStencilRenderTarget() != nullptr)
6041     {
6042         if (executable.usesDepthFramebufferFetch())
6043         {
6044             const uint32_t depthBinding =
6045                 variableInfoMap
6046                     .getVariableById(gl::ShaderType::Fragment,
6047                                      sh::vk::spirv::kIdDepthInputAttachment)
6048                     .binding;
6049             updateWriteDesc(depthBinding, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1);
6050         }
6051 
6052         if (executable.usesStencilFramebufferFetch())
6053         {
6054             const uint32_t stencilBinding =
6055                 variableInfoMap
6056                     .getVariableById(gl::ShaderType::Fragment,
6057                                      sh::vk::spirv::kIdStencilInputAttachment)
6058                     .binding;
6059             updateWriteDesc(stencilBinding, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1);
6060         }
6061     }
6062 
6063     if (!executable.usesColorFramebufferFetch())
6064     {
6065         return;
6066     }
6067 
6068     const uint32_t firstColorInputAttachment =
6069         static_cast<uint32_t>(executable.getFragmentInoutIndices().first());
6070 
6071     const ShaderInterfaceVariableInfo &baseColorInfo = variableInfoMap.getVariableById(
6072         gl::ShaderType::Fragment, sh::vk::spirv::kIdInputAttachment0 + firstColorInputAttachment);
6073 
6074     const uint32_t baseColorBinding = baseColorInfo.binding - firstColorInputAttachment;
6075 
6076     for (size_t colorIndex : framebufferVk->getState().getColorAttachmentsMask())
6077     {
6078         uint32_t binding = baseColorBinding + static_cast<uint32_t>(colorIndex);
6079         updateWriteDesc(binding, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1);
6080     }
6081 }
6082 
updateExecutableActiveTextures(const ShaderInterfaceVariableInfoMap & variableInfoMap,const gl::ProgramExecutable & executable)6083 void WriteDescriptorDescs::updateExecutableActiveTextures(
6084     const ShaderInterfaceVariableInfoMap &variableInfoMap,
6085     const gl::ProgramExecutable &executable)
6086 {
6087     const std::vector<gl::SamplerBinding> &samplerBindings = executable.getSamplerBindings();
6088     const std::vector<gl::LinkedUniform> &uniforms         = executable.getUniforms();
6089 
6090     for (uint32_t samplerIndex = 0; samplerIndex < samplerBindings.size(); ++samplerIndex)
6091     {
6092         const gl::SamplerBinding &samplerBinding = samplerBindings[samplerIndex];
6093         uint32_t uniformIndex = executable.getUniformIndexFromSamplerIndex(samplerIndex);
6094         const gl::LinkedUniform &samplerUniform = uniforms[uniformIndex];
6095 
6096         if (samplerUniform.activeShaders().none())
6097         {
6098             continue;
6099         }
6100 
6101         const gl::ShaderType firstShaderType = samplerUniform.getFirstActiveShaderType();
6102         const ShaderInterfaceVariableInfo &info =
6103             variableInfoMap.getVariableById(firstShaderType, samplerUniform.getId(firstShaderType));
6104 
6105         uint32_t arraySize              = static_cast<uint32_t>(samplerBinding.textureUnitsCount);
6106         uint32_t descriptorCount        = arraySize * samplerUniform.getOuterArraySizeProduct();
6107         VkDescriptorType descriptorType = (samplerBinding.textureType == gl::TextureType::Buffer)
6108                                               ? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
6109                                               : VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
6110 
6111         updateWriteDesc(info.binding, descriptorType, descriptorCount);
6112     }
6113 }
6114 
updateDefaultUniform(gl::ShaderBitSet shaderTypes,const ShaderInterfaceVariableInfoMap & variableInfoMap,const gl::ProgramExecutable & executable)6115 void WriteDescriptorDescs::updateDefaultUniform(
6116     gl::ShaderBitSet shaderTypes,
6117     const ShaderInterfaceVariableInfoMap &variableInfoMap,
6118     const gl::ProgramExecutable &executable)
6119 {
6120     for (const gl::ShaderType shaderType : shaderTypes)
6121     {
6122         uint32_t binding = variableInfoMap.getDefaultUniformBinding(shaderType);
6123         updateWriteDesc(binding, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1);
6124     }
6125 }
6126 
updateTransformFeedbackWrite(const ShaderInterfaceVariableInfoMap & variableInfoMap,const gl::ProgramExecutable & executable)6127 void WriteDescriptorDescs::updateTransformFeedbackWrite(
6128     const ShaderInterfaceVariableInfoMap &variableInfoMap,
6129     const gl::ProgramExecutable &executable)
6130 {
6131     uint32_t xfbBufferCount = static_cast<uint32_t>(executable.getTransformFeedbackBufferCount());
6132     updateWriteDesc(variableInfoMap.getEmulatedXfbBufferBinding(0),
6133                     VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, xfbBufferCount);
6134 }
6135 
updateDynamicDescriptorsCount()6136 void WriteDescriptorDescs::updateDynamicDescriptorsCount()
6137 {
6138     mDynamicDescriptorSetCount = 0;
6139     for (uint32_t index = 0; index < mDescs.size(); ++index)
6140     {
6141         const WriteDescriptorDesc &writeDesc = mDescs[index];
6142         if (IsDynamicDescriptor(static_cast<VkDescriptorType>(writeDesc.descriptorType)))
6143         {
6144             mDynamicDescriptorSetCount += writeDesc.descriptorCount;
6145         }
6146     }
6147 }
6148 
operator <<(std::ostream & os,const WriteDescriptorDescs & desc)6149 std::ostream &operator<<(std::ostream &os, const WriteDescriptorDescs &desc)
6150 {
6151     os << " WriteDescriptorDescs[" << desc.size() << "]:";
6152     for (uint32_t index = 0; index < desc.size(); ++index)
6153     {
6154         const WriteDescriptorDesc &writeDesc = desc[index];
6155         os << static_cast<int>(writeDesc.binding) << ": "
6156            << static_cast<int>(writeDesc.descriptorCount) << ": "
6157            << kDescriptorTypeNameMap[writeDesc.descriptorType] << ": "
6158            << writeDesc.descriptorInfoIndex;
6159     }
6160     return os;
6161 }
6162 
6163 // DescriptorSetDesc implementation.
updateDescriptorSet(Renderer * renderer,const WriteDescriptorDescs & writeDescriptorDescs,UpdateDescriptorSetsBuilder * updateBuilder,const DescriptorDescHandles * handles,VkDescriptorSet descriptorSet) const6164 void DescriptorSetDesc::updateDescriptorSet(Renderer *renderer,
6165                                             const WriteDescriptorDescs &writeDescriptorDescs,
6166                                             UpdateDescriptorSetsBuilder *updateBuilder,
6167                                             const DescriptorDescHandles *handles,
6168                                             VkDescriptorSet descriptorSet) const
6169 {
6170     for (uint32_t writeIndex = 0; writeIndex < writeDescriptorDescs.size(); ++writeIndex)
6171     {
6172         const WriteDescriptorDesc &writeDesc = writeDescriptorDescs[writeIndex];
6173 
6174         if (writeDesc.descriptorCount == 0)
6175         {
6176             continue;
6177         }
6178 
6179         VkWriteDescriptorSet &writeSet = updateBuilder->allocWriteDescriptorSet();
6180 
6181         writeSet.descriptorCount  = writeDesc.descriptorCount;
6182         writeSet.descriptorType   = static_cast<VkDescriptorType>(writeDesc.descriptorType);
6183         writeSet.dstArrayElement  = 0;
6184         writeSet.dstBinding       = writeIndex;
6185         writeSet.dstSet           = descriptorSet;
6186         writeSet.pBufferInfo      = nullptr;
6187         writeSet.pImageInfo       = nullptr;
6188         writeSet.pNext            = nullptr;
6189         writeSet.pTexelBufferView = nullptr;
6190         writeSet.sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
6191 
6192         uint32_t infoDescIndex = writeDesc.descriptorInfoIndex;
6193 
6194         switch (writeSet.descriptorType)
6195         {
6196             case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
6197             case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
6198             {
6199                 ASSERT(writeDesc.descriptorCount == 1);
6200                 VkBufferView &bufferView  = updateBuilder->allocBufferView();
6201                 bufferView                = handles[infoDescIndex].bufferView;
6202                 writeSet.pTexelBufferView = &bufferView;
6203                 break;
6204             }
6205             case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
6206             case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
6207             case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
6208             case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
6209             {
6210                 VkDescriptorBufferInfo *writeBuffers =
6211                     updateBuilder->allocDescriptorBufferInfos(writeSet.descriptorCount);
6212                 for (uint32_t arrayElement = 0; arrayElement < writeSet.descriptorCount;
6213                      ++arrayElement)
6214                 {
6215                     const DescriptorInfoDesc &infoDesc =
6216                         mDescriptorInfos[infoDescIndex + arrayElement];
6217                     VkDescriptorBufferInfo &bufferInfo = writeBuffers[arrayElement];
6218                     bufferInfo.buffer = handles[infoDescIndex + arrayElement].buffer;
6219                     bufferInfo.offset = infoDesc.imageViewSerialOrOffset;
6220                     bufferInfo.range  = infoDesc.imageLayoutOrRange;
6221                 }
6222                 writeSet.pBufferInfo = writeBuffers;
6223                 break;
6224             }
6225             case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
6226             case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
6227             case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
6228             case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
6229             {
6230                 VkDescriptorImageInfo *writeImages =
6231                     updateBuilder->allocDescriptorImageInfos(writeSet.descriptorCount);
6232                 for (uint32_t arrayElement = 0; arrayElement < writeSet.descriptorCount;
6233                      ++arrayElement)
6234                 {
6235                     const DescriptorInfoDesc &infoDesc =
6236                         mDescriptorInfos[infoDescIndex + arrayElement];
6237                     VkDescriptorImageInfo &imageInfo = writeImages[arrayElement];
6238 
6239                     imageInfo.imageLayout = static_cast<VkImageLayout>(infoDesc.imageLayoutOrRange);
6240                     imageInfo.imageView = handles[infoDescIndex + arrayElement].imageView;
6241                     imageInfo.sampler   = handles[infoDescIndex + arrayElement].sampler;
6242                 }
6243                 writeSet.pImageInfo = writeImages;
6244                 break;
6245             }
6246 
6247             default:
6248                 UNREACHABLE();
6249                 break;
6250         }
6251     }
6252 }
6253 
operator <<(std::ostream & os,const DescriptorSetDesc & desc)6254 std::ostream &operator<<(std::ostream &os, const DescriptorSetDesc &desc)
6255 {
6256     os << " desc[" << desc.size() << "]:";
6257     for (uint32_t index = 0; index < desc.size(); ++index)
6258     {
6259         const DescriptorInfoDesc &infoDesc = desc.getInfoDesc(index);
6260         os << "{" << infoDesc.samplerOrBufferSerial << ", " << infoDesc.imageViewSerialOrOffset
6261            << ", " << infoDesc.imageLayoutOrRange << ", " << infoDesc.imageSubresourceRange << "}";
6262     }
6263     return os;
6264 }
6265 
6266 // DescriptorSetDescAndPool implementation
destroyCachedObject(Renderer * renderer)6267 void DescriptorSetDescAndPool::destroyCachedObject(Renderer *renderer)
6268 {
6269     ASSERT(valid());
6270     mPool->destroyCachedDescriptorSet(renderer, mDesc);
6271     mPool = nullptr;
6272 }
6273 
releaseCachedObject(Renderer * renderer)6274 void DescriptorSetDescAndPool::releaseCachedObject(Renderer *renderer)
6275 {
6276     ASSERT(valid());
6277     mPool->releaseCachedDescriptorSet(renderer, mDesc);
6278     mPool = nullptr;
6279 }
6280 
hasValidCachedObject(ContextVk * contextVk) const6281 bool DescriptorSetDescAndPool::hasValidCachedObject(ContextVk *contextVk) const
6282 {
6283     ASSERT(valid());
6284     return mPool->hasCachedDescriptorSet(mDesc);
6285 }
6286 
6287 // DescriptorSetDescBuilder implementation.
6288 DescriptorSetDescBuilder::DescriptorSetDescBuilder() = default;
DescriptorSetDescBuilder(size_t descriptorCount)6289 DescriptorSetDescBuilder::DescriptorSetDescBuilder(size_t descriptorCount)
6290 {
6291     resize(descriptorCount);
6292 }
6293 
~DescriptorSetDescBuilder()6294 DescriptorSetDescBuilder::~DescriptorSetDescBuilder() {}
6295 
DescriptorSetDescBuilder(const DescriptorSetDescBuilder & other)6296 DescriptorSetDescBuilder::DescriptorSetDescBuilder(const DescriptorSetDescBuilder &other)
6297     : mDesc(other.mDesc), mHandles(other.mHandles), mDynamicOffsets(other.mDynamicOffsets)
6298 {}
6299 
operator =(const DescriptorSetDescBuilder & other)6300 DescriptorSetDescBuilder &DescriptorSetDescBuilder::operator=(const DescriptorSetDescBuilder &other)
6301 {
6302     mDesc           = other.mDesc;
6303     mHandles        = other.mHandles;
6304     mDynamicOffsets = other.mDynamicOffsets;
6305     return *this;
6306 }
6307 
updateUniformBuffer(uint32_t bindingIndex,const WriteDescriptorDescs & writeDescriptorDescs,const BufferHelper & bufferHelper,VkDeviceSize bufferRange)6308 void DescriptorSetDescBuilder::updateUniformBuffer(uint32_t bindingIndex,
6309                                                    const WriteDescriptorDescs &writeDescriptorDescs,
6310                                                    const BufferHelper &bufferHelper,
6311                                                    VkDeviceSize bufferRange)
6312 {
6313     uint32_t infoIndex           = writeDescriptorDescs[bindingIndex].descriptorInfoIndex;
6314     DescriptorInfoDesc &infoDesc = mDesc.getInfoDesc(infoIndex);
6315 
6316     infoDesc.samplerOrBufferSerial   = bufferHelper.getBlockSerial().getValue();
6317     infoDesc.imageViewSerialOrOffset = 0;
6318     SetBitField(infoDesc.imageLayoutOrRange, bufferRange);
6319     infoDesc.imageSubresourceRange = 0;
6320 
6321     mHandles[infoIndex].buffer = bufferHelper.getBuffer().getHandle();
6322 }
6323 
updateTransformFeedbackBuffer(const Context * context,const ShaderInterfaceVariableInfoMap & variableInfoMap,const WriteDescriptorDescs & writeDescriptorDescs,uint32_t xfbBufferIndex,const BufferHelper & bufferHelper,VkDeviceSize bufferOffset,VkDeviceSize bufferRange)6324 void DescriptorSetDescBuilder::updateTransformFeedbackBuffer(
6325     const Context *context,
6326     const ShaderInterfaceVariableInfoMap &variableInfoMap,
6327     const WriteDescriptorDescs &writeDescriptorDescs,
6328     uint32_t xfbBufferIndex,
6329     const BufferHelper &bufferHelper,
6330     VkDeviceSize bufferOffset,
6331     VkDeviceSize bufferRange)
6332 {
6333     const uint32_t baseBinding = variableInfoMap.getEmulatedXfbBufferBinding(0);
6334 
6335     Renderer *renderer = context->getRenderer();
6336     VkDeviceSize offsetAlignment =
6337         renderer->getPhysicalDeviceProperties().limits.minStorageBufferOffsetAlignment;
6338     // Set the offset as close as possible to the requested offset while remaining aligned.
6339     VkDeviceSize alignedOffset = (bufferOffset / offsetAlignment) * offsetAlignment;
6340     VkDeviceSize adjustedRange = bufferRange + (bufferOffset - alignedOffset);
6341 
6342     uint32_t infoIndex = writeDescriptorDescs[baseBinding].descriptorInfoIndex + xfbBufferIndex;
6343     DescriptorInfoDesc &infoDesc   = mDesc.getInfoDesc(infoIndex);
6344     infoDesc.samplerOrBufferSerial = bufferHelper.getBufferSerial().getValue();
6345     SetBitField(infoDesc.imageViewSerialOrOffset, alignedOffset);
6346     SetBitField(infoDesc.imageLayoutOrRange, adjustedRange);
6347     infoDesc.imageSubresourceRange = 0;
6348 
6349     mHandles[infoIndex].buffer = bufferHelper.getBuffer().getHandle();
6350 }
6351 
updateUniformsAndXfb(Context * context,const gl::ProgramExecutable & executable,const WriteDescriptorDescs & writeDescriptorDescs,const BufferHelper * currentUniformBuffer,const BufferHelper & emptyBuffer,bool activeUnpaused,TransformFeedbackVk * transformFeedbackVk)6352 void DescriptorSetDescBuilder::updateUniformsAndXfb(
6353     Context *context,
6354     const gl::ProgramExecutable &executable,
6355     const WriteDescriptorDescs &writeDescriptorDescs,
6356     const BufferHelper *currentUniformBuffer,
6357     const BufferHelper &emptyBuffer,
6358     bool activeUnpaused,
6359     TransformFeedbackVk *transformFeedbackVk)
6360 {
6361     const ProgramExecutableVk *executableVk = vk::GetImpl(&executable);
6362     gl::ShaderBitSet linkedStages           = executable.getLinkedShaderStages();
6363 
6364     const ShaderInterfaceVariableInfoMap &variableInfoMap = executableVk->getVariableInfoMap();
6365 
6366     for (const gl::ShaderType shaderType : linkedStages)
6367     {
6368         uint32_t binding         = variableInfoMap.getDefaultUniformBinding(shaderType);
6369         VkDeviceSize bufferRange = executableVk->getDefaultUniformAlignedSize(context, shaderType);
6370         if (bufferRange == 0)
6371         {
6372             updateUniformBuffer(binding, writeDescriptorDescs, emptyBuffer, emptyBuffer.getSize());
6373         }
6374         else
6375         {
6376             ASSERT(currentUniformBuffer);
6377             updateUniformBuffer(binding, writeDescriptorDescs, *currentUniformBuffer, bufferRange);
6378         }
6379 
6380         if (transformFeedbackVk && shaderType == gl::ShaderType::Vertex &&
6381             context->getFeatures().emulateTransformFeedback.enabled)
6382         {
6383             transformFeedbackVk->updateTransformFeedbackDescriptorDesc(
6384                 context, executable, variableInfoMap, writeDescriptorDescs, emptyBuffer,
6385                 activeUnpaused, this);
6386         }
6387     }
6388 }
6389 
updatePreCacheActiveTextures(Context * context,const gl::ProgramExecutable & executable,const gl::ActiveTextureArray<TextureVk * > & textures,const gl::SamplerBindingVector & samplers)6390 void DescriptorSetDescBuilder::updatePreCacheActiveTextures(
6391     Context *context,
6392     const gl::ProgramExecutable &executable,
6393     const gl::ActiveTextureArray<TextureVk *> &textures,
6394     const gl::SamplerBindingVector &samplers)
6395 {
6396     const std::vector<gl::SamplerBinding> &samplerBindings = executable.getSamplerBindings();
6397     const gl::ActiveTextureMask &activeTextures            = executable.getActiveSamplersMask();
6398     const ProgramExecutableVk *executableVk                = vk::GetImpl(&executable);
6399 
6400     resize(executableVk->getTextureWriteDescriptorDescs().getTotalDescriptorCount());
6401     const WriteDescriptorDescs &writeDescriptorDescs =
6402         executableVk->getTextureWriteDescriptorDescs();
6403 
6404     const ShaderInterfaceVariableInfoMap &variableInfoMap = executableVk->getVariableInfoMap();
6405     const std::vector<gl::LinkedUniform> &uniforms        = executable.getUniforms();
6406 
6407     for (uint32_t samplerIndex = 0; samplerIndex < samplerBindings.size(); ++samplerIndex)
6408     {
6409         const gl::SamplerBinding &samplerBinding = samplerBindings[samplerIndex];
6410         uint16_t arraySize                       = samplerBinding.textureUnitsCount;
6411         bool isSamplerExternalY2Y = samplerBinding.samplerType == GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT;
6412 
6413         uint32_t uniformIndex = executable.getUniformIndexFromSamplerIndex(samplerIndex);
6414         const gl::LinkedUniform &samplerUniform = uniforms[uniformIndex];
6415 
6416         if (samplerUniform.activeShaders().none())
6417         {
6418             continue;
6419         }
6420 
6421         const gl::ShaderType firstShaderType = samplerUniform.getFirstActiveShaderType();
6422         const ShaderInterfaceVariableInfo &info =
6423             variableInfoMap.getVariableById(firstShaderType, samplerUniform.getId(firstShaderType));
6424 
6425         for (uint16_t arrayElement = 0; arrayElement < arraySize; ++arrayElement)
6426         {
6427             GLuint textureUnit = samplerBinding.getTextureUnit(
6428                 executable.getSamplerBoundTextureUnits(), arrayElement);
6429             if (!activeTextures.test(textureUnit))
6430                 continue;
6431             TextureVk *textureVk = textures[textureUnit];
6432 
6433             uint32_t infoIndex = writeDescriptorDescs[info.binding].descriptorInfoIndex +
6434                                  arrayElement + samplerUniform.getOuterArrayOffset();
6435             DescriptorInfoDesc &infoDesc = mDesc.getInfoDesc(infoIndex);
6436 
6437             if (textureVk->getState().getType() == gl::TextureType::Buffer)
6438             {
6439                 ImageOrBufferViewSubresourceSerial imageViewSerial =
6440                     textureVk->getBufferViewSerial();
6441                 infoDesc.imageViewSerialOrOffset = imageViewSerial.viewSerial.getValue();
6442                 infoDesc.imageLayoutOrRange      = 0;
6443                 infoDesc.samplerOrBufferSerial   = 0;
6444                 infoDesc.imageSubresourceRange   = 0;
6445             }
6446             else
6447             {
6448                 gl::Sampler *sampler       = samplers[textureUnit].get();
6449                 const SamplerVk *samplerVk = sampler ? vk::GetImpl(sampler) : nullptr;
6450 
6451                 const SamplerHelper &samplerHelper =
6452                     samplerVk ? samplerVk->getSampler()
6453                               : textureVk->getSampler(isSamplerExternalY2Y);
6454                 const gl::SamplerState &samplerState =
6455                     sampler ? sampler->getSamplerState() : textureVk->getState().getSamplerState();
6456 
6457                 ImageOrBufferViewSubresourceSerial imageViewSerial =
6458                     textureVk->getImageViewSubresourceSerial(
6459                         samplerState, samplerUniform.isTexelFetchStaticUse());
6460 
6461                 VkImageLayout imageLayout = textureVk->getImage().getCurrentLayout();
6462                 SetBitField(infoDesc.imageLayoutOrRange, imageLayout);
6463                 infoDesc.imageViewSerialOrOffset = imageViewSerial.viewSerial.getValue();
6464                 infoDesc.samplerOrBufferSerial   = samplerHelper.getSamplerSerial().getValue();
6465                 memcpy(&infoDesc.imageSubresourceRange, &imageViewSerial.subresource,
6466                        sizeof(uint32_t));
6467             }
6468         }
6469     }
6470 }
6471 
setEmptyBuffer(uint32_t infoDescIndex,VkDescriptorType descriptorType,const BufferHelper & emptyBuffer)6472 void DescriptorSetDescBuilder::setEmptyBuffer(uint32_t infoDescIndex,
6473                                               VkDescriptorType descriptorType,
6474                                               const BufferHelper &emptyBuffer)
6475 {
6476     DescriptorInfoDesc &emptyDesc = mDesc.getInfoDesc(infoDescIndex);
6477     SetBitField(emptyDesc.imageLayoutOrRange, emptyBuffer.getSize());
6478     emptyDesc.imageViewSerialOrOffset = 0;
6479     emptyDesc.samplerOrBufferSerial   = emptyBuffer.getBlockSerial().getValue();
6480 
6481     mHandles[infoDescIndex].buffer = emptyBuffer.getBuffer().getHandle();
6482 
6483     if (IsDynamicDescriptor(descriptorType))
6484     {
6485         mDynamicOffsets[infoDescIndex] = 0;
6486     }
6487 }
6488 
6489 template <typename CommandBufferT>
updateOneShaderBuffer(Context * context,CommandBufferT * commandBufferHelper,const ShaderInterfaceVariableInfoMap & variableInfoMap,const gl::BufferVector & buffers,const gl::InterfaceBlock & block,uint32_t bufferIndex,VkDescriptorType descriptorType,VkDeviceSize maxBoundBufferRange,const BufferHelper & emptyBuffer,const WriteDescriptorDescs & writeDescriptorDescs,const GLbitfield memoryBarrierBits)6490 void DescriptorSetDescBuilder::updateOneShaderBuffer(
6491     Context *context,
6492     CommandBufferT *commandBufferHelper,
6493     const ShaderInterfaceVariableInfoMap &variableInfoMap,
6494     const gl::BufferVector &buffers,
6495     const gl::InterfaceBlock &block,
6496     uint32_t bufferIndex,
6497     VkDescriptorType descriptorType,
6498     VkDeviceSize maxBoundBufferRange,
6499     const BufferHelper &emptyBuffer,
6500     const WriteDescriptorDescs &writeDescriptorDescs,
6501     const GLbitfield memoryBarrierBits)
6502 {
6503     if (block.activeShaders().none())
6504     {
6505         return;
6506     }
6507 
6508     const gl::ShaderType firstShaderType = block.getFirstActiveShaderType();
6509     const ShaderInterfaceVariableInfo &info =
6510         variableInfoMap.getVariableById(firstShaderType, block.getId(firstShaderType));
6511 
6512     uint32_t binding       = info.binding;
6513     uint32_t arrayElement  = block.pod.isArray ? block.pod.arrayElement : 0;
6514     uint32_t infoDescIndex = writeDescriptorDescs[binding].descriptorInfoIndex + arrayElement;
6515 
6516     const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding = buffers[bufferIndex];
6517     if (bufferBinding.get() == nullptr)
6518     {
6519         setEmptyBuffer(infoDescIndex, descriptorType, emptyBuffer);
6520         return;
6521     }
6522 
6523     // Limit bound buffer size to maximum resource binding size.
6524     GLsizeiptr boundBufferSize = gl::GetBoundBufferAvailableSize(bufferBinding);
6525     VkDeviceSize size          = std::min<VkDeviceSize>(boundBufferSize, maxBoundBufferRange);
6526 
6527     // Make sure there's no possible under/overflow with binding size.
6528     static_assert(sizeof(VkDeviceSize) >= sizeof(bufferBinding.getSize()),
6529                   "VkDeviceSize too small");
6530     ASSERT(bufferBinding.getSize() >= 0);
6531 
6532     BufferVk *bufferVk         = vk::GetImpl(bufferBinding.get());
6533     BufferHelper &bufferHelper = bufferVk->getBuffer();
6534 
6535     const bool isUniformBuffer = descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
6536                                  descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
6537     if (isUniformBuffer)
6538     {
6539         commandBufferHelper->bufferRead(context, VK_ACCESS_UNIFORM_READ_BIT, block.activeShaders(),
6540                                         &bufferHelper);
6541     }
6542     else
6543     {
6544         ASSERT(descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER ||
6545                descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC);
6546         if (block.pod.isReadOnly)
6547         {
6548             // Avoid unnecessary barriers for readonly SSBOs by making sure the buffers are
6549             // marked read-only.  This also helps BufferVk make better decisions during
6550             // buffer data uploads and copies by knowing that the buffers are not actually
6551             // being written to.
6552             commandBufferHelper->bufferRead(context, VK_ACCESS_SHADER_READ_BIT,
6553                                             block.activeShaders(), &bufferHelper);
6554         }
6555         else if ((bufferHelper.getCurrentWriteAccess() & VK_ACCESS_SHADER_WRITE_BIT) != 0 &&
6556                  (memoryBarrierBits & kBufferMemoryBarrierBits) == 0)
6557         {
6558             // Buffer is already in shader write access, and this is not from memoryBarrier call,
6559             // then skip the WAW barrier since GL spec says driver is not required to insert barrier
6560             // here. We still need to maintain object life time tracking here.
6561             // Based on discussion here https://gitlab.khronos.org/opengl/API/-/issues/144, the
6562             // above check of VK_ACCESS_SHADER_WRITE_BIT bit can be removed and instead rely on app
6563             // issue glMemoryBarrier. But almost all usage I am seeing does not issue
6564             // glMemoryBarrier before SSBO write. They only issue glMemoryBarrier after the SSBO
6565             // write. This is to ensure we do not break the existing usage even if we think they are
6566             // out of spec.
6567             commandBufferHelper->retainResourceForWrite(&bufferHelper);
6568         }
6569         else
6570         {
6571             // We set the SHADER_READ_BIT to be conservative.
6572             VkAccessFlags accessFlags = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
6573             commandBufferHelper->bufferWrite(context, accessFlags, block.activeShaders(),
6574                                              &bufferHelper);
6575         }
6576     }
6577 
6578     VkDeviceSize offset = bufferBinding.getOffset() + bufferHelper.getOffset();
6579 
6580     DescriptorInfoDesc &infoDesc   = mDesc.getInfoDesc(infoDescIndex);
6581     infoDesc.samplerOrBufferSerial = bufferHelper.getBlockSerial().getValue();
6582     if (IsDynamicDescriptor(descriptorType))
6583     {
6584         SetBitField(mDynamicOffsets[infoDescIndex], offset);
6585         infoDesc.imageViewSerialOrOffset = 0;
6586     }
6587     else
6588     {
6589         SetBitField(infoDesc.imageViewSerialOrOffset, offset);
6590     }
6591     SetBitField(infoDesc.imageLayoutOrRange, size);
6592     infoDesc.imageSubresourceRange = 0;
6593 
6594     mHandles[infoDescIndex].buffer = bufferHelper.getBuffer().getHandle();
6595 }
6596 
6597 template <typename CommandBufferT>
updateShaderBuffers(Context * context,CommandBufferT * commandBufferHelper,const gl::ProgramExecutable & executable,const ShaderInterfaceVariableInfoMap & variableInfoMap,const gl::BufferVector & buffers,const std::vector<gl::InterfaceBlock> & blocks,VkDescriptorType descriptorType,VkDeviceSize maxBoundBufferRange,const BufferHelper & emptyBuffer,const WriteDescriptorDescs & writeDescriptorDescs,const GLbitfield memoryBarrierBits)6598 void DescriptorSetDescBuilder::updateShaderBuffers(
6599     Context *context,
6600     CommandBufferT *commandBufferHelper,
6601     const gl::ProgramExecutable &executable,
6602     const ShaderInterfaceVariableInfoMap &variableInfoMap,
6603     const gl::BufferVector &buffers,
6604     const std::vector<gl::InterfaceBlock> &blocks,
6605     VkDescriptorType descriptorType,
6606     VkDeviceSize maxBoundBufferRange,
6607     const BufferHelper &emptyBuffer,
6608     const WriteDescriptorDescs &writeDescriptorDescs,
6609     const GLbitfield memoryBarrierBits)
6610 {
6611     const bool isUniformBuffer = descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
6612                                  descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
6613 
6614     // Now that we have the proper array elements counts, initialize the info structures.
6615     for (uint32_t blockIndex = 0; blockIndex < blocks.size(); ++blockIndex)
6616     {
6617         const GLuint binding = isUniformBuffer
6618                                    ? executable.getUniformBlockBinding(blockIndex)
6619                                    : executable.getShaderStorageBlockBinding(blockIndex);
6620         updateOneShaderBuffer(context, commandBufferHelper, variableInfoMap, buffers,
6621                               blocks[blockIndex], binding, descriptorType, maxBoundBufferRange,
6622                               emptyBuffer, writeDescriptorDescs, memoryBarrierBits);
6623     }
6624 }
6625 
6626 template <typename CommandBufferT>
updateAtomicCounters(Context * context,CommandBufferT * commandBufferHelper,const gl::ProgramExecutable & executable,const ShaderInterfaceVariableInfoMap & variableInfoMap,const gl::BufferVector & buffers,const std::vector<gl::AtomicCounterBuffer> & atomicCounterBuffers,const VkDeviceSize requiredOffsetAlignment,const BufferHelper & emptyBuffer,const WriteDescriptorDescs & writeDescriptorDescs)6627 void DescriptorSetDescBuilder::updateAtomicCounters(
6628     Context *context,
6629     CommandBufferT *commandBufferHelper,
6630     const gl::ProgramExecutable &executable,
6631     const ShaderInterfaceVariableInfoMap &variableInfoMap,
6632     const gl::BufferVector &buffers,
6633     const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers,
6634     const VkDeviceSize requiredOffsetAlignment,
6635     const BufferHelper &emptyBuffer,
6636     const WriteDescriptorDescs &writeDescriptorDescs)
6637 {
6638     ASSERT(!atomicCounterBuffers.empty());
6639     static_assert(!IsDynamicDescriptor(kStorageBufferDescriptorType),
6640                   "This method needs an update to handle dynamic descriptors");
6641 
6642     if (atomicCounterBuffers.empty())
6643     {
6644         return;
6645     }
6646 
6647     uint32_t binding = variableInfoMap.getAtomicCounterBufferBinding(
6648         atomicCounterBuffers[0].getFirstActiveShaderType(), 0);
6649     uint32_t baseInfoIndex = writeDescriptorDescs[binding].descriptorInfoIndex;
6650 
6651     // Bind the empty buffer to every array slot that's unused.
6652     for (uint32_t arrayElement = 0;
6653          arrayElement < gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS; ++arrayElement)
6654     {
6655         uint32_t infoIndex = baseInfoIndex + arrayElement;
6656         setEmptyBuffer(infoIndex, kStorageBufferDescriptorType, emptyBuffer);
6657     }
6658 
6659     for (uint32_t bufferIndex = 0; bufferIndex < atomicCounterBuffers.size(); ++bufferIndex)
6660     {
6661         const gl::AtomicCounterBuffer &atomicCounterBuffer = atomicCounterBuffers[bufferIndex];
6662         const GLuint arrayElement = executable.getAtomicCounterBufferBinding(bufferIndex);
6663         const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding = buffers[arrayElement];
6664 
6665         uint32_t infoIndex = baseInfoIndex + arrayElement;
6666 
6667         if (bufferBinding.get() == nullptr)
6668         {
6669             setEmptyBuffer(infoIndex, kStorageBufferDescriptorType, emptyBuffer);
6670             continue;
6671         }
6672 
6673         BufferVk *bufferVk             = vk::GetImpl(bufferBinding.get());
6674         vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
6675 
6676         VkAccessFlags accessFlags = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
6677         commandBufferHelper->bufferWrite(context, accessFlags, atomicCounterBuffer.activeShaders(),
6678                                          &bufferHelper);
6679 
6680         VkDeviceSize offset = bufferBinding.getOffset() + bufferHelper.getOffset();
6681 
6682         VkDeviceSize alignedOffset = (offset / requiredOffsetAlignment) * requiredOffsetAlignment;
6683         VkDeviceSize offsetDiff    = offset - alignedOffset;
6684 
6685         offset = alignedOffset;
6686 
6687         VkDeviceSize range = gl::GetBoundBufferAvailableSize(bufferBinding) + offsetDiff;
6688 
6689         DescriptorInfoDesc &infoDesc = mDesc.getInfoDesc(infoIndex);
6690         SetBitField(infoDesc.imageLayoutOrRange, range);
6691         SetBitField(infoDesc.imageViewSerialOrOffset, offset);
6692         infoDesc.samplerOrBufferSerial = bufferHelper.getBlockSerial().getValue();
6693         infoDesc.imageSubresourceRange = 0;
6694 
6695         mHandles[infoIndex].buffer = bufferHelper.getBuffer().getHandle();
6696     }
6697 }
6698 
6699 // Explicit instantiation
6700 template void DescriptorSetDescBuilder::updateOneShaderBuffer<vk::RenderPassCommandBufferHelper>(
6701     Context *context,
6702     RenderPassCommandBufferHelper *commandBufferHelper,
6703     const ShaderInterfaceVariableInfoMap &variableInfoMap,
6704     const gl::BufferVector &buffers,
6705     const gl::InterfaceBlock &block,
6706     uint32_t bufferIndex,
6707     VkDescriptorType descriptorType,
6708     VkDeviceSize maxBoundBufferRange,
6709     const BufferHelper &emptyBuffer,
6710     const WriteDescriptorDescs &writeDescriptorDescs,
6711     const GLbitfield memoryBarrierBits);
6712 
6713 template void DescriptorSetDescBuilder::updateOneShaderBuffer<OutsideRenderPassCommandBufferHelper>(
6714     Context *context,
6715     OutsideRenderPassCommandBufferHelper *commandBufferHelper,
6716     const ShaderInterfaceVariableInfoMap &variableInfoMap,
6717     const gl::BufferVector &buffers,
6718     const gl::InterfaceBlock &block,
6719     uint32_t bufferIndex,
6720     VkDescriptorType descriptorType,
6721     VkDeviceSize maxBoundBufferRange,
6722     const BufferHelper &emptyBuffer,
6723     const WriteDescriptorDescs &writeDescriptorDescs,
6724     const GLbitfield memoryBarrierBits);
6725 
6726 template void DescriptorSetDescBuilder::updateShaderBuffers<OutsideRenderPassCommandBufferHelper>(
6727     Context *context,
6728     OutsideRenderPassCommandBufferHelper *commandBufferHelper,
6729     const gl::ProgramExecutable &executable,
6730     const ShaderInterfaceVariableInfoMap &variableInfoMap,
6731     const gl::BufferVector &buffers,
6732     const std::vector<gl::InterfaceBlock> &blocks,
6733     VkDescriptorType descriptorType,
6734     VkDeviceSize maxBoundBufferRange,
6735     const BufferHelper &emptyBuffer,
6736     const WriteDescriptorDescs &writeDescriptorDescs,
6737     const GLbitfield memoryBarrierBits);
6738 
6739 template void DescriptorSetDescBuilder::updateShaderBuffers<RenderPassCommandBufferHelper>(
6740     Context *context,
6741     RenderPassCommandBufferHelper *commandBufferHelper,
6742     const gl::ProgramExecutable &executable,
6743     const ShaderInterfaceVariableInfoMap &variableInfoMap,
6744     const gl::BufferVector &buffers,
6745     const std::vector<gl::InterfaceBlock> &blocks,
6746     VkDescriptorType descriptorType,
6747     VkDeviceSize maxBoundBufferRange,
6748     const BufferHelper &emptyBuffer,
6749     const WriteDescriptorDescs &writeDescriptorDescs,
6750     const GLbitfield memoryBarrierBits);
6751 
6752 template void DescriptorSetDescBuilder::updateAtomicCounters<OutsideRenderPassCommandBufferHelper>(
6753     Context *context,
6754     OutsideRenderPassCommandBufferHelper *commandBufferHelper,
6755     const gl::ProgramExecutable &executable,
6756     const ShaderInterfaceVariableInfoMap &variableInfoMap,
6757     const gl::BufferVector &buffers,
6758     const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers,
6759     const VkDeviceSize requiredOffsetAlignment,
6760     const BufferHelper &emptyBuffer,
6761     const WriteDescriptorDescs &writeDescriptorDescs);
6762 
6763 template void DescriptorSetDescBuilder::updateAtomicCounters<RenderPassCommandBufferHelper>(
6764     Context *context,
6765     RenderPassCommandBufferHelper *commandBufferHelper,
6766     const gl::ProgramExecutable &executable,
6767     const ShaderInterfaceVariableInfoMap &variableInfoMap,
6768     const gl::BufferVector &buffers,
6769     const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers,
6770     const VkDeviceSize requiredOffsetAlignment,
6771     const BufferHelper &emptyBuffer,
6772     const WriteDescriptorDescs &writeDescriptorDescs);
6773 
updateImages(Context * context,const gl::ProgramExecutable & executable,const ShaderInterfaceVariableInfoMap & variableInfoMap,const gl::ActiveTextureArray<TextureVk * > & activeImages,const std::vector<gl::ImageUnit> & imageUnits,const WriteDescriptorDescs & writeDescriptorDescs)6774 angle::Result DescriptorSetDescBuilder::updateImages(
6775     Context *context,
6776     const gl::ProgramExecutable &executable,
6777     const ShaderInterfaceVariableInfoMap &variableInfoMap,
6778     const gl::ActiveTextureArray<TextureVk *> &activeImages,
6779     const std::vector<gl::ImageUnit> &imageUnits,
6780     const WriteDescriptorDescs &writeDescriptorDescs)
6781 {
6782     Renderer *renderer                                 = context->getRenderer();
6783     const std::vector<gl::ImageBinding> &imageBindings = executable.getImageBindings();
6784     const std::vector<gl::LinkedUniform> &uniforms     = executable.getUniforms();
6785 
6786     if (imageBindings.empty())
6787     {
6788         return angle::Result::Continue;
6789     }
6790 
6791     for (uint32_t imageIndex = 0; imageIndex < imageBindings.size(); ++imageIndex)
6792     {
6793         const gl::ImageBinding &imageBinding = imageBindings[imageIndex];
6794         uint32_t uniformIndex                = executable.getUniformIndexFromImageIndex(imageIndex);
6795         const gl::LinkedUniform &imageUniform = uniforms[uniformIndex];
6796 
6797         if (imageUniform.activeShaders().none())
6798         {
6799             continue;
6800         }
6801 
6802         const gl::ShaderType firstShaderType = imageUniform.getFirstActiveShaderType();
6803         const ShaderInterfaceVariableInfo &info =
6804             variableInfoMap.getVariableById(firstShaderType, imageUniform.getId(firstShaderType));
6805 
6806         uint32_t arraySize = static_cast<uint32_t>(imageBinding.boundImageUnits.size());
6807 
6808         // Texture buffers use buffer views, so they are especially handled.
6809         if (imageBinding.textureType == gl::TextureType::Buffer)
6810         {
6811             // Handle format reinterpretation by looking for a view with the format specified in
6812             // the shader (if any, instead of the format specified to glTexBuffer).
6813             const vk::Format *format = nullptr;
6814             if (imageUniform.getImageUnitFormat() != GL_NONE)
6815             {
6816                 format = &renderer->getFormat(imageUniform.getImageUnitFormat());
6817             }
6818 
6819             for (uint32_t arrayElement = 0; arrayElement < arraySize; ++arrayElement)
6820             {
6821                 GLuint imageUnit     = imageBinding.boundImageUnits[arrayElement];
6822                 TextureVk *textureVk = activeImages[imageUnit];
6823 
6824                 uint32_t infoIndex = writeDescriptorDescs[info.binding].descriptorInfoIndex +
6825                                      arrayElement + imageUniform.getOuterArrayOffset();
6826 
6827                 const vk::BufferView *view = nullptr;
6828                 ANGLE_TRY(textureVk->getBufferView(context, format, nullptr, true, &view));
6829 
6830                 DescriptorInfoDesc &infoDesc = mDesc.getInfoDesc(infoIndex);
6831                 infoDesc.imageViewSerialOrOffset =
6832                     textureVk->getBufferViewSerial().viewSerial.getValue();
6833                 infoDesc.imageLayoutOrRange    = 0;
6834                 infoDesc.imageSubresourceRange = 0;
6835                 infoDesc.samplerOrBufferSerial = 0;
6836 
6837                 mHandles[infoIndex].bufferView = view->getHandle();
6838             }
6839         }
6840         else
6841         {
6842             for (uint32_t arrayElement = 0; arrayElement < arraySize; ++arrayElement)
6843             {
6844                 GLuint imageUnit             = imageBinding.boundImageUnits[arrayElement];
6845                 const gl::ImageUnit &binding = imageUnits[imageUnit];
6846                 TextureVk *textureVk         = activeImages[imageUnit];
6847 
6848                 vk::ImageHelper *image         = &textureVk->getImage();
6849                 const vk::ImageView *imageView = nullptr;
6850 
6851                 vk::ImageOrBufferViewSubresourceSerial serial =
6852                     textureVk->getStorageImageViewSerial(binding);
6853 
6854                 ANGLE_TRY(textureVk->getStorageImageView(context, binding, &imageView));
6855 
6856                 uint32_t infoIndex = writeDescriptorDescs[info.binding].descriptorInfoIndex +
6857                                      arrayElement + imageUniform.getOuterArrayOffset();
6858 
6859                 // Note: binding.access is unused because it is implied by the shader.
6860 
6861                 DescriptorInfoDesc &infoDesc = mDesc.getInfoDesc(infoIndex);
6862                 SetBitField(infoDesc.imageLayoutOrRange, image->getCurrentLayout());
6863                 memcpy(&infoDesc.imageSubresourceRange, &serial.subresource, sizeof(uint32_t));
6864                 infoDesc.imageViewSerialOrOffset = serial.viewSerial.getValue();
6865                 infoDesc.samplerOrBufferSerial   = 0;
6866 
6867                 mHandles[infoIndex].imageView = imageView->getHandle();
6868             }
6869         }
6870     }
6871 
6872     return angle::Result::Continue;
6873 }
6874 
updateInputAttachments(vk::Context * context,const gl::ProgramExecutable & executable,const ShaderInterfaceVariableInfoMap & variableInfoMap,FramebufferVk * framebufferVk,const WriteDescriptorDescs & writeDescriptorDescs)6875 angle::Result DescriptorSetDescBuilder::updateInputAttachments(
6876     vk::Context *context,
6877     const gl::ProgramExecutable &executable,
6878     const ShaderInterfaceVariableInfoMap &variableInfoMap,
6879     FramebufferVk *framebufferVk,
6880     const WriteDescriptorDescs &writeDescriptorDescs)
6881 {
6882     // Note: Depth/stencil input attachments are only supported in ANGLE when using
6883     // VK_KHR_dynamic_rendering_local_read, so the layout is chosen to be the one specifically made
6884     // for that extension.
6885     if (executable.usesDepthFramebufferFetch() || executable.usesStencilFramebufferFetch())
6886     {
6887         RenderTargetVk *renderTargetVk = framebufferVk->getDepthStencilRenderTarget();
6888         ASSERT(context->getFeatures().preferDynamicRendering.enabled);
6889 
6890         if (renderTargetVk != nullptr)
6891         {
6892             const ImageOrBufferViewSubresourceSerial serial =
6893                 renderTargetVk->getDrawSubresourceSerial();
6894             const VkImageAspectFlags aspects =
6895                 renderTargetVk->getImageForRenderPass().getAspectFlags();
6896 
6897             if (executable.usesDepthFramebufferFetch() &&
6898                 (aspects & VK_IMAGE_ASPECT_DEPTH_BIT) != 0)
6899             {
6900                 const vk::ImageView *imageView = nullptr;
6901                 ANGLE_TRY(renderTargetVk->getDepthOrStencilImageView(
6902                     context, VK_IMAGE_ASPECT_DEPTH_BIT, &imageView));
6903 
6904                 const uint32_t depthBinding =
6905                     variableInfoMap
6906                         .getVariableById(gl::ShaderType::Fragment,
6907                                          sh::vk::spirv::kIdDepthInputAttachment)
6908                         .binding;
6909                 updateInputAttachment(context, depthBinding,
6910                                       VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR, imageView, serial,
6911                                       writeDescriptorDescs);
6912             }
6913 
6914             if (executable.usesStencilFramebufferFetch() &&
6915                 (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) != 0)
6916             {
6917                 const vk::ImageView *imageView = nullptr;
6918                 ANGLE_TRY(renderTargetVk->getDepthOrStencilImageView(
6919                     context, VK_IMAGE_ASPECT_STENCIL_BIT, &imageView));
6920 
6921                 const uint32_t stencilBinding =
6922                     variableInfoMap
6923                         .getVariableById(gl::ShaderType::Fragment,
6924                                          sh::vk::spirv::kIdStencilInputAttachment)
6925                         .binding;
6926                 updateInputAttachment(context, stencilBinding,
6927                                       VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR, imageView, serial,
6928                                       writeDescriptorDescs);
6929             }
6930         }
6931     }
6932 
6933     if (!executable.usesColorFramebufferFetch())
6934     {
6935         return angle::Result::Continue;
6936     }
6937 
6938     const uint32_t firstColorInputAttachment =
6939         static_cast<uint32_t>(executable.getFragmentInoutIndices().first());
6940 
6941     const ShaderInterfaceVariableInfo &baseColorInfo = variableInfoMap.getVariableById(
6942         gl::ShaderType::Fragment, sh::vk::spirv::kIdInputAttachment0 + firstColorInputAttachment);
6943 
6944     const uint32_t baseColorBinding = baseColorInfo.binding - firstColorInputAttachment;
6945 
6946     for (size_t colorIndex : framebufferVk->getState().getColorAttachmentsMask())
6947     {
6948         uint32_t binding               = baseColorBinding + static_cast<uint32_t>(colorIndex);
6949         RenderTargetVk *renderTargetVk = framebufferVk->getColorDrawRenderTarget(colorIndex);
6950 
6951         const vk::ImageView *imageView = nullptr;
6952         ANGLE_TRY(renderTargetVk->getImageView(context, &imageView));
6953         const ImageOrBufferViewSubresourceSerial serial =
6954             renderTargetVk->getDrawSubresourceSerial();
6955 
6956         // We just need any layout that represents GENERAL for render pass objects.  With dynamic
6957         // rendering, there's a specific layout.
6958         updateInputAttachment(context, binding,
6959                               context->getFeatures().preferDynamicRendering.enabled
6960                                   ? VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR
6961                                   : VK_IMAGE_LAYOUT_GENERAL,
6962                               imageView, serial, writeDescriptorDescs);
6963     }
6964 
6965     return angle::Result::Continue;
6966 }
6967 
updateInputAttachment(Context * context,uint32_t binding,VkImageLayout layout,const vk::ImageView * imageView,ImageOrBufferViewSubresourceSerial serial,const WriteDescriptorDescs & writeDescriptorDescs)6968 void DescriptorSetDescBuilder::updateInputAttachment(
6969     Context *context,
6970     uint32_t binding,
6971     VkImageLayout layout,
6972     const vk::ImageView *imageView,
6973     ImageOrBufferViewSubresourceSerial serial,
6974     const WriteDescriptorDescs &writeDescriptorDescs)
6975 {
6976     uint32_t infoIndex = writeDescriptorDescs[binding].descriptorInfoIndex;
6977 
6978     DescriptorInfoDesc &infoDesc = mDesc.getInfoDesc(infoIndex);
6979 
6980     // The serial is not totally precise.
6981     SetBitField(infoDesc.imageLayoutOrRange, layout);
6982     infoDesc.imageViewSerialOrOffset = serial.viewSerial.getValue();
6983     memcpy(&infoDesc.imageSubresourceRange, &serial.subresource, sizeof(uint32_t));
6984     infoDesc.samplerOrBufferSerial = 0;
6985 
6986     mHandles[infoIndex].imageView = imageView->getHandle();
6987 }
6988 
updateDescriptorSet(Renderer * renderer,const WriteDescriptorDescs & writeDescriptorDescs,UpdateDescriptorSetsBuilder * updateBuilder,VkDescriptorSet descriptorSet) const6989 void DescriptorSetDescBuilder::updateDescriptorSet(Renderer *renderer,
6990                                                    const WriteDescriptorDescs &writeDescriptorDescs,
6991                                                    UpdateDescriptorSetsBuilder *updateBuilder,
6992                                                    VkDescriptorSet descriptorSet) const
6993 {
6994     mDesc.updateDescriptorSet(renderer, writeDescriptorDescs, updateBuilder, mHandles.data(),
6995                               descriptorSet);
6996 }
6997 
6998 // SharedCacheKeyManager implementation.
6999 template <class SharedCacheKeyT>
updateEmptySlotBits()7000 size_t SharedCacheKeyManager<SharedCacheKeyT>::updateEmptySlotBits()
7001 {
7002     ASSERT(mSharedCacheKeys.size() == mEmptySlotBits.size() * kSlotBitCount);
7003     size_t emptySlot = kInvalidSlot;
7004     for (size_t slot = 0; slot < mSharedCacheKeys.size(); ++slot)
7005     {
7006         SharedCacheKeyT &sharedCacheKey = mSharedCacheKeys[slot];
7007         if (!sharedCacheKey->valid())
7008         {
7009             mEmptySlotBits[slot / kSlotBitCount].set(slot % kSlotBitCount);
7010             emptySlot = slot;
7011         }
7012     }
7013     return emptySlot;
7014 }
7015 
7016 template <class SharedCacheKeyT>
addKeyImpl(const SharedCacheKeyT & key)7017 void SharedCacheKeyManager<SharedCacheKeyT>::addKeyImpl(const SharedCacheKeyT &key)
7018 {
7019     // Search for available slots and use that if any
7020     size_t slot = 0;
7021     for (SlotBitMask &emptyBits : mEmptySlotBits)
7022     {
7023         if (emptyBits.any())
7024         {
7025             slot += emptyBits.first();
7026             SharedCacheKeyT &sharedCacheKey = mSharedCacheKeys[slot];
7027             ASSERT(!sharedCacheKey->valid());
7028             sharedCacheKey = key;
7029             emptyBits.reset(slot % kSlotBitCount);
7030             return;
7031         }
7032         slot += kSlotBitCount;
7033     }
7034 
7035     // Some cached entries may have been released. Try to update and use any available slot if any.
7036     slot = updateEmptySlotBits();
7037     if (slot != kInvalidSlot)
7038     {
7039         SharedCacheKeyT &sharedCacheKey = mSharedCacheKeys[slot];
7040         ASSERT(!sharedCacheKey->valid());
7041         sharedCacheKey         = key;
7042         SlotBitMask &emptyBits = mEmptySlotBits[slot / kSlotBitCount];
7043         emptyBits.reset(slot % kSlotBitCount);
7044         return;
7045     }
7046 
7047     // No slot available, expand mSharedCacheKeys
7048     ASSERT(mSharedCacheKeys.size() == mEmptySlotBits.size() * kSlotBitCount);
7049     if (!mEmptySlotBits.empty())
7050     {
7051         // On first insertion, let std::vector allocate a single entry for minimal memory overhead,
7052         // since this is the most common usage case. If that exceeds, reserve a larger chunk to
7053         // avoid storage reallocation for efficiency (enough storage enough for 512 cache entries).
7054         mEmptySlotBits.reserve(8);
7055     }
7056     mEmptySlotBits.emplace_back(0xFFFFFFFE);
7057     mSharedCacheKeys.emplace_back(key);
7058     while (mSharedCacheKeys.size() < mEmptySlotBits.size() * kSlotBitCount)
7059     {
7060         mSharedCacheKeys.emplace_back();
7061         SharedCacheKeyT &sharedCacheKey = mSharedCacheKeys.back();
7062         // Insert an empty cache key so that sharedCacheKey will not be null.
7063         MakeInvalidCachedObject(&sharedCacheKey);
7064         ASSERT(!sharedCacheKey->valid());
7065     }
7066 }
7067 
7068 template <class SharedCacheKeyT>
releaseKeys(ContextVk * contextVk)7069 void SharedCacheKeyManager<SharedCacheKeyT>::releaseKeys(ContextVk *contextVk)
7070 {
7071     ASSERT(mSharedCacheKeys.size() == mEmptySlotBits.size() * kSlotBitCount);
7072     for (SharedCacheKeyT &sharedCacheKey : mSharedCacheKeys)
7073     {
7074         if (sharedCacheKey->valid())
7075         {
7076             // Immediate destroy the cached object and the key itself when first releaseRef call is
7077             // made
7078             sharedCacheKey->releaseCachedObject(contextVk);
7079         }
7080     }
7081     mSharedCacheKeys.clear();
7082     mEmptySlotBits.clear();
7083 }
7084 
7085 template <class SharedCacheKeyT>
releaseKeys(Renderer * renderer)7086 void SharedCacheKeyManager<SharedCacheKeyT>::releaseKeys(Renderer *renderer)
7087 {
7088     ASSERT(mSharedCacheKeys.size() == mEmptySlotBits.size() * kSlotBitCount);
7089     for (SharedCacheKeyT &sharedCacheKey : mSharedCacheKeys)
7090     {
7091         if (sharedCacheKey->valid())
7092         {
7093             // Immediate destroy the cached object and the key itself when first releaseKeys call is
7094             // made
7095             sharedCacheKey->releaseCachedObject(renderer);
7096         }
7097     }
7098     mSharedCacheKeys.clear();
7099     mEmptySlotBits.clear();
7100 }
7101 
7102 template <class SharedCacheKeyT>
destroyKeys(Renderer * renderer)7103 void SharedCacheKeyManager<SharedCacheKeyT>::destroyKeys(Renderer *renderer)
7104 {
7105     ASSERT(mSharedCacheKeys.size() == mEmptySlotBits.size() * kSlotBitCount);
7106     for (SharedCacheKeyT &sharedCacheKey : mSharedCacheKeys)
7107     {
7108         // destroy the cache key
7109         if (sharedCacheKey->valid())
7110         {
7111             // Immediate destroy the cached object and the key
7112             sharedCacheKey->destroyCachedObject(renderer);
7113         }
7114     }
7115     mSharedCacheKeys.clear();
7116     mEmptySlotBits.clear();
7117 }
7118 
7119 template <class SharedCacheKeyT>
clear()7120 void SharedCacheKeyManager<SharedCacheKeyT>::clear()
7121 {
7122     // Caller must have already freed all caches
7123     assertAllEntriesDestroyed();
7124     mSharedCacheKeys.clear();
7125     mEmptySlotBits.clear();
7126 }
7127 
7128 template <class SharedCacheKeyT>
containsKeyWithOwnerEqual(const SharedCacheKeyT & key) const7129 bool SharedCacheKeyManager<SharedCacheKeyT>::containsKeyWithOwnerEqual(
7130     const SharedCacheKeyT &key) const
7131 {
7132     for (const SharedCacheKeyT &sharedCacheKey : mSharedCacheKeys)
7133     {
7134         if (key.owner_equal(sharedCacheKey))
7135         {
7136             return true;
7137         }
7138     }
7139     return false;
7140 }
7141 
7142 template <class SharedCacheKeyT>
assertAllEntriesDestroyed() const7143 void SharedCacheKeyManager<SharedCacheKeyT>::assertAllEntriesDestroyed() const
7144 {
7145     // Caller must have already freed all caches
7146     for (const SharedCacheKeyT &sharedCacheKey : mSharedCacheKeys)
7147     {
7148         ASSERT(!sharedCacheKey->valid());
7149     }
7150 }
7151 
7152 template <class SharedCacheKeyT>
allValidEntriesAreCached(ContextVk * contextVk) const7153 bool SharedCacheKeyManager<SharedCacheKeyT>::allValidEntriesAreCached(ContextVk *contextVk) const
7154 {
7155     for (const SharedCacheKeyT &sharedCacheKey : mSharedCacheKeys)
7156     {
7157         if (sharedCacheKey->valid() && !sharedCacheKey->hasValidCachedObject(contextVk))
7158         {
7159             return false;
7160         }
7161     }
7162     return true;
7163 }
7164 
7165 // Explict instantiate for FramebufferCacheManager
7166 template class SharedCacheKeyManager<SharedFramebufferCacheKey>;
7167 template <>
addKey(const SharedFramebufferCacheKey & key)7168 void SharedCacheKeyManager<SharedFramebufferCacheKey>::addKey(const SharedFramebufferCacheKey &key)
7169 {
7170     addKeyImpl(key);
7171 }
7172 
7173 // Explict instantiate for DescriptorSetCacheManager
7174 template class SharedCacheKeyManager<SharedDescriptorSetCacheKey>;
7175 template <>
addKey(const SharedDescriptorSetCacheKey & key)7176 void SharedCacheKeyManager<SharedDescriptorSetCacheKey>::addKey(
7177     const SharedDescriptorSetCacheKey &key)
7178 {
7179     // There are cases that same texture or buffer are bound in multiple binding point. When we have
7180     // a cache miss, we end up looping binding point and calling addKey which may end up adding same
7181     // key multiple times. This is a quick way to avoid that.
7182     if (mLastAddedSharedCacheKey.owner_equal(key))
7183     {
7184         return;
7185     }
7186 
7187     // In case of the texture or buffer is part of many descriptorSets, lets not track it any more
7188     // to alleviate the overhead associated with this. We will rely on eviction to free the
7189     // descriptorSets when needed.
7190     static constexpr size_t kMaxEmptySlots            = 4;
7191     static constexpr size_t kMaxSharedCacheKeyTracked = kSlotBitCount * kMaxEmptySlots;
7192     if (mSharedCacheKeys.size() >= kMaxSharedCacheKeyTracked)
7193     {
7194         return;
7195     }
7196 
7197     mLastAddedSharedCacheKey = key;
7198     ASSERT(!containsKeyWithOwnerEqual(key));
7199 
7200     addKeyImpl(key);
7201 }
7202 
7203 // PipelineCacheAccess implementation.
getLock()7204 std::unique_lock<angle::SimpleMutex> PipelineCacheAccess::getLock()
7205 {
7206     if (mMutex == nullptr)
7207     {
7208         return std::unique_lock<angle::SimpleMutex>();
7209     }
7210 
7211     return std::unique_lock<angle::SimpleMutex>(*mMutex);
7212 }
7213 
createGraphicsPipeline(vk::ErrorContext * context,const VkGraphicsPipelineCreateInfo & createInfo,vk::Pipeline * pipelineOut)7214 VkResult PipelineCacheAccess::createGraphicsPipeline(vk::ErrorContext *context,
7215                                                      const VkGraphicsPipelineCreateInfo &createInfo,
7216                                                      vk::Pipeline *pipelineOut)
7217 {
7218     std::unique_lock<angle::SimpleMutex> lock = getLock();
7219 
7220     return pipelineOut->initGraphics(context->getDevice(), createInfo, *mPipelineCache);
7221 }
7222 
createComputePipeline(vk::ErrorContext * context,const VkComputePipelineCreateInfo & createInfo,vk::Pipeline * pipelineOut)7223 VkResult PipelineCacheAccess::createComputePipeline(vk::ErrorContext *context,
7224                                                     const VkComputePipelineCreateInfo &createInfo,
7225                                                     vk::Pipeline *pipelineOut)
7226 {
7227     std::unique_lock<angle::SimpleMutex> lock = getLock();
7228 
7229     return pipelineOut->initCompute(context->getDevice(), createInfo, *mPipelineCache);
7230 }
7231 
getCacheData(vk::ErrorContext * context,size_t * cacheSize,void * cacheData)7232 VkResult PipelineCacheAccess::getCacheData(vk::ErrorContext *context,
7233                                            size_t *cacheSize,
7234                                            void *cacheData)
7235 {
7236     std::unique_lock<angle::SimpleMutex> lock = getLock();
7237     return mPipelineCache->getCacheData(context->getDevice(), cacheSize, cacheData);
7238 }
7239 
merge(Renderer * renderer,const vk::PipelineCache & pipelineCache)7240 void PipelineCacheAccess::merge(Renderer *renderer, const vk::PipelineCache &pipelineCache)
7241 {
7242     ASSERT(isThreadSafe());
7243 
7244     std::unique_lock<angle::SimpleMutex> lock = getLock();
7245 
7246     mPipelineCache->merge(renderer->getDevice(), 1, pipelineCache.ptr());
7247 }
7248 }  // namespace vk
7249 
7250 // UpdateDescriptorSetsBuilder implementation.
UpdateDescriptorSetsBuilder()7251 UpdateDescriptorSetsBuilder::UpdateDescriptorSetsBuilder()
7252 {
7253     // Reserve reasonable amount of spaces so that for majority of apps we don't need to grow at all
7254     constexpr size_t kDescriptorBufferInfosInitialSize = 16;
7255     constexpr size_t kDescriptorImageInfosInitialSize  = 16;
7256     constexpr size_t kDescriptorBufferViewsInitialSize = 1;
7257     constexpr size_t kDescriptorWriteInfosInitialSize =
7258         kDescriptorBufferInfosInitialSize + kDescriptorImageInfosInitialSize;
7259 
7260     mDescriptorBufferInfos.init(kDescriptorBufferInfosInitialSize);
7261     mDescriptorImageInfos.init(kDescriptorImageInfosInitialSize);
7262     mBufferViews.init(kDescriptorBufferViewsInitialSize);
7263     mWriteDescriptorSets.init(kDescriptorWriteInfosInitialSize);
7264 }
7265 
7266 UpdateDescriptorSetsBuilder::~UpdateDescriptorSetsBuilder() = default;
7267 
7268 template <typename T>
allocate(uint32_t count)7269 T *UpdateDescriptorSetsBuilder::DescriptorInfoAllocator<T>::allocate(uint32_t count)
7270 {
7271     size_t oldSize = mCurrentVector->size();
7272     size_t newSize = oldSize + count;
7273     if (newSize <= mCurrentVector->capacity())
7274     {
7275         (*mCurrentVector).resize(newSize);
7276         mTotalSize += count;
7277         return &(*mCurrentVector)[oldSize];
7278     }
7279 
7280     ++mCurrentVector;
7281     // clear() always ensures we have a single element left.
7282     ASSERT(mCurrentVector == mDescriptorInfos.end());
7283 
7284     // We have reached capacity, grow the storage
7285     mVectorCapacity = std::max(count, mVectorCapacity);
7286     mDescriptorInfos.emplace_back();
7287     mDescriptorInfos.back().reserve(mVectorCapacity);
7288     mCurrentVector = mDescriptorInfos.end() - 1;
7289 
7290     mCurrentVector->resize(count);
7291     mTotalSize += count;
7292 
7293     return &mCurrentVector->front();
7294 }
7295 
updateDescriptorSets(VkDevice device) const7296 uint32_t UpdateDescriptorSetsBuilder::WriteDescriptorSetAllocator::updateDescriptorSets(
7297     VkDevice device) const
7298 {
7299     for (const std::vector<VkWriteDescriptorSet> &vector : mDescriptorInfos)
7300     {
7301         if (!vector.empty())
7302         {
7303             vkUpdateDescriptorSets(device, static_cast<uint32_t>(vector.size()), vector.data(), 0,
7304                                    nullptr);
7305         }
7306     }
7307     return mTotalSize;
7308 }
7309 
flushDescriptorSetUpdates(VkDevice device)7310 uint32_t UpdateDescriptorSetsBuilder::flushDescriptorSetUpdates(VkDevice device)
7311 {
7312     if (mWriteDescriptorSets.empty())
7313     {
7314         ASSERT(mDescriptorBufferInfos.empty());
7315         ASSERT(mDescriptorImageInfos.empty());
7316         return 0;
7317     }
7318 
7319     uint32_t totalSize = mWriteDescriptorSets.updateDescriptorSets(device);
7320 
7321     mWriteDescriptorSets.clear();
7322     mDescriptorBufferInfos.clear();
7323     mDescriptorImageInfos.clear();
7324     mBufferViews.clear();
7325 
7326     return totalSize;
7327 }
7328 
7329 // FramebufferCache implementation.
destroy(vk::Renderer * renderer)7330 void FramebufferCache::destroy(vk::Renderer *renderer)
7331 {
7332     renderer->accumulateCacheStats(VulkanCacheType::Framebuffer, mCacheStats);
7333     for (auto &entry : mPayload)
7334     {
7335         vk::FramebufferHelper &tmpFB = entry.second;
7336         tmpFB.destroy(renderer);
7337     }
7338     mPayload.clear();
7339 }
7340 
get(ContextVk * contextVk,const vk::FramebufferDesc & desc,vk::Framebuffer & framebuffer)7341 bool FramebufferCache::get(ContextVk *contextVk,
7342                            const vk::FramebufferDesc &desc,
7343                            vk::Framebuffer &framebuffer)
7344 {
7345     ASSERT(!contextVk->getFeatures().supportsImagelessFramebuffer.enabled);
7346 
7347     auto iter = mPayload.find(desc);
7348     if (iter != mPayload.end())
7349     {
7350         framebuffer.setHandle(iter->second.getFramebuffer().getHandle());
7351         mCacheStats.hit();
7352         return true;
7353     }
7354 
7355     mCacheStats.miss();
7356     return false;
7357 }
7358 
insert(ContextVk * contextVk,const vk::FramebufferDesc & desc,vk::FramebufferHelper && framebufferHelper)7359 void FramebufferCache::insert(ContextVk *contextVk,
7360                               const vk::FramebufferDesc &desc,
7361                               vk::FramebufferHelper &&framebufferHelper)
7362 {
7363     ASSERT(!contextVk->getFeatures().supportsImagelessFramebuffer.enabled);
7364 
7365     mPayload.emplace(desc, std::move(framebufferHelper));
7366 }
7367 
erase(ContextVk * contextVk,const vk::FramebufferDesc & desc)7368 void FramebufferCache::erase(ContextVk *contextVk, const vk::FramebufferDesc &desc)
7369 {
7370     ASSERT(!contextVk->getFeatures().supportsImagelessFramebuffer.enabled);
7371 
7372     auto iter = mPayload.find(desc);
7373     if (iter != mPayload.end())
7374     {
7375         vk::FramebufferHelper &tmpFB = iter->second;
7376         tmpFB.release(contextVk);
7377         mPayload.erase(desc);
7378     }
7379 }
7380 
7381 // RenderPassCache implementation.
7382 RenderPassCache::RenderPassCache() = default;
7383 
~RenderPassCache()7384 RenderPassCache::~RenderPassCache()
7385 {
7386     ASSERT(mPayload.empty());
7387 }
7388 
destroy(ContextVk * contextVk)7389 void RenderPassCache::destroy(ContextVk *contextVk)
7390 {
7391     vk::Renderer *renderer = contextVk->getRenderer();
7392 
7393     renderer->accumulateCacheStats(VulkanCacheType::CompatibleRenderPass,
7394                                    mCompatibleRenderPassCacheStats);
7395     renderer->accumulateCacheStats(VulkanCacheType::RenderPassWithOps,
7396                                    mRenderPassWithOpsCacheStats);
7397 
7398     VkDevice device = renderer->getDevice();
7399 
7400     // Make sure there are no jobs referencing the render pass cache.
7401     contextVk->getShareGroup()->waitForCurrentMonolithicPipelineCreationTask();
7402 
7403     for (auto &outerIt : mPayload)
7404     {
7405         for (auto &innerIt : outerIt.second)
7406         {
7407             innerIt.second.destroy(device);
7408         }
7409     }
7410     mPayload.clear();
7411 }
7412 
clear(ContextVk * contextVk)7413 void RenderPassCache::clear(ContextVk *contextVk)
7414 {
7415     // Make sure there are no jobs referencing the render pass cache.
7416     contextVk->getShareGroup()->waitForCurrentMonolithicPipelineCreationTask();
7417 
7418     for (auto &outerIt : mPayload)
7419     {
7420         for (auto &innerIt : outerIt.second)
7421         {
7422             innerIt.second.release(contextVk);
7423         }
7424     }
7425     mPayload.clear();
7426 }
7427 
7428 // static
InitializeOpsForCompatibleRenderPass(const vk::RenderPassDesc & desc,vk::AttachmentOpsArray * opsOut)7429 void RenderPassCache::InitializeOpsForCompatibleRenderPass(const vk::RenderPassDesc &desc,
7430                                                            vk::AttachmentOpsArray *opsOut)
7431 {
7432     // This API is only used by getCompatibleRenderPass() to create a compatible render pass.  The
7433     // following does not participate in render pass compatibility, so could take any value:
7434     //
7435     // - Load and store ops
7436     // - Attachment layouts
7437     // - Existance of resolve attachment (if single subpass)
7438     //
7439     // The values chosen here are arbitrary.
7440 
7441     vk::PackedAttachmentIndex colorIndexVk(0);
7442     for (uint32_t colorIndexGL = 0; colorIndexGL < desc.colorAttachmentRange(); ++colorIndexGL)
7443     {
7444         if (!desc.isColorAttachmentEnabled(colorIndexGL))
7445         {
7446             continue;
7447         }
7448 
7449         const vk::ImageLayout imageLayout = vk::ImageLayout::ColorWrite;
7450         opsOut->initWithLoadStore(colorIndexVk, imageLayout, imageLayout);
7451         ++colorIndexVk;
7452     }
7453 
7454     if (desc.hasDepthStencilAttachment())
7455     {
7456         const vk::ImageLayout imageLayout = vk::ImageLayout::DepthWriteStencilWrite;
7457         opsOut->initWithLoadStore(colorIndexVk, imageLayout, imageLayout);
7458     }
7459 }
7460 
addCompatibleRenderPass(ContextVk * contextVk,const vk::RenderPassDesc & desc,const vk::RenderPass ** renderPassOut)7461 angle::Result RenderPassCache::addCompatibleRenderPass(ContextVk *contextVk,
7462                                                        const vk::RenderPassDesc &desc,
7463                                                        const vk::RenderPass **renderPassOut)
7464 {
7465     vk::AttachmentOpsArray ops;
7466     InitializeOpsForCompatibleRenderPass(desc, &ops);
7467 
7468     return getRenderPassWithOpsImpl(contextVk, desc, ops, false, renderPassOut);
7469 }
7470 
getRenderPassWithOps(ContextVk * contextVk,const vk::RenderPassDesc & desc,const vk::AttachmentOpsArray & attachmentOps,const vk::RenderPass ** renderPassOut)7471 angle::Result RenderPassCache::getRenderPassWithOps(ContextVk *contextVk,
7472                                                     const vk::RenderPassDesc &desc,
7473                                                     const vk::AttachmentOpsArray &attachmentOps,
7474                                                     const vk::RenderPass **renderPassOut)
7475 {
7476     return getRenderPassWithOpsImpl(contextVk, desc, attachmentOps, true, renderPassOut);
7477 }
7478 
getRenderPassWithOpsImpl(ContextVk * contextVk,const vk::RenderPassDesc & desc,const vk::AttachmentOpsArray & attachmentOps,bool updatePerfCounters,const vk::RenderPass ** renderPassOut)7479 angle::Result RenderPassCache::getRenderPassWithOpsImpl(ContextVk *contextVk,
7480                                                         const vk::RenderPassDesc &desc,
7481                                                         const vk::AttachmentOpsArray &attachmentOps,
7482                                                         bool updatePerfCounters,
7483                                                         const vk::RenderPass **renderPassOut)
7484 {
7485     ASSERT(!contextVk->getFeatures().preferDynamicRendering.enabled);
7486 
7487     auto outerIt = mPayload.find(desc);
7488     if (outerIt != mPayload.end())
7489     {
7490         InnerCache &innerCache = outerIt->second;
7491 
7492         auto innerIt = innerCache.find(attachmentOps);
7493         if (innerIt != innerCache.end())
7494         {
7495             // TODO(jmadill): Could possibly use an MRU cache here.
7496             vk::GetRenderPassAndUpdateCounters(contextVk, updatePerfCounters, &innerIt->second,
7497                                                renderPassOut);
7498             mRenderPassWithOpsCacheStats.hit();
7499             return angle::Result::Continue;
7500         }
7501     }
7502     else
7503     {
7504         auto emplaceResult = mPayload.emplace(desc, InnerCache());
7505         outerIt            = emplaceResult.first;
7506     }
7507 
7508     mRenderPassWithOpsCacheStats.missAndIncrementSize();
7509     vk::RenderPassHelper newRenderPass;
7510     ANGLE_TRY(MakeRenderPass(contextVk, desc, attachmentOps, &newRenderPass.getRenderPass(),
7511                              &newRenderPass.getPerfCounters()));
7512 
7513     InnerCache &innerCache = outerIt->second;
7514     auto insertPos         = innerCache.emplace(attachmentOps, std::move(newRenderPass));
7515     vk::GetRenderPassAndUpdateCounters(contextVk, updatePerfCounters, &insertPos.first->second,
7516                                        renderPassOut);
7517 
7518     // TODO(jmadill): Trim cache, and pre-populate with the most common RPs on startup.
7519     return angle::Result::Continue;
7520 }
7521 
7522 // static
MakeRenderPass(vk::ErrorContext * context,const vk::RenderPassDesc & desc,const vk::AttachmentOpsArray & ops,vk::RenderPass * renderPass,vk::RenderPassPerfCounters * renderPassCounters)7523 angle::Result RenderPassCache::MakeRenderPass(vk::ErrorContext *context,
7524                                               const vk::RenderPassDesc &desc,
7525                                               const vk::AttachmentOpsArray &ops,
7526                                               vk::RenderPass *renderPass,
7527                                               vk::RenderPassPerfCounters *renderPassCounters)
7528 {
7529     ASSERT(!context->getFeatures().preferDynamicRendering.enabled);
7530 
7531     vk::Renderer *renderer                             = context->getRenderer();
7532     constexpr VkAttachmentReference2 kUnusedAttachment = {VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,
7533                                                           nullptr, VK_ATTACHMENT_UNUSED,
7534                                                           VK_IMAGE_LAYOUT_UNDEFINED, 0};
7535 
7536     ASSERT(!desc.hasDepthStencilFramebufferFetch());
7537     const bool needInputAttachments = desc.hasColorFramebufferFetch();
7538     const bool isRenderToTextureThroughExtension =
7539         desc.isRenderToTexture() &&
7540         renderer->getFeatures().supportsMultisampledRenderToSingleSampled.enabled;
7541     const bool isRenderToTextureThroughEmulation =
7542         desc.isRenderToTexture() && !isRenderToTextureThroughExtension;
7543 
7544     const uint8_t descSamples            = desc.samples();
7545     const uint8_t attachmentSamples      = isRenderToTextureThroughExtension ? 1 : descSamples;
7546     const uint8_t renderToTextureSamples = isRenderToTextureThroughExtension ? descSamples : 1;
7547 
7548     // Unpack the packed and split representation into the format required by Vulkan.
7549     gl::DrawBuffersVector<VkAttachmentReference2> colorAttachmentRefs;
7550     gl::DrawBuffersVector<VkAttachmentReference2> colorResolveAttachmentRefs;
7551     VkAttachmentReference2 depthStencilAttachmentRef        = kUnusedAttachment;
7552     VkAttachmentReference2 depthStencilResolveAttachmentRef = kUnusedAttachment;
7553     VkAttachmentReference2 fragmentShadingRateAttachmentRef = kUnusedAttachment;
7554 
7555     // The list of attachments includes all non-resolve and resolve attachments.
7556     vk::FramebufferAttachmentArray<VkAttachmentDescription2> attachmentDescs;
7557 
7558     // Track invalidated attachments so their resolve attachments can be invalidated as well.
7559     // Resolve attachments can be removed in that case if the render pass has only one subpass
7560     // (which is the case if there are no unresolve attachments).
7561     gl::DrawBufferMask isMSRTTEmulationColorInvalidated;
7562     bool isMSRTTEmulationDepthInvalidated   = false;
7563     bool isMSRTTEmulationStencilInvalidated = false;
7564     const bool hasUnresolveAttachments =
7565         desc.getColorUnresolveAttachmentMask().any() || desc.hasDepthStencilUnresolveAttachment();
7566     const bool canRemoveResolveAttachments =
7567         isRenderToTextureThroughEmulation && !hasUnresolveAttachments;
7568 
7569 #if defined(ANGLE_PLATFORM_ANDROID)
7570     // if yuv, we're going to chain this on to some VkAttachmentDescription2
7571     VkExternalFormatANDROID externalFormat = {VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID, nullptr,
7572                                               0};
7573 #endif
7574 
7575     gl::DrawBuffersArray<vk::ImageLayout> colorResolveImageLayout = {};
7576 
7577     // Pack color attachments
7578     vk::PackedAttachmentIndex attachmentCount(0);
7579     for (uint32_t colorIndexGL = 0; colorIndexGL < desc.colorAttachmentRange(); ++colorIndexGL)
7580     {
7581         // Vulkan says:
7582         //
7583         // > Each element of the pColorAttachments array corresponds to an output location in the
7584         // > shader, i.e. if the shader declares an output variable decorated with a Location value
7585         // > of X, then it uses the attachment provided in pColorAttachments[X].
7586         //
7587         // This means that colorAttachmentRefs is indexed by colorIndexGL.  Where the color
7588         // attachment is disabled, a reference with VK_ATTACHMENT_UNUSED is given.
7589 
7590         if (!desc.isColorAttachmentEnabled(colorIndexGL))
7591         {
7592             colorAttachmentRefs.push_back(kUnusedAttachment);
7593             continue;
7594         }
7595 
7596         angle::FormatID attachmentFormatID = desc[colorIndexGL];
7597         ASSERT(attachmentFormatID != angle::FormatID::NONE);
7598 
7599         bool isYUVExternalFormat = vk::IsYUVExternalFormat(attachmentFormatID);
7600 
7601         // If nullColorAttachmentWithExternalFormatResolve is VK_TRUE, pack YUV resolve first as if
7602         // it is the color attachment.
7603         if (isYUVExternalFormat && renderer->nullColorAttachmentWithExternalFormatResolve())
7604         {
7605             colorAttachmentRefs.push_back(kUnusedAttachment);
7606             // temporary workaround for ARM driver assertion. Will remove once driver fix lands
7607             colorAttachmentRefs.back().layout     = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
7608             colorAttachmentRefs.back().aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
7609 
7610             VkAttachmentReference2 colorRef = {};
7611             colorRef.sType                  = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2;
7612             colorRef.attachment             = attachmentCount.get();
7613             colorRef.layout                 = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
7614             colorRef.aspectMask             = VK_IMAGE_ASPECT_COLOR_BIT;
7615 
7616             colorResolveAttachmentRefs.push_back(colorRef);
7617             vk::UnpackAttachmentDesc(renderer, &attachmentDescs[attachmentCount.get()],
7618                                      attachmentFormatID, attachmentSamples, ops[attachmentCount]);
7619 
7620 #if defined(ANGLE_PLATFORM_ANDROID)
7621             // For rendering to YUV, chain on the external format info to the resolve
7622             // attachment
7623             const vk::ExternalYuvFormatInfo &externalFormatInfo =
7624                 renderer->getExternalFormatTable()->getExternalFormatInfo(attachmentFormatID);
7625             externalFormat.externalFormat        = externalFormatInfo.externalFormat;
7626             VkAttachmentDescription2 &attachment = attachmentDescs[attachmentCount.get()];
7627             attachment.pNext                     = &externalFormat;
7628             ASSERT(attachment.format == VK_FORMAT_UNDEFINED);
7629 #endif
7630             ++attachmentCount;
7631             continue;
7632         }
7633 
7634         ASSERT(static_cast<vk::ImageLayout>(ops[attachmentCount].initialLayout) !=
7635                    vk::ImageLayout::SharedPresent ||
7636                static_cast<vk::ImageLayout>(ops[attachmentCount].finalLayout) ==
7637                    vk::ImageLayout::SharedPresent);
7638 
7639         VkAttachmentReference2 colorRef = {};
7640         colorRef.sType                  = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2;
7641         colorRef.attachment             = attachmentCount.get();
7642         colorRef.layout                 = needInputAttachments
7643                                               ? VK_IMAGE_LAYOUT_GENERAL
7644                                               : vk::ConvertImageLayoutToVkImageLayout(static_cast<vk::ImageLayout>(
7645                                     ops[attachmentCount].initialLayout));
7646         colorRef.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
7647         colorAttachmentRefs.push_back(colorRef);
7648 
7649         vk::UnpackAttachmentDesc(renderer, &attachmentDescs[attachmentCount.get()],
7650                                  attachmentFormatID, attachmentSamples, ops[attachmentCount]);
7651         colorResolveImageLayout[colorIndexGL] =
7652             static_cast<vk::ImageLayout>(ops[attachmentCount].finalResolveLayout);
7653 
7654         if (isYUVExternalFormat)
7655         {
7656             const vk::ExternalYuvFormatInfo &externalFormatInfo =
7657                 renderer->getExternalFormatTable()->getExternalFormatInfo(attachmentFormatID);
7658             attachmentDescs[attachmentCount.get()].format =
7659                 externalFormatInfo.colorAttachmentFormat;
7660         }
7661         else
7662         {
7663             attachmentDescs[attachmentCount.get()].format =
7664                 vk::GetVkFormatFromFormatID(renderer, attachmentFormatID);
7665         }
7666         ASSERT(attachmentDescs[attachmentCount.get()].format != VK_FORMAT_UNDEFINED);
7667 
7668         // When multisampled-render-to-texture is used, invalidating an attachment invalidates both
7669         // the multisampled and the resolve attachments.  Otherwise, the resolve attachment is
7670         // independent of the multisampled attachment, and is never invalidated.
7671         // This is also the case for external format resolve
7672         if (isRenderToTextureThroughEmulation)
7673         {
7674             isMSRTTEmulationColorInvalidated.set(colorIndexGL, ops[attachmentCount].isInvalidated);
7675         }
7676 
7677         ++attachmentCount;
7678     }
7679 
7680     // Pack depth/stencil attachment, if any
7681     if (desc.hasDepthStencilAttachment())
7682     {
7683         uint32_t depthStencilIndexGL = static_cast<uint32_t>(desc.depthStencilAttachmentIndex());
7684 
7685         angle::FormatID attachmentFormatID = desc[depthStencilIndexGL];
7686         ASSERT(attachmentFormatID != angle::FormatID::NONE);
7687 
7688         depthStencilAttachmentRef.sType      = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2;
7689         depthStencilAttachmentRef.attachment = attachmentCount.get();
7690         depthStencilAttachmentRef.layout     = ConvertImageLayoutToVkImageLayout(
7691             static_cast<vk::ImageLayout>(ops[attachmentCount].initialLayout));
7692         depthStencilAttachmentRef.aspectMask =
7693             VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
7694 
7695         vk::UnpackAttachmentDesc(renderer, &attachmentDescs[attachmentCount.get()],
7696                                  attachmentFormatID, attachmentSamples, ops[attachmentCount]);
7697 
7698         if (isRenderToTextureThroughEmulation)
7699         {
7700             isMSRTTEmulationDepthInvalidated   = ops[attachmentCount].isInvalidated;
7701             isMSRTTEmulationStencilInvalidated = ops[attachmentCount].isStencilInvalidated;
7702         }
7703 
7704         ++attachmentCount;
7705     }
7706 
7707     // Pack fragment shading rate attachment, if any
7708     if (desc.hasFragmentShadingAttachment())
7709     {
7710         vk::UnpackFragmentShadingRateAttachmentDesc(&attachmentDescs[attachmentCount.get()]);
7711 
7712         fragmentShadingRateAttachmentRef.sType      = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2;
7713         fragmentShadingRateAttachmentRef.attachment = attachmentCount.get();
7714         fragmentShadingRateAttachmentRef.layout =
7715             VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;
7716 
7717         ++attachmentCount;
7718     }
7719 
7720     // Pack color resolve attachments
7721     uint32_t nonResolveAttachmentCount = attachmentCount.get();
7722     for (uint32_t colorIndexGL = 0; colorIndexGL < desc.colorAttachmentRange(); ++colorIndexGL)
7723     {
7724         if (!desc.hasColorResolveAttachment(colorIndexGL))
7725         {
7726             colorResolveAttachmentRefs.push_back(kUnusedAttachment);
7727             continue;
7728         }
7729 
7730         ASSERT(desc.isColorAttachmentEnabled(colorIndexGL));
7731 
7732         angle::FormatID attachmentFormatID = desc[colorIndexGL];
7733         bool isYUVExternalFormat           = vk::IsYUVExternalFormat(attachmentFormatID);
7734 
7735         if (isYUVExternalFormat && renderer->nullColorAttachmentWithExternalFormatResolve())
7736         {
7737             // attachmentCount counts the YUV resolve, so decrease nonResolveAttachmentCount here.
7738             --nonResolveAttachmentCount;
7739             continue;
7740         }
7741 
7742         const VkImageLayout finalLayout =
7743             ConvertImageLayoutToVkImageLayout(colorResolveImageLayout[colorIndexGL]);
7744         const VkImageLayout initialLayout = (finalLayout == VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR
7745                                                  ? VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR
7746                                                  : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
7747 
7748         VkAttachmentReference2 colorRef = {};
7749         colorRef.sType                  = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2;
7750         colorRef.attachment             = attachmentCount.get();
7751         colorRef.layout                 = initialLayout;
7752         colorRef.aspectMask             = VK_IMAGE_ASPECT_COLOR_BIT;
7753 
7754         // If color attachment is invalidated, try to remove its resolve attachment altogether.
7755         if (canRemoveResolveAttachments && isMSRTTEmulationColorInvalidated.test(colorIndexGL))
7756         {
7757             colorResolveAttachmentRefs.push_back(kUnusedAttachment);
7758         }
7759         else
7760         {
7761             colorResolveAttachmentRefs.push_back(colorRef);
7762         }
7763 
7764         const bool isInvalidated = isMSRTTEmulationColorInvalidated.test(colorIndexGL);
7765 
7766         vk::UnpackColorResolveAttachmentDesc(
7767             renderer, &attachmentDescs[attachmentCount.get()], attachmentFormatID,
7768             {desc.hasColorUnresolveAttachment(colorIndexGL), isInvalidated, false}, initialLayout,
7769             finalLayout);
7770 
7771 #if defined(ANGLE_PLATFORM_ANDROID)
7772         // For rendering to YUV, chain on the external format info to the resolve attachment
7773         if (isYUVExternalFormat)
7774         {
7775             const vk::ExternalYuvFormatInfo &externalFormatInfo =
7776                 renderer->getExternalFormatTable()->getExternalFormatInfo(attachmentFormatID);
7777             externalFormat.externalFormat        = externalFormatInfo.externalFormat;
7778             VkAttachmentDescription2 &attachment = attachmentDescs[attachmentCount.get()];
7779             attachment.pNext                     = &externalFormat;
7780             ASSERT(attachment.format == VK_FORMAT_UNDEFINED);
7781         }
7782 #endif
7783 
7784         ++attachmentCount;
7785     }
7786 
7787     // Pack depth/stencil resolve attachment, if any
7788     if (desc.hasDepthStencilResolveAttachment())
7789     {
7790         ASSERT(desc.hasDepthStencilAttachment());
7791 
7792         uint32_t depthStencilIndexGL = static_cast<uint32_t>(desc.depthStencilAttachmentIndex());
7793 
7794         angle::FormatID attachmentFormatID = desc[depthStencilIndexGL];
7795         const angle::Format &angleFormat   = angle::Format::Get(attachmentFormatID);
7796 
7797         bool isDepthUnused   = false;
7798         bool isStencilUnused = false;
7799 
7800         // Treat missing aspect as invalidated for the purpose of the resolve attachment.
7801         if (angleFormat.depthBits == 0)
7802         {
7803             isMSRTTEmulationDepthInvalidated = true;
7804         }
7805         else if (!desc.hasDepthResolveAttachment())
7806         {
7807             isDepthUnused = true;
7808         }
7809         if (angleFormat.stencilBits == 0)
7810         {
7811             isMSRTTEmulationStencilInvalidated = true;
7812         }
7813         else if (!desc.hasStencilResolveAttachment())
7814         {
7815             isStencilUnused = true;
7816         }
7817 
7818         depthStencilResolveAttachmentRef.attachment = attachmentCount.get();
7819         depthStencilResolveAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
7820         depthStencilResolveAttachmentRef.aspectMask = 0;
7821 
7822         if (!isMSRTTEmulationDepthInvalidated && !isDepthUnused)
7823         {
7824             depthStencilResolveAttachmentRef.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
7825         }
7826         if (!isMSRTTEmulationStencilInvalidated && !isStencilUnused)
7827         {
7828             depthStencilResolveAttachmentRef.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
7829         }
7830 
7831         vk::UnpackDepthStencilResolveAttachmentDesc(
7832             context, &attachmentDescs[attachmentCount.get()], attachmentFormatID,
7833             {desc.hasDepthUnresolveAttachment(), isMSRTTEmulationDepthInvalidated, isDepthUnused},
7834             {desc.hasStencilUnresolveAttachment(), isMSRTTEmulationStencilInvalidated,
7835              isStencilUnused});
7836 
7837         ++attachmentCount;
7838     }
7839 
7840     vk::SubpassVector<VkSubpassDescription2> subpassDesc;
7841 
7842     // If any attachment needs to be unresolved, create an initial subpass for this purpose.  Note
7843     // that the following arrays are used in initializing a VkSubpassDescription2 in subpassDesc,
7844     // which is in turn used in VkRenderPassCreateInfo below.  That is why they are declared in the
7845     // same scope.
7846     gl::DrawBuffersVector<VkAttachmentReference2> unresolveColorAttachmentRefs;
7847     VkAttachmentReference2 unresolveDepthStencilAttachmentRef = kUnusedAttachment;
7848     vk::FramebufferAttachmentsVector<VkAttachmentReference2> unresolveInputAttachmentRefs;
7849     vk::FramebufferAttachmentsVector<uint32_t> unresolvePreserveAttachmentRefs;
7850     if (hasUnresolveAttachments)
7851     {
7852         subpassDesc.push_back({});
7853         vk::InitializeUnresolveSubpass(
7854             desc, colorAttachmentRefs, colorResolveAttachmentRefs, depthStencilAttachmentRef,
7855             depthStencilResolveAttachmentRef, &unresolveColorAttachmentRefs,
7856             &unresolveDepthStencilAttachmentRef, &unresolveInputAttachmentRefs,
7857             &unresolvePreserveAttachmentRefs, &subpassDesc.back());
7858     }
7859 
7860     subpassDesc.push_back({});
7861     VkSubpassDescription2 *applicationSubpass = &subpassDesc.back();
7862 
7863     applicationSubpass->sType             = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2;
7864     applicationSubpass->pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
7865     applicationSubpass->inputAttachmentCount =
7866         needInputAttachments ? static_cast<uint32_t>(colorAttachmentRefs.size()) : 0;
7867     applicationSubpass->pInputAttachments =
7868         needInputAttachments ? colorAttachmentRefs.data() : nullptr;
7869     applicationSubpass->colorAttachmentCount = static_cast<uint32_t>(colorAttachmentRefs.size());
7870     applicationSubpass->pColorAttachments    = colorAttachmentRefs.data();
7871     applicationSubpass->pResolveAttachments  = attachmentCount.get() > nonResolveAttachmentCount
7872                                                    ? colorResolveAttachmentRefs.data()
7873                                                    : nullptr;
7874     applicationSubpass->pDepthStencilAttachment =
7875         (depthStencilAttachmentRef.attachment != VK_ATTACHMENT_UNUSED ? &depthStencilAttachmentRef
7876                                                                       : nullptr);
7877 
7878     // Specify rasterization order for color on the subpass when available and
7879     // there is framebuffer fetch.  This is required when the corresponding
7880     // flag is set on the pipeline.
7881     if (renderer->getFeatures().supportsRasterizationOrderAttachmentAccess.enabled &&
7882         desc.hasColorFramebufferFetch())
7883     {
7884         for (VkSubpassDescription2 &subpass : subpassDesc)
7885         {
7886             subpass.flags |=
7887                 VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_EXT;
7888         }
7889     }
7890 
7891     if (desc.isLegacyDitherEnabled())
7892     {
7893         ASSERT(renderer->getFeatures().supportsLegacyDithering.enabled);
7894         subpassDesc.back().flags |= VK_SUBPASS_DESCRIPTION_ENABLE_LEGACY_DITHERING_BIT_EXT;
7895     }
7896 
7897     // If depth/stencil is to be resolved, add a VkSubpassDescriptionDepthStencilResolve to the
7898     // pNext chain of the subpass description.
7899     VkSubpassDescriptionDepthStencilResolve depthStencilResolve = {};
7900     VkSubpassDescriptionDepthStencilResolve msrtssResolve       = {};
7901     VkMultisampledRenderToSingleSampledInfoEXT msrtss           = {};
7902     if (desc.hasDepthStencilResolveAttachment())
7903     {
7904         ASSERT(!isRenderToTextureThroughExtension);
7905 
7906         uint32_t depthStencilIndexGL = static_cast<uint32_t>(desc.depthStencilAttachmentIndex());
7907         const angle::Format &angleFormat = angle::Format::Get(desc[depthStencilIndexGL]);
7908 
7909         depthStencilResolve.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE;
7910 
7911         if (!renderer->getFeatures().supportsDepthStencilIndependentResolveNone.enabled)
7912         {
7913             // Assert that depth/stencil is not separately resolved without this feature
7914             ASSERT(desc.hasDepthResolveAttachment() || angleFormat.depthBits == 0);
7915             ASSERT(desc.hasStencilResolveAttachment() || angleFormat.stencilBits == 0);
7916 
7917             depthStencilResolve.depthResolveMode   = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
7918             depthStencilResolve.stencilResolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
7919         }
7920         else
7921         {
7922             depthStencilResolve.depthResolveMode =
7923                 desc.hasDepthResolveAttachment() && !isMSRTTEmulationDepthInvalidated
7924                     ? VK_RESOLVE_MODE_SAMPLE_ZERO_BIT
7925                     : VK_RESOLVE_MODE_NONE;
7926             depthStencilResolve.stencilResolveMode =
7927                 desc.hasStencilResolveAttachment() && !isMSRTTEmulationStencilInvalidated
7928                     ? VK_RESOLVE_MODE_SAMPLE_ZERO_BIT
7929                     : VK_RESOLVE_MODE_NONE;
7930         }
7931 
7932         // If depth/stencil attachment is invalidated or is otherwise not really resolved, don't set
7933         // it as the resolve attachment in the first place.
7934         const bool isResolvingDepth = !isMSRTTEmulationDepthInvalidated &&
7935                                       angleFormat.depthBits > 0 &&
7936                                       depthStencilResolve.depthResolveMode != VK_RESOLVE_MODE_NONE;
7937         const bool isResolvingStencil =
7938             !isMSRTTEmulationStencilInvalidated && angleFormat.stencilBits > 0 &&
7939             depthStencilResolve.stencilResolveMode != VK_RESOLVE_MODE_NONE;
7940 
7941         if (isResolvingDepth || isResolvingStencil)
7942         {
7943             depthStencilResolve.pDepthStencilResolveAttachment = &depthStencilResolveAttachmentRef;
7944             vk::AddToPNextChain(&subpassDesc.back(), &depthStencilResolve);
7945         }
7946     }
7947     else if (isRenderToTextureThroughExtension)
7948     {
7949         ASSERT(subpassDesc.size() == 1);
7950         vk::InitializeMSRTSS(context, renderToTextureSamples, &subpassDesc.back(), &msrtssResolve,
7951                              &msrtss);
7952     }
7953 
7954     VkFragmentShadingRateAttachmentInfoKHR fragmentShadingRateAttachmentInfo = {};
7955     if (desc.hasFragmentShadingAttachment())
7956     {
7957         fragmentShadingRateAttachmentInfo.sType =
7958             VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR;
7959         fragmentShadingRateAttachmentInfo.pFragmentShadingRateAttachment =
7960             &fragmentShadingRateAttachmentRef;
7961         fragmentShadingRateAttachmentInfo.shadingRateAttachmentTexelSize =
7962             renderer->getMaxFragmentShadingRateAttachmentTexelSize();
7963 
7964         vk::AddToPNextChain(&subpassDesc.back(), &fragmentShadingRateAttachmentInfo);
7965     }
7966 
7967     std::vector<VkSubpassDependency2> subpassDependencies;
7968     if (hasUnresolveAttachments)
7969     {
7970         vk::InitializeUnresolveSubpassDependencies(
7971             subpassDesc, desc.getColorUnresolveAttachmentMask().any(),
7972             desc.hasDepthStencilUnresolveAttachment(), &subpassDependencies);
7973     }
7974 
7975     const uint32_t drawSubpassIndex = static_cast<uint32_t>(subpassDesc.size()) - 1;
7976     vk::InitializeDefaultSubpassSelfDependencies(context, desc, drawSubpassIndex,
7977                                                  &subpassDependencies);
7978 
7979     VkRenderPassCreateInfo2 createInfo = {};
7980     createInfo.sType                   = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2;
7981     createInfo.attachmentCount         = attachmentCount.get();
7982     createInfo.pAttachments            = attachmentDescs.data();
7983     createInfo.subpassCount            = static_cast<uint32_t>(subpassDesc.size());
7984     createInfo.pSubpasses              = subpassDesc.data();
7985 
7986     if (!subpassDependencies.empty())
7987     {
7988         createInfo.dependencyCount = static_cast<uint32_t>(subpassDependencies.size());
7989         createInfo.pDependencies   = subpassDependencies.data();
7990     }
7991 
7992     const uint32_t viewMask = angle::BitMask<uint32_t>(desc.viewCount());
7993     if (desc.viewCount() > 0)
7994     {
7995         vk::SetRenderPassViewMask(context, &viewMask, &createInfo, &subpassDesc);
7996     }
7997 
7998     // If VK_KHR_create_renderpass2 is not supported, we must use core Vulkan 1.0.  This is
7999     // increasingly uncommon.  Note that extensions that require chaining information to subpasses
8000     // are automatically not used when this extension is not available.
8001     if (!renderer->getFeatures().supportsRenderpass2.enabled)
8002     {
8003         ANGLE_TRY(vk::CreateRenderPass1(context, createInfo, desc.viewCount(), renderPass));
8004     }
8005     else
8006     {
8007         ANGLE_VK_TRY(context, renderPass->init2(context->getDevice(), createInfo));
8008     }
8009 
8010     if (renderPassCounters != nullptr)
8011     {
8012         // Calculate perf counters associated with this render pass, such as load/store ops,
8013         // unresolve and resolve operations etc.  This information is taken out of the render pass
8014         // create info.  Depth/stencil resolve attachment uses RenderPass2 structures, so it's
8015         // passed in separately.
8016         vk::UpdateRenderPassPerfCounters(desc, createInfo, depthStencilResolve, renderPassCounters);
8017     }
8018 
8019     return angle::Result::Continue;
8020 }
8021 
8022 // ComputePipelineCache implementation
destroy(vk::ErrorContext * context)8023 void ComputePipelineCache::destroy(vk::ErrorContext *context)
8024 {
8025     VkDevice device = context->getDevice();
8026 
8027     for (auto &item : mPayload)
8028     {
8029         vk::PipelineHelper &pipeline = item.second;
8030         ASSERT(context->getRenderer()->hasResourceUseFinished(pipeline.getResourceUse()));
8031         pipeline.destroy(device);
8032     }
8033 
8034     mPayload.clear();
8035 }
8036 
release(vk::ErrorContext * context)8037 void ComputePipelineCache::release(vk::ErrorContext *context)
8038 {
8039     for (auto &item : mPayload)
8040     {
8041         vk::PipelineHelper &pipeline = item.second;
8042         pipeline.release(context);
8043     }
8044 
8045     mPayload.clear();
8046 }
8047 
getOrCreatePipeline(vk::ErrorContext * context,vk::PipelineCacheAccess * pipelineCache,const vk::PipelineLayout & pipelineLayout,rx::vk::ComputePipelineOptions & pipelineOptions,PipelineSource source,vk::PipelineHelper ** pipelineOut,const char * shaderName,VkSpecializationInfo * specializationInfo,const vk::ShaderModuleMap & shaderModuleMap)8048 angle::Result ComputePipelineCache::getOrCreatePipeline(
8049     vk::ErrorContext *context,
8050     vk::PipelineCacheAccess *pipelineCache,
8051     const vk::PipelineLayout &pipelineLayout,
8052     rx::vk::ComputePipelineOptions &pipelineOptions,
8053     PipelineSource source,
8054     vk::PipelineHelper **pipelineOut,
8055     const char *shaderName,
8056     VkSpecializationInfo *specializationInfo,
8057     const vk::ShaderModuleMap &shaderModuleMap)
8058 {
8059     vk::ComputePipelineDesc desc(specializationInfo, pipelineOptions);
8060 
8061     auto iter = mPayload.find(desc);
8062     if (iter != mPayload.end())
8063     {
8064         mCacheStats.hit();
8065         *pipelineOut = &iter->second;
8066         return angle::Result::Continue;
8067     }
8068     return createPipeline(context, pipelineCache, pipelineLayout, pipelineOptions, source,
8069                           shaderName, *shaderModuleMap[gl::ShaderType::Compute].get(),
8070                           specializationInfo, desc, pipelineOut);
8071 }
8072 
createPipeline(vk::ErrorContext * context,vk::PipelineCacheAccess * pipelineCache,const vk::PipelineLayout & pipelineLayout,vk::ComputePipelineOptions & pipelineOptions,PipelineSource source,const char * shaderName,const vk::ShaderModule & shaderModule,VkSpecializationInfo * specializationInfo,const vk::ComputePipelineDesc & desc,vk::PipelineHelper ** pipelineOut)8073 angle::Result ComputePipelineCache::createPipeline(vk::ErrorContext *context,
8074                                                    vk::PipelineCacheAccess *pipelineCache,
8075                                                    const vk::PipelineLayout &pipelineLayout,
8076                                                    vk::ComputePipelineOptions &pipelineOptions,
8077                                                    PipelineSource source,
8078                                                    const char *shaderName,
8079                                                    const vk::ShaderModule &shaderModule,
8080                                                    VkSpecializationInfo *specializationInfo,
8081                                                    const vk::ComputePipelineDesc &desc,
8082                                                    vk::PipelineHelper **pipelineOut)
8083 {
8084     VkPipelineShaderStageCreateInfo shaderStage = {};
8085     VkComputePipelineCreateInfo createInfo      = {};
8086 
8087     shaderStage.sType               = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
8088     shaderStage.flags               = 0;
8089     shaderStage.stage               = VK_SHADER_STAGE_COMPUTE_BIT;
8090     shaderStage.module              = shaderModule.getHandle();
8091     shaderStage.pName               = shaderName ? shaderName : "main";
8092     shaderStage.pSpecializationInfo = specializationInfo;
8093 
8094     createInfo.sType              = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
8095     createInfo.flags              = 0;
8096     createInfo.stage              = shaderStage;
8097     createInfo.layout             = pipelineLayout.getHandle();
8098     createInfo.basePipelineHandle = VK_NULL_HANDLE;
8099     createInfo.basePipelineIndex  = 0;
8100 
8101     VkPipelineRobustnessCreateInfoEXT robustness = {};
8102     robustness.sType = VK_STRUCTURE_TYPE_PIPELINE_ROBUSTNESS_CREATE_INFO_EXT;
8103 
8104     // Enable robustness on the pipeline if needed.  Note that the global robustBufferAccess feature
8105     // must be disabled by default.
8106     if (pipelineOptions.robustness != 0)
8107     {
8108         ASSERT(context->getFeatures().supportsPipelineRobustness.enabled);
8109 
8110         robustness.storageBuffers = VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_EXT;
8111         robustness.uniformBuffers = VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_EXT;
8112         robustness.vertexInputs   = VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DEVICE_DEFAULT_EXT;
8113         robustness.images         = VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DEVICE_DEFAULT_EXT;
8114 
8115         vk::AddToPNextChain(&createInfo, &robustness);
8116     }
8117 
8118     // Restrict pipeline to protected or unprotected command buffers if possible.
8119     if (pipelineOptions.protectedAccess != 0)
8120     {
8121         ASSERT(context->getFeatures().supportsPipelineProtectedAccess.enabled);
8122         createInfo.flags |= VK_PIPELINE_CREATE_PROTECTED_ACCESS_ONLY_BIT_EXT;
8123     }
8124     else if (context->getFeatures().supportsPipelineProtectedAccess.enabled)
8125     {
8126         createInfo.flags |= VK_PIPELINE_CREATE_NO_PROTECTED_ACCESS_BIT_EXT;
8127     }
8128 
8129     VkPipelineCreationFeedback feedback               = {};
8130     VkPipelineCreationFeedback perStageFeedback       = {};
8131     VkPipelineCreationFeedbackCreateInfo feedbackInfo = {};
8132     feedbackInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO;
8133     feedbackInfo.pPipelineCreationFeedback = &feedback;
8134     // Note: see comment in GraphicsPipelineDesc::initializePipeline about why per-stage feedback is
8135     // specified even though unused.
8136     feedbackInfo.pipelineStageCreationFeedbackCount = 1;
8137     feedbackInfo.pPipelineStageCreationFeedbacks    = &perStageFeedback;
8138 
8139     const bool supportsFeedback =
8140         context->getRenderer()->getFeatures().supportsPipelineCreationFeedback.enabled;
8141     if (supportsFeedback)
8142     {
8143         vk::AddToPNextChain(&createInfo, &feedbackInfo);
8144     }
8145 
8146     vk::Pipeline pipeline;
8147     ANGLE_VK_TRY(context, pipelineCache->createComputePipeline(context, createInfo, &pipeline));
8148 
8149     vk::CacheLookUpFeedback lookUpFeedback = vk::CacheLookUpFeedback::None;
8150 
8151     if (supportsFeedback)
8152     {
8153         const bool cacheHit =
8154             (feedback.flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT) !=
8155             0;
8156 
8157         lookUpFeedback = cacheHit ? vk::CacheLookUpFeedback::Hit : vk::CacheLookUpFeedback::Miss;
8158         ApplyPipelineCreationFeedback(context, feedback);
8159     }
8160     vk::PipelineHelper computePipeline = vk::PipelineHelper();
8161     computePipeline.setComputePipeline(std::move(pipeline), lookUpFeedback);
8162 
8163     mCacheStats.missAndIncrementSize();
8164     mPayload[desc] = std::move(computePipeline);
8165     *pipelineOut   = &mPayload[desc];
8166 
8167     return angle::Result::Continue;
8168 }
8169 
8170 // GraphicsPipelineCache implementation.
8171 template <typename Hash>
destroy(vk::ErrorContext * context)8172 void GraphicsPipelineCache<Hash>::destroy(vk::ErrorContext *context)
8173 {
8174     if (vk::ShouldDumpPipelineCacheGraph(context) && !mPayload.empty())
8175     {
8176         vk::DumpPipelineCacheGraph<Hash>(context, mPayload);
8177     }
8178 
8179     accumulateCacheStats(context->getRenderer());
8180 
8181     VkDevice device = context->getDevice();
8182 
8183     for (auto &item : mPayload)
8184     {
8185         vk::PipelineHelper &pipeline = item.second;
8186         pipeline.destroy(device);
8187     }
8188 
8189     mPayload.clear();
8190 }
8191 
8192 template <typename Hash>
release(vk::ErrorContext * context)8193 void GraphicsPipelineCache<Hash>::release(vk::ErrorContext *context)
8194 {
8195     if (vk::ShouldDumpPipelineCacheGraph(context) && !mPayload.empty())
8196     {
8197         vk::DumpPipelineCacheGraph<Hash>(context, mPayload);
8198     }
8199 
8200     for (auto &item : mPayload)
8201     {
8202         vk::PipelineHelper &pipeline = item.second;
8203         pipeline.release(context);
8204     }
8205 
8206     mPayload.clear();
8207 }
8208 
8209 template <typename Hash>
createPipeline(vk::ErrorContext * context,vk::PipelineCacheAccess * pipelineCache,const vk::RenderPass & compatibleRenderPass,const vk::PipelineLayout & pipelineLayout,const vk::GraphicsPipelineShadersInfo & shaders,PipelineSource source,const vk::GraphicsPipelineDesc & desc,const vk::GraphicsPipelineDesc ** descPtrOut,vk::PipelineHelper ** pipelineOut)8210 angle::Result GraphicsPipelineCache<Hash>::createPipeline(
8211     vk::ErrorContext *context,
8212     vk::PipelineCacheAccess *pipelineCache,
8213     const vk::RenderPass &compatibleRenderPass,
8214     const vk::PipelineLayout &pipelineLayout,
8215     const vk::GraphicsPipelineShadersInfo &shaders,
8216     PipelineSource source,
8217     const vk::GraphicsPipelineDesc &desc,
8218     const vk::GraphicsPipelineDesc **descPtrOut,
8219     vk::PipelineHelper **pipelineOut)
8220 {
8221     vk::Pipeline newPipeline;
8222     vk::CacheLookUpFeedback feedback = vk::CacheLookUpFeedback::None;
8223 
8224     // This "if" is left here for the benefit of VulkanPipelineCachePerfTest.
8225     if (context != nullptr)
8226     {
8227         constexpr vk::GraphicsPipelineSubset kSubset =
8228             GraphicsPipelineCacheTypeHelper<Hash>::kSubset;
8229 
8230         ANGLE_VK_TRY(context,
8231                      desc.initializePipeline(context, pipelineCache, kSubset, compatibleRenderPass,
8232                                              pipelineLayout, shaders, &newPipeline, &feedback));
8233     }
8234 
8235     if (source == PipelineSource::WarmUp)
8236     {
8237         // Warm up task will pass in the placeholder PipelineHelper created in
8238         // ProgramExecutableVk::getPipelineCacheWarmUpTasks. Update that with the newly created
8239         // pipeline.
8240         **pipelineOut =
8241             vk::PipelineHelper(std::move(newPipeline), vk::CacheLookUpFeedback::WarmUpMiss);
8242         ASSERT(!shaders.usePipelineLibrary());
8243     }
8244     else
8245     {
8246         addToCache(source, desc, std::move(newPipeline), feedback, descPtrOut, pipelineOut);
8247         if (shaders.usePipelineLibrary())
8248         {
8249             (*pipelineOut)->setLinkedLibraryReferences(shaders.pipelineLibrary());
8250         }
8251     }
8252     return angle::Result::Continue;
8253 }
8254 
8255 template <typename Hash>
addToCache(PipelineSource source,const vk::GraphicsPipelineDesc & desc,vk::Pipeline && pipeline,vk::CacheLookUpFeedback feedback,const vk::GraphicsPipelineDesc ** descPtrOut,vk::PipelineHelper ** pipelineOut)8256 void GraphicsPipelineCache<Hash>::addToCache(PipelineSource source,
8257                                              const vk::GraphicsPipelineDesc &desc,
8258                                              vk::Pipeline &&pipeline,
8259                                              vk::CacheLookUpFeedback feedback,
8260                                              const vk::GraphicsPipelineDesc **descPtrOut,
8261                                              vk::PipelineHelper **pipelineOut)
8262 {
8263     ASSERT(mPayload.find(desc) == mPayload.end());
8264 
8265     mCacheStats.missAndIncrementSize();
8266 
8267     switch (source)
8268     {
8269         case PipelineSource::WarmUp:
8270             feedback = feedback == vk::CacheLookUpFeedback::Hit
8271                            ? vk::CacheLookUpFeedback::WarmUpHit
8272                            : vk::CacheLookUpFeedback::WarmUpMiss;
8273             break;
8274         case PipelineSource::DrawLinked:
8275             feedback = feedback == vk::CacheLookUpFeedback::Hit
8276                            ? vk::CacheLookUpFeedback::LinkedDrawHit
8277                            : vk::CacheLookUpFeedback::LinkedDrawMiss;
8278             break;
8279         case PipelineSource::Utils:
8280             feedback = feedback == vk::CacheLookUpFeedback::Hit
8281                            ? vk::CacheLookUpFeedback::UtilsHit
8282                            : vk::CacheLookUpFeedback::UtilsMiss;
8283             break;
8284         default:
8285             break;
8286     }
8287 
8288     auto insertedItem = mPayload.emplace(std::piecewise_construct, std::forward_as_tuple(desc),
8289                                          std::forward_as_tuple(std::move(pipeline), feedback));
8290     *descPtrOut       = &insertedItem.first->first;
8291     *pipelineOut      = &insertedItem.first->second;
8292 }
8293 
8294 template <typename Hash>
populate(const vk::GraphicsPipelineDesc & desc,vk::Pipeline && pipeline,vk::PipelineHelper ** pipelineHelperOut)8295 void GraphicsPipelineCache<Hash>::populate(const vk::GraphicsPipelineDesc &desc,
8296                                            vk::Pipeline &&pipeline,
8297                                            vk::PipelineHelper **pipelineHelperOut)
8298 {
8299     auto item = mPayload.find(desc);
8300     if (item != mPayload.end())
8301     {
8302         return;
8303     }
8304 
8305     // This function is used by -
8306     // 1. WarmUp tasks to insert placeholder pipelines
8307     // 2. VulkanPipelineCachePerfTest
8308     auto insertedItem =
8309         mPayload.emplace(std::piecewise_construct, std::forward_as_tuple(desc),
8310                          std::forward_as_tuple(std::move(pipeline), vk::CacheLookUpFeedback::None));
8311 
8312     if (pipelineHelperOut)
8313     {
8314         ASSERT(insertedItem.second);
8315         *pipelineHelperOut = &insertedItem.first->second;
8316     }
8317 }
8318 
8319 // Instantiate the pipeline cache functions
8320 template void GraphicsPipelineCache<GraphicsPipelineDescCompleteHash>::destroy(
8321     vk::ErrorContext *context);
8322 template void GraphicsPipelineCache<GraphicsPipelineDescCompleteHash>::release(
8323     vk::ErrorContext *context);
8324 template angle::Result GraphicsPipelineCache<GraphicsPipelineDescCompleteHash>::createPipeline(
8325     vk::ErrorContext *context,
8326     vk::PipelineCacheAccess *pipelineCache,
8327     const vk::RenderPass &compatibleRenderPass,
8328     const vk::PipelineLayout &pipelineLayout,
8329     const vk::GraphicsPipelineShadersInfo &shaders,
8330     PipelineSource source,
8331     const vk::GraphicsPipelineDesc &desc,
8332     const vk::GraphicsPipelineDesc **descPtrOut,
8333     vk::PipelineHelper **pipelineOut);
8334 template void GraphicsPipelineCache<GraphicsPipelineDescCompleteHash>::populate(
8335     const vk::GraphicsPipelineDesc &desc,
8336     vk::Pipeline &&pipeline,
8337     vk::PipelineHelper **pipelineHelperOut);
8338 
8339 template void GraphicsPipelineCache<GraphicsPipelineDescShadersHash>::destroy(
8340     vk::ErrorContext *context);
8341 template void GraphicsPipelineCache<GraphicsPipelineDescShadersHash>::release(
8342     vk::ErrorContext *context);
8343 template angle::Result GraphicsPipelineCache<GraphicsPipelineDescShadersHash>::createPipeline(
8344     vk::ErrorContext *context,
8345     vk::PipelineCacheAccess *pipelineCache,
8346     const vk::RenderPass &compatibleRenderPass,
8347     const vk::PipelineLayout &pipelineLayout,
8348     const vk::GraphicsPipelineShadersInfo &shaders,
8349     PipelineSource source,
8350     const vk::GraphicsPipelineDesc &desc,
8351     const vk::GraphicsPipelineDesc **descPtrOut,
8352     vk::PipelineHelper **pipelineOut);
8353 template void GraphicsPipelineCache<GraphicsPipelineDescShadersHash>::populate(
8354     const vk::GraphicsPipelineDesc &desc,
8355     vk::Pipeline &&pipeline,
8356     vk::PipelineHelper **pipelineHelperOut);
8357 
8358 // DescriptorSetLayoutCache implementation.
8359 DescriptorSetLayoutCache::DescriptorSetLayoutCache() = default;
8360 
~DescriptorSetLayoutCache()8361 DescriptorSetLayoutCache::~DescriptorSetLayoutCache()
8362 {
8363     ASSERT(mPayload.empty());
8364 }
8365 
destroy(vk::Renderer * renderer)8366 void DescriptorSetLayoutCache::destroy(vk::Renderer *renderer)
8367 {
8368     renderer->accumulateCacheStats(VulkanCacheType::DescriptorSetLayout, mCacheStats);
8369     ASSERT(AllCacheEntriesHaveUniqueReference(mPayload));
8370     mPayload.clear();
8371 }
8372 
getDescriptorSetLayout(vk::ErrorContext * context,const vk::DescriptorSetLayoutDesc & desc,vk::DescriptorSetLayoutPtr * descriptorSetLayoutOut)8373 angle::Result DescriptorSetLayoutCache::getDescriptorSetLayout(
8374     vk::ErrorContext *context,
8375     const vk::DescriptorSetLayoutDesc &desc,
8376     vk::DescriptorSetLayoutPtr *descriptorSetLayoutOut)
8377 {
8378     // Note: this function may be called without holding the share group lock.
8379     std::unique_lock<angle::SimpleMutex> lock(mMutex);
8380 
8381     auto iter = mPayload.find(desc);
8382     if (iter != mPayload.end())
8383     {
8384         *descriptorSetLayoutOut = iter->second;
8385         mCacheStats.hit();
8386         return angle::Result::Continue;
8387     }
8388 
8389     // If DescriptorSetLayoutDesc is empty, reuse placeholder descriptor set layout handle
8390     if (desc.empty())
8391     {
8392         *descriptorSetLayoutOut = context->getRenderer()->getEmptyDescriptorLayout();
8393         return angle::Result::Continue;
8394     }
8395 
8396     mCacheStats.missAndIncrementSize();
8397     // We must unpack the descriptor set layout description.
8398     vk::DescriptorSetLayoutBindingVector bindingVector;
8399     desc.unpackBindings(&bindingVector);
8400 
8401     VkDescriptorSetLayoutCreateInfo createInfo = {};
8402     createInfo.sType        = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
8403     createInfo.flags        = 0;
8404     createInfo.bindingCount = static_cast<uint32_t>(bindingVector.size());
8405     createInfo.pBindings    = bindingVector.data();
8406 
8407     vk::DescriptorSetLayoutPtr newLayout =
8408         vk::DescriptorSetLayoutPtr::MakeShared(context->getDevice());
8409     ANGLE_VK_TRY(context, newLayout->init(context->getDevice(), createInfo));
8410 
8411     *descriptorSetLayoutOut = newLayout;
8412     mPayload.emplace(desc, std::move(newLayout));
8413 
8414     return angle::Result::Continue;
8415 }
8416 
8417 // PipelineLayoutCache implementation.
8418 PipelineLayoutCache::PipelineLayoutCache() = default;
8419 
~PipelineLayoutCache()8420 PipelineLayoutCache::~PipelineLayoutCache()
8421 {
8422     ASSERT(mPayload.empty());
8423 }
8424 
destroy(vk::Renderer * renderer)8425 void PipelineLayoutCache::destroy(vk::Renderer *renderer)
8426 {
8427     accumulateCacheStats(renderer);
8428     ASSERT(AllCacheEntriesHaveUniqueReference(mPayload));
8429     mPayload.clear();
8430 }
8431 
getPipelineLayout(vk::ErrorContext * context,const vk::PipelineLayoutDesc & desc,const vk::DescriptorSetLayoutPointerArray & descriptorSetLayouts,vk::PipelineLayoutPtr * pipelineLayoutOut)8432 angle::Result PipelineLayoutCache::getPipelineLayout(
8433     vk::ErrorContext *context,
8434     const vk::PipelineLayoutDesc &desc,
8435     const vk::DescriptorSetLayoutPointerArray &descriptorSetLayouts,
8436     vk::PipelineLayoutPtr *pipelineLayoutOut)
8437 {
8438     // Note: this function may be called without holding the share group lock.
8439     std::unique_lock<angle::SimpleMutex> lock(mMutex);
8440 
8441     auto iter = mPayload.find(desc);
8442     if (iter != mPayload.end())
8443     {
8444         *pipelineLayoutOut = iter->second;
8445         mCacheStats.hit();
8446         return angle::Result::Continue;
8447     }
8448 
8449     mCacheStats.missAndIncrementSize();
8450     // Note this does not handle gaps in descriptor set layouts gracefully.
8451     angle::FixedVector<VkDescriptorSetLayout, vk::kMaxDescriptorSetLayouts> setLayoutHandles;
8452     for (const vk::DescriptorSetLayoutPtr &layoutPtr : descriptorSetLayouts)
8453     {
8454         if (layoutPtr)
8455         {
8456             VkDescriptorSetLayout setLayout = layoutPtr->getHandle();
8457             ASSERT(setLayout != VK_NULL_HANDLE);
8458             setLayoutHandles.push_back(setLayout);
8459         }
8460     }
8461 
8462     const vk::PackedPushConstantRange &descPushConstantRange = desc.getPushConstantRange();
8463     VkPushConstantRange pushConstantRange;
8464     pushConstantRange.stageFlags = descPushConstantRange.stageMask;
8465     pushConstantRange.offset     = descPushConstantRange.offset;
8466     pushConstantRange.size       = descPushConstantRange.size;
8467 
8468     // No pipeline layout found. We must create a new one.
8469     VkPipelineLayoutCreateInfo createInfo = {};
8470     createInfo.sType                      = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
8471     createInfo.flags                      = 0;
8472     createInfo.setLayoutCount             = static_cast<uint32_t>(setLayoutHandles.size());
8473     createInfo.pSetLayouts                = setLayoutHandles.data();
8474     if (pushConstantRange.size > 0)
8475     {
8476         createInfo.pushConstantRangeCount = 1;
8477         createInfo.pPushConstantRanges    = &pushConstantRange;
8478     }
8479 
8480     vk::PipelineLayoutPtr newLayout = vk::PipelineLayoutPtr::MakeShared(context->getDevice());
8481     ANGLE_VK_TRY(context, newLayout->init(context->getDevice(), createInfo));
8482 
8483     *pipelineLayoutOut = newLayout;
8484     mPayload.emplace(desc, std::move(newLayout));
8485 
8486     return angle::Result::Continue;
8487 }
8488 
8489 // YuvConversionCache implementation
8490 SamplerYcbcrConversionCache::SamplerYcbcrConversionCache() = default;
8491 
~SamplerYcbcrConversionCache()8492 SamplerYcbcrConversionCache::~SamplerYcbcrConversionCache()
8493 {
8494     ASSERT(mExternalFormatPayload.empty() && mVkFormatPayload.empty());
8495 }
8496 
destroy(vk::Renderer * renderer)8497 void SamplerYcbcrConversionCache::destroy(vk::Renderer *renderer)
8498 {
8499     renderer->accumulateCacheStats(VulkanCacheType::SamplerYcbcrConversion, mCacheStats);
8500 
8501     VkDevice device = renderer->getDevice();
8502 
8503     uint32_t count = static_cast<uint32_t>(mExternalFormatPayload.size());
8504     for (auto &iter : mExternalFormatPayload)
8505     {
8506         vk::SamplerYcbcrConversion &samplerYcbcrConversion = iter.second;
8507         samplerYcbcrConversion.destroy(device);
8508     }
8509     renderer->onDeallocateHandle(vk::HandleType::SamplerYcbcrConversion, count);
8510 
8511     count = static_cast<uint32_t>(mExternalFormatPayload.size());
8512     for (auto &iter : mVkFormatPayload)
8513     {
8514         vk::SamplerYcbcrConversion &samplerYcbcrConversion = iter.second;
8515         samplerYcbcrConversion.destroy(device);
8516     }
8517     renderer->onDeallocateHandle(vk::HandleType::SamplerYcbcrConversion, count);
8518 
8519     mExternalFormatPayload.clear();
8520     mVkFormatPayload.clear();
8521 }
8522 
getSamplerYcbcrConversion(vk::ErrorContext * context,const vk::YcbcrConversionDesc & ycbcrConversionDesc,VkSamplerYcbcrConversion * vkSamplerYcbcrConversionOut)8523 angle::Result SamplerYcbcrConversionCache::getSamplerYcbcrConversion(
8524     vk::ErrorContext *context,
8525     const vk::YcbcrConversionDesc &ycbcrConversionDesc,
8526     VkSamplerYcbcrConversion *vkSamplerYcbcrConversionOut)
8527 {
8528     ASSERT(ycbcrConversionDesc.valid());
8529     ASSERT(vkSamplerYcbcrConversionOut);
8530 
8531     SamplerYcbcrConversionMap &payload =
8532         (ycbcrConversionDesc.getExternalFormat() != 0) ? mExternalFormatPayload : mVkFormatPayload;
8533     const auto iter = payload.find(ycbcrConversionDesc);
8534     if (iter != payload.end())
8535     {
8536         vk::SamplerYcbcrConversion &samplerYcbcrConversion = iter->second;
8537         mCacheStats.hit();
8538         *vkSamplerYcbcrConversionOut = samplerYcbcrConversion.getHandle();
8539         return angle::Result::Continue;
8540     }
8541 
8542     mCacheStats.missAndIncrementSize();
8543 
8544     // Create the VkSamplerYcbcrConversion
8545     vk::SamplerYcbcrConversion wrappedSamplerYcbcrConversion;
8546     ANGLE_TRY(ycbcrConversionDesc.init(context, &wrappedSamplerYcbcrConversion));
8547 
8548     auto insertedItem = payload.emplace(
8549         ycbcrConversionDesc, vk::SamplerYcbcrConversion(std::move(wrappedSamplerYcbcrConversion)));
8550     vk::SamplerYcbcrConversion &insertedSamplerYcbcrConversion = insertedItem.first->second;
8551     *vkSamplerYcbcrConversionOut = insertedSamplerYcbcrConversion.getHandle();
8552 
8553     context->getRenderer()->onAllocateHandle(vk::HandleType::SamplerYcbcrConversion);
8554 
8555     return angle::Result::Continue;
8556 }
8557 
8558 // SamplerCache implementation.
8559 SamplerCache::SamplerCache() = default;
8560 
~SamplerCache()8561 SamplerCache::~SamplerCache()
8562 {
8563     ASSERT(mPayload.empty());
8564 }
8565 
destroy(vk::Renderer * renderer)8566 void SamplerCache::destroy(vk::Renderer *renderer)
8567 {
8568     renderer->accumulateCacheStats(VulkanCacheType::Sampler, mCacheStats);
8569 
8570     uint32_t count = static_cast<uint32_t>(mPayload.size());
8571     ASSERT(AllCacheEntriesHaveUniqueReference(mPayload));
8572     mPayload.clear();
8573     renderer->onDeallocateHandle(vk::HandleType::Sampler, count);
8574 }
8575 
getSampler(ContextVk * contextVk,const vk::SamplerDesc & desc,vk::SharedSamplerPtr * samplerOut)8576 angle::Result SamplerCache::getSampler(ContextVk *contextVk,
8577                                        const vk::SamplerDesc &desc,
8578                                        vk::SharedSamplerPtr *samplerOut)
8579 {
8580     auto iter = mPayload.find(desc);
8581     if (iter != mPayload.end())
8582     {
8583         *samplerOut = iter->second;
8584         mCacheStats.hit();
8585         return angle::Result::Continue;
8586     }
8587 
8588     mCacheStats.missAndIncrementSize();
8589     vk::SharedSamplerPtr newSampler = vk::SharedSamplerPtr::MakeShared(contextVk->getDevice());
8590     ANGLE_TRY(newSampler->init(contextVk, desc));
8591 
8592     (*samplerOut) = newSampler;
8593     mPayload.emplace(desc, std::move(newSampler));
8594 
8595     contextVk->getRenderer()->onAllocateHandle(vk::HandleType::Sampler);
8596 
8597     return angle::Result::Continue;
8598 }
8599 }  // namespace rx
8600