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