1 //
2 // Copyright 2016 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 // FramebufferVk.cpp:
7 // Implements the class methods for FramebufferVk.
8 //
9
10 #include "libANGLE/renderer/vulkan/FramebufferVk.h"
11
12 #include <array>
13
14 #include "common/debug.h"
15 #include "common/vulkan/vk_headers.h"
16 #include "libANGLE/Context.h"
17 #include "libANGLE/Display.h"
18 #include "libANGLE/ErrorStrings.h"
19 #include "libANGLE/formatutils.h"
20 #include "libANGLE/renderer/renderer_utils.h"
21 #include "libANGLE/renderer/vulkan/ContextVk.h"
22 #include "libANGLE/renderer/vulkan/DisplayVk.h"
23 #include "libANGLE/renderer/vulkan/RenderTargetVk.h"
24 #include "libANGLE/renderer/vulkan/RendererVk.h"
25 #include "libANGLE/renderer/vulkan/ResourceVk.h"
26 #include "libANGLE/renderer/vulkan/SurfaceVk.h"
27 #include "libANGLE/renderer/vulkan/vk_format_utils.h"
28 #include "libANGLE/trace.h"
29
30 namespace rx
31 {
32
33 namespace
34 {
35 // Clear values are only used when loadOp=Clear is set in clearWithRenderPassOp. When starting a
36 // new render pass, the clear value is set to an unlikely value (bright pink) to stand out better
37 // in case of a bug.
38 constexpr VkClearValue kUninitializedClearValue = {{{0.95, 0.05, 0.95, 0.95}}};
39
40 // The value to assign an alpha channel that's emulated. The type is unsigned int, though it will
41 // automatically convert to the actual data type.
42 constexpr unsigned int kEmulatedAlphaValue = 1;
43
HasSrcBlitFeature(RendererVk * renderer,RenderTargetVk * srcRenderTarget)44 bool HasSrcBlitFeature(RendererVk *renderer, RenderTargetVk *srcRenderTarget)
45 {
46 angle::FormatID srcFormatID = srcRenderTarget->getImageActualFormatID();
47 return renderer->hasImageFormatFeatureBits(srcFormatID, VK_FORMAT_FEATURE_BLIT_SRC_BIT);
48 }
49
HasDstBlitFeature(RendererVk * renderer,RenderTargetVk * dstRenderTarget)50 bool HasDstBlitFeature(RendererVk *renderer, RenderTargetVk *dstRenderTarget)
51 {
52 angle::FormatID dstFormatID = dstRenderTarget->getImageActualFormatID();
53 return renderer->hasImageFormatFeatureBits(dstFormatID, VK_FORMAT_FEATURE_BLIT_DST_BIT);
54 }
55
56 // Returns false if destination has any channel the source doesn't. This means that channel was
57 // emulated and using the Vulkan blit command would overwrite that emulated channel.
AreSrcAndDstColorChannelsBlitCompatible(RenderTargetVk * srcRenderTarget,RenderTargetVk * dstRenderTarget)58 bool AreSrcAndDstColorChannelsBlitCompatible(RenderTargetVk *srcRenderTarget,
59 RenderTargetVk *dstRenderTarget)
60 {
61 const angle::Format &srcFormat = srcRenderTarget->getImageIntendedFormat();
62 const angle::Format &dstFormat = dstRenderTarget->getImageIntendedFormat();
63
64 // Luminance/alpha formats are not renderable, so they can't have ended up in a framebuffer to
65 // participate in a blit.
66 ASSERT(!dstFormat.isLUMA() && !srcFormat.isLUMA());
67
68 // All color formats have the red channel.
69 ASSERT(dstFormat.redBits > 0 && srcFormat.redBits > 0);
70
71 return (dstFormat.greenBits > 0 || srcFormat.greenBits == 0) &&
72 (dstFormat.blueBits > 0 || srcFormat.blueBits == 0) &&
73 (dstFormat.alphaBits > 0 || srcFormat.alphaBits == 0);
74 }
75
76 // Returns false if formats are not identical. vkCmdResolveImage and resolve attachments both
77 // require identical formats between source and destination. vkCmdBlitImage additionally requires
78 // the same for depth/stencil formats.
AreSrcAndDstFormatsIdentical(RenderTargetVk * srcRenderTarget,RenderTargetVk * dstRenderTarget)79 bool AreSrcAndDstFormatsIdentical(RenderTargetVk *srcRenderTarget, RenderTargetVk *dstRenderTarget)
80 {
81 angle::FormatID srcFormatID = srcRenderTarget->getImageActualFormatID();
82 angle::FormatID dstFormatID = dstRenderTarget->getImageActualFormatID();
83
84 return srcFormatID == dstFormatID;
85 }
86
AreSrcAndDstDepthStencilChannelsBlitCompatible(RenderTargetVk * srcRenderTarget,RenderTargetVk * dstRenderTarget)87 bool AreSrcAndDstDepthStencilChannelsBlitCompatible(RenderTargetVk *srcRenderTarget,
88 RenderTargetVk *dstRenderTarget)
89 {
90 const angle::Format &srcFormat = srcRenderTarget->getImageIntendedFormat();
91 const angle::Format &dstFormat = dstRenderTarget->getImageIntendedFormat();
92
93 return (dstFormat.depthBits > 0 || srcFormat.depthBits == 0) &&
94 (dstFormat.stencilBits > 0 || srcFormat.stencilBits == 0);
95 }
96
EarlyAdjustFlipYForPreRotation(SurfaceRotation blitAngleIn,SurfaceRotation * blitAngleOut,bool * blitFlipYOut)97 void EarlyAdjustFlipYForPreRotation(SurfaceRotation blitAngleIn,
98 SurfaceRotation *blitAngleOut,
99 bool *blitFlipYOut)
100 {
101 switch (blitAngleIn)
102 {
103 case SurfaceRotation::Identity:
104 // No adjustments needed
105 break;
106 case SurfaceRotation::Rotated90Degrees:
107 *blitAngleOut = SurfaceRotation::Rotated90Degrees;
108 *blitFlipYOut = false;
109 break;
110 case SurfaceRotation::Rotated180Degrees:
111 *blitAngleOut = SurfaceRotation::Rotated180Degrees;
112 break;
113 case SurfaceRotation::Rotated270Degrees:
114 *blitAngleOut = SurfaceRotation::Rotated270Degrees;
115 *blitFlipYOut = false;
116 break;
117 default:
118 UNREACHABLE();
119 break;
120 }
121 }
122
AdjustBlitAreaForPreRotation(SurfaceRotation framebufferAngle,const gl::Rectangle & blitAreaIn,const gl::Rectangle & framebufferDimensions,gl::Rectangle * blitAreaOut)123 void AdjustBlitAreaForPreRotation(SurfaceRotation framebufferAngle,
124 const gl::Rectangle &blitAreaIn,
125 const gl::Rectangle &framebufferDimensions,
126 gl::Rectangle *blitAreaOut)
127 {
128 switch (framebufferAngle)
129 {
130 case SurfaceRotation::Identity:
131 // No adjustments needed
132 break;
133 case SurfaceRotation::Rotated90Degrees:
134 blitAreaOut->x = blitAreaIn.y;
135 blitAreaOut->y = blitAreaIn.x;
136 std::swap(blitAreaOut->width, blitAreaOut->height);
137 break;
138 case SurfaceRotation::Rotated180Degrees:
139 blitAreaOut->x = framebufferDimensions.width - blitAreaIn.x - blitAreaIn.width;
140 blitAreaOut->y = framebufferDimensions.height - blitAreaIn.y - blitAreaIn.height;
141 break;
142 case SurfaceRotation::Rotated270Degrees:
143 blitAreaOut->x = framebufferDimensions.height - blitAreaIn.y - blitAreaIn.height;
144 blitAreaOut->y = framebufferDimensions.width - blitAreaIn.x - blitAreaIn.width;
145 std::swap(blitAreaOut->width, blitAreaOut->height);
146 break;
147 default:
148 UNREACHABLE();
149 break;
150 }
151 }
152
AdjustDimensionsAndFlipForPreRotation(SurfaceRotation framebufferAngle,gl::Rectangle * framebufferDimensions,bool * flipX,bool * flipY)153 void AdjustDimensionsAndFlipForPreRotation(SurfaceRotation framebufferAngle,
154 gl::Rectangle *framebufferDimensions,
155 bool *flipX,
156 bool *flipY)
157 {
158 switch (framebufferAngle)
159 {
160 case SurfaceRotation::Identity:
161 // No adjustments needed
162 break;
163 case SurfaceRotation::Rotated90Degrees:
164 std::swap(framebufferDimensions->width, framebufferDimensions->height);
165 std::swap(*flipX, *flipY);
166 break;
167 case SurfaceRotation::Rotated180Degrees:
168 break;
169 case SurfaceRotation::Rotated270Degrees:
170 std::swap(framebufferDimensions->width, framebufferDimensions->height);
171 std::swap(*flipX, *flipY);
172 break;
173 default:
174 UNREACHABLE();
175 break;
176 }
177 }
178
179 // When blitting, the source and destination areas are viewed like UVs. For example, a 64x64
180 // texture if flipped should have an offset of 64 in either X or Y which corresponds to U or V of 1.
181 // On the other hand, when resolving, the source and destination areas are used as fragment
182 // coordinates to fetch from. In that case, when flipped, the texture in the above example must
183 // have an offset of 63.
AdjustBlitResolveParametersForResolve(const gl::Rectangle & sourceArea,const gl::Rectangle & destArea,UtilsVk::BlitResolveParameters * params)184 void AdjustBlitResolveParametersForResolve(const gl::Rectangle &sourceArea,
185 const gl::Rectangle &destArea,
186 UtilsVk::BlitResolveParameters *params)
187 {
188 params->srcOffset[0] = sourceArea.x;
189 params->srcOffset[1] = sourceArea.y;
190 params->dstOffset[0] = destArea.x;
191 params->dstOffset[1] = destArea.y;
192
193 if (sourceArea.isReversedX())
194 {
195 ASSERT(sourceArea.x > 0);
196 --params->srcOffset[0];
197 }
198 if (sourceArea.isReversedY())
199 {
200 ASSERT(sourceArea.y > 0);
201 --params->srcOffset[1];
202 }
203 if (destArea.isReversedX())
204 {
205 ASSERT(destArea.x > 0);
206 --params->dstOffset[0];
207 }
208 if (destArea.isReversedY())
209 {
210 ASSERT(destArea.y > 0);
211 --params->dstOffset[1];
212 }
213 }
214
215 // Potentially make adjustments for pre-rotatation. Depending on the angle some of the params need
216 // to be swapped and/or changes made to which axis are flipped.
AdjustBlitResolveParametersForPreRotation(SurfaceRotation framebufferAngle,SurfaceRotation srcFramebufferAngle,UtilsVk::BlitResolveParameters * params)217 void AdjustBlitResolveParametersForPreRotation(SurfaceRotation framebufferAngle,
218 SurfaceRotation srcFramebufferAngle,
219 UtilsVk::BlitResolveParameters *params)
220 {
221 switch (framebufferAngle)
222 {
223 case SurfaceRotation::Identity:
224 break;
225 case SurfaceRotation::Rotated90Degrees:
226 std::swap(params->stretch[0], params->stretch[1]);
227 std::swap(params->srcOffset[0], params->srcOffset[1]);
228 std::swap(params->rotatedOffsetFactor[0], params->rotatedOffsetFactor[1]);
229 std::swap(params->flipX, params->flipY);
230 if (srcFramebufferAngle == framebufferAngle)
231 {
232 std::swap(params->dstOffset[0], params->dstOffset[1]);
233 std::swap(params->stretch[0], params->stretch[1]);
234 }
235 break;
236 case SurfaceRotation::Rotated180Degrees:
237 // Combine flip info with api flip.
238 params->flipX = !params->flipX;
239 params->flipY = !params->flipY;
240 break;
241 case SurfaceRotation::Rotated270Degrees:
242 std::swap(params->stretch[0], params->stretch[1]);
243 std::swap(params->srcOffset[0], params->srcOffset[1]);
244 std::swap(params->rotatedOffsetFactor[0], params->rotatedOffsetFactor[1]);
245 if (srcFramebufferAngle == framebufferAngle)
246 {
247 std::swap(params->stretch[0], params->stretch[1]);
248 }
249 // Combine flip info with api flip.
250 params->flipX = !params->flipX;
251 params->flipY = !params->flipY;
252 std::swap(params->flipX, params->flipY);
253
254 break;
255 default:
256 UNREACHABLE();
257 break;
258 }
259 }
260
HasResolveAttachment(const gl::AttachmentArray<RenderTargetVk * > & colorRenderTargets,const gl::DrawBufferMask & getEnabledDrawBuffers)261 bool HasResolveAttachment(const gl::AttachmentArray<RenderTargetVk *> &colorRenderTargets,
262 const gl::DrawBufferMask &getEnabledDrawBuffers)
263 {
264 for (size_t colorIndexGL : getEnabledDrawBuffers)
265 {
266 RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
267 if (colorRenderTarget->hasResolveAttachment())
268 {
269 return true;
270 }
271 }
272 return false;
273 }
274
MakeUnresolveAttachmentMask(const vk::RenderPassDesc & desc)275 vk::FramebufferNonResolveAttachmentMask MakeUnresolveAttachmentMask(const vk::RenderPassDesc &desc)
276 {
277 vk::FramebufferNonResolveAttachmentMask unresolveMask(
278 desc.getColorUnresolveAttachmentMask().bits());
279 if (desc.hasDepthUnresolveAttachment() || desc.hasStencilUnresolveAttachment())
280 {
281 // This mask only needs to know if the depth/stencil attachment needs to be unresolved, and
282 // is agnostic of the aspect.
283 unresolveMask.set(vk::kUnpackedDepthIndex);
284 }
285 return unresolveMask;
286 }
287
IsAnyAttachment3DWithoutAllLayers(const RenderTargetCache<RenderTargetVk> & renderTargetCache,gl::DrawBufferMask colorAttachmentsMask,uint32_t framebufferLayerCount)288 bool IsAnyAttachment3DWithoutAllLayers(const RenderTargetCache<RenderTargetVk> &renderTargetCache,
289 gl::DrawBufferMask colorAttachmentsMask,
290 uint32_t framebufferLayerCount)
291 {
292 const auto &colorRenderTargets = renderTargetCache.getColors();
293 for (size_t colorIndexGL : colorAttachmentsMask)
294 {
295 RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
296 ASSERT(colorRenderTarget);
297
298 const vk::ImageHelper &image = colorRenderTarget->getImageForRenderPass();
299
300 if (image.getType() == VK_IMAGE_TYPE_3D && image.getExtents().depth > framebufferLayerCount)
301 {
302 return true;
303 }
304 }
305
306 // Depth/stencil attachments cannot be 3D.
307 ASSERT(renderTargetCache.getDepthStencil() == nullptr ||
308 renderTargetCache.getDepthStencil()->getImageForRenderPass().getType() !=
309 VK_IMAGE_TYPE_3D);
310
311 return false;
312 }
313 } // anonymous namespace
314
315 // static
CreateUserFBO(RendererVk * renderer,const gl::FramebufferState & state)316 FramebufferVk *FramebufferVk::CreateUserFBO(RendererVk *renderer, const gl::FramebufferState &state)
317 {
318 return new FramebufferVk(renderer, state, nullptr);
319 }
320
321 // static
CreateDefaultFBO(RendererVk * renderer,const gl::FramebufferState & state,WindowSurfaceVk * backbuffer)322 FramebufferVk *FramebufferVk::CreateDefaultFBO(RendererVk *renderer,
323 const gl::FramebufferState &state,
324 WindowSurfaceVk *backbuffer)
325 {
326 return new FramebufferVk(renderer, state, backbuffer);
327 }
328
FramebufferVk(RendererVk * renderer,const gl::FramebufferState & state,WindowSurfaceVk * backbuffer)329 FramebufferVk::FramebufferVk(RendererVk *renderer,
330 const gl::FramebufferState &state,
331 WindowSurfaceVk *backbuffer)
332 : FramebufferImpl(state),
333 mBackbuffer(backbuffer),
334 mFramebuffer(nullptr),
335 mActiveColorComponentMasksForClear(0),
336 mReadOnlyDepthFeedbackLoopMode(false)
337 {}
338
339 FramebufferVk::~FramebufferVk() = default;
340
destroy(const gl::Context * context)341 void FramebufferVk::destroy(const gl::Context *context)
342 {
343 ContextVk *contextVk = vk::GetImpl(context);
344 RendererVk *rendererVk = contextVk->getRenderer();
345
346 mFramebufferCache.clear(contextVk);
347 mFramebufferCache.destroy(rendererVk);
348 mFramebuffer = nullptr;
349 }
350
discard(const gl::Context * context,size_t count,const GLenum * attachments)351 angle::Result FramebufferVk::discard(const gl::Context *context,
352 size_t count,
353 const GLenum *attachments)
354 {
355 return invalidate(context, count, attachments);
356 }
357
invalidate(const gl::Context * context,size_t count,const GLenum * attachments)358 angle::Result FramebufferVk::invalidate(const gl::Context *context,
359 size_t count,
360 const GLenum *attachments)
361 {
362 ContextVk *contextVk = vk::GetImpl(context);
363
364 ANGLE_TRY(invalidateImpl(contextVk, count, attachments, false,
365 getRotatedCompleteRenderArea(contextVk)));
366 return angle::Result::Continue;
367 }
368
invalidateSub(const gl::Context * context,size_t count,const GLenum * attachments,const gl::Rectangle & area)369 angle::Result FramebufferVk::invalidateSub(const gl::Context *context,
370 size_t count,
371 const GLenum *attachments,
372 const gl::Rectangle &area)
373 {
374 ContextVk *contextVk = vk::GetImpl(context);
375
376 const gl::Rectangle nonRotatedCompleteRenderArea = getNonRotatedCompleteRenderArea();
377 gl::Rectangle rotatedInvalidateArea;
378 RotateRectangle(contextVk->getRotationDrawFramebuffer(),
379 contextVk->isViewportFlipEnabledForDrawFBO(),
380 nonRotatedCompleteRenderArea.width, nonRotatedCompleteRenderArea.height, area,
381 &rotatedInvalidateArea);
382
383 // If invalidateSub() covers the whole framebuffer area, make it behave as invalidate().
384 // The invalidate area is clipped to the render area for use inside invalidateImpl.
385 const gl::Rectangle completeRenderArea = getRotatedCompleteRenderArea(contextVk);
386 if (ClipRectangle(rotatedInvalidateArea, completeRenderArea, &rotatedInvalidateArea) &&
387 rotatedInvalidateArea == completeRenderArea)
388 {
389 return invalidate(context, count, attachments);
390 }
391
392 // If there are deferred clears, redefer them. syncState may have accumulated deferred clears,
393 // but if the framebuffer's attachments are used after this call not through the framebuffer,
394 // those clears wouldn't get flushed otherwise (for example as the destination of
395 // glCopyTex[Sub]Image, shader storage image, etc).
396 redeferClears(contextVk);
397
398 if (contextVk->hasStartedRenderPass() &&
399 rotatedInvalidateArea.encloses(contextVk->getStartedRenderPassCommands().getRenderArea()))
400 {
401 // Because the render pass's render area is within the invalidated area, it is fine for
402 // invalidateImpl() to use a storeOp of DONT_CARE (i.e. fine to not store the contents of
403 // the invalidated area).
404 ANGLE_TRY(invalidateImpl(contextVk, count, attachments, true, rotatedInvalidateArea));
405 }
406 else
407 {
408 ANGLE_VK_PERF_WARNING(
409 contextVk, GL_DEBUG_SEVERITY_LOW,
410 "InvalidateSubFramebuffer ignored due to area not covering the render area");
411 }
412
413 return angle::Result::Continue;
414 }
415
clear(const gl::Context * context,GLbitfield mask)416 angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
417 {
418 ANGLE_TRACE_EVENT0("gpu.angle", "FramebufferVk::clear");
419 ContextVk *contextVk = vk::GetImpl(context);
420
421 bool clearColor = IsMaskFlagSet(mask, static_cast<GLbitfield>(GL_COLOR_BUFFER_BIT));
422 bool clearDepth = IsMaskFlagSet(mask, static_cast<GLbitfield>(GL_DEPTH_BUFFER_BIT));
423 bool clearStencil = IsMaskFlagSet(mask, static_cast<GLbitfield>(GL_STENCIL_BUFFER_BIT));
424 gl::DrawBufferMask clearColorBuffers;
425 if (clearColor)
426 {
427 clearColorBuffers = mState.getEnabledDrawBuffers();
428 }
429
430 const VkClearColorValue &clearColorValue = contextVk->getClearColorValue().color;
431 const VkClearDepthStencilValue &clearDepthStencilValue =
432 contextVk->getClearDepthStencilValue().depthStencil;
433
434 return clearImpl(context, clearColorBuffers, clearDepth, clearStencil, clearColorValue,
435 clearDepthStencilValue);
436 }
437
clearImpl(const gl::Context * context,gl::DrawBufferMask clearColorBuffers,bool clearDepth,bool clearStencil,const VkClearColorValue & clearColorValue,const VkClearDepthStencilValue & clearDepthStencilValue)438 angle::Result FramebufferVk::clearImpl(const gl::Context *context,
439 gl::DrawBufferMask clearColorBuffers,
440 bool clearDepth,
441 bool clearStencil,
442 const VkClearColorValue &clearColorValue,
443 const VkClearDepthStencilValue &clearDepthStencilValue)
444 {
445 ContextVk *contextVk = vk::GetImpl(context);
446
447 const gl::Rectangle scissoredRenderArea = getRotatedScissoredRenderArea(contextVk);
448 ASSERT(scissoredRenderArea.width != 0 && scissoredRenderArea.height != 0);
449
450 // This function assumes that only enabled attachments are asked to be cleared.
451 ASSERT((clearColorBuffers & mState.getEnabledDrawBuffers()) == clearColorBuffers);
452 ASSERT(!clearDepth || mState.getDepthAttachment() != nullptr);
453 ASSERT(!clearStencil || mState.getStencilAttachment() != nullptr);
454
455 gl::BlendStateExt::ColorMaskStorage::Type colorMasks = contextVk->getClearColorMasks();
456 bool clearColor = clearColorBuffers.any();
457
458 // When this function is called, there should always be something to clear.
459 ASSERT(clearColor || clearDepth || clearStencil);
460
461 const uint8_t stencilMask =
462 static_cast<uint8_t>(contextVk->getState().getDepthStencilState().stencilWritemask);
463
464 // The front-end should ensure we don't attempt to clear color if all channels are masked.
465 ASSERT(!clearColor || colorMasks != 0);
466 // The front-end should ensure we don't attempt to clear depth if depth write is disabled.
467 ASSERT(!clearDepth || contextVk->getState().getDepthStencilState().depthMask);
468 // The front-end should ensure we don't attempt to clear stencil if all bits are masked.
469 ASSERT(!clearStencil || stencilMask != 0);
470
471 // Make sure to close the render pass now if in read-only depth/stencil feedback loop mode and
472 // depth/stencil is being cleared.
473 if (clearDepth || clearStencil)
474 {
475 ANGLE_TRY(contextVk->updateRenderPassDepthFeedbackLoopMode(
476 clearDepth ? UpdateDepthFeedbackLoopReason::Clear : UpdateDepthFeedbackLoopReason::None,
477 clearStencil ? UpdateDepthFeedbackLoopReason::Clear
478 : UpdateDepthFeedbackLoopReason::None));
479 }
480
481 const bool scissoredClear = scissoredRenderArea != getRotatedCompleteRenderArea(contextVk);
482
483 // We use the draw path if scissored clear, or color or stencil are masked. Note that depth
484 // clearing is already disabled if there's a depth mask.
485 const bool maskedClearColor = clearColor && (mActiveColorComponentMasksForClear & colorMasks) !=
486 mActiveColorComponentMasksForClear;
487 const bool maskedClearStencil = clearStencil && stencilMask != 0xFF;
488
489 bool clearColorWithDraw = clearColor && (maskedClearColor || scissoredClear);
490 bool clearDepthWithDraw = clearDepth && scissoredClear;
491 bool clearStencilWithDraw = clearStencil && (maskedClearStencil || scissoredClear);
492
493 const bool isMidRenderPassClear = contextVk->hasStartedRenderPassWithCommands();
494
495 if (isMidRenderPassClear)
496 {
497 // If a render pass is open with commands, it must be for this framebuffer. Otherwise,
498 // either FramebufferVk::syncState() or ContextVk::syncState() would have closed it.
499 vk::Framebuffer *currentFramebuffer = nullptr;
500 ANGLE_TRY(getFramebuffer(contextVk, ¤tFramebuffer, nullptr,
501 SwapchainResolveMode::Disabled));
502 ASSERT(contextVk->hasStartedRenderPassWithFramebuffer(currentFramebuffer));
503
504 // Emit debug-util markers for this mid-render-pass clear
505 ANGLE_TRY(
506 contextVk->handleGraphicsEventLog(rx::GraphicsEventCmdBuf::InRenderPassCmdBufQueryCmd));
507 }
508 else
509 {
510 // Emit debug-util markers for this outside-render-pass clear
511 ANGLE_TRY(
512 contextVk->handleGraphicsEventLog(rx::GraphicsEventCmdBuf::InOutsideCmdBufQueryCmd));
513 }
514
515 const bool preferDrawOverClearAttachments =
516 contextVk->getRenderer()->getFeatures().preferDrawClearOverVkCmdClearAttachments.enabled;
517
518 // Merge current clears with the deferred clears, then proceed with only processing deferred
519 // clears. This simplifies the clear paths such that they don't need to consider both the
520 // current and deferred clears. Additionally, it avoids needing to undo an unresolve
521 // operation; say attachment A is deferred cleared and multisampled-render-to-texture
522 // attachment B is currently cleared. Assuming a render pass needs to start (because for
523 // example attachment C needs to clear with a draw path), starting one with only deferred
524 // clears and then applying the current clears won't work as attachment B is unresolved, and
525 // there are no facilities to undo that.
526 if (preferDrawOverClearAttachments && isMidRenderPassClear)
527 {
528 // On buggy hardware, prefer to clear with a draw call instead of vkCmdClearAttachments.
529 // Note that it's impossible to have deferred clears in the middle of the render pass.
530 ASSERT(!mDeferredClears.any());
531
532 clearColorWithDraw = clearColor;
533 clearDepthWithDraw = clearDepth;
534 clearStencilWithDraw = clearStencil;
535 }
536 else
537 {
538 gl::DrawBufferMask clearColorDrawBuffersMask;
539 if (clearColor && !clearColorWithDraw)
540 {
541 clearColorDrawBuffersMask = clearColorBuffers;
542 }
543
544 mergeClearsWithDeferredClears(clearColorDrawBuffersMask, clearDepth && !clearDepthWithDraw,
545 clearStencil && !clearStencilWithDraw, clearColorValue,
546 clearDepthStencilValue);
547 }
548
549 // If any deferred clears, we can further defer them, clear them with vkCmdClearAttachments or
550 // flush them if necessary.
551 if (mDeferredClears.any())
552 {
553 const bool clearAnyWithDraw =
554 clearColorWithDraw || clearDepthWithDraw || clearStencilWithDraw;
555
556 // If we are in an active renderpass that has recorded commands and the framebuffer hasn't
557 // changed, inline the clear.
558 if (isMidRenderPassClear)
559 {
560 ANGLE_VK_PERF_WARNING(
561 contextVk, GL_DEBUG_SEVERITY_LOW,
562 "Clear effectively discarding previous draw call results. Suggest earlier Clear "
563 "followed by masked color or depth/stencil draw calls instead, or "
564 "glInvalidateFramebuffer to discard data instead");
565
566 ASSERT(!preferDrawOverClearAttachments);
567
568 // clearWithCommand will operate on deferred clears.
569 clearWithCommand(contextVk, scissoredRenderArea);
570
571 // clearWithCommand will clear only those attachments that have been used in the render
572 // pass, and removes them from mDeferredClears. Any deferred clears that are left can
573 // be performed with a renderpass loadOp.
574 if (mDeferredClears.any())
575 {
576 clearWithLoadOp(contextVk);
577 }
578 }
579 else
580 {
581 ASSERT(!contextVk->hasStartedRenderPass());
582
583 // This path will defer the current clears along with deferred clears. This won't work
584 // if any attachment needs to be subsequently cleared with a draw call. In that case,
585 // flush deferred clears, which will start a render pass with deferred clear values.
586 // The subsequent draw call will then operate on the cleared attachments.
587 //
588 // Additionally, if the framebuffer is layered, any attachment is 3D and it has a larger
589 // depth than the framebuffer layers, clears cannot be deferred. This is because the
590 // clear may later need to be flushed with vkCmdClearColorImage, which cannot partially
591 // clear the 3D texture. In that case, the clears are flushed immediately too.
592 bool isAnyAttachment3DWithoutAllLayers = IsAnyAttachment3DWithoutAllLayers(
593 mRenderTargetCache, mState.getColorAttachmentsMask(),
594 mCurrentFramebufferDesc.getLayerCount());
595
596 if (clearAnyWithDraw || isAnyAttachment3DWithoutAllLayers)
597 {
598 ANGLE_TRY(flushDeferredClears(contextVk));
599 }
600 else
601 {
602 redeferClears(contextVk);
603 }
604 }
605
606 // If nothing left to clear, early out.
607 if (!clearAnyWithDraw)
608 {
609 ASSERT(mDeferredClears.empty());
610 return angle::Result::Continue;
611 }
612 }
613
614 if (!clearColorWithDraw)
615 {
616 clearColorBuffers.reset();
617 }
618
619 // The most costly clear mode is when we need to mask out specific color channels or stencil
620 // bits. This can only be done with a draw call.
621 return clearWithDraw(contextVk, scissoredRenderArea, clearColorBuffers, clearDepthWithDraw,
622 clearStencilWithDraw, colorMasks, stencilMask, clearColorValue,
623 clearDepthStencilValue);
624 }
625
clearBufferfv(const gl::Context * context,GLenum buffer,GLint drawbuffer,const GLfloat * values)626 angle::Result FramebufferVk::clearBufferfv(const gl::Context *context,
627 GLenum buffer,
628 GLint drawbuffer,
629 const GLfloat *values)
630 {
631 VkClearValue clearValue = {};
632
633 bool clearDepth = false;
634 gl::DrawBufferMask clearColorBuffers;
635
636 if (buffer == GL_DEPTH)
637 {
638 clearDepth = true;
639 clearValue.depthStencil.depth = values[0];
640 }
641 else
642 {
643 clearColorBuffers.set(drawbuffer);
644 clearValue.color.float32[0] = values[0];
645 clearValue.color.float32[1] = values[1];
646 clearValue.color.float32[2] = values[2];
647 clearValue.color.float32[3] = values[3];
648 }
649
650 return clearImpl(context, clearColorBuffers, clearDepth, false, clearValue.color,
651 clearValue.depthStencil);
652 }
653
clearBufferuiv(const gl::Context * context,GLenum buffer,GLint drawbuffer,const GLuint * values)654 angle::Result FramebufferVk::clearBufferuiv(const gl::Context *context,
655 GLenum buffer,
656 GLint drawbuffer,
657 const GLuint *values)
658 {
659 VkClearValue clearValue = {};
660
661 gl::DrawBufferMask clearColorBuffers;
662 clearColorBuffers.set(drawbuffer);
663
664 clearValue.color.uint32[0] = values[0];
665 clearValue.color.uint32[1] = values[1];
666 clearValue.color.uint32[2] = values[2];
667 clearValue.color.uint32[3] = values[3];
668
669 return clearImpl(context, clearColorBuffers, false, false, clearValue.color,
670 clearValue.depthStencil);
671 }
672
clearBufferiv(const gl::Context * context,GLenum buffer,GLint drawbuffer,const GLint * values)673 angle::Result FramebufferVk::clearBufferiv(const gl::Context *context,
674 GLenum buffer,
675 GLint drawbuffer,
676 const GLint *values)
677 {
678 VkClearValue clearValue = {};
679
680 bool clearStencil = false;
681 gl::DrawBufferMask clearColorBuffers;
682
683 if (buffer == GL_STENCIL)
684 {
685 clearStencil = true;
686 clearValue.depthStencil.stencil = static_cast<uint8_t>(values[0]);
687 }
688 else
689 {
690 clearColorBuffers.set(drawbuffer);
691 clearValue.color.int32[0] = values[0];
692 clearValue.color.int32[1] = values[1];
693 clearValue.color.int32[2] = values[2];
694 clearValue.color.int32[3] = values[3];
695 }
696
697 return clearImpl(context, clearColorBuffers, false, clearStencil, clearValue.color,
698 clearValue.depthStencil);
699 }
700
clearBufferfi(const gl::Context * context,GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)701 angle::Result FramebufferVk::clearBufferfi(const gl::Context *context,
702 GLenum buffer,
703 GLint drawbuffer,
704 GLfloat depth,
705 GLint stencil)
706 {
707 VkClearValue clearValue = {};
708
709 clearValue.depthStencil.depth = depth;
710 clearValue.depthStencil.stencil = static_cast<uint8_t>(stencil);
711
712 return clearImpl(context, gl::DrawBufferMask(), true, true, clearValue.color,
713 clearValue.depthStencil);
714 }
715
getImplementationColorReadFormat(const gl::Context * context) const716 const gl::InternalFormat &FramebufferVk::getImplementationColorReadFormat(
717 const gl::Context *context) const
718 {
719 ContextVk *contextVk = vk::GetImpl(context);
720 GLenum sizedFormat = mState.getReadAttachment()->getFormat().info->sizedInternalFormat;
721 const vk::Format &vkFormat = contextVk->getRenderer()->getFormat(sizedFormat);
722 GLenum implFormat = vkFormat.getActualRenderableImageFormat().fboImplementationInternalFormat;
723 return gl::GetSizedInternalFormatInfo(implFormat);
724 }
725
readPixels(const gl::Context * context,const gl::Rectangle & area,GLenum format,GLenum type,const gl::PixelPackState & pack,gl::Buffer * packBuffer,void * pixels)726 angle::Result FramebufferVk::readPixels(const gl::Context *context,
727 const gl::Rectangle &area,
728 GLenum format,
729 GLenum type,
730 const gl::PixelPackState &pack,
731 gl::Buffer *packBuffer,
732 void *pixels)
733 {
734 // Clip read area to framebuffer.
735 const gl::Extents &fbSize = getState().getReadPixelsAttachment(format)->getSize();
736 const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
737 ContextVk *contextVk = vk::GetImpl(context);
738
739 gl::Rectangle clippedArea;
740 if (!ClipRectangle(area, fbRect, &clippedArea))
741 {
742 // nothing to read
743 return angle::Result::Continue;
744 }
745
746 // Flush any deferred clears.
747 ANGLE_TRY(flushDeferredClears(contextVk));
748
749 GLuint outputSkipBytes = 0;
750 PackPixelsParams params;
751 ANGLE_TRY(vk::ImageHelper::GetReadPixelsParams(contextVk, pack, packBuffer, format, type, area,
752 clippedArea, ¶ms, &outputSkipBytes));
753
754 bool flipY = contextVk->isViewportFlipEnabledForReadFBO();
755 switch (params.rotation = contextVk->getRotationReadFramebuffer())
756 {
757 case SurfaceRotation::Identity:
758 // Do not rotate gl_Position (surface matches the device's orientation):
759 if (flipY)
760 {
761 params.area.y = fbRect.height - clippedArea.y - clippedArea.height;
762 }
763 break;
764 case SurfaceRotation::Rotated90Degrees:
765 // Rotate gl_Position 90 degrees:
766 params.area.x = clippedArea.y;
767 params.area.y =
768 flipY ? clippedArea.x : fbRect.width - clippedArea.x - clippedArea.width;
769 std::swap(params.area.width, params.area.height);
770 break;
771 case SurfaceRotation::Rotated180Degrees:
772 // Rotate gl_Position 180 degrees:
773 params.area.x = fbRect.width - clippedArea.x - clippedArea.width;
774 params.area.y =
775 flipY ? clippedArea.y : fbRect.height - clippedArea.y - clippedArea.height;
776 break;
777 case SurfaceRotation::Rotated270Degrees:
778 // Rotate gl_Position 270 degrees:
779 params.area.x = fbRect.height - clippedArea.y - clippedArea.height;
780 params.area.y =
781 flipY ? fbRect.width - clippedArea.x - clippedArea.width : clippedArea.x;
782 std::swap(params.area.width, params.area.height);
783 break;
784 default:
785 UNREACHABLE();
786 break;
787 }
788 if (flipY)
789 {
790 params.reverseRowOrder = !params.reverseRowOrder;
791 }
792
793 ANGLE_TRY(readPixelsImpl(contextVk, params.area, params, getReadPixelsAspectFlags(format),
794 getReadPixelsRenderTarget(format),
795 static_cast<uint8_t *>(pixels) + outputSkipBytes));
796 return angle::Result::Continue;
797 }
798
getDepthStencilRenderTarget() const799 RenderTargetVk *FramebufferVk::getDepthStencilRenderTarget() const
800 {
801 return mRenderTargetCache.getDepthStencil();
802 }
803
getColorDrawRenderTarget(size_t colorIndex) const804 RenderTargetVk *FramebufferVk::getColorDrawRenderTarget(size_t colorIndex) const
805 {
806 RenderTargetVk *renderTarget = mRenderTargetCache.getColorDraw(mState, colorIndex);
807 ASSERT(renderTarget && renderTarget->getImageForRenderPass().valid());
808 return renderTarget;
809 }
810
getColorReadRenderTarget() const811 RenderTargetVk *FramebufferVk::getColorReadRenderTarget() const
812 {
813 RenderTargetVk *renderTarget = mRenderTargetCache.getColorRead(mState);
814 ASSERT(renderTarget && renderTarget->getImageForRenderPass().valid());
815 return renderTarget;
816 }
817
getReadPixelsRenderTarget(GLenum format) const818 RenderTargetVk *FramebufferVk::getReadPixelsRenderTarget(GLenum format) const
819 {
820 switch (format)
821 {
822 case GL_DEPTH_COMPONENT:
823 case GL_STENCIL_INDEX_OES:
824 return getDepthStencilRenderTarget();
825 default:
826 return getColorReadRenderTarget();
827 }
828 }
829
getReadPixelsAspectFlags(GLenum format) const830 VkImageAspectFlagBits FramebufferVk::getReadPixelsAspectFlags(GLenum format) const
831 {
832 switch (format)
833 {
834 case GL_DEPTH_COMPONENT:
835 return VK_IMAGE_ASPECT_DEPTH_BIT;
836 case GL_STENCIL_INDEX_OES:
837 return VK_IMAGE_ASPECT_STENCIL_BIT;
838 default:
839 return VK_IMAGE_ASPECT_COLOR_BIT;
840 }
841 }
842
blitWithCommand(ContextVk * contextVk,const gl::Rectangle & sourceArea,const gl::Rectangle & destArea,RenderTargetVk * readRenderTarget,RenderTargetVk * drawRenderTarget,GLenum filter,bool colorBlit,bool depthBlit,bool stencilBlit,bool flipX,bool flipY)843 angle::Result FramebufferVk::blitWithCommand(ContextVk *contextVk,
844 const gl::Rectangle &sourceArea,
845 const gl::Rectangle &destArea,
846 RenderTargetVk *readRenderTarget,
847 RenderTargetVk *drawRenderTarget,
848 GLenum filter,
849 bool colorBlit,
850 bool depthBlit,
851 bool stencilBlit,
852 bool flipX,
853 bool flipY)
854 {
855 // Since blitRenderbufferRect is called for each render buffer that needs to be blitted,
856 // it should never be the case that both color and depth/stencil need to be blitted at
857 // at the same time.
858 ASSERT(colorBlit != (depthBlit || stencilBlit));
859
860 vk::ImageHelper *srcImage = &readRenderTarget->getImageForCopy();
861 vk::ImageHelper *dstImage = &drawRenderTarget->getImageForWrite();
862
863 VkImageAspectFlags imageAspectMask = srcImage->getAspectFlags();
864 VkImageAspectFlags blitAspectMask = imageAspectMask;
865
866 // Remove depth or stencil aspects if they are not requested to be blitted.
867 if (!depthBlit)
868 {
869 blitAspectMask &= ~VK_IMAGE_ASPECT_DEPTH_BIT;
870 }
871 if (!stencilBlit)
872 {
873 blitAspectMask &= ~VK_IMAGE_ASPECT_STENCIL_BIT;
874 }
875
876 vk::CommandBufferAccess access;
877 access.onImageTransferRead(imageAspectMask, srcImage);
878 access.onImageTransferWrite(drawRenderTarget->getLevelIndex(), 1,
879 drawRenderTarget->getLayerIndex(), 1, imageAspectMask, dstImage);
880 vk::OutsideRenderPassCommandBuffer *commandBuffer;
881 ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
882
883 VkImageBlit blit = {};
884 blit.srcSubresource.aspectMask = blitAspectMask;
885 blit.srcSubresource.mipLevel = srcImage->toVkLevel(readRenderTarget->getLevelIndex()).get();
886 blit.srcSubresource.baseArrayLayer = readRenderTarget->getLayerIndex();
887 blit.srcSubresource.layerCount = 1;
888 blit.srcOffsets[0] = {sourceArea.x0(), sourceArea.y0(), 0};
889 blit.srcOffsets[1] = {sourceArea.x1(), sourceArea.y1(), 1};
890 blit.dstSubresource.aspectMask = blitAspectMask;
891 blit.dstSubresource.mipLevel = dstImage->toVkLevel(drawRenderTarget->getLevelIndex()).get();
892 blit.dstSubresource.baseArrayLayer = drawRenderTarget->getLayerIndex();
893 blit.dstSubresource.layerCount = 1;
894 blit.dstOffsets[0] = {destArea.x0(), destArea.y0(), 0};
895 blit.dstOffsets[1] = {destArea.x1(), destArea.y1(), 1};
896
897 commandBuffer->blitImage(srcImage->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
898 dstImage->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit,
899 gl_vk::GetFilter(filter));
900
901 return angle::Result::Continue;
902 }
903
blit(const gl::Context * context,const gl::Rectangle & sourceAreaIn,const gl::Rectangle & destAreaIn,GLbitfield mask,GLenum filter)904 angle::Result FramebufferVk::blit(const gl::Context *context,
905 const gl::Rectangle &sourceAreaIn,
906 const gl::Rectangle &destAreaIn,
907 GLbitfield mask,
908 GLenum filter)
909 {
910 ContextVk *contextVk = vk::GetImpl(context);
911 RendererVk *renderer = contextVk->getRenderer();
912 UtilsVk &utilsVk = contextVk->getUtils();
913
914 // We can sometimes end up in a blit with some clear commands saved. Ensure all clear commands
915 // are issued before we issue the blit command.
916 ANGLE_TRY(flushDeferredClears(contextVk));
917
918 const gl::State &glState = contextVk->getState();
919 const gl::Framebuffer *srcFramebuffer = glState.getReadFramebuffer();
920 FramebufferVk *srcFramebufferVk = vk::GetImpl(srcFramebuffer);
921
922 const bool blitColorBuffer = (mask & GL_COLOR_BUFFER_BIT) != 0;
923 const bool blitDepthBuffer = (mask & GL_DEPTH_BUFFER_BIT) != 0;
924 const bool blitStencilBuffer = (mask & GL_STENCIL_BUFFER_BIT) != 0;
925
926 // If a framebuffer contains a mixture of multisampled and multisampled-render-to-texture
927 // attachments, this function could be simultaneously doing a blit on one attachment and resolve
928 // on another. For the most part, this means resolve semantics apply. However, as the resolve
929 // path cannot be taken for multisampled-render-to-texture attachments, the distinction of
930 // whether resolve is done for each attachment or blit is made.
931 const bool isColorResolve =
932 blitColorBuffer &&
933 srcFramebufferVk->getColorReadRenderTarget()->getImageForCopy().getSamples() > 1;
934 const bool isDepthStencilResolve =
935 (blitDepthBuffer || blitStencilBuffer) &&
936 srcFramebufferVk->getDepthStencilRenderTarget()->getImageForCopy().getSamples() > 1;
937 const bool isResolve = isColorResolve || isDepthStencilResolve;
938
939 bool srcFramebufferFlippedY = contextVk->isViewportFlipEnabledForReadFBO();
940 bool dstFramebufferFlippedY = contextVk->isViewportFlipEnabledForDrawFBO();
941
942 gl::Rectangle sourceArea = sourceAreaIn;
943 gl::Rectangle destArea = destAreaIn;
944
945 // Note: GLES (all 3.x versions) require source and destination area to be identical when
946 // resolving.
947 ASSERT(!isResolve ||
948 (sourceArea.x == destArea.x && sourceArea.y == destArea.y &&
949 sourceArea.width == destArea.width && sourceArea.height == destArea.height));
950
951 gl::Rectangle srcFramebufferDimensions = srcFramebufferVk->getNonRotatedCompleteRenderArea();
952 gl::Rectangle dstFramebufferDimensions = getNonRotatedCompleteRenderArea();
953
954 // If the destination is flipped in either direction, we will flip the source instead so that
955 // the destination area is always unflipped.
956 sourceArea = sourceArea.flip(destArea.isReversedX(), destArea.isReversedY());
957 destArea = destArea.removeReversal();
958
959 // Calculate the stretch factor prior to any clipping, as it needs to remain constant.
960 const double stretch[2] = {
961 std::abs(sourceArea.width / static_cast<double>(destArea.width)),
962 std::abs(sourceArea.height / static_cast<double>(destArea.height)),
963 };
964
965 // Potentially make adjustments for pre-rotatation. To handle various cases (e.g. clipping)
966 // and to not interrupt the normal flow of the code, different adjustments are made in
967 // different parts of the code. These first adjustments are for whether or not to flip the
968 // y-axis, and to note the overall rotation (regardless of whether it is the source or
969 // destination that is rotated).
970 SurfaceRotation srcFramebufferRotation = contextVk->getRotationReadFramebuffer();
971 SurfaceRotation dstFramebufferRotation = contextVk->getRotationDrawFramebuffer();
972 SurfaceRotation rotation = SurfaceRotation::Identity;
973 // Both the source and destination cannot be rotated (which would indicate both are the default
974 // framebuffer (i.e. swapchain image).
975 ASSERT((srcFramebufferRotation == SurfaceRotation::Identity) ||
976 (dstFramebufferRotation == SurfaceRotation::Identity));
977 EarlyAdjustFlipYForPreRotation(srcFramebufferRotation, &rotation, &srcFramebufferFlippedY);
978 EarlyAdjustFlipYForPreRotation(dstFramebufferRotation, &rotation, &dstFramebufferFlippedY);
979
980 // First, clip the source area to framebuffer. That requires transforming the destination area
981 // to match the clipped source.
982 gl::Rectangle absSourceArea = sourceArea.removeReversal();
983 gl::Rectangle clippedSourceArea;
984 if (!gl::ClipRectangle(srcFramebufferDimensions, absSourceArea, &clippedSourceArea))
985 {
986 return angle::Result::Continue;
987 }
988
989 // Resize the destination area based on the new size of source. Note again that stretch is
990 // calculated as SrcDimension/DestDimension.
991 gl::Rectangle srcClippedDestArea;
992 if (isResolve)
993 {
994 // Source and destination areas are identical in resolve (except rotate it, if appropriate).
995 srcClippedDestArea = clippedSourceArea;
996 AdjustBlitAreaForPreRotation(dstFramebufferRotation, clippedSourceArea,
997 dstFramebufferDimensions, &srcClippedDestArea);
998 }
999 else if (clippedSourceArea == absSourceArea)
1000 {
1001 // If there was no clipping, keep destination area as is (except rotate it, if appropriate).
1002 srcClippedDestArea = destArea;
1003 AdjustBlitAreaForPreRotation(dstFramebufferRotation, destArea, dstFramebufferDimensions,
1004 &srcClippedDestArea);
1005 }
1006 else
1007 {
1008 // Shift destination area's x0,y0,x1,y1 by as much as the source area's got shifted (taking
1009 // stretching into account). Note that double is used as float doesn't have enough
1010 // precision near the end of int range.
1011 double x0Shift = std::round((clippedSourceArea.x - absSourceArea.x) / stretch[0]);
1012 double y0Shift = std::round((clippedSourceArea.y - absSourceArea.y) / stretch[1]);
1013 double x1Shift = std::round((absSourceArea.x1() - clippedSourceArea.x1()) / stretch[0]);
1014 double y1Shift = std::round((absSourceArea.y1() - clippedSourceArea.y1()) / stretch[1]);
1015
1016 // If the source area was reversed in any direction, the shift should be applied in the
1017 // opposite direction as well.
1018 if (sourceArea.isReversedX())
1019 {
1020 std::swap(x0Shift, x1Shift);
1021 }
1022
1023 if (sourceArea.isReversedY())
1024 {
1025 std::swap(y0Shift, y1Shift);
1026 }
1027
1028 srcClippedDestArea.x = destArea.x0() + static_cast<int>(x0Shift);
1029 srcClippedDestArea.y = destArea.y0() + static_cast<int>(y0Shift);
1030 int x1 = destArea.x1() - static_cast<int>(x1Shift);
1031 int y1 = destArea.y1() - static_cast<int>(y1Shift);
1032
1033 srcClippedDestArea.width = x1 - srcClippedDestArea.x;
1034 srcClippedDestArea.height = y1 - srcClippedDestArea.y;
1035
1036 // Rotate srcClippedDestArea if the destination is rotated
1037 if (dstFramebufferRotation != SurfaceRotation::Identity)
1038 {
1039 gl::Rectangle originalSrcClippedDestArea = srcClippedDestArea;
1040 AdjustBlitAreaForPreRotation(dstFramebufferRotation, originalSrcClippedDestArea,
1041 dstFramebufferDimensions, &srcClippedDestArea);
1042 }
1043 }
1044
1045 // If framebuffers are flipped in Y, flip the source and destination area (which define the
1046 // transformation regardless of clipping), as well as the blit area (which is the clipped
1047 // destination area).
1048 if (srcFramebufferFlippedY)
1049 {
1050 sourceArea.y = srcFramebufferDimensions.height - sourceArea.y;
1051 sourceArea.height = -sourceArea.height;
1052 }
1053 if (dstFramebufferFlippedY)
1054 {
1055 destArea.y = dstFramebufferDimensions.height - destArea.y;
1056 destArea.height = -destArea.height;
1057
1058 srcClippedDestArea.y =
1059 dstFramebufferDimensions.height - srcClippedDestArea.y - srcClippedDestArea.height;
1060 }
1061
1062 bool flipX = sourceArea.isReversedX() != destArea.isReversedX();
1063 bool flipY = sourceArea.isReversedY() != destArea.isReversedY();
1064
1065 // GLES doesn't allow flipping the parameters of glBlitFramebuffer if performing a resolve.
1066 ASSERT(!isResolve ||
1067 (flipX == false && flipY == (srcFramebufferFlippedY != dstFramebufferFlippedY)));
1068
1069 // Again, transfer the destination flip to source, so destination is unflipped. Note that
1070 // destArea was not reversed until the final possible Y-flip.
1071 ASSERT(!destArea.isReversedX());
1072 sourceArea = sourceArea.flip(false, destArea.isReversedY());
1073 destArea = destArea.removeReversal();
1074
1075 // Now that clipping and flipping is done, rotate certain values that will be used for
1076 // UtilsVk::BlitResolveParameters
1077 gl::Rectangle sourceAreaOld = sourceArea;
1078 gl::Rectangle destAreaOld = destArea;
1079 if (srcFramebufferRotation == rotation)
1080 {
1081 AdjustBlitAreaForPreRotation(srcFramebufferRotation, sourceAreaOld,
1082 srcFramebufferDimensions, &sourceArea);
1083 AdjustDimensionsAndFlipForPreRotation(srcFramebufferRotation, &srcFramebufferDimensions,
1084 &flipX, &flipY);
1085 }
1086 SurfaceRotation rememberDestFramebufferRotation = dstFramebufferRotation;
1087 if (srcFramebufferRotation == SurfaceRotation::Rotated90Degrees)
1088 {
1089 dstFramebufferRotation = rotation;
1090 }
1091 AdjustBlitAreaForPreRotation(dstFramebufferRotation, destAreaOld, dstFramebufferDimensions,
1092 &destArea);
1093 dstFramebufferRotation = rememberDestFramebufferRotation;
1094
1095 // Clip the destination area to the framebuffer size and scissor. Note that we don't care
1096 // about the source area anymore. The offset translation is done based on the original source
1097 // and destination rectangles. The stretch factor is already calculated as well.
1098 gl::Rectangle blitArea;
1099 if (!gl::ClipRectangle(getRotatedScissoredRenderArea(contextVk), srcClippedDestArea, &blitArea))
1100 {
1101 return angle::Result::Continue;
1102 }
1103
1104 bool noClip = blitArea == destArea && stretch[0] == 1.0f && stretch[1] == 1.0f;
1105 bool noFlip = !flipX && !flipY;
1106 bool disableFlippingBlitWithCommand =
1107 contextVk->getRenderer()->getFeatures().disableFlippingBlitWithCommand.enabled;
1108
1109 UtilsVk::BlitResolveParameters commonParams;
1110 commonParams.srcOffset[0] = sourceArea.x;
1111 commonParams.srcOffset[1] = sourceArea.y;
1112 commonParams.dstOffset[0] = destArea.x;
1113 commonParams.dstOffset[1] = destArea.y;
1114 commonParams.rotatedOffsetFactor[0] = std::abs(sourceArea.width);
1115 commonParams.rotatedOffsetFactor[1] = std::abs(sourceArea.height);
1116 commonParams.stretch[0] = static_cast<float>(stretch[0]);
1117 commonParams.stretch[1] = static_cast<float>(stretch[1]);
1118 commonParams.srcExtents[0] = srcFramebufferDimensions.width;
1119 commonParams.srcExtents[1] = srcFramebufferDimensions.height;
1120 commonParams.blitArea = blitArea;
1121 commonParams.linear = filter == GL_LINEAR;
1122 commonParams.flipX = flipX;
1123 commonParams.flipY = flipY;
1124 commonParams.rotation = rotation;
1125
1126 if (blitColorBuffer)
1127 {
1128 RenderTargetVk *readRenderTarget = srcFramebufferVk->getColorReadRenderTarget();
1129 UtilsVk::BlitResolveParameters params = commonParams;
1130 params.srcLayer = readRenderTarget->getLayerIndex();
1131
1132 // Multisampled images are not allowed to have mips.
1133 ASSERT(!isColorResolve || readRenderTarget->getLevelIndex() == gl::LevelIndex(0));
1134
1135 // If there was no clipping and the format capabilities allow us, use Vulkan's builtin blit.
1136 // The reason clipping is prohibited in this path is that due to rounding errors, it would
1137 // be hard to guarantee the image stretching remains perfect. That also allows us not to
1138 // have to transform back the destination clipping to source.
1139 //
1140 // Non-identity pre-rotation cases do not use Vulkan's builtin blit.
1141 //
1142 // For simplicity, we either blit all render targets with a Vulkan command, or none.
1143 bool canBlitWithCommand =
1144 !isColorResolve && noClip && (noFlip || !disableFlippingBlitWithCommand) &&
1145 HasSrcBlitFeature(renderer, readRenderTarget) && rotation == SurfaceRotation::Identity;
1146 // If we need to reinterpret the colorspace then the blit must be done through a shader
1147 bool reinterpretsColorspace =
1148 mCurrentFramebufferDesc.getWriteControlMode() != gl::SrgbWriteControlMode::Default;
1149 bool areChannelsBlitCompatible = true;
1150 bool areFormatsIdentical = true;
1151 for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
1152 {
1153 RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL];
1154 canBlitWithCommand =
1155 canBlitWithCommand && HasDstBlitFeature(renderer, drawRenderTarget);
1156 areChannelsBlitCompatible =
1157 areChannelsBlitCompatible &&
1158 AreSrcAndDstColorChannelsBlitCompatible(readRenderTarget, drawRenderTarget);
1159 areFormatsIdentical = AreSrcAndDstFormatsIdentical(readRenderTarget, drawRenderTarget);
1160 }
1161
1162 // Now that all flipping is done, adjust the offsets for resolve and prerotation
1163 if (isColorResolve)
1164 {
1165 AdjustBlitResolveParametersForResolve(sourceArea, destArea, ¶ms);
1166 }
1167 AdjustBlitResolveParametersForPreRotation(rotation, srcFramebufferRotation, ¶ms);
1168
1169 if (canBlitWithCommand && areChannelsBlitCompatible && !reinterpretsColorspace)
1170 {
1171 for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
1172 {
1173 RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL];
1174 ANGLE_TRY(blitWithCommand(contextVk, sourceArea, destArea, readRenderTarget,
1175 drawRenderTarget, filter, true, false, false, flipX,
1176 flipY));
1177 }
1178 }
1179 // If we're not flipping or rotating, use Vulkan's builtin resolve.
1180 else if (isColorResolve && !flipX && !flipY && areChannelsBlitCompatible &&
1181 areFormatsIdentical && rotation == SurfaceRotation::Identity &&
1182 !reinterpretsColorspace)
1183 {
1184 // Resolving with a subpass resolve attachment has a few restrictions:
1185 // 1.) glBlitFramebuffer() needs to copy the read color attachment to all enabled
1186 // attachments in the draw framebuffer, but Vulkan requires a 1:1 relationship for
1187 // multisample attachments to resolve attachments in the render pass subpass.
1188 // Due to this, we currently only support using resolve attachments when there is a
1189 // single draw attachment enabled.
1190 // 2.) Using a subpass resolve attachment relies on using the render pass that performs
1191 // the draw to still be open, so it can be updated to use the resolve attachment to draw
1192 // into. If there's no render pass with commands, then the multisampled render pass is
1193 // already done and whose data is already flushed from the tile (in a tile-based
1194 // renderer), so there's no chance for the resolve attachment to take advantage of the
1195 // data already being present in the tile.
1196 vk::Framebuffer *srcVkFramebuffer = nullptr;
1197 ANGLE_TRY(srcFramebufferVk->getFramebuffer(contextVk, &srcVkFramebuffer, nullptr,
1198 SwapchainResolveMode::Disabled));
1199
1200 // TODO(https://anglebug.com/4968): Support multiple open render passes so we can remove
1201 // this hack to 'restore' the finished render pass.
1202 contextVk->restoreFinishedRenderPass(srcVkFramebuffer);
1203
1204 // glBlitFramebuffer() needs to copy the read color attachment to all enabled
1205 // attachments in the draw framebuffer, but Vulkan requires a 1:1 relationship for
1206 // multisample attachments to resolve attachments in the render pass subpass. Due to
1207 // this, we currently only support using resolve attachments when there is a single draw
1208 // attachment enabled.
1209 bool canResolveWithSubpass =
1210 mState.getEnabledDrawBuffers().count() == 1 &&
1211 mCurrentFramebufferDesc.getLayerCount() == 1 &&
1212 contextVk->hasStartedRenderPassWithFramebuffer(srcVkFramebuffer);
1213
1214 // Additionally, when resolving with a resolve attachment, the src and destination
1215 // offsets must match, the render area must match the resolve area, and there should be
1216 // no flipping or rotation. Fortunately, in GLES the blit source and destination areas
1217 // are already required to be identical.
1218 ASSERT(params.srcOffset[0] == params.dstOffset[0] &&
1219 params.srcOffset[1] == params.dstOffset[1]);
1220 canResolveWithSubpass =
1221 canResolveWithSubpass && noFlip && rotation == SurfaceRotation::Identity &&
1222 blitArea == contextVk->getStartedRenderPassCommands().getRenderArea();
1223
1224 if (canResolveWithSubpass)
1225 {
1226 ANGLE_TRY(resolveColorWithSubpass(contextVk, params));
1227 }
1228 else
1229 {
1230 ANGLE_TRY(resolveColorWithCommand(contextVk, params,
1231 &readRenderTarget->getImageForCopy()));
1232 }
1233 }
1234 // Otherwise use a shader to do blit or resolve.
1235 else
1236 {
1237 // Flush the render pass, which may incur a vkQueueSubmit, before taking any views.
1238 // Otherwise the view serials would not reflect the render pass they are really used in.
1239 // http://crbug.com/1272266#c22
1240 ANGLE_TRY(
1241 contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::PrepareForBlit));
1242
1243 const vk::ImageView *copyImageView = nullptr;
1244 ANGLE_TRY(readRenderTarget->getCopyImageView(contextVk, ©ImageView));
1245 ANGLE_TRY(utilsVk.colorBlitResolve(
1246 contextVk, this, &readRenderTarget->getImageForCopy(), copyImageView, params));
1247 }
1248 }
1249
1250 if (blitDepthBuffer || blitStencilBuffer)
1251 {
1252 RenderTargetVk *readRenderTarget = srcFramebufferVk->getDepthStencilRenderTarget();
1253 RenderTargetVk *drawRenderTarget = mRenderTargetCache.getDepthStencil();
1254 UtilsVk::BlitResolveParameters params = commonParams;
1255 params.srcLayer = readRenderTarget->getLayerIndex();
1256
1257 // Multisampled images are not allowed to have mips.
1258 ASSERT(!isDepthStencilResolve || readRenderTarget->getLevelIndex() == gl::LevelIndex(0));
1259
1260 // Similarly, only blit if there's been no clipping or rotating.
1261 bool canBlitWithCommand =
1262 !isDepthStencilResolve && noClip && (noFlip || !disableFlippingBlitWithCommand) &&
1263 HasSrcBlitFeature(renderer, readRenderTarget) &&
1264 HasDstBlitFeature(renderer, drawRenderTarget) && rotation == SurfaceRotation::Identity;
1265 bool areChannelsBlitCompatible =
1266 AreSrcAndDstDepthStencilChannelsBlitCompatible(readRenderTarget, drawRenderTarget);
1267
1268 // glBlitFramebuffer requires that depth/stencil blits have matching formats.
1269 ASSERT(AreSrcAndDstFormatsIdentical(readRenderTarget, drawRenderTarget));
1270
1271 if (canBlitWithCommand && areChannelsBlitCompatible)
1272 {
1273 ANGLE_TRY(blitWithCommand(contextVk, sourceArea, destArea, readRenderTarget,
1274 drawRenderTarget, filter, false, blitDepthBuffer,
1275 blitStencilBuffer, flipX, flipY));
1276 }
1277 else
1278 {
1279 // Now that all flipping is done, adjust the offsets for resolve and prerotation
1280 if (isDepthStencilResolve)
1281 {
1282 AdjustBlitResolveParametersForResolve(sourceArea, destArea, ¶ms);
1283 }
1284 AdjustBlitResolveParametersForPreRotation(rotation, srcFramebufferRotation, ¶ms);
1285
1286 // Create depth- and stencil-only views for reading.
1287 vk::DeviceScoped<vk::ImageView> depthView(contextVk->getDevice());
1288 vk::DeviceScoped<vk::ImageView> stencilView(contextVk->getDevice());
1289
1290 vk::ImageHelper *depthStencilImage = &readRenderTarget->getImageForCopy();
1291 vk::LevelIndex levelIndex =
1292 depthStencilImage->toVkLevel(readRenderTarget->getLevelIndex());
1293 uint32_t layerIndex = readRenderTarget->getLayerIndex();
1294 gl::TextureType textureType = vk::Get2DTextureType(depthStencilImage->getLayerCount(),
1295 depthStencilImage->getSamples());
1296
1297 if (blitDepthBuffer)
1298 {
1299 ANGLE_TRY(depthStencilImage->initLayerImageView(
1300 contextVk, textureType, VK_IMAGE_ASPECT_DEPTH_BIT, gl::SwizzleState(),
1301 &depthView.get(), levelIndex, 1, layerIndex, 1,
1302 gl::SrgbWriteControlMode::Default));
1303 }
1304
1305 if (blitStencilBuffer)
1306 {
1307 ANGLE_TRY(depthStencilImage->initLayerImageView(
1308 contextVk, textureType, VK_IMAGE_ASPECT_STENCIL_BIT, gl::SwizzleState(),
1309 &stencilView.get(), levelIndex, 1, layerIndex, 1,
1310 gl::SrgbWriteControlMode::Default));
1311 }
1312
1313 // If shader stencil export is not possible, defer stencil blit/stencil to another pass.
1314 bool hasShaderStencilExport =
1315 contextVk->getRenderer()->getFeatures().supportsShaderStencilExport.enabled;
1316
1317 // Blit depth. If shader stencil export is present, blit stencil as well.
1318 if (blitDepthBuffer || (blitStencilBuffer && hasShaderStencilExport))
1319 {
1320 const vk::ImageView *depth = blitDepthBuffer ? &depthView.get() : nullptr;
1321 const vk::ImageView *stencil =
1322 blitStencilBuffer && hasShaderStencilExport ? &stencilView.get() : nullptr;
1323
1324 ANGLE_TRY(utilsVk.depthStencilBlitResolve(contextVk, this, depthStencilImage, depth,
1325 stencil, params));
1326 }
1327
1328 // If shader stencil export is not present, blit stencil through a different path.
1329 if (blitStencilBuffer && !hasShaderStencilExport)
1330 {
1331 ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_LOW,
1332 "Inefficient BlitFramebuffer operation on the stencil aspect "
1333 "due to lack of shader stencil export support");
1334 ANGLE_TRY(utilsVk.stencilBlitResolveNoShaderExport(
1335 contextVk, this, depthStencilImage, &stencilView.get(), params));
1336 }
1337
1338 vk::ImageView depthViewObject = depthView.release();
1339 vk::ImageView stencilViewObject = stencilView.release();
1340
1341 contextVk->addGarbage(&depthViewObject);
1342 contextVk->addGarbage(&stencilViewObject);
1343 }
1344 }
1345
1346 return angle::Result::Continue;
1347 }
1348
updateColorResolveAttachment(uint32_t colorIndexGL,vk::ImageOrBufferViewSubresourceSerial resolveImageViewSerial)1349 void FramebufferVk::updateColorResolveAttachment(
1350 uint32_t colorIndexGL,
1351 vk::ImageOrBufferViewSubresourceSerial resolveImageViewSerial)
1352 {
1353 mCurrentFramebufferDesc.updateColorResolve(colorIndexGL, resolveImageViewSerial);
1354 mFramebuffer = nullptr;
1355 mRenderPassDesc.packColorResolveAttachment(colorIndexGL);
1356 }
1357
removeColorResolveAttachment(uint32_t colorIndexGL)1358 void FramebufferVk::removeColorResolveAttachment(uint32_t colorIndexGL)
1359 {
1360 mCurrentFramebufferDesc.updateColorResolve(colorIndexGL,
1361 vk::kInvalidImageOrBufferViewSubresourceSerial);
1362 mFramebuffer = nullptr;
1363 mRenderPassDesc.removeColorResolveAttachment(colorIndexGL);
1364 }
1365
updateLayerCount()1366 void FramebufferVk::updateLayerCount()
1367 {
1368 uint32_t layerCount = std::numeric_limits<uint32_t>::max();
1369
1370 // Color attachments.
1371 const auto &colorRenderTargets = mRenderTargetCache.getColors();
1372 for (size_t colorIndexGL : mState.getColorAttachmentsMask())
1373 {
1374 RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
1375 ASSERT(colorRenderTarget);
1376 layerCount = std::min(layerCount, colorRenderTarget->getLayerCount());
1377 }
1378
1379 // Depth/stencil attachment.
1380 RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget();
1381 if (depthStencilRenderTarget)
1382 {
1383 layerCount = std::min(layerCount, depthStencilRenderTarget->getLayerCount());
1384 }
1385
1386 if (layerCount == std::numeric_limits<uint32_t>::max())
1387 {
1388 layerCount = mState.getDefaultLayers();
1389 }
1390
1391 // While layer count and view count are mutually exclusive, they result in different render
1392 // passes (and thus framebuffers). For multiview, layer count is set to view count and a flag
1393 // signifies that the framebuffer is multiview (as opposed to layered).
1394 const bool isMultiview = mState.isMultiview();
1395 if (isMultiview)
1396 {
1397 layerCount = mState.getNumViews();
1398 }
1399
1400 mCurrentFramebufferDesc.updateLayerCount(layerCount);
1401 mCurrentFramebufferDesc.updateIsMultiview(isMultiview);
1402 }
1403
resolveColorWithSubpass(ContextVk * contextVk,const UtilsVk::BlitResolveParameters & params)1404 angle::Result FramebufferVk::resolveColorWithSubpass(ContextVk *contextVk,
1405 const UtilsVk::BlitResolveParameters ¶ms)
1406 {
1407 // Vulkan requires a 1:1 relationship for multisample attachments to resolve attachments in the
1408 // render pass subpass. Due to this, we currently only support using resolve attachments when
1409 // there is a single draw attachment enabled.
1410 ASSERT(mState.getEnabledDrawBuffers().count() == 1);
1411 uint32_t drawColorIndexGL = static_cast<uint32_t>(*mState.getEnabledDrawBuffers().begin());
1412
1413 const gl::State &glState = contextVk->getState();
1414 const gl::Framebuffer *srcFramebuffer = glState.getReadFramebuffer();
1415 FramebufferVk *srcFramebufferVk = vk::GetImpl(srcFramebuffer);
1416 uint32_t readColorIndexGL = srcFramebuffer->getState().getReadIndex();
1417
1418 // Use the draw FBO's color attachments as resolve attachments in the read FBO.
1419 // - Assign the draw FBO's color attachment Serial to the read FBO's resolve attachment
1420 // - Deactivate the source Framebuffer, since the description changed
1421 // - Update the renderpass description to indicate there's a resolve attachment
1422 vk::ImageOrBufferViewSubresourceSerial resolveImageViewSerial =
1423 mCurrentFramebufferDesc.getColorImageViewSerial(drawColorIndexGL);
1424 ASSERT(resolveImageViewSerial.viewSerial.valid());
1425 srcFramebufferVk->updateColorResolveAttachment(readColorIndexGL, resolveImageViewSerial);
1426
1427 // Since the source FBO was updated with a resolve attachment it didn't have when the render
1428 // pass was started, we need to:
1429 // 1. Get the new framebuffer
1430 // - The draw framebuffer's ImageView will be used as the resolve attachment, so pass it along
1431 // in case vkCreateFramebuffer() needs to be called to create a new vkFramebuffer with the new
1432 // resolve attachment.
1433 RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[drawColorIndexGL];
1434 const vk::ImageView *resolveImageView = nullptr;
1435 ANGLE_TRY(drawRenderTarget->getImageView(contextVk, &resolveImageView));
1436 vk::Framebuffer *newSrcFramebuffer = nullptr;
1437 ANGLE_TRY(srcFramebufferVk->getFramebuffer(contextVk, &newSrcFramebuffer, resolveImageView,
1438 SwapchainResolveMode::Disabled));
1439 // 2. Update the RenderPassCommandBufferHelper with the new framebuffer and render pass
1440 vk::RenderPassCommandBufferHelper &commandBufferHelper =
1441 contextVk->getStartedRenderPassCommands();
1442 commandBufferHelper.updateRenderPassForResolve(contextVk, newSrcFramebuffer,
1443 srcFramebufferVk->getRenderPassDesc());
1444
1445 // End the render pass now since we don't (yet) support subpass dependencies.
1446 drawRenderTarget->onColorResolve(contextVk, mCurrentFramebufferDesc.getLayerCount());
1447 ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(
1448 RenderPassClosureReason::AlreadySpecifiedElsewhere));
1449
1450 // Remove the resolve attachment from the source framebuffer.
1451 srcFramebufferVk->removeColorResolveAttachment(readColorIndexGL);
1452
1453 return angle::Result::Continue;
1454 }
1455
resolveColorWithCommand(ContextVk * contextVk,const UtilsVk::BlitResolveParameters & params,vk::ImageHelper * srcImage)1456 angle::Result FramebufferVk::resolveColorWithCommand(ContextVk *contextVk,
1457 const UtilsVk::BlitResolveParameters ¶ms,
1458 vk::ImageHelper *srcImage)
1459 {
1460 vk::CommandBufferAccess access;
1461 access.onImageTransferRead(VK_IMAGE_ASPECT_COLOR_BIT, srcImage);
1462
1463 for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
1464 {
1465 RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL];
1466 vk::ImageHelper &dstImage = drawRenderTarget->getImageForWrite();
1467
1468 access.onImageTransferWrite(drawRenderTarget->getLevelIndex(), 1,
1469 drawRenderTarget->getLayerIndex(), 1, VK_IMAGE_ASPECT_COLOR_BIT,
1470 &dstImage);
1471 }
1472
1473 vk::OutsideRenderPassCommandBuffer *commandBuffer;
1474 ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
1475
1476 VkImageResolve resolveRegion = {};
1477 resolveRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1478 resolveRegion.srcSubresource.mipLevel = 0;
1479 resolveRegion.srcSubresource.baseArrayLayer = params.srcLayer;
1480 resolveRegion.srcSubresource.layerCount = 1;
1481 resolveRegion.srcOffset.x = params.blitArea.x;
1482 resolveRegion.srcOffset.y = params.blitArea.y;
1483 resolveRegion.srcOffset.z = 0;
1484 resolveRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1485 resolveRegion.dstSubresource.layerCount = 1;
1486 resolveRegion.dstOffset.x = params.blitArea.x;
1487 resolveRegion.dstOffset.y = params.blitArea.y;
1488 resolveRegion.dstOffset.z = 0;
1489 resolveRegion.extent.width = params.blitArea.width;
1490 resolveRegion.extent.height = params.blitArea.height;
1491 resolveRegion.extent.depth = 1;
1492
1493 angle::VulkanPerfCounters &perfCounters = contextVk->getPerfCounters();
1494 for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
1495 {
1496 RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL];
1497 vk::ImageHelper &dstImage = drawRenderTarget->getImageForWrite();
1498
1499 vk::LevelIndex levelVk = dstImage.toVkLevel(drawRenderTarget->getLevelIndex());
1500 resolveRegion.dstSubresource.mipLevel = levelVk.get();
1501 resolveRegion.dstSubresource.baseArrayLayer = drawRenderTarget->getLayerIndex();
1502
1503 srcImage->resolve(&dstImage, resolveRegion, commandBuffer);
1504
1505 perfCounters.resolveImageCommands++;
1506 }
1507
1508 return angle::Result::Continue;
1509 }
1510
checkStatus(const gl::Context * context) const1511 gl::FramebufferStatus FramebufferVk::checkStatus(const gl::Context *context) const
1512 {
1513 // if we have both a depth and stencil buffer, they must refer to the same object
1514 // since we only support packed_depth_stencil and not separate depth and stencil
1515 if (mState.hasSeparateDepthAndStencilAttachments())
1516 {
1517 return gl::FramebufferStatus::Incomplete(
1518 GL_FRAMEBUFFER_UNSUPPORTED,
1519 gl::err::kFramebufferIncompleteUnsupportedSeparateDepthStencilBuffers);
1520 }
1521
1522 return gl::FramebufferStatus::Complete();
1523 }
1524
invalidateImpl(ContextVk * contextVk,size_t count,const GLenum * attachments,bool isSubInvalidate,const gl::Rectangle & invalidateArea)1525 angle::Result FramebufferVk::invalidateImpl(ContextVk *contextVk,
1526 size_t count,
1527 const GLenum *attachments,
1528 bool isSubInvalidate,
1529 const gl::Rectangle &invalidateArea)
1530 {
1531 gl::DrawBufferMask invalidateColorBuffers;
1532 bool invalidateDepthBuffer = false;
1533 bool invalidateStencilBuffer = false;
1534
1535 for (size_t i = 0; i < count; ++i)
1536 {
1537 const GLenum attachment = attachments[i];
1538
1539 switch (attachment)
1540 {
1541 case GL_DEPTH:
1542 case GL_DEPTH_ATTACHMENT:
1543 invalidateDepthBuffer = true;
1544 break;
1545 case GL_STENCIL:
1546 case GL_STENCIL_ATTACHMENT:
1547 invalidateStencilBuffer = true;
1548 break;
1549 case GL_DEPTH_STENCIL_ATTACHMENT:
1550 invalidateDepthBuffer = true;
1551 invalidateStencilBuffer = true;
1552 break;
1553 default:
1554 ASSERT(
1555 (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15) ||
1556 (attachment == GL_COLOR));
1557
1558 invalidateColorBuffers.set(
1559 attachment == GL_COLOR ? 0u : (attachment - GL_COLOR_ATTACHMENT0));
1560 }
1561 }
1562
1563 // Shouldn't try to issue deferred clears if invalidating sub framebuffer.
1564 ASSERT(mDeferredClears.empty() || !isSubInvalidate);
1565
1566 // Remove deferred clears for the invalidated attachments.
1567 if (invalidateDepthBuffer)
1568 {
1569 mDeferredClears.reset(vk::kUnpackedDepthIndex);
1570 }
1571 if (invalidateStencilBuffer)
1572 {
1573 mDeferredClears.reset(vk::kUnpackedStencilIndex);
1574 }
1575 for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
1576 {
1577 if (invalidateColorBuffers.test(colorIndexGL))
1578 {
1579 mDeferredClears.reset(colorIndexGL);
1580 }
1581 }
1582
1583 // If there are still deferred clears, redefer them. See relevant comment in invalidateSub.
1584 redeferClears(contextVk);
1585
1586 const auto &colorRenderTargets = mRenderTargetCache.getColors();
1587 RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil();
1588
1589 // If not a partial invalidate, mark the contents of the invalidated attachments as undefined,
1590 // so their loadOp can be set to DONT_CARE in the following render pass.
1591 if (!isSubInvalidate)
1592 {
1593 for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
1594 {
1595 if (invalidateColorBuffers.test(colorIndexGL))
1596 {
1597 RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
1598 ASSERT(colorRenderTarget);
1599
1600 bool preferToKeepContentsDefined = false;
1601 colorRenderTarget->invalidateEntireContent(contextVk, &preferToKeepContentsDefined);
1602 if (preferToKeepContentsDefined)
1603 {
1604 invalidateColorBuffers.reset(colorIndexGL);
1605 }
1606 }
1607 }
1608
1609 // If we have a depth / stencil render target, invalidate its aspects.
1610 if (depthStencilRenderTarget)
1611 {
1612 if (invalidateDepthBuffer)
1613 {
1614 bool preferToKeepContentsDefined = false;
1615 depthStencilRenderTarget->invalidateEntireContent(contextVk,
1616 &preferToKeepContentsDefined);
1617 if (preferToKeepContentsDefined)
1618 {
1619 invalidateDepthBuffer = false;
1620 }
1621 }
1622 if (invalidateStencilBuffer)
1623 {
1624 bool preferToKeepContentsDefined = false;
1625 depthStencilRenderTarget->invalidateEntireStencilContent(
1626 contextVk, &preferToKeepContentsDefined);
1627 if (preferToKeepContentsDefined)
1628 {
1629 invalidateStencilBuffer = false;
1630 }
1631 }
1632 }
1633 }
1634
1635 // To ensure we invalidate the right renderpass we require that the current framebuffer be the
1636 // same as the current renderpass' framebuffer. E.g. prevent sequence like:
1637 //- Bind FBO 1, draw
1638 //- Bind FBO 2, draw
1639 //- Bind FBO 1, invalidate D/S
1640 // to invalidate the D/S of FBO 2 since it would be the currently active renderpass.
1641 vk::Framebuffer *currentFramebuffer = nullptr;
1642 ANGLE_TRY(
1643 getFramebuffer(contextVk, ¤tFramebuffer, nullptr, SwapchainResolveMode::Disabled));
1644
1645 if (contextVk->hasStartedRenderPassWithFramebuffer(currentFramebuffer))
1646 {
1647 // Mark the invalidated attachments in the render pass for loadOp and storeOp determination
1648 // at its end.
1649 vk::PackedAttachmentIndex colorIndexVk(0);
1650 for (size_t colorIndexGL : mState.getColorAttachmentsMask())
1651 {
1652 if (mState.getEnabledDrawBuffers()[colorIndexGL] &&
1653 invalidateColorBuffers.test(colorIndexGL))
1654 {
1655 contextVk->getStartedRenderPassCommands().invalidateRenderPassColorAttachment(
1656 contextVk->getState(), colorIndexGL, colorIndexVk, invalidateArea);
1657 }
1658 ++colorIndexVk;
1659 }
1660
1661 if (depthStencilRenderTarget)
1662 {
1663 const gl::DepthStencilState &dsState = contextVk->getState().getDepthStencilState();
1664 if (invalidateDepthBuffer)
1665 {
1666 contextVk->getStartedRenderPassCommands().invalidateRenderPassDepthAttachment(
1667 dsState, invalidateArea);
1668 }
1669
1670 if (invalidateStencilBuffer)
1671 {
1672 contextVk->getStartedRenderPassCommands().invalidateRenderPassStencilAttachment(
1673 dsState, invalidateArea);
1674 }
1675 }
1676 if (invalidateColorBuffers.any())
1677 {
1678 // Only end the render pass if invalidating at least one color buffer. Do not end the
1679 // render pass if only the depth and/or stencil buffer is invalidated. At least one
1680 // application invalidates those every frame, disables depth, and then continues to
1681 // draw only to the color buffer.
1682 //
1683 // Since we are not aware of any application that invalidates a color buffer and
1684 // continues to draw to it, we leave that unoptimized.
1685 ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(
1686 RenderPassClosureReason::ColorBufferInvalidate));
1687 }
1688 }
1689
1690 return angle::Result::Continue;
1691 }
1692
updateColorAttachment(const gl::Context * context,uint32_t colorIndexGL)1693 angle::Result FramebufferVk::updateColorAttachment(const gl::Context *context,
1694 uint32_t colorIndexGL)
1695 {
1696 ANGLE_TRY(mRenderTargetCache.updateColorRenderTarget(context, mState, colorIndexGL));
1697
1698 // Update cached masks for masked clears.
1699 RenderTargetVk *renderTarget = mRenderTargetCache.getColors()[colorIndexGL];
1700 if (renderTarget)
1701 {
1702 const angle::Format &actualFormat = renderTarget->getImageActualFormat();
1703 updateActiveColorMasks(colorIndexGL, actualFormat.redBits > 0, actualFormat.greenBits > 0,
1704 actualFormat.blueBits > 0, actualFormat.alphaBits > 0);
1705
1706 const angle::Format &intendedFormat = renderTarget->getImageIntendedFormat();
1707 mEmulatedAlphaAttachmentMask.set(
1708 colorIndexGL, intendedFormat.alphaBits == 0 && actualFormat.alphaBits > 0);
1709 }
1710 else
1711 {
1712 updateActiveColorMasks(colorIndexGL, false, false, false, false);
1713 }
1714
1715 const bool enabledColor =
1716 renderTarget && mState.getColorAttachments()[colorIndexGL].isAttached();
1717 const bool enabledResolve = enabledColor && renderTarget->hasResolveAttachment();
1718
1719 if (enabledColor)
1720 {
1721 mCurrentFramebufferDesc.updateColor(colorIndexGL, renderTarget->getDrawSubresourceSerial());
1722 }
1723 else
1724 {
1725 mCurrentFramebufferDesc.updateColor(colorIndexGL,
1726 vk::kInvalidImageOrBufferViewSubresourceSerial);
1727 }
1728
1729 if (enabledResolve)
1730 {
1731 mCurrentFramebufferDesc.updateColorResolve(colorIndexGL,
1732 renderTarget->getResolveSubresourceSerial());
1733 }
1734 else
1735 {
1736 mCurrentFramebufferDesc.updateColorResolve(colorIndexGL,
1737 vk::kInvalidImageOrBufferViewSubresourceSerial);
1738 }
1739
1740 return angle::Result::Continue;
1741 }
1742
updateDepthStencilAttachment(const gl::Context * context)1743 angle::Result FramebufferVk::updateDepthStencilAttachment(const gl::Context *context)
1744 {
1745 ANGLE_TRY(mRenderTargetCache.updateDepthStencilRenderTarget(context, mState));
1746
1747 ContextVk *contextVk = vk::GetImpl(context);
1748 updateDepthStencilAttachmentSerial(contextVk);
1749
1750 return angle::Result::Continue;
1751 }
1752
updateDepthStencilAttachmentSerial(ContextVk * contextVk)1753 void FramebufferVk::updateDepthStencilAttachmentSerial(ContextVk *contextVk)
1754 {
1755 RenderTargetVk *depthStencilRT = getDepthStencilRenderTarget();
1756
1757 if (depthStencilRT != nullptr)
1758 {
1759 mCurrentFramebufferDesc.updateDepthStencil(depthStencilRT->getDrawSubresourceSerial());
1760 }
1761 else
1762 {
1763 mCurrentFramebufferDesc.updateDepthStencil(vk::kInvalidImageOrBufferViewSubresourceSerial);
1764 }
1765
1766 if (depthStencilRT != nullptr && depthStencilRT->hasResolveAttachment())
1767 {
1768 mCurrentFramebufferDesc.updateDepthStencilResolve(
1769 depthStencilRT->getResolveSubresourceSerial());
1770 }
1771 else
1772 {
1773 mCurrentFramebufferDesc.updateDepthStencilResolve(
1774 vk::kInvalidImageOrBufferViewSubresourceSerial);
1775 }
1776 }
1777
flushColorAttachmentUpdates(const gl::Context * context,bool deferClears,uint32_t colorIndexGL)1778 angle::Result FramebufferVk::flushColorAttachmentUpdates(const gl::Context *context,
1779 bool deferClears,
1780 uint32_t colorIndexGL)
1781 {
1782 ContextVk *contextVk = vk::GetImpl(context);
1783 RenderTargetVk *readRenderTarget = nullptr;
1784 RenderTargetVk *drawRenderTarget = nullptr;
1785
1786 // It's possible for the read and draw color attachments to be different if different surfaces
1787 // are bound, so we need to flush any staged updates to both.
1788
1789 // Draw
1790 drawRenderTarget = mRenderTargetCache.getColorDraw(mState, colorIndexGL);
1791 if (drawRenderTarget)
1792 {
1793 if (deferClears)
1794 {
1795 ANGLE_TRY(
1796 drawRenderTarget->flushStagedUpdates(contextVk, &mDeferredClears, colorIndexGL,
1797 mCurrentFramebufferDesc.getLayerCount()));
1798 }
1799 else
1800 {
1801 ANGLE_TRY(drawRenderTarget->flushStagedUpdates(
1802 contextVk, nullptr, 0, mCurrentFramebufferDesc.getLayerCount()));
1803 }
1804 }
1805
1806 // Read
1807 if (mState.getReadBufferState() != GL_NONE && mState.getReadIndex() == colorIndexGL)
1808 {
1809 // Flush staged updates to the read render target as well, but only if it's not the same as
1810 // the draw render target. This can happen when the read render target is bound to another
1811 // surface.
1812 readRenderTarget = mRenderTargetCache.getColorRead(mState);
1813 if (readRenderTarget && readRenderTarget != drawRenderTarget)
1814 {
1815 ANGLE_TRY(readRenderTarget->flushStagedUpdates(
1816 contextVk, nullptr, 0, mCurrentFramebufferDesc.getLayerCount()));
1817 }
1818 }
1819
1820 return angle::Result::Continue;
1821 }
1822
flushDepthStencilAttachmentUpdates(const gl::Context * context,bool deferClears)1823 angle::Result FramebufferVk::flushDepthStencilAttachmentUpdates(const gl::Context *context,
1824 bool deferClears)
1825 {
1826 ContextVk *contextVk = vk::GetImpl(context);
1827
1828 RenderTargetVk *depthStencilRT = getDepthStencilRenderTarget();
1829 if (depthStencilRT == nullptr)
1830 {
1831 return angle::Result::Continue;
1832 }
1833
1834 if (deferClears)
1835 {
1836 return depthStencilRT->flushStagedUpdates(contextVk, &mDeferredClears,
1837 vk::kUnpackedDepthIndex,
1838 mCurrentFramebufferDesc.getLayerCount());
1839 }
1840
1841 return depthStencilRT->flushStagedUpdates(contextVk, nullptr, 0,
1842 mCurrentFramebufferDesc.getLayerCount());
1843 }
1844
syncState(const gl::Context * context,GLenum binding,const gl::Framebuffer::DirtyBits & dirtyBits,gl::Command command)1845 angle::Result FramebufferVk::syncState(const gl::Context *context,
1846 GLenum binding,
1847 const gl::Framebuffer::DirtyBits &dirtyBits,
1848 gl::Command command)
1849 {
1850 ContextVk *contextVk = vk::GetImpl(context);
1851
1852 vk::FramebufferDesc priorFramebufferDesc = mCurrentFramebufferDesc;
1853
1854 // Keep track of which attachments have dirty content and need their staged updates flushed.
1855 // The respective functions depend on |mCurrentFramebufferDesc::mLayerCount| which is updated
1856 // after all attachment render targets are updated.
1857 gl::DrawBufferMask dirtyColorAttachments;
1858 bool dirtyDepthStencilAttachment = false;
1859
1860 bool shouldUpdateColorMaskAndBlend = false;
1861 bool shouldUpdateLayerCount = false;
1862 bool shouldUpdateSrgbWriteControlMode = false;
1863
1864 // For any updated attachments we'll update their Serials below
1865 ASSERT(dirtyBits.any());
1866 for (size_t dirtyBit : dirtyBits)
1867 {
1868 switch (dirtyBit)
1869 {
1870 case gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
1871 case gl::Framebuffer::DIRTY_BIT_DEPTH_BUFFER_CONTENTS:
1872 case gl::Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
1873 case gl::Framebuffer::DIRTY_BIT_STENCIL_BUFFER_CONTENTS:
1874 ANGLE_TRY(updateDepthStencilAttachment(context));
1875 shouldUpdateLayerCount = true;
1876 dirtyDepthStencilAttachment = true;
1877 break;
1878 case gl::Framebuffer::DIRTY_BIT_READ_BUFFER:
1879 ANGLE_TRY(mRenderTargetCache.update(context, mState, dirtyBits));
1880 break;
1881 case gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
1882 shouldUpdateColorMaskAndBlend = true;
1883 shouldUpdateLayerCount = true;
1884 break;
1885 case gl::Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
1886 case gl::Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
1887 case gl::Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES:
1888 case gl::Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1889 // Invalidate the cache. If we have performance critical code hitting this path we
1890 // can add related data (such as width/height) to the cache
1891 mFramebufferCache.clear(contextVk);
1892 mFramebuffer = nullptr;
1893 break;
1894 case gl::Framebuffer::DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE:
1895 shouldUpdateSrgbWriteControlMode = true;
1896 break;
1897 case gl::Framebuffer::DIRTY_BIT_DEFAULT_LAYERS:
1898 shouldUpdateLayerCount = true;
1899 break;
1900 default:
1901 {
1902 static_assert(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0, "FB dirty bits");
1903 uint32_t colorIndexGL;
1904 if (dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX)
1905 {
1906 colorIndexGL = static_cast<uint32_t>(
1907 dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
1908 }
1909 else
1910 {
1911 ASSERT(dirtyBit >= gl::Framebuffer::DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 &&
1912 dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_BUFFER_CONTENTS_MAX);
1913 colorIndexGL = static_cast<uint32_t>(
1914 dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_BUFFER_CONTENTS_0);
1915 }
1916
1917 ANGLE_TRY(updateColorAttachment(context, colorIndexGL));
1918
1919 shouldUpdateColorMaskAndBlend = true;
1920 shouldUpdateLayerCount = true;
1921 dirtyColorAttachments.set(colorIndexGL);
1922
1923 break;
1924 }
1925 }
1926 }
1927
1928 if (shouldUpdateSrgbWriteControlMode)
1929 {
1930 // Framebuffer colorspace state has been modified, so refresh the current framebuffer
1931 // descriptor to reflect the new state.
1932 gl::SrgbWriteControlMode newSrgbWriteControlMode = mState.getWriteControlMode();
1933 mCurrentFramebufferDesc.setWriteControlMode(newSrgbWriteControlMode);
1934 mRenderPassDesc.setWriteControlMode(newSrgbWriteControlMode);
1935 }
1936
1937 if (shouldUpdateColorMaskAndBlend)
1938 {
1939 contextVk->updateColorMasks();
1940 contextVk->updateBlendFuncsAndEquations();
1941 }
1942
1943 if (shouldUpdateLayerCount)
1944 {
1945 updateLayerCount();
1946 }
1947
1948 // Only defer clears for draw framebuffer ops. Note that this will result in a render area that
1949 // completely covers the framebuffer, even if the operation that follows is scissored.
1950 bool deferClears = binding == GL_DRAW_FRAMEBUFFER;
1951
1952 // If we are notified that any attachment is dirty, but we have deferred clears for them, a
1953 // flushDeferredClears() call is missing somewhere. ASSERT this to catch these bugs.
1954 vk::ClearValuesArray previousDeferredClears = mDeferredClears;
1955
1956 for (size_t colorIndexGL : dirtyColorAttachments)
1957 {
1958 ASSERT(!previousDeferredClears.test(colorIndexGL));
1959 ANGLE_TRY(
1960 flushColorAttachmentUpdates(context, deferClears, static_cast<uint32_t>(colorIndexGL)));
1961 }
1962 if (dirtyDepthStencilAttachment)
1963 {
1964 ASSERT(!previousDeferredClears.testDepth());
1965 ASSERT(!previousDeferredClears.testStencil());
1966 ANGLE_TRY(flushDepthStencilAttachmentUpdates(context, deferClears));
1967 }
1968
1969 // No-op redundant changes to prevent closing the RenderPass.
1970 if (mCurrentFramebufferDesc == priorFramebufferDesc)
1971 {
1972 return angle::Result::Continue;
1973 }
1974
1975 if (command != gl::Command::Blit)
1976 {
1977 // Don't end the render pass when handling a blit to resolve, since we may be able to
1978 // optimize that path which requires modifying the current render pass.
1979 // We're deferring the resolve check to FramebufferVk::blit(), since if the read buffer is
1980 // multisampled-render-to-texture, then srcFramebuffer->getSamples(context) gives > 1, but
1981 // there's no resolve happening as the read buffer's single sampled image will be used as
1982 // blit src. FramebufferVk::blit() will handle those details for us.
1983 ANGLE_TRY(
1984 contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::FramebufferChange));
1985 }
1986
1987 updateRenderPassDesc(contextVk);
1988
1989 // Deactivate Framebuffer
1990 mFramebuffer = nullptr;
1991
1992 // Notify the ContextVk to update the pipeline desc.
1993 return contextVk->onFramebufferChange(this, command);
1994 }
1995
updateRenderPassDesc(ContextVk * contextVk)1996 void FramebufferVk::updateRenderPassDesc(ContextVk *contextVk)
1997 {
1998 mRenderPassDesc = {};
1999 mRenderPassDesc.setSamples(getSamples());
2000 mRenderPassDesc.setViewCount(
2001 mState.isMultiview() && mState.getNumViews() > 1 ? mState.getNumViews() : 0);
2002
2003 // Color attachments.
2004 const auto &colorRenderTargets = mRenderTargetCache.getColors();
2005 const gl::DrawBufferMask colorAttachmentMask = mState.getColorAttachmentsMask();
2006 for (size_t colorIndexGL = 0; colorIndexGL < colorAttachmentMask.size(); ++colorIndexGL)
2007 {
2008 if (colorAttachmentMask[colorIndexGL])
2009 {
2010 RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
2011 ASSERT(colorRenderTarget);
2012 mRenderPassDesc.packColorAttachment(
2013 colorIndexGL, colorRenderTarget->getImageForRenderPass().getActualFormatID());
2014
2015 // Add the resolve attachment, if any.
2016 if (colorRenderTarget->hasResolveAttachment())
2017 {
2018 mRenderPassDesc.packColorResolveAttachment(colorIndexGL);
2019 }
2020 }
2021 else
2022 {
2023 mRenderPassDesc.packColorAttachmentGap(colorIndexGL);
2024 }
2025 }
2026
2027 // Depth/stencil attachment.
2028 RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget();
2029 if (depthStencilRenderTarget)
2030 {
2031 mRenderPassDesc.packDepthStencilAttachment(
2032 depthStencilRenderTarget->getImageForRenderPass().getActualFormatID());
2033
2034 // Add the resolve attachment, if any.
2035 if (depthStencilRenderTarget->hasResolveAttachment())
2036 {
2037 mRenderPassDesc.packDepthStencilResolveAttachment();
2038 }
2039 }
2040
2041 // In case bound program uses shader framebuffer fetch and bound attachments are changed without
2042 // program change, we update framebuffer fetch mode in Renderpass here.
2043 bool programUsesFramebufferFetch = false;
2044 const gl::State &glState = contextVk->getState();
2045 const gl::ProgramExecutable *executable = glState.getProgramExecutable();
2046 if (executable)
2047 {
2048 programUsesFramebufferFetch = executable->usesFramebufferFetch();
2049 }
2050
2051 if (programUsesFramebufferFetch != mRenderPassDesc.getFramebufferFetchMode())
2052 {
2053 mCurrentFramebufferDesc.updateFramebufferFetchMode(programUsesFramebufferFetch);
2054 mRenderPassDesc.setFramebufferFetchMode(programUsesFramebufferFetch);
2055 }
2056
2057 if (contextVk->getFeatures().enableMultisampledRenderToTexture.enabled)
2058 {
2059 // Update descriptions regarding multisampled-render-to-texture use.
2060 bool isRenderToTexture = false;
2061 for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
2062 {
2063 const gl::FramebufferAttachment *color = mState.getColorAttachment(colorIndexGL);
2064 ASSERT(color);
2065
2066 if (color->isRenderToTexture())
2067 {
2068 isRenderToTexture = true;
2069 break;
2070 }
2071 }
2072 const gl::FramebufferAttachment *depthStencil = mState.getDepthStencilAttachment();
2073 if (depthStencil && depthStencil->isRenderToTexture())
2074 {
2075 isRenderToTexture = true;
2076 }
2077
2078 mCurrentFramebufferDesc.updateRenderToTexture(isRenderToTexture);
2079 mRenderPassDesc.updateRenderToTexture(isRenderToTexture);
2080 }
2081
2082 mCurrentFramebufferDesc.updateUnresolveMask({});
2083 mRenderPassDesc.setWriteControlMode(mCurrentFramebufferDesc.getWriteControlMode());
2084 }
2085
getFramebuffer(ContextVk * contextVk,vk::Framebuffer ** framebufferOut,const vk::ImageView * resolveImageViewIn,const SwapchainResolveMode swapchainResolveMode)2086 angle::Result FramebufferVk::getFramebuffer(ContextVk *contextVk,
2087 vk::Framebuffer **framebufferOut,
2088 const vk::ImageView *resolveImageViewIn,
2089 const SwapchainResolveMode swapchainResolveMode)
2090 {
2091 // First return a presently valid Framebuffer
2092 if (mFramebuffer != nullptr)
2093 {
2094 *framebufferOut = &mFramebuffer->getFramebuffer();
2095 return angle::Result::Continue;
2096 }
2097 // No current FB, so now check for previously cached Framebuffer
2098 vk::FramebufferHelper *framebufferHelper = nullptr;
2099 if (mFramebufferCache.get(contextVk, mCurrentFramebufferDesc, &framebufferHelper))
2100 {
2101 *framebufferOut = &framebufferHelper->getFramebuffer();
2102 return angle::Result::Continue;
2103 }
2104
2105 vk::RenderPass *compatibleRenderPass = nullptr;
2106 ANGLE_TRY(contextVk->getCompatibleRenderPass(mRenderPassDesc, &compatibleRenderPass));
2107
2108 // If we've a Framebuffer provided by a Surface (default FBO/backbuffer), query it.
2109 if (mBackbuffer)
2110 {
2111 return mBackbuffer->getCurrentFramebuffer(
2112 contextVk,
2113 mRenderPassDesc.getFramebufferFetchMode() ? FramebufferFetchMode::Enabled
2114 : FramebufferFetchMode::Disabled,
2115 *compatibleRenderPass, swapchainResolveMode, framebufferOut);
2116 }
2117
2118 // Gather VkImageViews over all FBO attachments, also size of attached region.
2119 std::vector<VkImageView> attachments;
2120 gl::Extents attachmentsSize = mState.getExtents();
2121 ASSERT(attachmentsSize.width != 0 && attachmentsSize.height != 0);
2122
2123 // Color attachments.
2124 const auto &colorRenderTargets = mRenderTargetCache.getColors();
2125 for (size_t colorIndexGL : mState.getColorAttachmentsMask())
2126 {
2127 RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
2128 ASSERT(colorRenderTarget);
2129
2130 const vk::ImageView *imageView = nullptr;
2131 ANGLE_TRY(colorRenderTarget->getImageViewWithColorspace(
2132 contextVk, mCurrentFramebufferDesc.getWriteControlMode(), &imageView));
2133
2134 attachments.push_back(imageView->getHandle());
2135 }
2136
2137 // Depth/stencil attachment.
2138 RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget();
2139 if (depthStencilRenderTarget)
2140 {
2141 const vk::ImageView *imageView = nullptr;
2142 ANGLE_TRY(depthStencilRenderTarget->getImageView(contextVk, &imageView));
2143
2144 attachments.push_back(imageView->getHandle());
2145 }
2146
2147 // Color resolve attachments.
2148 if (resolveImageViewIn)
2149 {
2150 ASSERT(!HasResolveAttachment(colorRenderTargets, mState.getEnabledDrawBuffers()));
2151
2152 // Need to use the passed in ImageView for the resolve attachment, since it came from
2153 // another Framebuffer.
2154 attachments.push_back(resolveImageViewIn->getHandle());
2155 }
2156 else
2157 {
2158 // This Framebuffer owns all of the ImageViews, including its own resolve ImageViews.
2159 for (size_t colorIndexGL : mState.getColorAttachmentsMask())
2160 {
2161 RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
2162 ASSERT(colorRenderTarget);
2163
2164 if (colorRenderTarget->hasResolveAttachment())
2165 {
2166 const vk::ImageView *resolveImageView = nullptr;
2167 ANGLE_TRY(colorRenderTarget->getResolveImageView(contextVk, &resolveImageView));
2168
2169 attachments.push_back(resolveImageView->getHandle());
2170 }
2171 }
2172 }
2173
2174 // Depth/stencil resolve attachment.
2175 if (depthStencilRenderTarget && depthStencilRenderTarget->hasResolveAttachment())
2176 {
2177 const vk::ImageView *imageView = nullptr;
2178 ANGLE_TRY(depthStencilRenderTarget->getResolveImageView(contextVk, &imageView));
2179
2180 attachments.push_back(imageView->getHandle());
2181 }
2182
2183 VkFramebufferCreateInfo framebufferInfo = {};
2184
2185 framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
2186 framebufferInfo.flags = 0;
2187 framebufferInfo.renderPass = compatibleRenderPass->getHandle();
2188 framebufferInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
2189 framebufferInfo.pAttachments = attachments.data();
2190 framebufferInfo.width = static_cast<uint32_t>(attachmentsSize.width);
2191 framebufferInfo.height = static_cast<uint32_t>(attachmentsSize.height);
2192 framebufferInfo.layers = 1;
2193 if (!mCurrentFramebufferDesc.isMultiview())
2194 {
2195 framebufferInfo.layers = std::max(mCurrentFramebufferDesc.getLayerCount(), 1u);
2196 }
2197
2198 vk::FramebufferHelper newFramebuffer;
2199 ANGLE_TRY(newFramebuffer.init(contextVk, framebufferInfo));
2200
2201 // Check that our description matches our attachments. Can catch implementation bugs.
2202 ASSERT(static_cast<uint32_t>(attachments.size()) == mCurrentFramebufferDesc.attachmentCount());
2203
2204 mFramebufferCache.insert(mCurrentFramebufferDesc, std::move(newFramebuffer));
2205 bool result = mFramebufferCache.get(contextVk, mCurrentFramebufferDesc, &mFramebuffer);
2206 ASSERT(result);
2207
2208 *framebufferOut = &mFramebuffer->getFramebuffer();
2209 return angle::Result::Continue;
2210 }
2211
mergeClearsWithDeferredClears(gl::DrawBufferMask clearColorBuffers,bool clearDepth,bool clearStencil,const VkClearColorValue & clearColorValue,const VkClearDepthStencilValue & clearDepthStencilValue)2212 void FramebufferVk::mergeClearsWithDeferredClears(
2213 gl::DrawBufferMask clearColorBuffers,
2214 bool clearDepth,
2215 bool clearStencil,
2216 const VkClearColorValue &clearColorValue,
2217 const VkClearDepthStencilValue &clearDepthStencilValue)
2218 {
2219 // Apply clears to mDeferredClears. Note that clears override deferred clears.
2220
2221 // Color clears.
2222 for (size_t colorIndexGL : clearColorBuffers)
2223 {
2224 ASSERT(mState.getEnabledDrawBuffers().test(colorIndexGL));
2225 VkClearValue clearValue = getCorrectedColorClearValue(colorIndexGL, clearColorValue);
2226 mDeferredClears.store(static_cast<uint32_t>(colorIndexGL), VK_IMAGE_ASPECT_COLOR_BIT,
2227 clearValue);
2228 }
2229
2230 // Depth and stencil clears.
2231 VkImageAspectFlags dsAspectFlags = 0;
2232 VkClearValue dsClearValue = {};
2233 dsClearValue.depthStencil = clearDepthStencilValue;
2234 if (clearDepth)
2235 {
2236 dsAspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
2237 }
2238 if (clearStencil)
2239 {
2240 dsAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
2241 }
2242
2243 if (dsAspectFlags != 0)
2244 {
2245 mDeferredClears.store(vk::kUnpackedDepthIndex, dsAspectFlags, dsClearValue);
2246 }
2247 }
2248
clearWithDraw(ContextVk * contextVk,const gl::Rectangle & clearArea,gl::DrawBufferMask clearColorBuffers,bool clearDepth,bool clearStencil,gl::BlendStateExt::ColorMaskStorage::Type colorMasks,uint8_t stencilMask,const VkClearColorValue & clearColorValue,const VkClearDepthStencilValue & clearDepthStencilValue)2249 angle::Result FramebufferVk::clearWithDraw(ContextVk *contextVk,
2250 const gl::Rectangle &clearArea,
2251 gl::DrawBufferMask clearColorBuffers,
2252 bool clearDepth,
2253 bool clearStencil,
2254 gl::BlendStateExt::ColorMaskStorage::Type colorMasks,
2255 uint8_t stencilMask,
2256 const VkClearColorValue &clearColorValue,
2257 const VkClearDepthStencilValue &clearDepthStencilValue)
2258 {
2259 // All deferred clears should be handled already.
2260 ASSERT(mDeferredClears.empty());
2261
2262 UtilsVk::ClearFramebufferParameters params = {};
2263 params.clearArea = clearArea;
2264 params.colorClearValue = clearColorValue;
2265 params.depthStencilClearValue = clearDepthStencilValue;
2266 params.stencilMask = stencilMask;
2267
2268 params.clearColor = true;
2269 params.clearDepth = clearDepth;
2270 params.clearStencil = clearStencil;
2271
2272 const auto &colorRenderTargets = mRenderTargetCache.getColors();
2273 for (size_t colorIndexGL : clearColorBuffers)
2274 {
2275 const RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
2276 ASSERT(colorRenderTarget);
2277
2278 params.colorFormat = &colorRenderTarget->getImageForRenderPass().getActualFormat();
2279 params.colorAttachmentIndexGL = static_cast<uint32_t>(colorIndexGL);
2280 params.colorMaskFlags =
2281 gl::BlendStateExt::ColorMaskStorage::GetValueIndexed(colorIndexGL, colorMasks);
2282 if (mEmulatedAlphaAttachmentMask[colorIndexGL])
2283 {
2284 params.colorMaskFlags &= ~VK_COLOR_COMPONENT_A_BIT;
2285 }
2286
2287 // TODO: implement clear of layered framebuffers. UtilsVk::clearFramebuffer should add a
2288 // geometry shader that is instanced layerCount times (or loops layerCount times), each time
2289 // selecting a different layer.
2290 // http://anglebug.com/5453
2291 ASSERT(mCurrentFramebufferDesc.isMultiview() || colorRenderTarget->getLayerCount() == 1);
2292
2293 ANGLE_TRY(contextVk->getUtils().clearFramebuffer(contextVk, this, params));
2294
2295 // Clear depth/stencil only once!
2296 params.clearDepth = false;
2297 params.clearStencil = false;
2298 }
2299
2300 // If there was no color clear, clear depth/stencil alone.
2301 if (params.clearDepth || params.clearStencil)
2302 {
2303 params.clearColor = false;
2304 ANGLE_TRY(contextVk->getUtils().clearFramebuffer(contextVk, this, params));
2305 }
2306
2307 return angle::Result::Continue;
2308 }
2309
getCorrectedColorClearValue(size_t colorIndexGL,const VkClearColorValue & clearColor) const2310 VkClearValue FramebufferVk::getCorrectedColorClearValue(size_t colorIndexGL,
2311 const VkClearColorValue &clearColor) const
2312 {
2313 VkClearValue clearValue = {};
2314 clearValue.color = clearColor;
2315
2316 if (!mEmulatedAlphaAttachmentMask[colorIndexGL])
2317 {
2318 return clearValue;
2319 }
2320
2321 // If the render target doesn't have alpha, but its emulated format has it, clear the alpha
2322 // to 1.
2323 RenderTargetVk *renderTarget = getColorDrawRenderTarget(colorIndexGL);
2324 const angle::Format &format = renderTarget->getImageActualFormat();
2325
2326 if (format.isUint())
2327 {
2328 clearValue.color.uint32[3] = kEmulatedAlphaValue;
2329 }
2330 else if (format.isSint())
2331 {
2332 clearValue.color.int32[3] = kEmulatedAlphaValue;
2333 }
2334 else
2335 {
2336 clearValue.color.float32[3] = kEmulatedAlphaValue;
2337 }
2338
2339 return clearValue;
2340 }
2341
redeferClears(ContextVk * contextVk)2342 void FramebufferVk::redeferClears(ContextVk *contextVk)
2343 {
2344 ASSERT(!contextVk->hasStartedRenderPass() || !mDeferredClears.any());
2345
2346 // Set the appropriate loadOp and clear values for depth and stencil.
2347 VkImageAspectFlags dsAspectFlags = 0;
2348 VkClearValue dsClearValue = {};
2349 dsClearValue.depthStencil.depth = mDeferredClears.getDepthValue();
2350 dsClearValue.depthStencil.stencil = mDeferredClears.getStencilValue();
2351
2352 if (mDeferredClears.testDepth())
2353 {
2354 dsAspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
2355 mDeferredClears.reset(vk::kUnpackedDepthIndex);
2356 }
2357
2358 if (mDeferredClears.testStencil())
2359 {
2360 dsAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
2361 mDeferredClears.reset(vk::kUnpackedStencilIndex);
2362 }
2363
2364 // Go through deferred clears and stage the clears for future.
2365 for (size_t colorIndexGL : mDeferredClears.getColorMask())
2366 {
2367 RenderTargetVk *renderTarget = getColorDrawRenderTarget(colorIndexGL);
2368 gl::ImageIndex imageIndex =
2369 renderTarget->getImageIndexForClear(mCurrentFramebufferDesc.getLayerCount());
2370 renderTarget->getImageForWrite().stageClear(imageIndex, VK_IMAGE_ASPECT_COLOR_BIT,
2371 mDeferredClears[colorIndexGL]);
2372 mDeferredClears.reset(colorIndexGL);
2373 }
2374
2375 if (dsAspectFlags)
2376 {
2377 RenderTargetVk *renderTarget = getDepthStencilRenderTarget();
2378 ASSERT(renderTarget);
2379
2380 gl::ImageIndex imageIndex =
2381 renderTarget->getImageIndexForClear(mCurrentFramebufferDesc.getLayerCount());
2382 renderTarget->getImageForWrite().stageClear(imageIndex, dsAspectFlags, dsClearValue);
2383 }
2384 }
2385
clearWithCommand(ContextVk * contextVk,const gl::Rectangle & scissoredRenderArea)2386 void FramebufferVk::clearWithCommand(ContextVk *contextVk, const gl::Rectangle &scissoredRenderArea)
2387 {
2388 // Clear is not affected by viewport, so ContextVk::updateScissor may have decided on a smaller
2389 // render area. Grow the render area to the full framebuffer size as this clear path is taken
2390 // when not scissored.
2391 vk::RenderPassCommandBufferHelper *renderPassCommands =
2392 &contextVk->getStartedRenderPassCommands();
2393 renderPassCommands->growRenderArea(contextVk, scissoredRenderArea);
2394
2395 gl::AttachmentVector<VkClearAttachment> attachments;
2396
2397 // Go through deferred clears and add them to the list of attachments to clear. If any
2398 // attachment is unused, skip the clear. clearWithLoadOp will follow and move the remaining
2399 // clears up to loadOp.
2400 vk::PackedAttachmentIndex colorIndexVk(0);
2401 for (size_t colorIndexGL : mState.getColorAttachmentsMask())
2402 {
2403 if (mDeferredClears.getColorMask().test(colorIndexGL))
2404 {
2405 if (!renderPassCommands->hasAnyColorAccess(colorIndexVk))
2406 {
2407 // Skip this attachment, so we can use a renderpass loadOp to clear it instead.
2408 // Note that if loadOp=Clear was already used for this color attachment, it will be
2409 // overriden by the new clear, which is valid because the attachment wasn't used in
2410 // between.
2411 ++colorIndexVk;
2412 continue;
2413 }
2414
2415 attachments.emplace_back(VkClearAttachment{VK_IMAGE_ASPECT_COLOR_BIT,
2416 static_cast<uint32_t>(colorIndexGL),
2417 mDeferredClears[colorIndexGL]});
2418 mDeferredClears.reset(colorIndexGL);
2419 ++contextVk->getPerfCounters().colorClearAttachments;
2420
2421 renderPassCommands->onColorAccess(colorIndexVk, vk::ResourceAccess::Write);
2422 }
2423 ++colorIndexVk;
2424 }
2425
2426 // Add depth and stencil to list of attachments as needed.
2427 VkImageAspectFlags dsAspectFlags = 0;
2428 VkClearValue dsClearValue = {};
2429 dsClearValue.depthStencil.depth = mDeferredClears.getDepthValue();
2430 dsClearValue.depthStencil.stencil = mDeferredClears.getStencilValue();
2431 if (mDeferredClears.testDepth() && renderPassCommands->hasAnyDepthAccess())
2432 {
2433 dsAspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
2434 // Explicitly mark a depth write because we are clearing the depth buffer.
2435 renderPassCommands->onDepthAccess(vk::ResourceAccess::Write);
2436 mDeferredClears.reset(vk::kUnpackedDepthIndex);
2437 ++contextVk->getPerfCounters().depthClearAttachments;
2438 }
2439
2440 if (mDeferredClears.testStencil() && renderPassCommands->hasAnyStencilAccess())
2441 {
2442 dsAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
2443 // Explicitly mark a stencil write because we are clearing the stencil buffer.
2444 renderPassCommands->onStencilAccess(vk::ResourceAccess::Write);
2445 mDeferredClears.reset(vk::kUnpackedStencilIndex);
2446 ++contextVk->getPerfCounters().stencilClearAttachments;
2447 }
2448
2449 if (dsAspectFlags != 0)
2450 {
2451 attachments.emplace_back(VkClearAttachment{dsAspectFlags, 0, dsClearValue});
2452 // Because we may have changed the depth stencil access mode, update read only depth mode
2453 // now.
2454 updateRenderPassReadOnlyDepthMode(contextVk, renderPassCommands);
2455 }
2456
2457 if (attachments.empty())
2458 {
2459 return;
2460 }
2461
2462 const uint32_t layerCount = mState.isMultiview() ? 1 : mCurrentFramebufferDesc.getLayerCount();
2463
2464 VkClearRect rect = {};
2465 rect.rect.extent.width = scissoredRenderArea.width;
2466 rect.rect.extent.height = scissoredRenderArea.height;
2467 rect.layerCount = layerCount;
2468 vk::RenderPassCommandBuffer *renderPassCommandBuffer = &renderPassCommands->getCommandBuffer();
2469
2470 renderPassCommandBuffer->clearAttachments(static_cast<uint32_t>(attachments.size()),
2471 attachments.data(), 1, &rect);
2472 return;
2473 }
2474
clearWithLoadOp(ContextVk * contextVk)2475 void FramebufferVk::clearWithLoadOp(ContextVk *contextVk)
2476 {
2477 vk::RenderPassCommandBufferHelper *renderPassCommands =
2478 &contextVk->getStartedRenderPassCommands();
2479
2480 // Update the render pass loadOps to clear the attachments.
2481 vk::PackedAttachmentIndex colorIndexVk(0);
2482 for (size_t colorIndexGL : mState.getColorAttachmentsMask())
2483 {
2484 if (!mDeferredClears.test(colorIndexGL))
2485 {
2486 ++colorIndexVk;
2487 continue;
2488 }
2489
2490 ASSERT(!renderPassCommands->hasAnyColorAccess(colorIndexVk));
2491
2492 renderPassCommands->updateRenderPassColorClear(colorIndexVk, mDeferredClears[colorIndexGL]);
2493
2494 mDeferredClears.reset(colorIndexGL);
2495
2496 ++colorIndexVk;
2497 }
2498
2499 VkClearValue dsClearValue = {};
2500 dsClearValue.depthStencil.depth = mDeferredClears.getDepthValue();
2501 dsClearValue.depthStencil.stencil = mDeferredClears.getStencilValue();
2502 VkImageAspectFlags dsAspects = 0;
2503
2504 if (mDeferredClears.testDepth())
2505 {
2506 ASSERT(!renderPassCommands->hasAnyDepthAccess());
2507 dsAspects |= VK_IMAGE_ASPECT_DEPTH_BIT;
2508 mDeferredClears.reset(vk::kUnpackedDepthIndex);
2509 }
2510
2511 if (mDeferredClears.testStencil())
2512 {
2513 ASSERT(!renderPassCommands->hasAnyStencilAccess());
2514 dsAspects |= VK_IMAGE_ASPECT_STENCIL_BIT;
2515 mDeferredClears.reset(vk::kUnpackedStencilIndex);
2516 }
2517
2518 if (dsAspects != 0)
2519 {
2520 renderPassCommands->updateRenderPassDepthStencilClear(dsAspects, dsClearValue);
2521 // The render pass can no longer be in read-only depth/stencil mode.
2522 updateRenderPassReadOnlyDepthMode(contextVk, renderPassCommands);
2523 }
2524 }
2525
getSamplePosition(const gl::Context * context,size_t index,GLfloat * xy) const2526 angle::Result FramebufferVk::getSamplePosition(const gl::Context *context,
2527 size_t index,
2528 GLfloat *xy) const
2529 {
2530 int sampleCount = getSamples();
2531 rx::GetSamplePosition(sampleCount, index, xy);
2532 return angle::Result::Continue;
2533 }
2534
startNewRenderPass(ContextVk * contextVk,const gl::Rectangle & scissoredRenderArea,vk::RenderPassCommandBuffer ** commandBufferOut,bool * renderPassDescChangedOut)2535 angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
2536 const gl::Rectangle &scissoredRenderArea,
2537 vk::RenderPassCommandBuffer **commandBufferOut,
2538 bool *renderPassDescChangedOut)
2539 {
2540 ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::NewRenderPass));
2541
2542 // Initialize RenderPass info.
2543 vk::AttachmentOpsArray renderPassAttachmentOps;
2544 vk::PackedClearValuesArray packedClearValues;
2545 gl::DrawBufferMask previousUnresolveColorMask =
2546 mRenderPassDesc.getColorUnresolveAttachmentMask();
2547 const bool hasDeferredClears = mDeferredClears.any();
2548 const bool previousUnresolveDepth = mRenderPassDesc.hasDepthUnresolveAttachment();
2549 const bool previousUnresolveStencil = mRenderPassDesc.hasStencilUnresolveAttachment();
2550
2551 // Make sure render pass and framebuffer are in agreement w.r.t unresolve attachments.
2552 ASSERT(mCurrentFramebufferDesc.getUnresolveAttachmentMask() ==
2553 MakeUnresolveAttachmentMask(mRenderPassDesc));
2554
2555 // Color attachments.
2556 const auto &colorRenderTargets = mRenderTargetCache.getColors();
2557 vk::PackedAttachmentIndex colorIndexVk(0);
2558 for (size_t colorIndexGL : mState.getColorAttachmentsMask())
2559 {
2560 RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
2561 ASSERT(colorRenderTarget);
2562
2563 // Color render targets are never entirely transient. Only depth/stencil
2564 // multisampled-render-to-texture textures can be so.
2565 ASSERT(!colorRenderTarget->isEntirelyTransient());
2566 const vk::RenderPassStoreOp storeOp = colorRenderTarget->isImageTransient()
2567 ? vk::RenderPassStoreOp::DontCare
2568 : vk::RenderPassStoreOp::Store;
2569
2570 if (mDeferredClears.test(colorIndexGL))
2571 {
2572 renderPassAttachmentOps.setOps(colorIndexVk, vk::RenderPassLoadOp::Clear, storeOp);
2573 packedClearValues.store(colorIndexVk, VK_IMAGE_ASPECT_COLOR_BIT,
2574 mDeferredClears[colorIndexGL]);
2575 mDeferredClears.reset(colorIndexGL);
2576 }
2577 else
2578 {
2579 const vk::RenderPassLoadOp loadOp = colorRenderTarget->hasDefinedContent()
2580 ? vk::RenderPassLoadOp::Load
2581 : vk::RenderPassLoadOp::DontCare;
2582
2583 renderPassAttachmentOps.setOps(colorIndexVk, loadOp, storeOp);
2584 packedClearValues.store(colorIndexVk, VK_IMAGE_ASPECT_COLOR_BIT,
2585 kUninitializedClearValue);
2586 }
2587 renderPassAttachmentOps.setStencilOps(colorIndexVk, vk::RenderPassLoadOp::DontCare,
2588 vk::RenderPassStoreOp::DontCare);
2589
2590 // If there's a resolve attachment, and loadOp needs to be LOAD, the multisampled attachment
2591 // needs to take its value from the resolve attachment. In this case, an initial subpass is
2592 // added for this very purpose which uses the resolve attachment as input attachment. As a
2593 // result, loadOp of the multisampled attachment can remain DONT_CARE.
2594 //
2595 // Note that this only needs to be done if the multisampled image and the resolve attachment
2596 // come from the same source. isImageTransient() indicates whether this should happen.
2597 if (colorRenderTarget->hasResolveAttachment() && colorRenderTarget->isImageTransient())
2598 {
2599 if (renderPassAttachmentOps[colorIndexVk].loadOp == VK_ATTACHMENT_LOAD_OP_LOAD)
2600 {
2601 renderPassAttachmentOps[colorIndexVk].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
2602
2603 // Update the render pass desc to specify that this attachment should be unresolved.
2604 mRenderPassDesc.packColorUnresolveAttachment(colorIndexGL);
2605 }
2606 else
2607 {
2608 mRenderPassDesc.removeColorUnresolveAttachment(colorIndexGL);
2609 }
2610 }
2611 else
2612 {
2613 ASSERT(!mRenderPassDesc.getColorUnresolveAttachmentMask().test(colorIndexGL));
2614 }
2615
2616 ++colorIndexVk;
2617 }
2618
2619 // Depth/stencil attachment.
2620 vk::PackedAttachmentIndex depthStencilAttachmentIndex = vk::kAttachmentIndexInvalid;
2621 RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget();
2622 if (depthStencilRenderTarget)
2623 {
2624 const bool canExportStencil =
2625 contextVk->getRenderer()->getFeatures().supportsShaderStencilExport.enabled;
2626
2627 // depth stencil attachment always immediately follows color attachment
2628 depthStencilAttachmentIndex = colorIndexVk;
2629
2630 vk::RenderPassLoadOp depthLoadOp = vk::RenderPassLoadOp::Load;
2631 vk::RenderPassLoadOp stencilLoadOp = vk::RenderPassLoadOp::Load;
2632 vk::RenderPassStoreOp depthStoreOp = vk::RenderPassStoreOp::Store;
2633 vk::RenderPassStoreOp stencilStoreOp = vk::RenderPassStoreOp::Store;
2634
2635 // If the image data was previously discarded (with no update in between), don't attempt to
2636 // load the image. Additionally, if the multisampled image data is transient and there is
2637 // no resolve attachment, there's no data to load. The latter is the case with
2638 // depth/stencil texture attachments per GL_EXT_multisampled_render_to_texture2.
2639 if (!depthStencilRenderTarget->hasDefinedContent() ||
2640 depthStencilRenderTarget->isEntirelyTransient())
2641 {
2642 depthLoadOp = vk::RenderPassLoadOp::DontCare;
2643 }
2644 if (!depthStencilRenderTarget->hasDefinedStencilContent() ||
2645 depthStencilRenderTarget->isEntirelyTransient())
2646 {
2647 stencilLoadOp = vk::RenderPassLoadOp::DontCare;
2648 }
2649
2650 // If depth/stencil image is transient, no need to store its data at the end of the render
2651 // pass. If shader stencil export is not supported, stencil data cannot be unresolved on
2652 // the next render pass, so it must be stored/loaded. If the image is entirely transient,
2653 // there is no resolve/unresolve and the image data is never stored/loaded.
2654 if (depthStencilRenderTarget->isImageTransient())
2655 {
2656 depthStoreOp = vk::RenderPassStoreOp::DontCare;
2657
2658 if (canExportStencil || depthStencilRenderTarget->isEntirelyTransient())
2659 {
2660 stencilStoreOp = vk::RenderPassStoreOp::DontCare;
2661 }
2662 }
2663
2664 if (mDeferredClears.testDepth() || mDeferredClears.testStencil())
2665 {
2666 VkClearValue clearValue = {};
2667
2668 if (mDeferredClears.testDepth())
2669 {
2670 depthLoadOp = vk::RenderPassLoadOp::Clear;
2671 clearValue.depthStencil.depth = mDeferredClears.getDepthValue();
2672 mDeferredClears.reset(vk::kUnpackedDepthIndex);
2673 }
2674
2675 if (mDeferredClears.testStencil())
2676 {
2677 stencilLoadOp = vk::RenderPassLoadOp::Clear;
2678 clearValue.depthStencil.stencil = mDeferredClears.getStencilValue();
2679 mDeferredClears.reset(vk::kUnpackedStencilIndex);
2680 }
2681
2682 // Note the aspect is only depth here. That's intentional.
2683 packedClearValues.store(depthStencilAttachmentIndex, VK_IMAGE_ASPECT_DEPTH_BIT,
2684 clearValue);
2685 }
2686 else
2687 {
2688 // Note the aspect is only depth here. That's intentional.
2689 packedClearValues.store(depthStencilAttachmentIndex, VK_IMAGE_ASPECT_DEPTH_BIT,
2690 kUninitializedClearValue);
2691 }
2692
2693 const angle::Format &format = depthStencilRenderTarget->getImageIntendedFormat();
2694 // If the format we picked has stencil but user did not ask for it due to hardware
2695 // limitations, use DONT_CARE for load/store. The same logic for depth follows.
2696 if (format.stencilBits == 0)
2697 {
2698 stencilLoadOp = vk::RenderPassLoadOp::DontCare;
2699 stencilStoreOp = vk::RenderPassStoreOp::DontCare;
2700 }
2701 if (format.depthBits == 0)
2702 {
2703 depthLoadOp = vk::RenderPassLoadOp::DontCare;
2704 depthStoreOp = vk::RenderPassStoreOp::DontCare;
2705 }
2706
2707 // Similar to color attachments, if there's a resolve attachment and the multisampled image
2708 // is transient, depth/stencil data need to be unresolved in an initial subpass.
2709 //
2710 // Note that stencil unresolve is currently only possible if shader stencil export is
2711 // supported.
2712 if (depthStencilRenderTarget->hasResolveAttachment() &&
2713 depthStencilRenderTarget->isImageTransient())
2714 {
2715 const bool unresolveDepth = depthLoadOp == vk::RenderPassLoadOp::Load;
2716 const bool unresolveStencil =
2717 stencilLoadOp == vk::RenderPassLoadOp::Load && canExportStencil;
2718
2719 if (unresolveDepth)
2720 {
2721 depthLoadOp = vk::RenderPassLoadOp::DontCare;
2722 }
2723
2724 if (unresolveStencil)
2725 {
2726 stencilLoadOp = vk::RenderPassLoadOp::DontCare;
2727 }
2728
2729 if (unresolveDepth || unresolveStencil)
2730 {
2731 mRenderPassDesc.packDepthStencilUnresolveAttachment(unresolveDepth,
2732 unresolveStencil);
2733 }
2734 else
2735 {
2736 mRenderPassDesc.removeDepthStencilUnresolveAttachment();
2737 }
2738 }
2739
2740 renderPassAttachmentOps.setOps(depthStencilAttachmentIndex, depthLoadOp, depthStoreOp);
2741 renderPassAttachmentOps.setStencilOps(depthStencilAttachmentIndex, stencilLoadOp,
2742 stencilStoreOp);
2743 }
2744
2745 // If render pass description is changed, the previous render pass desc is no longer compatible.
2746 // Tell the context so that the graphics pipelines can be recreated.
2747 //
2748 // Note that render passes are compatible only if the differences are in loadOp/storeOp values,
2749 // or the existence of resolve attachments in single subpass render passes. The modification
2750 // here can add/remove a subpass, or modify its input attachments.
2751 gl::DrawBufferMask unresolveColorMask = mRenderPassDesc.getColorUnresolveAttachmentMask();
2752 const bool unresolveDepth = mRenderPassDesc.hasDepthUnresolveAttachment();
2753 const bool unresolveStencil = mRenderPassDesc.hasStencilUnresolveAttachment();
2754 const bool unresolveChanged = previousUnresolveColorMask != unresolveColorMask ||
2755 previousUnresolveDepth != unresolveDepth ||
2756 previousUnresolveStencil != unresolveStencil;
2757 if (unresolveChanged)
2758 {
2759 // Make sure framebuffer is recreated.
2760 mFramebuffer = nullptr;
2761
2762 mCurrentFramebufferDesc.updateUnresolveMask(MakeUnresolveAttachmentMask(mRenderPassDesc));
2763 }
2764
2765 vk::Framebuffer *framebuffer = nullptr;
2766 ANGLE_TRY(getFramebuffer(contextVk, &framebuffer, nullptr, SwapchainResolveMode::Disabled));
2767
2768 // If deferred clears were used in the render pass, expand the render area to the whole
2769 // framebuffer.
2770 gl::Rectangle renderArea = scissoredRenderArea;
2771 if (hasDeferredClears)
2772 {
2773 renderArea = getRotatedCompleteRenderArea(contextVk);
2774 }
2775
2776 ANGLE_TRY(contextVk->beginNewRenderPass(
2777 *framebuffer, renderArea, mRenderPassDesc, renderPassAttachmentOps, colorIndexVk,
2778 depthStencilAttachmentIndex, packedClearValues, commandBufferOut));
2779
2780 // Add the images to the renderpass tracking list (through onColorDraw).
2781 vk::PackedAttachmentIndex colorAttachmentIndex(0);
2782 for (size_t colorIndexGL : mState.getColorAttachmentsMask())
2783 {
2784 RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
2785 colorRenderTarget->onColorDraw(contextVk, mCurrentFramebufferDesc.getLayerCount(),
2786 colorAttachmentIndex);
2787 ++colorAttachmentIndex;
2788 }
2789
2790 if (depthStencilRenderTarget)
2791 {
2792 // This must be called after hasDefined*Content() since it will set content to valid. If
2793 // the attachment ends up not used in the render pass, contents will be marked undefined at
2794 // endRenderPass. The actual layout determination is also deferred until the same time.
2795 depthStencilRenderTarget->onDepthStencilDraw(contextVk,
2796 mCurrentFramebufferDesc.getLayerCount());
2797 }
2798
2799 const bool anyUnresolve = unresolveColorMask.any() || unresolveDepth || unresolveStencil;
2800 if (anyUnresolve)
2801 {
2802 // Unresolve attachments if any.
2803 UtilsVk::UnresolveParameters params;
2804 params.unresolveColorMask = unresolveColorMask;
2805 params.unresolveDepth = unresolveDepth;
2806 params.unresolveStencil = unresolveStencil;
2807
2808 ANGLE_TRY(contextVk->getUtils().unresolve(contextVk, this, params));
2809
2810 // The unresolve subpass has only one draw call.
2811 ANGLE_TRY(contextVk->startNextSubpass());
2812 }
2813
2814 if (unresolveChanged || anyUnresolve)
2815 {
2816 contextVk->onDrawFramebufferRenderPassDescChange(this, renderPassDescChangedOut);
2817 }
2818
2819 return angle::Result::Continue;
2820 }
2821
updateActiveColorMasks(size_t colorIndexGL,bool r,bool g,bool b,bool a)2822 void FramebufferVk::updateActiveColorMasks(size_t colorIndexGL, bool r, bool g, bool b, bool a)
2823 {
2824 gl::BlendStateExt::ColorMaskStorage::SetValueIndexed(
2825 colorIndexGL, gl::BlendStateExt::PackColorMask(r, g, b, a),
2826 &mActiveColorComponentMasksForClear);
2827 }
2828
getEmulatedAlphaAttachmentMask() const2829 const gl::DrawBufferMask &FramebufferVk::getEmulatedAlphaAttachmentMask() const
2830 {
2831 return mEmulatedAlphaAttachmentMask;
2832 }
2833
readPixelsImpl(ContextVk * contextVk,const gl::Rectangle & area,const PackPixelsParams & packPixelsParams,VkImageAspectFlagBits copyAspectFlags,RenderTargetVk * renderTarget,void * pixels)2834 angle::Result FramebufferVk::readPixelsImpl(ContextVk *contextVk,
2835 const gl::Rectangle &area,
2836 const PackPixelsParams &packPixelsParams,
2837 VkImageAspectFlagBits copyAspectFlags,
2838 RenderTargetVk *renderTarget,
2839 void *pixels)
2840 {
2841 ANGLE_TRACE_EVENT0("gpu.angle", "FramebufferVk::readPixelsImpl");
2842 gl::LevelIndex levelGL = renderTarget->getLevelIndex();
2843 uint32_t layer = renderTarget->getLayerIndex();
2844 return renderTarget->getImageForCopy().readPixels(contextVk, area, packPixelsParams,
2845 copyAspectFlags, levelGL, layer, pixels);
2846 }
2847
getReadImageExtents() const2848 gl::Extents FramebufferVk::getReadImageExtents() const
2849 {
2850 RenderTargetVk *readRenderTarget = mRenderTargetCache.getColorRead(mState);
2851 return readRenderTarget->getExtents();
2852 }
2853
2854 // Return the framebuffer's non-rotated render area. This is a gl::Rectangle that is based on the
2855 // dimensions of the framebuffer, IS NOT rotated, and IS NOT y-flipped
getNonRotatedCompleteRenderArea() const2856 gl::Rectangle FramebufferVk::getNonRotatedCompleteRenderArea() const
2857 {
2858 const gl::Box &dimensions = mState.getDimensions();
2859 return gl::Rectangle(0, 0, dimensions.width, dimensions.height);
2860 }
2861
2862 // Return the framebuffer's rotated render area. This is a gl::Rectangle that is based on the
2863 // dimensions of the framebuffer, IS ROTATED for the draw FBO, and IS NOT y-flipped
2864 //
2865 // Note: Since the rectangle is not scissored (i.e. x and y are guaranteed to be zero), only the
2866 // width and height must be swapped if the rotation is 90 or 270 degrees.
getRotatedCompleteRenderArea(ContextVk * contextVk) const2867 gl::Rectangle FramebufferVk::getRotatedCompleteRenderArea(ContextVk *contextVk) const
2868 {
2869 gl::Rectangle renderArea = getNonRotatedCompleteRenderArea();
2870 if (contextVk->isRotatedAspectRatioForDrawFBO())
2871 {
2872 // The surface is rotated 90/270 degrees. This changes the aspect ratio of the surface.
2873 std::swap(renderArea.width, renderArea.height);
2874 }
2875 return renderArea;
2876 }
2877
2878 // Return the framebuffer's scissored and rotated render area. This is a gl::Rectangle that is
2879 // based on the dimensions of the framebuffer, is clipped to the scissor, IS ROTATED and IS
2880 // Y-FLIPPED for the draw FBO.
2881 //
2882 // Note: Since the rectangle is scissored, it must be fully rotated, and not just have the width
2883 // and height swapped.
getRotatedScissoredRenderArea(ContextVk * contextVk) const2884 gl::Rectangle FramebufferVk::getRotatedScissoredRenderArea(ContextVk *contextVk) const
2885 {
2886 const gl::Rectangle renderArea = getNonRotatedCompleteRenderArea();
2887 bool invertViewport = contextVk->isViewportFlipEnabledForDrawFBO();
2888 gl::Rectangle scissoredArea = ClipRectToScissor(contextVk->getState(), renderArea, false);
2889 gl::Rectangle rotatedScissoredArea;
2890 RotateRectangle(contextVk->getRotationDrawFramebuffer(), invertViewport, renderArea.width,
2891 renderArea.height, scissoredArea, &rotatedScissoredArea);
2892 return rotatedScissoredArea;
2893 }
2894
getSamples() const2895 GLint FramebufferVk::getSamples() const
2896 {
2897 const gl::FramebufferAttachment *lastAttachment = nullptr;
2898
2899 for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
2900 {
2901 const gl::FramebufferAttachment *color = mState.getColorAttachment(colorIndexGL);
2902 ASSERT(color);
2903
2904 if (color->isRenderToTexture())
2905 {
2906 return color->getSamples();
2907 }
2908
2909 lastAttachment = color;
2910 }
2911 const gl::FramebufferAttachment *depthStencil = mState.getDepthOrStencilAttachment();
2912 if (depthStencil)
2913 {
2914 if (depthStencil->isRenderToTexture())
2915 {
2916 return depthStencil->getSamples();
2917 }
2918 lastAttachment = depthStencil;
2919 }
2920
2921 // If none of the attachments are multisampled-render-to-texture, take the sample count from the
2922 // last attachment (any would have worked, as they would all have the same sample count).
2923 return std::max(lastAttachment ? lastAttachment->getSamples() : 1, 1);
2924 }
2925
flushDeferredClears(ContextVk * contextVk)2926 angle::Result FramebufferVk::flushDeferredClears(ContextVk *contextVk)
2927 {
2928 if (mDeferredClears.empty())
2929 {
2930 return angle::Result::Continue;
2931 }
2932
2933 return contextVk->startRenderPass(getRotatedCompleteRenderArea(contextVk), nullptr, nullptr);
2934 }
2935
updateRenderPassReadOnlyDepthMode(ContextVk * contextVk,vk::RenderPassCommandBufferHelper * renderPass)2936 void FramebufferVk::updateRenderPassReadOnlyDepthMode(ContextVk *contextVk,
2937 vk::RenderPassCommandBufferHelper *renderPass)
2938 {
2939 bool readOnlyDepthStencilMode =
2940 getDepthStencilRenderTarget() && !getDepthStencilRenderTarget()->hasResolveAttachment() &&
2941 (mReadOnlyDepthFeedbackLoopMode || !renderPass->hasDepthStencilWriteOrClear());
2942
2943 // If readOnlyDepthStencil is false, we are switching out of read only mode due to depth write.
2944 // We must not be in the read only feedback loop mode because the logic in
2945 // DIRTY_BIT_READ_ONLY_DEPTH_FEEDBACK_LOOP_MODE should ensure we end the previous renderpass and
2946 // a new renderpass will start with feedback loop disabled.
2947 ASSERT(readOnlyDepthStencilMode || !mReadOnlyDepthFeedbackLoopMode);
2948
2949 renderPass->updateStartedRenderPassWithDepthMode(readOnlyDepthStencilMode);
2950 }
2951
onSwitchProgramFramebufferFetch(ContextVk * contextVk,bool programUsesFramebufferFetch)2952 void FramebufferVk::onSwitchProgramFramebufferFetch(ContextVk *contextVk,
2953 bool programUsesFramebufferFetch)
2954 {
2955 if (programUsesFramebufferFetch != mRenderPassDesc.getFramebufferFetchMode())
2956 {
2957 // Make sure framebuffer is recreated.
2958 mFramebuffer = nullptr;
2959 mCurrentFramebufferDesc.updateFramebufferFetchMode(programUsesFramebufferFetch);
2960
2961 mRenderPassDesc.setFramebufferFetchMode(programUsesFramebufferFetch);
2962 contextVk->onDrawFramebufferRenderPassDescChange(this, nullptr);
2963 }
2964 }
2965
2966 // FramebufferCache implementation.
destroy(RendererVk * rendererVk)2967 void FramebufferCache::destroy(RendererVk *rendererVk)
2968 {
2969 rendererVk->accumulateCacheStats(VulkanCacheType::Framebuffer, mCacheStats);
2970 mPayload.clear();
2971 }
2972
get(ContextVk * contextVk,const vk::FramebufferDesc & desc,vk::FramebufferHelper ** framebufferHelperOut)2973 bool FramebufferCache::get(ContextVk *contextVk,
2974 const vk::FramebufferDesc &desc,
2975 vk::FramebufferHelper **framebufferHelperOut)
2976 {
2977 auto iter = mPayload.find(desc);
2978 if (iter != mPayload.end())
2979 {
2980 *framebufferHelperOut = &iter->second;
2981 mCacheStats.hit();
2982 return true;
2983 }
2984
2985 mCacheStats.miss();
2986 return false;
2987 }
2988
insert(const vk::FramebufferDesc & desc,vk::FramebufferHelper && framebufferHelper)2989 void FramebufferCache::insert(const vk::FramebufferDesc &desc,
2990 vk::FramebufferHelper &&framebufferHelper)
2991 {
2992 mPayload.emplace(desc, std::move(framebufferHelper));
2993 }
2994
clear(ContextVk * contextVk)2995 void FramebufferCache::clear(ContextVk *contextVk)
2996 {
2997 for (auto &entry : mPayload)
2998 {
2999 vk::FramebufferHelper &tmpFB = entry.second;
3000 tmpFB.release(contextVk);
3001 }
3002 mPayload.clear();
3003 }
3004 } // namespace rx
3005