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