• 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 "libANGLE/BlobCache.h"
15 #include "libANGLE/VertexAttribute.h"
16 #include "libANGLE/renderer/vulkan/FramebufferVk.h"
17 #include "libANGLE/renderer/vulkan/ProgramVk.h"
18 #include "libANGLE/renderer/vulkan/RendererVk.h"
19 #include "libANGLE/renderer/vulkan/VertexArrayVk.h"
20 #include "libANGLE/renderer/vulkan/vk_format_utils.h"
21 #include "libANGLE/renderer/vulkan/vk_helpers.h"
22 
23 #include <type_traits>
24 
25 namespace rx
26 {
27 namespace vk
28 {
29 
30 namespace
31 {
32 
PackGLBlendOp(GLenum blendOp)33 uint8_t PackGLBlendOp(GLenum blendOp)
34 {
35     switch (blendOp)
36     {
37         case GL_FUNC_ADD:
38             return static_cast<uint8_t>(VK_BLEND_OP_ADD);
39         case GL_FUNC_SUBTRACT:
40             return static_cast<uint8_t>(VK_BLEND_OP_SUBTRACT);
41         case GL_FUNC_REVERSE_SUBTRACT:
42             return static_cast<uint8_t>(VK_BLEND_OP_REVERSE_SUBTRACT);
43         case GL_MIN:
44             return static_cast<uint8_t>(VK_BLEND_OP_MIN);
45         case GL_MAX:
46             return static_cast<uint8_t>(VK_BLEND_OP_MAX);
47         default:
48             UNREACHABLE();
49             return 0;
50     }
51 }
52 
PackGLBlendFactor(GLenum blendFactor)53 uint8_t PackGLBlendFactor(GLenum blendFactor)
54 {
55     switch (blendFactor)
56     {
57         case GL_ZERO:
58             return static_cast<uint8_t>(VK_BLEND_FACTOR_ZERO);
59         case GL_ONE:
60             return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE);
61         case GL_SRC_COLOR:
62             return static_cast<uint8_t>(VK_BLEND_FACTOR_SRC_COLOR);
63         case GL_DST_COLOR:
64             return static_cast<uint8_t>(VK_BLEND_FACTOR_DST_COLOR);
65         case GL_ONE_MINUS_SRC_COLOR:
66             return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR);
67         case GL_SRC_ALPHA:
68             return static_cast<uint8_t>(VK_BLEND_FACTOR_SRC_ALPHA);
69         case GL_ONE_MINUS_SRC_ALPHA:
70             return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA);
71         case GL_DST_ALPHA:
72             return static_cast<uint8_t>(VK_BLEND_FACTOR_DST_ALPHA);
73         case GL_ONE_MINUS_DST_ALPHA:
74             return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA);
75         case GL_ONE_MINUS_DST_COLOR:
76             return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR);
77         case GL_SRC_ALPHA_SATURATE:
78             return static_cast<uint8_t>(VK_BLEND_FACTOR_SRC_ALPHA_SATURATE);
79         case GL_CONSTANT_COLOR:
80             return static_cast<uint8_t>(VK_BLEND_FACTOR_CONSTANT_COLOR);
81         case GL_CONSTANT_ALPHA:
82             return static_cast<uint8_t>(VK_BLEND_FACTOR_CONSTANT_ALPHA);
83         case GL_ONE_MINUS_CONSTANT_COLOR:
84             return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR);
85         case GL_ONE_MINUS_CONSTANT_ALPHA:
86             return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA);
87         default:
88             UNREACHABLE();
89             return 0;
90     }
91 }
92 
PackGLStencilOp(GLenum compareOp)93 VkStencilOp PackGLStencilOp(GLenum compareOp)
94 {
95     switch (compareOp)
96     {
97         case GL_KEEP:
98             return VK_STENCIL_OP_KEEP;
99         case GL_ZERO:
100             return VK_STENCIL_OP_ZERO;
101         case GL_REPLACE:
102             return VK_STENCIL_OP_REPLACE;
103         case GL_INCR:
104             return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
105         case GL_DECR:
106             return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
107         case GL_INCR_WRAP:
108             return VK_STENCIL_OP_INCREMENT_AND_WRAP;
109         case GL_DECR_WRAP:
110             return VK_STENCIL_OP_DECREMENT_AND_WRAP;
111         case GL_INVERT:
112             return VK_STENCIL_OP_INVERT;
113         default:
114             UNREACHABLE();
115             return VK_STENCIL_OP_KEEP;
116     }
117 }
118 
PackGLCompareFunc(GLenum compareFunc)119 VkCompareOp PackGLCompareFunc(GLenum compareFunc)
120 {
121     switch (compareFunc)
122     {
123         case GL_NEVER:
124             return VK_COMPARE_OP_NEVER;
125         case GL_ALWAYS:
126             return VK_COMPARE_OP_ALWAYS;
127         case GL_LESS:
128             return VK_COMPARE_OP_LESS;
129         case GL_LEQUAL:
130             return VK_COMPARE_OP_LESS_OR_EQUAL;
131         case GL_EQUAL:
132             return VK_COMPARE_OP_EQUAL;
133         case GL_GREATER:
134             return VK_COMPARE_OP_GREATER;
135         case GL_GEQUAL:
136             return VK_COMPARE_OP_GREATER_OR_EQUAL;
137         case GL_NOTEQUAL:
138             return VK_COMPARE_OP_NOT_EQUAL;
139         default:
140             UNREACHABLE();
141             return VK_COMPARE_OP_NEVER;
142     }
143 }
144 
UnpackAttachmentDesc(VkAttachmentDescription * desc,const vk::Format & format,uint8_t samples,const vk::PackedAttachmentOpsDesc & ops)145 void UnpackAttachmentDesc(VkAttachmentDescription *desc,
146                           const vk::Format &format,
147                           uint8_t samples,
148                           const vk::PackedAttachmentOpsDesc &ops)
149 {
150     // We would only need this flag for duplicated attachments. Apply it conservatively.
151     desc->flags          = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT;
152     desc->format         = format.vkImageFormat;
153     desc->samples        = gl_vk::GetSamples(samples);
154     desc->loadOp         = static_cast<VkAttachmentLoadOp>(ops.loadOp);
155     desc->storeOp        = static_cast<VkAttachmentStoreOp>(ops.storeOp);
156     desc->stencilLoadOp  = static_cast<VkAttachmentLoadOp>(ops.stencilLoadOp);
157     desc->stencilStoreOp = static_cast<VkAttachmentStoreOp>(ops.stencilStoreOp);
158     desc->initialLayout =
159         ConvertImageLayoutToVkImageLayout(static_cast<ImageLayout>(ops.initialLayout));
160     desc->finalLayout =
161         ConvertImageLayoutToVkImageLayout(static_cast<ImageLayout>(ops.finalLayout));
162 }
163 
UnpackStencilState(const vk::PackedStencilOpState & packedState,uint8_t stencilReference,VkStencilOpState * stateOut)164 void UnpackStencilState(const vk::PackedStencilOpState &packedState,
165                         uint8_t stencilReference,
166                         VkStencilOpState *stateOut)
167 {
168     stateOut->failOp      = static_cast<VkStencilOp>(packedState.ops.fail);
169     stateOut->passOp      = static_cast<VkStencilOp>(packedState.ops.pass);
170     stateOut->depthFailOp = static_cast<VkStencilOp>(packedState.ops.depthFail);
171     stateOut->compareOp   = static_cast<VkCompareOp>(packedState.ops.compare);
172     stateOut->compareMask = packedState.compareMask;
173     stateOut->writeMask   = packedState.writeMask;
174     stateOut->reference   = stencilReference;
175 }
176 
UnpackBlendAttachmentState(const vk::PackedColorBlendAttachmentState & packedState,VkPipelineColorBlendAttachmentState * stateOut)177 void UnpackBlendAttachmentState(const vk::PackedColorBlendAttachmentState &packedState,
178                                 VkPipelineColorBlendAttachmentState *stateOut)
179 {
180     stateOut->srcColorBlendFactor = static_cast<VkBlendFactor>(packedState.srcColorBlendFactor);
181     stateOut->dstColorBlendFactor = static_cast<VkBlendFactor>(packedState.dstColorBlendFactor);
182     stateOut->colorBlendOp        = static_cast<VkBlendOp>(packedState.colorBlendOp);
183     stateOut->srcAlphaBlendFactor = static_cast<VkBlendFactor>(packedState.srcAlphaBlendFactor);
184     stateOut->dstAlphaBlendFactor = static_cast<VkBlendFactor>(packedState.dstAlphaBlendFactor);
185     stateOut->alphaBlendOp        = static_cast<VkBlendOp>(packedState.alphaBlendOp);
186 }
187 
SetPipelineShaderStageInfo(const VkStructureType type,const VkShaderStageFlagBits stage,const VkShaderModule module,const VkSpecializationInfo & specializationInfo,VkPipelineShaderStageCreateInfo * shaderStage)188 void SetPipelineShaderStageInfo(const VkStructureType type,
189                                 const VkShaderStageFlagBits stage,
190                                 const VkShaderModule module,
191                                 const VkSpecializationInfo &specializationInfo,
192                                 VkPipelineShaderStageCreateInfo *shaderStage)
193 {
194     shaderStage->sType               = type;
195     shaderStage->flags               = 0;
196     shaderStage->stage               = stage;
197     shaderStage->module              = module;
198     shaderStage->pName               = "main";
199     shaderStage->pSpecializationInfo = &specializationInfo;
200 }
201 
InitializeRenderPassFromDesc(vk::Context * context,const RenderPassDesc & desc,const AttachmentOpsArray & ops,RenderPass * renderPass)202 angle::Result InitializeRenderPassFromDesc(vk::Context *context,
203                                            const RenderPassDesc &desc,
204                                            const AttachmentOpsArray &ops,
205                                            RenderPass *renderPass)
206 {
207     // Unpack the packed and split representation into the format required by Vulkan.
208     gl::DrawBuffersVector<VkAttachmentReference> colorAttachmentRefs;
209     VkAttachmentReference depthStencilAttachmentRef = {VK_ATTACHMENT_UNUSED,
210                                                        VK_IMAGE_LAYOUT_UNDEFINED};
211     gl::AttachmentArray<VkAttachmentDescription> attachmentDescs;
212 
213     uint32_t colorAttachmentCount = 0;
214     uint32_t attachmentCount      = 0;
215     for (uint32_t colorIndexGL = 0; colorIndexGL < desc.colorAttachmentRange(); ++colorIndexGL)
216     {
217         // Vulkan says:
218         //
219         // > Each element of the pColorAttachments array corresponds to an output location in the
220         // > shader, i.e. if the shader declares an output variable decorated with a Location value
221         // > of X, then it uses the attachment provided in pColorAttachments[X].
222         //
223         // This means that colorAttachmentRefs is indexed by colorIndexGL.  Where the color
224         // attachment is disabled, a reference with VK_ATTACHMENT_UNUSED is given.
225 
226         if (!desc.isColorAttachmentEnabled(colorIndexGL))
227         {
228             VkAttachmentReference colorRef;
229             colorRef.attachment = VK_ATTACHMENT_UNUSED;
230             colorRef.layout     = VK_IMAGE_LAYOUT_UNDEFINED;
231             colorAttachmentRefs.push_back(colorRef);
232 
233             continue;
234         }
235 
236         uint32_t colorIndexVk    = colorAttachmentCount++;
237         angle::FormatID formatID = desc[colorIndexGL];
238         ASSERT(formatID != angle::FormatID::NONE);
239         const vk::Format &format = context->getRenderer()->getFormat(formatID);
240 
241         VkAttachmentReference colorRef;
242         colorRef.attachment = colorIndexVk;
243         colorRef.layout     = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
244 
245         colorAttachmentRefs.push_back(colorRef);
246 
247         UnpackAttachmentDesc(&attachmentDescs[colorIndexVk], format, desc.samples(),
248                              ops[colorIndexVk]);
249 
250         ++attachmentCount;
251     }
252 
253     if (desc.hasDepthStencilAttachment())
254     {
255         uint32_t depthStencilIndex   = static_cast<uint32_t>(desc.depthStencilAttachmentIndex());
256         uint32_t depthStencilIndexVk = colorAttachmentCount;
257 
258         angle::FormatID formatID = desc[depthStencilIndex];
259         ASSERT(formatID != angle::FormatID::NONE);
260         const vk::Format &format = context->getRenderer()->getFormat(formatID);
261 
262         depthStencilAttachmentRef.attachment = depthStencilIndexVk;
263         depthStencilAttachmentRef.layout     = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
264 
265         UnpackAttachmentDesc(&attachmentDescs[depthStencilIndexVk], format, desc.samples(),
266                              ops[depthStencilIndexVk]);
267 
268         ++attachmentCount;
269     }
270 
271     VkSubpassDescription subpassDesc = {};
272 
273     subpassDesc.flags                = 0;
274     subpassDesc.pipelineBindPoint    = VK_PIPELINE_BIND_POINT_GRAPHICS;
275     subpassDesc.inputAttachmentCount = 0;
276     subpassDesc.pInputAttachments    = nullptr;
277     subpassDesc.colorAttachmentCount = static_cast<uint32_t>(colorAttachmentRefs.size());
278     subpassDesc.pColorAttachments    = colorAttachmentRefs.data();
279     subpassDesc.pResolveAttachments  = nullptr;
280     subpassDesc.pDepthStencilAttachment =
281         (depthStencilAttachmentRef.attachment != VK_ATTACHMENT_UNUSED ? &depthStencilAttachmentRef
282                                                                       : nullptr);
283     subpassDesc.preserveAttachmentCount = 0;
284     subpassDesc.pPreserveAttachments    = nullptr;
285 
286     VkRenderPassCreateInfo createInfo = {};
287     createInfo.sType                  = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
288     createInfo.flags                  = 0;
289     createInfo.attachmentCount        = attachmentCount;
290     createInfo.pAttachments           = attachmentDescs.data();
291     createInfo.subpassCount           = 1;
292     createInfo.pSubpasses             = &subpassDesc;
293     createInfo.dependencyCount        = 0;
294     createInfo.pDependencies          = nullptr;
295 
296     ANGLE_VK_TRY(context, renderPass->init(context->getDevice(), createInfo));
297     return angle::Result::Continue;
298 }
299 
InitializeSpecializationInfo(vk::SpecializationConstantBitSet specConsts,vk::SpecializationConstantMap<VkSpecializationMapEntry> * specializationEntriesOut,vk::SpecializationConstantMap<VkBool32> * specializationValuesOut,VkSpecializationInfo * specializationInfoOut)300 void InitializeSpecializationInfo(
301     vk::SpecializationConstantBitSet specConsts,
302     vk::SpecializationConstantMap<VkSpecializationMapEntry> *specializationEntriesOut,
303     vk::SpecializationConstantMap<VkBool32> *specializationValuesOut,
304     VkSpecializationInfo *specializationInfoOut)
305 {
306     // Collect specialization constants.
307     for (const sh::vk::SpecializationConstantId id :
308          angle::AllEnums<sh::vk::SpecializationConstantId>())
309     {
310         const uint32_t offset                      = static_cast<uint32_t>(id);
311         (*specializationValuesOut)[id]             = specConsts.test(id);
312         (*specializationEntriesOut)[id].constantID = offset;
313         (*specializationEntriesOut)[id].offset     = offset;
314         (*specializationEntriesOut)[id].size       = sizeof(VkBool32);
315     }
316 
317     specializationInfoOut->mapEntryCount = static_cast<uint32_t>(specializationEntriesOut->size());
318     specializationInfoOut->pMapEntries   = specializationEntriesOut->data();
319     specializationInfoOut->dataSize      = specializationEntriesOut->size() * sizeof(VkBool32);
320     specializationInfoOut->pData         = specializationValuesOut->data();
321 }
322 
323 // Utility for setting a value on a packed 4-bit integer array.
324 template <typename SrcT>
Int4Array_Set(uint8_t * arrayBytes,uint32_t arrayIndex,SrcT value)325 void Int4Array_Set(uint8_t *arrayBytes, uint32_t arrayIndex, SrcT value)
326 {
327     uint32_t byteIndex = arrayIndex >> 1;
328     ASSERT(value < 16);
329 
330     if ((arrayIndex & 1) == 0)
331     {
332         arrayBytes[byteIndex] &= 0xF0;
333         arrayBytes[byteIndex] |= static_cast<uint8_t>(value);
334     }
335     else
336     {
337         arrayBytes[byteIndex] &= 0x0F;
338         arrayBytes[byteIndex] |= static_cast<uint8_t>(value) << 4;
339     }
340 }
341 
342 // Utility for getting a value from a packed 4-bit integer array.
343 template <typename DestT>
Int4Array_Get(const uint8_t * arrayBytes,uint32_t arrayIndex)344 DestT Int4Array_Get(const uint8_t *arrayBytes, uint32_t arrayIndex)
345 {
346     uint32_t byteIndex = arrayIndex >> 1;
347 
348     if ((arrayIndex & 1) == 0)
349     {
350         return static_cast<DestT>(arrayBytes[byteIndex] & 0xF);
351     }
352     else
353     {
354         return static_cast<DestT>(arrayBytes[byteIndex] >> 4);
355     }
356 }
357 
358 // When converting a byte number to a transition bit index we can shift instead of divide.
359 constexpr size_t kTransitionByteShift = Log2(kGraphicsPipelineDirtyBitBytes);
360 
361 // When converting a number of bits offset to a transition bit index we can also shift.
362 constexpr size_t kBitsPerByte        = 8;
363 constexpr size_t kTransitionBitShift = kTransitionByteShift + Log2(kBitsPerByte);
364 
365 // Helper macro to map from a PipelineDesc struct and field to a dirty bit index.
366 // Uses the 'offsetof' macro to compute the offset 'Member' within the PipelineDesc
367 // and the offset of 'Field' within 'Member'. We can optimize the dirty bit setting by computing
368 // the shifted dirty bit at compile time instead of calling "set".
369 #define ANGLE_GET_TRANSITION_BIT(Member, Field)                                      \
370     ((offsetof(GraphicsPipelineDesc, Member) + offsetof(decltype(Member), Field)) >> \
371      kTransitionByteShift)
372 
373 // Indexed dirty bits cannot be entirely computed at compile time since the index is passed to
374 // the update function.
375 #define ANGLE_GET_INDEXED_TRANSITION_BIT(Member, Field, Index, BitWidth) \
376     (((BitWidth * Index) >> kTransitionBitShift) + ANGLE_GET_TRANSITION_BIT(Member, Field))
377 
378 constexpr angle::PackedEnumMap<gl::ComponentType, VkFormat> kMismatchedComponentTypeMap = {{
379     {gl::ComponentType::Float, VK_FORMAT_R32G32B32A32_SFLOAT},
380     {gl::ComponentType::Int, VK_FORMAT_R32G32B32A32_SINT},
381     {gl::ComponentType::UnsignedInt, VK_FORMAT_R32G32B32A32_UINT},
382 }};
383 }  // anonymous namespace
384 
385 // RenderPassDesc implementation.
RenderPassDesc()386 RenderPassDesc::RenderPassDesc()
387 {
388     memset(this, 0, sizeof(RenderPassDesc));
389 }
390 
391 RenderPassDesc::~RenderPassDesc() = default;
392 
RenderPassDesc(const RenderPassDesc & other)393 RenderPassDesc::RenderPassDesc(const RenderPassDesc &other)
394 {
395     memcpy(this, &other, sizeof(RenderPassDesc));
396 }
397 
setSamples(GLint samples)398 void RenderPassDesc::setSamples(GLint samples)
399 {
400     ASSERT(samples < std::numeric_limits<uint8_t>::max());
401     mSamples = static_cast<uint8_t>(samples);
402 }
403 
packColorAttachment(size_t colorIndexGL,angle::FormatID formatID)404 void RenderPassDesc::packColorAttachment(size_t colorIndexGL, angle::FormatID formatID)
405 {
406     ASSERT(colorIndexGL < mAttachmentFormats.size());
407     static_assert(angle::kNumANGLEFormats < std::numeric_limits<uint8_t>::max(),
408                   "Too many ANGLE formats to fit in uint8_t");
409     // Force the user to pack the depth/stencil attachment last.
410     ASSERT(mHasDepthStencilAttachment == false);
411     // This function should only be called for enabled GL color attachments.`
412     ASSERT(formatID != angle::FormatID::NONE);
413 
414     uint8_t &packedFormat = mAttachmentFormats[colorIndexGL];
415     SetBitField(packedFormat, formatID);
416 
417     // Set color attachment range such that it covers the range from index 0 through last
418     // active index.  This is the reason why we need depth/stencil to be packed last.
419     mColorAttachmentRange =
420         std::max<uint8_t>(mColorAttachmentRange, static_cast<uint8_t>(colorIndexGL) + 1);
421 }
422 
packColorAttachmentGap(size_t colorIndexGL)423 void RenderPassDesc::packColorAttachmentGap(size_t colorIndexGL)
424 {
425     ASSERT(colorIndexGL < mAttachmentFormats.size());
426     static_assert(angle::kNumANGLEFormats < std::numeric_limits<uint8_t>::max(),
427                   "Too many ANGLE formats to fit in uint8_t");
428     // Force the user to pack the depth/stencil attachment last.
429     ASSERT(mHasDepthStencilAttachment == false);
430 
431     // Use NONE as a flag for gaps in GL color attachments.
432     uint8_t &packedFormat = mAttachmentFormats[colorIndexGL];
433     SetBitField(packedFormat, angle::FormatID::NONE);
434 }
435 
packDepthStencilAttachment(angle::FormatID formatID)436 void RenderPassDesc::packDepthStencilAttachment(angle::FormatID formatID)
437 {
438     // Though written as Count, there is only ever a single depth/stencil attachment.
439     ASSERT(mHasDepthStencilAttachment == false);
440 
441     size_t index = depthStencilAttachmentIndex();
442     ASSERT(index < mAttachmentFormats.size());
443 
444     uint8_t &packedFormat = mAttachmentFormats[index];
445     SetBitField(packedFormat, formatID);
446 
447     mHasDepthStencilAttachment = true;
448 }
449 
operator =(const RenderPassDesc & other)450 RenderPassDesc &RenderPassDesc::operator=(const RenderPassDesc &other)
451 {
452     memcpy(this, &other, sizeof(RenderPassDesc));
453     return *this;
454 }
455 
hash() const456 size_t RenderPassDesc::hash() const
457 {
458     return angle::ComputeGenericHash(*this);
459 }
460 
isColorAttachmentEnabled(size_t colorIndexGL) const461 bool RenderPassDesc::isColorAttachmentEnabled(size_t colorIndexGL) const
462 {
463     angle::FormatID formatID = operator[](colorIndexGL);
464     return formatID != angle::FormatID::NONE;
465 }
466 
attachmentCount() const467 size_t RenderPassDesc::attachmentCount() const
468 {
469     size_t colorAttachmentCount = 0;
470     for (size_t i = 0; i < mColorAttachmentRange; ++i)
471     {
472         colorAttachmentCount += isColorAttachmentEnabled(i);
473     }
474 
475     // Note that there are no gaps in depth/stencil attachments.  In fact there is a maximum of 1 of
476     // it.
477     return colorAttachmentCount + mHasDepthStencilAttachment;
478 }
479 
operator ==(const RenderPassDesc & lhs,const RenderPassDesc & rhs)480 bool operator==(const RenderPassDesc &lhs, const RenderPassDesc &rhs)
481 {
482     return (memcmp(&lhs, &rhs, sizeof(RenderPassDesc)) == 0);
483 }
484 
485 // GraphicsPipelineDesc implementation.
486 // Use aligned allocation and free so we can use the alignas keyword.
operator new(std::size_t size)487 void *GraphicsPipelineDesc::operator new(std::size_t size)
488 {
489     return angle::AlignedAlloc(size, 32);
490 }
491 
operator delete(void * ptr)492 void GraphicsPipelineDesc::operator delete(void *ptr)
493 {
494     return angle::AlignedFree(ptr);
495 }
496 
GraphicsPipelineDesc()497 GraphicsPipelineDesc::GraphicsPipelineDesc()
498 {
499     memset(this, 0, sizeof(GraphicsPipelineDesc));
500 }
501 
502 GraphicsPipelineDesc::~GraphicsPipelineDesc() = default;
503 
GraphicsPipelineDesc(const GraphicsPipelineDesc & other)504 GraphicsPipelineDesc::GraphicsPipelineDesc(const GraphicsPipelineDesc &other)
505 {
506     memcpy(this, &other, sizeof(GraphicsPipelineDesc));
507 }
508 
operator =(const GraphicsPipelineDesc & other)509 GraphicsPipelineDesc &GraphicsPipelineDesc::operator=(const GraphicsPipelineDesc &other)
510 {
511     memcpy(this, &other, sizeof(GraphicsPipelineDesc));
512     return *this;
513 }
514 
hash() const515 size_t GraphicsPipelineDesc::hash() const
516 {
517     return angle::ComputeGenericHash(*this);
518 }
519 
operator ==(const GraphicsPipelineDesc & other) const520 bool GraphicsPipelineDesc::operator==(const GraphicsPipelineDesc &other) const
521 {
522     return (memcmp(this, &other, sizeof(GraphicsPipelineDesc)) == 0);
523 }
524 
525 // TODO(jmadill): We should prefer using Packed GLenums. http://anglebug.com/2169
526 
527 // Initialize PSO states, it is consistent with initial value of gl::State
initDefaults()528 void GraphicsPipelineDesc::initDefaults()
529 {
530     // Set all vertex input attributes to default, the default format is Float
531     angle::FormatID defaultFormat = GetCurrentValueFormatID(gl::VertexAttribType::Float);
532     for (PackedAttribDesc &packedAttrib : mVertexInputAttribs.attribs)
533     {
534         SetBitField(packedAttrib.stride, 0);
535         SetBitField(packedAttrib.divisor, 0);
536         SetBitField(packedAttrib.format, defaultFormat);
537         SetBitField(packedAttrib.offset, 0);
538     }
539 
540     mRasterizationAndMultisampleStateInfo.bits.depthClampEnable           = 0;
541     mRasterizationAndMultisampleStateInfo.bits.rasterizationDiscardEnable = 0;
542     SetBitField(mRasterizationAndMultisampleStateInfo.bits.polygonMode, VK_POLYGON_MODE_FILL);
543     SetBitField(mRasterizationAndMultisampleStateInfo.bits.cullMode, VK_CULL_MODE_BACK_BIT);
544     SetBitField(mRasterizationAndMultisampleStateInfo.bits.frontFace,
545                 VK_FRONT_FACE_COUNTER_CLOCKWISE);
546     mRasterizationAndMultisampleStateInfo.bits.depthBiasEnable    = 0;
547     mRasterizationAndMultisampleStateInfo.depthBiasConstantFactor = 0.0f;
548     mRasterizationAndMultisampleStateInfo.depthBiasClamp          = 0.0f;
549     mRasterizationAndMultisampleStateInfo.depthBiasSlopeFactor    = 0.0f;
550     mRasterizationAndMultisampleStateInfo.lineWidth               = 1.0f;
551 
552     mRasterizationAndMultisampleStateInfo.bits.rasterizationSamples = 1;
553     mRasterizationAndMultisampleStateInfo.bits.sampleShadingEnable  = 0;
554     mRasterizationAndMultisampleStateInfo.minSampleShading          = 0.0f;
555     for (uint32_t &sampleMask : mRasterizationAndMultisampleStateInfo.sampleMask)
556     {
557         sampleMask = 0xFFFFFFFF;
558     }
559     mRasterizationAndMultisampleStateInfo.bits.alphaToCoverageEnable = 0;
560     mRasterizationAndMultisampleStateInfo.bits.alphaToOneEnable      = 0;
561 
562     mDepthStencilStateInfo.enable.depthTest  = 0;
563     mDepthStencilStateInfo.enable.depthWrite = 1;
564     SetBitField(mDepthStencilStateInfo.depthCompareOp, VK_COMPARE_OP_LESS);
565     mDepthStencilStateInfo.enable.depthBoundsTest = 0;
566     mDepthStencilStateInfo.enable.stencilTest     = 0;
567     mDepthStencilStateInfo.minDepthBounds         = 0.0f;
568     mDepthStencilStateInfo.maxDepthBounds         = 0.0f;
569     SetBitField(mDepthStencilStateInfo.front.ops.fail, VK_STENCIL_OP_KEEP);
570     SetBitField(mDepthStencilStateInfo.front.ops.pass, VK_STENCIL_OP_KEEP);
571     SetBitField(mDepthStencilStateInfo.front.ops.depthFail, VK_STENCIL_OP_KEEP);
572     SetBitField(mDepthStencilStateInfo.front.ops.compare, VK_COMPARE_OP_ALWAYS);
573     SetBitField(mDepthStencilStateInfo.front.compareMask, 0xFF);
574     SetBitField(mDepthStencilStateInfo.front.writeMask, 0xFF);
575     mDepthStencilStateInfo.frontStencilReference = 0;
576     SetBitField(mDepthStencilStateInfo.back.ops.fail, VK_STENCIL_OP_KEEP);
577     SetBitField(mDepthStencilStateInfo.back.ops.pass, VK_STENCIL_OP_KEEP);
578     SetBitField(mDepthStencilStateInfo.back.ops.depthFail, VK_STENCIL_OP_KEEP);
579     SetBitField(mDepthStencilStateInfo.back.ops.compare, VK_COMPARE_OP_ALWAYS);
580     SetBitField(mDepthStencilStateInfo.back.compareMask, 0xFF);
581     SetBitField(mDepthStencilStateInfo.back.writeMask, 0xFF);
582     mDepthStencilStateInfo.backStencilReference = 0;
583 
584     PackedInputAssemblyAndColorBlendStateInfo &inputAndBlend = mInputAssemblyAndColorBlendStateInfo;
585     inputAndBlend.logic.opEnable                             = 0;
586     inputAndBlend.logic.op          = static_cast<uint32_t>(VK_LOGIC_OP_CLEAR);
587     inputAndBlend.blendEnableMask   = 0;
588     inputAndBlend.blendConstants[0] = 0.0f;
589     inputAndBlend.blendConstants[1] = 0.0f;
590     inputAndBlend.blendConstants[2] = 0.0f;
591     inputAndBlend.blendConstants[3] = 0.0f;
592 
593     VkFlags allColorBits = (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
594                             VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
595 
596     for (uint32_t colorIndexGL = 0; colorIndexGL < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
597          ++colorIndexGL)
598     {
599         Int4Array_Set(inputAndBlend.colorWriteMaskBits, colorIndexGL, allColorBits);
600     }
601 
602     PackedColorBlendAttachmentState blendAttachmentState;
603     SetBitField(blendAttachmentState.srcColorBlendFactor, VK_BLEND_FACTOR_ONE);
604     SetBitField(blendAttachmentState.dstColorBlendFactor, VK_BLEND_FACTOR_ZERO);
605     SetBitField(blendAttachmentState.colorBlendOp, VK_BLEND_OP_ADD);
606     SetBitField(blendAttachmentState.srcAlphaBlendFactor, VK_BLEND_FACTOR_ONE);
607     SetBitField(blendAttachmentState.dstAlphaBlendFactor, VK_BLEND_FACTOR_ZERO);
608     SetBitField(blendAttachmentState.alphaBlendOp, VK_BLEND_OP_ADD);
609 
610     std::fill(&inputAndBlend.attachments[0],
611               &inputAndBlend.attachments[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS],
612               blendAttachmentState);
613 
614     inputAndBlend.primitive.topology = static_cast<uint16_t>(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
615     inputAndBlend.primitive.restartEnable = 0;
616 
617     // Viewport and scissor will be set to valid values when framebuffer being binded
618     mViewport.x        = 0.0f;
619     mViewport.y        = 0.0f;
620     mViewport.width    = 0.0f;
621     mViewport.height   = 0.0f;
622     mViewport.minDepth = 0.0f;
623     mViewport.maxDepth = 1.0f;
624 
625     mScissor.offset.x      = 0;
626     mScissor.offset.y      = 0;
627     mScissor.extent.width  = 0;
628     mScissor.extent.height = 0;
629 }
630 
initializePipeline(ContextVk * contextVk,const vk::PipelineCache & pipelineCacheVk,const RenderPass & compatibleRenderPass,const PipelineLayout & pipelineLayout,const gl::AttributesMask & activeAttribLocationsMask,const gl::ComponentTypeMask & programAttribsTypeMask,const ShaderModule * vertexModule,const ShaderModule * fragmentModule,const ShaderModule * geometryModule,vk::SpecializationConstantBitSet specConsts,Pipeline * pipelineOut) const631 angle::Result GraphicsPipelineDesc::initializePipeline(
632     ContextVk *contextVk,
633     const vk::PipelineCache &pipelineCacheVk,
634     const RenderPass &compatibleRenderPass,
635     const PipelineLayout &pipelineLayout,
636     const gl::AttributesMask &activeAttribLocationsMask,
637     const gl::ComponentTypeMask &programAttribsTypeMask,
638     const ShaderModule *vertexModule,
639     const ShaderModule *fragmentModule,
640     const ShaderModule *geometryModule,
641     vk::SpecializationConstantBitSet specConsts,
642     Pipeline *pipelineOut) const
643 {
644     angle::FixedVector<VkPipelineShaderStageCreateInfo, 3> shaderStages;
645     VkPipelineVertexInputStateCreateInfo vertexInputState     = {};
646     VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = {};
647     VkPipelineViewportStateCreateInfo viewportState           = {};
648     VkPipelineRasterizationStateCreateInfo rasterState        = {};
649     VkPipelineMultisampleStateCreateInfo multisampleState     = {};
650     VkPipelineDepthStencilStateCreateInfo depthStencilState   = {};
651     std::array<VkPipelineColorBlendAttachmentState, gl::IMPLEMENTATION_MAX_DRAW_BUFFERS>
652         blendAttachmentState;
653     VkPipelineColorBlendStateCreateInfo blendState = {};
654     VkSpecializationInfo specializationInfo        = {};
655     VkGraphicsPipelineCreateInfo createInfo        = {};
656 
657     vk::SpecializationConstantMap<VkSpecializationMapEntry> specializationEntries;
658     vk::SpecializationConstantMap<VkBool32> specializationValues;
659     InitializeSpecializationInfo(specConsts, &specializationEntries, &specializationValues,
660                                  &specializationInfo);
661 
662     // Vertex shader is always expected to be present.
663     ASSERT(vertexModule != nullptr);
664     VkPipelineShaderStageCreateInfo vertexStage = {};
665     SetPipelineShaderStageInfo(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
666                                VK_SHADER_STAGE_VERTEX_BIT, vertexModule->getHandle(),
667                                specializationInfo, &vertexStage);
668     shaderStages.push_back(vertexStage);
669 
670     if (geometryModule)
671     {
672         VkPipelineShaderStageCreateInfo geometryStage = {};
673         SetPipelineShaderStageInfo(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
674                                    VK_SHADER_STAGE_GEOMETRY_BIT, geometryModule->getHandle(),
675                                    specializationInfo, &geometryStage);
676         shaderStages.push_back(geometryStage);
677     }
678 
679     // Fragment shader is optional.
680     // anglebug.com/3509 - Don't compile the fragment shader if rasterizationDiscardEnable = true
681     if (fragmentModule && !mRasterizationAndMultisampleStateInfo.bits.rasterizationDiscardEnable)
682     {
683         VkPipelineShaderStageCreateInfo fragmentStage = {};
684         SetPipelineShaderStageInfo(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
685                                    VK_SHADER_STAGE_FRAGMENT_BIT, fragmentModule->getHandle(),
686                                    specializationInfo, &fragmentStage);
687         shaderStages.push_back(fragmentStage);
688     }
689 
690     // TODO(jmadill): Possibly use different path for ES 3.1 split bindings/attribs.
691     gl::AttribArray<VkVertexInputBindingDescription> bindingDescs;
692     gl::AttribArray<VkVertexInputAttributeDescription> attributeDescs;
693 
694     uint32_t vertexAttribCount = 0;
695 
696     size_t unpackedSize = sizeof(shaderStages) + sizeof(vertexInputState) +
697                           sizeof(inputAssemblyState) + sizeof(viewportState) + sizeof(rasterState) +
698                           sizeof(multisampleState) + sizeof(depthStencilState) +
699                           sizeof(blendAttachmentState) + sizeof(blendState) + sizeof(bindingDescs) +
700                           sizeof(attributeDescs);
701     ANGLE_UNUSED_VARIABLE(unpackedSize);
702 
703     gl::AttribArray<VkVertexInputBindingDivisorDescriptionEXT> divisorDesc;
704     VkPipelineVertexInputDivisorStateCreateInfoEXT divisorState = {};
705     divisorState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
706     divisorState.pVertexBindingDivisors = divisorDesc.data();
707     for (size_t attribIndexSizeT : activeAttribLocationsMask)
708     {
709         const uint32_t attribIndex = static_cast<uint32_t>(attribIndexSizeT);
710 
711         VkVertexInputBindingDescription &bindingDesc  = bindingDescs[vertexAttribCount];
712         VkVertexInputAttributeDescription &attribDesc = attributeDescs[vertexAttribCount];
713         const PackedAttribDesc &packedAttrib          = mVertexInputAttribs.attribs[attribIndex];
714 
715         bindingDesc.binding = attribIndex;
716         bindingDesc.stride  = static_cast<uint32_t>(packedAttrib.stride);
717         if (packedAttrib.divisor != 0)
718         {
719             bindingDesc.inputRate = static_cast<VkVertexInputRate>(VK_VERTEX_INPUT_RATE_INSTANCE);
720             divisorDesc[divisorState.vertexBindingDivisorCount].binding = bindingDesc.binding;
721             divisorDesc[divisorState.vertexBindingDivisorCount].divisor = packedAttrib.divisor;
722             ++divisorState.vertexBindingDivisorCount;
723         }
724         else
725         {
726             bindingDesc.inputRate = static_cast<VkVertexInputRate>(VK_VERTEX_INPUT_RATE_VERTEX);
727         }
728 
729         // Get the corresponding VkFormat for the attrib's format.
730         angle::FormatID formatID         = static_cast<angle::FormatID>(packedAttrib.format);
731         const vk::Format &format         = contextVk->getRenderer()->getFormat(formatID);
732         const angle::Format &angleFormat = format.intendedFormat();
733         VkFormat vkFormat                = format.vkBufferFormat;
734 
735         gl::ComponentType attribType =
736             GetVertexAttributeComponentType(angleFormat.isPureInt(), angleFormat.vertexAttribType);
737         gl::ComponentType programAttribType =
738             gl::GetComponentTypeMask(programAttribsTypeMask, attribIndex);
739 
740         if (attribType != programAttribType)
741         {
742             // Override the format with a compatible one.
743             vkFormat = kMismatchedComponentTypeMap[programAttribType];
744 
745             bindingDesc.stride = 0;  // Prevent out-of-bounds accesses.
746         }
747 
748         // The binding index could become more dynamic in ES 3.1.
749         attribDesc.binding  = attribIndex;
750         attribDesc.format   = vkFormat;
751         attribDesc.location = static_cast<uint32_t>(attribIndex);
752         attribDesc.offset   = packedAttrib.offset;
753 
754         vertexAttribCount++;
755     }
756 
757     // The binding descriptions are filled in at draw time.
758     vertexInputState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
759     vertexInputState.flags = 0;
760     vertexInputState.vertexBindingDescriptionCount   = vertexAttribCount;
761     vertexInputState.pVertexBindingDescriptions      = bindingDescs.data();
762     vertexInputState.vertexAttributeDescriptionCount = vertexAttribCount;
763     vertexInputState.pVertexAttributeDescriptions    = attributeDescs.data();
764     if (divisorState.vertexBindingDivisorCount)
765         vertexInputState.pNext = &divisorState;
766 
767     // Primitive topology is filled in at draw time.
768     inputAssemblyState.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
769     inputAssemblyState.flags = 0;
770     inputAssemblyState.topology =
771         static_cast<VkPrimitiveTopology>(mInputAssemblyAndColorBlendStateInfo.primitive.topology);
772     // http://anglebug.com/3832
773     // We currently hit a VK Validation here where VUID
774     // VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00428 is flagged because we allow
775     // primitiveRestartEnable to be true for topologies VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
776     // VK_PRIMITIVE_TOPOLOGY_LINE_LIST, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
777     // VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,
778     // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY and VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
779     // However if we force primiteRestartEnable to FALSE we fail tests.
780     // Need to identify alternate fix.
781     inputAssemblyState.primitiveRestartEnable =
782         static_cast<VkBool32>(mInputAssemblyAndColorBlendStateInfo.primitive.restartEnable);
783 
784     // Set initial viewport and scissor state.
785 
786     // 0-sized viewports are invalid in Vulkan.  We always use a scissor that at least matches the
787     // requested viewport, so it's safe to adjust the viewport size here.
788     VkViewport viewport = mViewport;
789     if (viewport.width == 0)
790     {
791         viewport.width = 1;
792     }
793     if (viewport.height == 0)
794     {
795         viewport.height = 1;
796     }
797 
798     viewportState.sType         = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
799     viewportState.flags         = 0;
800     viewportState.viewportCount = 1;
801     viewportState.pViewports    = &viewport;
802     viewportState.scissorCount  = 1;
803     viewportState.pScissors     = &mScissor;
804 
805     const PackedRasterizationAndMultisampleStateInfo &rasterAndMS =
806         mRasterizationAndMultisampleStateInfo;
807 
808     // Rasterizer state.
809     rasterState.sType            = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
810     rasterState.flags            = 0;
811     rasterState.depthClampEnable = static_cast<VkBool32>(rasterAndMS.bits.depthClampEnable);
812     rasterState.rasterizerDiscardEnable =
813         static_cast<VkBool32>(rasterAndMS.bits.rasterizationDiscardEnable);
814     rasterState.polygonMode             = static_cast<VkPolygonMode>(rasterAndMS.bits.polygonMode);
815     rasterState.cullMode                = static_cast<VkCullModeFlags>(rasterAndMS.bits.cullMode);
816     rasterState.frontFace               = static_cast<VkFrontFace>(rasterAndMS.bits.frontFace);
817     rasterState.depthBiasEnable         = static_cast<VkBool32>(rasterAndMS.bits.depthBiasEnable);
818     rasterState.depthBiasConstantFactor = rasterAndMS.depthBiasConstantFactor;
819     rasterState.depthBiasClamp          = rasterAndMS.depthBiasClamp;
820     rasterState.depthBiasSlopeFactor    = rasterAndMS.depthBiasSlopeFactor;
821     rasterState.lineWidth               = rasterAndMS.lineWidth;
822     const void **pNextPtr               = &rasterState.pNext;
823 
824     VkPipelineRasterizationLineStateCreateInfoEXT rasterLineState = {};
825     rasterLineState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT;
826     // Enable Bresenham line rasterization if available and not multisampling.
827     if (rasterAndMS.bits.rasterizationSamples <= 1 &&
828         contextVk->getFeatures().bresenhamLineRasterization.enabled)
829     {
830         rasterLineState.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;
831         *pNextPtr                             = &rasterLineState;
832         pNextPtr                              = &rasterLineState.pNext;
833     }
834 
835     VkPipelineRasterizationProvokingVertexStateCreateInfoEXT provokingVertexState = {};
836     provokingVertexState.sType =
837         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT;
838     // Always set provoking vertex mode to last if available.
839     if (contextVk->getFeatures().provokingVertex.enabled)
840     {
841         provokingVertexState.provokingVertexMode = VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT;
842         *pNextPtr                                = &provokingVertexState;
843         pNextPtr                                 = &provokingVertexState.pNext;
844     }
845     VkPipelineRasterizationStateStreamCreateInfoEXT rasterStreamState = {};
846     rasterStreamState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT;
847     if (contextVk->getFeatures().supportsTransformFeedbackExtension.enabled)
848     {
849         rasterStreamState.rasterizationStream = 0;
850         rasterState.pNext                     = &rasterLineState;
851     }
852 
853     // Multisample state.
854     multisampleState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
855     multisampleState.flags = 0;
856     multisampleState.rasterizationSamples =
857         gl_vk::GetSamples(rasterAndMS.bits.rasterizationSamples);
858     multisampleState.sampleShadingEnable =
859         static_cast<VkBool32>(rasterAndMS.bits.sampleShadingEnable);
860     multisampleState.minSampleShading = rasterAndMS.minSampleShading;
861     multisampleState.pSampleMask      = rasterAndMS.sampleMask;
862     multisampleState.alphaToCoverageEnable =
863         static_cast<VkBool32>(rasterAndMS.bits.alphaToCoverageEnable);
864     multisampleState.alphaToOneEnable = static_cast<VkBool32>(rasterAndMS.bits.alphaToOneEnable);
865 
866     // Depth/stencil state.
867     depthStencilState.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
868     depthStencilState.flags = 0;
869     depthStencilState.depthTestEnable =
870         static_cast<VkBool32>(mDepthStencilStateInfo.enable.depthTest);
871     depthStencilState.depthWriteEnable =
872         static_cast<VkBool32>(mDepthStencilStateInfo.enable.depthWrite);
873     depthStencilState.depthCompareOp =
874         static_cast<VkCompareOp>(mDepthStencilStateInfo.depthCompareOp);
875     depthStencilState.depthBoundsTestEnable =
876         static_cast<VkBool32>(mDepthStencilStateInfo.enable.depthBoundsTest);
877     depthStencilState.stencilTestEnable =
878         static_cast<VkBool32>(mDepthStencilStateInfo.enable.stencilTest);
879     UnpackStencilState(mDepthStencilStateInfo.front, mDepthStencilStateInfo.frontStencilReference,
880                        &depthStencilState.front);
881     UnpackStencilState(mDepthStencilStateInfo.back, mDepthStencilStateInfo.backStencilReference,
882                        &depthStencilState.back);
883     depthStencilState.minDepthBounds = mDepthStencilStateInfo.minDepthBounds;
884     depthStencilState.maxDepthBounds = mDepthStencilStateInfo.maxDepthBounds;
885 
886     const PackedInputAssemblyAndColorBlendStateInfo &inputAndBlend =
887         mInputAssemblyAndColorBlendStateInfo;
888 
889     blendState.sType           = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
890     blendState.flags           = 0;
891     blendState.logicOpEnable   = static_cast<VkBool32>(inputAndBlend.logic.opEnable);
892     blendState.logicOp         = static_cast<VkLogicOp>(inputAndBlend.logic.op);
893     blendState.attachmentCount = static_cast<uint32_t>(mRenderPassDesc.colorAttachmentRange());
894     blendState.pAttachments    = blendAttachmentState.data();
895 
896     for (int i = 0; i < 4; i++)
897     {
898         blendState.blendConstants[i] = inputAndBlend.blendConstants[i];
899     }
900 
901     const gl::DrawBufferMask blendEnableMask(inputAndBlend.blendEnableMask);
902 
903     for (uint32_t colorIndexGL = 0; colorIndexGL < blendState.attachmentCount; ++colorIndexGL)
904     {
905         VkPipelineColorBlendAttachmentState &state = blendAttachmentState[colorIndexGL];
906 
907         state.blendEnable = blendEnableMask[colorIndexGL] ? VK_TRUE : VK_FALSE;
908         state.colorWriteMask =
909             Int4Array_Get<VkColorComponentFlags>(inputAndBlend.colorWriteMaskBits, colorIndexGL);
910         UnpackBlendAttachmentState(inputAndBlend.attachments[colorIndexGL], &state);
911     }
912 
913     // We would define dynamic state here if it were to be used.
914 
915     createInfo.sType               = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
916     createInfo.flags               = 0;
917     createInfo.stageCount          = static_cast<uint32_t>(shaderStages.size());
918     createInfo.pStages             = shaderStages.data();
919     createInfo.pVertexInputState   = &vertexInputState;
920     createInfo.pInputAssemblyState = &inputAssemblyState;
921     createInfo.pTessellationState  = nullptr;
922     createInfo.pViewportState      = &viewportState;
923     createInfo.pRasterizationState = &rasterState;
924     createInfo.pMultisampleState   = &multisampleState;
925     createInfo.pDepthStencilState  = &depthStencilState;
926     createInfo.pColorBlendState    = &blendState;
927     createInfo.pDynamicState       = nullptr;
928     createInfo.layout              = pipelineLayout.getHandle();
929     createInfo.renderPass          = compatibleRenderPass.getHandle();
930     createInfo.subpass             = 0;
931     createInfo.basePipelineHandle  = VK_NULL_HANDLE;
932     createInfo.basePipelineIndex   = 0;
933 
934     ANGLE_VK_TRY(contextVk,
935                  pipelineOut->initGraphics(contextVk->getDevice(), createInfo, pipelineCacheVk));
936     return angle::Result::Continue;
937 }
938 
updateVertexInput(GraphicsPipelineTransitionBits * transition,uint32_t attribIndex,GLuint stride,GLuint divisor,angle::FormatID format,GLuint relativeOffset)939 void GraphicsPipelineDesc::updateVertexInput(GraphicsPipelineTransitionBits *transition,
940                                              uint32_t attribIndex,
941                                              GLuint stride,
942                                              GLuint divisor,
943                                              angle::FormatID format,
944                                              GLuint relativeOffset)
945 {
946     vk::PackedAttribDesc &packedAttrib = mVertexInputAttribs.attribs[attribIndex];
947 
948     SetBitField(packedAttrib.stride, stride);
949     SetBitField(packedAttrib.divisor, divisor);
950 
951     if (format == angle::FormatID::NONE)
952     {
953         UNIMPLEMENTED();
954     }
955 
956     SetBitField(packedAttrib.format, format);
957     SetBitField(packedAttrib.offset, relativeOffset);
958 
959     constexpr size_t kAttribBits = kPackedAttribDescSize * kBitsPerByte;
960     const size_t kBit =
961         ANGLE_GET_INDEXED_TRANSITION_BIT(mVertexInputAttribs, attribs, attribIndex, kAttribBits);
962 
963     // Cover the next dirty bit conservatively. Because each attribute is 6 bytes.
964     transition->set(kBit);
965     transition->set(kBit + 1);
966 }
967 
updateTopology(GraphicsPipelineTransitionBits * transition,gl::PrimitiveMode drawMode)968 void GraphicsPipelineDesc::updateTopology(GraphicsPipelineTransitionBits *transition,
969                                           gl::PrimitiveMode drawMode)
970 {
971     VkPrimitiveTopology vkTopology = gl_vk::GetPrimitiveTopology(drawMode);
972     SetBitField(mInputAssemblyAndColorBlendStateInfo.primitive.topology, vkTopology);
973 
974     transition->set(ANGLE_GET_TRANSITION_BIT(mInputAssemblyAndColorBlendStateInfo, primitive));
975 }
976 
updatePrimitiveRestartEnabled(GraphicsPipelineTransitionBits * transition,bool primitiveRestartEnabled)977 void GraphicsPipelineDesc::updatePrimitiveRestartEnabled(GraphicsPipelineTransitionBits *transition,
978                                                          bool primitiveRestartEnabled)
979 {
980     mInputAssemblyAndColorBlendStateInfo.primitive.restartEnable =
981         static_cast<uint16_t>(primitiveRestartEnabled);
982     transition->set(ANGLE_GET_TRANSITION_BIT(mInputAssemblyAndColorBlendStateInfo, primitive));
983 }
984 
setCullMode(VkCullModeFlagBits cullMode)985 void GraphicsPipelineDesc::setCullMode(VkCullModeFlagBits cullMode)
986 {
987     SetBitField(mRasterizationAndMultisampleStateInfo.bits.cullMode, cullMode);
988 }
989 
updateCullMode(GraphicsPipelineTransitionBits * transition,const gl::RasterizerState & rasterState)990 void GraphicsPipelineDesc::updateCullMode(GraphicsPipelineTransitionBits *transition,
991                                           const gl::RasterizerState &rasterState)
992 {
993     setCullMode(gl_vk::GetCullMode(rasterState));
994     transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, bits));
995 }
996 
updateFrontFace(GraphicsPipelineTransitionBits * transition,const gl::RasterizerState & rasterState,bool invertFrontFace)997 void GraphicsPipelineDesc::updateFrontFace(GraphicsPipelineTransitionBits *transition,
998                                            const gl::RasterizerState &rasterState,
999                                            bool invertFrontFace)
1000 {
1001     mRasterizationAndMultisampleStateInfo.bits.frontFace =
1002         static_cast<uint16_t>(gl_vk::GetFrontFace(rasterState.frontFace, invertFrontFace));
1003     transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, bits));
1004 }
1005 
updateLineWidth(GraphicsPipelineTransitionBits * transition,float lineWidth)1006 void GraphicsPipelineDesc::updateLineWidth(GraphicsPipelineTransitionBits *transition,
1007                                            float lineWidth)
1008 {
1009     mRasterizationAndMultisampleStateInfo.lineWidth = lineWidth;
1010     transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, lineWidth));
1011 }
1012 
updateRasterizerDiscardEnabled(GraphicsPipelineTransitionBits * transition,bool rasterizerDiscardEnabled)1013 void GraphicsPipelineDesc::updateRasterizerDiscardEnabled(
1014     GraphicsPipelineTransitionBits *transition,
1015     bool rasterizerDiscardEnabled)
1016 {
1017     mRasterizationAndMultisampleStateInfo.bits.rasterizationDiscardEnable =
1018         static_cast<uint32_t>(rasterizerDiscardEnabled);
1019     transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, bits));
1020 }
1021 
getRasterizationSamples() const1022 uint32_t GraphicsPipelineDesc::getRasterizationSamples() const
1023 {
1024     return mRasterizationAndMultisampleStateInfo.bits.rasterizationSamples;
1025 }
1026 
setRasterizationSamples(uint32_t rasterizationSamples)1027 void GraphicsPipelineDesc::setRasterizationSamples(uint32_t rasterizationSamples)
1028 {
1029     mRasterizationAndMultisampleStateInfo.bits.rasterizationSamples = rasterizationSamples;
1030 }
1031 
updateRasterizationSamples(GraphicsPipelineTransitionBits * transition,uint32_t rasterizationSamples)1032 void GraphicsPipelineDesc::updateRasterizationSamples(GraphicsPipelineTransitionBits *transition,
1033                                                       uint32_t rasterizationSamples)
1034 {
1035     setRasterizationSamples(rasterizationSamples);
1036     transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, bits));
1037 }
1038 
updateAlphaToCoverageEnable(GraphicsPipelineTransitionBits * transition,bool enable)1039 void GraphicsPipelineDesc::updateAlphaToCoverageEnable(GraphicsPipelineTransitionBits *transition,
1040                                                        bool enable)
1041 {
1042     mRasterizationAndMultisampleStateInfo.bits.alphaToCoverageEnable = enable;
1043     transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, bits));
1044 }
1045 
updateAlphaToOneEnable(GraphicsPipelineTransitionBits * transition,bool enable)1046 void GraphicsPipelineDesc::updateAlphaToOneEnable(GraphicsPipelineTransitionBits *transition,
1047                                                   bool enable)
1048 {
1049     mRasterizationAndMultisampleStateInfo.bits.alphaToOneEnable = enable;
1050     transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, bits));
1051 }
1052 
updateSampleMask(GraphicsPipelineTransitionBits * transition,uint32_t maskNumber,uint32_t mask)1053 void GraphicsPipelineDesc::updateSampleMask(GraphicsPipelineTransitionBits *transition,
1054                                             uint32_t maskNumber,
1055                                             uint32_t mask)
1056 {
1057     ASSERT(maskNumber < gl::MAX_SAMPLE_MASK_WORDS);
1058     mRasterizationAndMultisampleStateInfo.sampleMask[maskNumber] = mask;
1059 
1060     constexpr size_t kMaskBits =
1061         sizeof(mRasterizationAndMultisampleStateInfo.sampleMask[0]) * kBitsPerByte;
1062     transition->set(ANGLE_GET_INDEXED_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo,
1063                                                      sampleMask, maskNumber, kMaskBits));
1064 }
1065 
updateBlendColor(GraphicsPipelineTransitionBits * transition,const gl::ColorF & color)1066 void GraphicsPipelineDesc::updateBlendColor(GraphicsPipelineTransitionBits *transition,
1067                                             const gl::ColorF &color)
1068 {
1069     mInputAssemblyAndColorBlendStateInfo.blendConstants[0] = color.red;
1070     mInputAssemblyAndColorBlendStateInfo.blendConstants[1] = color.green;
1071     mInputAssemblyAndColorBlendStateInfo.blendConstants[2] = color.blue;
1072     mInputAssemblyAndColorBlendStateInfo.blendConstants[3] = color.alpha;
1073     constexpr size_t kSize = sizeof(mInputAssemblyAndColorBlendStateInfo.blendConstants[0]) * 8;
1074 
1075     for (int index = 0; index < 4; ++index)
1076     {
1077         const size_t kBit = ANGLE_GET_INDEXED_TRANSITION_BIT(mInputAssemblyAndColorBlendStateInfo,
1078                                                              blendConstants, index, kSize);
1079         transition->set(kBit);
1080     }
1081 }
1082 
updateBlendEnabled(GraphicsPipelineTransitionBits * transition,bool isBlendEnabled)1083 void GraphicsPipelineDesc::updateBlendEnabled(GraphicsPipelineTransitionBits *transition,
1084                                               bool isBlendEnabled)
1085 {
1086     gl::DrawBufferMask blendEnabled;
1087     if (isBlendEnabled)
1088         blendEnabled.set();
1089     mInputAssemblyAndColorBlendStateInfo.blendEnableMask =
1090         static_cast<uint8_t>(blendEnabled.bits());
1091     transition->set(
1092         ANGLE_GET_TRANSITION_BIT(mInputAssemblyAndColorBlendStateInfo, blendEnableMask));
1093 }
1094 
updateBlendEquations(GraphicsPipelineTransitionBits * transition,const gl::BlendState & blendState)1095 void GraphicsPipelineDesc::updateBlendEquations(GraphicsPipelineTransitionBits *transition,
1096                                                 const gl::BlendState &blendState)
1097 {
1098     constexpr size_t kSize = sizeof(PackedColorBlendAttachmentState) * 8;
1099 
1100     for (size_t attachmentIndex = 0; attachmentIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
1101          ++attachmentIndex)
1102     {
1103         PackedColorBlendAttachmentState &blendAttachmentState =
1104             mInputAssemblyAndColorBlendStateInfo.attachments[attachmentIndex];
1105         blendAttachmentState.colorBlendOp = PackGLBlendOp(blendState.blendEquationRGB);
1106         blendAttachmentState.alphaBlendOp = PackGLBlendOp(blendState.blendEquationAlpha);
1107         transition->set(ANGLE_GET_INDEXED_TRANSITION_BIT(mInputAssemblyAndColorBlendStateInfo,
1108                                                          attachments, attachmentIndex, kSize));
1109     }
1110 }
1111 
updateBlendFuncs(GraphicsPipelineTransitionBits * transition,const gl::BlendState & blendState)1112 void GraphicsPipelineDesc::updateBlendFuncs(GraphicsPipelineTransitionBits *transition,
1113                                             const gl::BlendState &blendState)
1114 {
1115     constexpr size_t kSize = sizeof(PackedColorBlendAttachmentState) * 8;
1116     for (size_t attachmentIndex = 0; attachmentIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
1117          ++attachmentIndex)
1118     {
1119         PackedColorBlendAttachmentState &blendAttachmentState =
1120             mInputAssemblyAndColorBlendStateInfo.attachments[attachmentIndex];
1121         blendAttachmentState.srcColorBlendFactor = PackGLBlendFactor(blendState.sourceBlendRGB);
1122         blendAttachmentState.dstColorBlendFactor = PackGLBlendFactor(blendState.destBlendRGB);
1123         blendAttachmentState.srcAlphaBlendFactor = PackGLBlendFactor(blendState.sourceBlendAlpha);
1124         blendAttachmentState.dstAlphaBlendFactor = PackGLBlendFactor(blendState.destBlendAlpha);
1125         transition->set(ANGLE_GET_INDEXED_TRANSITION_BIT(mInputAssemblyAndColorBlendStateInfo,
1126                                                          attachments, attachmentIndex, kSize));
1127     }
1128 }
1129 
setColorWriteMask(VkColorComponentFlags colorComponentFlags,const gl::DrawBufferMask & alphaMask)1130 void GraphicsPipelineDesc::setColorWriteMask(VkColorComponentFlags colorComponentFlags,
1131                                              const gl::DrawBufferMask &alphaMask)
1132 {
1133     PackedInputAssemblyAndColorBlendStateInfo &inputAndBlend = mInputAssemblyAndColorBlendStateInfo;
1134     uint8_t colorMask = static_cast<uint8_t>(colorComponentFlags);
1135 
1136     for (uint32_t colorIndexGL = 0; colorIndexGL < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
1137          colorIndexGL++)
1138     {
1139         uint8_t mask =
1140             alphaMask[colorIndexGL] ? (colorMask & ~VK_COLOR_COMPONENT_A_BIT) : colorMask;
1141         Int4Array_Set(inputAndBlend.colorWriteMaskBits, colorIndexGL, mask);
1142     }
1143 }
1144 
setSingleColorWriteMask(uint32_t colorIndexGL,VkColorComponentFlags colorComponentFlags)1145 void GraphicsPipelineDesc::setSingleColorWriteMask(uint32_t colorIndexGL,
1146                                                    VkColorComponentFlags colorComponentFlags)
1147 {
1148     PackedInputAssemblyAndColorBlendStateInfo &inputAndBlend = mInputAssemblyAndColorBlendStateInfo;
1149     uint8_t colorMask = static_cast<uint8_t>(colorComponentFlags);
1150     Int4Array_Set(inputAndBlend.colorWriteMaskBits, colorIndexGL, colorMask);
1151 }
1152 
updateColorWriteMask(GraphicsPipelineTransitionBits * transition,VkColorComponentFlags colorComponentFlags,const gl::DrawBufferMask & alphaMask)1153 void GraphicsPipelineDesc::updateColorWriteMask(GraphicsPipelineTransitionBits *transition,
1154                                                 VkColorComponentFlags colorComponentFlags,
1155                                                 const gl::DrawBufferMask &alphaMask)
1156 {
1157     setColorWriteMask(colorComponentFlags, alphaMask);
1158 
1159     for (size_t colorIndexGL = 0; colorIndexGL < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
1160          colorIndexGL++)
1161     {
1162         transition->set(ANGLE_GET_INDEXED_TRANSITION_BIT(mInputAssemblyAndColorBlendStateInfo,
1163                                                          colorWriteMaskBits, colorIndexGL, 4));
1164     }
1165 }
1166 
setDepthTestEnabled(bool enabled)1167 void GraphicsPipelineDesc::setDepthTestEnabled(bool enabled)
1168 {
1169     mDepthStencilStateInfo.enable.depthTest = enabled;
1170 }
1171 
setDepthWriteEnabled(bool enabled)1172 void GraphicsPipelineDesc::setDepthWriteEnabled(bool enabled)
1173 {
1174     mDepthStencilStateInfo.enable.depthWrite = enabled;
1175 }
1176 
setDepthFunc(VkCompareOp op)1177 void GraphicsPipelineDesc::setDepthFunc(VkCompareOp op)
1178 {
1179     SetBitField(mDepthStencilStateInfo.depthCompareOp, op);
1180 }
1181 
setStencilTestEnabled(bool enabled)1182 void GraphicsPipelineDesc::setStencilTestEnabled(bool enabled)
1183 {
1184     mDepthStencilStateInfo.enable.stencilTest = enabled;
1185 }
1186 
setStencilFrontFuncs(uint8_t reference,VkCompareOp compareOp,uint8_t compareMask)1187 void GraphicsPipelineDesc::setStencilFrontFuncs(uint8_t reference,
1188                                                 VkCompareOp compareOp,
1189                                                 uint8_t compareMask)
1190 {
1191     mDepthStencilStateInfo.frontStencilReference = reference;
1192     mDepthStencilStateInfo.front.compareMask     = compareMask;
1193     SetBitField(mDepthStencilStateInfo.front.ops.compare, compareOp);
1194 }
1195 
setStencilBackFuncs(uint8_t reference,VkCompareOp compareOp,uint8_t compareMask)1196 void GraphicsPipelineDesc::setStencilBackFuncs(uint8_t reference,
1197                                                VkCompareOp compareOp,
1198                                                uint8_t compareMask)
1199 {
1200     mDepthStencilStateInfo.backStencilReference = reference;
1201     mDepthStencilStateInfo.back.compareMask     = compareMask;
1202     SetBitField(mDepthStencilStateInfo.back.ops.compare, compareOp);
1203 }
1204 
setStencilFrontOps(VkStencilOp failOp,VkStencilOp passOp,VkStencilOp depthFailOp)1205 void GraphicsPipelineDesc::setStencilFrontOps(VkStencilOp failOp,
1206                                               VkStencilOp passOp,
1207                                               VkStencilOp depthFailOp)
1208 {
1209     SetBitField(mDepthStencilStateInfo.front.ops.fail, failOp);
1210     SetBitField(mDepthStencilStateInfo.front.ops.pass, passOp);
1211     SetBitField(mDepthStencilStateInfo.front.ops.depthFail, depthFailOp);
1212 }
1213 
setStencilBackOps(VkStencilOp failOp,VkStencilOp passOp,VkStencilOp depthFailOp)1214 void GraphicsPipelineDesc::setStencilBackOps(VkStencilOp failOp,
1215                                              VkStencilOp passOp,
1216                                              VkStencilOp depthFailOp)
1217 {
1218     SetBitField(mDepthStencilStateInfo.back.ops.fail, failOp);
1219     SetBitField(mDepthStencilStateInfo.back.ops.pass, passOp);
1220     SetBitField(mDepthStencilStateInfo.back.ops.depthFail, depthFailOp);
1221 }
1222 
setStencilFrontWriteMask(uint8_t mask)1223 void GraphicsPipelineDesc::setStencilFrontWriteMask(uint8_t mask)
1224 {
1225     mDepthStencilStateInfo.front.writeMask = mask;
1226 }
1227 
setStencilBackWriteMask(uint8_t mask)1228 void GraphicsPipelineDesc::setStencilBackWriteMask(uint8_t mask)
1229 {
1230     mDepthStencilStateInfo.back.writeMask = mask;
1231 }
1232 
updateDepthTestEnabled(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState,const gl::Framebuffer * drawFramebuffer)1233 void GraphicsPipelineDesc::updateDepthTestEnabled(GraphicsPipelineTransitionBits *transition,
1234                                                   const gl::DepthStencilState &depthStencilState,
1235                                                   const gl::Framebuffer *drawFramebuffer)
1236 {
1237     // Only enable the depth test if the draw framebuffer has a depth buffer.  It's possible that
1238     // we're emulating a stencil-only buffer with a depth-stencil buffer
1239     setDepthTestEnabled(depthStencilState.depthTest && drawFramebuffer->hasDepth());
1240     transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, enable));
1241 }
1242 
updateDepthFunc(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState)1243 void GraphicsPipelineDesc::updateDepthFunc(GraphicsPipelineTransitionBits *transition,
1244                                            const gl::DepthStencilState &depthStencilState)
1245 {
1246     setDepthFunc(PackGLCompareFunc(depthStencilState.depthFunc));
1247     transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, depthCompareOp));
1248 }
1249 
updateDepthWriteEnabled(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState,const gl::Framebuffer * drawFramebuffer)1250 void GraphicsPipelineDesc::updateDepthWriteEnabled(GraphicsPipelineTransitionBits *transition,
1251                                                    const gl::DepthStencilState &depthStencilState,
1252                                                    const gl::Framebuffer *drawFramebuffer)
1253 {
1254     // Don't write to depth buffers that should not exist
1255     setDepthWriteEnabled(drawFramebuffer->hasDepth() ? depthStencilState.depthMask : false);
1256     transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, enable));
1257 }
1258 
updateStencilTestEnabled(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState,const gl::Framebuffer * drawFramebuffer)1259 void GraphicsPipelineDesc::updateStencilTestEnabled(GraphicsPipelineTransitionBits *transition,
1260                                                     const gl::DepthStencilState &depthStencilState,
1261                                                     const gl::Framebuffer *drawFramebuffer)
1262 {
1263     // Only enable the stencil test if the draw framebuffer has a stencil buffer.  It's possible
1264     // that we're emulating a depth-only buffer with a depth-stencil buffer
1265     setStencilTestEnabled(depthStencilState.stencilTest && drawFramebuffer->hasStencil());
1266     transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, enable));
1267 }
1268 
updateStencilFrontFuncs(GraphicsPipelineTransitionBits * transition,GLint ref,const gl::DepthStencilState & depthStencilState)1269 void GraphicsPipelineDesc::updateStencilFrontFuncs(GraphicsPipelineTransitionBits *transition,
1270                                                    GLint ref,
1271                                                    const gl::DepthStencilState &depthStencilState)
1272 {
1273     setStencilFrontFuncs(static_cast<uint8_t>(ref),
1274                          PackGLCompareFunc(depthStencilState.stencilFunc),
1275                          static_cast<uint8_t>(depthStencilState.stencilMask));
1276     transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, front));
1277     transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, frontStencilReference));
1278 }
1279 
updateStencilBackFuncs(GraphicsPipelineTransitionBits * transition,GLint ref,const gl::DepthStencilState & depthStencilState)1280 void GraphicsPipelineDesc::updateStencilBackFuncs(GraphicsPipelineTransitionBits *transition,
1281                                                   GLint ref,
1282                                                   const gl::DepthStencilState &depthStencilState)
1283 {
1284     setStencilBackFuncs(static_cast<uint8_t>(ref),
1285                         PackGLCompareFunc(depthStencilState.stencilBackFunc),
1286                         static_cast<uint8_t>(depthStencilState.stencilBackMask));
1287     transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, back));
1288     transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, backStencilReference));
1289 }
1290 
updateStencilFrontOps(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState)1291 void GraphicsPipelineDesc::updateStencilFrontOps(GraphicsPipelineTransitionBits *transition,
1292                                                  const gl::DepthStencilState &depthStencilState)
1293 {
1294     setStencilFrontOps(PackGLStencilOp(depthStencilState.stencilFail),
1295                        PackGLStencilOp(depthStencilState.stencilPassDepthPass),
1296                        PackGLStencilOp(depthStencilState.stencilPassDepthFail));
1297     transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, front));
1298 }
1299 
updateStencilBackOps(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState)1300 void GraphicsPipelineDesc::updateStencilBackOps(GraphicsPipelineTransitionBits *transition,
1301                                                 const gl::DepthStencilState &depthStencilState)
1302 {
1303     setStencilBackOps(PackGLStencilOp(depthStencilState.stencilBackFail),
1304                       PackGLStencilOp(depthStencilState.stencilBackPassDepthPass),
1305                       PackGLStencilOp(depthStencilState.stencilBackPassDepthFail));
1306     transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, back));
1307 }
1308 
updateStencilFrontWriteMask(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState,const gl::Framebuffer * drawFramebuffer)1309 void GraphicsPipelineDesc::updateStencilFrontWriteMask(
1310     GraphicsPipelineTransitionBits *transition,
1311     const gl::DepthStencilState &depthStencilState,
1312     const gl::Framebuffer *drawFramebuffer)
1313 {
1314     // Don't write to stencil buffers that should not exist
1315     setStencilFrontWriteMask(static_cast<uint8_t>(
1316         drawFramebuffer->hasStencil() ? depthStencilState.stencilWritemask : 0));
1317     transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, front));
1318 }
1319 
updateStencilBackWriteMask(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState,const gl::Framebuffer * drawFramebuffer)1320 void GraphicsPipelineDesc::updateStencilBackWriteMask(
1321     GraphicsPipelineTransitionBits *transition,
1322     const gl::DepthStencilState &depthStencilState,
1323     const gl::Framebuffer *drawFramebuffer)
1324 {
1325     // Don't write to stencil buffers that should not exist
1326     setStencilBackWriteMask(static_cast<uint8_t>(
1327         drawFramebuffer->hasStencil() ? depthStencilState.stencilBackWritemask : 0));
1328     transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, back));
1329 }
1330 
updatePolygonOffsetFillEnabled(GraphicsPipelineTransitionBits * transition,bool enabled)1331 void GraphicsPipelineDesc::updatePolygonOffsetFillEnabled(
1332     GraphicsPipelineTransitionBits *transition,
1333     bool enabled)
1334 {
1335     mRasterizationAndMultisampleStateInfo.bits.depthBiasEnable = enabled;
1336     transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, bits));
1337 }
1338 
updatePolygonOffset(GraphicsPipelineTransitionBits * transition,const gl::RasterizerState & rasterState)1339 void GraphicsPipelineDesc::updatePolygonOffset(GraphicsPipelineTransitionBits *transition,
1340                                                const gl::RasterizerState &rasterState)
1341 {
1342     mRasterizationAndMultisampleStateInfo.depthBiasSlopeFactor    = rasterState.polygonOffsetFactor;
1343     mRasterizationAndMultisampleStateInfo.depthBiasConstantFactor = rasterState.polygonOffsetUnits;
1344     transition->set(
1345         ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, depthBiasSlopeFactor));
1346     transition->set(
1347         ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, depthBiasConstantFactor));
1348 }
1349 
setRenderPassDesc(const RenderPassDesc & renderPassDesc)1350 void GraphicsPipelineDesc::setRenderPassDesc(const RenderPassDesc &renderPassDesc)
1351 {
1352     mRenderPassDesc = renderPassDesc;
1353 }
1354 
setViewport(const VkViewport & viewport)1355 void GraphicsPipelineDesc::setViewport(const VkViewport &viewport)
1356 {
1357     mViewport = viewport;
1358 }
1359 
updateViewport(GraphicsPipelineTransitionBits * transition,const VkViewport & viewport)1360 void GraphicsPipelineDesc::updateViewport(GraphicsPipelineTransitionBits *transition,
1361                                           const VkViewport &viewport)
1362 {
1363     mViewport = viewport;
1364     transition->set(ANGLE_GET_TRANSITION_BIT(mViewport, x));
1365     transition->set(ANGLE_GET_TRANSITION_BIT(mViewport, y));
1366     transition->set(ANGLE_GET_TRANSITION_BIT(mViewport, width));
1367     transition->set(ANGLE_GET_TRANSITION_BIT(mViewport, height));
1368     transition->set(ANGLE_GET_TRANSITION_BIT(mViewport, minDepth));
1369     transition->set(ANGLE_GET_TRANSITION_BIT(mViewport, maxDepth));
1370 }
1371 
updateDepthRange(GraphicsPipelineTransitionBits * transition,float nearPlane,float farPlane)1372 void GraphicsPipelineDesc::updateDepthRange(GraphicsPipelineTransitionBits *transition,
1373                                             float nearPlane,
1374                                             float farPlane)
1375 {
1376     // GLES2.0 Section 2.12.1: Each of n and f are clamped to lie within [0, 1], as are all
1377     // arguments of type clampf.
1378     ASSERT(nearPlane >= 0.0f && nearPlane <= 1.0f);
1379     ASSERT(farPlane >= 0.0f && farPlane <= 1.0f);
1380     mViewport.minDepth = nearPlane;
1381     mViewport.maxDepth = farPlane;
1382     transition->set(ANGLE_GET_TRANSITION_BIT(mViewport, minDepth));
1383     transition->set(ANGLE_GET_TRANSITION_BIT(mViewport, maxDepth));
1384 }
1385 
setScissor(const VkRect2D & scissor)1386 void GraphicsPipelineDesc::setScissor(const VkRect2D &scissor)
1387 {
1388     mScissor = scissor;
1389 }
1390 
updateScissor(GraphicsPipelineTransitionBits * transition,const VkRect2D & scissor)1391 void GraphicsPipelineDesc::updateScissor(GraphicsPipelineTransitionBits *transition,
1392                                          const VkRect2D &scissor)
1393 {
1394     mScissor = scissor;
1395     transition->set(ANGLE_GET_TRANSITION_BIT(mScissor, offset.x));
1396     transition->set(ANGLE_GET_TRANSITION_BIT(mScissor, offset.y));
1397     transition->set(ANGLE_GET_TRANSITION_BIT(mScissor, extent.width));
1398     transition->set(ANGLE_GET_TRANSITION_BIT(mScissor, extent.height));
1399 }
1400 
updateRenderPassDesc(GraphicsPipelineTransitionBits * transition,const RenderPassDesc & renderPassDesc)1401 void GraphicsPipelineDesc::updateRenderPassDesc(GraphicsPipelineTransitionBits *transition,
1402                                                 const RenderPassDesc &renderPassDesc)
1403 {
1404     setRenderPassDesc(renderPassDesc);
1405 
1406     // The RenderPass is a special case where it spans multiple bits but has no member.
1407     constexpr size_t kFirstBit =
1408         offsetof(GraphicsPipelineDesc, mRenderPassDesc) >> kTransitionByteShift;
1409     constexpr size_t kBitCount = kRenderPassDescSize >> kTransitionByteShift;
1410     for (size_t bit = 0; bit < kBitCount; ++bit)
1411     {
1412         transition->set(kFirstBit + bit);
1413     }
1414 }
1415 
1416 // AttachmentOpsArray implementation.
AttachmentOpsArray()1417 AttachmentOpsArray::AttachmentOpsArray()
1418 {
1419     memset(&mOps, 0, sizeof(PackedAttachmentOpsDesc) * mOps.size());
1420 }
1421 
1422 AttachmentOpsArray::~AttachmentOpsArray() = default;
1423 
AttachmentOpsArray(const AttachmentOpsArray & other)1424 AttachmentOpsArray::AttachmentOpsArray(const AttachmentOpsArray &other)
1425 {
1426     memcpy(&mOps, &other.mOps, sizeof(PackedAttachmentOpsDesc) * mOps.size());
1427 }
1428 
operator =(const AttachmentOpsArray & other)1429 AttachmentOpsArray &AttachmentOpsArray::operator=(const AttachmentOpsArray &other)
1430 {
1431     memcpy(&mOps, &other.mOps, sizeof(PackedAttachmentOpsDesc) * mOps.size());
1432     return *this;
1433 }
1434 
operator [](size_t index) const1435 const PackedAttachmentOpsDesc &AttachmentOpsArray::operator[](size_t index) const
1436 {
1437     return mOps[index];
1438 }
1439 
operator [](size_t index)1440 PackedAttachmentOpsDesc &AttachmentOpsArray::operator[](size_t index)
1441 {
1442     return mOps[index];
1443 }
1444 
initDummyOp(size_t index,ImageLayout initialLayout,ImageLayout finalLayout)1445 void AttachmentOpsArray::initDummyOp(size_t index,
1446                                      ImageLayout initialLayout,
1447                                      ImageLayout finalLayout)
1448 {
1449     PackedAttachmentOpsDesc &ops = mOps[index];
1450 
1451     SetBitField(ops.initialLayout, initialLayout);
1452     SetBitField(ops.finalLayout, finalLayout);
1453     SetBitField(ops.loadOp, VK_ATTACHMENT_LOAD_OP_LOAD);
1454     SetBitField(ops.stencilLoadOp, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
1455     SetBitField(ops.storeOp, VK_ATTACHMENT_STORE_OP_STORE);
1456     SetBitField(ops.stencilStoreOp, VK_ATTACHMENT_STORE_OP_DONT_CARE);
1457 }
1458 
initWithStore(size_t index,VkAttachmentLoadOp loadOp,ImageLayout initialLayout,ImageLayout finalLayout)1459 void AttachmentOpsArray::initWithStore(size_t index,
1460                                        VkAttachmentLoadOp loadOp,
1461                                        ImageLayout initialLayout,
1462                                        ImageLayout finalLayout)
1463 {
1464     PackedAttachmentOpsDesc &ops = mOps[index];
1465 
1466     SetBitField(ops.initialLayout, initialLayout);
1467     SetBitField(ops.finalLayout, finalLayout);
1468     SetBitField(ops.loadOp, loadOp);
1469     SetBitField(ops.stencilLoadOp, loadOp);
1470     SetBitField(ops.storeOp, VK_ATTACHMENT_STORE_OP_STORE);
1471     SetBitField(ops.stencilStoreOp, VK_ATTACHMENT_STORE_OP_STORE);
1472 }
1473 
hash() const1474 size_t AttachmentOpsArray::hash() const
1475 {
1476     return angle::ComputeGenericHash(mOps);
1477 }
1478 
operator ==(const AttachmentOpsArray & lhs,const AttachmentOpsArray & rhs)1479 bool operator==(const AttachmentOpsArray &lhs, const AttachmentOpsArray &rhs)
1480 {
1481     return (memcmp(&lhs, &rhs, sizeof(AttachmentOpsArray)) == 0);
1482 }
1483 
1484 // DescriptorSetLayoutDesc implementation.
DescriptorSetLayoutDesc()1485 DescriptorSetLayoutDesc::DescriptorSetLayoutDesc() : mPackedDescriptorSetLayout{} {}
1486 
1487 DescriptorSetLayoutDesc::~DescriptorSetLayoutDesc() = default;
1488 
1489 DescriptorSetLayoutDesc::DescriptorSetLayoutDesc(const DescriptorSetLayoutDesc &other) = default;
1490 
1491 DescriptorSetLayoutDesc &DescriptorSetLayoutDesc::operator=(const DescriptorSetLayoutDesc &other) =
1492     default;
1493 
hash() const1494 size_t DescriptorSetLayoutDesc::hash() const
1495 {
1496     return angle::ComputeGenericHash(mPackedDescriptorSetLayout);
1497 }
1498 
operator ==(const DescriptorSetLayoutDesc & other) const1499 bool DescriptorSetLayoutDesc::operator==(const DescriptorSetLayoutDesc &other) const
1500 {
1501     return (memcmp(&mPackedDescriptorSetLayout, &other.mPackedDescriptorSetLayout,
1502                    sizeof(mPackedDescriptorSetLayout)) == 0);
1503 }
1504 
update(uint32_t bindingIndex,VkDescriptorType type,uint32_t count,VkShaderStageFlags stages)1505 void DescriptorSetLayoutDesc::update(uint32_t bindingIndex,
1506                                      VkDescriptorType type,
1507                                      uint32_t count,
1508                                      VkShaderStageFlags stages)
1509 {
1510     ASSERT(static_cast<size_t>(type) < std::numeric_limits<uint16_t>::max());
1511     ASSERT(count < std::numeric_limits<uint16_t>::max());
1512 
1513     PackedDescriptorSetBinding &packedBinding = mPackedDescriptorSetLayout[bindingIndex];
1514 
1515     SetBitField(packedBinding.type, type);
1516     SetBitField(packedBinding.count, count);
1517     SetBitField(packedBinding.stages, stages);
1518 }
1519 
unpackBindings(DescriptorSetLayoutBindingVector * bindings) const1520 void DescriptorSetLayoutDesc::unpackBindings(DescriptorSetLayoutBindingVector *bindings) const
1521 {
1522     for (uint32_t bindingIndex = 0; bindingIndex < kMaxDescriptorSetLayoutBindings; ++bindingIndex)
1523     {
1524         const PackedDescriptorSetBinding &packedBinding = mPackedDescriptorSetLayout[bindingIndex];
1525         if (packedBinding.count == 0)
1526             continue;
1527 
1528         VkDescriptorSetLayoutBinding binding = {};
1529         binding.binding                      = bindingIndex;
1530         binding.descriptorCount              = packedBinding.count;
1531         binding.descriptorType               = static_cast<VkDescriptorType>(packedBinding.type);
1532         binding.stageFlags         = static_cast<VkShaderStageFlags>(packedBinding.stages);
1533         binding.pImmutableSamplers = nullptr;
1534 
1535         bindings->push_back(binding);
1536     }
1537 }
1538 
1539 // PipelineLayoutDesc implementation.
PipelineLayoutDesc()1540 PipelineLayoutDesc::PipelineLayoutDesc() : mDescriptorSetLayouts{}, mPushConstantRanges{} {}
1541 
1542 PipelineLayoutDesc::~PipelineLayoutDesc() = default;
1543 
1544 PipelineLayoutDesc::PipelineLayoutDesc(const PipelineLayoutDesc &other) = default;
1545 
operator =(const PipelineLayoutDesc & rhs)1546 PipelineLayoutDesc &PipelineLayoutDesc::operator=(const PipelineLayoutDesc &rhs)
1547 {
1548     mDescriptorSetLayouts = rhs.mDescriptorSetLayouts;
1549     mPushConstantRanges   = rhs.mPushConstantRanges;
1550     return *this;
1551 }
1552 
hash() const1553 size_t PipelineLayoutDesc::hash() const
1554 {
1555     return angle::ComputeGenericHash(*this);
1556 }
1557 
operator ==(const PipelineLayoutDesc & other) const1558 bool PipelineLayoutDesc::operator==(const PipelineLayoutDesc &other) const
1559 {
1560     return memcmp(this, &other, sizeof(PipelineLayoutDesc)) == 0;
1561 }
1562 
updateDescriptorSetLayout(uint32_t setIndex,const DescriptorSetLayoutDesc & desc)1563 void PipelineLayoutDesc::updateDescriptorSetLayout(uint32_t setIndex,
1564                                                    const DescriptorSetLayoutDesc &desc)
1565 {
1566     ASSERT(setIndex < mDescriptorSetLayouts.size());
1567     mDescriptorSetLayouts[setIndex] = desc;
1568 }
1569 
updatePushConstantRange(gl::ShaderType shaderType,uint32_t offset,uint32_t size)1570 void PipelineLayoutDesc::updatePushConstantRange(gl::ShaderType shaderType,
1571                                                  uint32_t offset,
1572                                                  uint32_t size)
1573 {
1574     ASSERT(shaderType == gl::ShaderType::Vertex || shaderType == gl::ShaderType::Fragment ||
1575            shaderType == gl::ShaderType::Geometry || shaderType == gl::ShaderType::Compute);
1576     PackedPushConstantRange &packed = mPushConstantRanges[shaderType];
1577     packed.offset                   = offset;
1578     packed.size                     = size;
1579 }
1580 
getPushConstantRanges() const1581 const PushConstantRangeArray<PackedPushConstantRange> &PipelineLayoutDesc::getPushConstantRanges()
1582     const
1583 {
1584     return mPushConstantRanges;
1585 }
1586 
1587 // PipelineHelper implementation.
1588 PipelineHelper::PipelineHelper() = default;
1589 
1590 PipelineHelper::~PipelineHelper() = default;
1591 
destroy(VkDevice device)1592 void PipelineHelper::destroy(VkDevice device)
1593 {
1594     mPipeline.destroy(device);
1595 }
1596 
addTransition(GraphicsPipelineTransitionBits bits,const GraphicsPipelineDesc * desc,PipelineHelper * pipeline)1597 void PipelineHelper::addTransition(GraphicsPipelineTransitionBits bits,
1598                                    const GraphicsPipelineDesc *desc,
1599                                    PipelineHelper *pipeline)
1600 {
1601     mTransitions.emplace_back(bits, desc, pipeline);
1602 }
1603 
TextureDescriptorDesc()1604 TextureDescriptorDesc::TextureDescriptorDesc() : mMaxIndex(0)
1605 {
1606     mSerials.fill({0, 0});
1607 }
1608 
1609 TextureDescriptorDesc::~TextureDescriptorDesc()                                  = default;
1610 TextureDescriptorDesc::TextureDescriptorDesc(const TextureDescriptorDesc &other) = default;
1611 TextureDescriptorDesc &TextureDescriptorDesc::operator=(const TextureDescriptorDesc &other) =
1612     default;
1613 
update(size_t index,Serial textureSerial,Serial samplerSerial)1614 void TextureDescriptorDesc::update(size_t index, Serial textureSerial, Serial samplerSerial)
1615 {
1616     if (index >= mMaxIndex)
1617     {
1618         mMaxIndex = static_cast<uint32_t>(index + 1);
1619     }
1620 
1621     // If the serial number overflows we should defragment and regenerate all serials.
1622     // There should never be more than UINT_MAX textures alive at a time.
1623     ASSERT(textureSerial.getValue() < std::numeric_limits<uint32_t>::max());
1624     ASSERT(samplerSerial.getValue() < std::numeric_limits<uint32_t>::max());
1625     mSerials[index].texture = static_cast<uint32_t>(textureSerial.getValue());
1626     mSerials[index].sampler = static_cast<uint32_t>(samplerSerial.getValue());
1627 }
1628 
hash() const1629 size_t TextureDescriptorDesc::hash() const
1630 {
1631     return angle::ComputeGenericHash(&mSerials, sizeof(TexUnitSerials) * mMaxIndex);
1632 }
1633 
reset()1634 void TextureDescriptorDesc::reset()
1635 {
1636     memset(mSerials.data(), 0, sizeof(mSerials[0]) * mMaxIndex);
1637     mMaxIndex = 0;
1638 }
1639 
operator ==(const TextureDescriptorDesc & other) const1640 bool TextureDescriptorDesc::operator==(const TextureDescriptorDesc &other) const
1641 {
1642     if (mMaxIndex != other.mMaxIndex)
1643         return false;
1644 
1645     if (mMaxIndex == 0)
1646         return true;
1647 
1648     return memcmp(mSerials.data(), other.mSerials.data(), sizeof(TexUnitSerials) * mMaxIndex) == 0;
1649 }
1650 
1651 // FramebufferDesc implementation.
1652 
FramebufferDesc()1653 FramebufferDesc::FramebufferDesc()
1654 {
1655     reset();
1656 }
1657 
1658 FramebufferDesc::~FramebufferDesc()                            = default;
1659 FramebufferDesc::FramebufferDesc(const FramebufferDesc &other) = default;
1660 FramebufferDesc &FramebufferDesc::operator=(const FramebufferDesc &other) = default;
1661 
update(uint32_t index,AttachmentSerial serial)1662 void FramebufferDesc::update(uint32_t index, AttachmentSerial serial)
1663 {
1664     ASSERT(index < kMaxFramebufferAttachments);
1665     mSerials[index] = serial;
1666 }
1667 
hash() const1668 size_t FramebufferDesc::hash() const
1669 {
1670     return angle::ComputeGenericHash(&mSerials,
1671                                      sizeof(AttachmentSerial) * kMaxFramebufferAttachments);
1672 }
1673 
reset()1674 void FramebufferDesc::reset()
1675 {
1676     memset(&mSerials, 0, sizeof(AttachmentSerial) * kMaxFramebufferAttachments);
1677 }
1678 
operator ==(const FramebufferDesc & other) const1679 bool FramebufferDesc::operator==(const FramebufferDesc &other) const
1680 {
1681     return memcmp(&mSerials, &other.mSerials, sizeof(Serial) * kMaxFramebufferAttachments) == 0;
1682 }
1683 
attachmentCount() const1684 uint32_t FramebufferDesc::attachmentCount() const
1685 {
1686     uint32_t count = 0;
1687     for (const AttachmentSerial &serial : mSerials)
1688     {
1689         if (serial.imageSerial != 0)
1690         {
1691             count++;
1692         }
1693     }
1694     return count;
1695 }
1696 }  // namespace vk
1697 
1698 // RenderPassCache implementation.
1699 RenderPassCache::RenderPassCache() = default;
1700 
~RenderPassCache()1701 RenderPassCache::~RenderPassCache()
1702 {
1703     ASSERT(mPayload.empty());
1704 }
1705 
destroy(VkDevice device)1706 void RenderPassCache::destroy(VkDevice device)
1707 {
1708     for (auto &outerIt : mPayload)
1709     {
1710         for (auto &innerIt : outerIt.second)
1711         {
1712             innerIt.second.get().destroy(device);
1713         }
1714     }
1715     mPayload.clear();
1716 }
1717 
addRenderPass(ContextVk * contextVk,Serial serial,const vk::RenderPassDesc & desc,vk::RenderPass ** renderPassOut)1718 angle::Result RenderPassCache::addRenderPass(ContextVk *contextVk,
1719                                              Serial serial,
1720                                              const vk::RenderPassDesc &desc,
1721                                              vk::RenderPass **renderPassOut)
1722 {
1723     // Insert some dummy attachment ops.  Note that render passes with different ops are still
1724     // compatible.
1725     //
1726     // It would be nice to pre-populate the cache in the Renderer so we rarely miss here.
1727     vk::AttachmentOpsArray ops;
1728 
1729     uint32_t colorAttachmentCount = 0;
1730     for (uint32_t colorIndexGL = 0; colorIndexGL < desc.colorAttachmentRange(); ++colorIndexGL)
1731     {
1732         if (!desc.isColorAttachmentEnabled(colorIndexGL))
1733         {
1734             continue;
1735         }
1736 
1737         uint32_t colorIndexVk = colorAttachmentCount++;
1738         ops.initDummyOp(colorIndexVk, vk::ImageLayout::ColorAttachment,
1739                         vk::ImageLayout::ColorAttachment);
1740     }
1741 
1742     if (desc.hasDepthStencilAttachment())
1743     {
1744         uint32_t depthStencilIndexVk = colorAttachmentCount;
1745         ops.initDummyOp(depthStencilIndexVk, vk::ImageLayout::DepthStencilAttachment,
1746                         vk::ImageLayout::DepthStencilAttachment);
1747     }
1748 
1749     return getRenderPassWithOps(contextVk, serial, desc, ops, renderPassOut);
1750 }
1751 
getRenderPassWithOps(vk::Context * context,Serial serial,const vk::RenderPassDesc & desc,const vk::AttachmentOpsArray & attachmentOps,vk::RenderPass ** renderPassOut)1752 angle::Result RenderPassCache::getRenderPassWithOps(vk::Context *context,
1753                                                     Serial serial,
1754                                                     const vk::RenderPassDesc &desc,
1755                                                     const vk::AttachmentOpsArray &attachmentOps,
1756                                                     vk::RenderPass **renderPassOut)
1757 {
1758     auto outerIt = mPayload.find(desc);
1759     if (outerIt != mPayload.end())
1760     {
1761         InnerCache &innerCache = outerIt->second;
1762 
1763         auto innerIt = innerCache.find(attachmentOps);
1764         if (innerIt != innerCache.end())
1765         {
1766             // Update the serial before we return.
1767             // TODO(jmadill): Could possibly use an MRU cache here.
1768             innerIt->second.updateSerial(serial);
1769             *renderPassOut = &innerIt->second.get();
1770             return angle::Result::Continue;
1771         }
1772     }
1773     else
1774     {
1775         auto emplaceResult = mPayload.emplace(desc, InnerCache());
1776         outerIt            = emplaceResult.first;
1777     }
1778 
1779     vk::RenderPass newRenderPass;
1780     ANGLE_TRY(vk::InitializeRenderPassFromDesc(context, desc, attachmentOps, &newRenderPass));
1781 
1782     vk::RenderPassAndSerial withSerial(std::move(newRenderPass), serial);
1783 
1784     InnerCache &innerCache = outerIt->second;
1785     auto insertPos         = innerCache.emplace(attachmentOps, std::move(withSerial));
1786     *renderPassOut         = &insertPos.first->second.get();
1787 
1788     // TODO(jmadill): Trim cache, and pre-populate with the most common RPs on startup.
1789     return angle::Result::Continue;
1790 }
1791 
1792 // GraphicsPipelineCache implementation.
1793 GraphicsPipelineCache::GraphicsPipelineCache() = default;
1794 
~GraphicsPipelineCache()1795 GraphicsPipelineCache::~GraphicsPipelineCache()
1796 {
1797     ASSERT(mPayload.empty());
1798 }
1799 
destroy(VkDevice device)1800 void GraphicsPipelineCache::destroy(VkDevice device)
1801 {
1802     for (auto &item : mPayload)
1803     {
1804         vk::PipelineHelper &pipeline = item.second;
1805         pipeline.destroy(device);
1806     }
1807 
1808     mPayload.clear();
1809 }
1810 
release(ContextVk * context)1811 void GraphicsPipelineCache::release(ContextVk *context)
1812 {
1813     for (auto &item : mPayload)
1814     {
1815         vk::PipelineHelper &pipeline = item.second;
1816         context->addGarbage(&pipeline.getPipeline());
1817     }
1818 
1819     mPayload.clear();
1820 }
1821 
insertPipeline(ContextVk * contextVk,const vk::PipelineCache & pipelineCacheVk,const vk::RenderPass & compatibleRenderPass,const vk::PipelineLayout & pipelineLayout,const gl::AttributesMask & activeAttribLocationsMask,const gl::ComponentTypeMask & programAttribsTypeMask,const vk::ShaderModule * vertexModule,const vk::ShaderModule * fragmentModule,const vk::ShaderModule * geometryModule,vk::SpecializationConstantBitSet specConsts,const vk::GraphicsPipelineDesc & desc,const vk::GraphicsPipelineDesc ** descPtrOut,vk::PipelineHelper ** pipelineOut)1822 angle::Result GraphicsPipelineCache::insertPipeline(
1823     ContextVk *contextVk,
1824     const vk::PipelineCache &pipelineCacheVk,
1825     const vk::RenderPass &compatibleRenderPass,
1826     const vk::PipelineLayout &pipelineLayout,
1827     const gl::AttributesMask &activeAttribLocationsMask,
1828     const gl::ComponentTypeMask &programAttribsTypeMask,
1829     const vk::ShaderModule *vertexModule,
1830     const vk::ShaderModule *fragmentModule,
1831     const vk::ShaderModule *geometryModule,
1832     vk::SpecializationConstantBitSet specConsts,
1833     const vk::GraphicsPipelineDesc &desc,
1834     const vk::GraphicsPipelineDesc **descPtrOut,
1835     vk::PipelineHelper **pipelineOut)
1836 {
1837     vk::Pipeline newPipeline;
1838 
1839     // This "if" is left here for the benefit of VulkanPipelineCachePerfTest.
1840     if (contextVk != nullptr)
1841     {
1842         contextVk->getRenderer()->onNewGraphicsPipeline();
1843         ANGLE_TRY(desc.initializePipeline(contextVk, pipelineCacheVk, compatibleRenderPass,
1844                                           pipelineLayout, activeAttribLocationsMask,
1845                                           programAttribsTypeMask, vertexModule, fragmentModule,
1846                                           geometryModule, specConsts, &newPipeline));
1847     }
1848 
1849     // The Serial will be updated outside of this query.
1850     auto insertedItem = mPayload.emplace(desc, std::move(newPipeline));
1851     *descPtrOut       = &insertedItem.first->first;
1852     *pipelineOut      = &insertedItem.first->second;
1853 
1854     return angle::Result::Continue;
1855 }
1856 
populate(const vk::GraphicsPipelineDesc & desc,vk::Pipeline && pipeline)1857 void GraphicsPipelineCache::populate(const vk::GraphicsPipelineDesc &desc, vk::Pipeline &&pipeline)
1858 {
1859     auto item = mPayload.find(desc);
1860     if (item != mPayload.end())
1861     {
1862         return;
1863     }
1864 
1865     mPayload.emplace(desc, std::move(pipeline));
1866 }
1867 
1868 // DescriptorSetLayoutCache implementation.
1869 DescriptorSetLayoutCache::DescriptorSetLayoutCache() = default;
1870 
~DescriptorSetLayoutCache()1871 DescriptorSetLayoutCache::~DescriptorSetLayoutCache()
1872 {
1873     ASSERT(mPayload.empty());
1874 }
1875 
destroy(VkDevice device)1876 void DescriptorSetLayoutCache::destroy(VkDevice device)
1877 {
1878     for (auto &item : mPayload)
1879     {
1880         vk::RefCountedDescriptorSetLayout &layout = item.second;
1881         ASSERT(!layout.isReferenced());
1882         layout.get().destroy(device);
1883     }
1884 
1885     mPayload.clear();
1886 }
1887 
getDescriptorSetLayout(vk::Context * context,const vk::DescriptorSetLayoutDesc & desc,vk::BindingPointer<vk::DescriptorSetLayout> * descriptorSetLayoutOut)1888 angle::Result DescriptorSetLayoutCache::getDescriptorSetLayout(
1889     vk::Context *context,
1890     const vk::DescriptorSetLayoutDesc &desc,
1891     vk::BindingPointer<vk::DescriptorSetLayout> *descriptorSetLayoutOut)
1892 {
1893     auto iter = mPayload.find(desc);
1894     if (iter != mPayload.end())
1895     {
1896         vk::RefCountedDescriptorSetLayout &layout = iter->second;
1897         descriptorSetLayoutOut->set(&layout);
1898         return angle::Result::Continue;
1899     }
1900 
1901     // We must unpack the descriptor set layout description.
1902     vk::DescriptorSetLayoutBindingVector bindings;
1903     desc.unpackBindings(&bindings);
1904 
1905     VkDescriptorSetLayoutCreateInfo createInfo = {};
1906     createInfo.sType        = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
1907     createInfo.flags        = 0;
1908     createInfo.bindingCount = static_cast<uint32_t>(bindings.size());
1909     createInfo.pBindings    = bindings.data();
1910 
1911     vk::DescriptorSetLayout newLayout;
1912     ANGLE_VK_TRY(context, newLayout.init(context->getDevice(), createInfo));
1913 
1914     auto insertedItem =
1915         mPayload.emplace(desc, vk::RefCountedDescriptorSetLayout(std::move(newLayout)));
1916     vk::RefCountedDescriptorSetLayout &insertedLayout = insertedItem.first->second;
1917     descriptorSetLayoutOut->set(&insertedLayout);
1918 
1919     return angle::Result::Continue;
1920 }
1921 
1922 // PipelineLayoutCache implementation.
1923 PipelineLayoutCache::PipelineLayoutCache() = default;
1924 
~PipelineLayoutCache()1925 PipelineLayoutCache::~PipelineLayoutCache()
1926 {
1927     ASSERT(mPayload.empty());
1928 }
1929 
destroy(VkDevice device)1930 void PipelineLayoutCache::destroy(VkDevice device)
1931 {
1932     for (auto &item : mPayload)
1933     {
1934         vk::RefCountedPipelineLayout &layout = item.second;
1935         layout.get().destroy(device);
1936     }
1937 
1938     mPayload.clear();
1939 }
1940 
getPipelineLayout(vk::Context * context,const vk::PipelineLayoutDesc & desc,const vk::DescriptorSetLayoutPointerArray & descriptorSetLayouts,vk::BindingPointer<vk::PipelineLayout> * pipelineLayoutOut)1941 angle::Result PipelineLayoutCache::getPipelineLayout(
1942     vk::Context *context,
1943     const vk::PipelineLayoutDesc &desc,
1944     const vk::DescriptorSetLayoutPointerArray &descriptorSetLayouts,
1945     vk::BindingPointer<vk::PipelineLayout> *pipelineLayoutOut)
1946 {
1947     auto iter = mPayload.find(desc);
1948     if (iter != mPayload.end())
1949     {
1950         vk::RefCountedPipelineLayout &layout = iter->second;
1951         pipelineLayoutOut->set(&layout);
1952         return angle::Result::Continue;
1953     }
1954 
1955     // Note this does not handle gaps in descriptor set layouts gracefully.
1956     angle::FixedVector<VkDescriptorSetLayout, vk::kMaxDescriptorSetLayouts> setLayoutHandles;
1957     for (const vk::BindingPointer<vk::DescriptorSetLayout> &layoutPtr : descriptorSetLayouts)
1958     {
1959         if (layoutPtr.valid())
1960         {
1961             VkDescriptorSetLayout setLayout = layoutPtr.get().getHandle();
1962             if (setLayout != VK_NULL_HANDLE)
1963             {
1964                 setLayoutHandles.push_back(setLayout);
1965             }
1966         }
1967     }
1968 
1969     const vk::PushConstantRangeArray<vk::PackedPushConstantRange> &descPushConstantRanges =
1970         desc.getPushConstantRanges();
1971 
1972     gl::ShaderVector<VkPushConstantRange> pushConstantRanges;
1973 
1974     for (const gl::ShaderType shaderType : gl::AllShaderTypes())
1975     {
1976         const vk::PackedPushConstantRange &pushConstantDesc = descPushConstantRanges[shaderType];
1977         if (pushConstantDesc.size > 0)
1978         {
1979             VkPushConstantRange range;
1980             range.stageFlags = gl_vk::kShaderStageMap[shaderType];
1981             range.offset     = pushConstantDesc.offset;
1982             range.size       = pushConstantDesc.size;
1983 
1984             pushConstantRanges.push_back(range);
1985         }
1986     }
1987 
1988     // No pipeline layout found. We must create a new one.
1989     VkPipelineLayoutCreateInfo createInfo = {};
1990     createInfo.sType                      = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
1991     createInfo.flags                      = 0;
1992     createInfo.setLayoutCount             = static_cast<uint32_t>(setLayoutHandles.size());
1993     createInfo.pSetLayouts                = setLayoutHandles.data();
1994     createInfo.pushConstantRangeCount     = static_cast<uint32_t>(pushConstantRanges.size());
1995     createInfo.pPushConstantRanges        = pushConstantRanges.data();
1996 
1997     vk::PipelineLayout newLayout;
1998     ANGLE_VK_TRY(context, newLayout.init(context->getDevice(), createInfo));
1999 
2000     auto insertedItem = mPayload.emplace(desc, vk::RefCountedPipelineLayout(std::move(newLayout)));
2001     vk::RefCountedPipelineLayout &insertedLayout = insertedItem.first->second;
2002     pipelineLayoutOut->set(&insertedLayout);
2003 
2004     return angle::Result::Continue;
2005 }
2006 }  // namespace rx
2007