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