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