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