• 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/vulkan/vk_google_filtering_precision.h"
15 #include "libANGLE/BlobCache.h"
16 #include "libANGLE/VertexAttribute.h"
17 #include "libANGLE/renderer/vulkan/DisplayVk.h"
18 #include "libANGLE/renderer/vulkan/FramebufferVk.h"
19 #include "libANGLE/renderer/vulkan/ProgramVk.h"
20 #include "libANGLE/renderer/vulkan/RendererVk.h"
21 #include "libANGLE/renderer/vulkan/VertexArrayVk.h"
22 #include "libANGLE/renderer/vulkan/vk_format_utils.h"
23 #include "libANGLE/renderer/vulkan/vk_helpers.h"
24 
25 #include <type_traits>
26 
27 namespace rx
28 {
29 namespace vk
30 {
31 
32 namespace
33 {
34 
PackGLBlendOp(GLenum blendOp)35 uint8_t PackGLBlendOp(GLenum blendOp)
36 {
37     switch (blendOp)
38     {
39         case GL_FUNC_ADD:
40             return static_cast<uint8_t>(VK_BLEND_OP_ADD);
41         case GL_FUNC_SUBTRACT:
42             return static_cast<uint8_t>(VK_BLEND_OP_SUBTRACT);
43         case GL_FUNC_REVERSE_SUBTRACT:
44             return static_cast<uint8_t>(VK_BLEND_OP_REVERSE_SUBTRACT);
45         case GL_MIN:
46             return static_cast<uint8_t>(VK_BLEND_OP_MIN);
47         case GL_MAX:
48             return static_cast<uint8_t>(VK_BLEND_OP_MAX);
49         default:
50             UNREACHABLE();
51             return 0;
52     }
53 }
54 
PackGLBlendFactor(GLenum blendFactor)55 uint8_t PackGLBlendFactor(GLenum blendFactor)
56 {
57     switch (blendFactor)
58     {
59         case GL_ZERO:
60             return static_cast<uint8_t>(VK_BLEND_FACTOR_ZERO);
61         case GL_ONE:
62             return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE);
63         case GL_SRC_COLOR:
64             return static_cast<uint8_t>(VK_BLEND_FACTOR_SRC_COLOR);
65         case GL_DST_COLOR:
66             return static_cast<uint8_t>(VK_BLEND_FACTOR_DST_COLOR);
67         case GL_ONE_MINUS_SRC_COLOR:
68             return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR);
69         case GL_SRC_ALPHA:
70             return static_cast<uint8_t>(VK_BLEND_FACTOR_SRC_ALPHA);
71         case GL_ONE_MINUS_SRC_ALPHA:
72             return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA);
73         case GL_DST_ALPHA:
74             return static_cast<uint8_t>(VK_BLEND_FACTOR_DST_ALPHA);
75         case GL_ONE_MINUS_DST_ALPHA:
76             return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA);
77         case GL_ONE_MINUS_DST_COLOR:
78             return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR);
79         case GL_SRC_ALPHA_SATURATE:
80             return static_cast<uint8_t>(VK_BLEND_FACTOR_SRC_ALPHA_SATURATE);
81         case GL_CONSTANT_COLOR:
82             return static_cast<uint8_t>(VK_BLEND_FACTOR_CONSTANT_COLOR);
83         case GL_CONSTANT_ALPHA:
84             return static_cast<uint8_t>(VK_BLEND_FACTOR_CONSTANT_ALPHA);
85         case GL_ONE_MINUS_CONSTANT_COLOR:
86             return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR);
87         case GL_ONE_MINUS_CONSTANT_ALPHA:
88             return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA);
89         case GL_SRC1_COLOR_EXT:
90             return static_cast<uint8_t>(VK_BLEND_FACTOR_SRC1_COLOR);
91         case GL_SRC1_ALPHA_EXT:
92             return static_cast<uint8_t>(VK_BLEND_FACTOR_SRC1_ALPHA);
93         case GL_ONE_MINUS_SRC1_COLOR_EXT:
94             return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR);
95         case GL_ONE_MINUS_SRC1_ALPHA_EXT:
96             return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA);
97         default:
98             UNREACHABLE();
99             return 0;
100     }
101 }
102 
PackGLStencilOp(GLenum compareOp)103 VkStencilOp PackGLStencilOp(GLenum compareOp)
104 {
105     switch (compareOp)
106     {
107         case GL_KEEP:
108             return VK_STENCIL_OP_KEEP;
109         case GL_ZERO:
110             return VK_STENCIL_OP_ZERO;
111         case GL_REPLACE:
112             return VK_STENCIL_OP_REPLACE;
113         case GL_INCR:
114             return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
115         case GL_DECR:
116             return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
117         case GL_INCR_WRAP:
118             return VK_STENCIL_OP_INCREMENT_AND_WRAP;
119         case GL_DECR_WRAP:
120             return VK_STENCIL_OP_DECREMENT_AND_WRAP;
121         case GL_INVERT:
122             return VK_STENCIL_OP_INVERT;
123         default:
124             UNREACHABLE();
125             return VK_STENCIL_OP_KEEP;
126     }
127 }
128 
PackGLCompareFunc(GLenum compareFunc)129 VkCompareOp PackGLCompareFunc(GLenum compareFunc)
130 {
131     switch (compareFunc)
132     {
133         case GL_NEVER:
134             return VK_COMPARE_OP_NEVER;
135         case GL_ALWAYS:
136             return VK_COMPARE_OP_ALWAYS;
137         case GL_LESS:
138             return VK_COMPARE_OP_LESS;
139         case GL_LEQUAL:
140             return VK_COMPARE_OP_LESS_OR_EQUAL;
141         case GL_EQUAL:
142             return VK_COMPARE_OP_EQUAL;
143         case GL_GREATER:
144             return VK_COMPARE_OP_GREATER;
145         case GL_GEQUAL:
146             return VK_COMPARE_OP_GREATER_OR_EQUAL;
147         case GL_NOTEQUAL:
148             return VK_COMPARE_OP_NOT_EQUAL;
149         default:
150             UNREACHABLE();
151             return VK_COMPARE_OP_NEVER;
152     }
153 }
154 
UnpackAttachmentDesc(VkAttachmentDescription * desc,const Format & format,uint8_t samples,const PackedAttachmentOpsDesc & ops)155 void UnpackAttachmentDesc(VkAttachmentDescription *desc,
156                           const Format &format,
157                           uint8_t samples,
158                           const PackedAttachmentOpsDesc &ops)
159 {
160     desc->flags   = 0;
161     desc->format  = format.actualImageVkFormat();
162     desc->samples = gl_vk::GetSamples(samples);
163     desc->loadOp  = static_cast<VkAttachmentLoadOp>(ops.loadOp);
164     desc->storeOp =
165         ConvertRenderPassStoreOpToVkStoreOp(static_cast<RenderPassStoreOp>(ops.storeOp));
166     desc->stencilLoadOp = static_cast<VkAttachmentLoadOp>(ops.stencilLoadOp);
167     desc->stencilStoreOp =
168         ConvertRenderPassStoreOpToVkStoreOp(static_cast<RenderPassStoreOp>(ops.stencilStoreOp));
169     desc->initialLayout =
170         ConvertImageLayoutToVkImageLayout(static_cast<ImageLayout>(ops.initialLayout));
171     desc->finalLayout =
172         ConvertImageLayoutToVkImageLayout(static_cast<ImageLayout>(ops.finalLayout));
173 }
174 
UnpackColorResolveAttachmentDesc(VkAttachmentDescription * desc,const Format & format,bool usedAsInputAttachment,bool isInvalidated)175 void UnpackColorResolveAttachmentDesc(VkAttachmentDescription *desc,
176                                       const Format &format,
177                                       bool usedAsInputAttachment,
178                                       bool isInvalidated)
179 {
180     desc->flags  = 0;
181     desc->format = format.actualImageVkFormat();
182 
183     // This function is for color resolve attachments.
184     const angle::Format &angleFormat = format.actualImageFormat();
185     ASSERT(angleFormat.depthBits == 0 && angleFormat.stencilBits == 0);
186 
187     // Resolve attachments always have a sample count of 1.
188     //
189     // If the corresponding color attachment needs to take its initial value from the resolve
190     // attachment (i.e. needs to be unresolved), loadOp needs to be set to LOAD, otherwise it should
191     // be DONT_CARE as it gets overwritten during resolve.
192     //
193     // storeOp should be STORE.  If the attachment is invalidated, it is set to DONT_CARE.
194     desc->samples = VK_SAMPLE_COUNT_1_BIT;
195     desc->loadOp =
196         usedAsInputAttachment ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE;
197     desc->storeOp = isInvalidated ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE;
198     desc->stencilLoadOp  = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
199     desc->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
200     desc->initialLayout  = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
201     desc->finalLayout    = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
202 }
203 
UnpackDepthStencilResolveAttachmentDesc(VkAttachmentDescription * desc,const Format & format,bool usedAsDepthInputAttachment,bool usedAsStencilInputAttachment,bool isDepthInvalidated,bool isStencilInvalidated)204 void UnpackDepthStencilResolveAttachmentDesc(VkAttachmentDescription *desc,
205                                              const Format &format,
206                                              bool usedAsDepthInputAttachment,
207                                              bool usedAsStencilInputAttachment,
208                                              bool isDepthInvalidated,
209                                              bool isStencilInvalidated)
210 {
211     // There cannot be simultaneous usages of the depth/stencil resolve image, as depth/stencil
212     // resolve currently only comes from depth/stencil renderbuffers.
213     desc->flags  = 0;
214     desc->format = format.actualImageVkFormat();
215 
216     // This function is for depth/stencil resolve attachment.
217     const angle::Format &angleFormat = format.intendedFormat();
218     ASSERT(angleFormat.depthBits != 0 || angleFormat.stencilBits != 0);
219 
220     // Missing aspects are folded in is*Invalidated parameters, so no need to double check.
221     ASSERT(angleFormat.depthBits > 0 || isDepthInvalidated);
222     ASSERT(angleFormat.stencilBits > 0 || isStencilInvalidated);
223 
224     // Similarly to color resolve attachments, sample count is 1, loadOp is LOAD or DONT_CARE based
225     // on whether unresolve is required, and storeOp is STORE or DONT_CARE based on whether the
226     // attachment is invalidated or the aspect exists.
227     desc->samples = VK_SAMPLE_COUNT_1_BIT;
228     desc->loadOp =
229         usedAsDepthInputAttachment ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE;
230     desc->storeOp =
231         isDepthInvalidated ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE;
232     desc->stencilLoadOp =
233         usedAsStencilInputAttachment ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE;
234     desc->stencilStoreOp =
235         isStencilInvalidated ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE;
236     desc->initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
237     desc->finalLayout   = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
238 }
239 
UnpackStencilState(const PackedStencilOpState & packedState,uint8_t stencilReference,VkStencilOpState * stateOut)240 void UnpackStencilState(const PackedStencilOpState &packedState,
241                         uint8_t stencilReference,
242                         VkStencilOpState *stateOut)
243 {
244     stateOut->failOp      = static_cast<VkStencilOp>(packedState.ops.fail);
245     stateOut->passOp      = static_cast<VkStencilOp>(packedState.ops.pass);
246     stateOut->depthFailOp = static_cast<VkStencilOp>(packedState.ops.depthFail);
247     stateOut->compareOp   = static_cast<VkCompareOp>(packedState.ops.compare);
248     stateOut->compareMask = packedState.compareMask;
249     stateOut->writeMask   = packedState.writeMask;
250     stateOut->reference   = stencilReference;
251 }
252 
UnpackBlendAttachmentState(const PackedColorBlendAttachmentState & packedState,VkPipelineColorBlendAttachmentState * stateOut)253 void UnpackBlendAttachmentState(const PackedColorBlendAttachmentState &packedState,
254                                 VkPipelineColorBlendAttachmentState *stateOut)
255 {
256     stateOut->srcColorBlendFactor = static_cast<VkBlendFactor>(packedState.srcColorBlendFactor);
257     stateOut->dstColorBlendFactor = static_cast<VkBlendFactor>(packedState.dstColorBlendFactor);
258     stateOut->colorBlendOp        = static_cast<VkBlendOp>(packedState.colorBlendOp);
259     stateOut->srcAlphaBlendFactor = static_cast<VkBlendFactor>(packedState.srcAlphaBlendFactor);
260     stateOut->dstAlphaBlendFactor = static_cast<VkBlendFactor>(packedState.dstAlphaBlendFactor);
261     stateOut->alphaBlendOp        = static_cast<VkBlendOp>(packedState.alphaBlendOp);
262 }
263 
SetPipelineShaderStageInfo(const VkStructureType type,const VkShaderStageFlagBits stage,const VkShaderModule module,const VkSpecializationInfo & specializationInfo,VkPipelineShaderStageCreateInfo * shaderStage)264 void SetPipelineShaderStageInfo(const VkStructureType type,
265                                 const VkShaderStageFlagBits stage,
266                                 const VkShaderModule module,
267                                 const VkSpecializationInfo &specializationInfo,
268                                 VkPipelineShaderStageCreateInfo *shaderStage)
269 {
270     shaderStage->sType               = type;
271     shaderStage->flags               = 0;
272     shaderStage->stage               = stage;
273     shaderStage->module              = module;
274     shaderStage->pName               = "main";
275     shaderStage->pSpecializationInfo = &specializationInfo;
276 }
277 
278 // Defines a subpass that uses the resolve attachments as input attachments to initialize color and
279 // depth/stencil attachments that need to be "unresolved" at the start of the render pass.  The
280 // subpass will only contain the attachments that need to be unresolved to simplify the shader that
281 // performs the operations.
InitializeUnresolveSubpass(const RenderPassDesc & desc,const gl::DrawBuffersVector<VkAttachmentReference> & drawSubpassColorAttachmentRefs,const gl::DrawBuffersVector<VkAttachmentReference> & drawSubpassResolveAttachmentRefs,const VkAttachmentReference & depthStencilAttachmentRef,const VkAttachmentReference2KHR & depthStencilResolveAttachmentRef,gl::DrawBuffersVector<VkAttachmentReference> * unresolveColorAttachmentRefs,VkAttachmentReference * unresolveDepthStencilAttachmentRef,FramebufferAttachmentsVector<VkAttachmentReference> * unresolveInputAttachmentRefs,FramebufferAttachmentsVector<uint32_t> * unresolvePreserveAttachmentRefs,VkSubpassDescription * subpassDesc)282 void InitializeUnresolveSubpass(
283     const RenderPassDesc &desc,
284     const gl::DrawBuffersVector<VkAttachmentReference> &drawSubpassColorAttachmentRefs,
285     const gl::DrawBuffersVector<VkAttachmentReference> &drawSubpassResolveAttachmentRefs,
286     const VkAttachmentReference &depthStencilAttachmentRef,
287     const VkAttachmentReference2KHR &depthStencilResolveAttachmentRef,
288     gl::DrawBuffersVector<VkAttachmentReference> *unresolveColorAttachmentRefs,
289     VkAttachmentReference *unresolveDepthStencilAttachmentRef,
290     FramebufferAttachmentsVector<VkAttachmentReference> *unresolveInputAttachmentRefs,
291     FramebufferAttachmentsVector<uint32_t> *unresolvePreserveAttachmentRefs,
292     VkSubpassDescription *subpassDesc)
293 {
294     for (uint32_t colorIndexGL = 0; colorIndexGL < desc.colorAttachmentRange(); ++colorIndexGL)
295     {
296         // Assume the GL Framebuffer has the following attachments enabled:
297         //
298         //     GL Color 0
299         //     GL Color 3
300         //     GL Color 4
301         //     GL Color 6
302         //     GL Color 7
303         //     GL Depth/Stencil
304         //
305         // Additionally, assume Color 0, 4 and 6 are multisampled-render-to-texture (or for any
306         // other reason) have corresponding resolve attachments.  Furthermore, say Color 4 and 6
307         // require an initial unresolve operation.
308         //
309         // In the above example, the render pass is created with the following attachments:
310         //
311         //     RP Attachment[0] <- corresponding to GL Color 0
312         //     RP Attachment[1] <- corresponding to GL Color 3
313         //     RP Attachment[2] <- corresponding to GL Color 4
314         //     RP Attachment[3] <- corresponding to GL Color 6
315         //     RP Attachment[4] <- corresponding to GL Color 7
316         //     RP Attachment[5] <- corresponding to GL Depth/Stencil
317         //     RP Attachment[6] <- corresponding to resolve attachment of GL Color 0
318         //     RP Attachment[7] <- corresponding to resolve attachment of GL Color 4
319         //     RP Attachment[8] <- corresponding to resolve attachment of GL Color 6
320         //
321         // If the depth/stencil attachment is to be resolved, the following attachment would also be
322         // present:
323         //
324         //     RP Attachment[9] <- corresponding to resolve attachment of GL Depth/Stencil
325         //
326         // The subpass that takes the application draw calls has the following attachments, creating
327         // the mapping from the Vulkan attachment indices (i.e. RP attachment indices) to GL indices
328         // as indicated by the GL shaders:
329         //
330         //     Subpass[1] Color[0] -> RP Attachment[0]
331         //     Subpass[1] Color[1] -> VK_ATTACHMENT_UNUSED
332         //     Subpass[1] Color[2] -> VK_ATTACHMENT_UNUSED
333         //     Subpass[1] Color[3] -> RP Attachment[1]
334         //     Subpass[1] Color[4] -> RP Attachment[2]
335         //     Subpass[1] Color[5] -> VK_ATTACHMENT_UNUSED
336         //     Subpass[1] Color[6] -> RP Attachment[3]
337         //     Subpass[1] Color[7] -> RP Attachment[4]
338         //     Subpass[1] Depth/Stencil -> RP Attachment[5]
339         //     Subpass[1] Resolve[0] -> RP Attachment[6]
340         //     Subpass[1] Resolve[1] -> VK_ATTACHMENT_UNUSED
341         //     Subpass[1] Resolve[2] -> VK_ATTACHMENT_UNUSED
342         //     Subpass[1] Resolve[3] -> VK_ATTACHMENT_UNUSED
343         //     Subpass[1] Resolve[4] -> RP Attachment[7]
344         //     Subpass[1] Resolve[5] -> VK_ATTACHMENT_UNUSED
345         //     Subpass[1] Resolve[6] -> RP Attachment[8]
346         //     Subpass[1] Resolve[7] -> VK_ATTACHMENT_UNUSED
347         //
348         // With depth/stencil resolve attachment:
349         //
350         //     Subpass[1] Depth/Stencil Resolve -> RP Attachment[9]
351         //
352         // The initial subpass that's created here is (remember that in the above example Color 4
353         // and 6 need to be unresolved):
354         //
355         //     Subpass[0] Input[0] -> RP Attachment[7] = Subpass[1] Resolve[4]
356         //     Subpass[0] Input[1] -> RP Attachment[8] = Subpass[1] Resolve[6]
357         //     Subpass[0] Color[0] -> RP Attachment[2] = Subpass[1] Color[4]
358         //     Subpass[0] Color[1] -> RP Attachment[3] = Subpass[1] Color[6]
359         //
360         // The trick here therefore is to use the color attachment refs already created for the
361         // application draw subpass indexed with colorIndexGL.
362         //
363         // If depth/stencil needs to be unresolved:
364         //
365         //     Subpass[0] Input[2] -> RP Attachment[9] = Subpass[1] Depth/Stencil Resolve
366         //     Subpass[0] Color[2] -> RP Attachment[5] = Subpass[1] Depth/Stencil
367         //
368         // As an additional note, the attachments that are not used in the unresolve subpass must be
369         // preserved.  That is color attachments and the depth/stencil attachment if any.  Resolve
370         // attachments are rewritten by the next subpass, so they don't need to be preserved.  Note
371         // that there's no need to preserve attachments whose loadOp is DONT_CARE.  For simplicity,
372         // we preserve those as well.  The driver would ideally avoid preserving attachments with
373         // loadOp=DONT_CARE.
374         //
375         // With the above example:
376         //
377         //     Subpass[0] Preserve[0] -> RP Attachment[0] = Subpass[1] Color[0]
378         //     Subpass[0] Preserve[1] -> RP Attachment[1] = Subpass[1] Color[3]
379         //     Subpass[0] Preserve[2] -> RP Attachment[4] = Subpass[1] Color[7]
380         //
381         // If depth/stencil is not unresolved:
382         //
383         //     Subpass[0] Preserve[3] -> RP Attachment[5] = Subpass[1] Depth/Stencil
384         //
385         // Again, the color attachment refs already created for the application draw subpass can be
386         // used indexed with colorIndexGL.
387 
388         if (!desc.hasColorUnresolveAttachment(colorIndexGL))
389         {
390             if (desc.isColorAttachmentEnabled(colorIndexGL))
391             {
392                 unresolvePreserveAttachmentRefs->push_back(
393                     drawSubpassColorAttachmentRefs[colorIndexGL].attachment);
394             }
395             continue;
396         }
397         ASSERT(desc.isColorAttachmentEnabled(colorIndexGL));
398         ASSERT(desc.hasColorResolveAttachment(colorIndexGL));
399         ASSERT(drawSubpassColorAttachmentRefs[colorIndexGL].attachment != VK_ATTACHMENT_UNUSED);
400         ASSERT(drawSubpassResolveAttachmentRefs[colorIndexGL].attachment != VK_ATTACHMENT_UNUSED);
401 
402         unresolveColorAttachmentRefs->push_back(drawSubpassColorAttachmentRefs[colorIndexGL]);
403         unresolveInputAttachmentRefs->push_back(drawSubpassResolveAttachmentRefs[colorIndexGL]);
404 
405         // Note the input attachment layout should be shader read-only.  The subpass dependency
406         // will take care of transitioning the layout of the resolve attachment to color attachment
407         // automatically.
408         unresolveInputAttachmentRefs->back().layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
409     }
410 
411     if (desc.hasDepthStencilUnresolveAttachment())
412     {
413         ASSERT(desc.hasDepthStencilAttachment());
414         ASSERT(desc.hasDepthStencilResolveAttachment());
415 
416         *unresolveDepthStencilAttachmentRef = depthStencilAttachmentRef;
417 
418         VkAttachmentReference unresolveDepthStencilInputAttachmentRef = {};
419         unresolveDepthStencilInputAttachmentRef.attachment =
420             depthStencilResolveAttachmentRef.attachment;
421         unresolveDepthStencilInputAttachmentRef.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
422 
423         unresolveInputAttachmentRefs->push_back(unresolveDepthStencilInputAttachmentRef);
424     }
425     else if (desc.hasDepthStencilAttachment())
426     {
427         // Preserve the depth/stencil attachment if not unresolved.  Again, there's no need to
428         // preserve this attachment if loadOp=DONT_CARE, but we do for simplicity.
429         unresolvePreserveAttachmentRefs->push_back(depthStencilAttachmentRef.attachment);
430     }
431 
432     ASSERT(!unresolveColorAttachmentRefs->empty() ||
433            unresolveDepthStencilAttachmentRef->attachment != VK_ATTACHMENT_UNUSED);
434     ASSERT(unresolveColorAttachmentRefs->size() +
435                (desc.hasDepthStencilUnresolveAttachment() ? 1 : 0) ==
436            unresolveInputAttachmentRefs->size());
437 
438     subpassDesc->flags                = 0;
439     subpassDesc->pipelineBindPoint    = VK_PIPELINE_BIND_POINT_GRAPHICS;
440     subpassDesc->inputAttachmentCount = static_cast<uint32_t>(unresolveInputAttachmentRefs->size());
441     subpassDesc->pInputAttachments    = unresolveInputAttachmentRefs->data();
442     subpassDesc->colorAttachmentCount = static_cast<uint32_t>(unresolveColorAttachmentRefs->size());
443     subpassDesc->pColorAttachments    = unresolveColorAttachmentRefs->data();
444     subpassDesc->pResolveAttachments  = nullptr;
445     subpassDesc->pDepthStencilAttachment = unresolveDepthStencilAttachmentRef;
446     subpassDesc->preserveAttachmentCount =
447         static_cast<uint32_t>(unresolvePreserveAttachmentRefs->size());
448     subpassDesc->pPreserveAttachments = unresolvePreserveAttachmentRefs->data();
449 }
450 
451 // There is normally one subpass, and occasionally another for the unresolve operation.
452 constexpr size_t kSubpassFastVectorSize = 2;
453 template <typename T>
454 using SubpassVector = angle::FastVector<T, kSubpassFastVectorSize>;
455 
InitializeUnresolveSubpassDependencies(const SubpassVector<VkSubpassDescription> & subpassDesc,bool unresolveColor,bool unresolveDepthStencil,std::vector<VkSubpassDependency> * subpassDependencies)456 void InitializeUnresolveSubpassDependencies(const SubpassVector<VkSubpassDescription> &subpassDesc,
457                                             bool unresolveColor,
458                                             bool unresolveDepthStencil,
459                                             std::vector<VkSubpassDependency> *subpassDependencies)
460 {
461     ASSERT(subpassDesc.size() >= 2);
462     ASSERT(unresolveColor || unresolveDepthStencil);
463 
464     // The unresolve subpass is the first subpass.  The application draw subpass is the next one.
465     constexpr uint32_t kUnresolveSubpassIndex = 0;
466     constexpr uint32_t kDrawSubpassIndex      = 1;
467 
468     // A subpass dependency is needed between the unresolve and draw subpasses.  There are two
469     // hazards here:
470     //
471     // - Subpass 0 writes to color/depth/stencil attachments, subpass 1 writes to the same
472     //   attachments.  This is a WaW hazard (color/depth/stencil write -> color/depth/stencil write)
473     //   similar to when two subsequent render passes write to the same images.
474     // - Subpass 0 reads from resolve attachments, subpass 1 writes to the same resolve attachments.
475     //   This is a WaR hazard (fragment shader read -> color write) which only requires an execution
476     //   barrier.
477     //
478     // Note: the DEPENDENCY_BY_REGION flag is necessary to create a "framebuffer-local" dependency,
479     // as opposed to "framebuffer-global".  The latter is effectively a render pass break.  The
480     // former creates a dependency per framebuffer region.  If dependency scopes correspond to
481     // attachments with:
482     //
483     // - Same sample count: dependency is at sample granularity
484     // - Different sample count: dependency is at pixel granularity
485     //
486     // The latter is clarified by the spec as such:
487     //
488     // > Practically, the pixel vs sample granularity dependency means that if an input attachment
489     // > has a different number of samples than the pipeline's rasterizationSamples, then a fragment
490     // > can access any sample in the input attachment's pixel even if it only uses
491     // > framebuffer-local dependencies.
492     //
493     // The dependency for the first hazard above (attachment write -> attachment write) is on
494     // same-sample attachments, so it will not allow the use of input attachments as required by the
495     // unresolve subpass.  As a result, even though the second hazard seems to be subsumed by the
496     // first (its src stage is earlier and its dst stage is the same), a separate dependency is
497     // created for it just to obtain a pixel granularity dependency.
498     //
499     // Note: depth/stencil resolve is considered to be done in the color write stage:
500     //
501     // > Moving to the next subpass automatically performs any multisample resolve operations in the
502     // > subpass being ended. End-of-subpass multisample resolves are treated as color attachment
503     // > writes for the purposes of synchronization. This applies to resolve operations for both
504     // > color and depth/stencil attachments. That is, they are considered to execute in the
505     // > VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT pipeline stage and their writes are
506     // > synchronized with VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT.
507 
508     subpassDependencies->emplace_back();
509     VkSubpassDependency *dependency = &subpassDependencies->back();
510 
511     constexpr VkPipelineStageFlags kColorWriteStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
512     constexpr VkPipelineStageFlags kColorReadWriteStage =
513         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
514     constexpr VkAccessFlags kColorWriteFlags = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
515     constexpr VkAccessFlags kColorReadWriteFlags =
516         kColorWriteFlags | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
517 
518     constexpr VkPipelineStageFlags kDepthStencilWriteStage =
519         VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
520     constexpr VkPipelineStageFlags kDepthStencilReadWriteStage =
521         VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
522     constexpr VkAccessFlags kDepthStencilWriteFlags = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
523     constexpr VkAccessFlags kDepthStencilReadWriteFlags =
524         kDepthStencilWriteFlags | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
525 
526     VkPipelineStageFlags attachmentWriteStages     = 0;
527     VkPipelineStageFlags attachmentReadWriteStages = 0;
528     VkAccessFlags attachmentWriteFlags             = 0;
529     VkAccessFlags attachmentReadWriteFlags         = 0;
530 
531     if (unresolveColor)
532     {
533         attachmentWriteStages |= kColorWriteStage;
534         attachmentReadWriteStages |= kColorReadWriteStage;
535         attachmentWriteFlags |= kColorWriteFlags;
536         attachmentReadWriteFlags |= kColorReadWriteFlags;
537     }
538 
539     if (unresolveDepthStencil)
540     {
541         attachmentWriteStages |= kDepthStencilWriteStage;
542         attachmentReadWriteStages |= kDepthStencilReadWriteStage;
543         attachmentWriteFlags |= kDepthStencilWriteFlags;
544         attachmentReadWriteFlags |= kDepthStencilReadWriteFlags;
545     }
546 
547     dependency->srcSubpass      = kUnresolveSubpassIndex;
548     dependency->dstSubpass      = kDrawSubpassIndex;
549     dependency->srcStageMask    = attachmentWriteStages;
550     dependency->dstStageMask    = attachmentReadWriteStages;
551     dependency->srcAccessMask   = attachmentWriteFlags;
552     dependency->dstAccessMask   = attachmentReadWriteFlags;
553     dependency->dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
554 
555     subpassDependencies->emplace_back();
556     dependency = &subpassDependencies->back();
557 
558     // Note again that depth/stencil resolve is considered to be done in the color output stage.
559     dependency->srcSubpass      = kUnresolveSubpassIndex;
560     dependency->dstSubpass      = kDrawSubpassIndex;
561     dependency->srcStageMask    = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
562     dependency->dstStageMask    = kColorWriteStage;
563     dependency->srcAccessMask   = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
564     dependency->dstAccessMask   = kColorWriteFlags;
565     dependency->dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
566 }
567 
InitializeInputAttachmentSubpassDependencies(std::vector<VkSubpassDependency> * subpassDependencies,uint32_t subpassIndex)568 void InitializeInputAttachmentSubpassDependencies(
569     std::vector<VkSubpassDependency> *subpassDependencies,
570     uint32_t subpassIndex)
571 {
572     subpassDependencies->emplace_back();
573     VkSubpassDependency *dependency = &subpassDependencies->back();
574 
575     dependency->srcSubpass      = subpassIndex;
576     dependency->dstSubpass      = subpassIndex;
577     dependency->srcStageMask    = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
578     dependency->dstStageMask    = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
579     dependency->srcAccessMask   = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
580     dependency->dstAccessMask   = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
581     dependency->dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
582 }
583 
ToAttachmentDesciption2(const VkAttachmentDescription & desc,VkAttachmentDescription2KHR * desc2Out)584 void ToAttachmentDesciption2(const VkAttachmentDescription &desc,
585                              VkAttachmentDescription2KHR *desc2Out)
586 {
587     *desc2Out                = {};
588     desc2Out->sType          = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR;
589     desc2Out->flags          = desc.flags;
590     desc2Out->format         = desc.format;
591     desc2Out->samples        = desc.samples;
592     desc2Out->loadOp         = desc.loadOp;
593     desc2Out->storeOp        = desc.storeOp;
594     desc2Out->stencilLoadOp  = desc.stencilLoadOp;
595     desc2Out->stencilStoreOp = desc.stencilStoreOp;
596     desc2Out->initialLayout  = desc.initialLayout;
597     desc2Out->finalLayout    = desc.finalLayout;
598 }
599 
ToAttachmentReference2(const VkAttachmentReference & ref,VkImageAspectFlags aspectMask,VkAttachmentReference2KHR * ref2Out)600 void ToAttachmentReference2(const VkAttachmentReference &ref,
601                             VkImageAspectFlags aspectMask,
602                             VkAttachmentReference2KHR *ref2Out)
603 {
604     *ref2Out            = {};
605     ref2Out->sType      = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;
606     ref2Out->attachment = ref.attachment;
607     ref2Out->layout     = ref.layout;
608     ref2Out->aspectMask = aspectMask;
609 }
610 
ToSubpassDescription2(const VkSubpassDescription & desc,const FramebufferAttachmentsVector<VkAttachmentReference2KHR> & inputRefs,const gl::DrawBuffersVector<VkAttachmentReference2KHR> & colorRefs,const gl::DrawBuffersVector<VkAttachmentReference2KHR> & resolveRefs,const VkAttachmentReference2KHR & depthStencilRef,uint32_t viewMask,VkSubpassDescription2KHR * desc2Out)611 void ToSubpassDescription2(const VkSubpassDescription &desc,
612                            const FramebufferAttachmentsVector<VkAttachmentReference2KHR> &inputRefs,
613                            const gl::DrawBuffersVector<VkAttachmentReference2KHR> &colorRefs,
614                            const gl::DrawBuffersVector<VkAttachmentReference2KHR> &resolveRefs,
615                            const VkAttachmentReference2KHR &depthStencilRef,
616                            uint32_t viewMask,
617                            VkSubpassDescription2KHR *desc2Out)
618 {
619     *desc2Out                         = {};
620     desc2Out->sType                   = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR;
621     desc2Out->flags                   = desc.flags;
622     desc2Out->pipelineBindPoint       = desc.pipelineBindPoint;
623     desc2Out->viewMask                = viewMask;
624     desc2Out->inputAttachmentCount    = static_cast<uint32_t>(inputRefs.size());
625     desc2Out->pInputAttachments       = !inputRefs.empty() ? inputRefs.data() : nullptr;
626     desc2Out->colorAttachmentCount    = static_cast<uint32_t>(colorRefs.size());
627     desc2Out->pColorAttachments       = !colorRefs.empty() ? colorRefs.data() : nullptr;
628     desc2Out->pResolveAttachments     = !resolveRefs.empty() ? resolveRefs.data() : nullptr;
629     desc2Out->pDepthStencilAttachment = desc.pDepthStencilAttachment ? &depthStencilRef : nullptr;
630     desc2Out->preserveAttachmentCount = desc.preserveAttachmentCount;
631     desc2Out->pPreserveAttachments    = desc.pPreserveAttachments;
632 }
633 
ToSubpassDependency2(const VkSubpassDependency & dep,VkSubpassDependency2KHR * dep2Out)634 void ToSubpassDependency2(const VkSubpassDependency &dep, VkSubpassDependency2KHR *dep2Out)
635 {
636     *dep2Out                 = {};
637     dep2Out->sType           = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2_KHR;
638     dep2Out->srcSubpass      = dep.srcSubpass;
639     dep2Out->dstSubpass      = dep.dstSubpass;
640     dep2Out->srcStageMask    = dep.srcStageMask;
641     dep2Out->dstStageMask    = dep.dstStageMask;
642     dep2Out->srcAccessMask   = dep.srcAccessMask;
643     dep2Out->dstAccessMask   = dep.dstAccessMask;
644     dep2Out->dependencyFlags = dep.dependencyFlags;
645 }
646 
CreateRenderPass2(Context * context,const VkRenderPassCreateInfo & createInfo,const VkSubpassDescriptionDepthStencilResolve & depthStencilResolve,const VkRenderPassMultiviewCreateInfo & multiviewInfo,bool unresolveDepth,bool unresolveStencil,bool isRenderToTexture,uint8_t renderToTextureSamples,RenderPass * renderPass)647 angle::Result CreateRenderPass2(Context *context,
648                                 const VkRenderPassCreateInfo &createInfo,
649                                 const VkSubpassDescriptionDepthStencilResolve &depthStencilResolve,
650                                 const VkRenderPassMultiviewCreateInfo &multiviewInfo,
651                                 bool unresolveDepth,
652                                 bool unresolveStencil,
653                                 bool isRenderToTexture,
654                                 uint8_t renderToTextureSamples,
655                                 RenderPass *renderPass)
656 {
657     // Convert the attachments to VkAttachmentDescription2.
658     FramebufferAttachmentArray<VkAttachmentDescription2KHR> attachmentDescs;
659     for (uint32_t index = 0; index < createInfo.attachmentCount; ++index)
660     {
661         ToAttachmentDesciption2(createInfo.pAttachments[index], &attachmentDescs[index]);
662     }
663 
664     // Convert subpass attachments to VkAttachmentReference2 and the subpass description to
665     // VkSubpassDescription2.
666     SubpassVector<FramebufferAttachmentsVector<VkAttachmentReference2KHR>>
667         subpassInputAttachmentRefs(createInfo.subpassCount);
668     SubpassVector<gl::DrawBuffersVector<VkAttachmentReference2KHR>> subpassColorAttachmentRefs(
669         createInfo.subpassCount);
670     SubpassVector<gl::DrawBuffersVector<VkAttachmentReference2KHR>> subpassResolveAttachmentRefs(
671         createInfo.subpassCount);
672     SubpassVector<VkAttachmentReference2KHR> subpassDepthStencilAttachmentRefs(
673         createInfo.subpassCount);
674     SubpassVector<VkSubpassDescription2KHR> subpassDescriptions(createInfo.subpassCount);
675     for (uint32_t subpass = 0; subpass < createInfo.subpassCount; ++subpass)
676     {
677         const VkSubpassDescription &desc = createInfo.pSubpasses[subpass];
678         FramebufferAttachmentsVector<VkAttachmentReference2KHR> &inputRefs =
679             subpassInputAttachmentRefs[subpass];
680         gl::DrawBuffersVector<VkAttachmentReference2KHR> &colorRefs =
681             subpassColorAttachmentRefs[subpass];
682         gl::DrawBuffersVector<VkAttachmentReference2KHR> &resolveRefs =
683             subpassResolveAttachmentRefs[subpass];
684         VkAttachmentReference2KHR &depthStencilRef = subpassDepthStencilAttachmentRefs[subpass];
685 
686         inputRefs.resize(desc.inputAttachmentCount);
687         colorRefs.resize(desc.colorAttachmentCount);
688 
689         // Convert subpass attachment references.
690         for (uint32_t index = 0; index < desc.inputAttachmentCount; ++index)
691         {
692             VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
693             if (index >= desc.colorAttachmentCount)
694             {
695                 // Set the aspect of the depth/stencil input attachment (of which there can be only
696                 // one).
697                 ASSERT(index + 1 == desc.inputAttachmentCount);
698                 aspectMask = 0;
699                 if (unresolveDepth)
700                 {
701                     aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
702                 }
703                 if (unresolveStencil)
704                 {
705                     aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
706                 }
707                 ASSERT(aspectMask != 0);
708             }
709 
710             ToAttachmentReference2(desc.pInputAttachments[index], aspectMask, &inputRefs[index]);
711         }
712 
713         for (uint32_t index = 0; index < desc.colorAttachmentCount; ++index)
714         {
715             ToAttachmentReference2(desc.pColorAttachments[index], VK_IMAGE_ASPECT_COLOR_BIT,
716                                    &colorRefs[index]);
717         }
718         if (desc.pResolveAttachments)
719         {
720             resolveRefs.resize(desc.colorAttachmentCount);
721             for (uint32_t index = 0; index < desc.colorAttachmentCount; ++index)
722             {
723                 ToAttachmentReference2(desc.pResolveAttachments[index], VK_IMAGE_ASPECT_COLOR_BIT,
724                                        &resolveRefs[index]);
725             }
726         }
727         if (desc.pDepthStencilAttachment)
728         {
729             ToAttachmentReference2(*desc.pDepthStencilAttachment,
730                                    VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,
731                                    &depthStencilRef);
732         }
733 
734         // Convert subpass itself.
735         ToSubpassDescription2(desc, inputRefs, colorRefs, resolveRefs, depthStencilRef,
736                               multiviewInfo.pViewMasks[subpass], &subpassDescriptions[subpass]);
737     }
738 
739     VkMultisampledRenderToSingleSampledInfoEXT renderToTextureInfo = {};
740     renderToTextureInfo.sType = VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT;
741     renderToTextureInfo.multisampledRenderToSingleSampledEnable = true;
742     renderToTextureInfo.rasterizationSamples = gl_vk::GetSamples(renderToTextureSamples);
743     renderToTextureInfo.depthResolveMode     = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
744     renderToTextureInfo.stencilResolveMode   = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
745 
746     // Append the depth/stencil resolve attachment to the pNext chain of last subpass, if any.
747     if (depthStencilResolve.pDepthStencilResolveAttachment != nullptr)
748     {
749         ASSERT(!isRenderToTexture);
750         subpassDescriptions.back().pNext = &depthStencilResolve;
751     }
752     else
753     {
754         RendererVk *renderer = context->getRenderer();
755 
756         ASSERT(isRenderToTexture);
757         ASSERT(renderer->getFeatures().supportsMultisampledRenderToSingleSampled.enabled);
758         ASSERT(subpassDescriptions.size() == 1);
759 
760         subpassDescriptions.back().pNext = &renderToTextureInfo;
761     }
762 
763     // Convert subpass dependencies to VkSubpassDependency2.
764     std::vector<VkSubpassDependency2KHR> subpassDependencies(createInfo.dependencyCount);
765     for (uint32_t index = 0; index < createInfo.dependencyCount; ++index)
766     {
767         ToSubpassDependency2(createInfo.pDependencies[index], &subpassDependencies[index]);
768     }
769 
770     // Convert CreateInfo itself
771     VkRenderPassCreateInfo2KHR createInfo2 = {};
772     createInfo2.sType                      = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR;
773     createInfo2.flags                      = createInfo.flags;
774     createInfo2.attachmentCount            = createInfo.attachmentCount;
775     createInfo2.pAttachments               = attachmentDescs.data();
776     createInfo2.subpassCount               = createInfo.subpassCount;
777     createInfo2.pSubpasses                 = subpassDescriptions.data();
778     createInfo2.dependencyCount            = static_cast<uint32_t>(subpassDependencies.size());
779     createInfo2.pDependencies = !subpassDependencies.empty() ? subpassDependencies.data() : nullptr;
780     createInfo2.correlatedViewMaskCount = multiviewInfo.correlationMaskCount;
781     createInfo2.pCorrelatedViewMasks    = multiviewInfo.pCorrelationMasks;
782 
783     // Initialize the render pass.
784     ANGLE_VK_TRY(context, renderPass->init2(context->getDevice(), createInfo2));
785 
786     return angle::Result::Continue;
787 }
788 
UpdateRenderPassColorPerfCounters(const VkRenderPassCreateInfo & createInfo,const VkSubpassDescription & subpass,RenderPassPerfCounters * countersOut)789 void UpdateRenderPassColorPerfCounters(const VkRenderPassCreateInfo &createInfo,
790                                        const VkSubpassDescription &subpass,
791                                        RenderPassPerfCounters *countersOut)
792 {
793     // Color resolve counters.
794     if (subpass.pResolveAttachments == nullptr)
795     {
796         return;
797     }
798 
799     for (uint32_t colorSubpassIndex = 0; colorSubpassIndex < subpass.colorAttachmentCount;
800          ++colorSubpassIndex)
801     {
802         uint32_t resolveRenderPassIndex = subpass.pResolveAttachments[colorSubpassIndex].attachment;
803 
804         if (resolveRenderPassIndex == VK_ATTACHMENT_UNUSED)
805         {
806             continue;
807         }
808 
809         ++countersOut->colorAttachmentResolves;
810     }
811 }
812 
UpdateRenderPassDepthStencilPerfCounters(const VkRenderPassCreateInfo & createInfo,size_t renderPassIndex,RenderPassPerfCounters * countersOut)813 void UpdateRenderPassDepthStencilPerfCounters(const VkRenderPassCreateInfo &createInfo,
814                                               size_t renderPassIndex,
815                                               RenderPassPerfCounters *countersOut)
816 {
817     ASSERT(renderPassIndex != VK_ATTACHMENT_UNUSED);
818 
819     // Depth/stencil ops counters.
820     const VkAttachmentDescription &ds = createInfo.pAttachments[renderPassIndex];
821 
822     countersOut->depthClears += ds.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ? 1 : 0;
823     countersOut->depthLoads += ds.loadOp == VK_ATTACHMENT_LOAD_OP_LOAD ? 1 : 0;
824     countersOut->depthStores +=
825         ds.storeOp == static_cast<uint16_t>(RenderPassStoreOp::Store) ? 1 : 0;
826 
827     countersOut->stencilClears += ds.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ? 1 : 0;
828     countersOut->stencilLoads += ds.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD ? 1 : 0;
829     countersOut->stencilStores +=
830         ds.stencilStoreOp == static_cast<uint16_t>(RenderPassStoreOp::Store) ? 1 : 0;
831 
832     // Depth/stencil read-only mode.
833     countersOut->readOnlyDepthStencil +=
834         ds.finalLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL ? 1 : 0;
835 }
836 
UpdateRenderPassDepthStencilResolvePerfCounters(const VkRenderPassCreateInfo & createInfo,const VkSubpassDescriptionDepthStencilResolve & depthStencilResolve,RenderPassPerfCounters * countersOut)837 void UpdateRenderPassDepthStencilResolvePerfCounters(
838     const VkRenderPassCreateInfo &createInfo,
839     const VkSubpassDescriptionDepthStencilResolve &depthStencilResolve,
840     RenderPassPerfCounters *countersOut)
841 {
842     if (depthStencilResolve.pDepthStencilResolveAttachment == nullptr)
843     {
844         return;
845     }
846 
847     uint32_t resolveRenderPassIndex =
848         depthStencilResolve.pDepthStencilResolveAttachment->attachment;
849 
850     if (resolveRenderPassIndex == VK_ATTACHMENT_UNUSED)
851     {
852         return;
853     }
854 
855     const VkAttachmentDescription &dsResolve = createInfo.pAttachments[resolveRenderPassIndex];
856 
857     // Resolve depth/stencil ops counters.
858     countersOut->depthClears += dsResolve.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ? 1 : 0;
859     countersOut->depthLoads += dsResolve.loadOp == VK_ATTACHMENT_LOAD_OP_LOAD ? 1 : 0;
860     countersOut->depthStores +=
861         dsResolve.storeOp == static_cast<uint16_t>(RenderPassStoreOp::Store) ? 1 : 0;
862 
863     countersOut->stencilClears += dsResolve.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ? 1 : 0;
864     countersOut->stencilLoads += dsResolve.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD ? 1 : 0;
865     countersOut->stencilStores +=
866         dsResolve.stencilStoreOp == static_cast<uint16_t>(RenderPassStoreOp::Store) ? 1 : 0;
867 
868     // Depth/stencil resolve counters.
869     countersOut->depthAttachmentResolves +=
870         depthStencilResolve.depthResolveMode != VK_RESOLVE_MODE_NONE ? 1 : 0;
871     countersOut->stencilAttachmentResolves +=
872         depthStencilResolve.stencilResolveMode != VK_RESOLVE_MODE_NONE ? 1 : 0;
873 }
874 
UpdateRenderPassPerfCounters(const RenderPassDesc & desc,const VkRenderPassCreateInfo & createInfo,const VkSubpassDescriptionDepthStencilResolve & depthStencilResolve,RenderPassPerfCounters * countersOut)875 void UpdateRenderPassPerfCounters(
876     const RenderPassDesc &desc,
877     const VkRenderPassCreateInfo &createInfo,
878     const VkSubpassDescriptionDepthStencilResolve &depthStencilResolve,
879     RenderPassPerfCounters *countersOut)
880 {
881     // Accumulate depth/stencil attachment indices in all subpasses to avoid double-counting
882     // counters.
883     FramebufferAttachmentMask depthStencilAttachmentIndices;
884 
885     for (uint32_t subpassIndex = 0; subpassIndex < createInfo.subpassCount; ++subpassIndex)
886     {
887         const VkSubpassDescription &subpass = createInfo.pSubpasses[subpassIndex];
888 
889         // Color counters.  Note: currently there are no counters for load/store ops of color
890         // attachments, so there's no risk of double counting.
891         UpdateRenderPassColorPerfCounters(createInfo, subpass, countersOut);
892 
893         // Record index of depth/stencil attachment.
894         if (subpass.pDepthStencilAttachment != nullptr)
895         {
896             uint32_t attachmentRenderPassIndex = subpass.pDepthStencilAttachment->attachment;
897             if (attachmentRenderPassIndex != VK_ATTACHMENT_UNUSED)
898             {
899                 depthStencilAttachmentIndices.set(attachmentRenderPassIndex);
900             }
901         }
902     }
903 
904     // Depth/stencil counters.  Currently, both subpasses use the same depth/stencil attachment (if
905     // any).
906     ASSERT(depthStencilAttachmentIndices.count() <= 1);
907     for (size_t attachmentRenderPassIndex : depthStencilAttachmentIndices)
908     {
909         UpdateRenderPassDepthStencilPerfCounters(createInfo, attachmentRenderPassIndex,
910                                                  countersOut);
911     }
912 
913     UpdateRenderPassDepthStencilResolvePerfCounters(createInfo, depthStencilResolve, countersOut);
914 
915     // Determine unresolve counters from the render pass desc, to avoid making guesses from subpass
916     // count etc.
917     countersOut->colorAttachmentUnresolves += desc.getColorUnresolveAttachmentMask().count();
918     countersOut->depthAttachmentUnresolves += desc.hasDepthUnresolveAttachment() ? 1 : 0;
919     countersOut->stencilAttachmentUnresolves += desc.hasStencilUnresolveAttachment() ? 1 : 0;
920 }
921 
InitializeRenderPassFromDesc(ContextVk * contextVk,const RenderPassDesc & desc,const AttachmentOpsArray & ops,RenderPassHelper * renderPassHelper)922 angle::Result InitializeRenderPassFromDesc(ContextVk *contextVk,
923                                            const RenderPassDesc &desc,
924                                            const AttachmentOpsArray &ops,
925                                            RenderPassHelper *renderPassHelper)
926 {
927     RendererVk *renderer = contextVk->getRenderer();
928 
929     constexpr VkAttachmentReference kUnusedAttachment   = {VK_ATTACHMENT_UNUSED,
930                                                          VK_IMAGE_LAYOUT_UNDEFINED};
931     constexpr VkAttachmentReference2 kUnusedAttachment2 = {
932         VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR, nullptr, VK_ATTACHMENT_UNUSED,
933         VK_IMAGE_LAYOUT_UNDEFINED, 0};
934 
935     const bool needInputAttachments = desc.getFramebufferFetchMode();
936     const bool isRenderToTexture    = desc.isRenderToTexture();
937 
938     const uint8_t descSamples            = desc.samples();
939     const uint8_t attachmentSamples      = isRenderToTexture ? 1 : descSamples;
940     const uint8_t renderToTextureSamples = isRenderToTexture ? descSamples : 1;
941 
942     // Unpack the packed and split representation into the format required by Vulkan.
943     gl::DrawBuffersVector<VkAttachmentReference> colorAttachmentRefs;
944     gl::DrawBuffersVector<VkAttachmentReference> colorResolveAttachmentRefs;
945     VkAttachmentReference depthStencilAttachmentRef            = kUnusedAttachment;
946     VkAttachmentReference2KHR depthStencilResolveAttachmentRef = kUnusedAttachment2;
947 
948     // The list of attachments includes all non-resolve and resolve attachments.
949     FramebufferAttachmentArray<VkAttachmentDescription> attachmentDescs;
950 
951     // Track invalidated attachments so their resolve attachments can be invalidated as well.
952     // Resolve attachments can be removed in that case if the render pass has only one subpass
953     // (which is the case if there are no unresolve attachments).
954     gl::DrawBufferMask isColorInvalidated;
955     bool isDepthInvalidated   = false;
956     bool isStencilInvalidated = false;
957     const bool hasUnresolveAttachments =
958         desc.getColorUnresolveAttachmentMask().any() || desc.hasDepthStencilUnresolveAttachment();
959     const bool canRemoveResolveAttachments = !hasUnresolveAttachments;
960 
961     // Pack color attachments
962     PackedAttachmentIndex attachmentCount(0);
963     for (uint32_t colorIndexGL = 0; colorIndexGL < desc.colorAttachmentRange(); ++colorIndexGL)
964     {
965         // Vulkan says:
966         //
967         // > Each element of the pColorAttachments array corresponds to an output location in the
968         // > shader, i.e. if the shader declares an output variable decorated with a Location value
969         // > of X, then it uses the attachment provided in pColorAttachments[X].
970         //
971         // This means that colorAttachmentRefs is indexed by colorIndexGL.  Where the color
972         // attachment is disabled, a reference with VK_ATTACHMENT_UNUSED is given.
973 
974         if (!desc.isColorAttachmentEnabled(colorIndexGL))
975         {
976             colorAttachmentRefs.push_back(kUnusedAttachment);
977             continue;
978         }
979 
980         angle::FormatID formatID = desc[colorIndexGL];
981         ASSERT(formatID != angle::FormatID::NONE);
982         const Format &format = renderer->getFormat(formatID);
983 
984         VkAttachmentReference colorRef;
985         colorRef.attachment = attachmentCount.get();
986         colorRef.layout     = needInputAttachments
987                               ? VK_IMAGE_LAYOUT_GENERAL
988                               : ConvertImageLayoutToVkImageLayout(
989                                     static_cast<ImageLayout>(ops[attachmentCount].initialLayout));
990         colorAttachmentRefs.push_back(colorRef);
991 
992         UnpackAttachmentDesc(&attachmentDescs[attachmentCount.get()], format, attachmentSamples,
993                              ops[attachmentCount]);
994 
995         angle::FormatID attachmentFormat = format.actualImageFormatID;
996 
997         // If this renderpass uses EXT_srgb_write_control, we need to override the format to its
998         // linear counterpart. Formats that cannot be reinterpreted are exempt from this
999         // requirement.
1000         angle::FormatID linearFormat = rx::ConvertToLinear(attachmentFormat);
1001         if (linearFormat != angle::FormatID::NONE)
1002         {
1003             if (desc.getSRGBWriteControlMode() == gl::SrgbWriteControlMode::Linear)
1004             {
1005                 attachmentFormat = linearFormat;
1006             }
1007         }
1008         attachmentDescs[attachmentCount.get()].format =
1009             contextVk->getRenderer()->getFormat(attachmentFormat).actualImageVkFormat();
1010         ASSERT(attachmentDescs[attachmentCount.get()].format != VK_FORMAT_UNDEFINED);
1011 
1012         isColorInvalidated.set(colorIndexGL, ops[attachmentCount].isInvalidated);
1013 
1014         ++attachmentCount;
1015     }
1016 
1017     // Pack depth/stencil attachment, if any
1018     if (desc.hasDepthStencilAttachment())
1019     {
1020         uint32_t depthStencilIndexGL = static_cast<uint32_t>(desc.depthStencilAttachmentIndex());
1021 
1022         angle::FormatID formatID = desc[depthStencilIndexGL];
1023         ASSERT(formatID != angle::FormatID::NONE);
1024         const Format &format = renderer->getFormat(formatID);
1025 
1026         depthStencilAttachmentRef.attachment = attachmentCount.get();
1027         depthStencilAttachmentRef.layout     = ConvertImageLayoutToVkImageLayout(
1028             static_cast<ImageLayout>(ops[attachmentCount].initialLayout));
1029 
1030         UnpackAttachmentDesc(&attachmentDescs[attachmentCount.get()], format, attachmentSamples,
1031                              ops[attachmentCount]);
1032 
1033         isDepthInvalidated   = ops[attachmentCount].isInvalidated;
1034         isStencilInvalidated = ops[attachmentCount].isStencilInvalidated;
1035 
1036         ++attachmentCount;
1037     }
1038 
1039     // Pack color resolve attachments
1040     const uint32_t nonResolveAttachmentCount = attachmentCount.get();
1041     for (uint32_t colorIndexGL = 0; colorIndexGL < desc.colorAttachmentRange(); ++colorIndexGL)
1042     {
1043         if (!desc.hasColorResolveAttachment(colorIndexGL))
1044         {
1045             colorResolveAttachmentRefs.push_back(kUnusedAttachment);
1046             continue;
1047         }
1048 
1049         ASSERT(desc.isColorAttachmentEnabled(colorIndexGL));
1050 
1051         const Format &format = renderer->getFormat(desc[colorIndexGL]);
1052 
1053         VkAttachmentReference colorRef;
1054         colorRef.attachment = attachmentCount.get();
1055         colorRef.layout     = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1056 
1057         // If color attachment is invalidated, try to remove its resolve attachment altogether.
1058         if (canRemoveResolveAttachments && isColorInvalidated.test(colorIndexGL))
1059         {
1060             colorResolveAttachmentRefs.push_back(kUnusedAttachment);
1061         }
1062         else
1063         {
1064             colorResolveAttachmentRefs.push_back(colorRef);
1065         }
1066 
1067         UnpackColorResolveAttachmentDesc(&attachmentDescs[attachmentCount.get()], format,
1068                                          desc.hasColorUnresolveAttachment(colorIndexGL),
1069                                          isColorInvalidated.test(colorIndexGL));
1070 
1071         ++attachmentCount;
1072     }
1073 
1074     // Pack depth/stencil resolve attachment, if any
1075     if (desc.hasDepthStencilResolveAttachment())
1076     {
1077         ASSERT(desc.hasDepthStencilAttachment());
1078 
1079         uint32_t depthStencilIndexGL = static_cast<uint32_t>(desc.depthStencilAttachmentIndex());
1080 
1081         const Format &format             = renderer->getFormat(desc[depthStencilIndexGL]);
1082         const angle::Format &angleFormat = format.intendedFormat();
1083 
1084         // Treat missing aspect as invalidated for the purpose of the resolve attachment.
1085         if (angleFormat.depthBits == 0)
1086         {
1087             isDepthInvalidated = true;
1088         }
1089         if (angleFormat.stencilBits == 0)
1090         {
1091             isStencilInvalidated = true;
1092         }
1093 
1094         depthStencilResolveAttachmentRef.attachment = attachmentCount.get();
1095         depthStencilResolveAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
1096         depthStencilResolveAttachmentRef.aspectMask = 0;
1097 
1098         if (!isDepthInvalidated)
1099         {
1100             depthStencilResolveAttachmentRef.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
1101         }
1102         if (!isStencilInvalidated)
1103         {
1104             depthStencilResolveAttachmentRef.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
1105         }
1106 
1107         UnpackDepthStencilResolveAttachmentDesc(
1108             &attachmentDescs[attachmentCount.get()], format, desc.hasDepthUnresolveAttachment(),
1109             desc.hasStencilUnresolveAttachment(), isDepthInvalidated, isStencilInvalidated);
1110 
1111         ++attachmentCount;
1112     }
1113 
1114     SubpassVector<VkSubpassDescription> subpassDesc;
1115 
1116     // If any attachment needs to be unresolved, create an initial subpass for this purpose.  Note
1117     // that the following arrays are used in initializing a VkSubpassDescription in subpassDesc,
1118     // which is in turn used in VkRenderPassCreateInfo below.  That is why they are declared in the
1119     // same scope.
1120     gl::DrawBuffersVector<VkAttachmentReference> unresolveColorAttachmentRefs;
1121     VkAttachmentReference unresolveDepthStencilAttachmentRef = kUnusedAttachment;
1122     FramebufferAttachmentsVector<VkAttachmentReference> unresolveInputAttachmentRefs;
1123     FramebufferAttachmentsVector<uint32_t> unresolvePreserveAttachmentRefs;
1124     if (hasUnresolveAttachments)
1125     {
1126         subpassDesc.push_back({});
1127         InitializeUnresolveSubpass(
1128             desc, colorAttachmentRefs, colorResolveAttachmentRefs, depthStencilAttachmentRef,
1129             depthStencilResolveAttachmentRef, &unresolveColorAttachmentRefs,
1130             &unresolveDepthStencilAttachmentRef, &unresolveInputAttachmentRefs,
1131             &unresolvePreserveAttachmentRefs, &subpassDesc.back());
1132     }
1133 
1134     subpassDesc.push_back({});
1135     VkSubpassDescription *applicationSubpass = &subpassDesc.back();
1136 
1137     applicationSubpass->flags             = 0;
1138     applicationSubpass->pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
1139     applicationSubpass->inputAttachmentCount =
1140         needInputAttachments ? static_cast<uint32_t>(colorAttachmentRefs.size()) : 0;
1141     applicationSubpass->pInputAttachments =
1142         needInputAttachments ? colorAttachmentRefs.data() : nullptr;
1143     applicationSubpass->colorAttachmentCount = static_cast<uint32_t>(colorAttachmentRefs.size());
1144     applicationSubpass->pColorAttachments    = colorAttachmentRefs.data();
1145     applicationSubpass->pResolveAttachments  = attachmentCount.get() > nonResolveAttachmentCount
1146                                                   ? colorResolveAttachmentRefs.data()
1147                                                   : nullptr;
1148     applicationSubpass->pDepthStencilAttachment =
1149         (depthStencilAttachmentRef.attachment != VK_ATTACHMENT_UNUSED ? &depthStencilAttachmentRef
1150                                                                       : nullptr);
1151     applicationSubpass->preserveAttachmentCount = 0;
1152     applicationSubpass->pPreserveAttachments    = nullptr;
1153 
1154     // If depth/stencil is to be resolved, add a VkSubpassDescriptionDepthStencilResolve to the
1155     // pNext chain of the subpass description.  Note that we need a VkSubpassDescription2KHR to have
1156     // a pNext pointer.  CreateRenderPass2 is called to convert the data structures here to those
1157     // specified by VK_KHR_create_renderpass2 for this purpose.
1158     VkSubpassDescriptionDepthStencilResolve depthStencilResolve = {};
1159     if (desc.hasDepthStencilResolveAttachment())
1160     {
1161         depthStencilResolve.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE;
1162         depthStencilResolve.depthResolveMode   = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
1163         depthStencilResolve.stencilResolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
1164 
1165         // If depth/stencil attachment is invalidated, try to remove its resolve attachment
1166         // altogether.
1167         const bool removeDepthStencilResolve =
1168             canRemoveResolveAttachments && isDepthInvalidated && isStencilInvalidated;
1169         if (!removeDepthStencilResolve)
1170         {
1171             depthStencilResolve.pDepthStencilResolveAttachment = &depthStencilResolveAttachmentRef;
1172         }
1173     }
1174 
1175     std::vector<VkSubpassDependency> subpassDependencies;
1176     if (hasUnresolveAttachments)
1177     {
1178         InitializeUnresolveSubpassDependencies(
1179             subpassDesc, desc.getColorUnresolveAttachmentMask().any(),
1180             desc.hasDepthStencilUnresolveAttachment(), &subpassDependencies);
1181     }
1182 
1183     if (needInputAttachments)
1184     {
1185         uint32_t drawSubpassIndex = static_cast<uint32_t>(subpassDesc.size()) - 1;
1186         InitializeInputAttachmentSubpassDependencies(&subpassDependencies, drawSubpassIndex);
1187     }
1188 
1189     VkRenderPassCreateInfo createInfo = {};
1190     createInfo.sType                  = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
1191     createInfo.flags                  = 0;
1192     createInfo.attachmentCount        = attachmentCount.get();
1193     createInfo.pAttachments           = attachmentDescs.data();
1194     createInfo.subpassCount           = static_cast<uint32_t>(subpassDesc.size());
1195     createInfo.pSubpasses             = subpassDesc.data();
1196     createInfo.dependencyCount        = 0;
1197     createInfo.pDependencies          = nullptr;
1198 
1199     if (!subpassDependencies.empty())
1200     {
1201         createInfo.dependencyCount = static_cast<uint32_t>(subpassDependencies.size());
1202         createInfo.pDependencies   = subpassDependencies.data();
1203     }
1204 
1205     SubpassVector<uint32_t> viewMasks(subpassDesc.size(),
1206                                       angle::BitMask<uint32_t>(desc.viewCount()));
1207     VkRenderPassMultiviewCreateInfo multiviewInfo = {};
1208     multiviewInfo.sType        = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO;
1209     multiviewInfo.subpassCount = createInfo.subpassCount;
1210     multiviewInfo.pViewMasks   = viewMasks.data();
1211 
1212     if (desc.viewCount() > 0)
1213     {
1214         // For VR, the views are correlated, so this would be an optimization.  However, an
1215         // application can also use multiview for example to render to all 6 faces of a cubemap, in
1216         // which case the views are actually not so correlated.  In the absence of any hints from
1217         // the application (TODO: verify that extension has no hints), we have to decide on one or
1218         // the other.  Since VR is more expensive, the views are marked as correlated to optimize
1219         // that use case.
1220         multiviewInfo.correlationMaskCount = 1;
1221         multiviewInfo.pCorrelationMasks    = viewMasks.data();
1222 
1223         createInfo.pNext = &multiviewInfo;
1224     }
1225 
1226     // If depth/stencil resolve is used, we need to create the render pass with
1227     // vkCreateRenderPass2KHR.  Same when using the VK_EXT_multisampled_render_to_single_sampled
1228     // extension.
1229     if (depthStencilResolve.pDepthStencilResolveAttachment != nullptr || desc.isRenderToTexture())
1230     {
1231         ANGLE_TRY(CreateRenderPass2(contextVk, createInfo, depthStencilResolve, multiviewInfo,
1232                                     desc.hasDepthUnresolveAttachment(),
1233                                     desc.hasStencilUnresolveAttachment(), desc.isRenderToTexture(),
1234                                     renderToTextureSamples, &renderPassHelper->getRenderPass()));
1235     }
1236     else
1237     {
1238         ANGLE_VK_TRY(contextVk,
1239                      renderPassHelper->getRenderPass().init(contextVk->getDevice(), createInfo));
1240     }
1241 
1242     // Calculate perf counters associated with this render pass, such as load/store ops, unresolve
1243     // and resolve operations etc.  This information is taken out of the render pass create info.
1244     // Depth/stencil resolve attachment uses RenderPass2 structures, so it's passed in separately.
1245     UpdateRenderPassPerfCounters(desc, createInfo, depthStencilResolve,
1246                                  &renderPassHelper->getPerfCounters());
1247 
1248     return angle::Result::Continue;
1249 }
1250 
GetRenderPassAndUpdateCounters(ContextVk * contextVk,bool updatePerfCounters,RenderPassHelper * renderPassHelper,RenderPass ** renderPassOut)1251 void GetRenderPassAndUpdateCounters(ContextVk *contextVk,
1252                                     bool updatePerfCounters,
1253                                     RenderPassHelper *renderPassHelper,
1254                                     RenderPass **renderPassOut)
1255 {
1256     *renderPassOut = &renderPassHelper->getRenderPass();
1257     if (updatePerfCounters)
1258     {
1259         PerfCounters &counters                   = contextVk->getPerfCounters();
1260         const RenderPassPerfCounters &rpCounters = renderPassHelper->getPerfCounters();
1261 
1262         counters.depthClears += rpCounters.depthClears;
1263         counters.depthLoads += rpCounters.depthLoads;
1264         counters.depthStores += rpCounters.depthStores;
1265         counters.stencilClears += rpCounters.stencilClears;
1266         counters.stencilLoads += rpCounters.stencilLoads;
1267         counters.stencilStores += rpCounters.stencilStores;
1268         counters.colorAttachmentUnresolves += rpCounters.colorAttachmentUnresolves;
1269         counters.colorAttachmentResolves += rpCounters.colorAttachmentResolves;
1270         counters.depthAttachmentUnresolves += rpCounters.depthAttachmentUnresolves;
1271         counters.depthAttachmentResolves += rpCounters.depthAttachmentResolves;
1272         counters.stencilAttachmentUnresolves += rpCounters.stencilAttachmentUnresolves;
1273         counters.stencilAttachmentResolves += rpCounters.stencilAttachmentResolves;
1274         counters.readOnlyDepthStencilRenderPasses += rpCounters.readOnlyDepthStencil;
1275     }
1276 }
1277 
InitializeSpecializationInfo(const SpecializationConstants & specConsts,SpecializationConstantMap<VkSpecializationMapEntry> * specializationEntriesOut,VkSpecializationInfo * specializationInfoOut)1278 void InitializeSpecializationInfo(
1279     const SpecializationConstants &specConsts,
1280     SpecializationConstantMap<VkSpecializationMapEntry> *specializationEntriesOut,
1281     VkSpecializationInfo *specializationInfoOut)
1282 {
1283     // Collect specialization constants.
1284     for (const sh::vk::SpecializationConstantId id :
1285          angle::AllEnums<sh::vk::SpecializationConstantId>())
1286     {
1287         (*specializationEntriesOut)[id].constantID = static_cast<uint32_t>(id);
1288         switch (id)
1289         {
1290             case sh::vk::SpecializationConstantId::LineRasterEmulation:
1291                 (*specializationEntriesOut)[id].offset =
1292                     offsetof(SpecializationConstants, lineRasterEmulation);
1293                 (*specializationEntriesOut)[id].size = sizeof(specConsts.lineRasterEmulation);
1294                 break;
1295             case sh::vk::SpecializationConstantId::SurfaceRotation:
1296                 (*specializationEntriesOut)[id].offset =
1297                     offsetof(SpecializationConstants, surfaceRotation);
1298                 (*specializationEntriesOut)[id].size = sizeof(specConsts.surfaceRotation);
1299                 break;
1300             case sh::vk::SpecializationConstantId::DrawableWidth:
1301                 (*specializationEntriesOut)[id].offset =
1302                     offsetof(vk::SpecializationConstants, drawableWidth);
1303                 (*specializationEntriesOut)[id].size = sizeof(specConsts.drawableWidth);
1304                 break;
1305             case sh::vk::SpecializationConstantId::DrawableHeight:
1306                 (*specializationEntriesOut)[id].offset =
1307                     offsetof(vk::SpecializationConstants, drawableHeight);
1308                 (*specializationEntriesOut)[id].size = sizeof(specConsts.drawableHeight);
1309                 break;
1310             default:
1311                 UNREACHABLE();
1312                 break;
1313         }
1314     }
1315 
1316     specializationInfoOut->mapEntryCount = static_cast<uint32_t>(specializationEntriesOut->size());
1317     specializationInfoOut->pMapEntries   = specializationEntriesOut->data();
1318     specializationInfoOut->dataSize      = sizeof(specConsts);
1319     specializationInfoOut->pData         = &specConsts;
1320 }
1321 
1322 // Utility for setting a value on a packed 4-bit integer array.
1323 template <typename SrcT>
Int4Array_Set(uint8_t * arrayBytes,uint32_t arrayIndex,SrcT value)1324 void Int4Array_Set(uint8_t *arrayBytes, uint32_t arrayIndex, SrcT value)
1325 {
1326     uint32_t byteIndex = arrayIndex >> 1;
1327     ASSERT(value < 16);
1328 
1329     if ((arrayIndex & 1) == 0)
1330     {
1331         arrayBytes[byteIndex] &= 0xF0;
1332         arrayBytes[byteIndex] |= static_cast<uint8_t>(value);
1333     }
1334     else
1335     {
1336         arrayBytes[byteIndex] &= 0x0F;
1337         arrayBytes[byteIndex] |= static_cast<uint8_t>(value) << 4;
1338     }
1339 }
1340 
1341 // Utility for getting a value from a packed 4-bit integer array.
1342 template <typename DestT>
Int4Array_Get(const uint8_t * arrayBytes,uint32_t arrayIndex)1343 DestT Int4Array_Get(const uint8_t *arrayBytes, uint32_t arrayIndex)
1344 {
1345     uint32_t byteIndex = arrayIndex >> 1;
1346 
1347     if ((arrayIndex & 1) == 0)
1348     {
1349         return static_cast<DestT>(arrayBytes[byteIndex] & 0xF);
1350     }
1351     else
1352     {
1353         return static_cast<DestT>(arrayBytes[byteIndex] >> 4);
1354     }
1355 }
1356 
1357 // When converting a byte number to a transition bit index we can shift instead of divide.
1358 constexpr size_t kTransitionByteShift = Log2(kGraphicsPipelineDirtyBitBytes);
1359 
1360 // When converting a number of bits offset to a transition bit index we can also shift.
1361 constexpr size_t kBitsPerByte        = 8;
1362 constexpr size_t kTransitionBitShift = kTransitionByteShift + Log2(kBitsPerByte);
1363 
1364 // Helper macro to map from a PipelineDesc struct and field to a dirty bit index.
1365 // Uses the 'offsetof' macro to compute the offset 'Member' within the PipelineDesc
1366 // and the offset of 'Field' within 'Member'. We can optimize the dirty bit setting by computing
1367 // the shifted dirty bit at compile time instead of calling "set".
1368 #define ANGLE_GET_TRANSITION_BIT(Member, Field)                                      \
1369     ((offsetof(GraphicsPipelineDesc, Member) + offsetof(decltype(Member), Field)) >> \
1370      kTransitionByteShift)
1371 
1372 // Indexed dirty bits cannot be entirely computed at compile time since the index is passed to
1373 // the update function.
1374 #define ANGLE_GET_INDEXED_TRANSITION_BIT(Member, Field, Index, BitWidth) \
1375     (((BitWidth * Index) >> kTransitionBitShift) + ANGLE_GET_TRANSITION_BIT(Member, Field))
1376 
1377 constexpr angle::PackedEnumMap<gl::ComponentType, VkFormat> kMismatchedComponentTypeMap = {{
1378     {gl::ComponentType::Float, VK_FORMAT_R32G32B32A32_SFLOAT},
1379     {gl::ComponentType::Int, VK_FORMAT_R32G32B32A32_SINT},
1380     {gl::ComponentType::UnsignedInt, VK_FORMAT_R32G32B32A32_UINT},
1381 }};
1382 }  // anonymous namespace
1383 
1384 // RenderPassDesc implementation.
RenderPassDesc()1385 RenderPassDesc::RenderPassDesc()
1386 {
1387     memset(this, 0, sizeof(RenderPassDesc));
1388 }
1389 
1390 RenderPassDesc::~RenderPassDesc() = default;
1391 
RenderPassDesc(const RenderPassDesc & other)1392 RenderPassDesc::RenderPassDesc(const RenderPassDesc &other)
1393 {
1394     memcpy(this, &other, sizeof(RenderPassDesc));
1395 }
1396 
packColorAttachment(size_t colorIndexGL,angle::FormatID formatID)1397 void RenderPassDesc::packColorAttachment(size_t colorIndexGL, angle::FormatID formatID)
1398 {
1399     ASSERT(colorIndexGL < mAttachmentFormats.size());
1400     static_assert(angle::kNumANGLEFormats < std::numeric_limits<uint8_t>::max(),
1401                   "Too many ANGLE formats to fit in uint8_t");
1402     // Force the user to pack the depth/stencil attachment last.
1403     ASSERT(!hasDepthStencilAttachment());
1404     // This function should only be called for enabled GL color attachments.
1405     ASSERT(formatID != angle::FormatID::NONE);
1406 
1407     uint8_t &packedFormat = mAttachmentFormats[colorIndexGL];
1408     SetBitField(packedFormat, formatID);
1409 
1410     // Set color attachment range such that it covers the range from index 0 through last active
1411     // index.  This is the reasons why we need depth/stencil to be packed last.
1412     SetBitField(mColorAttachmentRange, std::max<size_t>(mColorAttachmentRange, colorIndexGL + 1));
1413 }
1414 
packColorAttachmentGap(size_t colorIndexGL)1415 void RenderPassDesc::packColorAttachmentGap(size_t colorIndexGL)
1416 {
1417     ASSERT(colorIndexGL < mAttachmentFormats.size());
1418     static_assert(angle::kNumANGLEFormats < std::numeric_limits<uint8_t>::max(),
1419                   "Too many ANGLE formats to fit in uint8_t");
1420     // Force the user to pack the depth/stencil attachment last.
1421     ASSERT(!hasDepthStencilAttachment());
1422 
1423     // Use NONE as a flag for gaps in GL color attachments.
1424     uint8_t &packedFormat = mAttachmentFormats[colorIndexGL];
1425     SetBitField(packedFormat, angle::FormatID::NONE);
1426 }
1427 
packDepthStencilAttachment(angle::FormatID formatID)1428 void RenderPassDesc::packDepthStencilAttachment(angle::FormatID formatID)
1429 {
1430     ASSERT(!hasDepthStencilAttachment());
1431 
1432     size_t index = depthStencilAttachmentIndex();
1433     ASSERT(index < mAttachmentFormats.size());
1434 
1435     uint8_t &packedFormat = mAttachmentFormats[index];
1436     SetBitField(packedFormat, formatID);
1437 }
1438 
packColorResolveAttachment(size_t colorIndexGL)1439 void RenderPassDesc::packColorResolveAttachment(size_t colorIndexGL)
1440 {
1441     ASSERT(isColorAttachmentEnabled(colorIndexGL));
1442     ASSERT(!mColorResolveAttachmentMask.test(colorIndexGL));
1443     ASSERT(mSamples > 1);
1444     mColorResolveAttachmentMask.set(colorIndexGL);
1445 }
1446 
removeColorResolveAttachment(size_t colorIndexGL)1447 void RenderPassDesc::removeColorResolveAttachment(size_t colorIndexGL)
1448 {
1449     ASSERT(mColorResolveAttachmentMask.test(colorIndexGL));
1450     mColorResolveAttachmentMask.reset(colorIndexGL);
1451 }
1452 
packColorUnresolveAttachment(size_t colorIndexGL)1453 void RenderPassDesc::packColorUnresolveAttachment(size_t colorIndexGL)
1454 {
1455     mColorUnresolveAttachmentMask.set(colorIndexGL);
1456 }
1457 
removeColorUnresolveAttachment(size_t colorIndexGL)1458 void RenderPassDesc::removeColorUnresolveAttachment(size_t colorIndexGL)
1459 {
1460     mColorUnresolveAttachmentMask.reset(colorIndexGL);
1461 }
1462 
packDepthStencilResolveAttachment()1463 void RenderPassDesc::packDepthStencilResolveAttachment()
1464 {
1465     ASSERT(hasDepthStencilAttachment());
1466     ASSERT(!hasDepthStencilResolveAttachment());
1467 
1468     mResolveDepthStencil = true;
1469 }
1470 
packDepthStencilUnresolveAttachment(bool unresolveDepth,bool unresolveStencil)1471 void RenderPassDesc::packDepthStencilUnresolveAttachment(bool unresolveDepth, bool unresolveStencil)
1472 {
1473     ASSERT(hasDepthStencilAttachment());
1474 
1475     mUnresolveDepth   = unresolveDepth;
1476     mUnresolveStencil = unresolveStencil;
1477 }
1478 
removeDepthStencilUnresolveAttachment()1479 void RenderPassDesc::removeDepthStencilUnresolveAttachment()
1480 {
1481     mUnresolveDepth   = false;
1482     mUnresolveStencil = false;
1483 }
1484 
operator =(const RenderPassDesc & other)1485 RenderPassDesc &RenderPassDesc::operator=(const RenderPassDesc &other)
1486 {
1487     memcpy(this, &other, sizeof(RenderPassDesc));
1488     return *this;
1489 }
1490 
setWriteControlMode(gl::SrgbWriteControlMode mode)1491 void RenderPassDesc::setWriteControlMode(gl::SrgbWriteControlMode mode)
1492 {
1493     SetBitField(mSrgbWriteControl, mode);
1494 }
1495 
hash() const1496 size_t RenderPassDesc::hash() const
1497 {
1498     return angle::ComputeGenericHash(*this);
1499 }
1500 
isColorAttachmentEnabled(size_t colorIndexGL) const1501 bool RenderPassDesc::isColorAttachmentEnabled(size_t colorIndexGL) const
1502 {
1503     angle::FormatID formatID = operator[](colorIndexGL);
1504     return formatID != angle::FormatID::NONE;
1505 }
1506 
hasDepthStencilAttachment() const1507 bool RenderPassDesc::hasDepthStencilAttachment() const
1508 {
1509     angle::FormatID formatID = operator[](depthStencilAttachmentIndex());
1510     return formatID != angle::FormatID::NONE;
1511 }
1512 
attachmentCount() const1513 size_t RenderPassDesc::attachmentCount() const
1514 {
1515     size_t colorAttachmentCount = 0;
1516     for (size_t i = 0; i < mColorAttachmentRange; ++i)
1517     {
1518         colorAttachmentCount += isColorAttachmentEnabled(i);
1519     }
1520 
1521     // Note that there are no gaps in depth/stencil attachments.  In fact there is a maximum of 1 of
1522     // it + 1 for its resolve attachment.
1523     size_t depthStencilCount        = hasDepthStencilAttachment() ? 1 : 0;
1524     size_t depthStencilResolveCount = hasDepthStencilResolveAttachment() ? 1 : 0;
1525     return colorAttachmentCount + mColorResolveAttachmentMask.count() + depthStencilCount +
1526            depthStencilResolveCount;
1527 }
1528 
operator ==(const RenderPassDesc & lhs,const RenderPassDesc & rhs)1529 bool operator==(const RenderPassDesc &lhs, const RenderPassDesc &rhs)
1530 {
1531     return (memcmp(&lhs, &rhs, sizeof(RenderPassDesc)) == 0);
1532 }
1533 
1534 // GraphicsPipelineDesc implementation.
1535 // Use aligned allocation and free so we can use the alignas keyword.
operator new(std::size_t size)1536 void *GraphicsPipelineDesc::operator new(std::size_t size)
1537 {
1538     return angle::AlignedAlloc(size, 32);
1539 }
1540 
operator delete(void * ptr)1541 void GraphicsPipelineDesc::operator delete(void *ptr)
1542 {
1543     return angle::AlignedFree(ptr);
1544 }
1545 
GraphicsPipelineDesc()1546 GraphicsPipelineDesc::GraphicsPipelineDesc()
1547 {
1548     memset(this, 0, sizeof(GraphicsPipelineDesc));
1549 }
1550 
1551 GraphicsPipelineDesc::~GraphicsPipelineDesc() = default;
1552 
GraphicsPipelineDesc(const GraphicsPipelineDesc & other)1553 GraphicsPipelineDesc::GraphicsPipelineDesc(const GraphicsPipelineDesc &other)
1554 {
1555     memcpy(this, &other, sizeof(GraphicsPipelineDesc));
1556 }
1557 
operator =(const GraphicsPipelineDesc & other)1558 GraphicsPipelineDesc &GraphicsPipelineDesc::operator=(const GraphicsPipelineDesc &other)
1559 {
1560     memcpy(this, &other, sizeof(GraphicsPipelineDesc));
1561     return *this;
1562 }
1563 
hash() const1564 size_t GraphicsPipelineDesc::hash() const
1565 {
1566     return angle::ComputeGenericHash(*this);
1567 }
1568 
operator ==(const GraphicsPipelineDesc & other) const1569 bool GraphicsPipelineDesc::operator==(const GraphicsPipelineDesc &other) const
1570 {
1571     return (memcmp(this, &other, sizeof(GraphicsPipelineDesc)) == 0);
1572 }
1573 
1574 // TODO(jmadill): We should prefer using Packed GLenums. http://anglebug.com/2169
1575 
1576 // Initialize PSO states, it is consistent with initial value of gl::State
initDefaults(const ContextVk * contextVk)1577 void GraphicsPipelineDesc::initDefaults(const ContextVk *contextVk)
1578 {
1579     // Set all vertex input attributes to default, the default format is Float
1580     angle::FormatID defaultFormat = GetCurrentValueFormatID(gl::VertexAttribType::Float);
1581     for (PackedAttribDesc &packedAttrib : mVertexInputAttribs.attribs)
1582     {
1583         SetBitField(packedAttrib.stride, 0);
1584         SetBitField(packedAttrib.divisor, 0);
1585         SetBitField(packedAttrib.format, defaultFormat);
1586         SetBitField(packedAttrib.compressed, 0);
1587         SetBitField(packedAttrib.offset, 0);
1588     }
1589 
1590     mRasterizationAndMultisampleStateInfo.bits.subpass = 0;
1591     mRasterizationAndMultisampleStateInfo.bits.depthClampEnable =
1592         contextVk->getFeatures().depthClamping.enabled ? VK_TRUE : VK_FALSE;
1593     mRasterizationAndMultisampleStateInfo.bits.rasterizationDiscardEnable = 0;
1594     SetBitField(mRasterizationAndMultisampleStateInfo.bits.polygonMode, VK_POLYGON_MODE_FILL);
1595     SetBitField(mRasterizationAndMultisampleStateInfo.bits.cullMode, VK_CULL_MODE_BACK_BIT);
1596     SetBitField(mRasterizationAndMultisampleStateInfo.bits.frontFace,
1597                 VK_FRONT_FACE_COUNTER_CLOCKWISE);
1598     mRasterizationAndMultisampleStateInfo.bits.depthBiasEnable    = 0;
1599     mRasterizationAndMultisampleStateInfo.depthBiasConstantFactor = 0.0f;
1600     mRasterizationAndMultisampleStateInfo.depthBiasClamp          = 0.0f;
1601     mRasterizationAndMultisampleStateInfo.depthBiasSlopeFactor    = 0.0f;
1602     mRasterizationAndMultisampleStateInfo.lineWidth               = 1.0f;
1603 
1604     mRasterizationAndMultisampleStateInfo.bits.rasterizationSamples = 1;
1605     mRasterizationAndMultisampleStateInfo.bits.sampleShadingEnable  = 0;
1606     mRasterizationAndMultisampleStateInfo.minSampleShading          = 1.0f;
1607     for (uint32_t &sampleMask : mRasterizationAndMultisampleStateInfo.sampleMask)
1608     {
1609         sampleMask = 0xFFFFFFFF;
1610     }
1611     mRasterizationAndMultisampleStateInfo.bits.alphaToCoverageEnable = 0;
1612     mRasterizationAndMultisampleStateInfo.bits.alphaToOneEnable      = 0;
1613 
1614     mDepthStencilStateInfo.enable.depthTest  = 0;
1615     mDepthStencilStateInfo.enable.depthWrite = 1;
1616     SetBitField(mDepthStencilStateInfo.depthCompareOpAndSurfaceRotation.depthCompareOp,
1617                 VK_COMPARE_OP_LESS);
1618     mDepthStencilStateInfo.enable.depthBoundsTest = 0;
1619     mDepthStencilStateInfo.enable.stencilTest     = 0;
1620     mDepthStencilStateInfo.minDepthBounds         = 0.0f;
1621     mDepthStencilStateInfo.maxDepthBounds         = 0.0f;
1622     SetBitField(mDepthStencilStateInfo.front.ops.fail, VK_STENCIL_OP_KEEP);
1623     SetBitField(mDepthStencilStateInfo.front.ops.pass, VK_STENCIL_OP_KEEP);
1624     SetBitField(mDepthStencilStateInfo.front.ops.depthFail, VK_STENCIL_OP_KEEP);
1625     SetBitField(mDepthStencilStateInfo.front.ops.compare, VK_COMPARE_OP_ALWAYS);
1626     SetBitField(mDepthStencilStateInfo.front.compareMask, 0xFF);
1627     SetBitField(mDepthStencilStateInfo.front.writeMask, 0xFF);
1628     mDepthStencilStateInfo.frontStencilReference = 0;
1629     SetBitField(mDepthStencilStateInfo.back.ops.fail, VK_STENCIL_OP_KEEP);
1630     SetBitField(mDepthStencilStateInfo.back.ops.pass, VK_STENCIL_OP_KEEP);
1631     SetBitField(mDepthStencilStateInfo.back.ops.depthFail, VK_STENCIL_OP_KEEP);
1632     SetBitField(mDepthStencilStateInfo.back.ops.compare, VK_COMPARE_OP_ALWAYS);
1633     SetBitField(mDepthStencilStateInfo.back.compareMask, 0xFF);
1634     SetBitField(mDepthStencilStateInfo.back.writeMask, 0xFF);
1635     mDepthStencilStateInfo.backStencilReference = 0;
1636 
1637     mDepthStencilStateInfo.depthCompareOpAndSurfaceRotation.surfaceRotation =
1638         static_cast<uint8_t>(SurfaceRotation::Identity);
1639 
1640     PackedInputAssemblyAndColorBlendStateInfo &inputAndBlend = mInputAssemblyAndColorBlendStateInfo;
1641     inputAndBlend.logic.opEnable                             = 0;
1642     inputAndBlend.logic.op          = static_cast<uint32_t>(VK_LOGIC_OP_CLEAR);
1643     inputAndBlend.blendEnableMask   = 0;
1644     inputAndBlend.blendConstants[0] = 0.0f;
1645     inputAndBlend.blendConstants[1] = 0.0f;
1646     inputAndBlend.blendConstants[2] = 0.0f;
1647     inputAndBlend.blendConstants[3] = 0.0f;
1648 
1649     VkFlags allColorBits = (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
1650                             VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
1651 
1652     for (uint32_t colorIndexGL = 0; colorIndexGL < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
1653          ++colorIndexGL)
1654     {
1655         Int4Array_Set(inputAndBlend.colorWriteMaskBits, colorIndexGL, allColorBits);
1656     }
1657 
1658     PackedColorBlendAttachmentState blendAttachmentState;
1659     SetBitField(blendAttachmentState.srcColorBlendFactor, VK_BLEND_FACTOR_ONE);
1660     SetBitField(blendAttachmentState.dstColorBlendFactor, VK_BLEND_FACTOR_ZERO);
1661     SetBitField(blendAttachmentState.colorBlendOp, VK_BLEND_OP_ADD);
1662     SetBitField(blendAttachmentState.srcAlphaBlendFactor, VK_BLEND_FACTOR_ONE);
1663     SetBitField(blendAttachmentState.dstAlphaBlendFactor, VK_BLEND_FACTOR_ZERO);
1664     SetBitField(blendAttachmentState.alphaBlendOp, VK_BLEND_OP_ADD);
1665 
1666     std::fill(&inputAndBlend.attachments[0],
1667               &inputAndBlend.attachments[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS],
1668               blendAttachmentState);
1669 
1670     SetBitField(inputAndBlend.primitive.topology, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
1671     SetBitField(inputAndBlend.primitive.patchVertices, 3);
1672     inputAndBlend.primitive.restartEnable = 0;
1673 
1674     mDrawableSize.width  = 1;
1675     mDrawableSize.height = 1;
1676 }
1677 
initializePipeline(ContextVk * contextVk,const PipelineCache & pipelineCacheVk,const RenderPass & compatibleRenderPass,const PipelineLayout & pipelineLayout,const gl::AttributesMask & activeAttribLocationsMask,const gl::ComponentTypeMask & programAttribsTypeMask,const ShaderModule * vertexModule,const ShaderModule * fragmentModule,const ShaderModule * geometryModule,const ShaderModule * tessControlModule,const ShaderModule * tessEvaluationModule,const SpecializationConstants & specConsts,Pipeline * pipelineOut) const1678 angle::Result GraphicsPipelineDesc::initializePipeline(
1679     ContextVk *contextVk,
1680     const PipelineCache &pipelineCacheVk,
1681     const RenderPass &compatibleRenderPass,
1682     const PipelineLayout &pipelineLayout,
1683     const gl::AttributesMask &activeAttribLocationsMask,
1684     const gl::ComponentTypeMask &programAttribsTypeMask,
1685     const ShaderModule *vertexModule,
1686     const ShaderModule *fragmentModule,
1687     const ShaderModule *geometryModule,
1688     const ShaderModule *tessControlModule,
1689     const ShaderModule *tessEvaluationModule,
1690     const SpecializationConstants &specConsts,
1691     Pipeline *pipelineOut) const
1692 {
1693     angle::FixedVector<VkPipelineShaderStageCreateInfo, 5> shaderStages;
1694     VkPipelineVertexInputStateCreateInfo vertexInputState     = {};
1695     VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = {};
1696     VkPipelineViewportStateCreateInfo viewportState           = {};
1697     VkPipelineRasterizationStateCreateInfo rasterState        = {};
1698     VkPipelineMultisampleStateCreateInfo multisampleState     = {};
1699     VkPipelineDepthStencilStateCreateInfo depthStencilState   = {};
1700     gl::DrawBuffersArray<VkPipelineColorBlendAttachmentState> blendAttachmentState;
1701     VkPipelineTessellationStateCreateInfo tessellationState             = {};
1702     VkPipelineTessellationDomainOriginStateCreateInfo domainOriginState = {};
1703     VkPipelineColorBlendStateCreateInfo blendState                      = {};
1704     VkSpecializationInfo specializationInfo                             = {};
1705     VkGraphicsPipelineCreateInfo createInfo                             = {};
1706 
1707     SpecializationConstantMap<VkSpecializationMapEntry> specializationEntries;
1708     InitializeSpecializationInfo(specConsts, &specializationEntries, &specializationInfo);
1709 
1710     // Vertex shader is always expected to be present.
1711     ASSERT(vertexModule != nullptr);
1712     VkPipelineShaderStageCreateInfo vertexStage = {};
1713     SetPipelineShaderStageInfo(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1714                                VK_SHADER_STAGE_VERTEX_BIT, vertexModule->getHandle(),
1715                                specializationInfo, &vertexStage);
1716     shaderStages.push_back(vertexStage);
1717 
1718     if (tessControlModule)
1719     {
1720         VkPipelineShaderStageCreateInfo tessControlStage = {};
1721         SetPipelineShaderStageInfo(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1722                                    VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
1723                                    tessControlModule->getHandle(), specializationInfo,
1724                                    &tessControlStage);
1725         shaderStages.push_back(tessControlStage);
1726     }
1727 
1728     if (tessEvaluationModule)
1729     {
1730         VkPipelineShaderStageCreateInfo tessEvaluationStage = {};
1731         SetPipelineShaderStageInfo(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1732                                    VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1733                                    tessEvaluationModule->getHandle(), specializationInfo,
1734                                    &tessEvaluationStage);
1735         shaderStages.push_back(tessEvaluationStage);
1736     }
1737 
1738     if (geometryModule)
1739     {
1740         VkPipelineShaderStageCreateInfo geometryStage = {};
1741         SetPipelineShaderStageInfo(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1742                                    VK_SHADER_STAGE_GEOMETRY_BIT, geometryModule->getHandle(),
1743                                    specializationInfo, &geometryStage);
1744         shaderStages.push_back(geometryStage);
1745     }
1746 
1747     // Fragment shader is optional.
1748     // anglebug.com/3509 - Don't compile the fragment shader if rasterizationDiscardEnable = true
1749     if (fragmentModule && !mRasterizationAndMultisampleStateInfo.bits.rasterizationDiscardEnable)
1750     {
1751         VkPipelineShaderStageCreateInfo fragmentStage = {};
1752         SetPipelineShaderStageInfo(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1753                                    VK_SHADER_STAGE_FRAGMENT_BIT, fragmentModule->getHandle(),
1754                                    specializationInfo, &fragmentStage);
1755         shaderStages.push_back(fragmentStage);
1756     }
1757 
1758     // TODO(jmadill): Possibly use different path for ES 3.1 split bindings/attribs.
1759     gl::AttribArray<VkVertexInputBindingDescription> bindingDescs;
1760     gl::AttribArray<VkVertexInputAttributeDescription> attributeDescs;
1761 
1762     uint32_t vertexAttribCount = 0;
1763 
1764     size_t unpackedSize = sizeof(shaderStages) + sizeof(vertexInputState) +
1765                           sizeof(inputAssemblyState) + sizeof(viewportState) + sizeof(rasterState) +
1766                           sizeof(multisampleState) + sizeof(depthStencilState) +
1767                           sizeof(tessellationState) + sizeof(blendAttachmentState) +
1768                           sizeof(blendState) + sizeof(bindingDescs) + sizeof(attributeDescs);
1769     ANGLE_UNUSED_VARIABLE(unpackedSize);
1770 
1771     gl::AttribArray<VkVertexInputBindingDivisorDescriptionEXT> divisorDesc;
1772     VkPipelineVertexInputDivisorStateCreateInfoEXT divisorState = {};
1773     divisorState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
1774     divisorState.pVertexBindingDivisors = divisorDesc.data();
1775     for (size_t attribIndexSizeT : activeAttribLocationsMask)
1776     {
1777         const uint32_t attribIndex = static_cast<uint32_t>(attribIndexSizeT);
1778 
1779         VkVertexInputBindingDescription &bindingDesc  = bindingDescs[vertexAttribCount];
1780         VkVertexInputAttributeDescription &attribDesc = attributeDescs[vertexAttribCount];
1781         const PackedAttribDesc &packedAttrib          = mVertexInputAttribs.attribs[attribIndex];
1782 
1783         bindingDesc.binding = attribIndex;
1784         bindingDesc.stride  = static_cast<uint32_t>(packedAttrib.stride);
1785         if (packedAttrib.divisor != 0)
1786         {
1787             bindingDesc.inputRate = static_cast<VkVertexInputRate>(VK_VERTEX_INPUT_RATE_INSTANCE);
1788             divisorDesc[divisorState.vertexBindingDivisorCount].binding = bindingDesc.binding;
1789             divisorDesc[divisorState.vertexBindingDivisorCount].divisor = packedAttrib.divisor;
1790             ++divisorState.vertexBindingDivisorCount;
1791         }
1792         else
1793         {
1794             bindingDesc.inputRate = static_cast<VkVertexInputRate>(VK_VERTEX_INPUT_RATE_VERTEX);
1795         }
1796 
1797         // Get the corresponding VkFormat for the attrib's format.
1798         angle::FormatID formatID         = static_cast<angle::FormatID>(packedAttrib.format);
1799         const Format &format             = contextVk->getRenderer()->getFormat(formatID);
1800         const angle::Format &angleFormat = format.intendedFormat();
1801         VkFormat vkFormat                = format.actualBufferVkFormat(packedAttrib.compressed);
1802 
1803         gl::ComponentType attribType =
1804             GetVertexAttributeComponentType(angleFormat.isPureInt(), angleFormat.vertexAttribType);
1805         gl::ComponentType programAttribType =
1806             gl::GetComponentTypeMask(programAttribsTypeMask, attribIndex);
1807 
1808         // This forces stride to 0 when glVertexAttribute specifies a different type from the
1809         // program's attribute type except when the type mismatch is a mismatched integer sign.
1810         if (attribType != programAttribType)
1811         {
1812             if (attribType == gl::ComponentType::Float ||
1813                 programAttribType == gl::ComponentType::Float)
1814             {
1815                 // When dealing with float to int or unsigned int or vice versa, just override the
1816                 // format with a compatible one.
1817                 vkFormat = kMismatchedComponentTypeMap[programAttribType];
1818             }
1819             else
1820             {
1821                 // When converting from an unsigned to a signed format or vice versa, attempt to
1822                 // match the bit width.
1823                 angle::FormatID convertedFormatID = gl::ConvertFormatSignedness(angleFormat);
1824                 const Format &convertedFormat =
1825                     contextVk->getRenderer()->getFormat(convertedFormatID);
1826                 ASSERT(angleFormat.channelCount == convertedFormat.intendedFormat().channelCount);
1827                 ASSERT(angleFormat.redBits == convertedFormat.intendedFormat().redBits);
1828                 ASSERT(angleFormat.greenBits == convertedFormat.intendedFormat().greenBits);
1829                 ASSERT(angleFormat.blueBits == convertedFormat.intendedFormat().blueBits);
1830                 ASSERT(angleFormat.alphaBits == convertedFormat.intendedFormat().alphaBits);
1831 
1832                 vkFormat = convertedFormat.actualBufferVkFormat(packedAttrib.compressed);
1833             }
1834 
1835             GLenum programAttributeType =
1836                 contextVk->getState().getProgramExecutable()->getProgramInputs()[attribIndex].type;
1837             GLuint attribSize = gl::GetVertexFormatFromID(formatID).components;
1838             GLuint shaderVarSize =
1839                 static_cast<GLuint>(gl::VariableColumnCount(programAttributeType));
1840 
1841             ASSERT(contextVk->getNativeExtensions().relaxedVertexAttributeTypeANGLE);
1842             if (programAttribType == gl::ComponentType::Float ||
1843                 attribType == gl::ComponentType::Float || attribSize != shaderVarSize)
1844             {
1845                 bindingDesc.stride = 0;  // Prevent out-of-bounds accesses.
1846             }
1847         }
1848 
1849         // The binding index could become more dynamic in ES 3.1.
1850         attribDesc.binding  = attribIndex;
1851         attribDesc.format   = vkFormat;
1852         attribDesc.location = static_cast<uint32_t>(attribIndex);
1853         attribDesc.offset   = packedAttrib.offset;
1854 
1855         vertexAttribCount++;
1856     }
1857 
1858     // The binding descriptions are filled in at draw time.
1859     vertexInputState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
1860     vertexInputState.flags = 0;
1861     vertexInputState.vertexBindingDescriptionCount   = vertexAttribCount;
1862     vertexInputState.pVertexBindingDescriptions      = bindingDescs.data();
1863     vertexInputState.vertexAttributeDescriptionCount = vertexAttribCount;
1864     vertexInputState.pVertexAttributeDescriptions    = attributeDescs.data();
1865     if (divisorState.vertexBindingDivisorCount)
1866         vertexInputState.pNext = &divisorState;
1867 
1868     // Primitive topology is filled in at draw time.
1869     inputAssemblyState.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
1870     inputAssemblyState.flags = 0;
1871     inputAssemblyState.topology =
1872         static_cast<VkPrimitiveTopology>(mInputAssemblyAndColorBlendStateInfo.primitive.topology);
1873     // http://anglebug.com/3832
1874     // We currently hit a VK Validation here where VUID
1875     // VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00428 is flagged because we allow
1876     // primitiveRestartEnable to be true for topologies VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
1877     // VK_PRIMITIVE_TOPOLOGY_LINE_LIST, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
1878     // VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,
1879     // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY and VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
1880     // However if we force primiteRestartEnable to FALSE we fail tests.
1881     // Need to identify alternate fix.
1882     inputAssemblyState.primitiveRestartEnable =
1883         static_cast<VkBool32>(mInputAssemblyAndColorBlendStateInfo.primitive.restartEnable);
1884 
1885     // Set initial viewport and scissor state.
1886     viewportState.sType         = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
1887     viewportState.flags         = 0;
1888     viewportState.viewportCount = 1;
1889     viewportState.pViewports    = nullptr;
1890     viewportState.scissorCount  = 1;
1891     viewportState.pScissors     = nullptr;
1892 
1893     const PackedRasterizationAndMultisampleStateInfo &rasterAndMS =
1894         mRasterizationAndMultisampleStateInfo;
1895 
1896     // Rasterizer state.
1897     rasterState.sType            = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
1898     rasterState.flags            = 0;
1899     rasterState.depthClampEnable = static_cast<VkBool32>(rasterAndMS.bits.depthClampEnable);
1900     rasterState.rasterizerDiscardEnable =
1901         static_cast<VkBool32>(rasterAndMS.bits.rasterizationDiscardEnable);
1902     rasterState.polygonMode             = static_cast<VkPolygonMode>(rasterAndMS.bits.polygonMode);
1903     rasterState.cullMode                = static_cast<VkCullModeFlags>(rasterAndMS.bits.cullMode);
1904     rasterState.frontFace               = static_cast<VkFrontFace>(rasterAndMS.bits.frontFace);
1905     rasterState.depthBiasEnable         = static_cast<VkBool32>(rasterAndMS.bits.depthBiasEnable);
1906     rasterState.depthBiasConstantFactor = rasterAndMS.depthBiasConstantFactor;
1907     rasterState.depthBiasClamp          = rasterAndMS.depthBiasClamp;
1908     rasterState.depthBiasSlopeFactor    = rasterAndMS.depthBiasSlopeFactor;
1909     rasterState.lineWidth               = rasterAndMS.lineWidth;
1910     const void **pNextPtr               = &rasterState.pNext;
1911 
1912     VkPipelineRasterizationLineStateCreateInfoEXT rasterLineState = {};
1913     rasterLineState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT;
1914     // Enable Bresenham line rasterization if available and the following conditions are met:
1915     // 1.) not multisampling
1916     // 2.) VUID-VkGraphicsPipelineCreateInfo-lineRasterizationMode-02766:
1917     // The Vulkan spec states: If the lineRasterizationMode member of a
1918     // VkPipelineRasterizationLineStateCreateInfoEXT structure included in the pNext chain of
1919     // pRasterizationState is VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT or
1920     // VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT and if rasterization is enabled, then the
1921     // alphaToCoverageEnable, alphaToOneEnable, and sampleShadingEnable members of pMultisampleState
1922     // must all be VK_FALSE.
1923     if (rasterAndMS.bits.rasterizationSamples <= 1 &&
1924         !rasterAndMS.bits.rasterizationDiscardEnable && !rasterAndMS.bits.alphaToCoverageEnable &&
1925         !rasterAndMS.bits.alphaToOneEnable && !rasterAndMS.bits.sampleShadingEnable &&
1926         contextVk->getFeatures().bresenhamLineRasterization.enabled)
1927     {
1928         rasterLineState.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;
1929         *pNextPtr                             = &rasterLineState;
1930         pNextPtr                              = &rasterLineState.pNext;
1931     }
1932 
1933     VkPipelineRasterizationProvokingVertexStateCreateInfoEXT provokingVertexState = {};
1934     provokingVertexState.sType =
1935         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT;
1936     // Always set provoking vertex mode to last if available.
1937     if (contextVk->getFeatures().provokingVertex.enabled)
1938     {
1939         provokingVertexState.provokingVertexMode = VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT;
1940         *pNextPtr                                = &provokingVertexState;
1941         pNextPtr                                 = &provokingVertexState.pNext;
1942     }
1943 
1944     // When depth clamping is used, depth clipping is automatically disabled.
1945     // When the 'depthClamping' feature is enabled, we'll be using depth clamping
1946     // to work around a driver issue, not as an alternative to depth clipping. Therefore we need to
1947     // explicitly re-enable depth clipping.
1948     VkPipelineRasterizationDepthClipStateCreateInfoEXT depthClipState = {};
1949     depthClipState.sType =
1950         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT;
1951     if (contextVk->getFeatures().depthClamping.enabled)
1952     {
1953         depthClipState.depthClipEnable = VK_TRUE;
1954         *pNextPtr                      = &depthClipState;
1955         pNextPtr                       = &depthClipState.pNext;
1956     }
1957 
1958     VkPipelineRasterizationStateStreamCreateInfoEXT rasterStreamState = {};
1959     rasterStreamState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT;
1960     if (contextVk->getFeatures().supportsTransformFeedbackExtension.enabled)
1961     {
1962         rasterStreamState.rasterizationStream = 0;
1963         *pNextPtr                             = &rasterStreamState;
1964         pNextPtr                              = &rasterStreamState.pNext;
1965     }
1966 
1967     // Multisample state.
1968     multisampleState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
1969     multisampleState.flags = 0;
1970     multisampleState.rasterizationSamples =
1971         gl_vk::GetSamples(rasterAndMS.bits.rasterizationSamples);
1972     multisampleState.sampleShadingEnable =
1973         static_cast<VkBool32>(rasterAndMS.bits.sampleShadingEnable);
1974     multisampleState.minSampleShading = rasterAndMS.minSampleShading;
1975     multisampleState.pSampleMask      = rasterAndMS.sampleMask;
1976     multisampleState.alphaToCoverageEnable =
1977         static_cast<VkBool32>(rasterAndMS.bits.alphaToCoverageEnable);
1978     multisampleState.alphaToOneEnable = static_cast<VkBool32>(rasterAndMS.bits.alphaToOneEnable);
1979 
1980     // Depth/stencil state.
1981     depthStencilState.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
1982     depthStencilState.flags = 0;
1983     depthStencilState.depthTestEnable =
1984         static_cast<VkBool32>(mDepthStencilStateInfo.enable.depthTest);
1985     depthStencilState.depthWriteEnable =
1986         static_cast<VkBool32>(mDepthStencilStateInfo.enable.depthWrite);
1987     depthStencilState.depthCompareOp = static_cast<VkCompareOp>(
1988         mDepthStencilStateInfo.depthCompareOpAndSurfaceRotation.depthCompareOp);
1989     depthStencilState.depthBoundsTestEnable =
1990         static_cast<VkBool32>(mDepthStencilStateInfo.enable.depthBoundsTest);
1991     depthStencilState.stencilTestEnable =
1992         static_cast<VkBool32>(mDepthStencilStateInfo.enable.stencilTest);
1993     UnpackStencilState(mDepthStencilStateInfo.front, mDepthStencilStateInfo.frontStencilReference,
1994                        &depthStencilState.front);
1995     UnpackStencilState(mDepthStencilStateInfo.back, mDepthStencilStateInfo.backStencilReference,
1996                        &depthStencilState.back);
1997     depthStencilState.minDepthBounds = mDepthStencilStateInfo.minDepthBounds;
1998     depthStencilState.maxDepthBounds = mDepthStencilStateInfo.maxDepthBounds;
1999 
2000     const PackedInputAssemblyAndColorBlendStateInfo &inputAndBlend =
2001         mInputAssemblyAndColorBlendStateInfo;
2002 
2003     blendState.sType           = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
2004     blendState.flags           = 0;
2005     blendState.logicOpEnable   = static_cast<VkBool32>(inputAndBlend.logic.opEnable);
2006     blendState.logicOp         = static_cast<VkLogicOp>(inputAndBlend.logic.op);
2007     blendState.attachmentCount = static_cast<uint32_t>(mRenderPassDesc.colorAttachmentRange());
2008     blendState.pAttachments    = blendAttachmentState.data();
2009 
2010     // If this graphics pipeline is for the unresolve operation, correct the color attachment count
2011     // for that subpass.
2012     if ((mRenderPassDesc.getColorUnresolveAttachmentMask().any() ||
2013          mRenderPassDesc.hasDepthStencilUnresolveAttachment()) &&
2014         mRasterizationAndMultisampleStateInfo.bits.subpass == 0)
2015     {
2016         blendState.attachmentCount =
2017             static_cast<uint32_t>(mRenderPassDesc.getColorUnresolveAttachmentMask().count());
2018     }
2019 
2020     for (int i = 0; i < 4; i++)
2021     {
2022         blendState.blendConstants[i] = inputAndBlend.blendConstants[i];
2023     }
2024 
2025     const gl::DrawBufferMask blendEnableMask(inputAndBlend.blendEnableMask);
2026 
2027     // Zero-init all states.
2028     blendAttachmentState = {};
2029 
2030     for (uint32_t colorIndexGL = 0; colorIndexGL < blendState.attachmentCount; ++colorIndexGL)
2031     {
2032         VkPipelineColorBlendAttachmentState &state = blendAttachmentState[colorIndexGL];
2033 
2034         if (blendEnableMask[colorIndexGL])
2035         {
2036             // To avoid triggering valid usage error, blending must be disabled for formats that do
2037             // not have VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT feature bit set.
2038             // From OpenGL ES clients, this means disabling blending for integer formats.
2039             if (!angle::Format::Get(mRenderPassDesc[colorIndexGL]).isInt())
2040             {
2041                 ASSERT(!contextVk->getRenderer()
2042                             ->getFormat(mRenderPassDesc[colorIndexGL])
2043                             .actualImageFormat()
2044                             .isInt());
2045                 state.blendEnable = VK_TRUE;
2046                 UnpackBlendAttachmentState(inputAndBlend.attachments[colorIndexGL], &state);
2047             }
2048         }
2049         state.colorWriteMask =
2050             Int4Array_Get<VkColorComponentFlags>(inputAndBlend.colorWriteMaskBits, colorIndexGL);
2051     }
2052 
2053     // Dynamic state
2054     angle::FixedVector<VkDynamicState, 2> dynamicStateList;
2055     dynamicStateList.push_back(VK_DYNAMIC_STATE_VIEWPORT);
2056     dynamicStateList.push_back(VK_DYNAMIC_STATE_SCISSOR);
2057 
2058     VkPipelineDynamicStateCreateInfo dynamicState = {};
2059     dynamicState.sType             = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
2060     dynamicState.dynamicStateCount = static_cast<uint32_t>(dynamicStateList.size());
2061     dynamicState.pDynamicStates    = dynamicStateList.data();
2062 
2063     // tessellation State
2064     if (tessControlModule && tessEvaluationModule)
2065     {
2066         domainOriginState.sType =
2067             VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO;
2068         domainOriginState.pNext        = NULL;
2069         domainOriginState.domainOrigin = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT;
2070 
2071         tessellationState.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
2072         tessellationState.flags = 0;
2073         tessellationState.pNext = &domainOriginState;
2074         tessellationState.patchControlPoints =
2075             static_cast<uint32_t>(inputAndBlend.primitive.patchVertices);
2076     }
2077 
2078     createInfo.sType               = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
2079     createInfo.flags               = 0;
2080     createInfo.stageCount          = static_cast<uint32_t>(shaderStages.size());
2081     createInfo.pStages             = shaderStages.data();
2082     createInfo.pVertexInputState   = &vertexInputState;
2083     createInfo.pInputAssemblyState = &inputAssemblyState;
2084     createInfo.pTessellationState  = &tessellationState;
2085     createInfo.pViewportState      = &viewportState;
2086     createInfo.pRasterizationState = &rasterState;
2087     createInfo.pMultisampleState   = &multisampleState;
2088     createInfo.pDepthStencilState  = &depthStencilState;
2089     createInfo.pColorBlendState    = &blendState;
2090     createInfo.pDynamicState       = dynamicStateList.empty() ? nullptr : &dynamicState;
2091     createInfo.layout              = pipelineLayout.getHandle();
2092     createInfo.renderPass          = compatibleRenderPass.getHandle();
2093     createInfo.subpass             = mRasterizationAndMultisampleStateInfo.bits.subpass;
2094     createInfo.basePipelineHandle  = VK_NULL_HANDLE;
2095     createInfo.basePipelineIndex   = 0;
2096 
2097     ANGLE_VK_TRY(contextVk,
2098                  pipelineOut->initGraphics(contextVk->getDevice(), createInfo, pipelineCacheVk));
2099     return angle::Result::Continue;
2100 }
2101 
updateVertexInput(GraphicsPipelineTransitionBits * transition,uint32_t attribIndex,GLuint stride,GLuint divisor,angle::FormatID format,bool compressed,GLuint relativeOffset)2102 void GraphicsPipelineDesc::updateVertexInput(GraphicsPipelineTransitionBits *transition,
2103                                              uint32_t attribIndex,
2104                                              GLuint stride,
2105                                              GLuint divisor,
2106                                              angle::FormatID format,
2107                                              bool compressed,
2108                                              GLuint relativeOffset)
2109 {
2110     PackedAttribDesc &packedAttrib = mVertexInputAttribs.attribs[attribIndex];
2111 
2112     SetBitField(packedAttrib.stride, stride);
2113     SetBitField(packedAttrib.divisor, divisor);
2114 
2115     if (format == angle::FormatID::NONE)
2116     {
2117         UNIMPLEMENTED();
2118     }
2119 
2120     SetBitField(packedAttrib.format, format);
2121     SetBitField(packedAttrib.compressed, compressed);
2122     SetBitField(packedAttrib.offset, relativeOffset);
2123 
2124     constexpr size_t kAttribBits = kPackedAttribDescSize * kBitsPerByte;
2125     const size_t kBit =
2126         ANGLE_GET_INDEXED_TRANSITION_BIT(mVertexInputAttribs, attribs, attribIndex, kAttribBits);
2127 
2128     // Cover the next dirty bit conservatively. Because each attribute is 6 bytes.
2129     transition->set(kBit);
2130     transition->set(kBit + 1);
2131 }
2132 
updateTopology(GraphicsPipelineTransitionBits * transition,gl::PrimitiveMode drawMode)2133 void GraphicsPipelineDesc::updateTopology(GraphicsPipelineTransitionBits *transition,
2134                                           gl::PrimitiveMode drawMode)
2135 {
2136     VkPrimitiveTopology vkTopology = gl_vk::GetPrimitiveTopology(drawMode);
2137     SetBitField(mInputAssemblyAndColorBlendStateInfo.primitive.topology, vkTopology);
2138 
2139     transition->set(ANGLE_GET_TRANSITION_BIT(mInputAssemblyAndColorBlendStateInfo, primitive));
2140 }
2141 
updatePrimitiveRestartEnabled(GraphicsPipelineTransitionBits * transition,bool primitiveRestartEnabled)2142 void GraphicsPipelineDesc::updatePrimitiveRestartEnabled(GraphicsPipelineTransitionBits *transition,
2143                                                          bool primitiveRestartEnabled)
2144 {
2145     mInputAssemblyAndColorBlendStateInfo.primitive.restartEnable =
2146         static_cast<uint16_t>(primitiveRestartEnabled);
2147     transition->set(ANGLE_GET_TRANSITION_BIT(mInputAssemblyAndColorBlendStateInfo, primitive));
2148 }
2149 
setCullMode(VkCullModeFlagBits cullMode)2150 void GraphicsPipelineDesc::setCullMode(VkCullModeFlagBits cullMode)
2151 {
2152     SetBitField(mRasterizationAndMultisampleStateInfo.bits.cullMode, cullMode);
2153 }
2154 
updateCullMode(GraphicsPipelineTransitionBits * transition,const gl::RasterizerState & rasterState)2155 void GraphicsPipelineDesc::updateCullMode(GraphicsPipelineTransitionBits *transition,
2156                                           const gl::RasterizerState &rasterState)
2157 {
2158     setCullMode(gl_vk::GetCullMode(rasterState));
2159     transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, bits));
2160 }
2161 
updateFrontFace(GraphicsPipelineTransitionBits * transition,const gl::RasterizerState & rasterState,bool invertFrontFace)2162 void GraphicsPipelineDesc::updateFrontFace(GraphicsPipelineTransitionBits *transition,
2163                                            const gl::RasterizerState &rasterState,
2164                                            bool invertFrontFace)
2165 {
2166     mRasterizationAndMultisampleStateInfo.bits.frontFace =
2167         static_cast<uint16_t>(gl_vk::GetFrontFace(rasterState.frontFace, invertFrontFace));
2168     transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, bits));
2169 }
2170 
updateLineWidth(GraphicsPipelineTransitionBits * transition,float lineWidth)2171 void GraphicsPipelineDesc::updateLineWidth(GraphicsPipelineTransitionBits *transition,
2172                                            float lineWidth)
2173 {
2174     mRasterizationAndMultisampleStateInfo.lineWidth = lineWidth;
2175     transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, lineWidth));
2176 }
2177 
updateRasterizerDiscardEnabled(GraphicsPipelineTransitionBits * transition,bool rasterizerDiscardEnabled)2178 void GraphicsPipelineDesc::updateRasterizerDiscardEnabled(
2179     GraphicsPipelineTransitionBits *transition,
2180     bool rasterizerDiscardEnabled)
2181 {
2182     mRasterizationAndMultisampleStateInfo.bits.rasterizationDiscardEnable =
2183         static_cast<uint32_t>(rasterizerDiscardEnabled);
2184     transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, bits));
2185 }
2186 
getRasterizationSamples() const2187 uint32_t GraphicsPipelineDesc::getRasterizationSamples() const
2188 {
2189     return mRasterizationAndMultisampleStateInfo.bits.rasterizationSamples;
2190 }
2191 
setRasterizationSamples(uint32_t rasterizationSamples)2192 void GraphicsPipelineDesc::setRasterizationSamples(uint32_t rasterizationSamples)
2193 {
2194     mRasterizationAndMultisampleStateInfo.bits.rasterizationSamples = rasterizationSamples;
2195 }
2196 
updateRasterizationSamples(GraphicsPipelineTransitionBits * transition,uint32_t rasterizationSamples)2197 void GraphicsPipelineDesc::updateRasterizationSamples(GraphicsPipelineTransitionBits *transition,
2198                                                       uint32_t rasterizationSamples)
2199 {
2200     setRasterizationSamples(rasterizationSamples);
2201     transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, bits));
2202 }
2203 
updateAlphaToCoverageEnable(GraphicsPipelineTransitionBits * transition,bool enable)2204 void GraphicsPipelineDesc::updateAlphaToCoverageEnable(GraphicsPipelineTransitionBits *transition,
2205                                                        bool enable)
2206 {
2207     mRasterizationAndMultisampleStateInfo.bits.alphaToCoverageEnable = enable;
2208     transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, bits));
2209 }
2210 
updateAlphaToOneEnable(GraphicsPipelineTransitionBits * transition,bool enable)2211 void GraphicsPipelineDesc::updateAlphaToOneEnable(GraphicsPipelineTransitionBits *transition,
2212                                                   bool enable)
2213 {
2214     mRasterizationAndMultisampleStateInfo.bits.alphaToOneEnable = enable;
2215     transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, bits));
2216 }
2217 
updateSampleMask(GraphicsPipelineTransitionBits * transition,uint32_t maskNumber,uint32_t mask)2218 void GraphicsPipelineDesc::updateSampleMask(GraphicsPipelineTransitionBits *transition,
2219                                             uint32_t maskNumber,
2220                                             uint32_t mask)
2221 {
2222     ASSERT(maskNumber < gl::MAX_SAMPLE_MASK_WORDS);
2223     mRasterizationAndMultisampleStateInfo.sampleMask[maskNumber] = mask;
2224 
2225     constexpr size_t kMaskBits =
2226         sizeof(mRasterizationAndMultisampleStateInfo.sampleMask[0]) * kBitsPerByte;
2227     transition->set(ANGLE_GET_INDEXED_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo,
2228                                                      sampleMask, maskNumber, kMaskBits));
2229 }
2230 
updateSampleShading(GraphicsPipelineTransitionBits * transition,bool enable,float value)2231 void GraphicsPipelineDesc::updateSampleShading(GraphicsPipelineTransitionBits *transition,
2232                                                bool enable,
2233                                                float value)
2234 {
2235     mRasterizationAndMultisampleStateInfo.bits.sampleShadingEnable = enable;
2236     mRasterizationAndMultisampleStateInfo.minSampleShading         = (enable ? value : 1.0f);
2237 
2238     transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, bits));
2239     transition->set(
2240         ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, minSampleShading));
2241 }
2242 
updateBlendColor(GraphicsPipelineTransitionBits * transition,const gl::ColorF & color)2243 void GraphicsPipelineDesc::updateBlendColor(GraphicsPipelineTransitionBits *transition,
2244                                             const gl::ColorF &color)
2245 {
2246     mInputAssemblyAndColorBlendStateInfo.blendConstants[0] = color.red;
2247     mInputAssemblyAndColorBlendStateInfo.blendConstants[1] = color.green;
2248     mInputAssemblyAndColorBlendStateInfo.blendConstants[2] = color.blue;
2249     mInputAssemblyAndColorBlendStateInfo.blendConstants[3] = color.alpha;
2250     constexpr size_t kSize = sizeof(mInputAssemblyAndColorBlendStateInfo.blendConstants[0]) * 8;
2251 
2252     for (int index = 0; index < 4; ++index)
2253     {
2254         const size_t kBit = ANGLE_GET_INDEXED_TRANSITION_BIT(mInputAssemblyAndColorBlendStateInfo,
2255                                                              blendConstants, index, kSize);
2256         transition->set(kBit);
2257     }
2258 }
2259 
updateBlendEnabled(GraphicsPipelineTransitionBits * transition,gl::DrawBufferMask blendEnabledMask)2260 void GraphicsPipelineDesc::updateBlendEnabled(GraphicsPipelineTransitionBits *transition,
2261                                               gl::DrawBufferMask blendEnabledMask)
2262 {
2263     mInputAssemblyAndColorBlendStateInfo.blendEnableMask =
2264         static_cast<uint8_t>(blendEnabledMask.bits());
2265     transition->set(
2266         ANGLE_GET_TRANSITION_BIT(mInputAssemblyAndColorBlendStateInfo, blendEnableMask));
2267 }
2268 
updateBlendEquations(GraphicsPipelineTransitionBits * transition,const gl::BlendStateExt & blendStateExt)2269 void GraphicsPipelineDesc::updateBlendEquations(GraphicsPipelineTransitionBits *transition,
2270                                                 const gl::BlendStateExt &blendStateExt)
2271 {
2272     constexpr size_t kSize = sizeof(PackedColorBlendAttachmentState) * 8;
2273 
2274     for (size_t attachmentIndex = 0; attachmentIndex < blendStateExt.mMaxDrawBuffers;
2275          ++attachmentIndex)
2276     {
2277         PackedColorBlendAttachmentState &blendAttachmentState =
2278             mInputAssemblyAndColorBlendStateInfo.attachments[attachmentIndex];
2279         blendAttachmentState.colorBlendOp =
2280             PackGLBlendOp(blendStateExt.getEquationColorIndexed(attachmentIndex));
2281         blendAttachmentState.alphaBlendOp =
2282             PackGLBlendOp(blendStateExt.getEquationAlphaIndexed(attachmentIndex));
2283         transition->set(ANGLE_GET_INDEXED_TRANSITION_BIT(mInputAssemblyAndColorBlendStateInfo,
2284                                                          attachments, attachmentIndex, kSize));
2285     }
2286 }
2287 
updateBlendFuncs(GraphicsPipelineTransitionBits * transition,const gl::BlendStateExt & blendStateExt)2288 void GraphicsPipelineDesc::updateBlendFuncs(GraphicsPipelineTransitionBits *transition,
2289                                             const gl::BlendStateExt &blendStateExt)
2290 {
2291     constexpr size_t kSize = sizeof(PackedColorBlendAttachmentState) * 8;
2292     for (size_t attachmentIndex = 0; attachmentIndex < blendStateExt.mMaxDrawBuffers;
2293          ++attachmentIndex)
2294     {
2295         PackedColorBlendAttachmentState &blendAttachmentState =
2296             mInputAssemblyAndColorBlendStateInfo.attachments[attachmentIndex];
2297         blendAttachmentState.srcColorBlendFactor =
2298             PackGLBlendFactor(blendStateExt.getSrcColorIndexed(attachmentIndex));
2299         blendAttachmentState.dstColorBlendFactor =
2300             PackGLBlendFactor(blendStateExt.getDstColorIndexed(attachmentIndex));
2301         blendAttachmentState.srcAlphaBlendFactor =
2302             PackGLBlendFactor(blendStateExt.getSrcAlphaIndexed(attachmentIndex));
2303         blendAttachmentState.dstAlphaBlendFactor =
2304             PackGLBlendFactor(blendStateExt.getDstAlphaIndexed(attachmentIndex));
2305         transition->set(ANGLE_GET_INDEXED_TRANSITION_BIT(mInputAssemblyAndColorBlendStateInfo,
2306                                                          attachments, attachmentIndex, kSize));
2307     }
2308 }
2309 
setColorWriteMasks(gl::BlendStateExt::ColorMaskStorage::Type colorMasks,const gl::DrawBufferMask & alphaMask,const gl::DrawBufferMask & enabledDrawBuffers)2310 void GraphicsPipelineDesc::setColorWriteMasks(gl::BlendStateExt::ColorMaskStorage::Type colorMasks,
2311                                               const gl::DrawBufferMask &alphaMask,
2312                                               const gl::DrawBufferMask &enabledDrawBuffers)
2313 {
2314     PackedInputAssemblyAndColorBlendStateInfo &inputAndBlend = mInputAssemblyAndColorBlendStateInfo;
2315 
2316     for (uint32_t colorIndexGL = 0; colorIndexGL < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
2317          colorIndexGL++)
2318     {
2319         uint8_t colorMask =
2320             gl::BlendStateExt::ColorMaskStorage::GetValueIndexed(colorIndexGL, colorMasks);
2321 
2322         uint8_t mask = 0;
2323         if (enabledDrawBuffers.test(colorIndexGL))
2324         {
2325             mask = alphaMask[colorIndexGL] ? (colorMask & ~VK_COLOR_COMPONENT_A_BIT) : colorMask;
2326         }
2327         Int4Array_Set(inputAndBlend.colorWriteMaskBits, colorIndexGL, mask);
2328     }
2329 }
2330 
setSingleColorWriteMask(uint32_t colorIndexGL,VkColorComponentFlags colorComponentFlags)2331 void GraphicsPipelineDesc::setSingleColorWriteMask(uint32_t colorIndexGL,
2332                                                    VkColorComponentFlags colorComponentFlags)
2333 {
2334     PackedInputAssemblyAndColorBlendStateInfo &inputAndBlend = mInputAssemblyAndColorBlendStateInfo;
2335     uint8_t colorMask = static_cast<uint8_t>(colorComponentFlags);
2336     Int4Array_Set(inputAndBlend.colorWriteMaskBits, colorIndexGL, colorMask);
2337 }
2338 
updateColorWriteMasks(GraphicsPipelineTransitionBits * transition,gl::BlendStateExt::ColorMaskStorage::Type colorMasks,const gl::DrawBufferMask & alphaMask,const gl::DrawBufferMask & enabledDrawBuffers)2339 void GraphicsPipelineDesc::updateColorWriteMasks(
2340     GraphicsPipelineTransitionBits *transition,
2341     gl::BlendStateExt::ColorMaskStorage::Type colorMasks,
2342     const gl::DrawBufferMask &alphaMask,
2343     const gl::DrawBufferMask &enabledDrawBuffers)
2344 {
2345     setColorWriteMasks(colorMasks, alphaMask, enabledDrawBuffers);
2346 
2347     for (size_t colorIndexGL = 0; colorIndexGL < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
2348          colorIndexGL++)
2349     {
2350         transition->set(ANGLE_GET_INDEXED_TRANSITION_BIT(mInputAssemblyAndColorBlendStateInfo,
2351                                                          colorWriteMaskBits, colorIndexGL, 4));
2352     }
2353 }
2354 
setDepthTestEnabled(bool enabled)2355 void GraphicsPipelineDesc::setDepthTestEnabled(bool enabled)
2356 {
2357     mDepthStencilStateInfo.enable.depthTest = enabled;
2358 }
2359 
setDepthWriteEnabled(bool enabled)2360 void GraphicsPipelineDesc::setDepthWriteEnabled(bool enabled)
2361 {
2362     mDepthStencilStateInfo.enable.depthWrite = enabled;
2363 }
2364 
setDepthFunc(VkCompareOp op)2365 void GraphicsPipelineDesc::setDepthFunc(VkCompareOp op)
2366 {
2367     SetBitField(mDepthStencilStateInfo.depthCompareOpAndSurfaceRotation.depthCompareOp, op);
2368 }
2369 
setDepthClampEnabled(bool enabled)2370 void GraphicsPipelineDesc::setDepthClampEnabled(bool enabled)
2371 {
2372     mRasterizationAndMultisampleStateInfo.bits.depthClampEnable = enabled;
2373 }
2374 
setStencilTestEnabled(bool enabled)2375 void GraphicsPipelineDesc::setStencilTestEnabled(bool enabled)
2376 {
2377     mDepthStencilStateInfo.enable.stencilTest = enabled;
2378 }
2379 
setStencilFrontFuncs(uint8_t reference,VkCompareOp compareOp,uint8_t compareMask)2380 void GraphicsPipelineDesc::setStencilFrontFuncs(uint8_t reference,
2381                                                 VkCompareOp compareOp,
2382                                                 uint8_t compareMask)
2383 {
2384     mDepthStencilStateInfo.frontStencilReference = reference;
2385     mDepthStencilStateInfo.front.compareMask     = compareMask;
2386     SetBitField(mDepthStencilStateInfo.front.ops.compare, compareOp);
2387 }
2388 
setStencilBackFuncs(uint8_t reference,VkCompareOp compareOp,uint8_t compareMask)2389 void GraphicsPipelineDesc::setStencilBackFuncs(uint8_t reference,
2390                                                VkCompareOp compareOp,
2391                                                uint8_t compareMask)
2392 {
2393     mDepthStencilStateInfo.backStencilReference = reference;
2394     mDepthStencilStateInfo.back.compareMask     = compareMask;
2395     SetBitField(mDepthStencilStateInfo.back.ops.compare, compareOp);
2396 }
2397 
setStencilFrontOps(VkStencilOp failOp,VkStencilOp passOp,VkStencilOp depthFailOp)2398 void GraphicsPipelineDesc::setStencilFrontOps(VkStencilOp failOp,
2399                                               VkStencilOp passOp,
2400                                               VkStencilOp depthFailOp)
2401 {
2402     SetBitField(mDepthStencilStateInfo.front.ops.fail, failOp);
2403     SetBitField(mDepthStencilStateInfo.front.ops.pass, passOp);
2404     SetBitField(mDepthStencilStateInfo.front.ops.depthFail, depthFailOp);
2405 }
2406 
setStencilBackOps(VkStencilOp failOp,VkStencilOp passOp,VkStencilOp depthFailOp)2407 void GraphicsPipelineDesc::setStencilBackOps(VkStencilOp failOp,
2408                                              VkStencilOp passOp,
2409                                              VkStencilOp depthFailOp)
2410 {
2411     SetBitField(mDepthStencilStateInfo.back.ops.fail, failOp);
2412     SetBitField(mDepthStencilStateInfo.back.ops.pass, passOp);
2413     SetBitField(mDepthStencilStateInfo.back.ops.depthFail, depthFailOp);
2414 }
2415 
setStencilFrontWriteMask(uint8_t mask)2416 void GraphicsPipelineDesc::setStencilFrontWriteMask(uint8_t mask)
2417 {
2418     mDepthStencilStateInfo.front.writeMask = mask;
2419 }
2420 
setStencilBackWriteMask(uint8_t mask)2421 void GraphicsPipelineDesc::setStencilBackWriteMask(uint8_t mask)
2422 {
2423     mDepthStencilStateInfo.back.writeMask = mask;
2424 }
2425 
updateDepthTestEnabled(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState,const gl::Framebuffer * drawFramebuffer)2426 void GraphicsPipelineDesc::updateDepthTestEnabled(GraphicsPipelineTransitionBits *transition,
2427                                                   const gl::DepthStencilState &depthStencilState,
2428                                                   const gl::Framebuffer *drawFramebuffer)
2429 {
2430     // Only enable the depth test if the draw framebuffer has a depth buffer.  It's possible that
2431     // we're emulating a stencil-only buffer with a depth-stencil buffer
2432     setDepthTestEnabled(depthStencilState.depthTest && drawFramebuffer->hasDepth());
2433     transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, enable));
2434 }
2435 
updateDepthFunc(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState)2436 void GraphicsPipelineDesc::updateDepthFunc(GraphicsPipelineTransitionBits *transition,
2437                                            const gl::DepthStencilState &depthStencilState)
2438 {
2439     setDepthFunc(PackGLCompareFunc(depthStencilState.depthFunc));
2440     transition->set(
2441         ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, depthCompareOpAndSurfaceRotation));
2442 }
2443 
updateSurfaceRotation(GraphicsPipelineTransitionBits * transition,const SurfaceRotation surfaceRotation)2444 void GraphicsPipelineDesc::updateSurfaceRotation(GraphicsPipelineTransitionBits *transition,
2445                                                  const SurfaceRotation surfaceRotation)
2446 {
2447     SetBitField(mDepthStencilStateInfo.depthCompareOpAndSurfaceRotation.surfaceRotation,
2448                 surfaceRotation);
2449     transition->set(
2450         ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, depthCompareOpAndSurfaceRotation));
2451 }
2452 
updateDepthWriteEnabled(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState,const gl::Framebuffer * drawFramebuffer)2453 void GraphicsPipelineDesc::updateDepthWriteEnabled(GraphicsPipelineTransitionBits *transition,
2454                                                    const gl::DepthStencilState &depthStencilState,
2455                                                    const gl::Framebuffer *drawFramebuffer)
2456 {
2457     // Don't write to depth buffers that should not exist
2458     setDepthWriteEnabled(drawFramebuffer->hasDepth() ? depthStencilState.depthMask : false);
2459     transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, enable));
2460 }
2461 
updateStencilTestEnabled(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState,const gl::Framebuffer * drawFramebuffer)2462 void GraphicsPipelineDesc::updateStencilTestEnabled(GraphicsPipelineTransitionBits *transition,
2463                                                     const gl::DepthStencilState &depthStencilState,
2464                                                     const gl::Framebuffer *drawFramebuffer)
2465 {
2466     // Only enable the stencil test if the draw framebuffer has a stencil buffer.  It's possible
2467     // that we're emulating a depth-only buffer with a depth-stencil buffer
2468     setStencilTestEnabled(depthStencilState.stencilTest && drawFramebuffer->hasStencil());
2469     transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, enable));
2470 }
2471 
updateStencilFrontFuncs(GraphicsPipelineTransitionBits * transition,GLint ref,const gl::DepthStencilState & depthStencilState)2472 void GraphicsPipelineDesc::updateStencilFrontFuncs(GraphicsPipelineTransitionBits *transition,
2473                                                    GLint ref,
2474                                                    const gl::DepthStencilState &depthStencilState)
2475 {
2476     setStencilFrontFuncs(static_cast<uint8_t>(ref),
2477                          PackGLCompareFunc(depthStencilState.stencilFunc),
2478                          static_cast<uint8_t>(depthStencilState.stencilMask));
2479     transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, front));
2480     transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, frontStencilReference));
2481 }
2482 
updateStencilBackFuncs(GraphicsPipelineTransitionBits * transition,GLint ref,const gl::DepthStencilState & depthStencilState)2483 void GraphicsPipelineDesc::updateStencilBackFuncs(GraphicsPipelineTransitionBits *transition,
2484                                                   GLint ref,
2485                                                   const gl::DepthStencilState &depthStencilState)
2486 {
2487     setStencilBackFuncs(static_cast<uint8_t>(ref),
2488                         PackGLCompareFunc(depthStencilState.stencilBackFunc),
2489                         static_cast<uint8_t>(depthStencilState.stencilBackMask));
2490     transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, back));
2491     transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, backStencilReference));
2492 }
2493 
updateStencilFrontOps(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState)2494 void GraphicsPipelineDesc::updateStencilFrontOps(GraphicsPipelineTransitionBits *transition,
2495                                                  const gl::DepthStencilState &depthStencilState)
2496 {
2497     setStencilFrontOps(PackGLStencilOp(depthStencilState.stencilFail),
2498                        PackGLStencilOp(depthStencilState.stencilPassDepthPass),
2499                        PackGLStencilOp(depthStencilState.stencilPassDepthFail));
2500     transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, front));
2501 }
2502 
updateStencilBackOps(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState)2503 void GraphicsPipelineDesc::updateStencilBackOps(GraphicsPipelineTransitionBits *transition,
2504                                                 const gl::DepthStencilState &depthStencilState)
2505 {
2506     setStencilBackOps(PackGLStencilOp(depthStencilState.stencilBackFail),
2507                       PackGLStencilOp(depthStencilState.stencilBackPassDepthPass),
2508                       PackGLStencilOp(depthStencilState.stencilBackPassDepthFail));
2509     transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, back));
2510 }
2511 
updateStencilFrontWriteMask(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState,const gl::Framebuffer * drawFramebuffer)2512 void GraphicsPipelineDesc::updateStencilFrontWriteMask(
2513     GraphicsPipelineTransitionBits *transition,
2514     const gl::DepthStencilState &depthStencilState,
2515     const gl::Framebuffer *drawFramebuffer)
2516 {
2517     // Don't write to stencil buffers that should not exist
2518     setStencilFrontWriteMask(static_cast<uint8_t>(
2519         drawFramebuffer->hasStencil() ? depthStencilState.stencilWritemask : 0));
2520     transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, front));
2521 }
2522 
updateStencilBackWriteMask(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState,const gl::Framebuffer * drawFramebuffer)2523 void GraphicsPipelineDesc::updateStencilBackWriteMask(
2524     GraphicsPipelineTransitionBits *transition,
2525     const gl::DepthStencilState &depthStencilState,
2526     const gl::Framebuffer *drawFramebuffer)
2527 {
2528     // Don't write to stencil buffers that should not exist
2529     setStencilBackWriteMask(static_cast<uint8_t>(
2530         drawFramebuffer->hasStencil() ? depthStencilState.stencilBackWritemask : 0));
2531     transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, back));
2532 }
2533 
updatePolygonOffsetFillEnabled(GraphicsPipelineTransitionBits * transition,bool enabled)2534 void GraphicsPipelineDesc::updatePolygonOffsetFillEnabled(
2535     GraphicsPipelineTransitionBits *transition,
2536     bool enabled)
2537 {
2538     mRasterizationAndMultisampleStateInfo.bits.depthBiasEnable = enabled;
2539     transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, bits));
2540 }
2541 
updatePolygonOffset(GraphicsPipelineTransitionBits * transition,const gl::RasterizerState & rasterState)2542 void GraphicsPipelineDesc::updatePolygonOffset(GraphicsPipelineTransitionBits *transition,
2543                                                const gl::RasterizerState &rasterState)
2544 {
2545     mRasterizationAndMultisampleStateInfo.depthBiasSlopeFactor    = rasterState.polygonOffsetFactor;
2546     mRasterizationAndMultisampleStateInfo.depthBiasConstantFactor = rasterState.polygonOffsetUnits;
2547     transition->set(
2548         ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, depthBiasSlopeFactor));
2549     transition->set(
2550         ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, depthBiasConstantFactor));
2551 }
2552 
setRenderPassDesc(const RenderPassDesc & renderPassDesc)2553 void GraphicsPipelineDesc::setRenderPassDesc(const RenderPassDesc &renderPassDesc)
2554 {
2555     mRenderPassDesc = renderPassDesc;
2556 }
2557 
updateDrawableSize(GraphicsPipelineTransitionBits * transition,uint32_t width,uint32_t height)2558 void GraphicsPipelineDesc::updateDrawableSize(GraphicsPipelineTransitionBits *transition,
2559                                               uint32_t width,
2560                                               uint32_t height)
2561 {
2562     SetBitField(mDrawableSize.width, width);
2563     SetBitField(mDrawableSize.height, height);
2564     transition->set(ANGLE_GET_TRANSITION_BIT(mDrawableSize, width));
2565     transition->set(ANGLE_GET_TRANSITION_BIT(mDrawableSize, height));
2566 }
2567 
updateSubpass(GraphicsPipelineTransitionBits * transition,uint32_t subpass)2568 void GraphicsPipelineDesc::updateSubpass(GraphicsPipelineTransitionBits *transition,
2569                                          uint32_t subpass)
2570 {
2571     if (mRasterizationAndMultisampleStateInfo.bits.subpass != subpass)
2572     {
2573         SetBitField(mRasterizationAndMultisampleStateInfo.bits.subpass, subpass);
2574         transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, bits));
2575     }
2576 }
2577 
updatePatchVertices(GraphicsPipelineTransitionBits * transition,GLuint value)2578 void GraphicsPipelineDesc::updatePatchVertices(GraphicsPipelineTransitionBits *transition,
2579                                                GLuint value)
2580 {
2581     SetBitField(mInputAssemblyAndColorBlendStateInfo.primitive.patchVertices, value);
2582 
2583     transition->set(ANGLE_GET_TRANSITION_BIT(mInputAssemblyAndColorBlendStateInfo, primitive));
2584 }
2585 
resetSubpass(GraphicsPipelineTransitionBits * transition)2586 void GraphicsPipelineDesc::resetSubpass(GraphicsPipelineTransitionBits *transition)
2587 {
2588     updateSubpass(transition, 0);
2589 }
2590 
nextSubpass(GraphicsPipelineTransitionBits * transition)2591 void GraphicsPipelineDesc::nextSubpass(GraphicsPipelineTransitionBits *transition)
2592 {
2593     updateSubpass(transition, mRasterizationAndMultisampleStateInfo.bits.subpass + 1);
2594 }
2595 
setSubpass(uint32_t subpass)2596 void GraphicsPipelineDesc::setSubpass(uint32_t subpass)
2597 {
2598     SetBitField(mRasterizationAndMultisampleStateInfo.bits.subpass, subpass);
2599 }
2600 
getSubpass() const2601 uint32_t GraphicsPipelineDesc::getSubpass() const
2602 {
2603     return mRasterizationAndMultisampleStateInfo.bits.subpass;
2604 }
2605 
updateRenderPassDesc(GraphicsPipelineTransitionBits * transition,const RenderPassDesc & renderPassDesc)2606 void GraphicsPipelineDesc::updateRenderPassDesc(GraphicsPipelineTransitionBits *transition,
2607                                                 const RenderPassDesc &renderPassDesc)
2608 {
2609     setRenderPassDesc(renderPassDesc);
2610 
2611     // The RenderPass is a special case where it spans multiple bits but has no member.
2612     constexpr size_t kFirstBit =
2613         offsetof(GraphicsPipelineDesc, mRenderPassDesc) >> kTransitionByteShift;
2614     constexpr size_t kBitCount = kRenderPassDescSize >> kTransitionByteShift;
2615     for (size_t bit = 0; bit < kBitCount; ++bit)
2616     {
2617         transition->set(kFirstBit + bit);
2618     }
2619 }
2620 
2621 // AttachmentOpsArray implementation.
AttachmentOpsArray()2622 AttachmentOpsArray::AttachmentOpsArray()
2623 {
2624     memset(&mOps, 0, sizeof(PackedAttachmentOpsDesc) * mOps.size());
2625 }
2626 
2627 AttachmentOpsArray::~AttachmentOpsArray() = default;
2628 
AttachmentOpsArray(const AttachmentOpsArray & other)2629 AttachmentOpsArray::AttachmentOpsArray(const AttachmentOpsArray &other)
2630 {
2631     memcpy(&mOps, &other.mOps, sizeof(PackedAttachmentOpsDesc) * mOps.size());
2632 }
2633 
operator =(const AttachmentOpsArray & other)2634 AttachmentOpsArray &AttachmentOpsArray::operator=(const AttachmentOpsArray &other)
2635 {
2636     memcpy(&mOps, &other.mOps, sizeof(PackedAttachmentOpsDesc) * mOps.size());
2637     return *this;
2638 }
2639 
operator [](PackedAttachmentIndex index) const2640 const PackedAttachmentOpsDesc &AttachmentOpsArray::operator[](PackedAttachmentIndex index) const
2641 {
2642     return mOps[index.get()];
2643 }
2644 
operator [](PackedAttachmentIndex index)2645 PackedAttachmentOpsDesc &AttachmentOpsArray::operator[](PackedAttachmentIndex index)
2646 {
2647     return mOps[index.get()];
2648 }
2649 
initWithLoadStore(PackedAttachmentIndex index,ImageLayout initialLayout,ImageLayout finalLayout)2650 void AttachmentOpsArray::initWithLoadStore(PackedAttachmentIndex index,
2651                                            ImageLayout initialLayout,
2652                                            ImageLayout finalLayout)
2653 {
2654     setLayouts(index, initialLayout, finalLayout);
2655     setOps(index, VK_ATTACHMENT_LOAD_OP_LOAD, RenderPassStoreOp::Store);
2656     setStencilOps(index, VK_ATTACHMENT_LOAD_OP_LOAD, RenderPassStoreOp::Store);
2657 }
2658 
setLayouts(PackedAttachmentIndex index,ImageLayout initialLayout,ImageLayout finalLayout)2659 void AttachmentOpsArray::setLayouts(PackedAttachmentIndex index,
2660                                     ImageLayout initialLayout,
2661                                     ImageLayout finalLayout)
2662 {
2663     PackedAttachmentOpsDesc &ops = mOps[index.get()];
2664     SetBitField(ops.initialLayout, initialLayout);
2665     SetBitField(ops.finalLayout, finalLayout);
2666 }
2667 
setOps(PackedAttachmentIndex index,VkAttachmentLoadOp loadOp,RenderPassStoreOp storeOp)2668 void AttachmentOpsArray::setOps(PackedAttachmentIndex index,
2669                                 VkAttachmentLoadOp loadOp,
2670                                 RenderPassStoreOp storeOp)
2671 {
2672     PackedAttachmentOpsDesc &ops = mOps[index.get()];
2673     SetBitField(ops.loadOp, loadOp);
2674     SetBitField(ops.storeOp, storeOp);
2675     ops.isInvalidated = false;
2676 }
2677 
setStencilOps(PackedAttachmentIndex index,VkAttachmentLoadOp loadOp,RenderPassStoreOp storeOp)2678 void AttachmentOpsArray::setStencilOps(PackedAttachmentIndex index,
2679                                        VkAttachmentLoadOp loadOp,
2680                                        RenderPassStoreOp storeOp)
2681 {
2682     PackedAttachmentOpsDesc &ops = mOps[index.get()];
2683     SetBitField(ops.stencilLoadOp, loadOp);
2684     SetBitField(ops.stencilStoreOp, storeOp);
2685     ops.isStencilInvalidated = false;
2686 }
2687 
setClearOp(PackedAttachmentIndex index)2688 void AttachmentOpsArray::setClearOp(PackedAttachmentIndex index)
2689 {
2690     PackedAttachmentOpsDesc &ops = mOps[index.get()];
2691     SetBitField(ops.loadOp, VK_ATTACHMENT_LOAD_OP_CLEAR);
2692 }
2693 
setClearStencilOp(PackedAttachmentIndex index)2694 void AttachmentOpsArray::setClearStencilOp(PackedAttachmentIndex index)
2695 {
2696     PackedAttachmentOpsDesc &ops = mOps[index.get()];
2697     SetBitField(ops.stencilLoadOp, VK_ATTACHMENT_LOAD_OP_CLEAR);
2698 }
2699 
hash() const2700 size_t AttachmentOpsArray::hash() const
2701 {
2702     return angle::ComputeGenericHash(mOps);
2703 }
2704 
operator ==(const AttachmentOpsArray & lhs,const AttachmentOpsArray & rhs)2705 bool operator==(const AttachmentOpsArray &lhs, const AttachmentOpsArray &rhs)
2706 {
2707     return (memcmp(&lhs, &rhs, sizeof(AttachmentOpsArray)) == 0);
2708 }
2709 
2710 // DescriptorSetLayoutDesc implementation.
DescriptorSetLayoutDesc()2711 DescriptorSetLayoutDesc::DescriptorSetLayoutDesc() : mPackedDescriptorSetLayout{} {}
2712 
2713 DescriptorSetLayoutDesc::~DescriptorSetLayoutDesc() = default;
2714 
2715 DescriptorSetLayoutDesc::DescriptorSetLayoutDesc(const DescriptorSetLayoutDesc &other) = default;
2716 
2717 DescriptorSetLayoutDesc &DescriptorSetLayoutDesc::operator=(const DescriptorSetLayoutDesc &other) =
2718     default;
2719 
hash() const2720 size_t DescriptorSetLayoutDesc::hash() const
2721 {
2722     return angle::ComputeGenericHash(mPackedDescriptorSetLayout);
2723 }
2724 
operator ==(const DescriptorSetLayoutDesc & other) const2725 bool DescriptorSetLayoutDesc::operator==(const DescriptorSetLayoutDesc &other) const
2726 {
2727     return (memcmp(&mPackedDescriptorSetLayout, &other.mPackedDescriptorSetLayout,
2728                    sizeof(mPackedDescriptorSetLayout)) == 0);
2729 }
2730 
update(uint32_t bindingIndex,VkDescriptorType type,uint32_t count,VkShaderStageFlags stages,const Sampler * immutableSampler)2731 void DescriptorSetLayoutDesc::update(uint32_t bindingIndex,
2732                                      VkDescriptorType type,
2733                                      uint32_t count,
2734                                      VkShaderStageFlags stages,
2735                                      const Sampler *immutableSampler)
2736 {
2737     ASSERT(static_cast<size_t>(type) < std::numeric_limits<uint16_t>::max());
2738     ASSERT(count < std::numeric_limits<uint16_t>::max());
2739 
2740     PackedDescriptorSetBinding &packedBinding = mPackedDescriptorSetLayout[bindingIndex];
2741 
2742     SetBitField(packedBinding.type, type);
2743     SetBitField(packedBinding.count, count);
2744     SetBitField(packedBinding.stages, stages);
2745     packedBinding.immutableSampler = VK_NULL_HANDLE;
2746     packedBinding.pad              = 0;
2747 
2748     if (immutableSampler)
2749     {
2750         ASSERT(count == 1);
2751         packedBinding.immutableSampler = immutableSampler->getHandle();
2752     }
2753 }
2754 
unpackBindings(DescriptorSetLayoutBindingVector * bindings,std::vector<VkSampler> * immutableSamplers) const2755 void DescriptorSetLayoutDesc::unpackBindings(DescriptorSetLayoutBindingVector *bindings,
2756                                              std::vector<VkSampler> *immutableSamplers) const
2757 {
2758     for (uint32_t bindingIndex = 0; bindingIndex < kMaxDescriptorSetLayoutBindings; ++bindingIndex)
2759     {
2760         const PackedDescriptorSetBinding &packedBinding = mPackedDescriptorSetLayout[bindingIndex];
2761         if (packedBinding.count == 0)
2762             continue;
2763 
2764         VkDescriptorSetLayoutBinding binding = {};
2765         binding.binding                      = bindingIndex;
2766         binding.descriptorCount              = packedBinding.count;
2767         binding.descriptorType               = static_cast<VkDescriptorType>(packedBinding.type);
2768         binding.stageFlags = static_cast<VkShaderStageFlags>(packedBinding.stages);
2769         if (packedBinding.immutableSampler != VK_NULL_HANDLE)
2770         {
2771             ASSERT(packedBinding.count == 1);
2772             immutableSamplers->push_back(packedBinding.immutableSampler);
2773             binding.pImmutableSamplers = reinterpret_cast<const VkSampler *>(angle::DirtyPointer);
2774         }
2775 
2776         bindings->push_back(binding);
2777     }
2778     if (!immutableSamplers->empty())
2779     {
2780         // Patch up pImmutableSampler addresses now that the vector is stable
2781         int immutableIndex = 0;
2782         for (VkDescriptorSetLayoutBinding &binding : *bindings)
2783         {
2784             if (binding.pImmutableSamplers)
2785             {
2786                 binding.pImmutableSamplers = &(*immutableSamplers)[immutableIndex];
2787                 immutableIndex++;
2788             }
2789         }
2790     }
2791 }
2792 
2793 // PipelineLayoutDesc implementation.
PipelineLayoutDesc()2794 PipelineLayoutDesc::PipelineLayoutDesc() : mDescriptorSetLayouts{}, mPushConstantRanges{} {}
2795 
2796 PipelineLayoutDesc::~PipelineLayoutDesc() = default;
2797 
2798 PipelineLayoutDesc::PipelineLayoutDesc(const PipelineLayoutDesc &other) = default;
2799 
operator =(const PipelineLayoutDesc & rhs)2800 PipelineLayoutDesc &PipelineLayoutDesc::operator=(const PipelineLayoutDesc &rhs)
2801 {
2802     mDescriptorSetLayouts = rhs.mDescriptorSetLayouts;
2803     mPushConstantRanges   = rhs.mPushConstantRanges;
2804     return *this;
2805 }
2806 
hash() const2807 size_t PipelineLayoutDesc::hash() const
2808 {
2809     return angle::ComputeGenericHash(*this);
2810 }
2811 
operator ==(const PipelineLayoutDesc & other) const2812 bool PipelineLayoutDesc::operator==(const PipelineLayoutDesc &other) const
2813 {
2814     return memcmp(this, &other, sizeof(PipelineLayoutDesc)) == 0;
2815 }
2816 
updateDescriptorSetLayout(DescriptorSetIndex setIndex,const DescriptorSetLayoutDesc & desc)2817 void PipelineLayoutDesc::updateDescriptorSetLayout(DescriptorSetIndex setIndex,
2818                                                    const DescriptorSetLayoutDesc &desc)
2819 {
2820     mDescriptorSetLayouts[setIndex] = desc;
2821 }
2822 
updatePushConstantRange(gl::ShaderType shaderType,uint32_t offset,uint32_t size)2823 void PipelineLayoutDesc::updatePushConstantRange(gl::ShaderType shaderType,
2824                                                  uint32_t offset,
2825                                                  uint32_t size)
2826 {
2827     ASSERT(shaderType == gl::ShaderType::Vertex || shaderType == gl::ShaderType::Fragment ||
2828            shaderType == gl::ShaderType::Geometry || shaderType == gl::ShaderType::Compute);
2829     PackedPushConstantRange &packed = mPushConstantRanges[shaderType];
2830     packed.offset                   = offset;
2831     packed.size                     = size;
2832 }
2833 
getPushConstantRanges() const2834 const PushConstantRangeArray<PackedPushConstantRange> &PipelineLayoutDesc::getPushConstantRanges()
2835     const
2836 {
2837     return mPushConstantRanges;
2838 }
2839 
2840 // PipelineHelper implementation.
2841 PipelineHelper::PipelineHelper() = default;
2842 
2843 PipelineHelper::~PipelineHelper() = default;
2844 
destroy(VkDevice device)2845 void PipelineHelper::destroy(VkDevice device)
2846 {
2847     mPipeline.destroy(device);
2848 }
2849 
addTransition(GraphicsPipelineTransitionBits bits,const GraphicsPipelineDesc * desc,PipelineHelper * pipeline)2850 void PipelineHelper::addTransition(GraphicsPipelineTransitionBits bits,
2851                                    const GraphicsPipelineDesc *desc,
2852                                    PipelineHelper *pipeline)
2853 {
2854     mTransitions.emplace_back(bits, desc, pipeline);
2855 }
2856 
TextureDescriptorDesc()2857 TextureDescriptorDesc::TextureDescriptorDesc() : mMaxIndex(0)
2858 {
2859     mSerials.fill({kInvalidImageOrBufferViewSubresourceSerial, kInvalidSamplerSerial});
2860 }
2861 
2862 TextureDescriptorDesc::~TextureDescriptorDesc()                                  = default;
2863 TextureDescriptorDesc::TextureDescriptorDesc(const TextureDescriptorDesc &other) = default;
2864 TextureDescriptorDesc &TextureDescriptorDesc::operator=(const TextureDescriptorDesc &other) =
2865     default;
2866 
update(size_t index,ImageOrBufferViewSubresourceSerial viewSerial,SamplerSerial samplerSerial)2867 void TextureDescriptorDesc::update(size_t index,
2868                                    ImageOrBufferViewSubresourceSerial viewSerial,
2869                                    SamplerSerial samplerSerial)
2870 {
2871     if (index >= mMaxIndex)
2872     {
2873         mMaxIndex = static_cast<uint32_t>(index + 1);
2874     }
2875 
2876     mSerials[index].view    = viewSerial;
2877     mSerials[index].sampler = samplerSerial;
2878 }
2879 
hash() const2880 size_t TextureDescriptorDesc::hash() const
2881 {
2882     return angle::ComputeGenericHash(&mSerials, sizeof(TexUnitSerials) * mMaxIndex);
2883 }
2884 
reset()2885 void TextureDescriptorDesc::reset()
2886 {
2887     memset(mSerials.data(), 0, sizeof(mSerials[0]) * mMaxIndex);
2888     mMaxIndex = 0;
2889 }
2890 
operator ==(const TextureDescriptorDesc & other) const2891 bool TextureDescriptorDesc::operator==(const TextureDescriptorDesc &other) const
2892 {
2893     if (mMaxIndex != other.mMaxIndex)
2894         return false;
2895 
2896     if (mMaxIndex == 0)
2897         return true;
2898 
2899     return memcmp(mSerials.data(), other.mSerials.data(), sizeof(TexUnitSerials) * mMaxIndex) == 0;
2900 }
2901 
2902 // UniformsAndXfbDescriptorDesc implementation.
UniformsAndXfbDescriptorDesc()2903 UniformsAndXfbDescriptorDesc::UniformsAndXfbDescriptorDesc()
2904 {
2905     reset();
2906 }
2907 
2908 UniformsAndXfbDescriptorDesc::~UniformsAndXfbDescriptorDesc() = default;
2909 UniformsAndXfbDescriptorDesc::UniformsAndXfbDescriptorDesc(
2910     const UniformsAndXfbDescriptorDesc &other)                      = default;
2911 UniformsAndXfbDescriptorDesc &UniformsAndXfbDescriptorDesc::operator=(
2912     const UniformsAndXfbDescriptorDesc &other) = default;
2913 
hash() const2914 size_t UniformsAndXfbDescriptorDesc::hash() const
2915 {
2916     ASSERT(mBufferCount > 0);
2917 
2918     return angle::ComputeGenericHash(&mBufferSerials, sizeof(mBufferSerials[0]) * mBufferCount) ^
2919            angle::ComputeGenericHash(
2920                &mXfbBufferOffsets,
2921                sizeof(mXfbBufferOffsets[0]) * (mBufferCount - kDefaultUniformBufferCount));
2922 }
2923 
reset()2924 void UniformsAndXfbDescriptorDesc::reset()
2925 {
2926     mBufferCount = 0;
2927     memset(&mBufferSerials, 0, sizeof(mBufferSerials));
2928     memset(&mXfbBufferOffsets, 0, sizeof(mXfbBufferOffsets));
2929 }
2930 
operator ==(const UniformsAndXfbDescriptorDesc & other) const2931 bool UniformsAndXfbDescriptorDesc::operator==(const UniformsAndXfbDescriptorDesc &other) const
2932 {
2933     if (mBufferCount != other.mBufferCount)
2934     {
2935         return false;
2936     }
2937 
2938     ASSERT(mBufferCount > 0);
2939 
2940     return memcmp(&mBufferSerials, &other.mBufferSerials,
2941                   sizeof(mBufferSerials[0]) * mBufferCount) == 0 &&
2942            memcmp(&mXfbBufferOffsets, &other.mXfbBufferOffsets,
2943                   sizeof(mXfbBufferOffsets[0]) * (mBufferCount - kDefaultUniformBufferCount)) == 0;
2944 }
2945 
2946 // ShaderBuffersDescriptorDesc implementation.
ShaderBuffersDescriptorDesc()2947 ShaderBuffersDescriptorDesc::ShaderBuffersDescriptorDesc()
2948 {
2949     reset();
2950 }
2951 
2952 ShaderBuffersDescriptorDesc::~ShaderBuffersDescriptorDesc() = default;
2953 
2954 ShaderBuffersDescriptorDesc::ShaderBuffersDescriptorDesc(const ShaderBuffersDescriptorDesc &other) =
2955     default;
2956 
2957 ShaderBuffersDescriptorDesc &ShaderBuffersDescriptorDesc::operator=(
2958     const ShaderBuffersDescriptorDesc &other) = default;
2959 
hash() const2960 size_t ShaderBuffersDescriptorDesc::hash() const
2961 {
2962     return angle::ComputeGenericHash(mPayload.data(), sizeof(mPayload[0]) * mPayload.size());
2963 }
2964 
reset()2965 void ShaderBuffersDescriptorDesc::reset()
2966 {
2967     mPayload.clear();
2968 }
2969 
operator ==(const ShaderBuffersDescriptorDesc & other) const2970 bool ShaderBuffersDescriptorDesc::operator==(const ShaderBuffersDescriptorDesc &other) const
2971 {
2972     return mPayload == other.mPayload;
2973 }
2974 
2975 // FramebufferDesc implementation.
2976 
FramebufferDesc()2977 FramebufferDesc::FramebufferDesc()
2978 {
2979     reset();
2980 }
2981 
2982 FramebufferDesc::~FramebufferDesc()                            = default;
2983 FramebufferDesc::FramebufferDesc(const FramebufferDesc &other) = default;
2984 FramebufferDesc &FramebufferDesc::operator=(const FramebufferDesc &other) = default;
2985 
update(uint32_t index,ImageOrBufferViewSubresourceSerial serial)2986 void FramebufferDesc::update(uint32_t index, ImageOrBufferViewSubresourceSerial serial)
2987 {
2988     static_assert(kMaxFramebufferAttachments + 1 < std::numeric_limits<uint8_t>::max(),
2989                   "mMaxIndex size is too small");
2990     ASSERT(index < kMaxFramebufferAttachments);
2991     mSerials[index] = serial;
2992     if (serial.viewSerial.valid())
2993     {
2994         SetBitField(mMaxIndex, std::max(mMaxIndex, static_cast<uint16_t>(index + 1)));
2995     }
2996 }
2997 
updateColor(uint32_t index,ImageOrBufferViewSubresourceSerial serial)2998 void FramebufferDesc::updateColor(uint32_t index, ImageOrBufferViewSubresourceSerial serial)
2999 {
3000     update(kFramebufferDescColorIndexOffset + index, serial);
3001 }
3002 
updateColorResolve(uint32_t index,ImageOrBufferViewSubresourceSerial serial)3003 void FramebufferDesc::updateColorResolve(uint32_t index, ImageOrBufferViewSubresourceSerial serial)
3004 {
3005     update(kFramebufferDescColorResolveIndexOffset + index, serial);
3006 }
3007 
updateUnresolveMask(FramebufferNonResolveAttachmentMask unresolveMask)3008 void FramebufferDesc::updateUnresolveMask(FramebufferNonResolveAttachmentMask unresolveMask)
3009 {
3010     SetBitField(mUnresolveAttachmentMask, unresolveMask.bits());
3011 }
3012 
updateDepthStencil(ImageOrBufferViewSubresourceSerial serial)3013 void FramebufferDesc::updateDepthStencil(ImageOrBufferViewSubresourceSerial serial)
3014 {
3015     update(kFramebufferDescDepthStencilIndex, serial);
3016 }
3017 
updateDepthStencilResolve(ImageOrBufferViewSubresourceSerial serial)3018 void FramebufferDesc::updateDepthStencilResolve(ImageOrBufferViewSubresourceSerial serial)
3019 {
3020     update(kFramebufferDescDepthStencilResolveIndexOffset, serial);
3021 }
3022 
hash() const3023 size_t FramebufferDesc::hash() const
3024 {
3025     return angle::ComputeGenericHash(&mSerials, sizeof(mSerials[0]) * mMaxIndex) ^
3026            mHasFramebufferFetch << 26 ^ mIsRenderToTexture << 25 ^ mLayerCount << 16 ^
3027            mUnresolveAttachmentMask;
3028 }
3029 
reset()3030 void FramebufferDesc::reset()
3031 {
3032     mMaxIndex                = 0;
3033     mHasFramebufferFetch     = false;
3034     mLayerCount              = 0;
3035     mSrgbWriteControlMode    = 0;
3036     mUnresolveAttachmentMask = 0;
3037     mIsRenderToTexture       = 0;
3038     memset(&mSerials, 0, sizeof(mSerials));
3039 }
3040 
operator ==(const FramebufferDesc & other) const3041 bool FramebufferDesc::operator==(const FramebufferDesc &other) const
3042 {
3043     if (mMaxIndex != other.mMaxIndex || mLayerCount != other.mLayerCount ||
3044         mUnresolveAttachmentMask != other.mUnresolveAttachmentMask ||
3045         mHasFramebufferFetch != other.mHasFramebufferFetch ||
3046         mSrgbWriteControlMode != other.mSrgbWriteControlMode ||
3047         mIsRenderToTexture != other.mIsRenderToTexture)
3048     {
3049         return false;
3050     }
3051 
3052     size_t validRegionSize = sizeof(mSerials[0]) * mMaxIndex;
3053     return memcmp(&mSerials, &other.mSerials, validRegionSize) == 0;
3054 }
3055 
attachmentCount() const3056 uint32_t FramebufferDesc::attachmentCount() const
3057 {
3058     uint32_t count = 0;
3059     for (const ImageOrBufferViewSubresourceSerial &serial : mSerials)
3060     {
3061         if (serial.viewSerial.valid())
3062         {
3063             count++;
3064         }
3065     }
3066     return count;
3067 }
3068 
getUnresolveAttachmentMask() const3069 FramebufferNonResolveAttachmentMask FramebufferDesc::getUnresolveAttachmentMask() const
3070 {
3071     return FramebufferNonResolveAttachmentMask(mUnresolveAttachmentMask);
3072 }
3073 
updateLayerCount(uint32_t layerCount)3074 void FramebufferDesc::updateLayerCount(uint32_t layerCount)
3075 {
3076     SetBitField(mLayerCount, layerCount);
3077 }
3078 
updateFramebufferFetchMode(bool hasFramebufferFetch)3079 void FramebufferDesc::updateFramebufferFetchMode(bool hasFramebufferFetch)
3080 {
3081     SetBitField(mHasFramebufferFetch, hasFramebufferFetch);
3082 }
3083 
updateRenderToTexture(bool isRenderToTexture)3084 void FramebufferDesc::updateRenderToTexture(bool isRenderToTexture)
3085 {
3086     SetBitField(mIsRenderToTexture, isRenderToTexture);
3087 }
3088 
3089 // SamplerDesc implementation.
SamplerDesc()3090 SamplerDesc::SamplerDesc()
3091 {
3092     reset();
3093 }
3094 
3095 SamplerDesc::~SamplerDesc() = default;
3096 
3097 SamplerDesc::SamplerDesc(const SamplerDesc &other) = default;
3098 
3099 SamplerDesc &SamplerDesc::operator=(const SamplerDesc &rhs) = default;
3100 
SamplerDesc(ContextVk * contextVk,const gl::SamplerState & samplerState,bool stencilMode,uint64_t externalFormat,angle::FormatID formatID)3101 SamplerDesc::SamplerDesc(ContextVk *contextVk,
3102                          const gl::SamplerState &samplerState,
3103                          bool stencilMode,
3104                          uint64_t externalFormat,
3105                          angle::FormatID formatID)
3106 {
3107     update(contextVk, samplerState, stencilMode, externalFormat, formatID);
3108 }
3109 
reset()3110 void SamplerDesc::reset()
3111 {
3112     mMipLodBias         = 0.0f;
3113     mMaxAnisotropy      = 0.0f;
3114     mMinLod             = 0.0f;
3115     mMaxLod             = 0.0f;
3116     mExternalOrVkFormat = 0;
3117     mMagFilter          = 0;
3118     mMinFilter          = 0;
3119     mMipmapMode         = 0;
3120     mAddressModeU       = 0;
3121     mAddressModeV       = 0;
3122     mAddressModeW       = 0;
3123     mCompareEnabled     = 0;
3124     mCompareOp          = 0;
3125     mIsExternalFormat   = 0;
3126     mPadding            = 0;
3127     mBorderColorType    = 0;
3128     mBorderColor.red    = 0.0f;
3129     mBorderColor.green  = 0.0f;
3130     mBorderColor.blue   = 0.0f;
3131     mBorderColor.alpha  = 0.0f;
3132     mReserved           = 0;
3133 }
3134 
update(ContextVk * contextVk,const gl::SamplerState & samplerState,bool stencilMode,uint64_t externalFormat,angle::FormatID formatID)3135 void SamplerDesc::update(ContextVk *contextVk,
3136                          const gl::SamplerState &samplerState,
3137                          bool stencilMode,
3138                          uint64_t externalFormat,
3139                          angle::FormatID formatID)
3140 {
3141     const angle::FeaturesVk &featuresVk = contextVk->getFeatures();
3142     mMipLodBias                         = 0.0f;
3143     for (size_t lodOffsetFeatureIdx = 0;
3144          lodOffsetFeatureIdx < featuresVk.forceTextureLODOffset.size(); lodOffsetFeatureIdx++)
3145     {
3146         if (featuresVk.forceTextureLODOffset[lodOffsetFeatureIdx].enabled)
3147         {
3148             // Make sure only one forceTextureLODOffset feature is set.
3149             ASSERT(mMipLodBias == 0.0f);
3150             mMipLodBias = static_cast<float>(lodOffsetFeatureIdx + 1);
3151         }
3152     }
3153 
3154     mMaxAnisotropy = samplerState.getMaxAnisotropy();
3155     mMinLod        = samplerState.getMinLod();
3156     mMaxLod        = samplerState.getMaxLod();
3157 
3158     // GL has no notion of external format, this must be provided from metadata from the image
3159     const vk::Format &vkFormat = contextVk->getRenderer()->getFormat(formatID);
3160     mIsExternalFormat          = (externalFormat != 0) ? 1 : 0;
3161     mExternalOrVkFormat        = (externalFormat != 0)
3162                               ? externalFormat
3163                               : (vkFormat.intendedFormat().isYUV)
3164                                     ? static_cast<uint64_t>(vkFormat.actualImageVkFormat())
3165                                     : 0;
3166 
3167     bool compareEnable    = samplerState.getCompareMode() == GL_COMPARE_REF_TO_TEXTURE;
3168     VkCompareOp compareOp = gl_vk::GetCompareOp(samplerState.getCompareFunc());
3169     // When sampling from stencil, deqp tests expect texture compare to have no effect
3170     // dEQP - GLES31.functional.stencil_texturing.misc.compare_mode_effect
3171     // states: NOTE: Texture compare mode has no effect when reading stencil values.
3172     if (stencilMode)
3173     {
3174         compareEnable = VK_FALSE;
3175         compareOp     = VK_COMPARE_OP_ALWAYS;
3176     }
3177 
3178     GLenum magFilter = samplerState.getMagFilter();
3179     GLenum minFilter = samplerState.getMinFilter();
3180     if (featuresVk.forceNearestFiltering.enabled)
3181     {
3182         magFilter = gl::ConvertToNearestFilterMode(magFilter);
3183         minFilter = gl::ConvertToNearestFilterMode(minFilter);
3184     }
3185     if (featuresVk.forceNearestMipFiltering.enabled)
3186     {
3187         minFilter = gl::ConvertToNearestMipFilterMode(minFilter);
3188     }
3189 
3190     SetBitField(mMagFilter, gl_vk::GetFilter(magFilter));
3191     SetBitField(mMinFilter, gl_vk::GetFilter(minFilter));
3192     SetBitField(mMipmapMode, gl_vk::GetSamplerMipmapMode(samplerState.getMinFilter()));
3193     SetBitField(mAddressModeU, gl_vk::GetSamplerAddressMode(samplerState.getWrapS()));
3194     SetBitField(mAddressModeV, gl_vk::GetSamplerAddressMode(samplerState.getWrapT()));
3195     SetBitField(mAddressModeW, gl_vk::GetSamplerAddressMode(samplerState.getWrapR()));
3196     SetBitField(mCompareEnabled, compareEnable);
3197     SetBitField(mCompareOp, compareOp);
3198 
3199     if (!gl::IsMipmapFiltered(minFilter))
3200     {
3201         // Per the Vulkan spec, GL_NEAREST and GL_LINEAR do not map directly to Vulkan, so
3202         // they must be emulated (See "Mapping of OpenGL to Vulkan filter modes")
3203         SetBitField(mMipmapMode, VK_SAMPLER_MIPMAP_MODE_NEAREST);
3204         mMinLod = 0.0f;
3205         mMaxLod = 0.25f;
3206     }
3207 
3208     mPadding = 0;
3209 
3210     mBorderColorType =
3211         (samplerState.getBorderColor().type == angle::ColorGeneric::Type::Float) ? 0 : 1;
3212 
3213     mBorderColor = samplerState.getBorderColor().colorF;
3214     if (vkFormat.intendedFormatID != angle::FormatID::NONE)
3215     {
3216         LoadTextureBorderFunctionInfo loadFunction = vkFormat.textureBorderLoadFunctions();
3217         loadFunction.loadFunction(mBorderColor);
3218     }
3219 
3220     mReserved = 0;
3221 }
3222 
init(ContextVk * contextVk,Sampler * sampler) const3223 angle::Result SamplerDesc::init(ContextVk *contextVk, Sampler *sampler) const
3224 {
3225     const gl::Extensions &extensions = contextVk->getExtensions();
3226 
3227     bool anisotropyEnable = extensions.textureFilterAnisotropic && mMaxAnisotropy > 1.0f;
3228 
3229     VkSamplerCreateInfo createInfo     = {};
3230     createInfo.sType                   = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
3231     createInfo.flags                   = 0;
3232     createInfo.magFilter               = static_cast<VkFilter>(mMagFilter);
3233     createInfo.minFilter               = static_cast<VkFilter>(mMinFilter);
3234     createInfo.mipmapMode              = static_cast<VkSamplerMipmapMode>(mMipmapMode);
3235     createInfo.addressModeU            = static_cast<VkSamplerAddressMode>(mAddressModeU);
3236     createInfo.addressModeV            = static_cast<VkSamplerAddressMode>(mAddressModeV);
3237     createInfo.addressModeW            = static_cast<VkSamplerAddressMode>(mAddressModeW);
3238     createInfo.mipLodBias              = mMipLodBias;
3239     createInfo.anisotropyEnable        = anisotropyEnable;
3240     createInfo.maxAnisotropy           = mMaxAnisotropy;
3241     createInfo.compareEnable           = mCompareEnabled ? VK_TRUE : VK_FALSE;
3242     createInfo.compareOp               = static_cast<VkCompareOp>(mCompareOp);
3243     createInfo.minLod                  = mMinLod;
3244     createInfo.maxLod                  = mMaxLod;
3245     createInfo.borderColor             = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK;
3246     createInfo.unnormalizedCoordinates = VK_FALSE;
3247 
3248     // Note: because we don't detect changes to this hint (no dirty bit), if a sampler is created
3249     // with the hint enabled, and then the hint gets disabled, the next render will do so with the
3250     // hint enabled.
3251     VkSamplerFilteringPrecisionGOOGLE filteringInfo = {};
3252     GLenum hint = contextVk->getState().getTextureFilteringHint();
3253     if (hint == GL_NICEST)
3254     {
3255         ASSERT(extensions.textureFilteringCHROMIUM);
3256         filteringInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_FILTERING_PRECISION_GOOGLE;
3257         filteringInfo.samplerFilteringPrecisionMode =
3258             VK_SAMPLER_FILTERING_PRECISION_MODE_HIGH_GOOGLE;
3259         AddToPNextChain(&createInfo, &filteringInfo);
3260     }
3261 
3262     VkSamplerYcbcrConversionInfo yuvConversionInfo = {};
3263     if (mExternalOrVkFormat)
3264     {
3265         ASSERT((contextVk->getRenderer()->getFeatures().supportsYUVSamplerConversion.enabled));
3266         yuvConversionInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO;
3267         yuvConversionInfo.pNext = nullptr;
3268         yuvConversionInfo.conversion =
3269             contextVk->getRenderer()->getYuvConversionCache().getSamplerYcbcrConversion(
3270                 mExternalOrVkFormat, (mIsExternalFormat == 1));
3271         AddToPNextChain(&createInfo, &yuvConversionInfo);
3272 
3273         // Vulkan spec requires these settings:
3274         createInfo.addressModeU            = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
3275         createInfo.addressModeV            = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
3276         createInfo.addressModeW            = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
3277         createInfo.anisotropyEnable        = VK_FALSE;
3278         createInfo.unnormalizedCoordinates = VK_FALSE;
3279         // VUID-VkSamplerCreateInfo-minFilter VkCreateSampler:
3280         // VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT
3281         // specifies that the format can have different chroma, min, and mag filters. However,
3282         // VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT is
3283         // not supported for VkSamplerYcbcrConversionCreateInfo.format = VK_FORMAT_UNDEFINED so
3284         // minFilter/magFilter needs to be equal to chromaFilter.
3285         // HardwareBufferImageSiblingVkAndroid() forces VK_FILTER_NEAREST, so force
3286         // VK_FILTER_NEAREST here too.
3287         createInfo.magFilter = VK_FILTER_NEAREST;
3288         createInfo.minFilter = VK_FILTER_NEAREST;
3289     }
3290 
3291     VkSamplerCustomBorderColorCreateInfoEXT customBorderColorInfo = {};
3292     if (createInfo.addressModeU == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER ||
3293         createInfo.addressModeV == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER ||
3294         createInfo.addressModeW == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER)
3295     {
3296         ASSERT((contextVk->getRenderer()->getFeatures().supportsCustomBorderColorEXT.enabled));
3297         customBorderColorInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT;
3298 
3299         customBorderColorInfo.customBorderColor.float32[0] = mBorderColor.red;
3300         customBorderColorInfo.customBorderColor.float32[1] = mBorderColor.green;
3301         customBorderColorInfo.customBorderColor.float32[2] = mBorderColor.blue;
3302         customBorderColorInfo.customBorderColor.float32[3] = mBorderColor.alpha;
3303 
3304         if (mBorderColorType == static_cast<uint32_t>(angle::ColorGeneric::Type::Float))
3305         {
3306             createInfo.borderColor = VK_BORDER_COLOR_FLOAT_CUSTOM_EXT;
3307         }
3308         else
3309         {
3310             createInfo.borderColor = VK_BORDER_COLOR_INT_CUSTOM_EXT;
3311         }
3312 
3313         vk::AddToPNextChain(&createInfo, &customBorderColorInfo);
3314     }
3315     ANGLE_VK_TRY(contextVk, sampler->init(contextVk->getDevice(), createInfo));
3316 
3317     return angle::Result::Continue;
3318 }
3319 
hash() const3320 size_t SamplerDesc::hash() const
3321 {
3322     return angle::ComputeGenericHash(*this);
3323 }
3324 
operator ==(const SamplerDesc & other) const3325 bool SamplerDesc::operator==(const SamplerDesc &other) const
3326 {
3327     return (memcmp(this, &other, sizeof(SamplerDesc)) == 0);
3328 }
3329 
3330 // SamplerHelper implementation.
SamplerHelper(ContextVk * contextVk)3331 SamplerHelper::SamplerHelper(ContextVk *contextVk)
3332     : mSamplerSerial(contextVk->getRenderer()->getResourceSerialFactory().generateSamplerSerial())
3333 {}
3334 
~SamplerHelper()3335 SamplerHelper::~SamplerHelper() {}
3336 
SamplerHelper(SamplerHelper && samplerHelper)3337 SamplerHelper::SamplerHelper(SamplerHelper &&samplerHelper)
3338 {
3339     *this = std::move(samplerHelper);
3340 }
3341 
operator =(SamplerHelper && rhs)3342 SamplerHelper &SamplerHelper::operator=(SamplerHelper &&rhs)
3343 {
3344     std::swap(mSampler, rhs.mSampler);
3345     std::swap(mSamplerSerial, rhs.mSamplerSerial);
3346     return *this;
3347 }
3348 
3349 // RenderPassHelper implementation.
RenderPassHelper()3350 RenderPassHelper::RenderPassHelper() : mPerfCounters{} {}
3351 
3352 RenderPassHelper::~RenderPassHelper() = default;
3353 
RenderPassHelper(RenderPassHelper && other)3354 RenderPassHelper::RenderPassHelper(RenderPassHelper &&other)
3355 {
3356     *this = std::move(other);
3357 }
3358 
operator =(RenderPassHelper && other)3359 RenderPassHelper &RenderPassHelper::operator=(RenderPassHelper &&other)
3360 {
3361     mRenderPass   = std::move(other.mRenderPass);
3362     mPerfCounters = std::move(other.mPerfCounters);
3363     return *this;
3364 }
3365 
destroy(VkDevice device)3366 void RenderPassHelper::destroy(VkDevice device)
3367 {
3368     mRenderPass.destroy(device);
3369 }
3370 
getRenderPass() const3371 const RenderPass &RenderPassHelper::getRenderPass() const
3372 {
3373     return mRenderPass;
3374 }
3375 
getRenderPass()3376 RenderPass &RenderPassHelper::getRenderPass()
3377 {
3378     return mRenderPass;
3379 }
3380 
getPerfCounters() const3381 const RenderPassPerfCounters &RenderPassHelper::getPerfCounters() const
3382 {
3383     return mPerfCounters;
3384 }
3385 
getPerfCounters()3386 RenderPassPerfCounters &RenderPassHelper::getPerfCounters()
3387 {
3388     return mPerfCounters;
3389 }
3390 }  // namespace vk
3391 
3392 // RenderPassCache implementation.
3393 RenderPassCache::RenderPassCache() = default;
3394 
~RenderPassCache()3395 RenderPassCache::~RenderPassCache()
3396 {
3397     ASSERT(mPayload.empty());
3398 }
3399 
destroy(RendererVk * rendererVk)3400 void RenderPassCache::destroy(RendererVk *rendererVk)
3401 {
3402     rendererVk->accumulateCacheStats(VulkanCacheType::CompatibleRenderPass,
3403                                      mCompatibleRenderPassCacheStats);
3404     rendererVk->accumulateCacheStats(VulkanCacheType::RenderPassWithOps,
3405                                      mRenderPassWithOpsCacheStats);
3406 
3407     VkDevice device = rendererVk->getDevice();
3408 
3409     for (auto &outerIt : mPayload)
3410     {
3411         for (auto &innerIt : outerIt.second)
3412         {
3413             innerIt.second.destroy(device);
3414         }
3415     }
3416     mPayload.clear();
3417 }
3418 
addRenderPass(ContextVk * contextVk,const vk::RenderPassDesc & desc,vk::RenderPass ** renderPassOut)3419 angle::Result RenderPassCache::addRenderPass(ContextVk *contextVk,
3420                                              const vk::RenderPassDesc &desc,
3421                                              vk::RenderPass **renderPassOut)
3422 {
3423     // Insert some placeholder attachment ops.  Note that render passes with different ops are still
3424     // compatible. The load/store values are not important as they are aren't used for real RPs.
3425     //
3426     // It would be nice to pre-populate the cache in the Renderer so we rarely miss here.
3427     vk::AttachmentOpsArray ops;
3428 
3429     vk::PackedAttachmentIndex colorIndexVk(0);
3430     for (uint32_t colorIndexGL = 0; colorIndexGL < desc.colorAttachmentRange(); ++colorIndexGL)
3431     {
3432         if (!desc.isColorAttachmentEnabled(colorIndexGL))
3433         {
3434             continue;
3435         }
3436 
3437         ops.initWithLoadStore(colorIndexVk, vk::ImageLayout::ColorAttachment,
3438                               vk::ImageLayout::ColorAttachment);
3439         ++colorIndexVk;
3440     }
3441 
3442     if (desc.hasDepthStencilAttachment())
3443     {
3444         // This API is only called by getCompatibleRenderPass(). What we need here is to create a
3445         // compatible renderpass with the desc. Vulkan spec says image layout are not counted toward
3446         // render pass compatibility: "Two render passes are compatible if their corresponding
3447         // color, input, resolve, and depth/stencil attachment references are compatible and if they
3448         // are otherwise identical except for: Initial and final image layout in attachment
3449         // descriptions; Image layout in attachment references". We pick the most used layout here
3450         // since it doesn't matter.
3451         vk::ImageLayout imageLayout = vk::ImageLayout::DepthStencilAttachment;
3452         ops.initWithLoadStore(colorIndexVk, imageLayout, imageLayout);
3453     }
3454 
3455     return getRenderPassWithOpsImpl(contextVk, desc, ops, false, renderPassOut);
3456 }
3457 
getRenderPassWithOps(ContextVk * contextVk,const vk::RenderPassDesc & desc,const vk::AttachmentOpsArray & attachmentOps,vk::RenderPass ** renderPassOut)3458 angle::Result RenderPassCache::getRenderPassWithOps(ContextVk *contextVk,
3459                                                     const vk::RenderPassDesc &desc,
3460                                                     const vk::AttachmentOpsArray &attachmentOps,
3461                                                     vk::RenderPass **renderPassOut)
3462 {
3463     return getRenderPassWithOpsImpl(contextVk, desc, attachmentOps, true, renderPassOut);
3464 }
3465 
getRenderPassWithOpsImpl(ContextVk * contextVk,const vk::RenderPassDesc & desc,const vk::AttachmentOpsArray & attachmentOps,bool updatePerfCounters,vk::RenderPass ** renderPassOut)3466 angle::Result RenderPassCache::getRenderPassWithOpsImpl(ContextVk *contextVk,
3467                                                         const vk::RenderPassDesc &desc,
3468                                                         const vk::AttachmentOpsArray &attachmentOps,
3469                                                         bool updatePerfCounters,
3470                                                         vk::RenderPass **renderPassOut)
3471 {
3472     auto outerIt = mPayload.find(desc);
3473     if (outerIt != mPayload.end())
3474     {
3475         InnerCache &innerCache = outerIt->second;
3476 
3477         auto innerIt = innerCache.find(attachmentOps);
3478         if (innerIt != innerCache.end())
3479         {
3480             // TODO(jmadill): Could possibly use an MRU cache here.
3481             vk::GetRenderPassAndUpdateCounters(contextVk, updatePerfCounters, &innerIt->second,
3482                                                renderPassOut);
3483             mRenderPassWithOpsCacheStats.hit();
3484             return angle::Result::Continue;
3485         }
3486     }
3487     else
3488     {
3489         auto emplaceResult = mPayload.emplace(desc, InnerCache());
3490         outerIt            = emplaceResult.first;
3491     }
3492 
3493     mRenderPassWithOpsCacheStats.miss();
3494     vk::RenderPassHelper newRenderPass;
3495     ANGLE_TRY(vk::InitializeRenderPassFromDesc(contextVk, desc, attachmentOps, &newRenderPass));
3496 
3497     InnerCache &innerCache = outerIt->second;
3498     auto insertPos         = innerCache.emplace(attachmentOps, std::move(newRenderPass));
3499     vk::GetRenderPassAndUpdateCounters(contextVk, updatePerfCounters, &insertPos.first->second,
3500                                        renderPassOut);
3501 
3502     // TODO(jmadill): Trim cache, and pre-populate with the most common RPs on startup.
3503     return angle::Result::Continue;
3504 }
3505 
3506 // GraphicsPipelineCache implementation.
3507 GraphicsPipelineCache::GraphicsPipelineCache() = default;
3508 
~GraphicsPipelineCache()3509 GraphicsPipelineCache::~GraphicsPipelineCache()
3510 {
3511     ASSERT(mPayload.empty());
3512 }
3513 
destroy(RendererVk * rendererVk)3514 void GraphicsPipelineCache::destroy(RendererVk *rendererVk)
3515 {
3516     accumulateCacheStats(rendererVk);
3517 
3518     VkDevice device = rendererVk->getDevice();
3519 
3520     for (auto &item : mPayload)
3521     {
3522         vk::PipelineHelper &pipeline = item.second;
3523         pipeline.destroy(device);
3524     }
3525 
3526     mPayload.clear();
3527 }
3528 
release(ContextVk * context)3529 void GraphicsPipelineCache::release(ContextVk *context)
3530 {
3531     for (auto &item : mPayload)
3532     {
3533         vk::PipelineHelper &pipeline = item.second;
3534         context->addGarbage(&pipeline.getPipeline());
3535     }
3536 
3537     mPayload.clear();
3538 }
3539 
insertPipeline(ContextVk * contextVk,const vk::PipelineCache & pipelineCacheVk,const vk::RenderPass & compatibleRenderPass,const vk::PipelineLayout & pipelineLayout,const gl::AttributesMask & activeAttribLocationsMask,const gl::ComponentTypeMask & programAttribsTypeMask,const vk::ShaderModule * vertexModule,const vk::ShaderModule * fragmentModule,const vk::ShaderModule * geometryModule,const vk::ShaderModule * tessControlModule,const vk::ShaderModule * tessEvaluationModule,const vk::SpecializationConstants & specConsts,const vk::GraphicsPipelineDesc & desc,const vk::GraphicsPipelineDesc ** descPtrOut,vk::PipelineHelper ** pipelineOut)3540 angle::Result GraphicsPipelineCache::insertPipeline(
3541     ContextVk *contextVk,
3542     const vk::PipelineCache &pipelineCacheVk,
3543     const vk::RenderPass &compatibleRenderPass,
3544     const vk::PipelineLayout &pipelineLayout,
3545     const gl::AttributesMask &activeAttribLocationsMask,
3546     const gl::ComponentTypeMask &programAttribsTypeMask,
3547     const vk::ShaderModule *vertexModule,
3548     const vk::ShaderModule *fragmentModule,
3549     const vk::ShaderModule *geometryModule,
3550     const vk::ShaderModule *tessControlModule,
3551     const vk::ShaderModule *tessEvaluationModule,
3552     const vk::SpecializationConstants &specConsts,
3553     const vk::GraphicsPipelineDesc &desc,
3554     const vk::GraphicsPipelineDesc **descPtrOut,
3555     vk::PipelineHelper **pipelineOut)
3556 {
3557     vk::Pipeline newPipeline;
3558 
3559     // This "if" is left here for the benefit of VulkanPipelineCachePerfTest.
3560     if (contextVk != nullptr)
3561     {
3562         contextVk->getRenderer()->onNewGraphicsPipeline();
3563         ANGLE_TRY(desc.initializePipeline(
3564             contextVk, pipelineCacheVk, compatibleRenderPass, pipelineLayout,
3565             activeAttribLocationsMask, programAttribsTypeMask, vertexModule, fragmentModule,
3566             geometryModule, tessControlModule, tessEvaluationModule, specConsts, &newPipeline));
3567     }
3568 
3569     // The Serial will be updated outside of this query.
3570     auto insertedItem = mPayload.emplace(desc, std::move(newPipeline));
3571     *descPtrOut       = &insertedItem.first->first;
3572     *pipelineOut      = &insertedItem.first->second;
3573 
3574     return angle::Result::Continue;
3575 }
3576 
populate(const vk::GraphicsPipelineDesc & desc,vk::Pipeline && pipeline)3577 void GraphicsPipelineCache::populate(const vk::GraphicsPipelineDesc &desc, vk::Pipeline &&pipeline)
3578 {
3579     auto item = mPayload.find(desc);
3580     if (item != mPayload.end())
3581     {
3582         return;
3583     }
3584 
3585     mPayload.emplace(desc, std::move(pipeline));
3586 }
3587 
3588 // DescriptorSetLayoutCache implementation.
3589 DescriptorSetLayoutCache::DescriptorSetLayoutCache() = default;
3590 
~DescriptorSetLayoutCache()3591 DescriptorSetLayoutCache::~DescriptorSetLayoutCache()
3592 {
3593     ASSERT(mPayload.empty());
3594 }
3595 
destroy(RendererVk * rendererVk)3596 void DescriptorSetLayoutCache::destroy(RendererVk *rendererVk)
3597 {
3598     rendererVk->accumulateCacheStats(VulkanCacheType::DescriptorSetLayout, mCacheStats);
3599 
3600     VkDevice device = rendererVk->getDevice();
3601 
3602     for (auto &item : mPayload)
3603     {
3604         vk::RefCountedDescriptorSetLayout &layout = item.second;
3605         ASSERT(!layout.isReferenced());
3606         layout.get().destroy(device);
3607     }
3608 
3609     mPayload.clear();
3610 }
3611 
getDescriptorSetLayout(vk::Context * context,const vk::DescriptorSetLayoutDesc & desc,vk::BindingPointer<vk::DescriptorSetLayout> * descriptorSetLayoutOut)3612 angle::Result DescriptorSetLayoutCache::getDescriptorSetLayout(
3613     vk::Context *context,
3614     const vk::DescriptorSetLayoutDesc &desc,
3615     vk::BindingPointer<vk::DescriptorSetLayout> *descriptorSetLayoutOut)
3616 {
3617     auto iter = mPayload.find(desc);
3618     if (iter != mPayload.end())
3619     {
3620         vk::RefCountedDescriptorSetLayout &layout = iter->second;
3621         descriptorSetLayoutOut->set(&layout);
3622         mCacheStats.hit();
3623         return angle::Result::Continue;
3624     }
3625 
3626     mCacheStats.miss();
3627     // We must unpack the descriptor set layout description.
3628     vk::DescriptorSetLayoutBindingVector bindingVector;
3629     std::vector<VkSampler> immutableSamplers;
3630     desc.unpackBindings(&bindingVector, &immutableSamplers);
3631 
3632     VkDescriptorSetLayoutCreateInfo createInfo = {};
3633     createInfo.sType        = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
3634     createInfo.flags        = 0;
3635     createInfo.bindingCount = static_cast<uint32_t>(bindingVector.size());
3636     createInfo.pBindings    = bindingVector.data();
3637 
3638     vk::DescriptorSetLayout newLayout;
3639     ANGLE_VK_TRY(context, newLayout.init(context->getDevice(), createInfo));
3640 
3641     auto insertedItem =
3642         mPayload.emplace(desc, vk::RefCountedDescriptorSetLayout(std::move(newLayout)));
3643     vk::RefCountedDescriptorSetLayout &insertedLayout = insertedItem.first->second;
3644     descriptorSetLayoutOut->set(&insertedLayout);
3645 
3646     return angle::Result::Continue;
3647 }
3648 
3649 // PipelineLayoutCache implementation.
3650 PipelineLayoutCache::PipelineLayoutCache() = default;
3651 
~PipelineLayoutCache()3652 PipelineLayoutCache::~PipelineLayoutCache()
3653 {
3654     ASSERT(mPayload.empty());
3655 }
3656 
destroy(RendererVk * rendererVk)3657 void PipelineLayoutCache::destroy(RendererVk *rendererVk)
3658 {
3659     accumulateCacheStats(rendererVk);
3660 
3661     VkDevice device = rendererVk->getDevice();
3662 
3663     for (auto &item : mPayload)
3664     {
3665         vk::RefCountedPipelineLayout &layout = item.second;
3666         layout.get().destroy(device);
3667     }
3668 
3669     mPayload.clear();
3670 }
3671 
getPipelineLayout(vk::Context * context,const vk::PipelineLayoutDesc & desc,const vk::DescriptorSetLayoutPointerArray & descriptorSetLayouts,vk::BindingPointer<vk::PipelineLayout> * pipelineLayoutOut)3672 angle::Result PipelineLayoutCache::getPipelineLayout(
3673     vk::Context *context,
3674     const vk::PipelineLayoutDesc &desc,
3675     const vk::DescriptorSetLayoutPointerArray &descriptorSetLayouts,
3676     vk::BindingPointer<vk::PipelineLayout> *pipelineLayoutOut)
3677 {
3678     auto iter = mPayload.find(desc);
3679     if (iter != mPayload.end())
3680     {
3681         vk::RefCountedPipelineLayout &layout = iter->second;
3682         pipelineLayoutOut->set(&layout);
3683         mCacheStats.hit();
3684         return angle::Result::Continue;
3685     }
3686 
3687     mCacheStats.miss();
3688     // Note this does not handle gaps in descriptor set layouts gracefully.
3689     angle::FixedVector<VkDescriptorSetLayout, vk::kMaxDescriptorSetLayouts> setLayoutHandles;
3690     for (const vk::BindingPointer<vk::DescriptorSetLayout> &layoutPtr : descriptorSetLayouts)
3691     {
3692         if (layoutPtr.valid())
3693         {
3694             VkDescriptorSetLayout setLayout = layoutPtr.get().getHandle();
3695             if (setLayout != VK_NULL_HANDLE)
3696             {
3697                 setLayoutHandles.push_back(setLayout);
3698             }
3699         }
3700     }
3701 
3702     const vk::PushConstantRangeArray<vk::PackedPushConstantRange> &descPushConstantRanges =
3703         desc.getPushConstantRanges();
3704 
3705     gl::ShaderVector<VkPushConstantRange> pushConstantRanges;
3706 
3707     for (const gl::ShaderType shaderType : gl::AllShaderTypes())
3708     {
3709         const vk::PackedPushConstantRange &pushConstantDesc = descPushConstantRanges[shaderType];
3710         if (pushConstantDesc.size > 0)
3711         {
3712             VkPushConstantRange range;
3713             range.stageFlags = gl_vk::kShaderStageMap[shaderType];
3714             range.offset     = pushConstantDesc.offset;
3715             range.size       = pushConstantDesc.size;
3716 
3717             pushConstantRanges.push_back(range);
3718         }
3719     }
3720 
3721     // No pipeline layout found. We must create a new one.
3722     VkPipelineLayoutCreateInfo createInfo = {};
3723     createInfo.sType                      = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
3724     createInfo.flags                      = 0;
3725     createInfo.setLayoutCount             = static_cast<uint32_t>(setLayoutHandles.size());
3726     createInfo.pSetLayouts                = setLayoutHandles.data();
3727     createInfo.pushConstantRangeCount     = static_cast<uint32_t>(pushConstantRanges.size());
3728     createInfo.pPushConstantRanges        = pushConstantRanges.data();
3729 
3730     vk::PipelineLayout newLayout;
3731     ANGLE_VK_TRY(context, newLayout.init(context->getDevice(), createInfo));
3732 
3733     auto insertedItem = mPayload.emplace(desc, vk::RefCountedPipelineLayout(std::move(newLayout)));
3734     vk::RefCountedPipelineLayout &insertedLayout = insertedItem.first->second;
3735     pipelineLayoutOut->set(&insertedLayout);
3736 
3737     return angle::Result::Continue;
3738 }
3739 
3740 // YuvConversionCache implementation
3741 SamplerYcbcrConversionCache::SamplerYcbcrConversionCache() = default;
3742 
~SamplerYcbcrConversionCache()3743 SamplerYcbcrConversionCache::~SamplerYcbcrConversionCache()
3744 {
3745     ASSERT(mExternalFormatPayload.empty() && mVkFormatPayload.empty());
3746 }
3747 
destroy(RendererVk * rendererVk)3748 void SamplerYcbcrConversionCache::destroy(RendererVk *rendererVk)
3749 {
3750     rendererVk->accumulateCacheStats(VulkanCacheType::SamplerYcbcrConversion, mCacheStats);
3751 
3752     VkDevice device = rendererVk->getDevice();
3753 
3754     for (auto &iter : mExternalFormatPayload)
3755     {
3756         vk::RefCountedSamplerYcbcrConversion &yuvSampler = iter.second;
3757         ASSERT(!yuvSampler.isReferenced());
3758         yuvSampler.get().destroy(device);
3759 
3760         rendererVk->getActiveHandleCounts().onDeallocate(vk::HandleType::SamplerYcbcrConversion);
3761     }
3762 
3763     for (auto &iter : mVkFormatPayload)
3764     {
3765         vk::RefCountedSamplerYcbcrConversion &yuvSampler = iter.second;
3766         ASSERT(!yuvSampler.isReferenced());
3767         yuvSampler.get().destroy(device);
3768 
3769         rendererVk->getActiveHandleCounts().onDeallocate(vk::HandleType::SamplerYcbcrConversion);
3770     }
3771 
3772     mExternalFormatPayload.clear();
3773     mVkFormatPayload.clear();
3774 }
3775 
3776 template <typename T>
getYuvConversionImpl(vk::Context * context,T format,SamplerYcbcrConversionMap<T> * payload,const VkSamplerYcbcrConversionCreateInfo & yuvConversionCreateInfo,vk::BindingPointer<vk::SamplerYcbcrConversion> * yuvConversionOut)3777 angle::Result SamplerYcbcrConversionCache::getYuvConversionImpl(
3778     vk::Context *context,
3779     T format,
3780     SamplerYcbcrConversionMap<T> *payload,
3781     const VkSamplerYcbcrConversionCreateInfo &yuvConversionCreateInfo,
3782     vk::BindingPointer<vk::SamplerYcbcrConversion> *yuvConversionOut)
3783 {
3784     const auto iter = payload->find(format);
3785     if (iter != payload->end())
3786     {
3787         vk::RefCountedSamplerYcbcrConversion &yuvConversion = iter->second;
3788         yuvConversionOut->set(&yuvConversion);
3789         mCacheStats.hit();
3790         return angle::Result::Continue;
3791     }
3792 
3793     mCacheStats.miss();
3794     vk::SamplerYcbcrConversion wrappedYuvConversion;
3795     ANGLE_VK_TRY(context, wrappedYuvConversion.init(context->getDevice(), yuvConversionCreateInfo));
3796 
3797     auto insertedItem = payload->emplace(
3798         format, vk::RefCountedSamplerYcbcrConversion(std::move(wrappedYuvConversion)));
3799     vk::RefCountedSamplerYcbcrConversion &insertedYuvConversion = insertedItem.first->second;
3800     yuvConversionOut->set(&insertedYuvConversion);
3801 
3802     context->getRenderer()->getActiveHandleCounts().onAllocate(
3803         vk::HandleType::SamplerYcbcrConversion);
3804 
3805     return angle::Result::Continue;
3806 }
3807 
getYuvConversion(vk::Context * context,uint64_t externalOrVkFormat,bool isExternalFormat,const VkSamplerYcbcrConversionCreateInfo & yuvConversionCreateInfo,vk::BindingPointer<vk::SamplerYcbcrConversion> * yuvConversionOut)3808 angle::Result SamplerYcbcrConversionCache::getYuvConversion(
3809     vk::Context *context,
3810     uint64_t externalOrVkFormat,
3811     bool isExternalFormat,
3812     const VkSamplerYcbcrConversionCreateInfo &yuvConversionCreateInfo,
3813     vk::BindingPointer<vk::SamplerYcbcrConversion> *yuvConversionOut)
3814 {
3815     if (isExternalFormat)
3816     {
3817         return getYuvConversionImpl(context, externalOrVkFormat, &mExternalFormatPayload,
3818                                     yuvConversionCreateInfo, yuvConversionOut);
3819     }
3820     else
3821     {
3822         return getYuvConversionImpl(context, static_cast<VkFormat>(externalOrVkFormat),
3823                                     &mVkFormatPayload, yuvConversionCreateInfo, yuvConversionOut);
3824     }
3825 }
3826 
3827 template <typename T>
getSamplerYcbcrConversionImpl(T format,const SamplerYcbcrConversionMap<T> & payload) const3828 VkSamplerYcbcrConversion SamplerYcbcrConversionCache::getSamplerYcbcrConversionImpl(
3829     T format,
3830     const SamplerYcbcrConversionMap<T> &payload) const
3831 {
3832     const auto iter = payload.find(format);
3833     if (iter != payload.end())
3834     {
3835         const vk::RefCountedSamplerYcbcrConversion &yuvConversion = iter->second;
3836         return yuvConversion.get().getHandle();
3837     }
3838 
3839     // Should never get here if we have a valid format.
3840     UNREACHABLE();
3841     return VK_NULL_HANDLE;
3842 }
3843 
getSamplerYcbcrConversion(uint64_t externalOrVkFormat,bool isExternalFormat) const3844 VkSamplerYcbcrConversion SamplerYcbcrConversionCache::getSamplerYcbcrConversion(
3845     uint64_t externalOrVkFormat,
3846     bool isExternalFormat) const
3847 {
3848     if (isExternalFormat)
3849     {
3850         return getSamplerYcbcrConversionImpl(externalOrVkFormat, mExternalFormatPayload);
3851     }
3852     else
3853     {
3854         return getSamplerYcbcrConversionImpl(static_cast<VkFormat>(externalOrVkFormat),
3855                                              mVkFormatPayload);
3856     }
3857 }
3858 
3859 // SamplerCache implementation.
3860 SamplerCache::SamplerCache() = default;
3861 
~SamplerCache()3862 SamplerCache::~SamplerCache()
3863 {
3864     ASSERT(mPayload.empty());
3865 }
3866 
destroy(RendererVk * rendererVk)3867 void SamplerCache::destroy(RendererVk *rendererVk)
3868 {
3869     rendererVk->accumulateCacheStats(VulkanCacheType::Sampler, mCacheStats);
3870 
3871     VkDevice device = rendererVk->getDevice();
3872 
3873     for (auto &iter : mPayload)
3874     {
3875         vk::RefCountedSampler &sampler = iter.second;
3876         ASSERT(!sampler.isReferenced());
3877         sampler.get().get().destroy(device);
3878 
3879         rendererVk->getActiveHandleCounts().onDeallocate(vk::HandleType::Sampler);
3880     }
3881 
3882     mPayload.clear();
3883 }
3884 
getSampler(ContextVk * contextVk,const vk::SamplerDesc & desc,vk::SamplerBinding * samplerOut)3885 angle::Result SamplerCache::getSampler(ContextVk *contextVk,
3886                                        const vk::SamplerDesc &desc,
3887                                        vk::SamplerBinding *samplerOut)
3888 {
3889     auto iter = mPayload.find(desc);
3890     if (iter != mPayload.end())
3891     {
3892         vk::RefCountedSampler &sampler = iter->second;
3893         samplerOut->set(&sampler);
3894         mCacheStats.hit();
3895         return angle::Result::Continue;
3896     }
3897 
3898     mCacheStats.miss();
3899     vk::SamplerHelper samplerHelper(contextVk);
3900     ANGLE_TRY(desc.init(contextVk, &samplerHelper.get()));
3901 
3902     vk::RefCountedSampler newSampler(std::move(samplerHelper));
3903     auto insertedItem                      = mPayload.emplace(desc, std::move(newSampler));
3904     vk::RefCountedSampler &insertedSampler = insertedItem.first->second;
3905     samplerOut->set(&insertedSampler);
3906 
3907     contextVk->getRenderer()->getActiveHandleCounts().onAllocate(vk::HandleType::Sampler);
3908 
3909     return angle::Result::Continue;
3910 }
3911 
3912 // DriverUniformsDescriptorSetCache implementation.
destroy(RendererVk * rendererVk)3913 void DriverUniformsDescriptorSetCache::destroy(RendererVk *rendererVk)
3914 {
3915     accumulateCacheStats(rendererVk);
3916     mPayload.clear();
3917 }
3918 
3919 // DescriptorSetCache implementation.
3920 template <typename Key, VulkanCacheType CacheType>
destroy(RendererVk * rendererVk)3921 void DescriptorSetCache<Key, CacheType>::destroy(RendererVk *rendererVk)
3922 {
3923     this->accumulateCacheStats(rendererVk);
3924     mPayload.clear();
3925 }
3926 
3927 // RendererVk's methods are not accessible in vk_cache_utils.h
3928 // Below declarations are needed to avoid linker errors.
3929 // Unclear why Clang warns about weak vtables in this case.
3930 ANGLE_DISABLE_WEAK_TEMPLATE_VTABLES_WARNING
3931 template class DescriptorSetCache<vk::TextureDescriptorDesc, VulkanCacheType::TextureDescriptors>;
3932 
3933 template class DescriptorSetCache<vk::UniformsAndXfbDescriptorDesc,
3934                                   VulkanCacheType::UniformsAndXfbDescriptors>;
3935 
3936 template class DescriptorSetCache<vk::ShaderBuffersDescriptorDesc,
3937                                   VulkanCacheType::ShaderBuffersDescriptors>;
3938 ANGLE_REENABLE_WEAK_TEMPLATE_VTABLES_WARNING
3939 }  // namespace rx
3940