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