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