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