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