1 //
2 // Copyright 2018 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // vk_cache_utils.cpp:
7 // Contains the classes for the Pipeline State Object cache as well as the RenderPass cache.
8 // Also contains the structures for the packed descriptions for the RenderPass and Pipeline.
9 //
10
11 #include "libANGLE/renderer/vulkan/vk_cache_utils.h"
12
13 #include "common/aligned_memory.h"
14 #include "common/vulkan/vk_google_filtering_precision.h"
15 #include "libANGLE/BlobCache.h"
16 #include "libANGLE/VertexAttribute.h"
17 #include "libANGLE/renderer/vulkan/DisplayVk.h"
18 #include "libANGLE/renderer/vulkan/FramebufferVk.h"
19 #include "libANGLE/renderer/vulkan/ProgramVk.h"
20 #include "libANGLE/renderer/vulkan/RendererVk.h"
21 #include "libANGLE/renderer/vulkan/VertexArrayVk.h"
22 #include "libANGLE/renderer/vulkan/vk_format_utils.h"
23 #include "libANGLE/renderer/vulkan/vk_helpers.h"
24
25 #include <type_traits>
26
27 namespace rx
28 {
29 namespace vk
30 {
31
32 namespace
33 {
34
PackGLBlendOp(GLenum blendOp)35 uint8_t PackGLBlendOp(GLenum blendOp)
36 {
37 switch (blendOp)
38 {
39 case GL_FUNC_ADD:
40 return static_cast<uint8_t>(VK_BLEND_OP_ADD);
41 case GL_FUNC_SUBTRACT:
42 return static_cast<uint8_t>(VK_BLEND_OP_SUBTRACT);
43 case GL_FUNC_REVERSE_SUBTRACT:
44 return static_cast<uint8_t>(VK_BLEND_OP_REVERSE_SUBTRACT);
45 case GL_MIN:
46 return static_cast<uint8_t>(VK_BLEND_OP_MIN);
47 case GL_MAX:
48 return static_cast<uint8_t>(VK_BLEND_OP_MAX);
49 default:
50 UNREACHABLE();
51 return 0;
52 }
53 }
54
PackGLBlendFactor(GLenum blendFactor)55 uint8_t PackGLBlendFactor(GLenum blendFactor)
56 {
57 switch (blendFactor)
58 {
59 case GL_ZERO:
60 return static_cast<uint8_t>(VK_BLEND_FACTOR_ZERO);
61 case GL_ONE:
62 return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE);
63 case GL_SRC_COLOR:
64 return static_cast<uint8_t>(VK_BLEND_FACTOR_SRC_COLOR);
65 case GL_DST_COLOR:
66 return static_cast<uint8_t>(VK_BLEND_FACTOR_DST_COLOR);
67 case GL_ONE_MINUS_SRC_COLOR:
68 return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR);
69 case GL_SRC_ALPHA:
70 return static_cast<uint8_t>(VK_BLEND_FACTOR_SRC_ALPHA);
71 case GL_ONE_MINUS_SRC_ALPHA:
72 return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA);
73 case GL_DST_ALPHA:
74 return static_cast<uint8_t>(VK_BLEND_FACTOR_DST_ALPHA);
75 case GL_ONE_MINUS_DST_ALPHA:
76 return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA);
77 case GL_ONE_MINUS_DST_COLOR:
78 return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR);
79 case GL_SRC_ALPHA_SATURATE:
80 return static_cast<uint8_t>(VK_BLEND_FACTOR_SRC_ALPHA_SATURATE);
81 case GL_CONSTANT_COLOR:
82 return static_cast<uint8_t>(VK_BLEND_FACTOR_CONSTANT_COLOR);
83 case GL_CONSTANT_ALPHA:
84 return static_cast<uint8_t>(VK_BLEND_FACTOR_CONSTANT_ALPHA);
85 case GL_ONE_MINUS_CONSTANT_COLOR:
86 return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR);
87 case GL_ONE_MINUS_CONSTANT_ALPHA:
88 return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA);
89 case GL_SRC1_COLOR_EXT:
90 return static_cast<uint8_t>(VK_BLEND_FACTOR_SRC1_COLOR);
91 case GL_SRC1_ALPHA_EXT:
92 return static_cast<uint8_t>(VK_BLEND_FACTOR_SRC1_ALPHA);
93 case GL_ONE_MINUS_SRC1_COLOR_EXT:
94 return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR);
95 case GL_ONE_MINUS_SRC1_ALPHA_EXT:
96 return static_cast<uint8_t>(VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA);
97 default:
98 UNREACHABLE();
99 return 0;
100 }
101 }
102
PackGLStencilOp(GLenum compareOp)103 VkStencilOp PackGLStencilOp(GLenum compareOp)
104 {
105 switch (compareOp)
106 {
107 case GL_KEEP:
108 return VK_STENCIL_OP_KEEP;
109 case GL_ZERO:
110 return VK_STENCIL_OP_ZERO;
111 case GL_REPLACE:
112 return VK_STENCIL_OP_REPLACE;
113 case GL_INCR:
114 return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
115 case GL_DECR:
116 return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
117 case GL_INCR_WRAP:
118 return VK_STENCIL_OP_INCREMENT_AND_WRAP;
119 case GL_DECR_WRAP:
120 return VK_STENCIL_OP_DECREMENT_AND_WRAP;
121 case GL_INVERT:
122 return VK_STENCIL_OP_INVERT;
123 default:
124 UNREACHABLE();
125 return VK_STENCIL_OP_KEEP;
126 }
127 }
128
PackGLCompareFunc(GLenum compareFunc)129 VkCompareOp PackGLCompareFunc(GLenum compareFunc)
130 {
131 switch (compareFunc)
132 {
133 case GL_NEVER:
134 return VK_COMPARE_OP_NEVER;
135 case GL_ALWAYS:
136 return VK_COMPARE_OP_ALWAYS;
137 case GL_LESS:
138 return VK_COMPARE_OP_LESS;
139 case GL_LEQUAL:
140 return VK_COMPARE_OP_LESS_OR_EQUAL;
141 case GL_EQUAL:
142 return VK_COMPARE_OP_EQUAL;
143 case GL_GREATER:
144 return VK_COMPARE_OP_GREATER;
145 case GL_GEQUAL:
146 return VK_COMPARE_OP_GREATER_OR_EQUAL;
147 case GL_NOTEQUAL:
148 return VK_COMPARE_OP_NOT_EQUAL;
149 default:
150 UNREACHABLE();
151 return VK_COMPARE_OP_NEVER;
152 }
153 }
154
UnpackAttachmentDesc(VkAttachmentDescription * desc,const Format & format,uint8_t samples,const PackedAttachmentOpsDesc & ops)155 void UnpackAttachmentDesc(VkAttachmentDescription *desc,
156 const Format &format,
157 uint8_t samples,
158 const PackedAttachmentOpsDesc &ops)
159 {
160 desc->flags = 0;
161 desc->format = format.actualImageVkFormat();
162 desc->samples = gl_vk::GetSamples(samples);
163 desc->loadOp = static_cast<VkAttachmentLoadOp>(ops.loadOp);
164 desc->storeOp =
165 ConvertRenderPassStoreOpToVkStoreOp(static_cast<RenderPassStoreOp>(ops.storeOp));
166 desc->stencilLoadOp = static_cast<VkAttachmentLoadOp>(ops.stencilLoadOp);
167 desc->stencilStoreOp =
168 ConvertRenderPassStoreOpToVkStoreOp(static_cast<RenderPassStoreOp>(ops.stencilStoreOp));
169 desc->initialLayout =
170 ConvertImageLayoutToVkImageLayout(static_cast<ImageLayout>(ops.initialLayout));
171 desc->finalLayout =
172 ConvertImageLayoutToVkImageLayout(static_cast<ImageLayout>(ops.finalLayout));
173 }
174
UnpackColorResolveAttachmentDesc(VkAttachmentDescription * desc,const Format & format,bool usedAsInputAttachment,bool isInvalidated)175 void UnpackColorResolveAttachmentDesc(VkAttachmentDescription *desc,
176 const Format &format,
177 bool usedAsInputAttachment,
178 bool isInvalidated)
179 {
180 desc->flags = 0;
181 desc->format = format.actualImageVkFormat();
182
183 // This function is for color resolve attachments.
184 const angle::Format &angleFormat = format.actualImageFormat();
185 ASSERT(angleFormat.depthBits == 0 && angleFormat.stencilBits == 0);
186
187 // Resolve attachments always have a sample count of 1.
188 //
189 // If the corresponding color attachment needs to take its initial value from the resolve
190 // attachment (i.e. needs to be unresolved), loadOp needs to be set to LOAD, otherwise it should
191 // be DONT_CARE as it gets overwritten during resolve.
192 //
193 // storeOp should be STORE. If the attachment is invalidated, it is set to DONT_CARE.
194 desc->samples = VK_SAMPLE_COUNT_1_BIT;
195 desc->loadOp =
196 usedAsInputAttachment ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE;
197 desc->storeOp = isInvalidated ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE;
198 desc->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
199 desc->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
200 desc->initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
201 desc->finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
202 }
203
UnpackDepthStencilResolveAttachmentDesc(VkAttachmentDescription * desc,const Format & format,bool usedAsDepthInputAttachment,bool usedAsStencilInputAttachment,bool isDepthInvalidated,bool isStencilInvalidated)204 void UnpackDepthStencilResolveAttachmentDesc(VkAttachmentDescription *desc,
205 const Format &format,
206 bool usedAsDepthInputAttachment,
207 bool usedAsStencilInputAttachment,
208 bool isDepthInvalidated,
209 bool isStencilInvalidated)
210 {
211 // There cannot be simultaneous usages of the depth/stencil resolve image, as depth/stencil
212 // resolve currently only comes from depth/stencil renderbuffers.
213 desc->flags = 0;
214 desc->format = format.actualImageVkFormat();
215
216 // This function is for depth/stencil resolve attachment.
217 const angle::Format &angleFormat = format.intendedFormat();
218 ASSERT(angleFormat.depthBits != 0 || angleFormat.stencilBits != 0);
219
220 // Missing aspects are folded in is*Invalidated parameters, so no need to double check.
221 ASSERT(angleFormat.depthBits > 0 || isDepthInvalidated);
222 ASSERT(angleFormat.stencilBits > 0 || isStencilInvalidated);
223
224 // Similarly to color resolve attachments, sample count is 1, loadOp is LOAD or DONT_CARE based
225 // on whether unresolve is required, and storeOp is STORE or DONT_CARE based on whether the
226 // attachment is invalidated or the aspect exists.
227 desc->samples = VK_SAMPLE_COUNT_1_BIT;
228 desc->loadOp =
229 usedAsDepthInputAttachment ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE;
230 desc->storeOp =
231 isDepthInvalidated ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE;
232 desc->stencilLoadOp =
233 usedAsStencilInputAttachment ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE;
234 desc->stencilStoreOp =
235 isStencilInvalidated ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE;
236 desc->initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
237 desc->finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
238 }
239
UnpackStencilState(const PackedStencilOpState & packedState,uint8_t stencilReference,VkStencilOpState * stateOut)240 void UnpackStencilState(const PackedStencilOpState &packedState,
241 uint8_t stencilReference,
242 VkStencilOpState *stateOut)
243 {
244 stateOut->failOp = static_cast<VkStencilOp>(packedState.ops.fail);
245 stateOut->passOp = static_cast<VkStencilOp>(packedState.ops.pass);
246 stateOut->depthFailOp = static_cast<VkStencilOp>(packedState.ops.depthFail);
247 stateOut->compareOp = static_cast<VkCompareOp>(packedState.ops.compare);
248 stateOut->compareMask = packedState.compareMask;
249 stateOut->writeMask = packedState.writeMask;
250 stateOut->reference = stencilReference;
251 }
252
UnpackBlendAttachmentState(const PackedColorBlendAttachmentState & packedState,VkPipelineColorBlendAttachmentState * stateOut)253 void UnpackBlendAttachmentState(const PackedColorBlendAttachmentState &packedState,
254 VkPipelineColorBlendAttachmentState *stateOut)
255 {
256 stateOut->srcColorBlendFactor = static_cast<VkBlendFactor>(packedState.srcColorBlendFactor);
257 stateOut->dstColorBlendFactor = static_cast<VkBlendFactor>(packedState.dstColorBlendFactor);
258 stateOut->colorBlendOp = static_cast<VkBlendOp>(packedState.colorBlendOp);
259 stateOut->srcAlphaBlendFactor = static_cast<VkBlendFactor>(packedState.srcAlphaBlendFactor);
260 stateOut->dstAlphaBlendFactor = static_cast<VkBlendFactor>(packedState.dstAlphaBlendFactor);
261 stateOut->alphaBlendOp = static_cast<VkBlendOp>(packedState.alphaBlendOp);
262 }
263
SetPipelineShaderStageInfo(const VkStructureType type,const VkShaderStageFlagBits stage,const VkShaderModule module,const VkSpecializationInfo & specializationInfo,VkPipelineShaderStageCreateInfo * shaderStage)264 void SetPipelineShaderStageInfo(const VkStructureType type,
265 const VkShaderStageFlagBits stage,
266 const VkShaderModule module,
267 const VkSpecializationInfo &specializationInfo,
268 VkPipelineShaderStageCreateInfo *shaderStage)
269 {
270 shaderStage->sType = type;
271 shaderStage->flags = 0;
272 shaderStage->stage = stage;
273 shaderStage->module = module;
274 shaderStage->pName = "main";
275 shaderStage->pSpecializationInfo = &specializationInfo;
276 }
277
278 // Defines a subpass that uses the resolve attachments as input attachments to initialize color and
279 // depth/stencil attachments that need to be "unresolved" at the start of the render pass. The
280 // subpass will only contain the attachments that need to be unresolved to simplify the shader that
281 // performs the operations.
InitializeUnresolveSubpass(const RenderPassDesc & desc,const gl::DrawBuffersVector<VkAttachmentReference> & drawSubpassColorAttachmentRefs,const gl::DrawBuffersVector<VkAttachmentReference> & drawSubpassResolveAttachmentRefs,const VkAttachmentReference & depthStencilAttachmentRef,const VkAttachmentReference2KHR & depthStencilResolveAttachmentRef,gl::DrawBuffersVector<VkAttachmentReference> * unresolveColorAttachmentRefs,VkAttachmentReference * unresolveDepthStencilAttachmentRef,FramebufferAttachmentsVector<VkAttachmentReference> * unresolveInputAttachmentRefs,FramebufferAttachmentsVector<uint32_t> * unresolvePreserveAttachmentRefs,VkSubpassDescription * subpassDesc)282 void InitializeUnresolveSubpass(
283 const RenderPassDesc &desc,
284 const gl::DrawBuffersVector<VkAttachmentReference> &drawSubpassColorAttachmentRefs,
285 const gl::DrawBuffersVector<VkAttachmentReference> &drawSubpassResolveAttachmentRefs,
286 const VkAttachmentReference &depthStencilAttachmentRef,
287 const VkAttachmentReference2KHR &depthStencilResolveAttachmentRef,
288 gl::DrawBuffersVector<VkAttachmentReference> *unresolveColorAttachmentRefs,
289 VkAttachmentReference *unresolveDepthStencilAttachmentRef,
290 FramebufferAttachmentsVector<VkAttachmentReference> *unresolveInputAttachmentRefs,
291 FramebufferAttachmentsVector<uint32_t> *unresolvePreserveAttachmentRefs,
292 VkSubpassDescription *subpassDesc)
293 {
294 for (uint32_t colorIndexGL = 0; colorIndexGL < desc.colorAttachmentRange(); ++colorIndexGL)
295 {
296 // Assume the GL Framebuffer has the following attachments enabled:
297 //
298 // GL Color 0
299 // GL Color 3
300 // GL Color 4
301 // GL Color 6
302 // GL Color 7
303 // GL Depth/Stencil
304 //
305 // Additionally, assume Color 0, 4 and 6 are multisampled-render-to-texture (or for any
306 // other reason) have corresponding resolve attachments. Furthermore, say Color 4 and 6
307 // require an initial unresolve operation.
308 //
309 // In the above example, the render pass is created with the following attachments:
310 //
311 // RP Attachment[0] <- corresponding to GL Color 0
312 // RP Attachment[1] <- corresponding to GL Color 3
313 // RP Attachment[2] <- corresponding to GL Color 4
314 // RP Attachment[3] <- corresponding to GL Color 6
315 // RP Attachment[4] <- corresponding to GL Color 7
316 // RP Attachment[5] <- corresponding to GL Depth/Stencil
317 // RP Attachment[6] <- corresponding to resolve attachment of GL Color 0
318 // RP Attachment[7] <- corresponding to resolve attachment of GL Color 4
319 // RP Attachment[8] <- corresponding to resolve attachment of GL Color 6
320 //
321 // If the depth/stencil attachment is to be resolved, the following attachment would also be
322 // present:
323 //
324 // RP Attachment[9] <- corresponding to resolve attachment of GL Depth/Stencil
325 //
326 // The subpass that takes the application draw calls has the following attachments, creating
327 // the mapping from the Vulkan attachment indices (i.e. RP attachment indices) to GL indices
328 // as indicated by the GL shaders:
329 //
330 // Subpass[1] Color[0] -> RP Attachment[0]
331 // Subpass[1] Color[1] -> VK_ATTACHMENT_UNUSED
332 // Subpass[1] Color[2] -> VK_ATTACHMENT_UNUSED
333 // Subpass[1] Color[3] -> RP Attachment[1]
334 // Subpass[1] Color[4] -> RP Attachment[2]
335 // Subpass[1] Color[5] -> VK_ATTACHMENT_UNUSED
336 // Subpass[1] Color[6] -> RP Attachment[3]
337 // Subpass[1] Color[7] -> RP Attachment[4]
338 // Subpass[1] Depth/Stencil -> RP Attachment[5]
339 // Subpass[1] Resolve[0] -> RP Attachment[6]
340 // Subpass[1] Resolve[1] -> VK_ATTACHMENT_UNUSED
341 // Subpass[1] Resolve[2] -> VK_ATTACHMENT_UNUSED
342 // Subpass[1] Resolve[3] -> VK_ATTACHMENT_UNUSED
343 // Subpass[1] Resolve[4] -> RP Attachment[7]
344 // Subpass[1] Resolve[5] -> VK_ATTACHMENT_UNUSED
345 // Subpass[1] Resolve[6] -> RP Attachment[8]
346 // Subpass[1] Resolve[7] -> VK_ATTACHMENT_UNUSED
347 //
348 // With depth/stencil resolve attachment:
349 //
350 // Subpass[1] Depth/Stencil Resolve -> RP Attachment[9]
351 //
352 // The initial subpass that's created here is (remember that in the above example Color 4
353 // and 6 need to be unresolved):
354 //
355 // Subpass[0] Input[0] -> RP Attachment[7] = Subpass[1] Resolve[4]
356 // Subpass[0] Input[1] -> RP Attachment[8] = Subpass[1] Resolve[6]
357 // Subpass[0] Color[0] -> RP Attachment[2] = Subpass[1] Color[4]
358 // Subpass[0] Color[1] -> RP Attachment[3] = Subpass[1] Color[6]
359 //
360 // The trick here therefore is to use the color attachment refs already created for the
361 // application draw subpass indexed with colorIndexGL.
362 //
363 // If depth/stencil needs to be unresolved:
364 //
365 // Subpass[0] Input[2] -> RP Attachment[9] = Subpass[1] Depth/Stencil Resolve
366 // Subpass[0] Color[2] -> RP Attachment[5] = Subpass[1] Depth/Stencil
367 //
368 // As an additional note, the attachments that are not used in the unresolve subpass must be
369 // preserved. That is color attachments and the depth/stencil attachment if any. Resolve
370 // attachments are rewritten by the next subpass, so they don't need to be preserved. Note
371 // that there's no need to preserve attachments whose loadOp is DONT_CARE. For simplicity,
372 // we preserve those as well. The driver would ideally avoid preserving attachments with
373 // loadOp=DONT_CARE.
374 //
375 // With the above example:
376 //
377 // Subpass[0] Preserve[0] -> RP Attachment[0] = Subpass[1] Color[0]
378 // Subpass[0] Preserve[1] -> RP Attachment[1] = Subpass[1] Color[3]
379 // Subpass[0] Preserve[2] -> RP Attachment[4] = Subpass[1] Color[7]
380 //
381 // If depth/stencil is not unresolved:
382 //
383 // Subpass[0] Preserve[3] -> RP Attachment[5] = Subpass[1] Depth/Stencil
384 //
385 // Again, the color attachment refs already created for the application draw subpass can be
386 // used indexed with colorIndexGL.
387
388 if (!desc.hasColorUnresolveAttachment(colorIndexGL))
389 {
390 if (desc.isColorAttachmentEnabled(colorIndexGL))
391 {
392 unresolvePreserveAttachmentRefs->push_back(
393 drawSubpassColorAttachmentRefs[colorIndexGL].attachment);
394 }
395 continue;
396 }
397 ASSERT(desc.isColorAttachmentEnabled(colorIndexGL));
398 ASSERT(desc.hasColorResolveAttachment(colorIndexGL));
399 ASSERT(drawSubpassColorAttachmentRefs[colorIndexGL].attachment != VK_ATTACHMENT_UNUSED);
400 ASSERT(drawSubpassResolveAttachmentRefs[colorIndexGL].attachment != VK_ATTACHMENT_UNUSED);
401
402 unresolveColorAttachmentRefs->push_back(drawSubpassColorAttachmentRefs[colorIndexGL]);
403 unresolveInputAttachmentRefs->push_back(drawSubpassResolveAttachmentRefs[colorIndexGL]);
404
405 // Note the input attachment layout should be shader read-only. The subpass dependency
406 // will take care of transitioning the layout of the resolve attachment to color attachment
407 // automatically.
408 unresolveInputAttachmentRefs->back().layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
409 }
410
411 if (desc.hasDepthStencilUnresolveAttachment())
412 {
413 ASSERT(desc.hasDepthStencilAttachment());
414 ASSERT(desc.hasDepthStencilResolveAttachment());
415
416 *unresolveDepthStencilAttachmentRef = depthStencilAttachmentRef;
417
418 VkAttachmentReference unresolveDepthStencilInputAttachmentRef = {};
419 unresolveDepthStencilInputAttachmentRef.attachment =
420 depthStencilResolveAttachmentRef.attachment;
421 unresolveDepthStencilInputAttachmentRef.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
422
423 unresolveInputAttachmentRefs->push_back(unresolveDepthStencilInputAttachmentRef);
424 }
425 else if (desc.hasDepthStencilAttachment())
426 {
427 // Preserve the depth/stencil attachment if not unresolved. Again, there's no need to
428 // preserve this attachment if loadOp=DONT_CARE, but we do for simplicity.
429 unresolvePreserveAttachmentRefs->push_back(depthStencilAttachmentRef.attachment);
430 }
431
432 ASSERT(!unresolveColorAttachmentRefs->empty() ||
433 unresolveDepthStencilAttachmentRef->attachment != VK_ATTACHMENT_UNUSED);
434 ASSERT(unresolveColorAttachmentRefs->size() +
435 (desc.hasDepthStencilUnresolveAttachment() ? 1 : 0) ==
436 unresolveInputAttachmentRefs->size());
437
438 subpassDesc->flags = 0;
439 subpassDesc->pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
440 subpassDesc->inputAttachmentCount = static_cast<uint32_t>(unresolveInputAttachmentRefs->size());
441 subpassDesc->pInputAttachments = unresolveInputAttachmentRefs->data();
442 subpassDesc->colorAttachmentCount = static_cast<uint32_t>(unresolveColorAttachmentRefs->size());
443 subpassDesc->pColorAttachments = unresolveColorAttachmentRefs->data();
444 subpassDesc->pResolveAttachments = nullptr;
445 subpassDesc->pDepthStencilAttachment = unresolveDepthStencilAttachmentRef;
446 subpassDesc->preserveAttachmentCount =
447 static_cast<uint32_t>(unresolvePreserveAttachmentRefs->size());
448 subpassDesc->pPreserveAttachments = unresolvePreserveAttachmentRefs->data();
449 }
450
451 // There is normally one subpass, and occasionally another for the unresolve operation.
452 constexpr size_t kSubpassFastVectorSize = 2;
453 template <typename T>
454 using SubpassVector = angle::FastVector<T, kSubpassFastVectorSize>;
455
InitializeUnresolveSubpassDependencies(const SubpassVector<VkSubpassDescription> & subpassDesc,bool unresolveColor,bool unresolveDepthStencil,std::vector<VkSubpassDependency> * subpassDependencies)456 void InitializeUnresolveSubpassDependencies(const SubpassVector<VkSubpassDescription> &subpassDesc,
457 bool unresolveColor,
458 bool unresolveDepthStencil,
459 std::vector<VkSubpassDependency> *subpassDependencies)
460 {
461 ASSERT(subpassDesc.size() >= 2);
462 ASSERT(unresolveColor || unresolveDepthStencil);
463
464 // The unresolve subpass is the first subpass. The application draw subpass is the next one.
465 constexpr uint32_t kUnresolveSubpassIndex = 0;
466 constexpr uint32_t kDrawSubpassIndex = 1;
467
468 // A subpass dependency is needed between the unresolve and draw subpasses. There are two
469 // hazards here:
470 //
471 // - Subpass 0 writes to color/depth/stencil attachments, subpass 1 writes to the same
472 // attachments. This is a WaW hazard (color/depth/stencil write -> color/depth/stencil write)
473 // similar to when two subsequent render passes write to the same images.
474 // - Subpass 0 reads from resolve attachments, subpass 1 writes to the same resolve attachments.
475 // This is a WaR hazard (fragment shader read -> color write) which only requires an execution
476 // barrier.
477 //
478 // Note: the DEPENDENCY_BY_REGION flag is necessary to create a "framebuffer-local" dependency,
479 // as opposed to "framebuffer-global". The latter is effectively a render pass break. The
480 // former creates a dependency per framebuffer region. If dependency scopes correspond to
481 // attachments with:
482 //
483 // - Same sample count: dependency is at sample granularity
484 // - Different sample count: dependency is at pixel granularity
485 //
486 // The latter is clarified by the spec as such:
487 //
488 // > Practically, the pixel vs sample granularity dependency means that if an input attachment
489 // > has a different number of samples than the pipeline's rasterizationSamples, then a fragment
490 // > can access any sample in the input attachment's pixel even if it only uses
491 // > framebuffer-local dependencies.
492 //
493 // The dependency for the first hazard above (attachment write -> attachment write) is on
494 // same-sample attachments, so it will not allow the use of input attachments as required by the
495 // unresolve subpass. As a result, even though the second hazard seems to be subsumed by the
496 // first (its src stage is earlier and its dst stage is the same), a separate dependency is
497 // created for it just to obtain a pixel granularity dependency.
498 //
499 // Note: depth/stencil resolve is considered to be done in the color write stage:
500 //
501 // > Moving to the next subpass automatically performs any multisample resolve operations in the
502 // > subpass being ended. End-of-subpass multisample resolves are treated as color attachment
503 // > writes for the purposes of synchronization. This applies to resolve operations for both
504 // > color and depth/stencil attachments. That is, they are considered to execute in the
505 // > VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT pipeline stage and their writes are
506 // > synchronized with VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT.
507
508 subpassDependencies->emplace_back();
509 VkSubpassDependency *dependency = &subpassDependencies->back();
510
511 constexpr VkPipelineStageFlags kColorWriteStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
512 constexpr VkPipelineStageFlags kColorReadWriteStage =
513 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
514 constexpr VkAccessFlags kColorWriteFlags = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
515 constexpr VkAccessFlags kColorReadWriteFlags =
516 kColorWriteFlags | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
517
518 constexpr VkPipelineStageFlags kDepthStencilWriteStage =
519 VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
520 constexpr VkPipelineStageFlags kDepthStencilReadWriteStage =
521 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
522 constexpr VkAccessFlags kDepthStencilWriteFlags = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
523 constexpr VkAccessFlags kDepthStencilReadWriteFlags =
524 kDepthStencilWriteFlags | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
525
526 VkPipelineStageFlags attachmentWriteStages = 0;
527 VkPipelineStageFlags attachmentReadWriteStages = 0;
528 VkAccessFlags attachmentWriteFlags = 0;
529 VkAccessFlags attachmentReadWriteFlags = 0;
530
531 if (unresolveColor)
532 {
533 attachmentWriteStages |= kColorWriteStage;
534 attachmentReadWriteStages |= kColorReadWriteStage;
535 attachmentWriteFlags |= kColorWriteFlags;
536 attachmentReadWriteFlags |= kColorReadWriteFlags;
537 }
538
539 if (unresolveDepthStencil)
540 {
541 attachmentWriteStages |= kDepthStencilWriteStage;
542 attachmentReadWriteStages |= kDepthStencilReadWriteStage;
543 attachmentWriteFlags |= kDepthStencilWriteFlags;
544 attachmentReadWriteFlags |= kDepthStencilReadWriteFlags;
545 }
546
547 dependency->srcSubpass = kUnresolveSubpassIndex;
548 dependency->dstSubpass = kDrawSubpassIndex;
549 dependency->srcStageMask = attachmentWriteStages;
550 dependency->dstStageMask = attachmentReadWriteStages;
551 dependency->srcAccessMask = attachmentWriteFlags;
552 dependency->dstAccessMask = attachmentReadWriteFlags;
553 dependency->dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
554
555 subpassDependencies->emplace_back();
556 dependency = &subpassDependencies->back();
557
558 // Note again that depth/stencil resolve is considered to be done in the color output stage.
559 dependency->srcSubpass = kUnresolveSubpassIndex;
560 dependency->dstSubpass = kDrawSubpassIndex;
561 dependency->srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
562 dependency->dstStageMask = kColorWriteStage;
563 dependency->srcAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
564 dependency->dstAccessMask = kColorWriteFlags;
565 dependency->dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
566 }
567
InitializeInputAttachmentSubpassDependencies(std::vector<VkSubpassDependency> * subpassDependencies,uint32_t subpassIndex)568 void InitializeInputAttachmentSubpassDependencies(
569 std::vector<VkSubpassDependency> *subpassDependencies,
570 uint32_t subpassIndex)
571 {
572 subpassDependencies->emplace_back();
573 VkSubpassDependency *dependency = &subpassDependencies->back();
574
575 dependency->srcSubpass = subpassIndex;
576 dependency->dstSubpass = subpassIndex;
577 dependency->srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
578 dependency->dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
579 dependency->srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
580 dependency->dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
581 dependency->dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
582 }
583
ToAttachmentDesciption2(const VkAttachmentDescription & desc,VkAttachmentDescription2KHR * desc2Out)584 void ToAttachmentDesciption2(const VkAttachmentDescription &desc,
585 VkAttachmentDescription2KHR *desc2Out)
586 {
587 *desc2Out = {};
588 desc2Out->sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR;
589 desc2Out->flags = desc.flags;
590 desc2Out->format = desc.format;
591 desc2Out->samples = desc.samples;
592 desc2Out->loadOp = desc.loadOp;
593 desc2Out->storeOp = desc.storeOp;
594 desc2Out->stencilLoadOp = desc.stencilLoadOp;
595 desc2Out->stencilStoreOp = desc.stencilStoreOp;
596 desc2Out->initialLayout = desc.initialLayout;
597 desc2Out->finalLayout = desc.finalLayout;
598 }
599
ToAttachmentReference2(const VkAttachmentReference & ref,VkImageAspectFlags aspectMask,VkAttachmentReference2KHR * ref2Out)600 void ToAttachmentReference2(const VkAttachmentReference &ref,
601 VkImageAspectFlags aspectMask,
602 VkAttachmentReference2KHR *ref2Out)
603 {
604 *ref2Out = {};
605 ref2Out->sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;
606 ref2Out->attachment = ref.attachment;
607 ref2Out->layout = ref.layout;
608 ref2Out->aspectMask = aspectMask;
609 }
610
ToSubpassDescription2(const VkSubpassDescription & desc,const FramebufferAttachmentsVector<VkAttachmentReference2KHR> & inputRefs,const gl::DrawBuffersVector<VkAttachmentReference2KHR> & colorRefs,const gl::DrawBuffersVector<VkAttachmentReference2KHR> & resolveRefs,const VkAttachmentReference2KHR & depthStencilRef,uint32_t viewMask,VkSubpassDescription2KHR * desc2Out)611 void ToSubpassDescription2(const VkSubpassDescription &desc,
612 const FramebufferAttachmentsVector<VkAttachmentReference2KHR> &inputRefs,
613 const gl::DrawBuffersVector<VkAttachmentReference2KHR> &colorRefs,
614 const gl::DrawBuffersVector<VkAttachmentReference2KHR> &resolveRefs,
615 const VkAttachmentReference2KHR &depthStencilRef,
616 uint32_t viewMask,
617 VkSubpassDescription2KHR *desc2Out)
618 {
619 *desc2Out = {};
620 desc2Out->sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR;
621 desc2Out->flags = desc.flags;
622 desc2Out->pipelineBindPoint = desc.pipelineBindPoint;
623 desc2Out->viewMask = viewMask;
624 desc2Out->inputAttachmentCount = static_cast<uint32_t>(inputRefs.size());
625 desc2Out->pInputAttachments = !inputRefs.empty() ? inputRefs.data() : nullptr;
626 desc2Out->colorAttachmentCount = static_cast<uint32_t>(colorRefs.size());
627 desc2Out->pColorAttachments = !colorRefs.empty() ? colorRefs.data() : nullptr;
628 desc2Out->pResolveAttachments = !resolveRefs.empty() ? resolveRefs.data() : nullptr;
629 desc2Out->pDepthStencilAttachment = desc.pDepthStencilAttachment ? &depthStencilRef : nullptr;
630 desc2Out->preserveAttachmentCount = desc.preserveAttachmentCount;
631 desc2Out->pPreserveAttachments = desc.pPreserveAttachments;
632 }
633
ToSubpassDependency2(const VkSubpassDependency & dep,VkSubpassDependency2KHR * dep2Out)634 void ToSubpassDependency2(const VkSubpassDependency &dep, VkSubpassDependency2KHR *dep2Out)
635 {
636 *dep2Out = {};
637 dep2Out->sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2_KHR;
638 dep2Out->srcSubpass = dep.srcSubpass;
639 dep2Out->dstSubpass = dep.dstSubpass;
640 dep2Out->srcStageMask = dep.srcStageMask;
641 dep2Out->dstStageMask = dep.dstStageMask;
642 dep2Out->srcAccessMask = dep.srcAccessMask;
643 dep2Out->dstAccessMask = dep.dstAccessMask;
644 dep2Out->dependencyFlags = dep.dependencyFlags;
645 }
646
CreateRenderPass2(Context * context,const VkRenderPassCreateInfo & createInfo,const VkSubpassDescriptionDepthStencilResolve & depthStencilResolve,const VkRenderPassMultiviewCreateInfo & multiviewInfo,bool unresolveDepth,bool unresolveStencil,bool isRenderToTexture,uint8_t renderToTextureSamples,RenderPass * renderPass)647 angle::Result CreateRenderPass2(Context *context,
648 const VkRenderPassCreateInfo &createInfo,
649 const VkSubpassDescriptionDepthStencilResolve &depthStencilResolve,
650 const VkRenderPassMultiviewCreateInfo &multiviewInfo,
651 bool unresolveDepth,
652 bool unresolveStencil,
653 bool isRenderToTexture,
654 uint8_t renderToTextureSamples,
655 RenderPass *renderPass)
656 {
657 // Convert the attachments to VkAttachmentDescription2.
658 FramebufferAttachmentArray<VkAttachmentDescription2KHR> attachmentDescs;
659 for (uint32_t index = 0; index < createInfo.attachmentCount; ++index)
660 {
661 ToAttachmentDesciption2(createInfo.pAttachments[index], &attachmentDescs[index]);
662 }
663
664 // Convert subpass attachments to VkAttachmentReference2 and the subpass description to
665 // VkSubpassDescription2.
666 SubpassVector<FramebufferAttachmentsVector<VkAttachmentReference2KHR>>
667 subpassInputAttachmentRefs(createInfo.subpassCount);
668 SubpassVector<gl::DrawBuffersVector<VkAttachmentReference2KHR>> subpassColorAttachmentRefs(
669 createInfo.subpassCount);
670 SubpassVector<gl::DrawBuffersVector<VkAttachmentReference2KHR>> subpassResolveAttachmentRefs(
671 createInfo.subpassCount);
672 SubpassVector<VkAttachmentReference2KHR> subpassDepthStencilAttachmentRefs(
673 createInfo.subpassCount);
674 SubpassVector<VkSubpassDescription2KHR> subpassDescriptions(createInfo.subpassCount);
675 for (uint32_t subpass = 0; subpass < createInfo.subpassCount; ++subpass)
676 {
677 const VkSubpassDescription &desc = createInfo.pSubpasses[subpass];
678 FramebufferAttachmentsVector<VkAttachmentReference2KHR> &inputRefs =
679 subpassInputAttachmentRefs[subpass];
680 gl::DrawBuffersVector<VkAttachmentReference2KHR> &colorRefs =
681 subpassColorAttachmentRefs[subpass];
682 gl::DrawBuffersVector<VkAttachmentReference2KHR> &resolveRefs =
683 subpassResolveAttachmentRefs[subpass];
684 VkAttachmentReference2KHR &depthStencilRef = subpassDepthStencilAttachmentRefs[subpass];
685
686 inputRefs.resize(desc.inputAttachmentCount);
687 colorRefs.resize(desc.colorAttachmentCount);
688
689 // Convert subpass attachment references.
690 for (uint32_t index = 0; index < desc.inputAttachmentCount; ++index)
691 {
692 VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
693 if (index >= desc.colorAttachmentCount)
694 {
695 // Set the aspect of the depth/stencil input attachment (of which there can be only
696 // one).
697 ASSERT(index + 1 == desc.inputAttachmentCount);
698 aspectMask = 0;
699 if (unresolveDepth)
700 {
701 aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
702 }
703 if (unresolveStencil)
704 {
705 aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
706 }
707 ASSERT(aspectMask != 0);
708 }
709
710 ToAttachmentReference2(desc.pInputAttachments[index], aspectMask, &inputRefs[index]);
711 }
712
713 for (uint32_t index = 0; index < desc.colorAttachmentCount; ++index)
714 {
715 ToAttachmentReference2(desc.pColorAttachments[index], VK_IMAGE_ASPECT_COLOR_BIT,
716 &colorRefs[index]);
717 }
718 if (desc.pResolveAttachments)
719 {
720 resolveRefs.resize(desc.colorAttachmentCount);
721 for (uint32_t index = 0; index < desc.colorAttachmentCount; ++index)
722 {
723 ToAttachmentReference2(desc.pResolveAttachments[index], VK_IMAGE_ASPECT_COLOR_BIT,
724 &resolveRefs[index]);
725 }
726 }
727 if (desc.pDepthStencilAttachment)
728 {
729 ToAttachmentReference2(*desc.pDepthStencilAttachment,
730 VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,
731 &depthStencilRef);
732 }
733
734 // Convert subpass itself.
735 ToSubpassDescription2(desc, inputRefs, colorRefs, resolveRefs, depthStencilRef,
736 multiviewInfo.pViewMasks[subpass], &subpassDescriptions[subpass]);
737 }
738
739 VkMultisampledRenderToSingleSampledInfoEXT renderToTextureInfo = {};
740 renderToTextureInfo.sType = VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT;
741 renderToTextureInfo.multisampledRenderToSingleSampledEnable = true;
742 renderToTextureInfo.rasterizationSamples = gl_vk::GetSamples(renderToTextureSamples);
743 renderToTextureInfo.depthResolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
744 renderToTextureInfo.stencilResolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
745
746 // Append the depth/stencil resolve attachment to the pNext chain of last subpass, if any.
747 if (depthStencilResolve.pDepthStencilResolveAttachment != nullptr)
748 {
749 ASSERT(!isRenderToTexture);
750 subpassDescriptions.back().pNext = &depthStencilResolve;
751 }
752 else
753 {
754 RendererVk *renderer = context->getRenderer();
755
756 ASSERT(isRenderToTexture);
757 ASSERT(renderer->getFeatures().supportsMultisampledRenderToSingleSampled.enabled);
758 ASSERT(subpassDescriptions.size() == 1);
759
760 subpassDescriptions.back().pNext = &renderToTextureInfo;
761 }
762
763 // Convert subpass dependencies to VkSubpassDependency2.
764 std::vector<VkSubpassDependency2KHR> subpassDependencies(createInfo.dependencyCount);
765 for (uint32_t index = 0; index < createInfo.dependencyCount; ++index)
766 {
767 ToSubpassDependency2(createInfo.pDependencies[index], &subpassDependencies[index]);
768 }
769
770 // Convert CreateInfo itself
771 VkRenderPassCreateInfo2KHR createInfo2 = {};
772 createInfo2.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR;
773 createInfo2.flags = createInfo.flags;
774 createInfo2.attachmentCount = createInfo.attachmentCount;
775 createInfo2.pAttachments = attachmentDescs.data();
776 createInfo2.subpassCount = createInfo.subpassCount;
777 createInfo2.pSubpasses = subpassDescriptions.data();
778 createInfo2.dependencyCount = static_cast<uint32_t>(subpassDependencies.size());
779 createInfo2.pDependencies = !subpassDependencies.empty() ? subpassDependencies.data() : nullptr;
780 createInfo2.correlatedViewMaskCount = multiviewInfo.correlationMaskCount;
781 createInfo2.pCorrelatedViewMasks = multiviewInfo.pCorrelationMasks;
782
783 // Initialize the render pass.
784 ANGLE_VK_TRY(context, renderPass->init2(context->getDevice(), createInfo2));
785
786 return angle::Result::Continue;
787 }
788
UpdateRenderPassColorPerfCounters(const VkRenderPassCreateInfo & createInfo,const VkSubpassDescription & subpass,RenderPassPerfCounters * countersOut)789 void UpdateRenderPassColorPerfCounters(const VkRenderPassCreateInfo &createInfo,
790 const VkSubpassDescription &subpass,
791 RenderPassPerfCounters *countersOut)
792 {
793 // Color resolve counters.
794 if (subpass.pResolveAttachments == nullptr)
795 {
796 return;
797 }
798
799 for (uint32_t colorSubpassIndex = 0; colorSubpassIndex < subpass.colorAttachmentCount;
800 ++colorSubpassIndex)
801 {
802 uint32_t resolveRenderPassIndex = subpass.pResolveAttachments[colorSubpassIndex].attachment;
803
804 if (resolveRenderPassIndex == VK_ATTACHMENT_UNUSED)
805 {
806 continue;
807 }
808
809 ++countersOut->colorAttachmentResolves;
810 }
811 }
812
UpdateRenderPassDepthStencilPerfCounters(const VkRenderPassCreateInfo & createInfo,size_t renderPassIndex,RenderPassPerfCounters * countersOut)813 void UpdateRenderPassDepthStencilPerfCounters(const VkRenderPassCreateInfo &createInfo,
814 size_t renderPassIndex,
815 RenderPassPerfCounters *countersOut)
816 {
817 ASSERT(renderPassIndex != VK_ATTACHMENT_UNUSED);
818
819 // Depth/stencil ops counters.
820 const VkAttachmentDescription &ds = createInfo.pAttachments[renderPassIndex];
821
822 countersOut->depthClears += ds.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ? 1 : 0;
823 countersOut->depthLoads += ds.loadOp == VK_ATTACHMENT_LOAD_OP_LOAD ? 1 : 0;
824 countersOut->depthStores +=
825 ds.storeOp == static_cast<uint16_t>(RenderPassStoreOp::Store) ? 1 : 0;
826
827 countersOut->stencilClears += ds.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ? 1 : 0;
828 countersOut->stencilLoads += ds.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD ? 1 : 0;
829 countersOut->stencilStores +=
830 ds.stencilStoreOp == static_cast<uint16_t>(RenderPassStoreOp::Store) ? 1 : 0;
831
832 // Depth/stencil read-only mode.
833 countersOut->readOnlyDepthStencil +=
834 ds.finalLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL ? 1 : 0;
835 }
836
UpdateRenderPassDepthStencilResolvePerfCounters(const VkRenderPassCreateInfo & createInfo,const VkSubpassDescriptionDepthStencilResolve & depthStencilResolve,RenderPassPerfCounters * countersOut)837 void UpdateRenderPassDepthStencilResolvePerfCounters(
838 const VkRenderPassCreateInfo &createInfo,
839 const VkSubpassDescriptionDepthStencilResolve &depthStencilResolve,
840 RenderPassPerfCounters *countersOut)
841 {
842 if (depthStencilResolve.pDepthStencilResolveAttachment == nullptr)
843 {
844 return;
845 }
846
847 uint32_t resolveRenderPassIndex =
848 depthStencilResolve.pDepthStencilResolveAttachment->attachment;
849
850 if (resolveRenderPassIndex == VK_ATTACHMENT_UNUSED)
851 {
852 return;
853 }
854
855 const VkAttachmentDescription &dsResolve = createInfo.pAttachments[resolveRenderPassIndex];
856
857 // Resolve depth/stencil ops counters.
858 countersOut->depthClears += dsResolve.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ? 1 : 0;
859 countersOut->depthLoads += dsResolve.loadOp == VK_ATTACHMENT_LOAD_OP_LOAD ? 1 : 0;
860 countersOut->depthStores +=
861 dsResolve.storeOp == static_cast<uint16_t>(RenderPassStoreOp::Store) ? 1 : 0;
862
863 countersOut->stencilClears += dsResolve.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ? 1 : 0;
864 countersOut->stencilLoads += dsResolve.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD ? 1 : 0;
865 countersOut->stencilStores +=
866 dsResolve.stencilStoreOp == static_cast<uint16_t>(RenderPassStoreOp::Store) ? 1 : 0;
867
868 // Depth/stencil resolve counters.
869 countersOut->depthAttachmentResolves +=
870 depthStencilResolve.depthResolveMode != VK_RESOLVE_MODE_NONE ? 1 : 0;
871 countersOut->stencilAttachmentResolves +=
872 depthStencilResolve.stencilResolveMode != VK_RESOLVE_MODE_NONE ? 1 : 0;
873 }
874
UpdateRenderPassPerfCounters(const RenderPassDesc & desc,const VkRenderPassCreateInfo & createInfo,const VkSubpassDescriptionDepthStencilResolve & depthStencilResolve,RenderPassPerfCounters * countersOut)875 void UpdateRenderPassPerfCounters(
876 const RenderPassDesc &desc,
877 const VkRenderPassCreateInfo &createInfo,
878 const VkSubpassDescriptionDepthStencilResolve &depthStencilResolve,
879 RenderPassPerfCounters *countersOut)
880 {
881 // Accumulate depth/stencil attachment indices in all subpasses to avoid double-counting
882 // counters.
883 FramebufferAttachmentMask depthStencilAttachmentIndices;
884
885 for (uint32_t subpassIndex = 0; subpassIndex < createInfo.subpassCount; ++subpassIndex)
886 {
887 const VkSubpassDescription &subpass = createInfo.pSubpasses[subpassIndex];
888
889 // Color counters. Note: currently there are no counters for load/store ops of color
890 // attachments, so there's no risk of double counting.
891 UpdateRenderPassColorPerfCounters(createInfo, subpass, countersOut);
892
893 // Record index of depth/stencil attachment.
894 if (subpass.pDepthStencilAttachment != nullptr)
895 {
896 uint32_t attachmentRenderPassIndex = subpass.pDepthStencilAttachment->attachment;
897 if (attachmentRenderPassIndex != VK_ATTACHMENT_UNUSED)
898 {
899 depthStencilAttachmentIndices.set(attachmentRenderPassIndex);
900 }
901 }
902 }
903
904 // Depth/stencil counters. Currently, both subpasses use the same depth/stencil attachment (if
905 // any).
906 ASSERT(depthStencilAttachmentIndices.count() <= 1);
907 for (size_t attachmentRenderPassIndex : depthStencilAttachmentIndices)
908 {
909 UpdateRenderPassDepthStencilPerfCounters(createInfo, attachmentRenderPassIndex,
910 countersOut);
911 }
912
913 UpdateRenderPassDepthStencilResolvePerfCounters(createInfo, depthStencilResolve, countersOut);
914
915 // Determine unresolve counters from the render pass desc, to avoid making guesses from subpass
916 // count etc.
917 countersOut->colorAttachmentUnresolves += desc.getColorUnresolveAttachmentMask().count();
918 countersOut->depthAttachmentUnresolves += desc.hasDepthUnresolveAttachment() ? 1 : 0;
919 countersOut->stencilAttachmentUnresolves += desc.hasStencilUnresolveAttachment() ? 1 : 0;
920 }
921
InitializeRenderPassFromDesc(ContextVk * contextVk,const RenderPassDesc & desc,const AttachmentOpsArray & ops,RenderPassHelper * renderPassHelper)922 angle::Result InitializeRenderPassFromDesc(ContextVk *contextVk,
923 const RenderPassDesc &desc,
924 const AttachmentOpsArray &ops,
925 RenderPassHelper *renderPassHelper)
926 {
927 RendererVk *renderer = contextVk->getRenderer();
928
929 constexpr VkAttachmentReference kUnusedAttachment = {VK_ATTACHMENT_UNUSED,
930 VK_IMAGE_LAYOUT_UNDEFINED};
931 constexpr VkAttachmentReference2 kUnusedAttachment2 = {
932 VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR, nullptr, VK_ATTACHMENT_UNUSED,
933 VK_IMAGE_LAYOUT_UNDEFINED, 0};
934
935 const bool needInputAttachments = desc.getFramebufferFetchMode();
936 const bool isRenderToTexture = desc.isRenderToTexture();
937
938 const uint8_t descSamples = desc.samples();
939 const uint8_t attachmentSamples = isRenderToTexture ? 1 : descSamples;
940 const uint8_t renderToTextureSamples = isRenderToTexture ? descSamples : 1;
941
942 // Unpack the packed and split representation into the format required by Vulkan.
943 gl::DrawBuffersVector<VkAttachmentReference> colorAttachmentRefs;
944 gl::DrawBuffersVector<VkAttachmentReference> colorResolveAttachmentRefs;
945 VkAttachmentReference depthStencilAttachmentRef = kUnusedAttachment;
946 VkAttachmentReference2KHR depthStencilResolveAttachmentRef = kUnusedAttachment2;
947
948 // The list of attachments includes all non-resolve and resolve attachments.
949 FramebufferAttachmentArray<VkAttachmentDescription> attachmentDescs;
950
951 // Track invalidated attachments so their resolve attachments can be invalidated as well.
952 // Resolve attachments can be removed in that case if the render pass has only one subpass
953 // (which is the case if there are no unresolve attachments).
954 gl::DrawBufferMask isColorInvalidated;
955 bool isDepthInvalidated = false;
956 bool isStencilInvalidated = false;
957 const bool hasUnresolveAttachments =
958 desc.getColorUnresolveAttachmentMask().any() || desc.hasDepthStencilUnresolveAttachment();
959 const bool canRemoveResolveAttachments = !hasUnresolveAttachments;
960
961 // Pack color attachments
962 PackedAttachmentIndex attachmentCount(0);
963 for (uint32_t colorIndexGL = 0; colorIndexGL < desc.colorAttachmentRange(); ++colorIndexGL)
964 {
965 // Vulkan says:
966 //
967 // > Each element of the pColorAttachments array corresponds to an output location in the
968 // > shader, i.e. if the shader declares an output variable decorated with a Location value
969 // > of X, then it uses the attachment provided in pColorAttachments[X].
970 //
971 // This means that colorAttachmentRefs is indexed by colorIndexGL. Where the color
972 // attachment is disabled, a reference with VK_ATTACHMENT_UNUSED is given.
973
974 if (!desc.isColorAttachmentEnabled(colorIndexGL))
975 {
976 colorAttachmentRefs.push_back(kUnusedAttachment);
977 continue;
978 }
979
980 angle::FormatID formatID = desc[colorIndexGL];
981 ASSERT(formatID != angle::FormatID::NONE);
982 const Format &format = renderer->getFormat(formatID);
983
984 VkAttachmentReference colorRef;
985 colorRef.attachment = attachmentCount.get();
986 colorRef.layout = needInputAttachments
987 ? VK_IMAGE_LAYOUT_GENERAL
988 : ConvertImageLayoutToVkImageLayout(
989 static_cast<ImageLayout>(ops[attachmentCount].initialLayout));
990 colorAttachmentRefs.push_back(colorRef);
991
992 UnpackAttachmentDesc(&attachmentDescs[attachmentCount.get()], format, attachmentSamples,
993 ops[attachmentCount]);
994
995 angle::FormatID attachmentFormat = format.actualImageFormatID;
996
997 // If this renderpass uses EXT_srgb_write_control, we need to override the format to its
998 // linear counterpart. Formats that cannot be reinterpreted are exempt from this
999 // requirement.
1000 angle::FormatID linearFormat = rx::ConvertToLinear(attachmentFormat);
1001 if (linearFormat != angle::FormatID::NONE)
1002 {
1003 if (desc.getSRGBWriteControlMode() == gl::SrgbWriteControlMode::Linear)
1004 {
1005 attachmentFormat = linearFormat;
1006 }
1007 }
1008 attachmentDescs[attachmentCount.get()].format =
1009 contextVk->getRenderer()->getFormat(attachmentFormat).actualImageVkFormat();
1010 ASSERT(attachmentDescs[attachmentCount.get()].format != VK_FORMAT_UNDEFINED);
1011
1012 isColorInvalidated.set(colorIndexGL, ops[attachmentCount].isInvalidated);
1013
1014 ++attachmentCount;
1015 }
1016
1017 // Pack depth/stencil attachment, if any
1018 if (desc.hasDepthStencilAttachment())
1019 {
1020 uint32_t depthStencilIndexGL = static_cast<uint32_t>(desc.depthStencilAttachmentIndex());
1021
1022 angle::FormatID formatID = desc[depthStencilIndexGL];
1023 ASSERT(formatID != angle::FormatID::NONE);
1024 const Format &format = renderer->getFormat(formatID);
1025
1026 depthStencilAttachmentRef.attachment = attachmentCount.get();
1027 depthStencilAttachmentRef.layout = ConvertImageLayoutToVkImageLayout(
1028 static_cast<ImageLayout>(ops[attachmentCount].initialLayout));
1029
1030 UnpackAttachmentDesc(&attachmentDescs[attachmentCount.get()], format, attachmentSamples,
1031 ops[attachmentCount]);
1032
1033 isDepthInvalidated = ops[attachmentCount].isInvalidated;
1034 isStencilInvalidated = ops[attachmentCount].isStencilInvalidated;
1035
1036 ++attachmentCount;
1037 }
1038
1039 // Pack color resolve attachments
1040 const uint32_t nonResolveAttachmentCount = attachmentCount.get();
1041 for (uint32_t colorIndexGL = 0; colorIndexGL < desc.colorAttachmentRange(); ++colorIndexGL)
1042 {
1043 if (!desc.hasColorResolveAttachment(colorIndexGL))
1044 {
1045 colorResolveAttachmentRefs.push_back(kUnusedAttachment);
1046 continue;
1047 }
1048
1049 ASSERT(desc.isColorAttachmentEnabled(colorIndexGL));
1050
1051 const Format &format = renderer->getFormat(desc[colorIndexGL]);
1052
1053 VkAttachmentReference colorRef;
1054 colorRef.attachment = attachmentCount.get();
1055 colorRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1056
1057 // If color attachment is invalidated, try to remove its resolve attachment altogether.
1058 if (canRemoveResolveAttachments && isColorInvalidated.test(colorIndexGL))
1059 {
1060 colorResolveAttachmentRefs.push_back(kUnusedAttachment);
1061 }
1062 else
1063 {
1064 colorResolveAttachmentRefs.push_back(colorRef);
1065 }
1066
1067 UnpackColorResolveAttachmentDesc(&attachmentDescs[attachmentCount.get()], format,
1068 desc.hasColorUnresolveAttachment(colorIndexGL),
1069 isColorInvalidated.test(colorIndexGL));
1070
1071 ++attachmentCount;
1072 }
1073
1074 // Pack depth/stencil resolve attachment, if any
1075 if (desc.hasDepthStencilResolveAttachment())
1076 {
1077 ASSERT(desc.hasDepthStencilAttachment());
1078
1079 uint32_t depthStencilIndexGL = static_cast<uint32_t>(desc.depthStencilAttachmentIndex());
1080
1081 const Format &format = renderer->getFormat(desc[depthStencilIndexGL]);
1082 const angle::Format &angleFormat = format.intendedFormat();
1083
1084 // Treat missing aspect as invalidated for the purpose of the resolve attachment.
1085 if (angleFormat.depthBits == 0)
1086 {
1087 isDepthInvalidated = true;
1088 }
1089 if (angleFormat.stencilBits == 0)
1090 {
1091 isStencilInvalidated = true;
1092 }
1093
1094 depthStencilResolveAttachmentRef.attachment = attachmentCount.get();
1095 depthStencilResolveAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
1096 depthStencilResolveAttachmentRef.aspectMask = 0;
1097
1098 if (!isDepthInvalidated)
1099 {
1100 depthStencilResolveAttachmentRef.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
1101 }
1102 if (!isStencilInvalidated)
1103 {
1104 depthStencilResolveAttachmentRef.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
1105 }
1106
1107 UnpackDepthStencilResolveAttachmentDesc(
1108 &attachmentDescs[attachmentCount.get()], format, desc.hasDepthUnresolveAttachment(),
1109 desc.hasStencilUnresolveAttachment(), isDepthInvalidated, isStencilInvalidated);
1110
1111 ++attachmentCount;
1112 }
1113
1114 SubpassVector<VkSubpassDescription> subpassDesc;
1115
1116 // If any attachment needs to be unresolved, create an initial subpass for this purpose. Note
1117 // that the following arrays are used in initializing a VkSubpassDescription in subpassDesc,
1118 // which is in turn used in VkRenderPassCreateInfo below. That is why they are declared in the
1119 // same scope.
1120 gl::DrawBuffersVector<VkAttachmentReference> unresolveColorAttachmentRefs;
1121 VkAttachmentReference unresolveDepthStencilAttachmentRef = kUnusedAttachment;
1122 FramebufferAttachmentsVector<VkAttachmentReference> unresolveInputAttachmentRefs;
1123 FramebufferAttachmentsVector<uint32_t> unresolvePreserveAttachmentRefs;
1124 if (hasUnresolveAttachments)
1125 {
1126 subpassDesc.push_back({});
1127 InitializeUnresolveSubpass(
1128 desc, colorAttachmentRefs, colorResolveAttachmentRefs, depthStencilAttachmentRef,
1129 depthStencilResolveAttachmentRef, &unresolveColorAttachmentRefs,
1130 &unresolveDepthStencilAttachmentRef, &unresolveInputAttachmentRefs,
1131 &unresolvePreserveAttachmentRefs, &subpassDesc.back());
1132 }
1133
1134 subpassDesc.push_back({});
1135 VkSubpassDescription *applicationSubpass = &subpassDesc.back();
1136
1137 applicationSubpass->flags = 0;
1138 applicationSubpass->pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
1139 applicationSubpass->inputAttachmentCount =
1140 needInputAttachments ? static_cast<uint32_t>(colorAttachmentRefs.size()) : 0;
1141 applicationSubpass->pInputAttachments =
1142 needInputAttachments ? colorAttachmentRefs.data() : nullptr;
1143 applicationSubpass->colorAttachmentCount = static_cast<uint32_t>(colorAttachmentRefs.size());
1144 applicationSubpass->pColorAttachments = colorAttachmentRefs.data();
1145 applicationSubpass->pResolveAttachments = attachmentCount.get() > nonResolveAttachmentCount
1146 ? colorResolveAttachmentRefs.data()
1147 : nullptr;
1148 applicationSubpass->pDepthStencilAttachment =
1149 (depthStencilAttachmentRef.attachment != VK_ATTACHMENT_UNUSED ? &depthStencilAttachmentRef
1150 : nullptr);
1151 applicationSubpass->preserveAttachmentCount = 0;
1152 applicationSubpass->pPreserveAttachments = nullptr;
1153
1154 // If depth/stencil is to be resolved, add a VkSubpassDescriptionDepthStencilResolve to the
1155 // pNext chain of the subpass description. Note that we need a VkSubpassDescription2KHR to have
1156 // a pNext pointer. CreateRenderPass2 is called to convert the data structures here to those
1157 // specified by VK_KHR_create_renderpass2 for this purpose.
1158 VkSubpassDescriptionDepthStencilResolve depthStencilResolve = {};
1159 if (desc.hasDepthStencilResolveAttachment())
1160 {
1161 depthStencilResolve.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE;
1162 depthStencilResolve.depthResolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
1163 depthStencilResolve.stencilResolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
1164
1165 // If depth/stencil attachment is invalidated, try to remove its resolve attachment
1166 // altogether.
1167 const bool removeDepthStencilResolve =
1168 canRemoveResolveAttachments && isDepthInvalidated && isStencilInvalidated;
1169 if (!removeDepthStencilResolve)
1170 {
1171 depthStencilResolve.pDepthStencilResolveAttachment = &depthStencilResolveAttachmentRef;
1172 }
1173 }
1174
1175 std::vector<VkSubpassDependency> subpassDependencies;
1176 if (hasUnresolveAttachments)
1177 {
1178 InitializeUnresolveSubpassDependencies(
1179 subpassDesc, desc.getColorUnresolveAttachmentMask().any(),
1180 desc.hasDepthStencilUnresolveAttachment(), &subpassDependencies);
1181 }
1182
1183 if (needInputAttachments)
1184 {
1185 uint32_t drawSubpassIndex = static_cast<uint32_t>(subpassDesc.size()) - 1;
1186 InitializeInputAttachmentSubpassDependencies(&subpassDependencies, drawSubpassIndex);
1187 }
1188
1189 VkRenderPassCreateInfo createInfo = {};
1190 createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
1191 createInfo.flags = 0;
1192 createInfo.attachmentCount = attachmentCount.get();
1193 createInfo.pAttachments = attachmentDescs.data();
1194 createInfo.subpassCount = static_cast<uint32_t>(subpassDesc.size());
1195 createInfo.pSubpasses = subpassDesc.data();
1196 createInfo.dependencyCount = 0;
1197 createInfo.pDependencies = nullptr;
1198
1199 if (!subpassDependencies.empty())
1200 {
1201 createInfo.dependencyCount = static_cast<uint32_t>(subpassDependencies.size());
1202 createInfo.pDependencies = subpassDependencies.data();
1203 }
1204
1205 SubpassVector<uint32_t> viewMasks(subpassDesc.size(),
1206 angle::BitMask<uint32_t>(desc.viewCount()));
1207 VkRenderPassMultiviewCreateInfo multiviewInfo = {};
1208 multiviewInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO;
1209 multiviewInfo.subpassCount = createInfo.subpassCount;
1210 multiviewInfo.pViewMasks = viewMasks.data();
1211
1212 if (desc.viewCount() > 0)
1213 {
1214 // For VR, the views are correlated, so this would be an optimization. However, an
1215 // application can also use multiview for example to render to all 6 faces of a cubemap, in
1216 // which case the views are actually not so correlated. In the absence of any hints from
1217 // the application (TODO: verify that extension has no hints), we have to decide on one or
1218 // the other. Since VR is more expensive, the views are marked as correlated to optimize
1219 // that use case.
1220 multiviewInfo.correlationMaskCount = 1;
1221 multiviewInfo.pCorrelationMasks = viewMasks.data();
1222
1223 createInfo.pNext = &multiviewInfo;
1224 }
1225
1226 // If depth/stencil resolve is used, we need to create the render pass with
1227 // vkCreateRenderPass2KHR. Same when using the VK_EXT_multisampled_render_to_single_sampled
1228 // extension.
1229 if (depthStencilResolve.pDepthStencilResolveAttachment != nullptr || desc.isRenderToTexture())
1230 {
1231 ANGLE_TRY(CreateRenderPass2(contextVk, createInfo, depthStencilResolve, multiviewInfo,
1232 desc.hasDepthUnresolveAttachment(),
1233 desc.hasStencilUnresolveAttachment(), desc.isRenderToTexture(),
1234 renderToTextureSamples, &renderPassHelper->getRenderPass()));
1235 }
1236 else
1237 {
1238 ANGLE_VK_TRY(contextVk,
1239 renderPassHelper->getRenderPass().init(contextVk->getDevice(), createInfo));
1240 }
1241
1242 // Calculate perf counters associated with this render pass, such as load/store ops, unresolve
1243 // and resolve operations etc. This information is taken out of the render pass create info.
1244 // Depth/stencil resolve attachment uses RenderPass2 structures, so it's passed in separately.
1245 UpdateRenderPassPerfCounters(desc, createInfo, depthStencilResolve,
1246 &renderPassHelper->getPerfCounters());
1247
1248 return angle::Result::Continue;
1249 }
1250
GetRenderPassAndUpdateCounters(ContextVk * contextVk,bool updatePerfCounters,RenderPassHelper * renderPassHelper,RenderPass ** renderPassOut)1251 void GetRenderPassAndUpdateCounters(ContextVk *contextVk,
1252 bool updatePerfCounters,
1253 RenderPassHelper *renderPassHelper,
1254 RenderPass **renderPassOut)
1255 {
1256 *renderPassOut = &renderPassHelper->getRenderPass();
1257 if (updatePerfCounters)
1258 {
1259 PerfCounters &counters = contextVk->getPerfCounters();
1260 const RenderPassPerfCounters &rpCounters = renderPassHelper->getPerfCounters();
1261
1262 counters.depthClears += rpCounters.depthClears;
1263 counters.depthLoads += rpCounters.depthLoads;
1264 counters.depthStores += rpCounters.depthStores;
1265 counters.stencilClears += rpCounters.stencilClears;
1266 counters.stencilLoads += rpCounters.stencilLoads;
1267 counters.stencilStores += rpCounters.stencilStores;
1268 counters.colorAttachmentUnresolves += rpCounters.colorAttachmentUnresolves;
1269 counters.colorAttachmentResolves += rpCounters.colorAttachmentResolves;
1270 counters.depthAttachmentUnresolves += rpCounters.depthAttachmentUnresolves;
1271 counters.depthAttachmentResolves += rpCounters.depthAttachmentResolves;
1272 counters.stencilAttachmentUnresolves += rpCounters.stencilAttachmentUnresolves;
1273 counters.stencilAttachmentResolves += rpCounters.stencilAttachmentResolves;
1274 counters.readOnlyDepthStencilRenderPasses += rpCounters.readOnlyDepthStencil;
1275 }
1276 }
1277
InitializeSpecializationInfo(const SpecializationConstants & specConsts,SpecializationConstantMap<VkSpecializationMapEntry> * specializationEntriesOut,VkSpecializationInfo * specializationInfoOut)1278 void InitializeSpecializationInfo(
1279 const SpecializationConstants &specConsts,
1280 SpecializationConstantMap<VkSpecializationMapEntry> *specializationEntriesOut,
1281 VkSpecializationInfo *specializationInfoOut)
1282 {
1283 // Collect specialization constants.
1284 for (const sh::vk::SpecializationConstantId id :
1285 angle::AllEnums<sh::vk::SpecializationConstantId>())
1286 {
1287 (*specializationEntriesOut)[id].constantID = static_cast<uint32_t>(id);
1288 switch (id)
1289 {
1290 case sh::vk::SpecializationConstantId::LineRasterEmulation:
1291 (*specializationEntriesOut)[id].offset =
1292 offsetof(SpecializationConstants, lineRasterEmulation);
1293 (*specializationEntriesOut)[id].size = sizeof(specConsts.lineRasterEmulation);
1294 break;
1295 case sh::vk::SpecializationConstantId::SurfaceRotation:
1296 (*specializationEntriesOut)[id].offset =
1297 offsetof(SpecializationConstants, surfaceRotation);
1298 (*specializationEntriesOut)[id].size = sizeof(specConsts.surfaceRotation);
1299 break;
1300 case sh::vk::SpecializationConstantId::DrawableWidth:
1301 (*specializationEntriesOut)[id].offset =
1302 offsetof(vk::SpecializationConstants, drawableWidth);
1303 (*specializationEntriesOut)[id].size = sizeof(specConsts.drawableWidth);
1304 break;
1305 case sh::vk::SpecializationConstantId::DrawableHeight:
1306 (*specializationEntriesOut)[id].offset =
1307 offsetof(vk::SpecializationConstants, drawableHeight);
1308 (*specializationEntriesOut)[id].size = sizeof(specConsts.drawableHeight);
1309 break;
1310 default:
1311 UNREACHABLE();
1312 break;
1313 }
1314 }
1315
1316 specializationInfoOut->mapEntryCount = static_cast<uint32_t>(specializationEntriesOut->size());
1317 specializationInfoOut->pMapEntries = specializationEntriesOut->data();
1318 specializationInfoOut->dataSize = sizeof(specConsts);
1319 specializationInfoOut->pData = &specConsts;
1320 }
1321
1322 // Utility for setting a value on a packed 4-bit integer array.
1323 template <typename SrcT>
Int4Array_Set(uint8_t * arrayBytes,uint32_t arrayIndex,SrcT value)1324 void Int4Array_Set(uint8_t *arrayBytes, uint32_t arrayIndex, SrcT value)
1325 {
1326 uint32_t byteIndex = arrayIndex >> 1;
1327 ASSERT(value < 16);
1328
1329 if ((arrayIndex & 1) == 0)
1330 {
1331 arrayBytes[byteIndex] &= 0xF0;
1332 arrayBytes[byteIndex] |= static_cast<uint8_t>(value);
1333 }
1334 else
1335 {
1336 arrayBytes[byteIndex] &= 0x0F;
1337 arrayBytes[byteIndex] |= static_cast<uint8_t>(value) << 4;
1338 }
1339 }
1340
1341 // Utility for getting a value from a packed 4-bit integer array.
1342 template <typename DestT>
Int4Array_Get(const uint8_t * arrayBytes,uint32_t arrayIndex)1343 DestT Int4Array_Get(const uint8_t *arrayBytes, uint32_t arrayIndex)
1344 {
1345 uint32_t byteIndex = arrayIndex >> 1;
1346
1347 if ((arrayIndex & 1) == 0)
1348 {
1349 return static_cast<DestT>(arrayBytes[byteIndex] & 0xF);
1350 }
1351 else
1352 {
1353 return static_cast<DestT>(arrayBytes[byteIndex] >> 4);
1354 }
1355 }
1356
1357 // When converting a byte number to a transition bit index we can shift instead of divide.
1358 constexpr size_t kTransitionByteShift = Log2(kGraphicsPipelineDirtyBitBytes);
1359
1360 // When converting a number of bits offset to a transition bit index we can also shift.
1361 constexpr size_t kBitsPerByte = 8;
1362 constexpr size_t kTransitionBitShift = kTransitionByteShift + Log2(kBitsPerByte);
1363
1364 // Helper macro to map from a PipelineDesc struct and field to a dirty bit index.
1365 // Uses the 'offsetof' macro to compute the offset 'Member' within the PipelineDesc
1366 // and the offset of 'Field' within 'Member'. We can optimize the dirty bit setting by computing
1367 // the shifted dirty bit at compile time instead of calling "set".
1368 #define ANGLE_GET_TRANSITION_BIT(Member, Field) \
1369 ((offsetof(GraphicsPipelineDesc, Member) + offsetof(decltype(Member), Field)) >> \
1370 kTransitionByteShift)
1371
1372 // Indexed dirty bits cannot be entirely computed at compile time since the index is passed to
1373 // the update function.
1374 #define ANGLE_GET_INDEXED_TRANSITION_BIT(Member, Field, Index, BitWidth) \
1375 (((BitWidth * Index) >> kTransitionBitShift) + ANGLE_GET_TRANSITION_BIT(Member, Field))
1376
1377 constexpr angle::PackedEnumMap<gl::ComponentType, VkFormat> kMismatchedComponentTypeMap = {{
1378 {gl::ComponentType::Float, VK_FORMAT_R32G32B32A32_SFLOAT},
1379 {gl::ComponentType::Int, VK_FORMAT_R32G32B32A32_SINT},
1380 {gl::ComponentType::UnsignedInt, VK_FORMAT_R32G32B32A32_UINT},
1381 }};
1382 } // anonymous namespace
1383
1384 // RenderPassDesc implementation.
RenderPassDesc()1385 RenderPassDesc::RenderPassDesc()
1386 {
1387 memset(this, 0, sizeof(RenderPassDesc));
1388 }
1389
1390 RenderPassDesc::~RenderPassDesc() = default;
1391
RenderPassDesc(const RenderPassDesc & other)1392 RenderPassDesc::RenderPassDesc(const RenderPassDesc &other)
1393 {
1394 memcpy(this, &other, sizeof(RenderPassDesc));
1395 }
1396
packColorAttachment(size_t colorIndexGL,angle::FormatID formatID)1397 void RenderPassDesc::packColorAttachment(size_t colorIndexGL, angle::FormatID formatID)
1398 {
1399 ASSERT(colorIndexGL < mAttachmentFormats.size());
1400 static_assert(angle::kNumANGLEFormats < std::numeric_limits<uint8_t>::max(),
1401 "Too many ANGLE formats to fit in uint8_t");
1402 // Force the user to pack the depth/stencil attachment last.
1403 ASSERT(!hasDepthStencilAttachment());
1404 // This function should only be called for enabled GL color attachments.
1405 ASSERT(formatID != angle::FormatID::NONE);
1406
1407 uint8_t &packedFormat = mAttachmentFormats[colorIndexGL];
1408 SetBitField(packedFormat, formatID);
1409
1410 // Set color attachment range such that it covers the range from index 0 through last active
1411 // index. This is the reasons why we need depth/stencil to be packed last.
1412 SetBitField(mColorAttachmentRange, std::max<size_t>(mColorAttachmentRange, colorIndexGL + 1));
1413 }
1414
packColorAttachmentGap(size_t colorIndexGL)1415 void RenderPassDesc::packColorAttachmentGap(size_t colorIndexGL)
1416 {
1417 ASSERT(colorIndexGL < mAttachmentFormats.size());
1418 static_assert(angle::kNumANGLEFormats < std::numeric_limits<uint8_t>::max(),
1419 "Too many ANGLE formats to fit in uint8_t");
1420 // Force the user to pack the depth/stencil attachment last.
1421 ASSERT(!hasDepthStencilAttachment());
1422
1423 // Use NONE as a flag for gaps in GL color attachments.
1424 uint8_t &packedFormat = mAttachmentFormats[colorIndexGL];
1425 SetBitField(packedFormat, angle::FormatID::NONE);
1426 }
1427
packDepthStencilAttachment(angle::FormatID formatID)1428 void RenderPassDesc::packDepthStencilAttachment(angle::FormatID formatID)
1429 {
1430 ASSERT(!hasDepthStencilAttachment());
1431
1432 size_t index = depthStencilAttachmentIndex();
1433 ASSERT(index < mAttachmentFormats.size());
1434
1435 uint8_t &packedFormat = mAttachmentFormats[index];
1436 SetBitField(packedFormat, formatID);
1437 }
1438
packColorResolveAttachment(size_t colorIndexGL)1439 void RenderPassDesc::packColorResolveAttachment(size_t colorIndexGL)
1440 {
1441 ASSERT(isColorAttachmentEnabled(colorIndexGL));
1442 ASSERT(!mColorResolveAttachmentMask.test(colorIndexGL));
1443 ASSERT(mSamples > 1);
1444 mColorResolveAttachmentMask.set(colorIndexGL);
1445 }
1446
removeColorResolveAttachment(size_t colorIndexGL)1447 void RenderPassDesc::removeColorResolveAttachment(size_t colorIndexGL)
1448 {
1449 ASSERT(mColorResolveAttachmentMask.test(colorIndexGL));
1450 mColorResolveAttachmentMask.reset(colorIndexGL);
1451 }
1452
packColorUnresolveAttachment(size_t colorIndexGL)1453 void RenderPassDesc::packColorUnresolveAttachment(size_t colorIndexGL)
1454 {
1455 mColorUnresolveAttachmentMask.set(colorIndexGL);
1456 }
1457
removeColorUnresolveAttachment(size_t colorIndexGL)1458 void RenderPassDesc::removeColorUnresolveAttachment(size_t colorIndexGL)
1459 {
1460 mColorUnresolveAttachmentMask.reset(colorIndexGL);
1461 }
1462
packDepthStencilResolveAttachment()1463 void RenderPassDesc::packDepthStencilResolveAttachment()
1464 {
1465 ASSERT(hasDepthStencilAttachment());
1466 ASSERT(!hasDepthStencilResolveAttachment());
1467
1468 mResolveDepthStencil = true;
1469 }
1470
packDepthStencilUnresolveAttachment(bool unresolveDepth,bool unresolveStencil)1471 void RenderPassDesc::packDepthStencilUnresolveAttachment(bool unresolveDepth, bool unresolveStencil)
1472 {
1473 ASSERT(hasDepthStencilAttachment());
1474
1475 mUnresolveDepth = unresolveDepth;
1476 mUnresolveStencil = unresolveStencil;
1477 }
1478
removeDepthStencilUnresolveAttachment()1479 void RenderPassDesc::removeDepthStencilUnresolveAttachment()
1480 {
1481 mUnresolveDepth = false;
1482 mUnresolveStencil = false;
1483 }
1484
operator =(const RenderPassDesc & other)1485 RenderPassDesc &RenderPassDesc::operator=(const RenderPassDesc &other)
1486 {
1487 memcpy(this, &other, sizeof(RenderPassDesc));
1488 return *this;
1489 }
1490
setWriteControlMode(gl::SrgbWriteControlMode mode)1491 void RenderPassDesc::setWriteControlMode(gl::SrgbWriteControlMode mode)
1492 {
1493 SetBitField(mSrgbWriteControl, mode);
1494 }
1495
hash() const1496 size_t RenderPassDesc::hash() const
1497 {
1498 return angle::ComputeGenericHash(*this);
1499 }
1500
isColorAttachmentEnabled(size_t colorIndexGL) const1501 bool RenderPassDesc::isColorAttachmentEnabled(size_t colorIndexGL) const
1502 {
1503 angle::FormatID formatID = operator[](colorIndexGL);
1504 return formatID != angle::FormatID::NONE;
1505 }
1506
hasDepthStencilAttachment() const1507 bool RenderPassDesc::hasDepthStencilAttachment() const
1508 {
1509 angle::FormatID formatID = operator[](depthStencilAttachmentIndex());
1510 return formatID != angle::FormatID::NONE;
1511 }
1512
attachmentCount() const1513 size_t RenderPassDesc::attachmentCount() const
1514 {
1515 size_t colorAttachmentCount = 0;
1516 for (size_t i = 0; i < mColorAttachmentRange; ++i)
1517 {
1518 colorAttachmentCount += isColorAttachmentEnabled(i);
1519 }
1520
1521 // Note that there are no gaps in depth/stencil attachments. In fact there is a maximum of 1 of
1522 // it + 1 for its resolve attachment.
1523 size_t depthStencilCount = hasDepthStencilAttachment() ? 1 : 0;
1524 size_t depthStencilResolveCount = hasDepthStencilResolveAttachment() ? 1 : 0;
1525 return colorAttachmentCount + mColorResolveAttachmentMask.count() + depthStencilCount +
1526 depthStencilResolveCount;
1527 }
1528
operator ==(const RenderPassDesc & lhs,const RenderPassDesc & rhs)1529 bool operator==(const RenderPassDesc &lhs, const RenderPassDesc &rhs)
1530 {
1531 return (memcmp(&lhs, &rhs, sizeof(RenderPassDesc)) == 0);
1532 }
1533
1534 // GraphicsPipelineDesc implementation.
1535 // Use aligned allocation and free so we can use the alignas keyword.
operator new(std::size_t size)1536 void *GraphicsPipelineDesc::operator new(std::size_t size)
1537 {
1538 return angle::AlignedAlloc(size, 32);
1539 }
1540
operator delete(void * ptr)1541 void GraphicsPipelineDesc::operator delete(void *ptr)
1542 {
1543 return angle::AlignedFree(ptr);
1544 }
1545
GraphicsPipelineDesc()1546 GraphicsPipelineDesc::GraphicsPipelineDesc()
1547 {
1548 memset(this, 0, sizeof(GraphicsPipelineDesc));
1549 }
1550
1551 GraphicsPipelineDesc::~GraphicsPipelineDesc() = default;
1552
GraphicsPipelineDesc(const GraphicsPipelineDesc & other)1553 GraphicsPipelineDesc::GraphicsPipelineDesc(const GraphicsPipelineDesc &other)
1554 {
1555 memcpy(this, &other, sizeof(GraphicsPipelineDesc));
1556 }
1557
operator =(const GraphicsPipelineDesc & other)1558 GraphicsPipelineDesc &GraphicsPipelineDesc::operator=(const GraphicsPipelineDesc &other)
1559 {
1560 memcpy(this, &other, sizeof(GraphicsPipelineDesc));
1561 return *this;
1562 }
1563
hash() const1564 size_t GraphicsPipelineDesc::hash() const
1565 {
1566 return angle::ComputeGenericHash(*this);
1567 }
1568
operator ==(const GraphicsPipelineDesc & other) const1569 bool GraphicsPipelineDesc::operator==(const GraphicsPipelineDesc &other) const
1570 {
1571 return (memcmp(this, &other, sizeof(GraphicsPipelineDesc)) == 0);
1572 }
1573
1574 // TODO(jmadill): We should prefer using Packed GLenums. http://anglebug.com/2169
1575
1576 // Initialize PSO states, it is consistent with initial value of gl::State
initDefaults(const ContextVk * contextVk)1577 void GraphicsPipelineDesc::initDefaults(const ContextVk *contextVk)
1578 {
1579 // Set all vertex input attributes to default, the default format is Float
1580 angle::FormatID defaultFormat = GetCurrentValueFormatID(gl::VertexAttribType::Float);
1581 for (PackedAttribDesc &packedAttrib : mVertexInputAttribs.attribs)
1582 {
1583 SetBitField(packedAttrib.stride, 0);
1584 SetBitField(packedAttrib.divisor, 0);
1585 SetBitField(packedAttrib.format, defaultFormat);
1586 SetBitField(packedAttrib.compressed, 0);
1587 SetBitField(packedAttrib.offset, 0);
1588 }
1589
1590 mRasterizationAndMultisampleStateInfo.bits.subpass = 0;
1591 mRasterizationAndMultisampleStateInfo.bits.depthClampEnable =
1592 contextVk->getFeatures().depthClamping.enabled ? VK_TRUE : VK_FALSE;
1593 mRasterizationAndMultisampleStateInfo.bits.rasterizationDiscardEnable = 0;
1594 SetBitField(mRasterizationAndMultisampleStateInfo.bits.polygonMode, VK_POLYGON_MODE_FILL);
1595 SetBitField(mRasterizationAndMultisampleStateInfo.bits.cullMode, VK_CULL_MODE_BACK_BIT);
1596 SetBitField(mRasterizationAndMultisampleStateInfo.bits.frontFace,
1597 VK_FRONT_FACE_COUNTER_CLOCKWISE);
1598 mRasterizationAndMultisampleStateInfo.bits.depthBiasEnable = 0;
1599 mRasterizationAndMultisampleStateInfo.depthBiasConstantFactor = 0.0f;
1600 mRasterizationAndMultisampleStateInfo.depthBiasClamp = 0.0f;
1601 mRasterizationAndMultisampleStateInfo.depthBiasSlopeFactor = 0.0f;
1602 mRasterizationAndMultisampleStateInfo.lineWidth = 1.0f;
1603
1604 mRasterizationAndMultisampleStateInfo.bits.rasterizationSamples = 1;
1605 mRasterizationAndMultisampleStateInfo.bits.sampleShadingEnable = 0;
1606 mRasterizationAndMultisampleStateInfo.minSampleShading = 1.0f;
1607 for (uint32_t &sampleMask : mRasterizationAndMultisampleStateInfo.sampleMask)
1608 {
1609 sampleMask = 0xFFFFFFFF;
1610 }
1611 mRasterizationAndMultisampleStateInfo.bits.alphaToCoverageEnable = 0;
1612 mRasterizationAndMultisampleStateInfo.bits.alphaToOneEnable = 0;
1613
1614 mDepthStencilStateInfo.enable.depthTest = 0;
1615 mDepthStencilStateInfo.enable.depthWrite = 1;
1616 SetBitField(mDepthStencilStateInfo.depthCompareOpAndSurfaceRotation.depthCompareOp,
1617 VK_COMPARE_OP_LESS);
1618 mDepthStencilStateInfo.enable.depthBoundsTest = 0;
1619 mDepthStencilStateInfo.enable.stencilTest = 0;
1620 mDepthStencilStateInfo.minDepthBounds = 0.0f;
1621 mDepthStencilStateInfo.maxDepthBounds = 0.0f;
1622 SetBitField(mDepthStencilStateInfo.front.ops.fail, VK_STENCIL_OP_KEEP);
1623 SetBitField(mDepthStencilStateInfo.front.ops.pass, VK_STENCIL_OP_KEEP);
1624 SetBitField(mDepthStencilStateInfo.front.ops.depthFail, VK_STENCIL_OP_KEEP);
1625 SetBitField(mDepthStencilStateInfo.front.ops.compare, VK_COMPARE_OP_ALWAYS);
1626 SetBitField(mDepthStencilStateInfo.front.compareMask, 0xFF);
1627 SetBitField(mDepthStencilStateInfo.front.writeMask, 0xFF);
1628 mDepthStencilStateInfo.frontStencilReference = 0;
1629 SetBitField(mDepthStencilStateInfo.back.ops.fail, VK_STENCIL_OP_KEEP);
1630 SetBitField(mDepthStencilStateInfo.back.ops.pass, VK_STENCIL_OP_KEEP);
1631 SetBitField(mDepthStencilStateInfo.back.ops.depthFail, VK_STENCIL_OP_KEEP);
1632 SetBitField(mDepthStencilStateInfo.back.ops.compare, VK_COMPARE_OP_ALWAYS);
1633 SetBitField(mDepthStencilStateInfo.back.compareMask, 0xFF);
1634 SetBitField(mDepthStencilStateInfo.back.writeMask, 0xFF);
1635 mDepthStencilStateInfo.backStencilReference = 0;
1636
1637 mDepthStencilStateInfo.depthCompareOpAndSurfaceRotation.surfaceRotation =
1638 static_cast<uint8_t>(SurfaceRotation::Identity);
1639
1640 PackedInputAssemblyAndColorBlendStateInfo &inputAndBlend = mInputAssemblyAndColorBlendStateInfo;
1641 inputAndBlend.logic.opEnable = 0;
1642 inputAndBlend.logic.op = static_cast<uint32_t>(VK_LOGIC_OP_CLEAR);
1643 inputAndBlend.blendEnableMask = 0;
1644 inputAndBlend.blendConstants[0] = 0.0f;
1645 inputAndBlend.blendConstants[1] = 0.0f;
1646 inputAndBlend.blendConstants[2] = 0.0f;
1647 inputAndBlend.blendConstants[3] = 0.0f;
1648
1649 VkFlags allColorBits = (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
1650 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
1651
1652 for (uint32_t colorIndexGL = 0; colorIndexGL < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
1653 ++colorIndexGL)
1654 {
1655 Int4Array_Set(inputAndBlend.colorWriteMaskBits, colorIndexGL, allColorBits);
1656 }
1657
1658 PackedColorBlendAttachmentState blendAttachmentState;
1659 SetBitField(blendAttachmentState.srcColorBlendFactor, VK_BLEND_FACTOR_ONE);
1660 SetBitField(blendAttachmentState.dstColorBlendFactor, VK_BLEND_FACTOR_ZERO);
1661 SetBitField(blendAttachmentState.colorBlendOp, VK_BLEND_OP_ADD);
1662 SetBitField(blendAttachmentState.srcAlphaBlendFactor, VK_BLEND_FACTOR_ONE);
1663 SetBitField(blendAttachmentState.dstAlphaBlendFactor, VK_BLEND_FACTOR_ZERO);
1664 SetBitField(blendAttachmentState.alphaBlendOp, VK_BLEND_OP_ADD);
1665
1666 std::fill(&inputAndBlend.attachments[0],
1667 &inputAndBlend.attachments[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS],
1668 blendAttachmentState);
1669
1670 SetBitField(inputAndBlend.primitive.topology, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
1671 SetBitField(inputAndBlend.primitive.patchVertices, 3);
1672 inputAndBlend.primitive.restartEnable = 0;
1673
1674 mDrawableSize.width = 1;
1675 mDrawableSize.height = 1;
1676 }
1677
initializePipeline(ContextVk * contextVk,const 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,const ShaderModule * tessControlModule,const ShaderModule * tessEvaluationModule,const SpecializationConstants & specConsts,Pipeline * pipelineOut) const1678 angle::Result GraphicsPipelineDesc::initializePipeline(
1679 ContextVk *contextVk,
1680 const PipelineCache &pipelineCacheVk,
1681 const RenderPass &compatibleRenderPass,
1682 const PipelineLayout &pipelineLayout,
1683 const gl::AttributesMask &activeAttribLocationsMask,
1684 const gl::ComponentTypeMask &programAttribsTypeMask,
1685 const ShaderModule *vertexModule,
1686 const ShaderModule *fragmentModule,
1687 const ShaderModule *geometryModule,
1688 const ShaderModule *tessControlModule,
1689 const ShaderModule *tessEvaluationModule,
1690 const SpecializationConstants &specConsts,
1691 Pipeline *pipelineOut) const
1692 {
1693 angle::FixedVector<VkPipelineShaderStageCreateInfo, 5> shaderStages;
1694 VkPipelineVertexInputStateCreateInfo vertexInputState = {};
1695 VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = {};
1696 VkPipelineViewportStateCreateInfo viewportState = {};
1697 VkPipelineRasterizationStateCreateInfo rasterState = {};
1698 VkPipelineMultisampleStateCreateInfo multisampleState = {};
1699 VkPipelineDepthStencilStateCreateInfo depthStencilState = {};
1700 gl::DrawBuffersArray<VkPipelineColorBlendAttachmentState> blendAttachmentState;
1701 VkPipelineTessellationStateCreateInfo tessellationState = {};
1702 VkPipelineTessellationDomainOriginStateCreateInfo domainOriginState = {};
1703 VkPipelineColorBlendStateCreateInfo blendState = {};
1704 VkSpecializationInfo specializationInfo = {};
1705 VkGraphicsPipelineCreateInfo createInfo = {};
1706
1707 SpecializationConstantMap<VkSpecializationMapEntry> specializationEntries;
1708 InitializeSpecializationInfo(specConsts, &specializationEntries, &specializationInfo);
1709
1710 // Vertex shader is always expected to be present.
1711 ASSERT(vertexModule != nullptr);
1712 VkPipelineShaderStageCreateInfo vertexStage = {};
1713 SetPipelineShaderStageInfo(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1714 VK_SHADER_STAGE_VERTEX_BIT, vertexModule->getHandle(),
1715 specializationInfo, &vertexStage);
1716 shaderStages.push_back(vertexStage);
1717
1718 if (tessControlModule)
1719 {
1720 VkPipelineShaderStageCreateInfo tessControlStage = {};
1721 SetPipelineShaderStageInfo(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1722 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
1723 tessControlModule->getHandle(), specializationInfo,
1724 &tessControlStage);
1725 shaderStages.push_back(tessControlStage);
1726 }
1727
1728 if (tessEvaluationModule)
1729 {
1730 VkPipelineShaderStageCreateInfo tessEvaluationStage = {};
1731 SetPipelineShaderStageInfo(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1732 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1733 tessEvaluationModule->getHandle(), specializationInfo,
1734 &tessEvaluationStage);
1735 shaderStages.push_back(tessEvaluationStage);
1736 }
1737
1738 if (geometryModule)
1739 {
1740 VkPipelineShaderStageCreateInfo geometryStage = {};
1741 SetPipelineShaderStageInfo(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1742 VK_SHADER_STAGE_GEOMETRY_BIT, geometryModule->getHandle(),
1743 specializationInfo, &geometryStage);
1744 shaderStages.push_back(geometryStage);
1745 }
1746
1747 // Fragment shader is optional.
1748 // anglebug.com/3509 - Don't compile the fragment shader if rasterizationDiscardEnable = true
1749 if (fragmentModule && !mRasterizationAndMultisampleStateInfo.bits.rasterizationDiscardEnable)
1750 {
1751 VkPipelineShaderStageCreateInfo fragmentStage = {};
1752 SetPipelineShaderStageInfo(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1753 VK_SHADER_STAGE_FRAGMENT_BIT, fragmentModule->getHandle(),
1754 specializationInfo, &fragmentStage);
1755 shaderStages.push_back(fragmentStage);
1756 }
1757
1758 // TODO(jmadill): Possibly use different path for ES 3.1 split bindings/attribs.
1759 gl::AttribArray<VkVertexInputBindingDescription> bindingDescs;
1760 gl::AttribArray<VkVertexInputAttributeDescription> attributeDescs;
1761
1762 uint32_t vertexAttribCount = 0;
1763
1764 size_t unpackedSize = sizeof(shaderStages) + sizeof(vertexInputState) +
1765 sizeof(inputAssemblyState) + sizeof(viewportState) + sizeof(rasterState) +
1766 sizeof(multisampleState) + sizeof(depthStencilState) +
1767 sizeof(tessellationState) + sizeof(blendAttachmentState) +
1768 sizeof(blendState) + sizeof(bindingDescs) + sizeof(attributeDescs);
1769 ANGLE_UNUSED_VARIABLE(unpackedSize);
1770
1771 gl::AttribArray<VkVertexInputBindingDivisorDescriptionEXT> divisorDesc;
1772 VkPipelineVertexInputDivisorStateCreateInfoEXT divisorState = {};
1773 divisorState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
1774 divisorState.pVertexBindingDivisors = divisorDesc.data();
1775 for (size_t attribIndexSizeT : activeAttribLocationsMask)
1776 {
1777 const uint32_t attribIndex = static_cast<uint32_t>(attribIndexSizeT);
1778
1779 VkVertexInputBindingDescription &bindingDesc = bindingDescs[vertexAttribCount];
1780 VkVertexInputAttributeDescription &attribDesc = attributeDescs[vertexAttribCount];
1781 const PackedAttribDesc &packedAttrib = mVertexInputAttribs.attribs[attribIndex];
1782
1783 bindingDesc.binding = attribIndex;
1784 bindingDesc.stride = static_cast<uint32_t>(packedAttrib.stride);
1785 if (packedAttrib.divisor != 0)
1786 {
1787 bindingDesc.inputRate = static_cast<VkVertexInputRate>(VK_VERTEX_INPUT_RATE_INSTANCE);
1788 divisorDesc[divisorState.vertexBindingDivisorCount].binding = bindingDesc.binding;
1789 divisorDesc[divisorState.vertexBindingDivisorCount].divisor = packedAttrib.divisor;
1790 ++divisorState.vertexBindingDivisorCount;
1791 }
1792 else
1793 {
1794 bindingDesc.inputRate = static_cast<VkVertexInputRate>(VK_VERTEX_INPUT_RATE_VERTEX);
1795 }
1796
1797 // Get the corresponding VkFormat for the attrib's format.
1798 angle::FormatID formatID = static_cast<angle::FormatID>(packedAttrib.format);
1799 const Format &format = contextVk->getRenderer()->getFormat(formatID);
1800 const angle::Format &angleFormat = format.intendedFormat();
1801 VkFormat vkFormat = format.actualBufferVkFormat(packedAttrib.compressed);
1802
1803 gl::ComponentType attribType =
1804 GetVertexAttributeComponentType(angleFormat.isPureInt(), angleFormat.vertexAttribType);
1805 gl::ComponentType programAttribType =
1806 gl::GetComponentTypeMask(programAttribsTypeMask, attribIndex);
1807
1808 // This forces stride to 0 when glVertexAttribute specifies a different type from the
1809 // program's attribute type except when the type mismatch is a mismatched integer sign.
1810 if (attribType != programAttribType)
1811 {
1812 if (attribType == gl::ComponentType::Float ||
1813 programAttribType == gl::ComponentType::Float)
1814 {
1815 // When dealing with float to int or unsigned int or vice versa, just override the
1816 // format with a compatible one.
1817 vkFormat = kMismatchedComponentTypeMap[programAttribType];
1818 }
1819 else
1820 {
1821 // When converting from an unsigned to a signed format or vice versa, attempt to
1822 // match the bit width.
1823 angle::FormatID convertedFormatID = gl::ConvertFormatSignedness(angleFormat);
1824 const Format &convertedFormat =
1825 contextVk->getRenderer()->getFormat(convertedFormatID);
1826 ASSERT(angleFormat.channelCount == convertedFormat.intendedFormat().channelCount);
1827 ASSERT(angleFormat.redBits == convertedFormat.intendedFormat().redBits);
1828 ASSERT(angleFormat.greenBits == convertedFormat.intendedFormat().greenBits);
1829 ASSERT(angleFormat.blueBits == convertedFormat.intendedFormat().blueBits);
1830 ASSERT(angleFormat.alphaBits == convertedFormat.intendedFormat().alphaBits);
1831
1832 vkFormat = convertedFormat.actualBufferVkFormat(packedAttrib.compressed);
1833 }
1834
1835 GLenum programAttributeType =
1836 contextVk->getState().getProgramExecutable()->getProgramInputs()[attribIndex].type;
1837 GLuint attribSize = gl::GetVertexFormatFromID(formatID).components;
1838 GLuint shaderVarSize =
1839 static_cast<GLuint>(gl::VariableColumnCount(programAttributeType));
1840
1841 ASSERT(contextVk->getNativeExtensions().relaxedVertexAttributeTypeANGLE);
1842 if (programAttribType == gl::ComponentType::Float ||
1843 attribType == gl::ComponentType::Float || attribSize != shaderVarSize)
1844 {
1845 bindingDesc.stride = 0; // Prevent out-of-bounds accesses.
1846 }
1847 }
1848
1849 // The binding index could become more dynamic in ES 3.1.
1850 attribDesc.binding = attribIndex;
1851 attribDesc.format = vkFormat;
1852 attribDesc.location = static_cast<uint32_t>(attribIndex);
1853 attribDesc.offset = packedAttrib.offset;
1854
1855 vertexAttribCount++;
1856 }
1857
1858 // The binding descriptions are filled in at draw time.
1859 vertexInputState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
1860 vertexInputState.flags = 0;
1861 vertexInputState.vertexBindingDescriptionCount = vertexAttribCount;
1862 vertexInputState.pVertexBindingDescriptions = bindingDescs.data();
1863 vertexInputState.vertexAttributeDescriptionCount = vertexAttribCount;
1864 vertexInputState.pVertexAttributeDescriptions = attributeDescs.data();
1865 if (divisorState.vertexBindingDivisorCount)
1866 vertexInputState.pNext = &divisorState;
1867
1868 // Primitive topology is filled in at draw time.
1869 inputAssemblyState.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
1870 inputAssemblyState.flags = 0;
1871 inputAssemblyState.topology =
1872 static_cast<VkPrimitiveTopology>(mInputAssemblyAndColorBlendStateInfo.primitive.topology);
1873 // http://anglebug.com/3832
1874 // We currently hit a VK Validation here where VUID
1875 // VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00428 is flagged because we allow
1876 // primitiveRestartEnable to be true for topologies VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
1877 // VK_PRIMITIVE_TOPOLOGY_LINE_LIST, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
1878 // VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,
1879 // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY and VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
1880 // However if we force primiteRestartEnable to FALSE we fail tests.
1881 // Need to identify alternate fix.
1882 inputAssemblyState.primitiveRestartEnable =
1883 static_cast<VkBool32>(mInputAssemblyAndColorBlendStateInfo.primitive.restartEnable);
1884
1885 // Set initial viewport and scissor state.
1886 viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
1887 viewportState.flags = 0;
1888 viewportState.viewportCount = 1;
1889 viewportState.pViewports = nullptr;
1890 viewportState.scissorCount = 1;
1891 viewportState.pScissors = nullptr;
1892
1893 const PackedRasterizationAndMultisampleStateInfo &rasterAndMS =
1894 mRasterizationAndMultisampleStateInfo;
1895
1896 // Rasterizer state.
1897 rasterState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
1898 rasterState.flags = 0;
1899 rasterState.depthClampEnable = static_cast<VkBool32>(rasterAndMS.bits.depthClampEnable);
1900 rasterState.rasterizerDiscardEnable =
1901 static_cast<VkBool32>(rasterAndMS.bits.rasterizationDiscardEnable);
1902 rasterState.polygonMode = static_cast<VkPolygonMode>(rasterAndMS.bits.polygonMode);
1903 rasterState.cullMode = static_cast<VkCullModeFlags>(rasterAndMS.bits.cullMode);
1904 rasterState.frontFace = static_cast<VkFrontFace>(rasterAndMS.bits.frontFace);
1905 rasterState.depthBiasEnable = static_cast<VkBool32>(rasterAndMS.bits.depthBiasEnable);
1906 rasterState.depthBiasConstantFactor = rasterAndMS.depthBiasConstantFactor;
1907 rasterState.depthBiasClamp = rasterAndMS.depthBiasClamp;
1908 rasterState.depthBiasSlopeFactor = rasterAndMS.depthBiasSlopeFactor;
1909 rasterState.lineWidth = rasterAndMS.lineWidth;
1910 const void **pNextPtr = &rasterState.pNext;
1911
1912 VkPipelineRasterizationLineStateCreateInfoEXT rasterLineState = {};
1913 rasterLineState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT;
1914 // Enable Bresenham line rasterization if available and the following conditions are met:
1915 // 1.) not multisampling
1916 // 2.) VUID-VkGraphicsPipelineCreateInfo-lineRasterizationMode-02766:
1917 // The Vulkan spec states: If the lineRasterizationMode member of a
1918 // VkPipelineRasterizationLineStateCreateInfoEXT structure included in the pNext chain of
1919 // pRasterizationState is VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT or
1920 // VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT and if rasterization is enabled, then the
1921 // alphaToCoverageEnable, alphaToOneEnable, and sampleShadingEnable members of pMultisampleState
1922 // must all be VK_FALSE.
1923 if (rasterAndMS.bits.rasterizationSamples <= 1 &&
1924 !rasterAndMS.bits.rasterizationDiscardEnable && !rasterAndMS.bits.alphaToCoverageEnable &&
1925 !rasterAndMS.bits.alphaToOneEnable && !rasterAndMS.bits.sampleShadingEnable &&
1926 contextVk->getFeatures().bresenhamLineRasterization.enabled)
1927 {
1928 rasterLineState.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;
1929 *pNextPtr = &rasterLineState;
1930 pNextPtr = &rasterLineState.pNext;
1931 }
1932
1933 VkPipelineRasterizationProvokingVertexStateCreateInfoEXT provokingVertexState = {};
1934 provokingVertexState.sType =
1935 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT;
1936 // Always set provoking vertex mode to last if available.
1937 if (contextVk->getFeatures().provokingVertex.enabled)
1938 {
1939 provokingVertexState.provokingVertexMode = VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT;
1940 *pNextPtr = &provokingVertexState;
1941 pNextPtr = &provokingVertexState.pNext;
1942 }
1943
1944 // When depth clamping is used, depth clipping is automatically disabled.
1945 // When the 'depthClamping' feature is enabled, we'll be using depth clamping
1946 // to work around a driver issue, not as an alternative to depth clipping. Therefore we need to
1947 // explicitly re-enable depth clipping.
1948 VkPipelineRasterizationDepthClipStateCreateInfoEXT depthClipState = {};
1949 depthClipState.sType =
1950 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT;
1951 if (contextVk->getFeatures().depthClamping.enabled)
1952 {
1953 depthClipState.depthClipEnable = VK_TRUE;
1954 *pNextPtr = &depthClipState;
1955 pNextPtr = &depthClipState.pNext;
1956 }
1957
1958 VkPipelineRasterizationStateStreamCreateInfoEXT rasterStreamState = {};
1959 rasterStreamState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT;
1960 if (contextVk->getFeatures().supportsTransformFeedbackExtension.enabled)
1961 {
1962 rasterStreamState.rasterizationStream = 0;
1963 *pNextPtr = &rasterStreamState;
1964 pNextPtr = &rasterStreamState.pNext;
1965 }
1966
1967 // Multisample state.
1968 multisampleState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
1969 multisampleState.flags = 0;
1970 multisampleState.rasterizationSamples =
1971 gl_vk::GetSamples(rasterAndMS.bits.rasterizationSamples);
1972 multisampleState.sampleShadingEnable =
1973 static_cast<VkBool32>(rasterAndMS.bits.sampleShadingEnable);
1974 multisampleState.minSampleShading = rasterAndMS.minSampleShading;
1975 multisampleState.pSampleMask = rasterAndMS.sampleMask;
1976 multisampleState.alphaToCoverageEnable =
1977 static_cast<VkBool32>(rasterAndMS.bits.alphaToCoverageEnable);
1978 multisampleState.alphaToOneEnable = static_cast<VkBool32>(rasterAndMS.bits.alphaToOneEnable);
1979
1980 // Depth/stencil state.
1981 depthStencilState.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
1982 depthStencilState.flags = 0;
1983 depthStencilState.depthTestEnable =
1984 static_cast<VkBool32>(mDepthStencilStateInfo.enable.depthTest);
1985 depthStencilState.depthWriteEnable =
1986 static_cast<VkBool32>(mDepthStencilStateInfo.enable.depthWrite);
1987 depthStencilState.depthCompareOp = static_cast<VkCompareOp>(
1988 mDepthStencilStateInfo.depthCompareOpAndSurfaceRotation.depthCompareOp);
1989 depthStencilState.depthBoundsTestEnable =
1990 static_cast<VkBool32>(mDepthStencilStateInfo.enable.depthBoundsTest);
1991 depthStencilState.stencilTestEnable =
1992 static_cast<VkBool32>(mDepthStencilStateInfo.enable.stencilTest);
1993 UnpackStencilState(mDepthStencilStateInfo.front, mDepthStencilStateInfo.frontStencilReference,
1994 &depthStencilState.front);
1995 UnpackStencilState(mDepthStencilStateInfo.back, mDepthStencilStateInfo.backStencilReference,
1996 &depthStencilState.back);
1997 depthStencilState.minDepthBounds = mDepthStencilStateInfo.minDepthBounds;
1998 depthStencilState.maxDepthBounds = mDepthStencilStateInfo.maxDepthBounds;
1999
2000 const PackedInputAssemblyAndColorBlendStateInfo &inputAndBlend =
2001 mInputAssemblyAndColorBlendStateInfo;
2002
2003 blendState.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
2004 blendState.flags = 0;
2005 blendState.logicOpEnable = static_cast<VkBool32>(inputAndBlend.logic.opEnable);
2006 blendState.logicOp = static_cast<VkLogicOp>(inputAndBlend.logic.op);
2007 blendState.attachmentCount = static_cast<uint32_t>(mRenderPassDesc.colorAttachmentRange());
2008 blendState.pAttachments = blendAttachmentState.data();
2009
2010 // If this graphics pipeline is for the unresolve operation, correct the color attachment count
2011 // for that subpass.
2012 if ((mRenderPassDesc.getColorUnresolveAttachmentMask().any() ||
2013 mRenderPassDesc.hasDepthStencilUnresolveAttachment()) &&
2014 mRasterizationAndMultisampleStateInfo.bits.subpass == 0)
2015 {
2016 blendState.attachmentCount =
2017 static_cast<uint32_t>(mRenderPassDesc.getColorUnresolveAttachmentMask().count());
2018 }
2019
2020 for (int i = 0; i < 4; i++)
2021 {
2022 blendState.blendConstants[i] = inputAndBlend.blendConstants[i];
2023 }
2024
2025 const gl::DrawBufferMask blendEnableMask(inputAndBlend.blendEnableMask);
2026
2027 // Zero-init all states.
2028 blendAttachmentState = {};
2029
2030 for (uint32_t colorIndexGL = 0; colorIndexGL < blendState.attachmentCount; ++colorIndexGL)
2031 {
2032 VkPipelineColorBlendAttachmentState &state = blendAttachmentState[colorIndexGL];
2033
2034 if (blendEnableMask[colorIndexGL])
2035 {
2036 // To avoid triggering valid usage error, blending must be disabled for formats that do
2037 // not have VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT feature bit set.
2038 // From OpenGL ES clients, this means disabling blending for integer formats.
2039 if (!angle::Format::Get(mRenderPassDesc[colorIndexGL]).isInt())
2040 {
2041 ASSERT(!contextVk->getRenderer()
2042 ->getFormat(mRenderPassDesc[colorIndexGL])
2043 .actualImageFormat()
2044 .isInt());
2045 state.blendEnable = VK_TRUE;
2046 UnpackBlendAttachmentState(inputAndBlend.attachments[colorIndexGL], &state);
2047 }
2048 }
2049 state.colorWriteMask =
2050 Int4Array_Get<VkColorComponentFlags>(inputAndBlend.colorWriteMaskBits, colorIndexGL);
2051 }
2052
2053 // Dynamic state
2054 angle::FixedVector<VkDynamicState, 2> dynamicStateList;
2055 dynamicStateList.push_back(VK_DYNAMIC_STATE_VIEWPORT);
2056 dynamicStateList.push_back(VK_DYNAMIC_STATE_SCISSOR);
2057
2058 VkPipelineDynamicStateCreateInfo dynamicState = {};
2059 dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
2060 dynamicState.dynamicStateCount = static_cast<uint32_t>(dynamicStateList.size());
2061 dynamicState.pDynamicStates = dynamicStateList.data();
2062
2063 // tessellation State
2064 if (tessControlModule && tessEvaluationModule)
2065 {
2066 domainOriginState.sType =
2067 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO;
2068 domainOriginState.pNext = NULL;
2069 domainOriginState.domainOrigin = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT;
2070
2071 tessellationState.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
2072 tessellationState.flags = 0;
2073 tessellationState.pNext = &domainOriginState;
2074 tessellationState.patchControlPoints =
2075 static_cast<uint32_t>(inputAndBlend.primitive.patchVertices);
2076 }
2077
2078 createInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
2079 createInfo.flags = 0;
2080 createInfo.stageCount = static_cast<uint32_t>(shaderStages.size());
2081 createInfo.pStages = shaderStages.data();
2082 createInfo.pVertexInputState = &vertexInputState;
2083 createInfo.pInputAssemblyState = &inputAssemblyState;
2084 createInfo.pTessellationState = &tessellationState;
2085 createInfo.pViewportState = &viewportState;
2086 createInfo.pRasterizationState = &rasterState;
2087 createInfo.pMultisampleState = &multisampleState;
2088 createInfo.pDepthStencilState = &depthStencilState;
2089 createInfo.pColorBlendState = &blendState;
2090 createInfo.pDynamicState = dynamicStateList.empty() ? nullptr : &dynamicState;
2091 createInfo.layout = pipelineLayout.getHandle();
2092 createInfo.renderPass = compatibleRenderPass.getHandle();
2093 createInfo.subpass = mRasterizationAndMultisampleStateInfo.bits.subpass;
2094 createInfo.basePipelineHandle = VK_NULL_HANDLE;
2095 createInfo.basePipelineIndex = 0;
2096
2097 ANGLE_VK_TRY(contextVk,
2098 pipelineOut->initGraphics(contextVk->getDevice(), createInfo, pipelineCacheVk));
2099 return angle::Result::Continue;
2100 }
2101
updateVertexInput(GraphicsPipelineTransitionBits * transition,uint32_t attribIndex,GLuint stride,GLuint divisor,angle::FormatID format,bool compressed,GLuint relativeOffset)2102 void GraphicsPipelineDesc::updateVertexInput(GraphicsPipelineTransitionBits *transition,
2103 uint32_t attribIndex,
2104 GLuint stride,
2105 GLuint divisor,
2106 angle::FormatID format,
2107 bool compressed,
2108 GLuint relativeOffset)
2109 {
2110 PackedAttribDesc &packedAttrib = mVertexInputAttribs.attribs[attribIndex];
2111
2112 SetBitField(packedAttrib.stride, stride);
2113 SetBitField(packedAttrib.divisor, divisor);
2114
2115 if (format == angle::FormatID::NONE)
2116 {
2117 UNIMPLEMENTED();
2118 }
2119
2120 SetBitField(packedAttrib.format, format);
2121 SetBitField(packedAttrib.compressed, compressed);
2122 SetBitField(packedAttrib.offset, relativeOffset);
2123
2124 constexpr size_t kAttribBits = kPackedAttribDescSize * kBitsPerByte;
2125 const size_t kBit =
2126 ANGLE_GET_INDEXED_TRANSITION_BIT(mVertexInputAttribs, attribs, attribIndex, kAttribBits);
2127
2128 // Cover the next dirty bit conservatively. Because each attribute is 6 bytes.
2129 transition->set(kBit);
2130 transition->set(kBit + 1);
2131 }
2132
updateTopology(GraphicsPipelineTransitionBits * transition,gl::PrimitiveMode drawMode)2133 void GraphicsPipelineDesc::updateTopology(GraphicsPipelineTransitionBits *transition,
2134 gl::PrimitiveMode drawMode)
2135 {
2136 VkPrimitiveTopology vkTopology = gl_vk::GetPrimitiveTopology(drawMode);
2137 SetBitField(mInputAssemblyAndColorBlendStateInfo.primitive.topology, vkTopology);
2138
2139 transition->set(ANGLE_GET_TRANSITION_BIT(mInputAssemblyAndColorBlendStateInfo, primitive));
2140 }
2141
updatePrimitiveRestartEnabled(GraphicsPipelineTransitionBits * transition,bool primitiveRestartEnabled)2142 void GraphicsPipelineDesc::updatePrimitiveRestartEnabled(GraphicsPipelineTransitionBits *transition,
2143 bool primitiveRestartEnabled)
2144 {
2145 mInputAssemblyAndColorBlendStateInfo.primitive.restartEnable =
2146 static_cast<uint16_t>(primitiveRestartEnabled);
2147 transition->set(ANGLE_GET_TRANSITION_BIT(mInputAssemblyAndColorBlendStateInfo, primitive));
2148 }
2149
setCullMode(VkCullModeFlagBits cullMode)2150 void GraphicsPipelineDesc::setCullMode(VkCullModeFlagBits cullMode)
2151 {
2152 SetBitField(mRasterizationAndMultisampleStateInfo.bits.cullMode, cullMode);
2153 }
2154
updateCullMode(GraphicsPipelineTransitionBits * transition,const gl::RasterizerState & rasterState)2155 void GraphicsPipelineDesc::updateCullMode(GraphicsPipelineTransitionBits *transition,
2156 const gl::RasterizerState &rasterState)
2157 {
2158 setCullMode(gl_vk::GetCullMode(rasterState));
2159 transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, bits));
2160 }
2161
updateFrontFace(GraphicsPipelineTransitionBits * transition,const gl::RasterizerState & rasterState,bool invertFrontFace)2162 void GraphicsPipelineDesc::updateFrontFace(GraphicsPipelineTransitionBits *transition,
2163 const gl::RasterizerState &rasterState,
2164 bool invertFrontFace)
2165 {
2166 mRasterizationAndMultisampleStateInfo.bits.frontFace =
2167 static_cast<uint16_t>(gl_vk::GetFrontFace(rasterState.frontFace, invertFrontFace));
2168 transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, bits));
2169 }
2170
updateLineWidth(GraphicsPipelineTransitionBits * transition,float lineWidth)2171 void GraphicsPipelineDesc::updateLineWidth(GraphicsPipelineTransitionBits *transition,
2172 float lineWidth)
2173 {
2174 mRasterizationAndMultisampleStateInfo.lineWidth = lineWidth;
2175 transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, lineWidth));
2176 }
2177
updateRasterizerDiscardEnabled(GraphicsPipelineTransitionBits * transition,bool rasterizerDiscardEnabled)2178 void GraphicsPipelineDesc::updateRasterizerDiscardEnabled(
2179 GraphicsPipelineTransitionBits *transition,
2180 bool rasterizerDiscardEnabled)
2181 {
2182 mRasterizationAndMultisampleStateInfo.bits.rasterizationDiscardEnable =
2183 static_cast<uint32_t>(rasterizerDiscardEnabled);
2184 transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, bits));
2185 }
2186
getRasterizationSamples() const2187 uint32_t GraphicsPipelineDesc::getRasterizationSamples() const
2188 {
2189 return mRasterizationAndMultisampleStateInfo.bits.rasterizationSamples;
2190 }
2191
setRasterizationSamples(uint32_t rasterizationSamples)2192 void GraphicsPipelineDesc::setRasterizationSamples(uint32_t rasterizationSamples)
2193 {
2194 mRasterizationAndMultisampleStateInfo.bits.rasterizationSamples = rasterizationSamples;
2195 }
2196
updateRasterizationSamples(GraphicsPipelineTransitionBits * transition,uint32_t rasterizationSamples)2197 void GraphicsPipelineDesc::updateRasterizationSamples(GraphicsPipelineTransitionBits *transition,
2198 uint32_t rasterizationSamples)
2199 {
2200 setRasterizationSamples(rasterizationSamples);
2201 transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, bits));
2202 }
2203
updateAlphaToCoverageEnable(GraphicsPipelineTransitionBits * transition,bool enable)2204 void GraphicsPipelineDesc::updateAlphaToCoverageEnable(GraphicsPipelineTransitionBits *transition,
2205 bool enable)
2206 {
2207 mRasterizationAndMultisampleStateInfo.bits.alphaToCoverageEnable = enable;
2208 transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, bits));
2209 }
2210
updateAlphaToOneEnable(GraphicsPipelineTransitionBits * transition,bool enable)2211 void GraphicsPipelineDesc::updateAlphaToOneEnable(GraphicsPipelineTransitionBits *transition,
2212 bool enable)
2213 {
2214 mRasterizationAndMultisampleStateInfo.bits.alphaToOneEnable = enable;
2215 transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, bits));
2216 }
2217
updateSampleMask(GraphicsPipelineTransitionBits * transition,uint32_t maskNumber,uint32_t mask)2218 void GraphicsPipelineDesc::updateSampleMask(GraphicsPipelineTransitionBits *transition,
2219 uint32_t maskNumber,
2220 uint32_t mask)
2221 {
2222 ASSERT(maskNumber < gl::MAX_SAMPLE_MASK_WORDS);
2223 mRasterizationAndMultisampleStateInfo.sampleMask[maskNumber] = mask;
2224
2225 constexpr size_t kMaskBits =
2226 sizeof(mRasterizationAndMultisampleStateInfo.sampleMask[0]) * kBitsPerByte;
2227 transition->set(ANGLE_GET_INDEXED_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo,
2228 sampleMask, maskNumber, kMaskBits));
2229 }
2230
updateSampleShading(GraphicsPipelineTransitionBits * transition,bool enable,float value)2231 void GraphicsPipelineDesc::updateSampleShading(GraphicsPipelineTransitionBits *transition,
2232 bool enable,
2233 float value)
2234 {
2235 mRasterizationAndMultisampleStateInfo.bits.sampleShadingEnable = enable;
2236 mRasterizationAndMultisampleStateInfo.minSampleShading = (enable ? value : 1.0f);
2237
2238 transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, bits));
2239 transition->set(
2240 ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, minSampleShading));
2241 }
2242
updateBlendColor(GraphicsPipelineTransitionBits * transition,const gl::ColorF & color)2243 void GraphicsPipelineDesc::updateBlendColor(GraphicsPipelineTransitionBits *transition,
2244 const gl::ColorF &color)
2245 {
2246 mInputAssemblyAndColorBlendStateInfo.blendConstants[0] = color.red;
2247 mInputAssemblyAndColorBlendStateInfo.blendConstants[1] = color.green;
2248 mInputAssemblyAndColorBlendStateInfo.blendConstants[2] = color.blue;
2249 mInputAssemblyAndColorBlendStateInfo.blendConstants[3] = color.alpha;
2250 constexpr size_t kSize = sizeof(mInputAssemblyAndColorBlendStateInfo.blendConstants[0]) * 8;
2251
2252 for (int index = 0; index < 4; ++index)
2253 {
2254 const size_t kBit = ANGLE_GET_INDEXED_TRANSITION_BIT(mInputAssemblyAndColorBlendStateInfo,
2255 blendConstants, index, kSize);
2256 transition->set(kBit);
2257 }
2258 }
2259
updateBlendEnabled(GraphicsPipelineTransitionBits * transition,gl::DrawBufferMask blendEnabledMask)2260 void GraphicsPipelineDesc::updateBlendEnabled(GraphicsPipelineTransitionBits *transition,
2261 gl::DrawBufferMask blendEnabledMask)
2262 {
2263 mInputAssemblyAndColorBlendStateInfo.blendEnableMask =
2264 static_cast<uint8_t>(blendEnabledMask.bits());
2265 transition->set(
2266 ANGLE_GET_TRANSITION_BIT(mInputAssemblyAndColorBlendStateInfo, blendEnableMask));
2267 }
2268
updateBlendEquations(GraphicsPipelineTransitionBits * transition,const gl::BlendStateExt & blendStateExt)2269 void GraphicsPipelineDesc::updateBlendEquations(GraphicsPipelineTransitionBits *transition,
2270 const gl::BlendStateExt &blendStateExt)
2271 {
2272 constexpr size_t kSize = sizeof(PackedColorBlendAttachmentState) * 8;
2273
2274 for (size_t attachmentIndex = 0; attachmentIndex < blendStateExt.mMaxDrawBuffers;
2275 ++attachmentIndex)
2276 {
2277 PackedColorBlendAttachmentState &blendAttachmentState =
2278 mInputAssemblyAndColorBlendStateInfo.attachments[attachmentIndex];
2279 blendAttachmentState.colorBlendOp =
2280 PackGLBlendOp(blendStateExt.getEquationColorIndexed(attachmentIndex));
2281 blendAttachmentState.alphaBlendOp =
2282 PackGLBlendOp(blendStateExt.getEquationAlphaIndexed(attachmentIndex));
2283 transition->set(ANGLE_GET_INDEXED_TRANSITION_BIT(mInputAssemblyAndColorBlendStateInfo,
2284 attachments, attachmentIndex, kSize));
2285 }
2286 }
2287
updateBlendFuncs(GraphicsPipelineTransitionBits * transition,const gl::BlendStateExt & blendStateExt)2288 void GraphicsPipelineDesc::updateBlendFuncs(GraphicsPipelineTransitionBits *transition,
2289 const gl::BlendStateExt &blendStateExt)
2290 {
2291 constexpr size_t kSize = sizeof(PackedColorBlendAttachmentState) * 8;
2292 for (size_t attachmentIndex = 0; attachmentIndex < blendStateExt.mMaxDrawBuffers;
2293 ++attachmentIndex)
2294 {
2295 PackedColorBlendAttachmentState &blendAttachmentState =
2296 mInputAssemblyAndColorBlendStateInfo.attachments[attachmentIndex];
2297 blendAttachmentState.srcColorBlendFactor =
2298 PackGLBlendFactor(blendStateExt.getSrcColorIndexed(attachmentIndex));
2299 blendAttachmentState.dstColorBlendFactor =
2300 PackGLBlendFactor(blendStateExt.getDstColorIndexed(attachmentIndex));
2301 blendAttachmentState.srcAlphaBlendFactor =
2302 PackGLBlendFactor(blendStateExt.getSrcAlphaIndexed(attachmentIndex));
2303 blendAttachmentState.dstAlphaBlendFactor =
2304 PackGLBlendFactor(blendStateExt.getDstAlphaIndexed(attachmentIndex));
2305 transition->set(ANGLE_GET_INDEXED_TRANSITION_BIT(mInputAssemblyAndColorBlendStateInfo,
2306 attachments, attachmentIndex, kSize));
2307 }
2308 }
2309
setColorWriteMasks(gl::BlendStateExt::ColorMaskStorage::Type colorMasks,const gl::DrawBufferMask & alphaMask,const gl::DrawBufferMask & enabledDrawBuffers)2310 void GraphicsPipelineDesc::setColorWriteMasks(gl::BlendStateExt::ColorMaskStorage::Type colorMasks,
2311 const gl::DrawBufferMask &alphaMask,
2312 const gl::DrawBufferMask &enabledDrawBuffers)
2313 {
2314 PackedInputAssemblyAndColorBlendStateInfo &inputAndBlend = mInputAssemblyAndColorBlendStateInfo;
2315
2316 for (uint32_t colorIndexGL = 0; colorIndexGL < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
2317 colorIndexGL++)
2318 {
2319 uint8_t colorMask =
2320 gl::BlendStateExt::ColorMaskStorage::GetValueIndexed(colorIndexGL, colorMasks);
2321
2322 uint8_t mask = 0;
2323 if (enabledDrawBuffers.test(colorIndexGL))
2324 {
2325 mask = alphaMask[colorIndexGL] ? (colorMask & ~VK_COLOR_COMPONENT_A_BIT) : colorMask;
2326 }
2327 Int4Array_Set(inputAndBlend.colorWriteMaskBits, colorIndexGL, mask);
2328 }
2329 }
2330
setSingleColorWriteMask(uint32_t colorIndexGL,VkColorComponentFlags colorComponentFlags)2331 void GraphicsPipelineDesc::setSingleColorWriteMask(uint32_t colorIndexGL,
2332 VkColorComponentFlags colorComponentFlags)
2333 {
2334 PackedInputAssemblyAndColorBlendStateInfo &inputAndBlend = mInputAssemblyAndColorBlendStateInfo;
2335 uint8_t colorMask = static_cast<uint8_t>(colorComponentFlags);
2336 Int4Array_Set(inputAndBlend.colorWriteMaskBits, colorIndexGL, colorMask);
2337 }
2338
updateColorWriteMasks(GraphicsPipelineTransitionBits * transition,gl::BlendStateExt::ColorMaskStorage::Type colorMasks,const gl::DrawBufferMask & alphaMask,const gl::DrawBufferMask & enabledDrawBuffers)2339 void GraphicsPipelineDesc::updateColorWriteMasks(
2340 GraphicsPipelineTransitionBits *transition,
2341 gl::BlendStateExt::ColorMaskStorage::Type colorMasks,
2342 const gl::DrawBufferMask &alphaMask,
2343 const gl::DrawBufferMask &enabledDrawBuffers)
2344 {
2345 setColorWriteMasks(colorMasks, alphaMask, enabledDrawBuffers);
2346
2347 for (size_t colorIndexGL = 0; colorIndexGL < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
2348 colorIndexGL++)
2349 {
2350 transition->set(ANGLE_GET_INDEXED_TRANSITION_BIT(mInputAssemblyAndColorBlendStateInfo,
2351 colorWriteMaskBits, colorIndexGL, 4));
2352 }
2353 }
2354
setDepthTestEnabled(bool enabled)2355 void GraphicsPipelineDesc::setDepthTestEnabled(bool enabled)
2356 {
2357 mDepthStencilStateInfo.enable.depthTest = enabled;
2358 }
2359
setDepthWriteEnabled(bool enabled)2360 void GraphicsPipelineDesc::setDepthWriteEnabled(bool enabled)
2361 {
2362 mDepthStencilStateInfo.enable.depthWrite = enabled;
2363 }
2364
setDepthFunc(VkCompareOp op)2365 void GraphicsPipelineDesc::setDepthFunc(VkCompareOp op)
2366 {
2367 SetBitField(mDepthStencilStateInfo.depthCompareOpAndSurfaceRotation.depthCompareOp, op);
2368 }
2369
setDepthClampEnabled(bool enabled)2370 void GraphicsPipelineDesc::setDepthClampEnabled(bool enabled)
2371 {
2372 mRasterizationAndMultisampleStateInfo.bits.depthClampEnable = enabled;
2373 }
2374
setStencilTestEnabled(bool enabled)2375 void GraphicsPipelineDesc::setStencilTestEnabled(bool enabled)
2376 {
2377 mDepthStencilStateInfo.enable.stencilTest = enabled;
2378 }
2379
setStencilFrontFuncs(uint8_t reference,VkCompareOp compareOp,uint8_t compareMask)2380 void GraphicsPipelineDesc::setStencilFrontFuncs(uint8_t reference,
2381 VkCompareOp compareOp,
2382 uint8_t compareMask)
2383 {
2384 mDepthStencilStateInfo.frontStencilReference = reference;
2385 mDepthStencilStateInfo.front.compareMask = compareMask;
2386 SetBitField(mDepthStencilStateInfo.front.ops.compare, compareOp);
2387 }
2388
setStencilBackFuncs(uint8_t reference,VkCompareOp compareOp,uint8_t compareMask)2389 void GraphicsPipelineDesc::setStencilBackFuncs(uint8_t reference,
2390 VkCompareOp compareOp,
2391 uint8_t compareMask)
2392 {
2393 mDepthStencilStateInfo.backStencilReference = reference;
2394 mDepthStencilStateInfo.back.compareMask = compareMask;
2395 SetBitField(mDepthStencilStateInfo.back.ops.compare, compareOp);
2396 }
2397
setStencilFrontOps(VkStencilOp failOp,VkStencilOp passOp,VkStencilOp depthFailOp)2398 void GraphicsPipelineDesc::setStencilFrontOps(VkStencilOp failOp,
2399 VkStencilOp passOp,
2400 VkStencilOp depthFailOp)
2401 {
2402 SetBitField(mDepthStencilStateInfo.front.ops.fail, failOp);
2403 SetBitField(mDepthStencilStateInfo.front.ops.pass, passOp);
2404 SetBitField(mDepthStencilStateInfo.front.ops.depthFail, depthFailOp);
2405 }
2406
setStencilBackOps(VkStencilOp failOp,VkStencilOp passOp,VkStencilOp depthFailOp)2407 void GraphicsPipelineDesc::setStencilBackOps(VkStencilOp failOp,
2408 VkStencilOp passOp,
2409 VkStencilOp depthFailOp)
2410 {
2411 SetBitField(mDepthStencilStateInfo.back.ops.fail, failOp);
2412 SetBitField(mDepthStencilStateInfo.back.ops.pass, passOp);
2413 SetBitField(mDepthStencilStateInfo.back.ops.depthFail, depthFailOp);
2414 }
2415
setStencilFrontWriteMask(uint8_t mask)2416 void GraphicsPipelineDesc::setStencilFrontWriteMask(uint8_t mask)
2417 {
2418 mDepthStencilStateInfo.front.writeMask = mask;
2419 }
2420
setStencilBackWriteMask(uint8_t mask)2421 void GraphicsPipelineDesc::setStencilBackWriteMask(uint8_t mask)
2422 {
2423 mDepthStencilStateInfo.back.writeMask = mask;
2424 }
2425
updateDepthTestEnabled(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState,const gl::Framebuffer * drawFramebuffer)2426 void GraphicsPipelineDesc::updateDepthTestEnabled(GraphicsPipelineTransitionBits *transition,
2427 const gl::DepthStencilState &depthStencilState,
2428 const gl::Framebuffer *drawFramebuffer)
2429 {
2430 // Only enable the depth test if the draw framebuffer has a depth buffer. It's possible that
2431 // we're emulating a stencil-only buffer with a depth-stencil buffer
2432 setDepthTestEnabled(depthStencilState.depthTest && drawFramebuffer->hasDepth());
2433 transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, enable));
2434 }
2435
updateDepthFunc(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState)2436 void GraphicsPipelineDesc::updateDepthFunc(GraphicsPipelineTransitionBits *transition,
2437 const gl::DepthStencilState &depthStencilState)
2438 {
2439 setDepthFunc(PackGLCompareFunc(depthStencilState.depthFunc));
2440 transition->set(
2441 ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, depthCompareOpAndSurfaceRotation));
2442 }
2443
updateSurfaceRotation(GraphicsPipelineTransitionBits * transition,const SurfaceRotation surfaceRotation)2444 void GraphicsPipelineDesc::updateSurfaceRotation(GraphicsPipelineTransitionBits *transition,
2445 const SurfaceRotation surfaceRotation)
2446 {
2447 SetBitField(mDepthStencilStateInfo.depthCompareOpAndSurfaceRotation.surfaceRotation,
2448 surfaceRotation);
2449 transition->set(
2450 ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, depthCompareOpAndSurfaceRotation));
2451 }
2452
updateDepthWriteEnabled(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState,const gl::Framebuffer * drawFramebuffer)2453 void GraphicsPipelineDesc::updateDepthWriteEnabled(GraphicsPipelineTransitionBits *transition,
2454 const gl::DepthStencilState &depthStencilState,
2455 const gl::Framebuffer *drawFramebuffer)
2456 {
2457 // Don't write to depth buffers that should not exist
2458 setDepthWriteEnabled(drawFramebuffer->hasDepth() ? depthStencilState.depthMask : false);
2459 transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, enable));
2460 }
2461
updateStencilTestEnabled(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState,const gl::Framebuffer * drawFramebuffer)2462 void GraphicsPipelineDesc::updateStencilTestEnabled(GraphicsPipelineTransitionBits *transition,
2463 const gl::DepthStencilState &depthStencilState,
2464 const gl::Framebuffer *drawFramebuffer)
2465 {
2466 // Only enable the stencil test if the draw framebuffer has a stencil buffer. It's possible
2467 // that we're emulating a depth-only buffer with a depth-stencil buffer
2468 setStencilTestEnabled(depthStencilState.stencilTest && drawFramebuffer->hasStencil());
2469 transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, enable));
2470 }
2471
updateStencilFrontFuncs(GraphicsPipelineTransitionBits * transition,GLint ref,const gl::DepthStencilState & depthStencilState)2472 void GraphicsPipelineDesc::updateStencilFrontFuncs(GraphicsPipelineTransitionBits *transition,
2473 GLint ref,
2474 const gl::DepthStencilState &depthStencilState)
2475 {
2476 setStencilFrontFuncs(static_cast<uint8_t>(ref),
2477 PackGLCompareFunc(depthStencilState.stencilFunc),
2478 static_cast<uint8_t>(depthStencilState.stencilMask));
2479 transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, front));
2480 transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, frontStencilReference));
2481 }
2482
updateStencilBackFuncs(GraphicsPipelineTransitionBits * transition,GLint ref,const gl::DepthStencilState & depthStencilState)2483 void GraphicsPipelineDesc::updateStencilBackFuncs(GraphicsPipelineTransitionBits *transition,
2484 GLint ref,
2485 const gl::DepthStencilState &depthStencilState)
2486 {
2487 setStencilBackFuncs(static_cast<uint8_t>(ref),
2488 PackGLCompareFunc(depthStencilState.stencilBackFunc),
2489 static_cast<uint8_t>(depthStencilState.stencilBackMask));
2490 transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, back));
2491 transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, backStencilReference));
2492 }
2493
updateStencilFrontOps(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState)2494 void GraphicsPipelineDesc::updateStencilFrontOps(GraphicsPipelineTransitionBits *transition,
2495 const gl::DepthStencilState &depthStencilState)
2496 {
2497 setStencilFrontOps(PackGLStencilOp(depthStencilState.stencilFail),
2498 PackGLStencilOp(depthStencilState.stencilPassDepthPass),
2499 PackGLStencilOp(depthStencilState.stencilPassDepthFail));
2500 transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, front));
2501 }
2502
updateStencilBackOps(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState)2503 void GraphicsPipelineDesc::updateStencilBackOps(GraphicsPipelineTransitionBits *transition,
2504 const gl::DepthStencilState &depthStencilState)
2505 {
2506 setStencilBackOps(PackGLStencilOp(depthStencilState.stencilBackFail),
2507 PackGLStencilOp(depthStencilState.stencilBackPassDepthPass),
2508 PackGLStencilOp(depthStencilState.stencilBackPassDepthFail));
2509 transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, back));
2510 }
2511
updateStencilFrontWriteMask(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState,const gl::Framebuffer * drawFramebuffer)2512 void GraphicsPipelineDesc::updateStencilFrontWriteMask(
2513 GraphicsPipelineTransitionBits *transition,
2514 const gl::DepthStencilState &depthStencilState,
2515 const gl::Framebuffer *drawFramebuffer)
2516 {
2517 // Don't write to stencil buffers that should not exist
2518 setStencilFrontWriteMask(static_cast<uint8_t>(
2519 drawFramebuffer->hasStencil() ? depthStencilState.stencilWritemask : 0));
2520 transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, front));
2521 }
2522
updateStencilBackWriteMask(GraphicsPipelineTransitionBits * transition,const gl::DepthStencilState & depthStencilState,const gl::Framebuffer * drawFramebuffer)2523 void GraphicsPipelineDesc::updateStencilBackWriteMask(
2524 GraphicsPipelineTransitionBits *transition,
2525 const gl::DepthStencilState &depthStencilState,
2526 const gl::Framebuffer *drawFramebuffer)
2527 {
2528 // Don't write to stencil buffers that should not exist
2529 setStencilBackWriteMask(static_cast<uint8_t>(
2530 drawFramebuffer->hasStencil() ? depthStencilState.stencilBackWritemask : 0));
2531 transition->set(ANGLE_GET_TRANSITION_BIT(mDepthStencilStateInfo, back));
2532 }
2533
updatePolygonOffsetFillEnabled(GraphicsPipelineTransitionBits * transition,bool enabled)2534 void GraphicsPipelineDesc::updatePolygonOffsetFillEnabled(
2535 GraphicsPipelineTransitionBits *transition,
2536 bool enabled)
2537 {
2538 mRasterizationAndMultisampleStateInfo.bits.depthBiasEnable = enabled;
2539 transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, bits));
2540 }
2541
updatePolygonOffset(GraphicsPipelineTransitionBits * transition,const gl::RasterizerState & rasterState)2542 void GraphicsPipelineDesc::updatePolygonOffset(GraphicsPipelineTransitionBits *transition,
2543 const gl::RasterizerState &rasterState)
2544 {
2545 mRasterizationAndMultisampleStateInfo.depthBiasSlopeFactor = rasterState.polygonOffsetFactor;
2546 mRasterizationAndMultisampleStateInfo.depthBiasConstantFactor = rasterState.polygonOffsetUnits;
2547 transition->set(
2548 ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, depthBiasSlopeFactor));
2549 transition->set(
2550 ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, depthBiasConstantFactor));
2551 }
2552
setRenderPassDesc(const RenderPassDesc & renderPassDesc)2553 void GraphicsPipelineDesc::setRenderPassDesc(const RenderPassDesc &renderPassDesc)
2554 {
2555 mRenderPassDesc = renderPassDesc;
2556 }
2557
updateDrawableSize(GraphicsPipelineTransitionBits * transition,uint32_t width,uint32_t height)2558 void GraphicsPipelineDesc::updateDrawableSize(GraphicsPipelineTransitionBits *transition,
2559 uint32_t width,
2560 uint32_t height)
2561 {
2562 SetBitField(mDrawableSize.width, width);
2563 SetBitField(mDrawableSize.height, height);
2564 transition->set(ANGLE_GET_TRANSITION_BIT(mDrawableSize, width));
2565 transition->set(ANGLE_GET_TRANSITION_BIT(mDrawableSize, height));
2566 }
2567
updateSubpass(GraphicsPipelineTransitionBits * transition,uint32_t subpass)2568 void GraphicsPipelineDesc::updateSubpass(GraphicsPipelineTransitionBits *transition,
2569 uint32_t subpass)
2570 {
2571 if (mRasterizationAndMultisampleStateInfo.bits.subpass != subpass)
2572 {
2573 SetBitField(mRasterizationAndMultisampleStateInfo.bits.subpass, subpass);
2574 transition->set(ANGLE_GET_TRANSITION_BIT(mRasterizationAndMultisampleStateInfo, bits));
2575 }
2576 }
2577
updatePatchVertices(GraphicsPipelineTransitionBits * transition,GLuint value)2578 void GraphicsPipelineDesc::updatePatchVertices(GraphicsPipelineTransitionBits *transition,
2579 GLuint value)
2580 {
2581 SetBitField(mInputAssemblyAndColorBlendStateInfo.primitive.patchVertices, value);
2582
2583 transition->set(ANGLE_GET_TRANSITION_BIT(mInputAssemblyAndColorBlendStateInfo, primitive));
2584 }
2585
resetSubpass(GraphicsPipelineTransitionBits * transition)2586 void GraphicsPipelineDesc::resetSubpass(GraphicsPipelineTransitionBits *transition)
2587 {
2588 updateSubpass(transition, 0);
2589 }
2590
nextSubpass(GraphicsPipelineTransitionBits * transition)2591 void GraphicsPipelineDesc::nextSubpass(GraphicsPipelineTransitionBits *transition)
2592 {
2593 updateSubpass(transition, mRasterizationAndMultisampleStateInfo.bits.subpass + 1);
2594 }
2595
setSubpass(uint32_t subpass)2596 void GraphicsPipelineDesc::setSubpass(uint32_t subpass)
2597 {
2598 SetBitField(mRasterizationAndMultisampleStateInfo.bits.subpass, subpass);
2599 }
2600
getSubpass() const2601 uint32_t GraphicsPipelineDesc::getSubpass() const
2602 {
2603 return mRasterizationAndMultisampleStateInfo.bits.subpass;
2604 }
2605
updateRenderPassDesc(GraphicsPipelineTransitionBits * transition,const RenderPassDesc & renderPassDesc)2606 void GraphicsPipelineDesc::updateRenderPassDesc(GraphicsPipelineTransitionBits *transition,
2607 const RenderPassDesc &renderPassDesc)
2608 {
2609 setRenderPassDesc(renderPassDesc);
2610
2611 // The RenderPass is a special case where it spans multiple bits but has no member.
2612 constexpr size_t kFirstBit =
2613 offsetof(GraphicsPipelineDesc, mRenderPassDesc) >> kTransitionByteShift;
2614 constexpr size_t kBitCount = kRenderPassDescSize >> kTransitionByteShift;
2615 for (size_t bit = 0; bit < kBitCount; ++bit)
2616 {
2617 transition->set(kFirstBit + bit);
2618 }
2619 }
2620
2621 // AttachmentOpsArray implementation.
AttachmentOpsArray()2622 AttachmentOpsArray::AttachmentOpsArray()
2623 {
2624 memset(&mOps, 0, sizeof(PackedAttachmentOpsDesc) * mOps.size());
2625 }
2626
2627 AttachmentOpsArray::~AttachmentOpsArray() = default;
2628
AttachmentOpsArray(const AttachmentOpsArray & other)2629 AttachmentOpsArray::AttachmentOpsArray(const AttachmentOpsArray &other)
2630 {
2631 memcpy(&mOps, &other.mOps, sizeof(PackedAttachmentOpsDesc) * mOps.size());
2632 }
2633
operator =(const AttachmentOpsArray & other)2634 AttachmentOpsArray &AttachmentOpsArray::operator=(const AttachmentOpsArray &other)
2635 {
2636 memcpy(&mOps, &other.mOps, sizeof(PackedAttachmentOpsDesc) * mOps.size());
2637 return *this;
2638 }
2639
operator [](PackedAttachmentIndex index) const2640 const PackedAttachmentOpsDesc &AttachmentOpsArray::operator[](PackedAttachmentIndex index) const
2641 {
2642 return mOps[index.get()];
2643 }
2644
operator [](PackedAttachmentIndex index)2645 PackedAttachmentOpsDesc &AttachmentOpsArray::operator[](PackedAttachmentIndex index)
2646 {
2647 return mOps[index.get()];
2648 }
2649
initWithLoadStore(PackedAttachmentIndex index,ImageLayout initialLayout,ImageLayout finalLayout)2650 void AttachmentOpsArray::initWithLoadStore(PackedAttachmentIndex index,
2651 ImageLayout initialLayout,
2652 ImageLayout finalLayout)
2653 {
2654 setLayouts(index, initialLayout, finalLayout);
2655 setOps(index, VK_ATTACHMENT_LOAD_OP_LOAD, RenderPassStoreOp::Store);
2656 setStencilOps(index, VK_ATTACHMENT_LOAD_OP_LOAD, RenderPassStoreOp::Store);
2657 }
2658
setLayouts(PackedAttachmentIndex index,ImageLayout initialLayout,ImageLayout finalLayout)2659 void AttachmentOpsArray::setLayouts(PackedAttachmentIndex index,
2660 ImageLayout initialLayout,
2661 ImageLayout finalLayout)
2662 {
2663 PackedAttachmentOpsDesc &ops = mOps[index.get()];
2664 SetBitField(ops.initialLayout, initialLayout);
2665 SetBitField(ops.finalLayout, finalLayout);
2666 }
2667
setOps(PackedAttachmentIndex index,VkAttachmentLoadOp loadOp,RenderPassStoreOp storeOp)2668 void AttachmentOpsArray::setOps(PackedAttachmentIndex index,
2669 VkAttachmentLoadOp loadOp,
2670 RenderPassStoreOp storeOp)
2671 {
2672 PackedAttachmentOpsDesc &ops = mOps[index.get()];
2673 SetBitField(ops.loadOp, loadOp);
2674 SetBitField(ops.storeOp, storeOp);
2675 ops.isInvalidated = false;
2676 }
2677
setStencilOps(PackedAttachmentIndex index,VkAttachmentLoadOp loadOp,RenderPassStoreOp storeOp)2678 void AttachmentOpsArray::setStencilOps(PackedAttachmentIndex index,
2679 VkAttachmentLoadOp loadOp,
2680 RenderPassStoreOp storeOp)
2681 {
2682 PackedAttachmentOpsDesc &ops = mOps[index.get()];
2683 SetBitField(ops.stencilLoadOp, loadOp);
2684 SetBitField(ops.stencilStoreOp, storeOp);
2685 ops.isStencilInvalidated = false;
2686 }
2687
setClearOp(PackedAttachmentIndex index)2688 void AttachmentOpsArray::setClearOp(PackedAttachmentIndex index)
2689 {
2690 PackedAttachmentOpsDesc &ops = mOps[index.get()];
2691 SetBitField(ops.loadOp, VK_ATTACHMENT_LOAD_OP_CLEAR);
2692 }
2693
setClearStencilOp(PackedAttachmentIndex index)2694 void AttachmentOpsArray::setClearStencilOp(PackedAttachmentIndex index)
2695 {
2696 PackedAttachmentOpsDesc &ops = mOps[index.get()];
2697 SetBitField(ops.stencilLoadOp, VK_ATTACHMENT_LOAD_OP_CLEAR);
2698 }
2699
hash() const2700 size_t AttachmentOpsArray::hash() const
2701 {
2702 return angle::ComputeGenericHash(mOps);
2703 }
2704
operator ==(const AttachmentOpsArray & lhs,const AttachmentOpsArray & rhs)2705 bool operator==(const AttachmentOpsArray &lhs, const AttachmentOpsArray &rhs)
2706 {
2707 return (memcmp(&lhs, &rhs, sizeof(AttachmentOpsArray)) == 0);
2708 }
2709
2710 // DescriptorSetLayoutDesc implementation.
DescriptorSetLayoutDesc()2711 DescriptorSetLayoutDesc::DescriptorSetLayoutDesc() : mPackedDescriptorSetLayout{} {}
2712
2713 DescriptorSetLayoutDesc::~DescriptorSetLayoutDesc() = default;
2714
2715 DescriptorSetLayoutDesc::DescriptorSetLayoutDesc(const DescriptorSetLayoutDesc &other) = default;
2716
2717 DescriptorSetLayoutDesc &DescriptorSetLayoutDesc::operator=(const DescriptorSetLayoutDesc &other) =
2718 default;
2719
hash() const2720 size_t DescriptorSetLayoutDesc::hash() const
2721 {
2722 return angle::ComputeGenericHash(mPackedDescriptorSetLayout);
2723 }
2724
operator ==(const DescriptorSetLayoutDesc & other) const2725 bool DescriptorSetLayoutDesc::operator==(const DescriptorSetLayoutDesc &other) const
2726 {
2727 return (memcmp(&mPackedDescriptorSetLayout, &other.mPackedDescriptorSetLayout,
2728 sizeof(mPackedDescriptorSetLayout)) == 0);
2729 }
2730
update(uint32_t bindingIndex,VkDescriptorType type,uint32_t count,VkShaderStageFlags stages,const Sampler * immutableSampler)2731 void DescriptorSetLayoutDesc::update(uint32_t bindingIndex,
2732 VkDescriptorType type,
2733 uint32_t count,
2734 VkShaderStageFlags stages,
2735 const Sampler *immutableSampler)
2736 {
2737 ASSERT(static_cast<size_t>(type) < std::numeric_limits<uint16_t>::max());
2738 ASSERT(count < std::numeric_limits<uint16_t>::max());
2739
2740 PackedDescriptorSetBinding &packedBinding = mPackedDescriptorSetLayout[bindingIndex];
2741
2742 SetBitField(packedBinding.type, type);
2743 SetBitField(packedBinding.count, count);
2744 SetBitField(packedBinding.stages, stages);
2745 packedBinding.immutableSampler = VK_NULL_HANDLE;
2746 packedBinding.pad = 0;
2747
2748 if (immutableSampler)
2749 {
2750 ASSERT(count == 1);
2751 packedBinding.immutableSampler = immutableSampler->getHandle();
2752 }
2753 }
2754
unpackBindings(DescriptorSetLayoutBindingVector * bindings,std::vector<VkSampler> * immutableSamplers) const2755 void DescriptorSetLayoutDesc::unpackBindings(DescriptorSetLayoutBindingVector *bindings,
2756 std::vector<VkSampler> *immutableSamplers) const
2757 {
2758 for (uint32_t bindingIndex = 0; bindingIndex < kMaxDescriptorSetLayoutBindings; ++bindingIndex)
2759 {
2760 const PackedDescriptorSetBinding &packedBinding = mPackedDescriptorSetLayout[bindingIndex];
2761 if (packedBinding.count == 0)
2762 continue;
2763
2764 VkDescriptorSetLayoutBinding binding = {};
2765 binding.binding = bindingIndex;
2766 binding.descriptorCount = packedBinding.count;
2767 binding.descriptorType = static_cast<VkDescriptorType>(packedBinding.type);
2768 binding.stageFlags = static_cast<VkShaderStageFlags>(packedBinding.stages);
2769 if (packedBinding.immutableSampler != VK_NULL_HANDLE)
2770 {
2771 ASSERT(packedBinding.count == 1);
2772 immutableSamplers->push_back(packedBinding.immutableSampler);
2773 binding.pImmutableSamplers = reinterpret_cast<const VkSampler *>(angle::DirtyPointer);
2774 }
2775
2776 bindings->push_back(binding);
2777 }
2778 if (!immutableSamplers->empty())
2779 {
2780 // Patch up pImmutableSampler addresses now that the vector is stable
2781 int immutableIndex = 0;
2782 for (VkDescriptorSetLayoutBinding &binding : *bindings)
2783 {
2784 if (binding.pImmutableSamplers)
2785 {
2786 binding.pImmutableSamplers = &(*immutableSamplers)[immutableIndex];
2787 immutableIndex++;
2788 }
2789 }
2790 }
2791 }
2792
2793 // PipelineLayoutDesc implementation.
PipelineLayoutDesc()2794 PipelineLayoutDesc::PipelineLayoutDesc() : mDescriptorSetLayouts{}, mPushConstantRanges{} {}
2795
2796 PipelineLayoutDesc::~PipelineLayoutDesc() = default;
2797
2798 PipelineLayoutDesc::PipelineLayoutDesc(const PipelineLayoutDesc &other) = default;
2799
operator =(const PipelineLayoutDesc & rhs)2800 PipelineLayoutDesc &PipelineLayoutDesc::operator=(const PipelineLayoutDesc &rhs)
2801 {
2802 mDescriptorSetLayouts = rhs.mDescriptorSetLayouts;
2803 mPushConstantRanges = rhs.mPushConstantRanges;
2804 return *this;
2805 }
2806
hash() const2807 size_t PipelineLayoutDesc::hash() const
2808 {
2809 return angle::ComputeGenericHash(*this);
2810 }
2811
operator ==(const PipelineLayoutDesc & other) const2812 bool PipelineLayoutDesc::operator==(const PipelineLayoutDesc &other) const
2813 {
2814 return memcmp(this, &other, sizeof(PipelineLayoutDesc)) == 0;
2815 }
2816
updateDescriptorSetLayout(DescriptorSetIndex setIndex,const DescriptorSetLayoutDesc & desc)2817 void PipelineLayoutDesc::updateDescriptorSetLayout(DescriptorSetIndex setIndex,
2818 const DescriptorSetLayoutDesc &desc)
2819 {
2820 mDescriptorSetLayouts[setIndex] = desc;
2821 }
2822
updatePushConstantRange(gl::ShaderType shaderType,uint32_t offset,uint32_t size)2823 void PipelineLayoutDesc::updatePushConstantRange(gl::ShaderType shaderType,
2824 uint32_t offset,
2825 uint32_t size)
2826 {
2827 ASSERT(shaderType == gl::ShaderType::Vertex || shaderType == gl::ShaderType::Fragment ||
2828 shaderType == gl::ShaderType::Geometry || shaderType == gl::ShaderType::Compute);
2829 PackedPushConstantRange &packed = mPushConstantRanges[shaderType];
2830 packed.offset = offset;
2831 packed.size = size;
2832 }
2833
getPushConstantRanges() const2834 const PushConstantRangeArray<PackedPushConstantRange> &PipelineLayoutDesc::getPushConstantRanges()
2835 const
2836 {
2837 return mPushConstantRanges;
2838 }
2839
2840 // PipelineHelper implementation.
2841 PipelineHelper::PipelineHelper() = default;
2842
2843 PipelineHelper::~PipelineHelper() = default;
2844
destroy(VkDevice device)2845 void PipelineHelper::destroy(VkDevice device)
2846 {
2847 mPipeline.destroy(device);
2848 }
2849
addTransition(GraphicsPipelineTransitionBits bits,const GraphicsPipelineDesc * desc,PipelineHelper * pipeline)2850 void PipelineHelper::addTransition(GraphicsPipelineTransitionBits bits,
2851 const GraphicsPipelineDesc *desc,
2852 PipelineHelper *pipeline)
2853 {
2854 mTransitions.emplace_back(bits, desc, pipeline);
2855 }
2856
TextureDescriptorDesc()2857 TextureDescriptorDesc::TextureDescriptorDesc() : mMaxIndex(0)
2858 {
2859 mSerials.fill({kInvalidImageOrBufferViewSubresourceSerial, kInvalidSamplerSerial});
2860 }
2861
2862 TextureDescriptorDesc::~TextureDescriptorDesc() = default;
2863 TextureDescriptorDesc::TextureDescriptorDesc(const TextureDescriptorDesc &other) = default;
2864 TextureDescriptorDesc &TextureDescriptorDesc::operator=(const TextureDescriptorDesc &other) =
2865 default;
2866
update(size_t index,ImageOrBufferViewSubresourceSerial viewSerial,SamplerSerial samplerSerial)2867 void TextureDescriptorDesc::update(size_t index,
2868 ImageOrBufferViewSubresourceSerial viewSerial,
2869 SamplerSerial samplerSerial)
2870 {
2871 if (index >= mMaxIndex)
2872 {
2873 mMaxIndex = static_cast<uint32_t>(index + 1);
2874 }
2875
2876 mSerials[index].view = viewSerial;
2877 mSerials[index].sampler = samplerSerial;
2878 }
2879
hash() const2880 size_t TextureDescriptorDesc::hash() const
2881 {
2882 return angle::ComputeGenericHash(&mSerials, sizeof(TexUnitSerials) * mMaxIndex);
2883 }
2884
reset()2885 void TextureDescriptorDesc::reset()
2886 {
2887 memset(mSerials.data(), 0, sizeof(mSerials[0]) * mMaxIndex);
2888 mMaxIndex = 0;
2889 }
2890
operator ==(const TextureDescriptorDesc & other) const2891 bool TextureDescriptorDesc::operator==(const TextureDescriptorDesc &other) const
2892 {
2893 if (mMaxIndex != other.mMaxIndex)
2894 return false;
2895
2896 if (mMaxIndex == 0)
2897 return true;
2898
2899 return memcmp(mSerials.data(), other.mSerials.data(), sizeof(TexUnitSerials) * mMaxIndex) == 0;
2900 }
2901
2902 // UniformsAndXfbDescriptorDesc implementation.
UniformsAndXfbDescriptorDesc()2903 UniformsAndXfbDescriptorDesc::UniformsAndXfbDescriptorDesc()
2904 {
2905 reset();
2906 }
2907
2908 UniformsAndXfbDescriptorDesc::~UniformsAndXfbDescriptorDesc() = default;
2909 UniformsAndXfbDescriptorDesc::UniformsAndXfbDescriptorDesc(
2910 const UniformsAndXfbDescriptorDesc &other) = default;
2911 UniformsAndXfbDescriptorDesc &UniformsAndXfbDescriptorDesc::operator=(
2912 const UniformsAndXfbDescriptorDesc &other) = default;
2913
hash() const2914 size_t UniformsAndXfbDescriptorDesc::hash() const
2915 {
2916 ASSERT(mBufferCount > 0);
2917
2918 return angle::ComputeGenericHash(&mBufferSerials, sizeof(mBufferSerials[0]) * mBufferCount) ^
2919 angle::ComputeGenericHash(
2920 &mXfbBufferOffsets,
2921 sizeof(mXfbBufferOffsets[0]) * (mBufferCount - kDefaultUniformBufferCount));
2922 }
2923
reset()2924 void UniformsAndXfbDescriptorDesc::reset()
2925 {
2926 mBufferCount = 0;
2927 memset(&mBufferSerials, 0, sizeof(mBufferSerials));
2928 memset(&mXfbBufferOffsets, 0, sizeof(mXfbBufferOffsets));
2929 }
2930
operator ==(const UniformsAndXfbDescriptorDesc & other) const2931 bool UniformsAndXfbDescriptorDesc::operator==(const UniformsAndXfbDescriptorDesc &other) const
2932 {
2933 if (mBufferCount != other.mBufferCount)
2934 {
2935 return false;
2936 }
2937
2938 ASSERT(mBufferCount > 0);
2939
2940 return memcmp(&mBufferSerials, &other.mBufferSerials,
2941 sizeof(mBufferSerials[0]) * mBufferCount) == 0 &&
2942 memcmp(&mXfbBufferOffsets, &other.mXfbBufferOffsets,
2943 sizeof(mXfbBufferOffsets[0]) * (mBufferCount - kDefaultUniformBufferCount)) == 0;
2944 }
2945
2946 // ShaderBuffersDescriptorDesc implementation.
ShaderBuffersDescriptorDesc()2947 ShaderBuffersDescriptorDesc::ShaderBuffersDescriptorDesc()
2948 {
2949 reset();
2950 }
2951
2952 ShaderBuffersDescriptorDesc::~ShaderBuffersDescriptorDesc() = default;
2953
2954 ShaderBuffersDescriptorDesc::ShaderBuffersDescriptorDesc(const ShaderBuffersDescriptorDesc &other) =
2955 default;
2956
2957 ShaderBuffersDescriptorDesc &ShaderBuffersDescriptorDesc::operator=(
2958 const ShaderBuffersDescriptorDesc &other) = default;
2959
hash() const2960 size_t ShaderBuffersDescriptorDesc::hash() const
2961 {
2962 return angle::ComputeGenericHash(mPayload.data(), sizeof(mPayload[0]) * mPayload.size());
2963 }
2964
reset()2965 void ShaderBuffersDescriptorDesc::reset()
2966 {
2967 mPayload.clear();
2968 }
2969
operator ==(const ShaderBuffersDescriptorDesc & other) const2970 bool ShaderBuffersDescriptorDesc::operator==(const ShaderBuffersDescriptorDesc &other) const
2971 {
2972 return mPayload == other.mPayload;
2973 }
2974
2975 // FramebufferDesc implementation.
2976
FramebufferDesc()2977 FramebufferDesc::FramebufferDesc()
2978 {
2979 reset();
2980 }
2981
2982 FramebufferDesc::~FramebufferDesc() = default;
2983 FramebufferDesc::FramebufferDesc(const FramebufferDesc &other) = default;
2984 FramebufferDesc &FramebufferDesc::operator=(const FramebufferDesc &other) = default;
2985
update(uint32_t index,ImageOrBufferViewSubresourceSerial serial)2986 void FramebufferDesc::update(uint32_t index, ImageOrBufferViewSubresourceSerial serial)
2987 {
2988 static_assert(kMaxFramebufferAttachments + 1 < std::numeric_limits<uint8_t>::max(),
2989 "mMaxIndex size is too small");
2990 ASSERT(index < kMaxFramebufferAttachments);
2991 mSerials[index] = serial;
2992 if (serial.viewSerial.valid())
2993 {
2994 SetBitField(mMaxIndex, std::max(mMaxIndex, static_cast<uint16_t>(index + 1)));
2995 }
2996 }
2997
updateColor(uint32_t index,ImageOrBufferViewSubresourceSerial serial)2998 void FramebufferDesc::updateColor(uint32_t index, ImageOrBufferViewSubresourceSerial serial)
2999 {
3000 update(kFramebufferDescColorIndexOffset + index, serial);
3001 }
3002
updateColorResolve(uint32_t index,ImageOrBufferViewSubresourceSerial serial)3003 void FramebufferDesc::updateColorResolve(uint32_t index, ImageOrBufferViewSubresourceSerial serial)
3004 {
3005 update(kFramebufferDescColorResolveIndexOffset + index, serial);
3006 }
3007
updateUnresolveMask(FramebufferNonResolveAttachmentMask unresolveMask)3008 void FramebufferDesc::updateUnresolveMask(FramebufferNonResolveAttachmentMask unresolveMask)
3009 {
3010 SetBitField(mUnresolveAttachmentMask, unresolveMask.bits());
3011 }
3012
updateDepthStencil(ImageOrBufferViewSubresourceSerial serial)3013 void FramebufferDesc::updateDepthStencil(ImageOrBufferViewSubresourceSerial serial)
3014 {
3015 update(kFramebufferDescDepthStencilIndex, serial);
3016 }
3017
updateDepthStencilResolve(ImageOrBufferViewSubresourceSerial serial)3018 void FramebufferDesc::updateDepthStencilResolve(ImageOrBufferViewSubresourceSerial serial)
3019 {
3020 update(kFramebufferDescDepthStencilResolveIndexOffset, serial);
3021 }
3022
hash() const3023 size_t FramebufferDesc::hash() const
3024 {
3025 return angle::ComputeGenericHash(&mSerials, sizeof(mSerials[0]) * mMaxIndex) ^
3026 mHasFramebufferFetch << 26 ^ mIsRenderToTexture << 25 ^ mLayerCount << 16 ^
3027 mUnresolveAttachmentMask;
3028 }
3029
reset()3030 void FramebufferDesc::reset()
3031 {
3032 mMaxIndex = 0;
3033 mHasFramebufferFetch = false;
3034 mLayerCount = 0;
3035 mSrgbWriteControlMode = 0;
3036 mUnresolveAttachmentMask = 0;
3037 mIsRenderToTexture = 0;
3038 memset(&mSerials, 0, sizeof(mSerials));
3039 }
3040
operator ==(const FramebufferDesc & other) const3041 bool FramebufferDesc::operator==(const FramebufferDesc &other) const
3042 {
3043 if (mMaxIndex != other.mMaxIndex || mLayerCount != other.mLayerCount ||
3044 mUnresolveAttachmentMask != other.mUnresolveAttachmentMask ||
3045 mHasFramebufferFetch != other.mHasFramebufferFetch ||
3046 mSrgbWriteControlMode != other.mSrgbWriteControlMode ||
3047 mIsRenderToTexture != other.mIsRenderToTexture)
3048 {
3049 return false;
3050 }
3051
3052 size_t validRegionSize = sizeof(mSerials[0]) * mMaxIndex;
3053 return memcmp(&mSerials, &other.mSerials, validRegionSize) == 0;
3054 }
3055
attachmentCount() const3056 uint32_t FramebufferDesc::attachmentCount() const
3057 {
3058 uint32_t count = 0;
3059 for (const ImageOrBufferViewSubresourceSerial &serial : mSerials)
3060 {
3061 if (serial.viewSerial.valid())
3062 {
3063 count++;
3064 }
3065 }
3066 return count;
3067 }
3068
getUnresolveAttachmentMask() const3069 FramebufferNonResolveAttachmentMask FramebufferDesc::getUnresolveAttachmentMask() const
3070 {
3071 return FramebufferNonResolveAttachmentMask(mUnresolveAttachmentMask);
3072 }
3073
updateLayerCount(uint32_t layerCount)3074 void FramebufferDesc::updateLayerCount(uint32_t layerCount)
3075 {
3076 SetBitField(mLayerCount, layerCount);
3077 }
3078
updateFramebufferFetchMode(bool hasFramebufferFetch)3079 void FramebufferDesc::updateFramebufferFetchMode(bool hasFramebufferFetch)
3080 {
3081 SetBitField(mHasFramebufferFetch, hasFramebufferFetch);
3082 }
3083
updateRenderToTexture(bool isRenderToTexture)3084 void FramebufferDesc::updateRenderToTexture(bool isRenderToTexture)
3085 {
3086 SetBitField(mIsRenderToTexture, isRenderToTexture);
3087 }
3088
3089 // SamplerDesc implementation.
SamplerDesc()3090 SamplerDesc::SamplerDesc()
3091 {
3092 reset();
3093 }
3094
3095 SamplerDesc::~SamplerDesc() = default;
3096
3097 SamplerDesc::SamplerDesc(const SamplerDesc &other) = default;
3098
3099 SamplerDesc &SamplerDesc::operator=(const SamplerDesc &rhs) = default;
3100
SamplerDesc(ContextVk * contextVk,const gl::SamplerState & samplerState,bool stencilMode,uint64_t externalFormat,angle::FormatID formatID)3101 SamplerDesc::SamplerDesc(ContextVk *contextVk,
3102 const gl::SamplerState &samplerState,
3103 bool stencilMode,
3104 uint64_t externalFormat,
3105 angle::FormatID formatID)
3106 {
3107 update(contextVk, samplerState, stencilMode, externalFormat, formatID);
3108 }
3109
reset()3110 void SamplerDesc::reset()
3111 {
3112 mMipLodBias = 0.0f;
3113 mMaxAnisotropy = 0.0f;
3114 mMinLod = 0.0f;
3115 mMaxLod = 0.0f;
3116 mExternalOrVkFormat = 0;
3117 mMagFilter = 0;
3118 mMinFilter = 0;
3119 mMipmapMode = 0;
3120 mAddressModeU = 0;
3121 mAddressModeV = 0;
3122 mAddressModeW = 0;
3123 mCompareEnabled = 0;
3124 mCompareOp = 0;
3125 mIsExternalFormat = 0;
3126 mPadding = 0;
3127 mBorderColorType = 0;
3128 mBorderColor.red = 0.0f;
3129 mBorderColor.green = 0.0f;
3130 mBorderColor.blue = 0.0f;
3131 mBorderColor.alpha = 0.0f;
3132 mReserved = 0;
3133 }
3134
update(ContextVk * contextVk,const gl::SamplerState & samplerState,bool stencilMode,uint64_t externalFormat,angle::FormatID formatID)3135 void SamplerDesc::update(ContextVk *contextVk,
3136 const gl::SamplerState &samplerState,
3137 bool stencilMode,
3138 uint64_t externalFormat,
3139 angle::FormatID formatID)
3140 {
3141 const angle::FeaturesVk &featuresVk = contextVk->getFeatures();
3142 mMipLodBias = 0.0f;
3143 for (size_t lodOffsetFeatureIdx = 0;
3144 lodOffsetFeatureIdx < featuresVk.forceTextureLODOffset.size(); lodOffsetFeatureIdx++)
3145 {
3146 if (featuresVk.forceTextureLODOffset[lodOffsetFeatureIdx].enabled)
3147 {
3148 // Make sure only one forceTextureLODOffset feature is set.
3149 ASSERT(mMipLodBias == 0.0f);
3150 mMipLodBias = static_cast<float>(lodOffsetFeatureIdx + 1);
3151 }
3152 }
3153
3154 mMaxAnisotropy = samplerState.getMaxAnisotropy();
3155 mMinLod = samplerState.getMinLod();
3156 mMaxLod = samplerState.getMaxLod();
3157
3158 // GL has no notion of external format, this must be provided from metadata from the image
3159 const vk::Format &vkFormat = contextVk->getRenderer()->getFormat(formatID);
3160 mIsExternalFormat = (externalFormat != 0) ? 1 : 0;
3161 mExternalOrVkFormat = (externalFormat != 0)
3162 ? externalFormat
3163 : (vkFormat.intendedFormat().isYUV)
3164 ? static_cast<uint64_t>(vkFormat.actualImageVkFormat())
3165 : 0;
3166
3167 bool compareEnable = samplerState.getCompareMode() == GL_COMPARE_REF_TO_TEXTURE;
3168 VkCompareOp compareOp = gl_vk::GetCompareOp(samplerState.getCompareFunc());
3169 // When sampling from stencil, deqp tests expect texture compare to have no effect
3170 // dEQP - GLES31.functional.stencil_texturing.misc.compare_mode_effect
3171 // states: NOTE: Texture compare mode has no effect when reading stencil values.
3172 if (stencilMode)
3173 {
3174 compareEnable = VK_FALSE;
3175 compareOp = VK_COMPARE_OP_ALWAYS;
3176 }
3177
3178 GLenum magFilter = samplerState.getMagFilter();
3179 GLenum minFilter = samplerState.getMinFilter();
3180 if (featuresVk.forceNearestFiltering.enabled)
3181 {
3182 magFilter = gl::ConvertToNearestFilterMode(magFilter);
3183 minFilter = gl::ConvertToNearestFilterMode(minFilter);
3184 }
3185 if (featuresVk.forceNearestMipFiltering.enabled)
3186 {
3187 minFilter = gl::ConvertToNearestMipFilterMode(minFilter);
3188 }
3189
3190 SetBitField(mMagFilter, gl_vk::GetFilter(magFilter));
3191 SetBitField(mMinFilter, gl_vk::GetFilter(minFilter));
3192 SetBitField(mMipmapMode, gl_vk::GetSamplerMipmapMode(samplerState.getMinFilter()));
3193 SetBitField(mAddressModeU, gl_vk::GetSamplerAddressMode(samplerState.getWrapS()));
3194 SetBitField(mAddressModeV, gl_vk::GetSamplerAddressMode(samplerState.getWrapT()));
3195 SetBitField(mAddressModeW, gl_vk::GetSamplerAddressMode(samplerState.getWrapR()));
3196 SetBitField(mCompareEnabled, compareEnable);
3197 SetBitField(mCompareOp, compareOp);
3198
3199 if (!gl::IsMipmapFiltered(minFilter))
3200 {
3201 // Per the Vulkan spec, GL_NEAREST and GL_LINEAR do not map directly to Vulkan, so
3202 // they must be emulated (See "Mapping of OpenGL to Vulkan filter modes")
3203 SetBitField(mMipmapMode, VK_SAMPLER_MIPMAP_MODE_NEAREST);
3204 mMinLod = 0.0f;
3205 mMaxLod = 0.25f;
3206 }
3207
3208 mPadding = 0;
3209
3210 mBorderColorType =
3211 (samplerState.getBorderColor().type == angle::ColorGeneric::Type::Float) ? 0 : 1;
3212
3213 mBorderColor = samplerState.getBorderColor().colorF;
3214 if (vkFormat.intendedFormatID != angle::FormatID::NONE)
3215 {
3216 LoadTextureBorderFunctionInfo loadFunction = vkFormat.textureBorderLoadFunctions();
3217 loadFunction.loadFunction(mBorderColor);
3218 }
3219
3220 mReserved = 0;
3221 }
3222
init(ContextVk * contextVk,Sampler * sampler) const3223 angle::Result SamplerDesc::init(ContextVk *contextVk, Sampler *sampler) const
3224 {
3225 const gl::Extensions &extensions = contextVk->getExtensions();
3226
3227 bool anisotropyEnable = extensions.textureFilterAnisotropic && mMaxAnisotropy > 1.0f;
3228
3229 VkSamplerCreateInfo createInfo = {};
3230 createInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
3231 createInfo.flags = 0;
3232 createInfo.magFilter = static_cast<VkFilter>(mMagFilter);
3233 createInfo.minFilter = static_cast<VkFilter>(mMinFilter);
3234 createInfo.mipmapMode = static_cast<VkSamplerMipmapMode>(mMipmapMode);
3235 createInfo.addressModeU = static_cast<VkSamplerAddressMode>(mAddressModeU);
3236 createInfo.addressModeV = static_cast<VkSamplerAddressMode>(mAddressModeV);
3237 createInfo.addressModeW = static_cast<VkSamplerAddressMode>(mAddressModeW);
3238 createInfo.mipLodBias = mMipLodBias;
3239 createInfo.anisotropyEnable = anisotropyEnable;
3240 createInfo.maxAnisotropy = mMaxAnisotropy;
3241 createInfo.compareEnable = mCompareEnabled ? VK_TRUE : VK_FALSE;
3242 createInfo.compareOp = static_cast<VkCompareOp>(mCompareOp);
3243 createInfo.minLod = mMinLod;
3244 createInfo.maxLod = mMaxLod;
3245 createInfo.borderColor = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK;
3246 createInfo.unnormalizedCoordinates = VK_FALSE;
3247
3248 // Note: because we don't detect changes to this hint (no dirty bit), if a sampler is created
3249 // with the hint enabled, and then the hint gets disabled, the next render will do so with the
3250 // hint enabled.
3251 VkSamplerFilteringPrecisionGOOGLE filteringInfo = {};
3252 GLenum hint = contextVk->getState().getTextureFilteringHint();
3253 if (hint == GL_NICEST)
3254 {
3255 ASSERT(extensions.textureFilteringCHROMIUM);
3256 filteringInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_FILTERING_PRECISION_GOOGLE;
3257 filteringInfo.samplerFilteringPrecisionMode =
3258 VK_SAMPLER_FILTERING_PRECISION_MODE_HIGH_GOOGLE;
3259 AddToPNextChain(&createInfo, &filteringInfo);
3260 }
3261
3262 VkSamplerYcbcrConversionInfo yuvConversionInfo = {};
3263 if (mExternalOrVkFormat)
3264 {
3265 ASSERT((contextVk->getRenderer()->getFeatures().supportsYUVSamplerConversion.enabled));
3266 yuvConversionInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO;
3267 yuvConversionInfo.pNext = nullptr;
3268 yuvConversionInfo.conversion =
3269 contextVk->getRenderer()->getYuvConversionCache().getSamplerYcbcrConversion(
3270 mExternalOrVkFormat, (mIsExternalFormat == 1));
3271 AddToPNextChain(&createInfo, &yuvConversionInfo);
3272
3273 // Vulkan spec requires these settings:
3274 createInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
3275 createInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
3276 createInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
3277 createInfo.anisotropyEnable = VK_FALSE;
3278 createInfo.unnormalizedCoordinates = VK_FALSE;
3279 // VUID-VkSamplerCreateInfo-minFilter VkCreateSampler:
3280 // VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT
3281 // specifies that the format can have different chroma, min, and mag filters. However,
3282 // VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT is
3283 // not supported for VkSamplerYcbcrConversionCreateInfo.format = VK_FORMAT_UNDEFINED so
3284 // minFilter/magFilter needs to be equal to chromaFilter.
3285 // HardwareBufferImageSiblingVkAndroid() forces VK_FILTER_NEAREST, so force
3286 // VK_FILTER_NEAREST here too.
3287 createInfo.magFilter = VK_FILTER_NEAREST;
3288 createInfo.minFilter = VK_FILTER_NEAREST;
3289 }
3290
3291 VkSamplerCustomBorderColorCreateInfoEXT customBorderColorInfo = {};
3292 if (createInfo.addressModeU == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER ||
3293 createInfo.addressModeV == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER ||
3294 createInfo.addressModeW == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER)
3295 {
3296 ASSERT((contextVk->getRenderer()->getFeatures().supportsCustomBorderColorEXT.enabled));
3297 customBorderColorInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT;
3298
3299 customBorderColorInfo.customBorderColor.float32[0] = mBorderColor.red;
3300 customBorderColorInfo.customBorderColor.float32[1] = mBorderColor.green;
3301 customBorderColorInfo.customBorderColor.float32[2] = mBorderColor.blue;
3302 customBorderColorInfo.customBorderColor.float32[3] = mBorderColor.alpha;
3303
3304 if (mBorderColorType == static_cast<uint32_t>(angle::ColorGeneric::Type::Float))
3305 {
3306 createInfo.borderColor = VK_BORDER_COLOR_FLOAT_CUSTOM_EXT;
3307 }
3308 else
3309 {
3310 createInfo.borderColor = VK_BORDER_COLOR_INT_CUSTOM_EXT;
3311 }
3312
3313 vk::AddToPNextChain(&createInfo, &customBorderColorInfo);
3314 }
3315 ANGLE_VK_TRY(contextVk, sampler->init(contextVk->getDevice(), createInfo));
3316
3317 return angle::Result::Continue;
3318 }
3319
hash() const3320 size_t SamplerDesc::hash() const
3321 {
3322 return angle::ComputeGenericHash(*this);
3323 }
3324
operator ==(const SamplerDesc & other) const3325 bool SamplerDesc::operator==(const SamplerDesc &other) const
3326 {
3327 return (memcmp(this, &other, sizeof(SamplerDesc)) == 0);
3328 }
3329
3330 // SamplerHelper implementation.
SamplerHelper(ContextVk * contextVk)3331 SamplerHelper::SamplerHelper(ContextVk *contextVk)
3332 : mSamplerSerial(contextVk->getRenderer()->getResourceSerialFactory().generateSamplerSerial())
3333 {}
3334
~SamplerHelper()3335 SamplerHelper::~SamplerHelper() {}
3336
SamplerHelper(SamplerHelper && samplerHelper)3337 SamplerHelper::SamplerHelper(SamplerHelper &&samplerHelper)
3338 {
3339 *this = std::move(samplerHelper);
3340 }
3341
operator =(SamplerHelper && rhs)3342 SamplerHelper &SamplerHelper::operator=(SamplerHelper &&rhs)
3343 {
3344 std::swap(mSampler, rhs.mSampler);
3345 std::swap(mSamplerSerial, rhs.mSamplerSerial);
3346 return *this;
3347 }
3348
3349 // RenderPassHelper implementation.
RenderPassHelper()3350 RenderPassHelper::RenderPassHelper() : mPerfCounters{} {}
3351
3352 RenderPassHelper::~RenderPassHelper() = default;
3353
RenderPassHelper(RenderPassHelper && other)3354 RenderPassHelper::RenderPassHelper(RenderPassHelper &&other)
3355 {
3356 *this = std::move(other);
3357 }
3358
operator =(RenderPassHelper && other)3359 RenderPassHelper &RenderPassHelper::operator=(RenderPassHelper &&other)
3360 {
3361 mRenderPass = std::move(other.mRenderPass);
3362 mPerfCounters = std::move(other.mPerfCounters);
3363 return *this;
3364 }
3365
destroy(VkDevice device)3366 void RenderPassHelper::destroy(VkDevice device)
3367 {
3368 mRenderPass.destroy(device);
3369 }
3370
getRenderPass() const3371 const RenderPass &RenderPassHelper::getRenderPass() const
3372 {
3373 return mRenderPass;
3374 }
3375
getRenderPass()3376 RenderPass &RenderPassHelper::getRenderPass()
3377 {
3378 return mRenderPass;
3379 }
3380
getPerfCounters() const3381 const RenderPassPerfCounters &RenderPassHelper::getPerfCounters() const
3382 {
3383 return mPerfCounters;
3384 }
3385
getPerfCounters()3386 RenderPassPerfCounters &RenderPassHelper::getPerfCounters()
3387 {
3388 return mPerfCounters;
3389 }
3390 } // namespace vk
3391
3392 // RenderPassCache implementation.
3393 RenderPassCache::RenderPassCache() = default;
3394
~RenderPassCache()3395 RenderPassCache::~RenderPassCache()
3396 {
3397 ASSERT(mPayload.empty());
3398 }
3399
destroy(RendererVk * rendererVk)3400 void RenderPassCache::destroy(RendererVk *rendererVk)
3401 {
3402 rendererVk->accumulateCacheStats(VulkanCacheType::CompatibleRenderPass,
3403 mCompatibleRenderPassCacheStats);
3404 rendererVk->accumulateCacheStats(VulkanCacheType::RenderPassWithOps,
3405 mRenderPassWithOpsCacheStats);
3406
3407 VkDevice device = rendererVk->getDevice();
3408
3409 for (auto &outerIt : mPayload)
3410 {
3411 for (auto &innerIt : outerIt.second)
3412 {
3413 innerIt.second.destroy(device);
3414 }
3415 }
3416 mPayload.clear();
3417 }
3418
addRenderPass(ContextVk * contextVk,const vk::RenderPassDesc & desc,vk::RenderPass ** renderPassOut)3419 angle::Result RenderPassCache::addRenderPass(ContextVk *contextVk,
3420 const vk::RenderPassDesc &desc,
3421 vk::RenderPass **renderPassOut)
3422 {
3423 // Insert some placeholder attachment ops. Note that render passes with different ops are still
3424 // compatible. The load/store values are not important as they are aren't used for real RPs.
3425 //
3426 // It would be nice to pre-populate the cache in the Renderer so we rarely miss here.
3427 vk::AttachmentOpsArray ops;
3428
3429 vk::PackedAttachmentIndex colorIndexVk(0);
3430 for (uint32_t colorIndexGL = 0; colorIndexGL < desc.colorAttachmentRange(); ++colorIndexGL)
3431 {
3432 if (!desc.isColorAttachmentEnabled(colorIndexGL))
3433 {
3434 continue;
3435 }
3436
3437 ops.initWithLoadStore(colorIndexVk, vk::ImageLayout::ColorAttachment,
3438 vk::ImageLayout::ColorAttachment);
3439 ++colorIndexVk;
3440 }
3441
3442 if (desc.hasDepthStencilAttachment())
3443 {
3444 // This API is only called by getCompatibleRenderPass(). What we need here is to create a
3445 // compatible renderpass with the desc. Vulkan spec says image layout are not counted toward
3446 // render pass compatibility: "Two render passes are compatible if their corresponding
3447 // color, input, resolve, and depth/stencil attachment references are compatible and if they
3448 // are otherwise identical except for: Initial and final image layout in attachment
3449 // descriptions; Image layout in attachment references". We pick the most used layout here
3450 // since it doesn't matter.
3451 vk::ImageLayout imageLayout = vk::ImageLayout::DepthStencilAttachment;
3452 ops.initWithLoadStore(colorIndexVk, imageLayout, imageLayout);
3453 }
3454
3455 return getRenderPassWithOpsImpl(contextVk, desc, ops, false, renderPassOut);
3456 }
3457
getRenderPassWithOps(ContextVk * contextVk,const vk::RenderPassDesc & desc,const vk::AttachmentOpsArray & attachmentOps,vk::RenderPass ** renderPassOut)3458 angle::Result RenderPassCache::getRenderPassWithOps(ContextVk *contextVk,
3459 const vk::RenderPassDesc &desc,
3460 const vk::AttachmentOpsArray &attachmentOps,
3461 vk::RenderPass **renderPassOut)
3462 {
3463 return getRenderPassWithOpsImpl(contextVk, desc, attachmentOps, true, renderPassOut);
3464 }
3465
getRenderPassWithOpsImpl(ContextVk * contextVk,const vk::RenderPassDesc & desc,const vk::AttachmentOpsArray & attachmentOps,bool updatePerfCounters,vk::RenderPass ** renderPassOut)3466 angle::Result RenderPassCache::getRenderPassWithOpsImpl(ContextVk *contextVk,
3467 const vk::RenderPassDesc &desc,
3468 const vk::AttachmentOpsArray &attachmentOps,
3469 bool updatePerfCounters,
3470 vk::RenderPass **renderPassOut)
3471 {
3472 auto outerIt = mPayload.find(desc);
3473 if (outerIt != mPayload.end())
3474 {
3475 InnerCache &innerCache = outerIt->second;
3476
3477 auto innerIt = innerCache.find(attachmentOps);
3478 if (innerIt != innerCache.end())
3479 {
3480 // TODO(jmadill): Could possibly use an MRU cache here.
3481 vk::GetRenderPassAndUpdateCounters(contextVk, updatePerfCounters, &innerIt->second,
3482 renderPassOut);
3483 mRenderPassWithOpsCacheStats.hit();
3484 return angle::Result::Continue;
3485 }
3486 }
3487 else
3488 {
3489 auto emplaceResult = mPayload.emplace(desc, InnerCache());
3490 outerIt = emplaceResult.first;
3491 }
3492
3493 mRenderPassWithOpsCacheStats.miss();
3494 vk::RenderPassHelper newRenderPass;
3495 ANGLE_TRY(vk::InitializeRenderPassFromDesc(contextVk, desc, attachmentOps, &newRenderPass));
3496
3497 InnerCache &innerCache = outerIt->second;
3498 auto insertPos = innerCache.emplace(attachmentOps, std::move(newRenderPass));
3499 vk::GetRenderPassAndUpdateCounters(contextVk, updatePerfCounters, &insertPos.first->second,
3500 renderPassOut);
3501
3502 // TODO(jmadill): Trim cache, and pre-populate with the most common RPs on startup.
3503 return angle::Result::Continue;
3504 }
3505
3506 // GraphicsPipelineCache implementation.
3507 GraphicsPipelineCache::GraphicsPipelineCache() = default;
3508
~GraphicsPipelineCache()3509 GraphicsPipelineCache::~GraphicsPipelineCache()
3510 {
3511 ASSERT(mPayload.empty());
3512 }
3513
destroy(RendererVk * rendererVk)3514 void GraphicsPipelineCache::destroy(RendererVk *rendererVk)
3515 {
3516 accumulateCacheStats(rendererVk);
3517
3518 VkDevice device = rendererVk->getDevice();
3519
3520 for (auto &item : mPayload)
3521 {
3522 vk::PipelineHelper &pipeline = item.second;
3523 pipeline.destroy(device);
3524 }
3525
3526 mPayload.clear();
3527 }
3528
release(ContextVk * context)3529 void GraphicsPipelineCache::release(ContextVk *context)
3530 {
3531 for (auto &item : mPayload)
3532 {
3533 vk::PipelineHelper &pipeline = item.second;
3534 context->addGarbage(&pipeline.getPipeline());
3535 }
3536
3537 mPayload.clear();
3538 }
3539
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,const vk::ShaderModule * tessControlModule,const vk::ShaderModule * tessEvaluationModule,const vk::SpecializationConstants & specConsts,const vk::GraphicsPipelineDesc & desc,const vk::GraphicsPipelineDesc ** descPtrOut,vk::PipelineHelper ** pipelineOut)3540 angle::Result GraphicsPipelineCache::insertPipeline(
3541 ContextVk *contextVk,
3542 const vk::PipelineCache &pipelineCacheVk,
3543 const vk::RenderPass &compatibleRenderPass,
3544 const vk::PipelineLayout &pipelineLayout,
3545 const gl::AttributesMask &activeAttribLocationsMask,
3546 const gl::ComponentTypeMask &programAttribsTypeMask,
3547 const vk::ShaderModule *vertexModule,
3548 const vk::ShaderModule *fragmentModule,
3549 const vk::ShaderModule *geometryModule,
3550 const vk::ShaderModule *tessControlModule,
3551 const vk::ShaderModule *tessEvaluationModule,
3552 const vk::SpecializationConstants &specConsts,
3553 const vk::GraphicsPipelineDesc &desc,
3554 const vk::GraphicsPipelineDesc **descPtrOut,
3555 vk::PipelineHelper **pipelineOut)
3556 {
3557 vk::Pipeline newPipeline;
3558
3559 // This "if" is left here for the benefit of VulkanPipelineCachePerfTest.
3560 if (contextVk != nullptr)
3561 {
3562 contextVk->getRenderer()->onNewGraphicsPipeline();
3563 ANGLE_TRY(desc.initializePipeline(
3564 contextVk, pipelineCacheVk, compatibleRenderPass, pipelineLayout,
3565 activeAttribLocationsMask, programAttribsTypeMask, vertexModule, fragmentModule,
3566 geometryModule, tessControlModule, tessEvaluationModule, specConsts, &newPipeline));
3567 }
3568
3569 // The Serial will be updated outside of this query.
3570 auto insertedItem = mPayload.emplace(desc, std::move(newPipeline));
3571 *descPtrOut = &insertedItem.first->first;
3572 *pipelineOut = &insertedItem.first->second;
3573
3574 return angle::Result::Continue;
3575 }
3576
populate(const vk::GraphicsPipelineDesc & desc,vk::Pipeline && pipeline)3577 void GraphicsPipelineCache::populate(const vk::GraphicsPipelineDesc &desc, vk::Pipeline &&pipeline)
3578 {
3579 auto item = mPayload.find(desc);
3580 if (item != mPayload.end())
3581 {
3582 return;
3583 }
3584
3585 mPayload.emplace(desc, std::move(pipeline));
3586 }
3587
3588 // DescriptorSetLayoutCache implementation.
3589 DescriptorSetLayoutCache::DescriptorSetLayoutCache() = default;
3590
~DescriptorSetLayoutCache()3591 DescriptorSetLayoutCache::~DescriptorSetLayoutCache()
3592 {
3593 ASSERT(mPayload.empty());
3594 }
3595
destroy(RendererVk * rendererVk)3596 void DescriptorSetLayoutCache::destroy(RendererVk *rendererVk)
3597 {
3598 rendererVk->accumulateCacheStats(VulkanCacheType::DescriptorSetLayout, mCacheStats);
3599
3600 VkDevice device = rendererVk->getDevice();
3601
3602 for (auto &item : mPayload)
3603 {
3604 vk::RefCountedDescriptorSetLayout &layout = item.second;
3605 ASSERT(!layout.isReferenced());
3606 layout.get().destroy(device);
3607 }
3608
3609 mPayload.clear();
3610 }
3611
getDescriptorSetLayout(vk::Context * context,const vk::DescriptorSetLayoutDesc & desc,vk::BindingPointer<vk::DescriptorSetLayout> * descriptorSetLayoutOut)3612 angle::Result DescriptorSetLayoutCache::getDescriptorSetLayout(
3613 vk::Context *context,
3614 const vk::DescriptorSetLayoutDesc &desc,
3615 vk::BindingPointer<vk::DescriptorSetLayout> *descriptorSetLayoutOut)
3616 {
3617 auto iter = mPayload.find(desc);
3618 if (iter != mPayload.end())
3619 {
3620 vk::RefCountedDescriptorSetLayout &layout = iter->second;
3621 descriptorSetLayoutOut->set(&layout);
3622 mCacheStats.hit();
3623 return angle::Result::Continue;
3624 }
3625
3626 mCacheStats.miss();
3627 // We must unpack the descriptor set layout description.
3628 vk::DescriptorSetLayoutBindingVector bindingVector;
3629 std::vector<VkSampler> immutableSamplers;
3630 desc.unpackBindings(&bindingVector, &immutableSamplers);
3631
3632 VkDescriptorSetLayoutCreateInfo createInfo = {};
3633 createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
3634 createInfo.flags = 0;
3635 createInfo.bindingCount = static_cast<uint32_t>(bindingVector.size());
3636 createInfo.pBindings = bindingVector.data();
3637
3638 vk::DescriptorSetLayout newLayout;
3639 ANGLE_VK_TRY(context, newLayout.init(context->getDevice(), createInfo));
3640
3641 auto insertedItem =
3642 mPayload.emplace(desc, vk::RefCountedDescriptorSetLayout(std::move(newLayout)));
3643 vk::RefCountedDescriptorSetLayout &insertedLayout = insertedItem.first->second;
3644 descriptorSetLayoutOut->set(&insertedLayout);
3645
3646 return angle::Result::Continue;
3647 }
3648
3649 // PipelineLayoutCache implementation.
3650 PipelineLayoutCache::PipelineLayoutCache() = default;
3651
~PipelineLayoutCache()3652 PipelineLayoutCache::~PipelineLayoutCache()
3653 {
3654 ASSERT(mPayload.empty());
3655 }
3656
destroy(RendererVk * rendererVk)3657 void PipelineLayoutCache::destroy(RendererVk *rendererVk)
3658 {
3659 accumulateCacheStats(rendererVk);
3660
3661 VkDevice device = rendererVk->getDevice();
3662
3663 for (auto &item : mPayload)
3664 {
3665 vk::RefCountedPipelineLayout &layout = item.second;
3666 layout.get().destroy(device);
3667 }
3668
3669 mPayload.clear();
3670 }
3671
getPipelineLayout(vk::Context * context,const vk::PipelineLayoutDesc & desc,const vk::DescriptorSetLayoutPointerArray & descriptorSetLayouts,vk::BindingPointer<vk::PipelineLayout> * pipelineLayoutOut)3672 angle::Result PipelineLayoutCache::getPipelineLayout(
3673 vk::Context *context,
3674 const vk::PipelineLayoutDesc &desc,
3675 const vk::DescriptorSetLayoutPointerArray &descriptorSetLayouts,
3676 vk::BindingPointer<vk::PipelineLayout> *pipelineLayoutOut)
3677 {
3678 auto iter = mPayload.find(desc);
3679 if (iter != mPayload.end())
3680 {
3681 vk::RefCountedPipelineLayout &layout = iter->second;
3682 pipelineLayoutOut->set(&layout);
3683 mCacheStats.hit();
3684 return angle::Result::Continue;
3685 }
3686
3687 mCacheStats.miss();
3688 // Note this does not handle gaps in descriptor set layouts gracefully.
3689 angle::FixedVector<VkDescriptorSetLayout, vk::kMaxDescriptorSetLayouts> setLayoutHandles;
3690 for (const vk::BindingPointer<vk::DescriptorSetLayout> &layoutPtr : descriptorSetLayouts)
3691 {
3692 if (layoutPtr.valid())
3693 {
3694 VkDescriptorSetLayout setLayout = layoutPtr.get().getHandle();
3695 if (setLayout != VK_NULL_HANDLE)
3696 {
3697 setLayoutHandles.push_back(setLayout);
3698 }
3699 }
3700 }
3701
3702 const vk::PushConstantRangeArray<vk::PackedPushConstantRange> &descPushConstantRanges =
3703 desc.getPushConstantRanges();
3704
3705 gl::ShaderVector<VkPushConstantRange> pushConstantRanges;
3706
3707 for (const gl::ShaderType shaderType : gl::AllShaderTypes())
3708 {
3709 const vk::PackedPushConstantRange &pushConstantDesc = descPushConstantRanges[shaderType];
3710 if (pushConstantDesc.size > 0)
3711 {
3712 VkPushConstantRange range;
3713 range.stageFlags = gl_vk::kShaderStageMap[shaderType];
3714 range.offset = pushConstantDesc.offset;
3715 range.size = pushConstantDesc.size;
3716
3717 pushConstantRanges.push_back(range);
3718 }
3719 }
3720
3721 // No pipeline layout found. We must create a new one.
3722 VkPipelineLayoutCreateInfo createInfo = {};
3723 createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
3724 createInfo.flags = 0;
3725 createInfo.setLayoutCount = static_cast<uint32_t>(setLayoutHandles.size());
3726 createInfo.pSetLayouts = setLayoutHandles.data();
3727 createInfo.pushConstantRangeCount = static_cast<uint32_t>(pushConstantRanges.size());
3728 createInfo.pPushConstantRanges = pushConstantRanges.data();
3729
3730 vk::PipelineLayout newLayout;
3731 ANGLE_VK_TRY(context, newLayout.init(context->getDevice(), createInfo));
3732
3733 auto insertedItem = mPayload.emplace(desc, vk::RefCountedPipelineLayout(std::move(newLayout)));
3734 vk::RefCountedPipelineLayout &insertedLayout = insertedItem.first->second;
3735 pipelineLayoutOut->set(&insertedLayout);
3736
3737 return angle::Result::Continue;
3738 }
3739
3740 // YuvConversionCache implementation
3741 SamplerYcbcrConversionCache::SamplerYcbcrConversionCache() = default;
3742
~SamplerYcbcrConversionCache()3743 SamplerYcbcrConversionCache::~SamplerYcbcrConversionCache()
3744 {
3745 ASSERT(mExternalFormatPayload.empty() && mVkFormatPayload.empty());
3746 }
3747
destroy(RendererVk * rendererVk)3748 void SamplerYcbcrConversionCache::destroy(RendererVk *rendererVk)
3749 {
3750 rendererVk->accumulateCacheStats(VulkanCacheType::SamplerYcbcrConversion, mCacheStats);
3751
3752 VkDevice device = rendererVk->getDevice();
3753
3754 for (auto &iter : mExternalFormatPayload)
3755 {
3756 vk::RefCountedSamplerYcbcrConversion &yuvSampler = iter.second;
3757 ASSERT(!yuvSampler.isReferenced());
3758 yuvSampler.get().destroy(device);
3759
3760 rendererVk->getActiveHandleCounts().onDeallocate(vk::HandleType::SamplerYcbcrConversion);
3761 }
3762
3763 for (auto &iter : mVkFormatPayload)
3764 {
3765 vk::RefCountedSamplerYcbcrConversion &yuvSampler = iter.second;
3766 ASSERT(!yuvSampler.isReferenced());
3767 yuvSampler.get().destroy(device);
3768
3769 rendererVk->getActiveHandleCounts().onDeallocate(vk::HandleType::SamplerYcbcrConversion);
3770 }
3771
3772 mExternalFormatPayload.clear();
3773 mVkFormatPayload.clear();
3774 }
3775
3776 template <typename T>
getYuvConversionImpl(vk::Context * context,T format,SamplerYcbcrConversionMap<T> * payload,const VkSamplerYcbcrConversionCreateInfo & yuvConversionCreateInfo,vk::BindingPointer<vk::SamplerYcbcrConversion> * yuvConversionOut)3777 angle::Result SamplerYcbcrConversionCache::getYuvConversionImpl(
3778 vk::Context *context,
3779 T format,
3780 SamplerYcbcrConversionMap<T> *payload,
3781 const VkSamplerYcbcrConversionCreateInfo &yuvConversionCreateInfo,
3782 vk::BindingPointer<vk::SamplerYcbcrConversion> *yuvConversionOut)
3783 {
3784 const auto iter = payload->find(format);
3785 if (iter != payload->end())
3786 {
3787 vk::RefCountedSamplerYcbcrConversion &yuvConversion = iter->second;
3788 yuvConversionOut->set(&yuvConversion);
3789 mCacheStats.hit();
3790 return angle::Result::Continue;
3791 }
3792
3793 mCacheStats.miss();
3794 vk::SamplerYcbcrConversion wrappedYuvConversion;
3795 ANGLE_VK_TRY(context, wrappedYuvConversion.init(context->getDevice(), yuvConversionCreateInfo));
3796
3797 auto insertedItem = payload->emplace(
3798 format, vk::RefCountedSamplerYcbcrConversion(std::move(wrappedYuvConversion)));
3799 vk::RefCountedSamplerYcbcrConversion &insertedYuvConversion = insertedItem.first->second;
3800 yuvConversionOut->set(&insertedYuvConversion);
3801
3802 context->getRenderer()->getActiveHandleCounts().onAllocate(
3803 vk::HandleType::SamplerYcbcrConversion);
3804
3805 return angle::Result::Continue;
3806 }
3807
getYuvConversion(vk::Context * context,uint64_t externalOrVkFormat,bool isExternalFormat,const VkSamplerYcbcrConversionCreateInfo & yuvConversionCreateInfo,vk::BindingPointer<vk::SamplerYcbcrConversion> * yuvConversionOut)3808 angle::Result SamplerYcbcrConversionCache::getYuvConversion(
3809 vk::Context *context,
3810 uint64_t externalOrVkFormat,
3811 bool isExternalFormat,
3812 const VkSamplerYcbcrConversionCreateInfo &yuvConversionCreateInfo,
3813 vk::BindingPointer<vk::SamplerYcbcrConversion> *yuvConversionOut)
3814 {
3815 if (isExternalFormat)
3816 {
3817 return getYuvConversionImpl(context, externalOrVkFormat, &mExternalFormatPayload,
3818 yuvConversionCreateInfo, yuvConversionOut);
3819 }
3820 else
3821 {
3822 return getYuvConversionImpl(context, static_cast<VkFormat>(externalOrVkFormat),
3823 &mVkFormatPayload, yuvConversionCreateInfo, yuvConversionOut);
3824 }
3825 }
3826
3827 template <typename T>
getSamplerYcbcrConversionImpl(T format,const SamplerYcbcrConversionMap<T> & payload) const3828 VkSamplerYcbcrConversion SamplerYcbcrConversionCache::getSamplerYcbcrConversionImpl(
3829 T format,
3830 const SamplerYcbcrConversionMap<T> &payload) const
3831 {
3832 const auto iter = payload.find(format);
3833 if (iter != payload.end())
3834 {
3835 const vk::RefCountedSamplerYcbcrConversion &yuvConversion = iter->second;
3836 return yuvConversion.get().getHandle();
3837 }
3838
3839 // Should never get here if we have a valid format.
3840 UNREACHABLE();
3841 return VK_NULL_HANDLE;
3842 }
3843
getSamplerYcbcrConversion(uint64_t externalOrVkFormat,bool isExternalFormat) const3844 VkSamplerYcbcrConversion SamplerYcbcrConversionCache::getSamplerYcbcrConversion(
3845 uint64_t externalOrVkFormat,
3846 bool isExternalFormat) const
3847 {
3848 if (isExternalFormat)
3849 {
3850 return getSamplerYcbcrConversionImpl(externalOrVkFormat, mExternalFormatPayload);
3851 }
3852 else
3853 {
3854 return getSamplerYcbcrConversionImpl(static_cast<VkFormat>(externalOrVkFormat),
3855 mVkFormatPayload);
3856 }
3857 }
3858
3859 // SamplerCache implementation.
3860 SamplerCache::SamplerCache() = default;
3861
~SamplerCache()3862 SamplerCache::~SamplerCache()
3863 {
3864 ASSERT(mPayload.empty());
3865 }
3866
destroy(RendererVk * rendererVk)3867 void SamplerCache::destroy(RendererVk *rendererVk)
3868 {
3869 rendererVk->accumulateCacheStats(VulkanCacheType::Sampler, mCacheStats);
3870
3871 VkDevice device = rendererVk->getDevice();
3872
3873 for (auto &iter : mPayload)
3874 {
3875 vk::RefCountedSampler &sampler = iter.second;
3876 ASSERT(!sampler.isReferenced());
3877 sampler.get().get().destroy(device);
3878
3879 rendererVk->getActiveHandleCounts().onDeallocate(vk::HandleType::Sampler);
3880 }
3881
3882 mPayload.clear();
3883 }
3884
getSampler(ContextVk * contextVk,const vk::SamplerDesc & desc,vk::SamplerBinding * samplerOut)3885 angle::Result SamplerCache::getSampler(ContextVk *contextVk,
3886 const vk::SamplerDesc &desc,
3887 vk::SamplerBinding *samplerOut)
3888 {
3889 auto iter = mPayload.find(desc);
3890 if (iter != mPayload.end())
3891 {
3892 vk::RefCountedSampler &sampler = iter->second;
3893 samplerOut->set(&sampler);
3894 mCacheStats.hit();
3895 return angle::Result::Continue;
3896 }
3897
3898 mCacheStats.miss();
3899 vk::SamplerHelper samplerHelper(contextVk);
3900 ANGLE_TRY(desc.init(contextVk, &samplerHelper.get()));
3901
3902 vk::RefCountedSampler newSampler(std::move(samplerHelper));
3903 auto insertedItem = mPayload.emplace(desc, std::move(newSampler));
3904 vk::RefCountedSampler &insertedSampler = insertedItem.first->second;
3905 samplerOut->set(&insertedSampler);
3906
3907 contextVk->getRenderer()->getActiveHandleCounts().onAllocate(vk::HandleType::Sampler);
3908
3909 return angle::Result::Continue;
3910 }
3911
3912 // DriverUniformsDescriptorSetCache implementation.
destroy(RendererVk * rendererVk)3913 void DriverUniformsDescriptorSetCache::destroy(RendererVk *rendererVk)
3914 {
3915 accumulateCacheStats(rendererVk);
3916 mPayload.clear();
3917 }
3918
3919 // DescriptorSetCache implementation.
3920 template <typename Key, VulkanCacheType CacheType>
destroy(RendererVk * rendererVk)3921 void DescriptorSetCache<Key, CacheType>::destroy(RendererVk *rendererVk)
3922 {
3923 this->accumulateCacheStats(rendererVk);
3924 mPayload.clear();
3925 }
3926
3927 // RendererVk's methods are not accessible in vk_cache_utils.h
3928 // Below declarations are needed to avoid linker errors.
3929 // Unclear why Clang warns about weak vtables in this case.
3930 ANGLE_DISABLE_WEAK_TEMPLATE_VTABLES_WARNING
3931 template class DescriptorSetCache<vk::TextureDescriptorDesc, VulkanCacheType::TextureDescriptors>;
3932
3933 template class DescriptorSetCache<vk::UniformsAndXfbDescriptorDesc,
3934 VulkanCacheType::UniformsAndXfbDescriptors>;
3935
3936 template class DescriptorSetCache<vk::ShaderBuffersDescriptorDesc,
3937 VulkanCacheType::ShaderBuffersDescriptors>;
3938 ANGLE_REENABLE_WEAK_TEMPLATE_VTABLES_WARNING
3939 } // namespace rx
3940