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