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