• 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/SurfaceVk.h"
25 #include "libANGLE/renderer/vulkan/vk_format_utils.h"
26 #include "libANGLE/renderer/vulkan/vk_renderer.h"
27 #include "libANGLE/renderer/vulkan/vk_resource.h"
28 
29 namespace rx
30 {
31 
32 namespace
33 {
34 // Clear values are only used when loadOp=Clear is set in clearWithRenderPassOp.  When starting a
35 // new render pass, the clear value is set to an unlikely value (bright pink) to stand out better
36 // in case of a bug.
37 constexpr VkClearValue kUninitializedClearValue = {{{0.95, 0.05, 0.95, 0.95}}};
38 
39 // The value to assign an alpha channel that's emulated.  The type is unsigned int, though it will
40 // automatically convert to the actual data type.
41 constexpr unsigned int kEmulatedAlphaValue = 1;
42 
HasSrcBlitFeature(vk::Renderer * renderer,RenderTargetVk * srcRenderTarget)43 bool HasSrcBlitFeature(vk::Renderer *renderer, RenderTargetVk *srcRenderTarget)
44 {
45     angle::FormatID srcFormatID = srcRenderTarget->getImageActualFormatID();
46     return renderer->hasImageFormatFeatureBits(srcFormatID, VK_FORMAT_FEATURE_BLIT_SRC_BIT);
47 }
48 
HasDstBlitFeature(vk::Renderer * renderer,RenderTargetVk * dstRenderTarget)49 bool HasDstBlitFeature(vk::Renderer *renderer, RenderTargetVk *dstRenderTarget)
50 {
51     angle::FormatID dstFormatID = dstRenderTarget->getImageActualFormatID();
52     return renderer->hasImageFormatFeatureBits(dstFormatID, VK_FORMAT_FEATURE_BLIT_DST_BIT);
53 }
54 
55 // Returns false if destination has any channel the source doesn't.  This means that channel was
56 // emulated and using the Vulkan blit command would overwrite that emulated channel.
AreSrcAndDstColorChannelsBlitCompatible(RenderTargetVk * srcRenderTarget,RenderTargetVk * dstRenderTarget)57 bool AreSrcAndDstColorChannelsBlitCompatible(RenderTargetVk *srcRenderTarget,
58                                              RenderTargetVk *dstRenderTarget)
59 {
60     const angle::Format &srcFormat = srcRenderTarget->getImageIntendedFormat();
61     const angle::Format &dstFormat = dstRenderTarget->getImageIntendedFormat();
62 
63     // Luminance/alpha formats are not renderable, so they can't have ended up in a framebuffer to
64     // participate in a blit.
65     ASSERT(!dstFormat.isLUMA() && !srcFormat.isLUMA());
66 
67     // All color formats have the red channel.
68     ASSERT(dstFormat.redBits > 0 && srcFormat.redBits > 0);
69 
70     return (dstFormat.greenBits > 0 || srcFormat.greenBits == 0) &&
71            (dstFormat.blueBits > 0 || srcFormat.blueBits == 0) &&
72            (dstFormat.alphaBits > 0 || srcFormat.alphaBits == 0);
73 }
74 
75 // Returns false if formats are not identical.  vkCmdResolveImage and resolve attachments both
76 // require identical formats between source and destination.  vkCmdBlitImage additionally requires
77 // the same for depth/stencil formats.
AreSrcAndDstFormatsIdentical(RenderTargetVk * srcRenderTarget,RenderTargetVk * dstRenderTarget)78 bool AreSrcAndDstFormatsIdentical(RenderTargetVk *srcRenderTarget, RenderTargetVk *dstRenderTarget)
79 {
80     angle::FormatID srcFormatID = srcRenderTarget->getImageActualFormatID();
81     angle::FormatID dstFormatID = dstRenderTarget->getImageActualFormatID();
82 
83     return srcFormatID == dstFormatID;
84 }
85 
AreSrcAndDstDepthStencilChannelsBlitCompatible(RenderTargetVk * srcRenderTarget,RenderTargetVk * dstRenderTarget)86 bool AreSrcAndDstDepthStencilChannelsBlitCompatible(RenderTargetVk *srcRenderTarget,
87                                                     RenderTargetVk *dstRenderTarget)
88 {
89     const angle::Format &srcFormat = srcRenderTarget->getImageIntendedFormat();
90     const angle::Format &dstFormat = dstRenderTarget->getImageIntendedFormat();
91 
92     return (dstFormat.depthBits > 0 || srcFormat.depthBits == 0) &&
93            (dstFormat.stencilBits > 0 || srcFormat.stencilBits == 0);
94 }
95 
EarlyAdjustFlipYForPreRotation(SurfaceRotation blitAngleIn,SurfaceRotation * blitAngleOut,bool * blitFlipYOut)96 void EarlyAdjustFlipYForPreRotation(SurfaceRotation blitAngleIn,
97                                     SurfaceRotation *blitAngleOut,
98                                     bool *blitFlipYOut)
99 {
100     switch (blitAngleIn)
101     {
102         case SurfaceRotation::Identity:
103             // No adjustments needed
104             break;
105         case SurfaceRotation::Rotated90Degrees:
106             *blitAngleOut = SurfaceRotation::Rotated90Degrees;
107             *blitFlipYOut = false;
108             break;
109         case SurfaceRotation::Rotated180Degrees:
110             *blitAngleOut = SurfaceRotation::Rotated180Degrees;
111             break;
112         case SurfaceRotation::Rotated270Degrees:
113             *blitAngleOut = SurfaceRotation::Rotated270Degrees;
114             *blitFlipYOut = false;
115             break;
116         default:
117             UNREACHABLE();
118             break;
119     }
120 }
121 
AdjustBlitAreaForPreRotation(SurfaceRotation framebufferAngle,const gl::Rectangle & blitAreaIn,const gl::Rectangle & framebufferDimensions,gl::Rectangle * blitAreaOut)122 void AdjustBlitAreaForPreRotation(SurfaceRotation framebufferAngle,
123                                   const gl::Rectangle &blitAreaIn,
124                                   const gl::Rectangle &framebufferDimensions,
125                                   gl::Rectangle *blitAreaOut)
126 {
127     switch (framebufferAngle)
128     {
129         case SurfaceRotation::Identity:
130             // No adjustments needed
131             break;
132         case SurfaceRotation::Rotated90Degrees:
133             blitAreaOut->x = blitAreaIn.y;
134             blitAreaOut->y = blitAreaIn.x;
135             std::swap(blitAreaOut->width, blitAreaOut->height);
136             break;
137         case SurfaceRotation::Rotated180Degrees:
138             blitAreaOut->x = framebufferDimensions.width - blitAreaIn.x - blitAreaIn.width;
139             blitAreaOut->y = framebufferDimensions.height - blitAreaIn.y - blitAreaIn.height;
140             break;
141         case SurfaceRotation::Rotated270Degrees:
142             blitAreaOut->x = framebufferDimensions.height - blitAreaIn.y - blitAreaIn.height;
143             blitAreaOut->y = framebufferDimensions.width - blitAreaIn.x - blitAreaIn.width;
144             std::swap(blitAreaOut->width, blitAreaOut->height);
145             break;
146         default:
147             UNREACHABLE();
148             break;
149     }
150 }
151 
AdjustDimensionsAndFlipForPreRotation(SurfaceRotation framebufferAngle,gl::Rectangle * framebufferDimensions,bool * flipX,bool * flipY)152 void AdjustDimensionsAndFlipForPreRotation(SurfaceRotation framebufferAngle,
153                                            gl::Rectangle *framebufferDimensions,
154                                            bool *flipX,
155                                            bool *flipY)
156 {
157     switch (framebufferAngle)
158     {
159         case SurfaceRotation::Identity:
160             // No adjustments needed
161             break;
162         case SurfaceRotation::Rotated90Degrees:
163             std::swap(framebufferDimensions->width, framebufferDimensions->height);
164             std::swap(*flipX, *flipY);
165             break;
166         case SurfaceRotation::Rotated180Degrees:
167             break;
168         case SurfaceRotation::Rotated270Degrees:
169             std::swap(framebufferDimensions->width, framebufferDimensions->height);
170             std::swap(*flipX, *flipY);
171             break;
172         default:
173             UNREACHABLE();
174             break;
175     }
176 }
177 
178 // When blitting, the source and destination areas are viewed like UVs.  For example, a 64x64
179 // texture if flipped should have an offset of 64 in either X or Y which corresponds to U or V of 1.
180 // On the other hand, when resolving, the source and destination areas are used as fragment
181 // coordinates to fetch from.  In that case, when flipped, the texture in the above example must
182 // have an offset of 63.
AdjustBlitResolveParametersForResolve(const gl::Rectangle & sourceArea,const gl::Rectangle & destArea,UtilsVk::BlitResolveParameters * params)183 void AdjustBlitResolveParametersForResolve(const gl::Rectangle &sourceArea,
184                                            const gl::Rectangle &destArea,
185                                            UtilsVk::BlitResolveParameters *params)
186 {
187     params->srcOffset[0] = sourceArea.x;
188     params->srcOffset[1] = sourceArea.y;
189     params->dstOffset[0] = destArea.x;
190     params->dstOffset[1] = destArea.y;
191 
192     if (sourceArea.isReversedX())
193     {
194         ASSERT(sourceArea.x > 0);
195         --params->srcOffset[0];
196     }
197     if (sourceArea.isReversedY())
198     {
199         ASSERT(sourceArea.y > 0);
200         --params->srcOffset[1];
201     }
202     if (destArea.isReversedX())
203     {
204         ASSERT(destArea.x > 0);
205         --params->dstOffset[0];
206     }
207     if (destArea.isReversedY())
208     {
209         ASSERT(destArea.y > 0);
210         --params->dstOffset[1];
211     }
212 }
213 
214 // Potentially make adjustments for pre-rotatation.  Depending on the angle some of the params need
215 // to be swapped and/or changes made to which axis are flipped.
AdjustBlitResolveParametersForPreRotation(SurfaceRotation framebufferAngle,SurfaceRotation srcFramebufferAngle,UtilsVk::BlitResolveParameters * params)216 void AdjustBlitResolveParametersForPreRotation(SurfaceRotation framebufferAngle,
217                                                SurfaceRotation srcFramebufferAngle,
218                                                UtilsVk::BlitResolveParameters *params)
219 {
220     switch (framebufferAngle)
221     {
222         case SurfaceRotation::Identity:
223             break;
224         case SurfaceRotation::Rotated90Degrees:
225             std::swap(params->stretch[0], params->stretch[1]);
226             std::swap(params->srcOffset[0], params->srcOffset[1]);
227             std::swap(params->rotatedOffsetFactor[0], params->rotatedOffsetFactor[1]);
228             std::swap(params->flipX, params->flipY);
229             if (srcFramebufferAngle == framebufferAngle)
230             {
231                 std::swap(params->dstOffset[0], params->dstOffset[1]);
232                 std::swap(params->stretch[0], params->stretch[1]);
233             }
234             break;
235         case SurfaceRotation::Rotated180Degrees:
236             // Combine flip info with api flip.
237             params->flipX = !params->flipX;
238             params->flipY = !params->flipY;
239             break;
240         case SurfaceRotation::Rotated270Degrees:
241             std::swap(params->stretch[0], params->stretch[1]);
242             std::swap(params->srcOffset[0], params->srcOffset[1]);
243             std::swap(params->rotatedOffsetFactor[0], params->rotatedOffsetFactor[1]);
244             if (srcFramebufferAngle == framebufferAngle)
245             {
246                 std::swap(params->stretch[0], params->stretch[1]);
247             }
248             // Combine flip info with api flip.
249             params->flipX = !params->flipX;
250             params->flipY = !params->flipY;
251             std::swap(params->flipX, params->flipY);
252 
253             break;
254         default:
255             UNREACHABLE();
256             break;
257     }
258 }
259 
MakeUnresolveAttachmentMask(const vk::RenderPassDesc & desc)260 vk::FramebufferNonResolveAttachmentMask MakeUnresolveAttachmentMask(const vk::RenderPassDesc &desc)
261 {
262     vk::FramebufferNonResolveAttachmentMask unresolveMask(
263         desc.getColorUnresolveAttachmentMask().bits());
264     if (desc.hasDepthUnresolveAttachment() || desc.hasStencilUnresolveAttachment())
265     {
266         // This mask only needs to know if the depth/stencil attachment needs to be unresolved, and
267         // is agnostic of the aspect.
268         unresolveMask.set(vk::kUnpackedDepthIndex);
269     }
270     return unresolveMask;
271 }
272 
IsAnyAttachment3DWithoutAllLayers(const RenderTargetCache<RenderTargetVk> & renderTargetCache,gl::DrawBufferMask colorAttachmentsMask,uint32_t framebufferLayerCount)273 bool IsAnyAttachment3DWithoutAllLayers(const RenderTargetCache<RenderTargetVk> &renderTargetCache,
274                                        gl::DrawBufferMask colorAttachmentsMask,
275                                        uint32_t framebufferLayerCount)
276 {
277     const auto &colorRenderTargets = renderTargetCache.getColors();
278     for (size_t colorIndexGL : colorAttachmentsMask)
279     {
280         RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
281         ASSERT(colorRenderTarget);
282 
283         const vk::ImageHelper &image = colorRenderTarget->getImageForRenderPass();
284 
285         if (image.getType() == VK_IMAGE_TYPE_3D && image.getExtents().depth > framebufferLayerCount)
286         {
287             return true;
288         }
289     }
290 
291     // Depth/stencil attachments cannot be 3D.
292     ASSERT(renderTargetCache.getDepthStencil() == nullptr ||
293            renderTargetCache.getDepthStencil()->getImageForRenderPass().getType() !=
294                VK_IMAGE_TYPE_3D);
295 
296     return false;
297 }
298 
299 // Should be called when the image type is VK_IMAGE_TYPE_3D.  Typically, the subresource, offsets
300 // and extents are filled in as if images are 2D layers (because depth slices of 3D images are also
301 // specified through "layers" everywhere, particularly by gl::ImageIndex).  This function adjusts
302 // the layer base/count and offsets.z/extents.z appropriately after these structs are set up.
AdjustLayersAndDepthFor3DImages(VkImageSubresourceLayers * subresource,VkOffset3D * offsetsStart,VkOffset3D * offsetsEnd)303 void AdjustLayersAndDepthFor3DImages(VkImageSubresourceLayers *subresource,
304                                      VkOffset3D *offsetsStart,
305                                      VkOffset3D *offsetsEnd)
306 {
307     // The struct must be set up as if the image was 2D array.
308     ASSERT(offsetsStart->z == 0);
309     ASSERT(offsetsEnd->z == 1);
310 
311     offsetsStart->z = subresource->baseArrayLayer;
312     offsetsEnd->z   = subresource->baseArrayLayer + subresource->layerCount;
313 
314     subresource->baseArrayLayer = 0;
315     subresource->layerCount     = 1;
316 }
317 
AllowAddingResolveAttachmentsToSubpass(const vk::RenderPassDesc & desc)318 bool AllowAddingResolveAttachmentsToSubpass(const vk::RenderPassDesc &desc)
319 {
320     // When in render-to-texture emulation mode, there are already resolve attachments present, and
321     // render pass compatibility rules would require packing those first before packing resolve
322     // attachments that may be added later (through glBlitFramebuffer).  While supporting that is
323     // not onerous, the code is simplified by not supporting this combination.  In practice no
324     // application should be mixing MSRTT textures and and truly multisampled textures in the same
325     // framebuffer (they could be using MSRTT for both).
326     //
327     // For the same reason, adding resolve attachments after the fact is disabled with YUV resolve.
328     return !desc.isRenderToTexture() && !desc.hasYUVResolveAttachment();
329 }
330 }  // anonymous namespace
331 
FramebufferVk(vk::Renderer * renderer,const gl::FramebufferState & state)332 FramebufferVk::FramebufferVk(vk::Renderer *renderer, const gl::FramebufferState &state)
333     : FramebufferImpl(state), mBackbuffer(nullptr), mActiveColorComponentMasksForClear(0)
334 {
335     if (mState.isDefault())
336     {
337         // These are immutable for system default framebuffer.
338         mCurrentFramebufferDesc.updateLayerCount(1);
339         mCurrentFramebufferDesc.updateIsMultiview(false);
340     }
341 
342     mIsCurrentFramebufferCached = !renderer->getFeatures().supportsImagelessFramebuffer.enabled;
343     mIsYUVResolve               = false;
344 }
345 
346 FramebufferVk::~FramebufferVk() = default;
347 
destroy(const gl::Context * context)348 void FramebufferVk::destroy(const gl::Context *context)
349 {
350     ContextVk *contextVk = vk::GetImpl(context);
351 
352     if (mFragmentShadingRateImage.valid())
353     {
354         vk::Renderer *renderer = contextVk->getRenderer();
355         mFragmentShadingRateImageView.release(renderer, mFragmentShadingRateImage.getResourceUse());
356         mFragmentShadingRateImage.releaseImage(renderer);
357     }
358 
359     releaseCurrentFramebuffer(contextVk);
360 }
361 
insertCache(ContextVk * contextVk,const vk::FramebufferDesc & desc,vk::FramebufferHelper && newFramebuffer)362 void FramebufferVk::insertCache(ContextVk *contextVk,
363                                 const vk::FramebufferDesc &desc,
364                                 vk::FramebufferHelper &&newFramebuffer)
365 {
366     // Add it into per share group cache
367     contextVk->getShareGroup()->getFramebufferCache().insert(contextVk, desc,
368                                                              std::move(newFramebuffer));
369 
370     // Create a refcounted cache key object and have each attachment keep a refcount to it so that
371     // it can be destroyed promptly if those attachments change.
372     const vk::SharedFramebufferCacheKey sharedFramebufferCacheKey =
373         vk::CreateSharedFramebufferCacheKey(desc);
374 
375     // Ask each attachment to hold a reference to the cache so that when any attachment is
376     // released, the cache can be destroyed.
377     const auto &colorRenderTargets = mRenderTargetCache.getColors();
378     for (size_t colorIndexGL : mState.getColorAttachmentsMask())
379     {
380         colorRenderTargets[colorIndexGL]->onNewFramebuffer(sharedFramebufferCacheKey);
381     }
382 
383     if (getDepthStencilRenderTarget())
384     {
385         getDepthStencilRenderTarget()->onNewFramebuffer(sharedFramebufferCacheKey);
386     }
387 }
388 
discard(const gl::Context * context,size_t count,const GLenum * attachments)389 angle::Result FramebufferVk::discard(const gl::Context *context,
390                                      size_t count,
391                                      const GLenum *attachments)
392 {
393     return invalidate(context, count, attachments);
394 }
395 
invalidate(const gl::Context * context,size_t count,const GLenum * attachments)396 angle::Result FramebufferVk::invalidate(const gl::Context *context,
397                                         size_t count,
398                                         const GLenum *attachments)
399 {
400     ContextVk *contextVk = vk::GetImpl(context);
401 
402     ANGLE_TRY(invalidateImpl(contextVk, count, attachments, false,
403                              getRotatedCompleteRenderArea(contextVk)));
404     return angle::Result::Continue;
405 }
406 
invalidateSub(const gl::Context * context,size_t count,const GLenum * attachments,const gl::Rectangle & area)407 angle::Result FramebufferVk::invalidateSub(const gl::Context *context,
408                                            size_t count,
409                                            const GLenum *attachments,
410                                            const gl::Rectangle &area)
411 {
412     ContextVk *contextVk = vk::GetImpl(context);
413 
414     const gl::Rectangle nonRotatedCompleteRenderArea = getNonRotatedCompleteRenderArea();
415     gl::Rectangle rotatedInvalidateArea;
416     RotateRectangle(contextVk->getRotationDrawFramebuffer(),
417                     contextVk->isViewportFlipEnabledForDrawFBO(),
418                     nonRotatedCompleteRenderArea.width, nonRotatedCompleteRenderArea.height, area,
419                     &rotatedInvalidateArea);
420 
421     // If invalidateSub() covers the whole framebuffer area, make it behave as invalidate().
422     // The invalidate area is clipped to the render area for use inside invalidateImpl.
423     const gl::Rectangle completeRenderArea = getRotatedCompleteRenderArea(contextVk);
424     if (ClipRectangle(rotatedInvalidateArea, completeRenderArea, &rotatedInvalidateArea) &&
425         rotatedInvalidateArea == completeRenderArea)
426     {
427         return invalidate(context, count, attachments);
428     }
429 
430     // If there are deferred clears, restage them.  syncState may have accumulated deferred clears,
431     // but if the framebuffer's attachments are used after this call not through the framebuffer,
432     // those clears wouldn't get flushed otherwise (for example as the destination of
433     // glCopyTex[Sub]Image, shader storage image, etc).
434     restageDeferredClears(contextVk);
435 
436     if (contextVk->hasActiveRenderPass() &&
437         rotatedInvalidateArea.encloses(contextVk->getStartedRenderPassCommands().getRenderArea()))
438     {
439         // Because the render pass's render area is within the invalidated area, it is fine for
440         // invalidateImpl() to use a storeOp of DONT_CARE (i.e. fine to not store the contents of
441         // the invalidated area).
442         ANGLE_TRY(invalidateImpl(contextVk, count, attachments, true, rotatedInvalidateArea));
443     }
444     else
445     {
446         ANGLE_VK_PERF_WARNING(
447             contextVk, GL_DEBUG_SEVERITY_LOW,
448             "InvalidateSubFramebuffer ignored due to area not covering the render area");
449     }
450 
451     return angle::Result::Continue;
452 }
453 
clear(const gl::Context * context,GLbitfield mask)454 angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
455 {
456     ANGLE_TRACE_EVENT0("gpu.angle", "FramebufferVk::clear");
457     ContextVk *contextVk = vk::GetImpl(context);
458 
459     bool clearColor   = IsMaskFlagSet(mask, static_cast<GLbitfield>(GL_COLOR_BUFFER_BIT));
460     bool clearDepth   = IsMaskFlagSet(mask, static_cast<GLbitfield>(GL_DEPTH_BUFFER_BIT));
461     bool clearStencil = IsMaskFlagSet(mask, static_cast<GLbitfield>(GL_STENCIL_BUFFER_BIT));
462     gl::DrawBufferMask clearColorBuffers;
463     if (clearColor)
464     {
465         clearColorBuffers = mState.getEnabledDrawBuffers();
466     }
467 
468     const VkClearColorValue &clearColorValue = contextVk->getClearColorValue().color;
469     const VkClearDepthStencilValue &clearDepthStencilValue =
470         contextVk->getClearDepthStencilValue().depthStencil;
471 
472     return clearImpl(context, clearColorBuffers, clearDepth, clearStencil, clearColorValue,
473                      clearDepthStencilValue);
474 }
475 
adjustFloatClearColorPrecision(const VkClearColorValue & color,const angle::Format & colorFormat)476 VkClearColorValue adjustFloatClearColorPrecision(const VkClearColorValue &color,
477                                                  const angle::Format &colorFormat)
478 {
479     // Truncate x to b bits: round(x * (2^b-1)) / (2^b-1)
480     // Implemented as floor(x * ((1 << b) - 1) + 0.5) / ((1 << b) - 1)
481 
482     float floatClearColorRed = color.float32[0];
483     GLuint targetRedBits     = colorFormat.redBits;
484     floatClearColorRed       = floor(floatClearColorRed * ((1 << targetRedBits) - 1) + 0.5f);
485     floatClearColorRed       = floatClearColorRed / ((1 << targetRedBits) - 1);
486 
487     float floatClearColorGreen = color.float32[1];
488     GLuint targetGreenBits     = colorFormat.greenBits;
489     floatClearColorGreen       = floor(floatClearColorGreen * ((1 << targetGreenBits) - 1) + 0.5f);
490     floatClearColorGreen       = floatClearColorGreen / ((1 << targetGreenBits) - 1);
491 
492     float floatClearColorBlue = color.float32[2];
493     GLuint targetBlueBits     = colorFormat.blueBits;
494     floatClearColorBlue       = floor(floatClearColorBlue * ((1 << targetBlueBits) - 1) + 0.5f);
495     floatClearColorBlue       = floatClearColorBlue / ((1 << targetBlueBits) - 1);
496 
497     float floatClearColorAlpha = color.float32[3];
498     GLuint targetAlphaBits     = colorFormat.alphaBits;
499     floatClearColorAlpha       = floor(floatClearColorAlpha * ((1 << targetAlphaBits) - 1) + 0.5f);
500     floatClearColorAlpha       = floatClearColorAlpha / ((1 << targetAlphaBits) - 1);
501 
502     VkClearColorValue adjustedClearColor = color;
503     adjustedClearColor.float32[0]        = floatClearColorRed;
504     adjustedClearColor.float32[1]        = floatClearColorGreen;
505     adjustedClearColor.float32[2]        = floatClearColorBlue;
506     adjustedClearColor.float32[3]        = floatClearColorAlpha;
507 
508     return adjustedClearColor;
509 }
510 
clearImpl(const gl::Context * context,gl::DrawBufferMask clearColorBuffers,bool clearDepth,bool clearStencil,const VkClearColorValue & clearColorValue,const VkClearDepthStencilValue & clearDepthStencilValue)511 angle::Result FramebufferVk::clearImpl(const gl::Context *context,
512                                        gl::DrawBufferMask clearColorBuffers,
513                                        bool clearDepth,
514                                        bool clearStencil,
515                                        const VkClearColorValue &clearColorValue,
516                                        const VkClearDepthStencilValue &clearDepthStencilValue)
517 {
518     ContextVk *contextVk = vk::GetImpl(context);
519 
520     const gl::Rectangle scissoredRenderArea = getRotatedScissoredRenderArea(contextVk);
521     if (scissoredRenderArea.width == 0 || scissoredRenderArea.height == 0)
522     {
523         restageDeferredClears(contextVk);
524         return angle::Result::Continue;
525     }
526 
527     // This function assumes that only enabled attachments are asked to be cleared.
528     ASSERT((clearColorBuffers & mState.getEnabledDrawBuffers()) == clearColorBuffers);
529     ASSERT(!clearDepth || mState.getDepthAttachment() != nullptr);
530     ASSERT(!clearStencil || mState.getStencilAttachment() != nullptr);
531 
532     gl::BlendStateExt::ColorMaskStorage::Type colorMasks = contextVk->getClearColorMasks();
533     bool clearColor                                      = clearColorBuffers.any();
534 
535     // When this function is called, there should always be something to clear.
536     ASSERT(clearColor || clearDepth || clearStencil);
537 
538     gl::DrawBuffersArray<VkClearColorValue> adjustedClearColorValues;
539     const gl::DrawBufferMask colorAttachmentMask = mState.getColorAttachmentsMask();
540     const auto &colorRenderTargets               = mRenderTargetCache.getColors();
541     bool anyAttachmentWithColorspaceOverride     = false;
542     for (size_t colorIndexGL = 0; colorIndexGL < colorAttachmentMask.size(); ++colorIndexGL)
543     {
544         if (colorAttachmentMask[colorIndexGL])
545         {
546             adjustedClearColorValues[colorIndexGL] = clearColorValue;
547 
548             RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
549             ASSERT(colorRenderTarget);
550 
551             // If a rendertarget has colorspace overrides, we need to clear with a draw
552             // to make sure the colorspace override is honored.
553             anyAttachmentWithColorspaceOverride =
554                 anyAttachmentWithColorspaceOverride ||
555                 colorRenderTarget->hasColorspaceOverrideForWrite();
556 
557             if (colorRenderTarget->isYuvResolve())
558             {
559                 // OpenGLES spec says "clear color should be defined in yuv color space and so
560                 // floating point r, g, and b value will be mapped to corresponding y, u and v
561                 // value" https://registry.khronos.org/OpenGL/extensions/EXT/EXT_YUV_target.txt.
562                 // But vulkan spec says "Values in the G, B, and R channels of the color
563                 // attachment will be written to the Y, CB, and CR channels of the external
564                 // format image, respectively." So we have to adjust the component mapping from
565                 // GL order to vulkan order.
566                 adjustedClearColorValues[colorIndexGL].float32[0] = clearColorValue.float32[2];
567                 adjustedClearColorValues[colorIndexGL].float32[1] = clearColorValue.float32[0];
568                 adjustedClearColorValues[colorIndexGL].float32[2] = clearColorValue.float32[1];
569             }
570             else if (contextVk->getFeatures().adjustClearColorPrecision.enabled)
571             {
572                 const angle::FormatID colorRenderTargetFormat =
573                     colorRenderTarget->getImageForRenderPass().getActualFormatID();
574                 if (colorRenderTargetFormat == angle::FormatID::R5G5B5A1_UNORM)
575                 {
576                     // Temporary workaround for https://issuetracker.google.com/292282210 to avoid
577                     // dithering being automatically applied
578                     adjustedClearColorValues[colorIndexGL] = adjustFloatClearColorPrecision(
579                         clearColorValue, angle::Format::Get(colorRenderTargetFormat));
580                 }
581             }
582         }
583     }
584 
585     const uint8_t stencilMask =
586         static_cast<uint8_t>(contextVk->getState().getDepthStencilState().stencilWritemask);
587 
588     // The front-end should ensure we don't attempt to clear color if all channels are masked.
589     ASSERT(!clearColor || colorMasks != 0);
590     // The front-end should ensure we don't attempt to clear depth if depth write is disabled.
591     ASSERT(!clearDepth || contextVk->getState().getDepthStencilState().depthMask);
592     // The front-end should ensure we don't attempt to clear stencil if all bits are masked.
593     ASSERT(!clearStencil || stencilMask != 0);
594 
595     // Make sure to close the render pass now if in read-only depth/stencil feedback loop mode and
596     // depth/stencil is being cleared.
597     if (clearDepth || clearStencil)
598     {
599         ANGLE_TRY(contextVk->updateRenderPassDepthFeedbackLoopMode(
600             clearDepth ? UpdateDepthFeedbackLoopReason::Clear : UpdateDepthFeedbackLoopReason::None,
601             clearStencil ? UpdateDepthFeedbackLoopReason::Clear
602                          : UpdateDepthFeedbackLoopReason::None));
603     }
604 
605     const bool scissoredClear = scissoredRenderArea != getRotatedCompleteRenderArea(contextVk);
606 
607     // We use the draw path if scissored clear, or color or stencil are masked.  Note that depth
608     // clearing is already disabled if there's a depth mask.
609     const bool maskedClearColor = clearColor && (mActiveColorComponentMasksForClear & colorMasks) !=
610                                                     mActiveColorComponentMasksForClear;
611     const bool maskedClearStencil = clearStencil && stencilMask != 0xFF;
612 
613     bool clearColorWithDraw =
614         clearColor && (maskedClearColor || scissoredClear || anyAttachmentWithColorspaceOverride);
615     bool clearDepthWithDraw   = clearDepth && scissoredClear;
616     bool clearStencilWithDraw = clearStencil && (maskedClearStencil || scissoredClear);
617 
618     const bool isMidRenderPassClear =
619         contextVk->hasStartedRenderPassWithQueueSerial(mLastRenderPassQueueSerial) &&
620         !contextVk->getStartedRenderPassCommands().getCommandBuffer().empty();
621     if (isMidRenderPassClear)
622     {
623         // Emit debug-util markers for this mid-render-pass clear
624         ANGLE_TRY(
625             contextVk->handleGraphicsEventLog(rx::GraphicsEventCmdBuf::InRenderPassCmdBufQueryCmd));
626     }
627     else
628     {
629         ASSERT(!contextVk->hasActiveRenderPass() ||
630                contextVk->hasStartedRenderPassWithQueueSerial(mLastRenderPassQueueSerial));
631         // Emit debug-util markers for this outside-render-pass clear
632         ANGLE_TRY(
633             contextVk->handleGraphicsEventLog(rx::GraphicsEventCmdBuf::InOutsideCmdBufQueryCmd));
634     }
635 
636     const bool preferDrawOverClearAttachments =
637         contextVk->getFeatures().preferDrawClearOverVkCmdClearAttachments.enabled;
638 
639     // Merge current clears with the deferred clears, then proceed with only processing deferred
640     // clears.  This simplifies the clear paths such that they don't need to consider both the
641     // current and deferred clears.  Additionally, it avoids needing to undo an unresolve
642     // operation; say attachment A is deferred cleared and multisampled-render-to-texture
643     // attachment B is currently cleared.  Assuming a render pass needs to start (because for
644     // example attachment C needs to clear with a draw path), starting one with only deferred
645     // clears and then applying the current clears won't work as attachment B is unresolved, and
646     // there are no facilities to undo that.
647     if (preferDrawOverClearAttachments && isMidRenderPassClear)
648     {
649         // On buggy hardware, prefer to clear with a draw call instead of vkCmdClearAttachments.
650         // Note that it's impossible to have deferred clears in the middle of the render pass.
651         ASSERT(!mDeferredClears.any());
652 
653         clearColorWithDraw   = clearColor;
654         clearDepthWithDraw   = clearDepth;
655         clearStencilWithDraw = clearStencil;
656     }
657     else
658     {
659         gl::DrawBufferMask clearColorDrawBuffersMask;
660         if (clearColor && !clearColorWithDraw)
661         {
662             clearColorDrawBuffersMask = clearColorBuffers;
663         }
664 
665         mergeClearsWithDeferredClears(clearColorDrawBuffersMask, clearDepth && !clearDepthWithDraw,
666                                       clearStencil && !clearStencilWithDraw,
667                                       adjustedClearColorValues, clearDepthStencilValue);
668     }
669 
670     // If any deferred clears, we can further defer them, clear them with vkCmdClearAttachments or
671     // flush them if necessary.
672     if (mDeferredClears.any())
673     {
674         const bool clearAnyWithDraw =
675             clearColorWithDraw || clearDepthWithDraw || clearStencilWithDraw;
676 
677         bool isAnyAttachment3DWithoutAllLayers =
678             IsAnyAttachment3DWithoutAllLayers(mRenderTargetCache, mState.getColorAttachmentsMask(),
679                                               mCurrentFramebufferDesc.getLayerCount());
680 
681         // If we are in an active renderpass that has recorded commands and the framebuffer hasn't
682         // changed, inline the clear.
683         if (isMidRenderPassClear)
684         {
685             ANGLE_VK_PERF_WARNING(
686                 contextVk, GL_DEBUG_SEVERITY_LOW,
687                 "Clear effectively discarding previous draw call results. Suggest earlier Clear "
688                 "followed by masked color or depth/stencil draw calls instead, or "
689                 "glInvalidateFramebuffer to discard data instead");
690 
691             ASSERT(!preferDrawOverClearAttachments);
692 
693             // clearWithCommand will operate on deferred clears.
694             clearWithCommand(contextVk, scissoredRenderArea, ClearWithCommand::OptimizeWithLoadOp,
695                              &mDeferredClears);
696 
697             // clearWithCommand will clear only those attachments that have been used in the render
698             // pass, and removes them from mDeferredClears.  Any deferred clears that are left can
699             // be performed with a renderpass loadOp.
700             if (mDeferredClears.any())
701             {
702                 clearWithLoadOp(contextVk);
703             }
704         }
705         else
706         {
707             if (contextVk->hasActiveRenderPass())
708             {
709                 // Typically, clears are deferred such that it's impossible to have a render pass
710                 // opened without any additional commands recorded on it.  This is not true for some
711                 // corner cases, such as with 3D or external attachments.  In those cases, a clear
712                 // can open a render pass that's otherwise empty, and additional clears can continue
713                 // to be accumulated in the render pass loadOps.
714                 ASSERT(isAnyAttachment3DWithoutAllLayers || hasAnyExternalAttachments());
715                 clearWithLoadOp(contextVk);
716             }
717 
718             // This path will defer the current clears along with deferred clears.  This won't work
719             // if any attachment needs to be subsequently cleared with a draw call.  In that case,
720             // flush deferred clears, which will start a render pass with deferred clear values.
721             // The subsequent draw call will then operate on the cleared attachments.
722             //
723             // Additionally, if the framebuffer is layered, any attachment is 3D and it has a larger
724             // depth than the framebuffer layers, clears cannot be deferred.  This is because the
725             // clear may later need to be flushed with vkCmdClearColorImage, which cannot partially
726             // clear the 3D texture.  In that case, the clears are flushed immediately too.
727             //
728             // For external images such as from AHBs, the clears are not deferred so that they are
729             // definitely applied before the application uses them outside of the control of ANGLE.
730             if (clearAnyWithDraw || isAnyAttachment3DWithoutAllLayers ||
731                 hasAnyExternalAttachments())
732             {
733                 ANGLE_TRY(flushDeferredClears(contextVk));
734             }
735             else
736             {
737                 restageDeferredClears(contextVk);
738             }
739         }
740 
741         // If nothing left to clear, early out.
742         if (!clearAnyWithDraw)
743         {
744             ASSERT(mDeferredClears.empty());
745             return angle::Result::Continue;
746         }
747     }
748 
749     if (!clearColorWithDraw)
750     {
751         clearColorBuffers.reset();
752     }
753 
754     // If we reach here simply because the clear is scissored (as opposed to masked), use
755     // vkCmdClearAttachments to clear the attachments.  The attachments that are masked will
756     // continue to use a draw call.  For depth, vkCmdClearAttachments can always be used, and no
757     // shader/pipeline support would then be required (though this is pending removal of the
758     // preferDrawOverClearAttachments workaround).
759     //
760     // A potential optimization is to use loadOp=Clear for scissored clears, but care needs to be
761     // taken to either break the render pass on growRenderArea(), or to turn the op back to Load and
762     // revert to vkCmdClearAttachments.  This is not currently deemed necessary.
763     if (((clearColorBuffers.any() && !mEmulatedAlphaAttachmentMask.any() && !maskedClearColor) ||
764          clearDepthWithDraw || (clearStencilWithDraw && !maskedClearStencil)) &&
765         !preferDrawOverClearAttachments && !anyAttachmentWithColorspaceOverride)
766     {
767         if (!contextVk->hasActiveRenderPass())
768         {
769             // Start a new render pass if necessary to record the commands.
770             vk::RenderPassCommandBuffer *commandBuffer;
771             gl::Rectangle renderArea = getRenderArea(contextVk);
772             ANGLE_TRY(contextVk->startRenderPass(renderArea, &commandBuffer, nullptr));
773         }
774 
775         // Build clear values
776         vk::ClearValuesArray clears;
777         if (!maskedClearColor && !mEmulatedAlphaAttachmentMask.any())
778         {
779             VkClearValue colorClearValue = {};
780             for (size_t colorIndexGL : clearColorBuffers)
781             {
782                 colorClearValue.color = adjustedClearColorValues[colorIndexGL];
783                 clears.store(static_cast<uint32_t>(colorIndexGL), VK_IMAGE_ASPECT_COLOR_BIT,
784                              colorClearValue);
785             }
786             clearColorBuffers.reset();
787         }
788         VkImageAspectFlags dsAspectFlags = 0;
789         if (clearDepthWithDraw)
790         {
791             dsAspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
792             clearDepthWithDraw = false;
793         }
794         if (clearStencilWithDraw && !maskedClearStencil)
795         {
796             dsAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
797             clearStencilWithDraw = false;
798         }
799         if (dsAspectFlags != 0)
800         {
801             VkClearValue dsClearValue = {};
802             dsClearValue.depthStencil = clearDepthStencilValue;
803             clears.store(vk::kUnpackedDepthIndex, dsAspectFlags, dsClearValue);
804         }
805 
806         clearWithCommand(contextVk, scissoredRenderArea, ClearWithCommand::Always, &clears);
807 
808         if (!clearColorBuffers.any() && !clearStencilWithDraw)
809         {
810             ASSERT(!clearDepthWithDraw);
811             return angle::Result::Continue;
812         }
813     }
814 
815     // The most costly clear mode is when we need to mask out specific color channels or stencil
816     // bits. This can only be done with a draw call.
817     return clearWithDraw(contextVk, scissoredRenderArea, clearColorBuffers, clearDepthWithDraw,
818                          clearStencilWithDraw, colorMasks, stencilMask, adjustedClearColorValues,
819                          clearDepthStencilValue);
820 }
821 
clearBufferfv(const gl::Context * context,GLenum buffer,GLint drawbuffer,const GLfloat * values)822 angle::Result FramebufferVk::clearBufferfv(const gl::Context *context,
823                                            GLenum buffer,
824                                            GLint drawbuffer,
825                                            const GLfloat *values)
826 {
827     VkClearValue clearValue = {};
828 
829     bool clearDepth = false;
830     gl::DrawBufferMask clearColorBuffers;
831 
832     if (buffer == GL_DEPTH)
833     {
834         clearDepth                    = true;
835         clearValue.depthStencil.depth = values[0];
836     }
837     else
838     {
839         clearColorBuffers.set(drawbuffer);
840         clearValue.color.float32[0] = values[0];
841         clearValue.color.float32[1] = values[1];
842         clearValue.color.float32[2] = values[2];
843         clearValue.color.float32[3] = values[3];
844     }
845 
846     return clearImpl(context, clearColorBuffers, clearDepth, false, clearValue.color,
847                      clearValue.depthStencil);
848 }
849 
clearBufferuiv(const gl::Context * context,GLenum buffer,GLint drawbuffer,const GLuint * values)850 angle::Result FramebufferVk::clearBufferuiv(const gl::Context *context,
851                                             GLenum buffer,
852                                             GLint drawbuffer,
853                                             const GLuint *values)
854 {
855     VkClearValue clearValue = {};
856 
857     gl::DrawBufferMask clearColorBuffers;
858     clearColorBuffers.set(drawbuffer);
859 
860     clearValue.color.uint32[0] = values[0];
861     clearValue.color.uint32[1] = values[1];
862     clearValue.color.uint32[2] = values[2];
863     clearValue.color.uint32[3] = values[3];
864 
865     return clearImpl(context, clearColorBuffers, false, false, clearValue.color,
866                      clearValue.depthStencil);
867 }
868 
clearBufferiv(const gl::Context * context,GLenum buffer,GLint drawbuffer,const GLint * values)869 angle::Result FramebufferVk::clearBufferiv(const gl::Context *context,
870                                            GLenum buffer,
871                                            GLint drawbuffer,
872                                            const GLint *values)
873 {
874     VkClearValue clearValue = {};
875 
876     bool clearStencil = false;
877     gl::DrawBufferMask clearColorBuffers;
878 
879     if (buffer == GL_STENCIL)
880     {
881         clearStencil                    = true;
882         clearValue.depthStencil.stencil = static_cast<uint8_t>(values[0]);
883     }
884     else
885     {
886         clearColorBuffers.set(drawbuffer);
887         clearValue.color.int32[0] = values[0];
888         clearValue.color.int32[1] = values[1];
889         clearValue.color.int32[2] = values[2];
890         clearValue.color.int32[3] = values[3];
891     }
892 
893     return clearImpl(context, clearColorBuffers, false, clearStencil, clearValue.color,
894                      clearValue.depthStencil);
895 }
896 
clearBufferfi(const gl::Context * context,GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)897 angle::Result FramebufferVk::clearBufferfi(const gl::Context *context,
898                                            GLenum buffer,
899                                            GLint drawbuffer,
900                                            GLfloat depth,
901                                            GLint stencil)
902 {
903     VkClearValue clearValue = {};
904 
905     clearValue.depthStencil.depth   = depth;
906     clearValue.depthStencil.stencil = static_cast<uint8_t>(stencil);
907 
908     return clearImpl(context, gl::DrawBufferMask(), true, true, clearValue.color,
909                      clearValue.depthStencil);
910 }
911 
getImplementationColorReadFormat(const gl::Context * context) const912 const gl::InternalFormat &FramebufferVk::getImplementationColorReadFormat(
913     const gl::Context *context) const
914 {
915     ContextVk *contextVk       = vk::GetImpl(context);
916     GLenum sizedFormat         = mState.getReadAttachment()->getFormat().info->sizedInternalFormat;
917     const vk::Format &vkFormat = contextVk->getRenderer()->getFormat(sizedFormat);
918     GLenum implFormat = vkFormat.getActualRenderableImageFormat().fboImplementationInternalFormat;
919     return gl::GetSizedInternalFormatInfo(implFormat);
920 }
921 
readPixels(const gl::Context * context,const gl::Rectangle & area,GLenum format,GLenum type,const gl::PixelPackState & pack,gl::Buffer * packBuffer,void * pixels)922 angle::Result FramebufferVk::readPixels(const gl::Context *context,
923                                         const gl::Rectangle &area,
924                                         GLenum format,
925                                         GLenum type,
926                                         const gl::PixelPackState &pack,
927                                         gl::Buffer *packBuffer,
928                                         void *pixels)
929 {
930     // Clip read area to framebuffer.
931     const gl::Extents &fbSize = getState().getReadPixelsAttachment(format)->getSize();
932     const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
933     ContextVk *contextVk = vk::GetImpl(context);
934 
935     gl::Rectangle clippedArea;
936     if (!ClipRectangle(area, fbRect, &clippedArea))
937     {
938         // nothing to read
939         return angle::Result::Continue;
940     }
941 
942     // Flush any deferred clears.
943     ANGLE_TRY(flushDeferredClears(contextVk));
944 
945     GLuint outputSkipBytes = 0;
946     PackPixelsParams params;
947     ANGLE_TRY(vk::ImageHelper::GetReadPixelsParams(contextVk, pack, packBuffer, format, type, area,
948                                                    clippedArea, &params, &outputSkipBytes));
949 
950     bool flipY = contextVk->isViewportFlipEnabledForReadFBO();
951     switch (params.rotation = contextVk->getRotationReadFramebuffer())
952     {
953         case SurfaceRotation::Identity:
954             // Do not rotate gl_Position (surface matches the device's orientation):
955             if (flipY)
956             {
957                 params.area.y = fbRect.height - clippedArea.y - clippedArea.height;
958             }
959             break;
960         case SurfaceRotation::Rotated90Degrees:
961             // Rotate gl_Position 90 degrees:
962             params.area.x = clippedArea.y;
963             params.area.y =
964                 flipY ? clippedArea.x : fbRect.width - clippedArea.x - clippedArea.width;
965             std::swap(params.area.width, params.area.height);
966             break;
967         case SurfaceRotation::Rotated180Degrees:
968             // Rotate gl_Position 180 degrees:
969             params.area.x = fbRect.width - clippedArea.x - clippedArea.width;
970             params.area.y =
971                 flipY ? clippedArea.y : fbRect.height - clippedArea.y - clippedArea.height;
972             break;
973         case SurfaceRotation::Rotated270Degrees:
974             // Rotate gl_Position 270 degrees:
975             params.area.x = fbRect.height - clippedArea.y - clippedArea.height;
976             params.area.y =
977                 flipY ? fbRect.width - clippedArea.x - clippedArea.width : clippedArea.x;
978             std::swap(params.area.width, params.area.height);
979             break;
980         default:
981             UNREACHABLE();
982             break;
983     }
984     if (flipY)
985     {
986         params.reverseRowOrder = !params.reverseRowOrder;
987     }
988 
989     ANGLE_TRY(readPixelsImpl(contextVk, params.area, params, getReadPixelsAspectFlags(format),
990                              getReadPixelsRenderTarget(format),
991                              static_cast<uint8_t *>(pixels) + outputSkipBytes));
992     return angle::Result::Continue;
993 }
994 
getColorDrawRenderTarget(size_t colorIndexGL) const995 RenderTargetVk *FramebufferVk::getColorDrawRenderTarget(size_t colorIndexGL) const
996 {
997     RenderTargetVk *renderTarget = mRenderTargetCache.getColorDraw(mState, colorIndexGL);
998     ASSERT(renderTarget && renderTarget->getImageForRenderPass().valid());
999     return renderTarget;
1000 }
1001 
getColorReadRenderTarget() const1002 RenderTargetVk *FramebufferVk::getColorReadRenderTarget() const
1003 {
1004     RenderTargetVk *renderTarget = mRenderTargetCache.getColorRead(mState);
1005     ASSERT(renderTarget && renderTarget->getImageForRenderPass().valid());
1006     return renderTarget;
1007 }
1008 
getReadPixelsRenderTarget(GLenum format) const1009 RenderTargetVk *FramebufferVk::getReadPixelsRenderTarget(GLenum format) const
1010 {
1011     switch (format)
1012     {
1013         case GL_DEPTH_COMPONENT:
1014         case GL_STENCIL_INDEX_OES:
1015         case GL_DEPTH_STENCIL_OES:
1016             return getDepthStencilRenderTarget();
1017         default:
1018             return getColorReadRenderTarget();
1019     }
1020 }
1021 
getReadPixelsAspectFlags(GLenum format) const1022 VkImageAspectFlagBits FramebufferVk::getReadPixelsAspectFlags(GLenum format) const
1023 {
1024     switch (format)
1025     {
1026         case GL_DEPTH_COMPONENT:
1027             return VK_IMAGE_ASPECT_DEPTH_BIT;
1028         case GL_STENCIL_INDEX_OES:
1029             return VK_IMAGE_ASPECT_STENCIL_BIT;
1030         case GL_DEPTH_STENCIL_OES:
1031             return vk::IMAGE_ASPECT_DEPTH_STENCIL;
1032         default:
1033             return VK_IMAGE_ASPECT_COLOR_BIT;
1034     }
1035 }
1036 
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)1037 angle::Result FramebufferVk::blitWithCommand(ContextVk *contextVk,
1038                                              const gl::Rectangle &sourceArea,
1039                                              const gl::Rectangle &destArea,
1040                                              RenderTargetVk *readRenderTarget,
1041                                              RenderTargetVk *drawRenderTarget,
1042                                              GLenum filter,
1043                                              bool colorBlit,
1044                                              bool depthBlit,
1045                                              bool stencilBlit,
1046                                              bool flipX,
1047                                              bool flipY)
1048 {
1049     // Since blitRenderbufferRect is called for each render buffer that needs to be blitted,
1050     // it should never be the case that both color and depth/stencil need to be blitted at
1051     // at the same time.
1052     ASSERT(colorBlit != (depthBlit || stencilBlit));
1053 
1054     vk::ImageHelper *srcImage = &readRenderTarget->getImageForCopy();
1055     vk::ImageHelper *dstImage = &drawRenderTarget->getImageForWrite();
1056 
1057     VkImageAspectFlags imageAspectMask = srcImage->getAspectFlags();
1058     VkImageAspectFlags blitAspectMask  = imageAspectMask;
1059 
1060     // Remove depth or stencil aspects if they are not requested to be blitted.
1061     if (!depthBlit)
1062     {
1063         blitAspectMask &= ~VK_IMAGE_ASPECT_DEPTH_BIT;
1064     }
1065     if (!stencilBlit)
1066     {
1067         blitAspectMask &= ~VK_IMAGE_ASPECT_STENCIL_BIT;
1068     }
1069 
1070     vk::CommandBufferAccess access;
1071     access.onImageTransferRead(imageAspectMask, srcImage);
1072     access.onImageTransferWrite(drawRenderTarget->getLevelIndex(), 1,
1073                                 drawRenderTarget->getLayerIndex(), 1, imageAspectMask, dstImage);
1074     vk::OutsideRenderPassCommandBuffer *commandBuffer;
1075     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
1076 
1077     VkImageBlit blit               = {};
1078     blit.srcSubresource.aspectMask = blitAspectMask;
1079     blit.srcSubresource.mipLevel   = srcImage->toVkLevel(readRenderTarget->getLevelIndex()).get();
1080     blit.srcSubresource.baseArrayLayer = readRenderTarget->getLayerIndex();
1081     blit.srcSubresource.layerCount     = 1;
1082     blit.srcOffsets[0]                 = {sourceArea.x0(), sourceArea.y0(), 0};
1083     blit.srcOffsets[1]                 = {sourceArea.x1(), sourceArea.y1(), 1};
1084     blit.dstSubresource.aspectMask     = blitAspectMask;
1085     blit.dstSubresource.mipLevel = dstImage->toVkLevel(drawRenderTarget->getLevelIndex()).get();
1086     blit.dstSubresource.baseArrayLayer = drawRenderTarget->getLayerIndex();
1087     blit.dstSubresource.layerCount     = 1;
1088     blit.dstOffsets[0]                 = {destArea.x0(), destArea.y0(), 0};
1089     blit.dstOffsets[1]                 = {destArea.x1(), destArea.y1(), 1};
1090 
1091     // Note: vkCmdBlitImage doesn't actually work between 3D and 2D array images due to Vulkan valid
1092     // usage restrictions (https://gitlab.khronos.org/vulkan/vulkan/-/issues/3490), but drivers seem
1093     // to work as expected anyway.  ANGLE continues to use vkCmdBlitImage in that case.
1094 
1095     const bool isSrc3D = srcImage->getType() == VK_IMAGE_TYPE_3D;
1096     const bool isDst3D = dstImage->getType() == VK_IMAGE_TYPE_3D;
1097     if (isSrc3D)
1098     {
1099         AdjustLayersAndDepthFor3DImages(&blit.srcSubresource, &blit.srcOffsets[0],
1100                                         &blit.srcOffsets[1]);
1101     }
1102     if (isDst3D)
1103     {
1104         AdjustLayersAndDepthFor3DImages(&blit.dstSubresource, &blit.dstOffsets[0],
1105                                         &blit.dstOffsets[1]);
1106     }
1107 
1108     commandBuffer->blitImage(srcImage->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1109                              dstImage->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit,
1110                              gl_vk::GetFilter(filter));
1111 
1112     return angle::Result::Continue;
1113 }
1114 
blit(const gl::Context * context,const gl::Rectangle & sourceAreaIn,const gl::Rectangle & destAreaIn,GLbitfield mask,GLenum filter)1115 angle::Result FramebufferVk::blit(const gl::Context *context,
1116                                   const gl::Rectangle &sourceAreaIn,
1117                                   const gl::Rectangle &destAreaIn,
1118                                   GLbitfield mask,
1119                                   GLenum filter)
1120 {
1121     ContextVk *contextVk   = vk::GetImpl(context);
1122     vk::Renderer *renderer = contextVk->getRenderer();
1123     UtilsVk &utilsVk       = contextVk->getUtils();
1124 
1125     // If any clears were picked up when syncing the read framebuffer (as the blit source), restage
1126     // them.  They correspond to attachments that are not used in the blit.  This will cause the
1127     // read framebuffer to become dirty, so the attachments will be synced again on the next command
1128     // that might be using them.
1129     const gl::State &glState              = contextVk->getState();
1130     const gl::Framebuffer *srcFramebuffer = glState.getReadFramebuffer();
1131     FramebufferVk *srcFramebufferVk       = vk::GetImpl(srcFramebuffer);
1132     if (srcFramebufferVk->mDeferredClears.any())
1133     {
1134         srcFramebufferVk->restageDeferredClearsForReadFramebuffer(contextVk);
1135     }
1136 
1137     // We can sometimes end up in a blit with some clear commands saved. Ensure all clear commands
1138     // are issued before we issue the blit command.
1139     ANGLE_TRY(flushDeferredClears(contextVk));
1140 
1141     const bool blitColorBuffer   = (mask & GL_COLOR_BUFFER_BIT) != 0;
1142     const bool blitDepthBuffer   = (mask & GL_DEPTH_BUFFER_BIT) != 0;
1143     const bool blitStencilBuffer = (mask & GL_STENCIL_BUFFER_BIT) != 0;
1144 
1145     // If a framebuffer contains a mixture of multisampled and multisampled-render-to-texture
1146     // attachments, this function could be simultaneously doing a blit on one attachment and resolve
1147     // on another.  For the most part, this means resolve semantics apply.  However, as the resolve
1148     // path cannot be taken for multisampled-render-to-texture attachments, the distinction of
1149     // whether resolve is done for each attachment or blit is made.
1150     const bool isColorResolve =
1151         blitColorBuffer &&
1152         srcFramebufferVk->getColorReadRenderTarget()->getImageForCopy().getSamples() > 1;
1153     const bool isDepthStencilResolve =
1154         (blitDepthBuffer || blitStencilBuffer) &&
1155         srcFramebufferVk->getDepthStencilRenderTarget()->getImageForCopy().getSamples() > 1;
1156     const bool isResolve = isColorResolve || isDepthStencilResolve;
1157 
1158     bool srcFramebufferFlippedY = contextVk->isViewportFlipEnabledForReadFBO();
1159     bool dstFramebufferFlippedY = contextVk->isViewportFlipEnabledForDrawFBO();
1160 
1161     gl::Rectangle sourceArea = sourceAreaIn;
1162     gl::Rectangle destArea   = destAreaIn;
1163 
1164     // Note: GLES (all 3.x versions) require source and destination area to be identical when
1165     // resolving.
1166     ASSERT(!isResolve ||
1167            (sourceArea.x == destArea.x && sourceArea.y == destArea.y &&
1168             sourceArea.width == destArea.width && sourceArea.height == destArea.height));
1169 
1170     gl::Rectangle srcFramebufferDimensions = srcFramebufferVk->getNonRotatedCompleteRenderArea();
1171     gl::Rectangle dstFramebufferDimensions = getNonRotatedCompleteRenderArea();
1172 
1173     // If the destination is flipped in either direction, we will flip the source instead so that
1174     // the destination area is always unflipped.
1175     sourceArea = sourceArea.flip(destArea.isReversedX(), destArea.isReversedY());
1176     destArea   = destArea.removeReversal();
1177 
1178     // Calculate the stretch factor prior to any clipping, as it needs to remain constant.
1179     const double stretch[2] = {
1180         std::abs(sourceArea.width / static_cast<double>(destArea.width)),
1181         std::abs(sourceArea.height / static_cast<double>(destArea.height)),
1182     };
1183 
1184     // Potentially make adjustments for pre-rotatation.  To handle various cases (e.g. clipping)
1185     // and to not interrupt the normal flow of the code, different adjustments are made in
1186     // different parts of the code.  These first adjustments are for whether or not to flip the
1187     // y-axis, and to note the overall rotation (regardless of whether it is the source or
1188     // destination that is rotated).
1189     SurfaceRotation srcFramebufferRotation = contextVk->getRotationReadFramebuffer();
1190     SurfaceRotation dstFramebufferRotation = contextVk->getRotationDrawFramebuffer();
1191     SurfaceRotation rotation               = SurfaceRotation::Identity;
1192     // Both the source and destination cannot be rotated (which would indicate both are the default
1193     // framebuffer (i.e. swapchain image).
1194     ASSERT((srcFramebufferRotation == SurfaceRotation::Identity) ||
1195            (dstFramebufferRotation == SurfaceRotation::Identity));
1196     EarlyAdjustFlipYForPreRotation(srcFramebufferRotation, &rotation, &srcFramebufferFlippedY);
1197     EarlyAdjustFlipYForPreRotation(dstFramebufferRotation, &rotation, &dstFramebufferFlippedY);
1198 
1199     // First, clip the source area to framebuffer.  That requires transforming the destination area
1200     // to match the clipped source.
1201     gl::Rectangle absSourceArea = sourceArea.removeReversal();
1202     gl::Rectangle clippedSourceArea;
1203     if (!gl::ClipRectangle(srcFramebufferDimensions, absSourceArea, &clippedSourceArea))
1204     {
1205         return angle::Result::Continue;
1206     }
1207 
1208     // Resize the destination area based on the new size of source.  Note again that stretch is
1209     // calculated as SrcDimension/DestDimension.
1210     gl::Rectangle srcClippedDestArea;
1211     if (isResolve)
1212     {
1213         // Source and destination areas are identical in resolve (except rotate it, if appropriate).
1214         srcClippedDestArea = clippedSourceArea;
1215         AdjustBlitAreaForPreRotation(dstFramebufferRotation, clippedSourceArea,
1216                                      dstFramebufferDimensions, &srcClippedDestArea);
1217     }
1218     else if (clippedSourceArea == absSourceArea)
1219     {
1220         // If there was no clipping, keep destination area as is (except rotate it, if appropriate).
1221         srcClippedDestArea = destArea;
1222         AdjustBlitAreaForPreRotation(dstFramebufferRotation, destArea, dstFramebufferDimensions,
1223                                      &srcClippedDestArea);
1224     }
1225     else
1226     {
1227         // Shift destination area's x0,y0,x1,y1 by as much as the source area's got shifted (taking
1228         // stretching into account).  Note that double is used as float doesn't have enough
1229         // precision near the end of int range.
1230         double x0Shift = std::round((clippedSourceArea.x - absSourceArea.x) / stretch[0]);
1231         double y0Shift = std::round((clippedSourceArea.y - absSourceArea.y) / stretch[1]);
1232         double x1Shift = std::round((absSourceArea.x1() - clippedSourceArea.x1()) / stretch[0]);
1233         double y1Shift = std::round((absSourceArea.y1() - clippedSourceArea.y1()) / stretch[1]);
1234 
1235         // If the source area was reversed in any direction, the shift should be applied in the
1236         // opposite direction as well.
1237         if (sourceArea.isReversedX())
1238         {
1239             std::swap(x0Shift, x1Shift);
1240         }
1241 
1242         if (sourceArea.isReversedY())
1243         {
1244             std::swap(y0Shift, y1Shift);
1245         }
1246 
1247         srcClippedDestArea.x = destArea.x0() + static_cast<int>(x0Shift);
1248         srcClippedDestArea.y = destArea.y0() + static_cast<int>(y0Shift);
1249         int x1               = destArea.x1() - static_cast<int>(x1Shift);
1250         int y1               = destArea.y1() - static_cast<int>(y1Shift);
1251 
1252         srcClippedDestArea.width  = x1 - srcClippedDestArea.x;
1253         srcClippedDestArea.height = y1 - srcClippedDestArea.y;
1254 
1255         // Rotate srcClippedDestArea if the destination is rotated
1256         if (dstFramebufferRotation != SurfaceRotation::Identity)
1257         {
1258             gl::Rectangle originalSrcClippedDestArea = srcClippedDestArea;
1259             AdjustBlitAreaForPreRotation(dstFramebufferRotation, originalSrcClippedDestArea,
1260                                          dstFramebufferDimensions, &srcClippedDestArea);
1261         }
1262     }
1263 
1264     // If framebuffers are flipped in Y, flip the source and destination area (which define the
1265     // transformation regardless of clipping), as well as the blit area (which is the clipped
1266     // destination area).
1267     if (srcFramebufferFlippedY)
1268     {
1269         sourceArea.y      = srcFramebufferDimensions.height - sourceArea.y;
1270         sourceArea.height = -sourceArea.height;
1271     }
1272     if (dstFramebufferFlippedY)
1273     {
1274         destArea.y      = dstFramebufferDimensions.height - destArea.y;
1275         destArea.height = -destArea.height;
1276 
1277         srcClippedDestArea.y =
1278             dstFramebufferDimensions.height - srcClippedDestArea.y - srcClippedDestArea.height;
1279     }
1280 
1281     bool flipX = sourceArea.isReversedX() != destArea.isReversedX();
1282     bool flipY = sourceArea.isReversedY() != destArea.isReversedY();
1283 
1284     // GLES doesn't allow flipping the parameters of glBlitFramebuffer if performing a resolve.
1285     ASSERT(!isResolve ||
1286            (flipX == false && flipY == (srcFramebufferFlippedY != dstFramebufferFlippedY)));
1287 
1288     // Again, transfer the destination flip to source, so destination is unflipped.  Note that
1289     // destArea was not reversed until the final possible Y-flip.
1290     ASSERT(!destArea.isReversedX());
1291     sourceArea = sourceArea.flip(false, destArea.isReversedY());
1292     destArea   = destArea.removeReversal();
1293 
1294     // Now that clipping and flipping is done, rotate certain values that will be used for
1295     // UtilsVk::BlitResolveParameters
1296     gl::Rectangle sourceAreaOld = sourceArea;
1297     gl::Rectangle destAreaOld   = destArea;
1298     if (srcFramebufferRotation == rotation)
1299     {
1300         AdjustBlitAreaForPreRotation(srcFramebufferRotation, sourceAreaOld,
1301                                      srcFramebufferDimensions, &sourceArea);
1302         AdjustDimensionsAndFlipForPreRotation(srcFramebufferRotation, &srcFramebufferDimensions,
1303                                               &flipX, &flipY);
1304     }
1305     SurfaceRotation rememberDestFramebufferRotation = dstFramebufferRotation;
1306     if (srcFramebufferRotation == SurfaceRotation::Rotated90Degrees)
1307     {
1308         dstFramebufferRotation = rotation;
1309     }
1310     AdjustBlitAreaForPreRotation(dstFramebufferRotation, destAreaOld, dstFramebufferDimensions,
1311                                  &destArea);
1312     dstFramebufferRotation = rememberDestFramebufferRotation;
1313 
1314     // Clip the destination area to the framebuffer size and scissor.  Note that we don't care
1315     // about the source area anymore.  The offset translation is done based on the original source
1316     // and destination rectangles.  The stretch factor is already calculated as well.
1317     gl::Rectangle blitArea;
1318     if (!gl::ClipRectangle(getRotatedScissoredRenderArea(contextVk), srcClippedDestArea, &blitArea))
1319     {
1320         return angle::Result::Continue;
1321     }
1322 
1323     bool noClip = blitArea == destArea && stretch[0] == 1.0f && stretch[1] == 1.0f;
1324     bool noFlip = !flipX && !flipY;
1325     bool disableFlippingBlitWithCommand =
1326         renderer->getFeatures().disableFlippingBlitWithCommand.enabled;
1327 
1328     UtilsVk::BlitResolveParameters commonParams;
1329     commonParams.srcOffset[0]           = sourceArea.x;
1330     commonParams.srcOffset[1]           = sourceArea.y;
1331     commonParams.dstOffset[0]           = destArea.x;
1332     commonParams.dstOffset[1]           = destArea.y;
1333     commonParams.rotatedOffsetFactor[0] = std::abs(sourceArea.width);
1334     commonParams.rotatedOffsetFactor[1] = std::abs(sourceArea.height);
1335     commonParams.stretch[0]             = static_cast<float>(stretch[0]);
1336     commonParams.stretch[1]             = static_cast<float>(stretch[1]);
1337     commonParams.srcExtents[0]          = srcFramebufferDimensions.width;
1338     commonParams.srcExtents[1]          = srcFramebufferDimensions.height;
1339     commonParams.blitArea               = blitArea;
1340     commonParams.linear                 = filter == GL_LINEAR && !isResolve;
1341     commonParams.flipX                  = flipX;
1342     commonParams.flipY                  = flipY;
1343     commonParams.rotation               = rotation;
1344 
1345     if (blitColorBuffer)
1346     {
1347         RenderTargetVk *readRenderTarget      = srcFramebufferVk->getColorReadRenderTarget();
1348         UtilsVk::BlitResolveParameters params = commonParams;
1349         params.srcLayer                       = readRenderTarget->getLayerIndex();
1350 
1351         // Multisampled images are not allowed to have mips.
1352         ASSERT(!isColorResolve || readRenderTarget->getLevelIndex() == gl::LevelIndex(0));
1353 
1354         // If there was no clipping and the format capabilities allow us, use Vulkan's builtin blit.
1355         // The reason clipping is prohibited in this path is that due to rounding errors, it would
1356         // be hard to guarantee the image stretching remains perfect.  That also allows us not to
1357         // have to transform back the destination clipping to source.
1358         //
1359         // Non-identity pre-rotation cases do not use Vulkan's builtin blit.  Additionally, blits
1360         // between 3D and non-3D-non-layer-0 images are forbidden (possibly due to an oversight:
1361         // https://gitlab.khronos.org/vulkan/vulkan/-/issues/3490)
1362         //
1363         // For simplicity, we either blit all render targets with a Vulkan command, or none.
1364         bool canBlitWithCommand =
1365             !isColorResolve && noClip && (noFlip || !disableFlippingBlitWithCommand) &&
1366             HasSrcBlitFeature(renderer, readRenderTarget) && rotation == SurfaceRotation::Identity;
1367 
1368         // If we need to reinterpret the colorspace of the read RenderTarget then the blit must be
1369         // done through a shader
1370         bool reinterpretsColorspace      = readRenderTarget->hasColorspaceOverrideForRead();
1371         bool areChannelsBlitCompatible   = true;
1372         bool areFormatsIdentical         = true;
1373         bool colorAttachmentAlreadyInUse = false;
1374         for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
1375         {
1376             RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL];
1377             canBlitWithCommand =
1378                 canBlitWithCommand && HasDstBlitFeature(renderer, drawRenderTarget);
1379             areChannelsBlitCompatible =
1380                 areChannelsBlitCompatible &&
1381                 AreSrcAndDstColorChannelsBlitCompatible(readRenderTarget, drawRenderTarget);
1382             areFormatsIdentical = areFormatsIdentical &&
1383                                   AreSrcAndDstFormatsIdentical(readRenderTarget, drawRenderTarget);
1384 
1385             // If any color attachment of the draw framebuffer was already in use in the currently
1386             // started renderpass, don't reuse the renderpass for blit.
1387             colorAttachmentAlreadyInUse =
1388                 colorAttachmentAlreadyInUse || contextVk->isRenderPassStartedAndUsesImage(
1389                                                    drawRenderTarget->getImageForRenderPass());
1390 
1391             // If we need to reinterpret the colorspace of the draw RenderTarget then the blit must
1392             // be done through a shader
1393             reinterpretsColorspace =
1394                 reinterpretsColorspace || drawRenderTarget->hasColorspaceOverrideForWrite();
1395         }
1396 
1397         // Now that all flipping is done, adjust the offsets for resolve and prerotation
1398         if (isColorResolve)
1399         {
1400             AdjustBlitResolveParametersForResolve(sourceArea, destArea, &params);
1401         }
1402         AdjustBlitResolveParametersForPreRotation(rotation, srcFramebufferRotation, &params);
1403 
1404         if (canBlitWithCommand && areChannelsBlitCompatible && !reinterpretsColorspace)
1405         {
1406             for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
1407             {
1408                 RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL];
1409                 ANGLE_TRY(blitWithCommand(contextVk, sourceArea, destArea, readRenderTarget,
1410                                           drawRenderTarget, filter, true, false, false, flipX,
1411                                           flipY));
1412             }
1413         }
1414         // If we're not flipping or rotating, use Vulkan's builtin resolve.
1415         else if (isColorResolve && !flipX && !flipY && areChannelsBlitCompatible &&
1416                  areFormatsIdentical && rotation == SurfaceRotation::Identity &&
1417                  !reinterpretsColorspace)
1418         {
1419             // Resolving with a subpass resolve attachment has a few restrictions:
1420             // 1.) glBlitFramebuffer() needs to copy the read color attachment to all enabled
1421             // attachments in the draw framebuffer, but Vulkan requires a 1:1 relationship for
1422             // multisample attachments to resolve attachments in the render pass subpass.
1423             // Due to this, we currently only support using resolve attachments when there is a
1424             // single draw attachment enabled.
1425             // 2.) Using a subpass resolve attachment relies on using the render pass that performs
1426             // the draw to still be open, so it can be updated to use the resolve attachment to draw
1427             // into. If there's no render pass with commands, then the multisampled render pass is
1428             // already done and whose data is already flushed from the tile (in a tile-based
1429             // renderer), so there's no chance for the resolve attachment to take advantage of the
1430             // data already being present in the tile.
1431 
1432             // Additionally, when resolving with a resolve attachment, the src and destination
1433             // offsets must match, the render area must match the resolve area, and there should be
1434             // no flipping or rotation.  Fortunately, in GLES the blit source and destination areas
1435             // are already required to be identical.
1436             ASSERT(params.srcOffset[0] == params.dstOffset[0] &&
1437                    params.srcOffset[1] == params.dstOffset[1]);
1438             bool canResolveWithSubpass = mState.getEnabledDrawBuffers().count() == 1 &&
1439                                          mCurrentFramebufferDesc.getLayerCount() == 1 &&
1440                                          contextVk->hasStartedRenderPassWithQueueSerial(
1441                                              srcFramebufferVk->getLastRenderPassQueueSerial()) &&
1442                                          !colorAttachmentAlreadyInUse;
1443 
1444             if (canResolveWithSubpass)
1445             {
1446                 const vk::RenderPassCommandBufferHelper &renderPassCommands =
1447                     contextVk->getStartedRenderPassCommands();
1448                 const vk::RenderPassDesc &renderPassDesc = renderPassCommands.getRenderPassDesc();
1449 
1450                 // Make sure that:
1451                 // - The blit and render areas are identical
1452                 // - There is no resolve attachment for the corresponding index already
1453                 // Additionally, disable the optimization for a few corner cases that are
1454                 // unrealistic and inconvenient.
1455                 const uint32_t readColorIndexGL = srcFramebuffer->getState().getReadIndex();
1456                 canResolveWithSubpass =
1457                     blitArea == renderPassCommands.getRenderArea() &&
1458                     !renderPassDesc.hasColorResolveAttachment(readColorIndexGL) &&
1459                     AllowAddingResolveAttachmentsToSubpass(renderPassDesc);
1460             }
1461 
1462             if (canResolveWithSubpass)
1463             {
1464                 ANGLE_TRY(resolveColorWithSubpass(contextVk, params));
1465             }
1466             else
1467             {
1468                 ANGLE_TRY(resolveColorWithCommand(contextVk, params,
1469                                                   &readRenderTarget->getImageForCopy()));
1470             }
1471         }
1472         else
1473         {
1474             // Otherwise use a shader to do blit or resolve.
1475 
1476             // Flush the render pass, which may incur a vkQueueSubmit, before taking any views.
1477             // Otherwise the view serials would not reflect the render pass they are really used in.
1478             // http://crbug.com/1272266#c22
1479             ANGLE_TRY(
1480                 contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::PrepareForBlit));
1481 
1482             const vk::ImageView *copyImageView = nullptr;
1483             ANGLE_TRY(readRenderTarget->getCopyImageView(contextVk, &copyImageView));
1484             ANGLE_TRY(utilsVk.colorBlitResolve(
1485                 contextVk, this, &readRenderTarget->getImageForCopy(), copyImageView, params));
1486         }
1487     }
1488 
1489     if (blitDepthBuffer || blitStencilBuffer)
1490     {
1491         RenderTargetVk *readRenderTarget      = srcFramebufferVk->getDepthStencilRenderTarget();
1492         RenderTargetVk *drawRenderTarget      = mRenderTargetCache.getDepthStencil();
1493         UtilsVk::BlitResolveParameters params = commonParams;
1494         params.srcLayer                       = readRenderTarget->getLayerIndex();
1495 
1496         // Multisampled images are not allowed to have mips.
1497         ASSERT(!isDepthStencilResolve || readRenderTarget->getLevelIndex() == gl::LevelIndex(0));
1498 
1499         // Similarly, only blit if there's been no clipping or rotating.
1500         bool canBlitWithCommand =
1501             !isDepthStencilResolve && noClip && (noFlip || !disableFlippingBlitWithCommand) &&
1502             HasSrcBlitFeature(renderer, readRenderTarget) &&
1503             HasDstBlitFeature(renderer, drawRenderTarget) && rotation == SurfaceRotation::Identity;
1504         bool areChannelsBlitCompatible =
1505             AreSrcAndDstDepthStencilChannelsBlitCompatible(readRenderTarget, drawRenderTarget);
1506 
1507         // glBlitFramebuffer requires that depth/stencil blits have matching formats.
1508         ASSERT(AreSrcAndDstFormatsIdentical(readRenderTarget, drawRenderTarget));
1509 
1510         if (canBlitWithCommand && areChannelsBlitCompatible)
1511         {
1512             ANGLE_TRY(blitWithCommand(contextVk, sourceArea, destArea, readRenderTarget,
1513                                       drawRenderTarget, filter, false, blitDepthBuffer,
1514                                       blitStencilBuffer, flipX, flipY));
1515         }
1516         else
1517         {
1518             vk::ImageHelper *depthStencilImage = &readRenderTarget->getImageForCopy();
1519 
1520             VkImageAspectFlags resolveAspects = 0;
1521             if (blitDepthBuffer)
1522             {
1523                 resolveAspects |= VK_IMAGE_ASPECT_DEPTH_BIT;
1524             }
1525             if (blitStencilBuffer)
1526             {
1527                 resolveAspects |= VK_IMAGE_ASPECT_STENCIL_BIT;
1528             }
1529 
1530             // See comment on canResolveWithSubpass for the color path.
1531             bool canResolveWithSubpass =
1532                 isDepthStencilResolve &&
1533                 !renderer->getFeatures().disableDepthStencilResolveThroughAttachment.enabled &&
1534                 areChannelsBlitCompatible && mCurrentFramebufferDesc.getLayerCount() == 1 &&
1535                 contextVk->hasStartedRenderPassWithQueueSerial(
1536                     srcFramebufferVk->getLastRenderPassQueueSerial()) &&
1537                 !contextVk->isRenderPassStartedAndUsesImage(
1538                     drawRenderTarget->getImageForRenderPass()) &&
1539                 noFlip && rotation == SurfaceRotation::Identity;
1540 
1541             if (canResolveWithSubpass)
1542             {
1543                 const vk::RenderPassCommandBufferHelper &renderPassCommands =
1544                     contextVk->getStartedRenderPassCommands();
1545                 const vk::RenderPassDesc &renderPassDesc = renderPassCommands.getRenderPassDesc();
1546 
1547                 const VkImageAspectFlags depthStencilImageAspects =
1548                     depthStencilImage->getAspectFlags();
1549                 const bool resolvesAllAspects =
1550                     (resolveAspects & depthStencilImageAspects) == depthStencilImageAspects;
1551 
1552                 // Make sure that:
1553                 // - The blit and render areas are identical
1554                 // - There is no resolve attachment already
1555                 // Additionally, disable the optimization for a few corner cases that are
1556                 // unrealistic and inconvenient.
1557                 //
1558                 // Note: currently, if two separate `glBlitFramebuffer` calls are made for each
1559                 // aspect, only the first one is optimized as a resolve attachment.  Applications
1560                 // should use one `glBlitFramebuffer` call with both aspects if they want to resolve
1561                 // both.
1562                 canResolveWithSubpass =
1563                     blitArea == renderPassCommands.getRenderArea() &&
1564                     (resolvesAllAspects ||
1565                      renderer->getFeatures().supportsDepthStencilIndependentResolveNone.enabled) &&
1566                     !renderPassDesc.hasDepthStencilResolveAttachment() &&
1567                     AllowAddingResolveAttachmentsToSubpass(renderPassDesc);
1568             }
1569 
1570             if (canResolveWithSubpass)
1571             {
1572                 ANGLE_TRY(resolveDepthStencilWithSubpass(contextVk, params, resolveAspects));
1573             }
1574             else
1575             {
1576                 // See comment for the draw-based color blit.  The render pass must be flushed
1577                 // before creating the views.
1578                 ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(
1579                     RenderPassClosureReason::PrepareForBlit));
1580 
1581                 // Now that all flipping is done, adjust the offsets for resolve and prerotation
1582                 if (isDepthStencilResolve)
1583                 {
1584                     AdjustBlitResolveParametersForResolve(sourceArea, destArea, &params);
1585                 }
1586                 AdjustBlitResolveParametersForPreRotation(rotation, srcFramebufferRotation,
1587                                                           &params);
1588 
1589                 // Get depth- and stencil-only views for reading.
1590                 const vk::ImageView *depthView   = nullptr;
1591                 const vk::ImageView *stencilView = nullptr;
1592 
1593                 if (blitDepthBuffer)
1594                 {
1595                     ANGLE_TRY(readRenderTarget->getDepthOrStencilImageViewForCopy(
1596                         contextVk, VK_IMAGE_ASPECT_DEPTH_BIT, &depthView));
1597                 }
1598 
1599                 if (blitStencilBuffer)
1600                 {
1601                     ANGLE_TRY(readRenderTarget->getDepthOrStencilImageViewForCopy(
1602                         contextVk, VK_IMAGE_ASPECT_STENCIL_BIT, &stencilView));
1603                 }
1604 
1605                 // If shader stencil export is not possible, defer stencil blit/resolve to another
1606                 // pass.
1607                 const bool hasShaderStencilExport =
1608                     renderer->getFeatures().supportsShaderStencilExport.enabled;
1609 
1610                 // Blit depth. If shader stencil export is present, blit stencil as well.
1611                 if (blitDepthBuffer || (blitStencilBuffer && hasShaderStencilExport))
1612                 {
1613                     ANGLE_TRY(utilsVk.depthStencilBlitResolve(
1614                         contextVk, this, depthStencilImage, depthView,
1615                         hasShaderStencilExport ? stencilView : nullptr, params));
1616                 }
1617 
1618                 // If shader stencil export is not present, blit stencil through a different path.
1619                 if (blitStencilBuffer && !hasShaderStencilExport)
1620                 {
1621                     ANGLE_VK_PERF_WARNING(
1622                         contextVk, GL_DEBUG_SEVERITY_LOW,
1623                         "Inefficient BlitFramebuffer operation on the stencil aspect "
1624                         "due to lack of shader stencil export support");
1625                     ANGLE_TRY(utilsVk.stencilBlitResolveNoShaderExport(
1626                         contextVk, this, depthStencilImage, stencilView, params));
1627                 }
1628             }
1629         }
1630     }
1631 
1632     return angle::Result::Continue;
1633 }
1634 
releaseCurrentFramebuffer(ContextVk * contextVk)1635 void FramebufferVk::releaseCurrentFramebuffer(ContextVk *contextVk)
1636 {
1637     if (mIsCurrentFramebufferCached)
1638     {
1639         mCurrentFramebuffer.release();
1640     }
1641     else
1642     {
1643         contextVk->addGarbage(&mCurrentFramebuffer);
1644     }
1645 }
1646 
updateLayerCount()1647 void FramebufferVk::updateLayerCount()
1648 {
1649     uint32_t layerCount = std::numeric_limits<uint32_t>::max();
1650 
1651     // Color attachments.
1652     const auto &colorRenderTargets = mRenderTargetCache.getColors();
1653     for (size_t colorIndexGL : mState.getColorAttachmentsMask())
1654     {
1655         RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
1656         ASSERT(colorRenderTarget);
1657         layerCount = std::min(layerCount, colorRenderTarget->getLayerCount());
1658     }
1659 
1660     // Depth/stencil attachment.
1661     RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget();
1662     if (depthStencilRenderTarget)
1663     {
1664         layerCount = std::min(layerCount, depthStencilRenderTarget->getLayerCount());
1665     }
1666 
1667     if (layerCount == std::numeric_limits<uint32_t>::max())
1668     {
1669         layerCount = mState.getDefaultLayers();
1670     }
1671 
1672     // While layer count and view count are mutually exclusive, they result in different render
1673     // passes (and thus framebuffers).  For multiview, layer count is set to view count and a flag
1674     // signifies that the framebuffer is multiview (as opposed to layered).
1675     const bool isMultiview = mState.isMultiview();
1676     if (isMultiview)
1677     {
1678         layerCount = mState.getNumViews();
1679     }
1680 
1681     mCurrentFramebufferDesc.updateLayerCount(layerCount);
1682     mCurrentFramebufferDesc.updateIsMultiview(isMultiview);
1683 }
1684 
ensureFragmentShadingRateImageAndViewInitialized(ContextVk * contextVk,const uint32_t fragmentShadingRateAttachmentWidth,const uint32_t fragmentShadingRateAttachmentHeight)1685 angle::Result FramebufferVk::ensureFragmentShadingRateImageAndViewInitialized(
1686     ContextVk *contextVk,
1687     const uint32_t fragmentShadingRateAttachmentWidth,
1688     const uint32_t fragmentShadingRateAttachmentHeight)
1689 {
1690     vk::Renderer *renderer = contextVk->getRenderer();
1691 
1692     // Release current valid image iff attachment extents need to change.
1693     if (mFragmentShadingRateImage.valid() &&
1694         (mFragmentShadingRateImage.getExtents().width != fragmentShadingRateAttachmentWidth ||
1695          mFragmentShadingRateImage.getExtents().height != fragmentShadingRateAttachmentHeight))
1696     {
1697         mFragmentShadingRateImageView.release(renderer, mFragmentShadingRateImage.getResourceUse());
1698         mFragmentShadingRateImage.releaseImage(renderer);
1699     }
1700 
1701     if (!mFragmentShadingRateImage.valid())
1702     {
1703         VkImageUsageFlags imageUsageFlags =
1704             VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR |
1705             VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1706         // Add storage usage iff we intend to generate data using compute shader
1707         if (!contextVk->getFeatures().generateFragmentShadingRateAttchementWithCpu.enabled)
1708         {
1709             imageUsageFlags |= VK_IMAGE_USAGE_STORAGE_BIT;
1710         }
1711 
1712         ANGLE_TRY(mFragmentShadingRateImage.init(
1713             contextVk, gl::TextureType::_2D,
1714             VkExtent3D{fragmentShadingRateAttachmentWidth, fragmentShadingRateAttachmentHeight, 1},
1715             renderer->getFormat(angle::FormatID::R8_UINT), 1, imageUsageFlags, gl::LevelIndex(0), 1,
1716             1, false, contextVk->getProtectionType() == vk::ProtectionType::Protected));
1717 
1718         ANGLE_TRY(contextVk->initImageAllocation(
1719             &mFragmentShadingRateImage, false, renderer->getMemoryProperties(),
1720             VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vk::MemoryAllocationType::TextureImage));
1721 
1722         mFragmentShadingRateImageView.init(renderer);
1723         ANGLE_TRY(mFragmentShadingRateImageView.initFragmentShadingRateView(
1724             contextVk, &mFragmentShadingRateImage));
1725     }
1726 
1727     return angle::Result::Continue;
1728 }
1729 
generateFragmentShadingRateWithCPU(ContextVk * contextVk,const uint32_t fragmentShadingRateWidth,const uint32_t fragmentShadingRateHeight,const uint32_t fragmentShadingRateBlockWidth,const uint32_t fragmentShadingRateBlockHeight,const uint32_t foveatedAttachmentWidth,const uint32_t foveatedAttachmentHeight,const std::vector<gl::FocalPoint> & activeFocalPoints)1730 angle::Result FramebufferVk::generateFragmentShadingRateWithCPU(
1731     ContextVk *contextVk,
1732     const uint32_t fragmentShadingRateWidth,
1733     const uint32_t fragmentShadingRateHeight,
1734     const uint32_t fragmentShadingRateBlockWidth,
1735     const uint32_t fragmentShadingRateBlockHeight,
1736     const uint32_t foveatedAttachmentWidth,
1737     const uint32_t foveatedAttachmentHeight,
1738     const std::vector<gl::FocalPoint> &activeFocalPoints)
1739 {
1740     // Fill in image with fragment shading rate data
1741     size_t bufferSize                   = fragmentShadingRateWidth * fragmentShadingRateHeight;
1742     VkBufferCreateInfo bufferCreateInfo = {};
1743     bufferCreateInfo.sType              = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
1744     bufferCreateInfo.size               = bufferSize;
1745     bufferCreateInfo.usage              = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
1746     bufferCreateInfo.sharingMode        = VK_SHARING_MODE_EXCLUSIVE;
1747     vk::RendererScoped<vk::BufferHelper> stagingBuffer(contextVk->getRenderer());
1748     vk::BufferHelper *buffer = &stagingBuffer.get();
1749     ANGLE_TRY(buffer->init(contextVk, bufferCreateInfo, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
1750     uint8_t *mappedBuffer;
1751     ANGLE_TRY(buffer->map(contextVk, &mappedBuffer));
1752     uint8_t val = 0;
1753     memset(mappedBuffer, 0, bufferSize);
1754 
1755     // The spec requires min_pixel_density to be computed thusly -
1756     //
1757     // min_pixel_density=0.;
1758     // for(int i=0;i<focalPointsPerLayer;++i)
1759     // {
1760     //     focal_point_density = 1./max((focalX[i]-px)^2*gainX[i]^2+
1761     //                         (focalY[i]-py)^2*gainY[i]^2-foveaArea[i],1.);
1762     //
1763     //     min_pixel_density=max(min_pixel_density,focal_point_density);
1764     // }
1765     float minPixelDensity   = 0.0f;
1766     float focalPointDensity = 0.0f;
1767     for (uint32_t y = 0; y < fragmentShadingRateHeight; y++)
1768     {
1769         for (uint32_t x = 0; x < fragmentShadingRateWidth; x++)
1770         {
1771             minPixelDensity = 0.0f;
1772             float px =
1773                 (static_cast<float>(x) * fragmentShadingRateBlockWidth / foveatedAttachmentWidth -
1774                  0.5f) *
1775                 2.0f;
1776             float py =
1777                 (static_cast<float>(y) * fragmentShadingRateBlockHeight / foveatedAttachmentHeight -
1778                  0.5f) *
1779                 2.0f;
1780             focalPointDensity = 0.0f;
1781             for (const gl::FocalPoint &focalPoint : activeFocalPoints)
1782             {
1783                 float density = 1.0f / std::max(std::pow(focalPoint.focalX - px, 2.0f) *
1784                                                         std::pow(focalPoint.gainX, 2.0f) +
1785                                                     std::pow(focalPoint.focalY - py, 2.0f) *
1786                                                         std::pow(focalPoint.gainY, 2.0f) -
1787                                                     focalPoint.foveaArea,
1788                                                 1.0f);
1789 
1790                 // When focal points are overlapping choose the highest quality of all
1791                 if (density > focalPointDensity)
1792                 {
1793                     focalPointDensity = density;
1794                 }
1795             }
1796             minPixelDensity = std::max(minPixelDensity, focalPointDensity);
1797 
1798             // https://docs.vulkan.org/spec/latest/chapters/primsrast.html#primsrast-fragment-shading-rate-attachment
1799             //
1800             // w = 2^((texel/4) & 3)
1801             // h = 2^(texel & 3)
1802             // `texel` would then be => log2(w) << 2 | log2(h).
1803             //
1804             // 1) The supported shading rates are - 1x1, 1x2, 2x1, 2x2
1805             // 2) log2(1) == 0, log2(2) == 1
1806             if (minPixelDensity > 0.75f)
1807             {
1808                 // Use shading rate 1x1
1809                 val = 0;
1810             }
1811             else if (minPixelDensity > 0.5f)
1812             {
1813                 // Use shading rate 2x1
1814                 val = (1 << 2);
1815             }
1816             else
1817             {
1818                 // Use shading rate 2x2
1819                 val = (1 << 2) | 1;
1820             }
1821             mappedBuffer[y * fragmentShadingRateWidth + x] = val;
1822         }
1823     }
1824 
1825     ANGLE_TRY(buffer->flush(contextVk->getRenderer(), 0, buffer->getSize()));
1826     buffer->unmap(contextVk->getRenderer());
1827     // copy data from staging buffer to image
1828     vk::CommandBufferAccess access;
1829     access.onBufferTransferRead(buffer);
1830     access.onImageTransferWrite(gl::LevelIndex(0), 1, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT,
1831                                 &mFragmentShadingRateImage);
1832     vk::OutsideRenderPassCommandBuffer *dataUpload;
1833     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &dataUpload));
1834     VkBufferImageCopy copy           = {};
1835     copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1836     copy.imageSubresource.layerCount = 1;
1837     copy.imageExtent.depth           = 1;
1838     copy.imageExtent.width           = fragmentShadingRateWidth;
1839     copy.imageExtent.height          = fragmentShadingRateHeight;
1840     dataUpload->copyBufferToImage(buffer->getBuffer().getHandle(),
1841                                   mFragmentShadingRateImage.getImage(),
1842                                   VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copy);
1843 
1844     return angle::Result::Continue;
1845 }
1846 
generateFragmentShadingRateWithCompute(ContextVk * contextVk,const uint32_t fragmentShadingRateWidth,const uint32_t fragmentShadingRateHeight,const uint32_t fragmentShadingRateBlockWidth,const uint32_t fragmentShadingRateBlockHeight,const uint32_t foveatedAttachmentWidth,const uint32_t foveatedAttachmentHeight,const std::vector<gl::FocalPoint> & activeFocalPoints)1847 angle::Result FramebufferVk::generateFragmentShadingRateWithCompute(
1848     ContextVk *contextVk,
1849     const uint32_t fragmentShadingRateWidth,
1850     const uint32_t fragmentShadingRateHeight,
1851     const uint32_t fragmentShadingRateBlockWidth,
1852     const uint32_t fragmentShadingRateBlockHeight,
1853     const uint32_t foveatedAttachmentWidth,
1854     const uint32_t foveatedAttachmentHeight,
1855     const std::vector<gl::FocalPoint> &activeFocalPoints)
1856 {
1857     ASSERT(activeFocalPoints.size() < gl::IMPLEMENTATION_MAX_FOCAL_POINTS);
1858 
1859     UtilsVk::GenerateFragmentShadingRateParameters shadingRateParams;
1860     shadingRateParams.textureWidth          = foveatedAttachmentWidth;
1861     shadingRateParams.textureHeight         = foveatedAttachmentHeight;
1862     shadingRateParams.attachmentBlockWidth  = fragmentShadingRateBlockWidth;
1863     shadingRateParams.attachmentBlockHeight = fragmentShadingRateBlockHeight;
1864     shadingRateParams.attachmentWidth       = fragmentShadingRateWidth;
1865     shadingRateParams.attachmentHeight      = fragmentShadingRateHeight;
1866     shadingRateParams.numFocalPoints        = 0;
1867 
1868     for (const gl::FocalPoint &focalPoint : activeFocalPoints)
1869     {
1870         ASSERT(focalPoint.valid());
1871         shadingRateParams.focalPoints[shadingRateParams.numFocalPoints] = focalPoint;
1872         shadingRateParams.numFocalPoints++;
1873     }
1874 
1875     return contextVk->getUtils().generateFragmentShadingRate(
1876         contextVk, &mFragmentShadingRateImage, &mFragmentShadingRateImageView, shadingRateParams);
1877 }
1878 
updateFragmentShadingRateAttachment(ContextVk * contextVk,const gl::FoveationState & foveationState,const gl::Extents & foveatedAttachmentSize)1879 angle::Result FramebufferVk::updateFragmentShadingRateAttachment(
1880     ContextVk *contextVk,
1881     const gl::FoveationState &foveationState,
1882     const gl::Extents &foveatedAttachmentSize)
1883 {
1884     const VkExtent2D fragmentShadingRateExtent =
1885         contextVk->getRenderer()->getMaxFragmentShadingRateAttachmentTexelSize();
1886     const uint32_t fragmentShadingRateBlockWidth  = fragmentShadingRateExtent.width;
1887     const uint32_t fragmentShadingRateBlockHeight = fragmentShadingRateExtent.height;
1888     const uint32_t foveatedAttachmentWidth        = foveatedAttachmentSize.width;
1889     const uint32_t foveatedAttachmentHeight       = foveatedAttachmentSize.height;
1890     const uint32_t fragmentShadingRateWidth =
1891         UnsignedCeilDivide(foveatedAttachmentWidth, fragmentShadingRateBlockWidth);
1892     const uint32_t fragmentShadingRateHeight =
1893         UnsignedCeilDivide(foveatedAttachmentHeight, fragmentShadingRateBlockHeight);
1894 
1895     ANGLE_TRY(ensureFragmentShadingRateImageAndViewInitialized(contextVk, fragmentShadingRateWidth,
1896                                                                fragmentShadingRateHeight));
1897     ASSERT(mFragmentShadingRateImage.valid());
1898 
1899     std::vector<gl::FocalPoint> activeFocalPoints;
1900     for (uint32_t point = 0; point < gl::IMPLEMENTATION_MAX_FOCAL_POINTS; point++)
1901     {
1902         const gl::FocalPoint &focalPoint = foveationState.getFocalPoint(0, point);
1903         if (focalPoint.valid())
1904         {
1905             activeFocalPoints.push_back(focalPoint);
1906         }
1907     }
1908     ASSERT(activeFocalPoints.size() > 0);
1909 
1910     if (contextVk->getFeatures().generateFragmentShadingRateAttchementWithCpu.enabled)
1911     {
1912         ANGLE_TRY(generateFragmentShadingRateWithCPU(
1913             contextVk, fragmentShadingRateWidth, fragmentShadingRateHeight,
1914             fragmentShadingRateBlockWidth, fragmentShadingRateBlockHeight, foveatedAttachmentWidth,
1915             foveatedAttachmentHeight, activeFocalPoints));
1916     }
1917     else
1918     {
1919         ANGLE_TRY(generateFragmentShadingRateWithCompute(
1920             contextVk, fragmentShadingRateWidth, fragmentShadingRateHeight,
1921             fragmentShadingRateBlockWidth, fragmentShadingRateBlockHeight, foveatedAttachmentWidth,
1922             foveatedAttachmentHeight, activeFocalPoints));
1923     }
1924 
1925     return angle::Result::Continue;
1926 }
1927 
updateFoveationState(ContextVk * contextVk,const gl::FoveationState & newFoveationState,const gl::Extents & foveatedAttachmentSize)1928 angle::Result FramebufferVk::updateFoveationState(ContextVk *contextVk,
1929                                                   const gl::FoveationState &newFoveationState,
1930                                                   const gl::Extents &foveatedAttachmentSize)
1931 {
1932     const bool isFoveationEnabled                 = newFoveationState.isFoveated();
1933     vk::ImageOrBufferViewSubresourceSerial serial = vk::kInvalidImageOrBufferViewSubresourceSerial;
1934     if (isFoveationEnabled)
1935     {
1936         ANGLE_TRY(updateFragmentShadingRateAttachment(contextVk, newFoveationState,
1937                                                       foveatedAttachmentSize));
1938         ASSERT(mFragmentShadingRateImage.valid());
1939 
1940         serial = mFragmentShadingRateImageView.getSubresourceSerial(gl::LevelIndex(0), 1, 0,
1941                                                                     vk::LayerMode::All);
1942     }
1943 
1944     // Update state after the possible failure point.
1945     mFoveationState = newFoveationState;
1946     mCurrentFramebufferDesc.updateFragmentShadingRate(serial);
1947     // mRenderPassDesc will be updated later in updateRenderPassDesc() in case if
1948     // mCurrentFramebufferDesc was changed.
1949     return angle::Result::Continue;
1950 }
1951 
resolveColorWithSubpass(ContextVk * contextVk,const UtilsVk::BlitResolveParameters & params)1952 angle::Result FramebufferVk::resolveColorWithSubpass(ContextVk *contextVk,
1953                                                      const UtilsVk::BlitResolveParameters &params)
1954 {
1955     // Vulkan requires a 1:1 relationship for multisample attachments to resolve attachments in the
1956     // render pass subpass. Due to this, we currently only support using resolve attachments when
1957     // there is a single draw attachment enabled.
1958     ASSERT(mState.getEnabledDrawBuffers().count() == 1);
1959     uint32_t drawColorIndexGL = static_cast<uint32_t>(*mState.getEnabledDrawBuffers().begin());
1960     RenderTargetVk *drawRenderTarget      = mRenderTargetCache.getColors()[drawColorIndexGL];
1961     const vk::ImageView *resolveImageView = nullptr;
1962     ANGLE_TRY(drawRenderTarget->getImageView(contextVk, &resolveImageView));
1963 
1964     const gl::Framebuffer *srcFramebuffer = contextVk->getState().getReadFramebuffer();
1965     uint32_t readColorIndexGL             = srcFramebuffer->getState().getReadIndex();
1966 
1967     vk::RenderPassCommandBufferHelper &renderPassCommands =
1968         contextVk->getStartedRenderPassCommands();
1969     ASSERT(!renderPassCommands.getRenderPassDesc().hasColorResolveAttachment(readColorIndexGL));
1970 
1971     drawRenderTarget->onColorResolve(contextVk, mCurrentFramebufferDesc.getLayerCount(),
1972                                      readColorIndexGL, *resolveImageView);
1973 
1974     // The render pass is already closed because of the change in the draw buffer.  Just don't let
1975     // it reactivate now that it has a resolve attachment.
1976     contextVk->disableRenderPassReactivation();
1977 
1978     return angle::Result::Continue;
1979 }
1980 
resolveDepthStencilWithSubpass(ContextVk * contextVk,const UtilsVk::BlitResolveParameters & params,VkImageAspectFlags aspects)1981 angle::Result FramebufferVk::resolveDepthStencilWithSubpass(
1982     ContextVk *contextVk,
1983     const UtilsVk::BlitResolveParameters &params,
1984     VkImageAspectFlags aspects)
1985 {
1986     RenderTargetVk *drawRenderTarget      = mRenderTargetCache.getDepthStencil();
1987     const vk::ImageView *resolveImageView = nullptr;
1988     ANGLE_TRY(drawRenderTarget->getImageView(contextVk, &resolveImageView));
1989 
1990     vk::RenderPassCommandBufferHelper &renderPassCommands =
1991         contextVk->getStartedRenderPassCommands();
1992     ASSERT(!renderPassCommands.getRenderPassDesc().hasDepthStencilResolveAttachment());
1993 
1994     drawRenderTarget->onDepthStencilResolve(contextVk, mCurrentFramebufferDesc.getLayerCount(),
1995                                             aspects, *resolveImageView);
1996 
1997     // The render pass is already closed because of the change in the draw buffer.  Just don't let
1998     // it reactivate now that it has a resolve attachment.
1999     contextVk->disableRenderPassReactivation();
2000 
2001     return angle::Result::Continue;
2002 }
2003 
resolveColorWithCommand(ContextVk * contextVk,const UtilsVk::BlitResolveParameters & params,vk::ImageHelper * srcImage)2004 angle::Result FramebufferVk::resolveColorWithCommand(ContextVk *contextVk,
2005                                                      const UtilsVk::BlitResolveParameters &params,
2006                                                      vk::ImageHelper *srcImage)
2007 {
2008     vk::CommandBufferAccess access;
2009     access.onImageTransferRead(VK_IMAGE_ASPECT_COLOR_BIT, srcImage);
2010 
2011     for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
2012     {
2013         RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL];
2014         vk::ImageHelper &dstImage        = drawRenderTarget->getImageForWrite();
2015 
2016         access.onImageTransferWrite(drawRenderTarget->getLevelIndex(), 1,
2017                                     drawRenderTarget->getLayerIndex(), 1, VK_IMAGE_ASPECT_COLOR_BIT,
2018                                     &dstImage);
2019     }
2020 
2021     vk::OutsideRenderPassCommandBuffer *commandBuffer;
2022     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
2023 
2024     VkImageResolve resolveRegion                = {};
2025     resolveRegion.srcSubresource.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
2026     resolveRegion.srcSubresource.mipLevel       = 0;
2027     resolveRegion.srcSubresource.baseArrayLayer = params.srcLayer;
2028     resolveRegion.srcSubresource.layerCount     = 1;
2029     resolveRegion.srcOffset.x                   = params.blitArea.x;
2030     resolveRegion.srcOffset.y                   = params.blitArea.y;
2031     resolveRegion.srcOffset.z                   = 0;
2032     resolveRegion.dstSubresource.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
2033     resolveRegion.dstSubresource.layerCount     = 1;
2034     resolveRegion.dstOffset.x                   = params.blitArea.x;
2035     resolveRegion.dstOffset.y                   = params.blitArea.y;
2036     resolveRegion.dstOffset.z                   = 0;
2037     resolveRegion.extent.width                  = params.blitArea.width;
2038     resolveRegion.extent.height                 = params.blitArea.height;
2039     resolveRegion.extent.depth                  = 1;
2040 
2041     angle::VulkanPerfCounters &perfCounters = contextVk->getPerfCounters();
2042     for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
2043     {
2044         RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL];
2045         vk::ImageHelper &dstImage        = drawRenderTarget->getImageForWrite();
2046 
2047         vk::LevelIndex levelVk = dstImage.toVkLevel(drawRenderTarget->getLevelIndex());
2048         resolveRegion.dstSubresource.mipLevel       = levelVk.get();
2049         resolveRegion.dstSubresource.baseArrayLayer = drawRenderTarget->getLayerIndex();
2050 
2051         srcImage->resolve(&dstImage, resolveRegion, commandBuffer);
2052 
2053         perfCounters.resolveImageCommands++;
2054     }
2055 
2056     return angle::Result::Continue;
2057 }
2058 
checkStatus(const gl::Context * context) const2059 gl::FramebufferStatus FramebufferVk::checkStatus(const gl::Context *context) const
2060 {
2061     // if we have both a depth and stencil buffer, they must refer to the same object
2062     // since we only support packed_depth_stencil and not separate depth and stencil
2063     if (mState.hasSeparateDepthAndStencilAttachments())
2064     {
2065         return gl::FramebufferStatus::Incomplete(
2066             GL_FRAMEBUFFER_UNSUPPORTED,
2067             gl::err::kFramebufferIncompleteUnsupportedSeparateDepthStencilBuffers);
2068     }
2069 
2070     return gl::FramebufferStatus::Complete();
2071 }
2072 
invalidateImpl(ContextVk * contextVk,size_t count,const GLenum * attachments,bool isSubInvalidate,const gl::Rectangle & invalidateArea)2073 angle::Result FramebufferVk::invalidateImpl(ContextVk *contextVk,
2074                                             size_t count,
2075                                             const GLenum *attachments,
2076                                             bool isSubInvalidate,
2077                                             const gl::Rectangle &invalidateArea)
2078 {
2079     gl::DrawBufferMask invalidateColorBuffers;
2080     bool invalidateDepthBuffer   = false;
2081     bool invalidateStencilBuffer = false;
2082 
2083     for (size_t i = 0; i < count; ++i)
2084     {
2085         const GLenum attachment = attachments[i];
2086 
2087         switch (attachment)
2088         {
2089             case GL_DEPTH:
2090             case GL_DEPTH_ATTACHMENT:
2091                 invalidateDepthBuffer = true;
2092                 break;
2093             case GL_STENCIL:
2094             case GL_STENCIL_ATTACHMENT:
2095                 invalidateStencilBuffer = true;
2096                 break;
2097             case GL_DEPTH_STENCIL_ATTACHMENT:
2098                 invalidateDepthBuffer   = true;
2099                 invalidateStencilBuffer = true;
2100                 break;
2101             default:
2102                 ASSERT(
2103                     (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15) ||
2104                     (attachment == GL_COLOR));
2105 
2106                 invalidateColorBuffers.set(
2107                     attachment == GL_COLOR ? 0u : (attachment - GL_COLOR_ATTACHMENT0));
2108         }
2109     }
2110 
2111     // Shouldn't try to issue deferred clears if invalidating sub framebuffer.
2112     ASSERT(mDeferredClears.empty() || !isSubInvalidate);
2113 
2114     // Remove deferred clears for the invalidated attachments.
2115     if (invalidateDepthBuffer)
2116     {
2117         mDeferredClears.reset(vk::kUnpackedDepthIndex);
2118     }
2119     if (invalidateStencilBuffer)
2120     {
2121         mDeferredClears.reset(vk::kUnpackedStencilIndex);
2122     }
2123     for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
2124     {
2125         if (invalidateColorBuffers.test(colorIndexGL))
2126         {
2127             mDeferredClears.reset(colorIndexGL);
2128         }
2129     }
2130 
2131     // If there are still deferred clears, restage them. See relevant comment in invalidateSub.
2132     restageDeferredClears(contextVk);
2133 
2134     const auto &colorRenderTargets           = mRenderTargetCache.getColors();
2135     RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil();
2136 
2137     // If not a partial invalidate, mark the contents of the invalidated attachments as undefined,
2138     // so their loadOp can be set to DONT_CARE in the following render pass.
2139     if (!isSubInvalidate)
2140     {
2141         for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
2142         {
2143             if (invalidateColorBuffers.test(colorIndexGL))
2144             {
2145                 RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
2146                 ASSERT(colorRenderTarget);
2147 
2148                 bool preferToKeepContentsDefined = false;
2149                 colorRenderTarget->invalidateEntireContent(contextVk, &preferToKeepContentsDefined);
2150                 if (preferToKeepContentsDefined)
2151                 {
2152                     invalidateColorBuffers.reset(colorIndexGL);
2153                 }
2154             }
2155         }
2156 
2157         // If we have a depth / stencil render target, invalidate its aspects.
2158         if (depthStencilRenderTarget)
2159         {
2160             if (invalidateDepthBuffer)
2161             {
2162                 bool preferToKeepContentsDefined = false;
2163                 depthStencilRenderTarget->invalidateEntireContent(contextVk,
2164                                                                   &preferToKeepContentsDefined);
2165                 if (preferToKeepContentsDefined)
2166                 {
2167                     invalidateDepthBuffer = false;
2168                 }
2169             }
2170             if (invalidateStencilBuffer)
2171             {
2172                 bool preferToKeepContentsDefined = false;
2173                 depthStencilRenderTarget->invalidateEntireStencilContent(
2174                     contextVk, &preferToKeepContentsDefined);
2175                 if (preferToKeepContentsDefined)
2176                 {
2177                     invalidateStencilBuffer = false;
2178                 }
2179             }
2180         }
2181     }
2182 
2183     // To ensure we invalidate the right renderpass we require that the current framebuffer be the
2184     // same as the current renderpass' framebuffer. E.g. prevent sequence like:
2185     //- Bind FBO 1, draw
2186     //- Bind FBO 2, draw
2187     //- Bind FBO 1, invalidate D/S
2188     // to invalidate the D/S of FBO 2 since it would be the currently active renderpass.
2189     if (contextVk->hasStartedRenderPassWithQueueSerial(mLastRenderPassQueueSerial))
2190     {
2191         bool closeRenderPass = false;
2192 
2193         // Mark the invalidated attachments in the render pass for loadOp and storeOp determination
2194         // at its end.
2195         vk::PackedAttachmentIndex colorIndexVk(0);
2196         for (size_t colorIndexGL : mState.getColorAttachmentsMask())
2197         {
2198             if (mState.getEnabledDrawBuffers()[colorIndexGL] &&
2199                 invalidateColorBuffers.test(colorIndexGL))
2200             {
2201                 contextVk->getStartedRenderPassCommands().invalidateRenderPassColorAttachment(
2202                     contextVk->getState(), colorIndexGL, colorIndexVk, invalidateArea);
2203 
2204                 // If invalidating a color image with emulated channels, a clear is automatically
2205                 // staged so the emulated channels don't contain invalid data later.  This is
2206                 // problematic with deferred clears; the clear marks the framebuffer attachment as
2207                 // dirty, and the next command causes |FramebufferVk::syncState| to pick the clear
2208                 // up as a deferred clear.
2209                 //
2210                 // This is normally correct, except if the following command is another draw call;
2211                 // in that case, the render pass does not close, yet the clear is cached in
2212                 // |mDeferredClears|.  When the render pass later closes, it undoes the invalidate
2213                 // and attempts to remove the clear from the image... but it does not exist there
2214                 // anymore (it's in |mDeferredClears|).  Next usage of the image then clears it,
2215                 // undoing the draws after invalidate.
2216                 //
2217                 // In this case, the simplest approach is to close the render pass right away here.
2218                 // Note that it is not possible to make |FramebufferVk::syncState| avoid picking up
2219                 // the clear in |mDeferredClears|, not apply the clear, _and_ keep the render pass
2220                 // open; because future uses of the image (like with |glReadPixels|) will not
2221                 // trigger |FramebufferVk::syncState| and the clear won't be done.
2222                 if (mEmulatedAlphaAttachmentMask[colorIndexGL])
2223                 {
2224                     closeRenderPass = true;
2225                 }
2226             }
2227             ++colorIndexVk;
2228         }
2229 
2230         if (depthStencilRenderTarget)
2231         {
2232             const gl::DepthStencilState &dsState = contextVk->getState().getDepthStencilState();
2233             if (invalidateDepthBuffer)
2234             {
2235                 contextVk->getStartedRenderPassCommands().invalidateRenderPassDepthAttachment(
2236                     dsState, invalidateArea);
2237             }
2238 
2239             if (invalidateStencilBuffer)
2240             {
2241                 contextVk->getStartedRenderPassCommands().invalidateRenderPassStencilAttachment(
2242                     dsState, mState.getStencilBitCount(), invalidateArea);
2243             }
2244         }
2245 
2246         if (closeRenderPass)
2247         {
2248             ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(
2249                 RenderPassClosureReason::ColorBufferWithEmulatedAlphaInvalidate));
2250         }
2251     }
2252 
2253     return angle::Result::Continue;
2254 }
2255 
updateColorAttachment(const gl::Context * context,uint32_t colorIndexGL)2256 angle::Result FramebufferVk::updateColorAttachment(const gl::Context *context,
2257                                                    uint32_t colorIndexGL)
2258 {
2259     ANGLE_TRY(mRenderTargetCache.updateColorRenderTarget(context, mState, colorIndexGL));
2260 
2261     // Update cached masks for masked clears.
2262     RenderTargetVk *renderTarget = mRenderTargetCache.getColors()[colorIndexGL];
2263     if (renderTarget)
2264     {
2265         const angle::Format &actualFormat = renderTarget->getImageActualFormat();
2266         updateActiveColorMasks(colorIndexGL, actualFormat.redBits > 0, actualFormat.greenBits > 0,
2267                                actualFormat.blueBits > 0, actualFormat.alphaBits > 0);
2268 
2269         const angle::Format &intendedFormat = renderTarget->getImageIntendedFormat();
2270         mEmulatedAlphaAttachmentMask.set(
2271             colorIndexGL, intendedFormat.alphaBits == 0 && actualFormat.alphaBits > 0);
2272     }
2273     else
2274     {
2275         updateActiveColorMasks(colorIndexGL, false, false, false, false);
2276     }
2277 
2278     const bool enabledColor =
2279         renderTarget && mState.getColorAttachments()[colorIndexGL].isAttached();
2280     const bool enabledResolve = enabledColor && renderTarget->hasResolveAttachment();
2281 
2282     if (enabledColor)
2283     {
2284         mCurrentFramebufferDesc.updateColor(colorIndexGL, renderTarget->getDrawSubresourceSerial());
2285         const bool isExternalImage =
2286             mState.getColorAttachments()[colorIndexGL].isExternalImageWithoutIndividualSync();
2287         mIsExternalColorAttachments.set(colorIndexGL, isExternalImage);
2288         mAttachmentHasFrontBufferUsage.set(
2289             colorIndexGL, mState.getColorAttachments()[colorIndexGL].hasFrontBufferUsage());
2290     }
2291     else
2292     {
2293         mCurrentFramebufferDesc.updateColor(colorIndexGL,
2294                                             vk::kInvalidImageOrBufferViewSubresourceSerial);
2295     }
2296 
2297     if (enabledResolve)
2298     {
2299         mCurrentFramebufferDesc.updateColorResolve(colorIndexGL,
2300                                                    renderTarget->getResolveSubresourceSerial());
2301     }
2302     else
2303     {
2304         mCurrentFramebufferDesc.updateColorResolve(colorIndexGL,
2305                                                    vk::kInvalidImageOrBufferViewSubresourceSerial);
2306     }
2307 
2308     return angle::Result::Continue;
2309 }
2310 
updateColorAttachmentColorspace(gl::SrgbWriteControlMode srgbWriteControlMode)2311 void FramebufferVk::updateColorAttachmentColorspace(gl::SrgbWriteControlMode srgbWriteControlMode)
2312 {
2313     // Update colorspace of color attachments.
2314     const auto &colorRenderTargets               = mRenderTargetCache.getColors();
2315     const gl::DrawBufferMask colorAttachmentMask = mState.getColorAttachmentsMask();
2316     for (size_t colorIndexGL : colorAttachmentMask)
2317     {
2318         RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
2319         ASSERT(colorRenderTarget);
2320         colorRenderTarget->updateWriteColorspace(srgbWriteControlMode);
2321     }
2322 }
2323 
updateDepthStencilAttachment(const gl::Context * context)2324 angle::Result FramebufferVk::updateDepthStencilAttachment(const gl::Context *context)
2325 {
2326     ANGLE_TRY(mRenderTargetCache.updateDepthStencilRenderTarget(context, mState));
2327 
2328     ContextVk *contextVk = vk::GetImpl(context);
2329     updateDepthStencilAttachmentSerial(contextVk);
2330 
2331     return angle::Result::Continue;
2332 }
2333 
updateDepthStencilAttachmentSerial(ContextVk * contextVk)2334 void FramebufferVk::updateDepthStencilAttachmentSerial(ContextVk *contextVk)
2335 {
2336     RenderTargetVk *depthStencilRT = getDepthStencilRenderTarget();
2337 
2338     if (depthStencilRT != nullptr)
2339     {
2340         mCurrentFramebufferDesc.updateDepthStencil(depthStencilRT->getDrawSubresourceSerial());
2341     }
2342     else
2343     {
2344         mCurrentFramebufferDesc.updateDepthStencil(vk::kInvalidImageOrBufferViewSubresourceSerial);
2345     }
2346 
2347     if (depthStencilRT != nullptr && depthStencilRT->hasResolveAttachment())
2348     {
2349         mCurrentFramebufferDesc.updateDepthStencilResolve(
2350             depthStencilRT->getResolveSubresourceSerial());
2351     }
2352     else
2353     {
2354         mCurrentFramebufferDesc.updateDepthStencilResolve(
2355             vk::kInvalidImageOrBufferViewSubresourceSerial);
2356     }
2357 }
2358 
flushColorAttachmentUpdates(const gl::Context * context,bool deferClears,uint32_t colorIndexGL)2359 angle::Result FramebufferVk::flushColorAttachmentUpdates(const gl::Context *context,
2360                                                          bool deferClears,
2361                                                          uint32_t colorIndexGL)
2362 {
2363     ContextVk *contextVk             = vk::GetImpl(context);
2364     RenderTargetVk *readRenderTarget = nullptr;
2365     RenderTargetVk *drawRenderTarget = nullptr;
2366 
2367     // It's possible for the read and draw color attachments to be different if different surfaces
2368     // are bound, so we need to flush any staged updates to both.
2369 
2370     // Draw
2371     drawRenderTarget = mRenderTargetCache.getColorDraw(mState, colorIndexGL);
2372     if (drawRenderTarget)
2373     {
2374         if (deferClears)
2375         {
2376             ANGLE_TRY(
2377                 drawRenderTarget->flushStagedUpdates(contextVk, &mDeferredClears, colorIndexGL,
2378                                                      mCurrentFramebufferDesc.getLayerCount()));
2379         }
2380         else
2381         {
2382             ANGLE_TRY(drawRenderTarget->flushStagedUpdates(
2383                 contextVk, nullptr, 0, mCurrentFramebufferDesc.getLayerCount()));
2384         }
2385     }
2386 
2387     // Read
2388     if (mState.getReadBufferState() != GL_NONE && mState.getReadIndex() == colorIndexGL)
2389     {
2390         // Flush staged updates to the read render target as well, but only if it's not the same as
2391         // the draw render target.  This can happen when the read render target is bound to another
2392         // surface.
2393         readRenderTarget = mRenderTargetCache.getColorRead(mState);
2394         if (readRenderTarget && readRenderTarget != drawRenderTarget)
2395         {
2396             ANGLE_TRY(readRenderTarget->flushStagedUpdates(
2397                 contextVk, nullptr, 0, mCurrentFramebufferDesc.getLayerCount()));
2398         }
2399     }
2400 
2401     return angle::Result::Continue;
2402 }
2403 
flushDepthStencilAttachmentUpdates(const gl::Context * context,bool deferClears)2404 angle::Result FramebufferVk::flushDepthStencilAttachmentUpdates(const gl::Context *context,
2405                                                                 bool deferClears)
2406 {
2407     ContextVk *contextVk = vk::GetImpl(context);
2408 
2409     RenderTargetVk *depthStencilRT = getDepthStencilRenderTarget();
2410     if (depthStencilRT == nullptr)
2411     {
2412         return angle::Result::Continue;
2413     }
2414 
2415     if (deferClears)
2416     {
2417         return depthStencilRT->flushStagedUpdates(contextVk, &mDeferredClears,
2418                                                   vk::kUnpackedDepthIndex,
2419                                                   mCurrentFramebufferDesc.getLayerCount());
2420     }
2421 
2422     return depthStencilRT->flushStagedUpdates(contextVk, nullptr, 0,
2423                                               mCurrentFramebufferDesc.getLayerCount());
2424 }
2425 
syncState(const gl::Context * context,GLenum binding,const gl::Framebuffer::DirtyBits & dirtyBits,gl::Command command)2426 angle::Result FramebufferVk::syncState(const gl::Context *context,
2427                                        GLenum binding,
2428                                        const gl::Framebuffer::DirtyBits &dirtyBits,
2429                                        gl::Command command)
2430 {
2431     ContextVk *contextVk = vk::GetImpl(context);
2432 
2433     vk::FramebufferDesc priorFramebufferDesc = mCurrentFramebufferDesc;
2434 
2435     // Keep track of which attachments have dirty content and need their staged updates flushed.
2436     // The respective functions depend on |mCurrentFramebufferDesc::mLayerCount| which is updated
2437     // after all attachment render targets are updated.
2438     gl::DrawBufferMask dirtyColorAttachments;
2439     bool dirtyDepthStencilAttachment = false;
2440 
2441     bool shouldUpdateColorMaskAndBlend = false;
2442     bool shouldUpdateLayerCount        = false;
2443 
2444     // Cache new foveation state, if any
2445     const gl::FoveationState *newFoveationState = nullptr;
2446     gl::Extents foveatedAttachmentSize;
2447 
2448     // For any updated attachments we'll update their Serials below
2449     ASSERT(dirtyBits.any());
2450     for (size_t dirtyBit : dirtyBits)
2451     {
2452         switch (dirtyBit)
2453         {
2454             case gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
2455             case gl::Framebuffer::DIRTY_BIT_DEPTH_BUFFER_CONTENTS:
2456             case gl::Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
2457             case gl::Framebuffer::DIRTY_BIT_STENCIL_BUFFER_CONTENTS:
2458                 ANGLE_TRY(updateDepthStencilAttachment(context));
2459                 shouldUpdateLayerCount      = true;
2460                 dirtyDepthStencilAttachment = true;
2461                 break;
2462             case gl::Framebuffer::DIRTY_BIT_READ_BUFFER:
2463                 ANGLE_TRY(mRenderTargetCache.update(context, mState, dirtyBits));
2464                 break;
2465             case gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
2466                 shouldUpdateColorMaskAndBlend = true;
2467                 shouldUpdateLayerCount        = true;
2468                 break;
2469             case gl::Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
2470             case gl::Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
2471             case gl::Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES:
2472             case gl::Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS:
2473                 // Invalidate the cache. If we have performance critical code hitting this path we
2474                 // can add related data (such as width/height) to the cache
2475                 releaseCurrentFramebuffer(contextVk);
2476                 break;
2477             case gl::Framebuffer::DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE:
2478                 break;
2479             case gl::Framebuffer::DIRTY_BIT_DEFAULT_LAYERS:
2480                 shouldUpdateLayerCount = true;
2481                 break;
2482             case gl::Framebuffer::DIRTY_BIT_FOVEATION:
2483                 // This dirty bit is set iff the framebuffer itself is foveated
2484                 ASSERT(mState.isFoveationEnabled());
2485 
2486                 newFoveationState      = &mState.getFoveationState();
2487                 foveatedAttachmentSize = mState.getExtents();
2488                 break;
2489             default:
2490             {
2491                 static_assert(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0, "FB dirty bits");
2492                 uint32_t colorIndexGL;
2493                 if (dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX)
2494                 {
2495                     colorIndexGL = static_cast<uint32_t>(
2496                         dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
2497                 }
2498                 else
2499                 {
2500                     ASSERT(dirtyBit >= gl::Framebuffer::DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 &&
2501                            dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_BUFFER_CONTENTS_MAX);
2502                     colorIndexGL = static_cast<uint32_t>(
2503                         dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_BUFFER_CONTENTS_0);
2504                 }
2505 
2506                 ANGLE_TRY(updateColorAttachment(context, colorIndexGL));
2507 
2508                 // Check if attachment has foveated rendering, if so grab foveation state
2509                 const gl::FramebufferAttachment *attachment =
2510                     mState.getColorAttachment(colorIndexGL);
2511                 if (attachment && attachment->hasFoveatedRendering())
2512                 {
2513                     // If attachment is foveated the framebuffer must not be.
2514                     ASSERT(!mState.isFoveationEnabled());
2515 
2516                     newFoveationState = attachment->getFoveationState();
2517                     ASSERT(newFoveationState != nullptr);
2518 
2519                     foveatedAttachmentSize = attachment->getSize();
2520                 }
2521 
2522                 // Window system framebuffer only have one color attachment and its property should
2523                 // never change unless via DIRTY_BIT_DRAW_BUFFERS bit.
2524                 if (!mState.isDefault())
2525                 {
2526                     shouldUpdateColorMaskAndBlend = true;
2527                     shouldUpdateLayerCount        = true;
2528                 }
2529                 dirtyColorAttachments.set(colorIndexGL);
2530 
2531                 break;
2532             }
2533         }
2534     }
2535 
2536     // A shared attachment's colospace could have been modified in another context, update
2537     // colorspace of all attachments to reflect current context's colorspace.
2538     gl::SrgbWriteControlMode srgbWriteControlMode = mState.getWriteControlMode();
2539     updateColorAttachmentColorspace(srgbWriteControlMode);
2540     // Update current framebuffer descriptor to reflect the new state.
2541     mCurrentFramebufferDesc.setWriteControlMode(srgbWriteControlMode);
2542 
2543     if (shouldUpdateColorMaskAndBlend)
2544     {
2545         contextVk->updateColorMasks();
2546         contextVk->updateBlendFuncsAndEquations();
2547     }
2548 
2549     if (shouldUpdateLayerCount)
2550     {
2551         updateLayerCount();
2552     }
2553 
2554     if (newFoveationState && mFoveationState != *newFoveationState)
2555     {
2556         ANGLE_TRY(updateFoveationState(contextVk, *newFoveationState, foveatedAttachmentSize));
2557     }
2558 
2559     // Defer clears for draw framebuffer ops.  Note that this will result in a render area that
2560     // completely covers the framebuffer, even if the operation that follows is scissored.
2561     //
2562     // Additionally, defer clears for read framebuffer attachments that are not taking part in a
2563     // blit operation.
2564     const bool isBlitCommand = command >= gl::Command::Blit && command <= gl::Command::BlitAll;
2565 
2566     bool deferColorClears        = binding == GL_DRAW_FRAMEBUFFER;
2567     bool deferDepthStencilClears = binding == GL_DRAW_FRAMEBUFFER;
2568     if (binding == GL_READ_FRAMEBUFFER && isBlitCommand)
2569     {
2570         uint32_t blitMask =
2571             static_cast<uint32_t>(command) - static_cast<uint32_t>(gl::Command::Blit);
2572         if ((blitMask & gl::CommandBlitBufferColor) == 0)
2573         {
2574             deferColorClears = true;
2575         }
2576         if ((blitMask & (gl::CommandBlitBufferDepth | gl::CommandBlitBufferStencil)) == 0)
2577         {
2578             deferDepthStencilClears = true;
2579         }
2580     }
2581 
2582     // If we are notified that any attachment is dirty, but we have deferred clears for them, a
2583     // flushDeferredClears() call is missing somewhere.  ASSERT this to catch these bugs.
2584     vk::ClearValuesArray previousDeferredClears = mDeferredClears;
2585 
2586     for (size_t colorIndexGL : dirtyColorAttachments)
2587     {
2588         ASSERT(!previousDeferredClears.test(colorIndexGL));
2589         ANGLE_TRY(flushColorAttachmentUpdates(context, deferColorClears,
2590                                               static_cast<uint32_t>(colorIndexGL)));
2591     }
2592     if (dirtyDepthStencilAttachment)
2593     {
2594         ASSERT(!previousDeferredClears.testDepth());
2595         ASSERT(!previousDeferredClears.testStencil());
2596         ANGLE_TRY(flushDepthStencilAttachmentUpdates(context, deferDepthStencilClears));
2597     }
2598 
2599     // No-op redundant changes to prevent closing the RenderPass.
2600     if (mCurrentFramebufferDesc == priorFramebufferDesc &&
2601         mCurrentFramebufferDesc.attachmentCount() > 0)
2602     {
2603         return angle::Result::Continue;
2604     }
2605 
2606     // ContextVk::onFramebufferChange will end up calling onRenderPassFinished if necessary,
2607     // which will trigger ending of current render pass.  |mLastRenderPassQueueSerial| is reset
2608     // so that the render pass will not get reactivated, since |mCurrentFramebufferDesc| has
2609     // changed.
2610     mLastRenderPassQueueSerial = QueueSerial();
2611 
2612     updateRenderPassDesc(contextVk);
2613 
2614     // Deactivate Framebuffer
2615     releaseCurrentFramebuffer(contextVk);
2616 
2617     // Notify the ContextVk to update the pipeline desc.
2618     return contextVk->onFramebufferChange(this, command);
2619 }
2620 
updateRenderPassDesc(ContextVk * contextVk)2621 void FramebufferVk::updateRenderPassDesc(ContextVk *contextVk)
2622 {
2623     mRenderPassDesc = {};
2624     mRenderPassDesc.setSamples(getSamples());
2625     mRenderPassDesc.setViewCount(
2626         mState.isMultiview() && mState.getNumViews() > 1 ? mState.getNumViews() : 0);
2627 
2628     // Color attachments.
2629     const auto &colorRenderTargets               = mRenderTargetCache.getColors();
2630     const gl::DrawBufferMask colorAttachmentMask = mState.getColorAttachmentsMask();
2631     for (size_t colorIndexGL = 0; colorIndexGL < colorAttachmentMask.size(); ++colorIndexGL)
2632     {
2633         if (colorAttachmentMask[colorIndexGL])
2634         {
2635             RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
2636             ASSERT(colorRenderTarget);
2637 
2638             if (colorRenderTarget->isYuvResolve())
2639             {
2640                 // If this is YUV resolve target, we use resolveImage's format since image maybe
2641                 // nullptr
2642                 auto const &resolveImage = colorRenderTarget->getResolveImageForRenderPass();
2643                 mRenderPassDesc.packColorAttachment(colorIndexGL, resolveImage.getActualFormatID());
2644                 mRenderPassDesc.packYUVResolveAttachment(colorIndexGL);
2645             }
2646             else
2647             {
2648                 // Account for attachments with colorspace override
2649                 angle::FormatID actualFormat =
2650                     colorRenderTarget->getImageForRenderPass().getActualFormatID();
2651                 if (colorRenderTarget->hasColorspaceOverrideForWrite())
2652                 {
2653                     actualFormat =
2654                         colorRenderTarget->getColorspaceOverrideFormatForWrite(actualFormat);
2655                 }
2656 
2657                 mRenderPassDesc.packColorAttachment(colorIndexGL, actualFormat);
2658                 // Add the resolve attachment, if any.
2659                 if (colorRenderTarget->hasResolveAttachment())
2660                 {
2661                     mRenderPassDesc.packColorResolveAttachment(colorIndexGL);
2662                 }
2663             }
2664         }
2665         else
2666         {
2667             mRenderPassDesc.packColorAttachmentGap(colorIndexGL);
2668         }
2669     }
2670 
2671     // Depth/stencil attachment.
2672     RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget();
2673     if (depthStencilRenderTarget)
2674     {
2675         mRenderPassDesc.packDepthStencilAttachment(
2676             depthStencilRenderTarget->getImageForRenderPass().getActualFormatID());
2677 
2678         // Add the resolve attachment, if any.
2679         if (depthStencilRenderTarget->hasResolveAttachment())
2680         {
2681             mRenderPassDesc.packDepthResolveAttachment();
2682             mRenderPassDesc.packStencilResolveAttachment();
2683         }
2684     }
2685 
2686     if (!contextVk->getFeatures().preferDynamicRendering.enabled &&
2687         contextVk->isInColorFramebufferFetchMode())
2688     {
2689         mRenderPassDesc.setFramebufferFetchMode(vk::FramebufferFetchMode::Color);
2690     }
2691 
2692     if (contextVk->getFeatures().enableMultisampledRenderToTexture.enabled)
2693     {
2694         // Update descriptions regarding multisampled-render-to-texture use.
2695         bool isRenderToTexture = false;
2696         for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
2697         {
2698             const gl::FramebufferAttachment *color = mState.getColorAttachment(colorIndexGL);
2699             ASSERT(color);
2700 
2701             if (color->isRenderToTexture())
2702             {
2703                 isRenderToTexture = true;
2704                 break;
2705             }
2706         }
2707         const gl::FramebufferAttachment *depthStencil = mState.getDepthStencilAttachment();
2708         if (depthStencil && depthStencil->isRenderToTexture())
2709         {
2710             isRenderToTexture = true;
2711         }
2712 
2713         mCurrentFramebufferDesc.updateRenderToTexture(isRenderToTexture);
2714         mRenderPassDesc.updateRenderToTexture(isRenderToTexture);
2715     }
2716 
2717     mCurrentFramebufferDesc.updateUnresolveMask({});
2718     mRenderPassDesc.setWriteControlMode(mCurrentFramebufferDesc.getWriteControlMode());
2719     mRenderPassDesc.setFragmentShadingAttachment(
2720         mCurrentFramebufferDesc.hasFragmentShadingRateAttachment());
2721 
2722     updateLegacyDither(contextVk);
2723 }
2724 
getAttachmentsAndRenderTargets(vk::ErrorContext * context,vk::FramebufferAttachmentsVector<VkImageView> * unpackedAttachments,vk::FramebufferAttachmentsVector<RenderTargetInfo> * packedRenderTargetsInfoOut)2725 angle::Result FramebufferVk::getAttachmentsAndRenderTargets(
2726     vk::ErrorContext *context,
2727     vk::FramebufferAttachmentsVector<VkImageView> *unpackedAttachments,
2728     vk::FramebufferAttachmentsVector<RenderTargetInfo> *packedRenderTargetsInfoOut)
2729 {
2730     bool anyResolveAttachments = false;
2731 
2732     // Color attachments.
2733     mIsYUVResolve                  = false;
2734     const auto &colorRenderTargets = mRenderTargetCache.getColors();
2735     for (size_t colorIndexGL : mState.getColorAttachmentsMask())
2736     {
2737         RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
2738         ASSERT(colorRenderTarget);
2739 
2740         if (colorRenderTarget->isYuvResolve())
2741         {
2742             mIsYUVResolve = true;
2743             if (context->getRenderer()->nullColorAttachmentWithExternalFormatResolve())
2744             {
2745                 // Because the color attachment will be null if
2746                 // nullColorAttachmentWithExternalFormatResolve is VK_TRUE, push YUV resolve as
2747                 // color attachment to ensure the coherency of other attachment information, like
2748                 // ops and clearValues.
2749                 const vk::ImageView *resolveImageView = nullptr;
2750                 ANGLE_TRY(colorRenderTarget->getResolveImageView(context, &resolveImageView));
2751                 unpackedAttachments->push_back(resolveImageView->getHandle());
2752 
2753                 packedRenderTargetsInfoOut->emplace_back(
2754                     RenderTargetInfo(colorRenderTarget, RenderTargetImage::Resolve));
2755 
2756                 anyResolveAttachments = true;
2757                 continue;
2758             }
2759         }
2760         const vk::ImageView *imageView = nullptr;
2761         ANGLE_TRY(colorRenderTarget->getImageViewWithColorspace(
2762             context, mCurrentFramebufferDesc.getWriteControlMode(), &imageView));
2763         unpackedAttachments->push_back(imageView->getHandle());
2764 
2765         packedRenderTargetsInfoOut->emplace_back(
2766             RenderTargetInfo(colorRenderTarget, RenderTargetImage::Attachment));
2767     }
2768 
2769     // Depth/stencil attachment.
2770     RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget();
2771     if (depthStencilRenderTarget)
2772     {
2773         const vk::ImageView *imageView = nullptr;
2774         ANGLE_TRY(depthStencilRenderTarget->getImageView(context, &imageView));
2775 
2776         unpackedAttachments->push_back(imageView->getHandle());
2777         packedRenderTargetsInfoOut->emplace_back(
2778             RenderTargetInfo(depthStencilRenderTarget, RenderTargetImage::Attachment));
2779     }
2780 
2781     // Fragment shading rate attachment.
2782     if (mCurrentFramebufferDesc.hasFragmentShadingRateAttachment())
2783     {
2784         const vk::ImageViewHelper *imageViewHelper = &mFragmentShadingRateImageView;
2785         unpackedAttachments->push_back(
2786             imageViewHelper->getFragmentShadingRateImageView().getHandle());
2787         packedRenderTargetsInfoOut->emplace_back(nullptr, RenderTargetImage::FragmentShadingRate);
2788     }
2789 
2790     // Color resolve attachments.  From here on, the views are placed at sparse indices because of
2791     // |RenderPassFramebuffer|.  That allows more resolve attachments to be added later.
2792     unpackedAttachments->resize(vk::kMaxFramebufferAttachments, VK_NULL_HANDLE);
2793     static_assert(vk::RenderPassFramebuffer::kColorResolveAttachmentBegin <
2794                   vk::kMaxFramebufferAttachments);
2795     static_assert(vk::RenderPassFramebuffer::kDepthStencilResolveAttachment <
2796                   vk::kMaxFramebufferAttachments);
2797 
2798     for (size_t colorIndexGL : mState.getColorAttachmentsMask())
2799     {
2800         RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
2801         ASSERT(colorRenderTarget);
2802 
2803         if (colorRenderTarget->hasResolveAttachment())
2804         {
2805             if (colorRenderTarget->isYuvResolve() &&
2806                 context->getRenderer()->nullColorAttachmentWithExternalFormatResolve())
2807             {
2808                 continue;
2809             }
2810 
2811             const vk::ImageView *resolveImageView = nullptr;
2812             ANGLE_TRY(colorRenderTarget->getResolveImageView(context, &resolveImageView));
2813 
2814             constexpr size_t kBaseIndex = vk::RenderPassFramebuffer::kColorResolveAttachmentBegin;
2815             (*unpackedAttachments)[kBaseIndex + colorIndexGL] = resolveImageView->getHandle();
2816             packedRenderTargetsInfoOut->emplace_back(
2817                 RenderTargetInfo(colorRenderTarget, RenderTargetImage::Resolve));
2818 
2819             anyResolveAttachments = true;
2820         }
2821     }
2822 
2823     // Depth/stencil resolve attachment.
2824     if (depthStencilRenderTarget && depthStencilRenderTarget->hasResolveAttachment())
2825     {
2826         const vk::ImageView *imageView = nullptr;
2827         ANGLE_TRY(depthStencilRenderTarget->getResolveImageView(context, &imageView));
2828 
2829         (*unpackedAttachments)[vk::RenderPassFramebuffer::kDepthStencilResolveAttachment] =
2830             imageView->getHandle();
2831         packedRenderTargetsInfoOut->emplace_back(
2832             RenderTargetInfo(depthStencilRenderTarget, RenderTargetImage::Resolve));
2833 
2834         anyResolveAttachments = true;
2835     }
2836 
2837     // Make sure |AllowAddingResolveAttachmentsToSubpass()| is guarding against all cases where a
2838     // resolve attachment is pre-present in the render pass.
2839     if (anyResolveAttachments)
2840     {
2841         ASSERT(!AllowAddingResolveAttachmentsToSubpass(mRenderPassDesc));
2842     }
2843 
2844     return angle::Result::Continue;
2845 }
2846 
createNewFramebuffer(ContextVk * contextVk,uint32_t framebufferWidth,const uint32_t framebufferHeight,const uint32_t framebufferLayers,const vk::FramebufferAttachmentsVector<VkImageView> & unpackedAttachments,const vk::FramebufferAttachmentsVector<RenderTargetInfo> & renderTargetsInfo)2847 angle::Result FramebufferVk::createNewFramebuffer(
2848     ContextVk *contextVk,
2849     uint32_t framebufferWidth,
2850     const uint32_t framebufferHeight,
2851     const uint32_t framebufferLayers,
2852     const vk::FramebufferAttachmentsVector<VkImageView> &unpackedAttachments,
2853     const vk::FramebufferAttachmentsVector<RenderTargetInfo> &renderTargetsInfo)
2854 {
2855     ASSERT(!contextVk->getFeatures().preferDynamicRendering.enabled);
2856 
2857     // The backbuffer framebuffer is cached in WindowSurfaceVk instead.
2858     ASSERT(mBackbuffer == nullptr);
2859     // Called only when a new framebuffer is needed.
2860     ASSERT(!mCurrentFramebuffer.valid());
2861 
2862     // When using imageless framebuffers, the framebuffer cache is not utilized.
2863     const bool useImagelessFramebuffer =
2864         contextVk->getFeatures().supportsImagelessFramebuffer.enabled;
2865 
2866     // Try to retrieve a framebuffer from the cache.
2867     if (!useImagelessFramebuffer && contextVk->getShareGroup()->getFramebufferCache().get(
2868                                         contextVk, mCurrentFramebufferDesc, mCurrentFramebuffer))
2869     {
2870         ASSERT(mCurrentFramebuffer.valid());
2871         mIsCurrentFramebufferCached = true;
2872         return angle::Result::Continue;
2873     }
2874 
2875     const vk::RenderPass *compatibleRenderPass = nullptr;
2876     ANGLE_TRY(contextVk->getCompatibleRenderPass(mRenderPassDesc, &compatibleRenderPass));
2877 
2878     // Create a new framebuffer.
2879     vk::FramebufferHelper newFramebuffer;
2880 
2881     VkFramebufferCreateInfo framebufferInfo = {};
2882     framebufferInfo.sType                   = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
2883     framebufferInfo.flags                   = 0;
2884     framebufferInfo.renderPass              = compatibleRenderPass->getHandle();
2885     framebufferInfo.attachmentCount         = static_cast<uint32_t>(renderTargetsInfo.size());
2886     framebufferInfo.width                   = framebufferWidth;
2887     framebufferInfo.height                  = framebufferHeight;
2888     framebufferInfo.layers                  = framebufferLayers;
2889 
2890     // Check that our description matches our attachments. Can catch implementation bugs.
2891     ASSERT((mIsYUVResolve &&
2892             contextVk->getRenderer()->nullColorAttachmentWithExternalFormatResolve()) ||
2893            static_cast<uint32_t>(renderTargetsInfo.size()) ==
2894                mCurrentFramebufferDesc.attachmentCount());
2895 
2896     if (!useImagelessFramebuffer)
2897     {
2898         vk::FramebufferAttachmentsVector<VkImageView> packedAttachments = unpackedAttachments;
2899         vk::RenderPassFramebuffer::PackViews(&packedAttachments);
2900 
2901         ASSERT(renderTargetsInfo.size() == packedAttachments.size());
2902         framebufferInfo.pAttachments = packedAttachments.data();
2903 
2904         // The cache key (|FramebufferDesc|) can't distinguish between two framebuffers with 0
2905         // attachments but with different sizes.  For simplicity, 0-attachment framebuffers are not
2906         // cached.
2907         ANGLE_TRY(newFramebuffer.init(contextVk, framebufferInfo));
2908         if (packedAttachments.empty())
2909         {
2910             mCurrentFramebuffer         = std::move(newFramebuffer.getFramebuffer());
2911             mIsCurrentFramebufferCached = false;
2912         }
2913         else
2914         {
2915             insertCache(contextVk, mCurrentFramebufferDesc, std::move(newFramebuffer));
2916 
2917             const bool result = contextVk->getShareGroup()->getFramebufferCache().get(
2918                 contextVk, mCurrentFramebufferDesc, mCurrentFramebuffer);
2919             ASSERT(result);
2920             mIsCurrentFramebufferCached = true;
2921         }
2922 
2923         return angle::Result::Continue;
2924     }
2925 
2926     // For imageless framebuffers, attachment image and create info objects should be defined
2927     // when creating the new framebuffer.
2928     vk::FramebufferAttachmentsVector<VkFramebufferAttachmentImageInfo> attachmentImageInfos(
2929         renderTargetsInfo.size(), {});
2930 
2931     for (size_t index = 0; index < renderTargetsInfo.size(); ++index)
2932     {
2933         const RenderTargetInfo &info                     = renderTargetsInfo[index];
2934         VkFramebufferAttachmentImageInfo &attachmentInfo = attachmentImageInfos[index];
2935 
2936         attachmentInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO;
2937 
2938         // The fragment shading rate attachment does not have a corresponding render target, and is
2939         // handled specially.
2940         if (info.renderTargetImage == RenderTargetImage::FragmentShadingRate)
2941         {
2942             attachmentInfo.width  = mFragmentShadingRateImage.getExtents().width;
2943             attachmentInfo.height = mFragmentShadingRateImage.getExtents().height;
2944 
2945             attachmentInfo.layerCount = 1;
2946             attachmentInfo.flags      = mFragmentShadingRateImage.getCreateFlags();
2947             attachmentInfo.usage      = mFragmentShadingRateImage.getUsage();
2948             attachmentInfo.viewFormatCount =
2949                 static_cast<uint32_t>(mFragmentShadingRateImage.getViewFormats().size());
2950             attachmentInfo.pViewFormats = mFragmentShadingRateImage.getViewFormats().data();
2951             continue;
2952         }
2953 
2954         vk::ImageHelper *image = (info.renderTargetImage == RenderTargetImage::Resolve ||
2955                                   info.renderTarget->isYuvResolve())
2956                                      ? &info.renderTarget->getResolveImageForRenderPass()
2957                                      : &info.renderTarget->getImageForRenderPass();
2958 
2959         const gl::LevelIndex level = info.renderTarget->getLevelIndexForImage(*image);
2960         const uint32_t layerCount  = info.renderTarget->getLayerCount();
2961         const gl::Extents extents  = image->getLevelExtents2D(image->toVkLevel(level));
2962 
2963         attachmentInfo.width           = std::max(extents.width, 1);
2964         attachmentInfo.height          = std::max(extents.height, 1);
2965         attachmentInfo.layerCount      = mCurrentFramebufferDesc.isMultiview()
2966                                              ? std::max<uint32_t>(mRenderPassDesc.viewCount(), 1u)
2967                                              : layerCount;
2968         attachmentInfo.flags           = image->getCreateFlags();
2969         attachmentInfo.usage           = image->getUsage();
2970         attachmentInfo.viewFormatCount = static_cast<uint32_t>(image->getViewFormats().size());
2971         attachmentInfo.pViewFormats    = image->getViewFormats().data();
2972     }
2973 
2974     VkFramebufferAttachmentsCreateInfo attachmentsCreateInfo = {};
2975     attachmentsCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO;
2976     attachmentsCreateInfo.attachmentImageInfoCount =
2977         static_cast<uint32_t>(attachmentImageInfos.size());
2978     attachmentsCreateInfo.pAttachmentImageInfos = attachmentImageInfos.data();
2979 
2980     framebufferInfo.flags |= VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT;
2981     vk::AddToPNextChain(&framebufferInfo, &attachmentsCreateInfo);
2982 
2983     ANGLE_TRY(newFramebuffer.init(contextVk, framebufferInfo));
2984     mCurrentFramebuffer = std::move(newFramebuffer.getFramebuffer());
2985 
2986     return angle::Result::Continue;
2987 }
2988 
getFramebuffer(ContextVk * contextVk,vk::RenderPassFramebuffer * framebufferOut)2989 angle::Result FramebufferVk::getFramebuffer(ContextVk *contextVk,
2990                                             vk::RenderPassFramebuffer *framebufferOut)
2991 {
2992     ASSERT(!mRenderPassDesc.hasDepthStencilFramebufferFetch());
2993     ASSERT(mCurrentFramebufferDesc.hasColorFramebufferFetch() ==
2994            mRenderPassDesc.hasColorFramebufferFetch());
2995 
2996     const gl::Extents attachmentsSize = mState.getExtents();
2997     ASSERT(attachmentsSize.width != 0 && attachmentsSize.height != 0);
2998 
2999     uint32_t framebufferWidth        = static_cast<uint32_t>(attachmentsSize.width);
3000     uint32_t framebufferHeight       = static_cast<uint32_t>(attachmentsSize.height);
3001     const uint32_t framebufferLayers = !mCurrentFramebufferDesc.isMultiview()
3002                                            ? std::max(mCurrentFramebufferDesc.getLayerCount(), 1u)
3003                                            : 1;
3004 
3005     vk::FramebufferAttachmentsVector<VkImageView> unpackedAttachments;
3006     vk::FramebufferAttachmentsVector<RenderTargetInfo> renderTargetsInfo;
3007     ANGLE_TRY(getAttachmentsAndRenderTargets(contextVk, &unpackedAttachments, &renderTargetsInfo));
3008 
3009     vk::Framebuffer framebufferHandle;
3010     if (contextVk->getFeatures().preferDynamicRendering.enabled)
3011     {
3012         // Nothing to do with dynamic rendering.  The image views and other info are still placed in
3013         // |framebufferOut| to be passed to |vkCmdBeginRendering| similarly to how they are used
3014         // with imageless framebuffers with render pass objects.
3015     }
3016     else if (mCurrentFramebuffer.valid())
3017     {
3018         // If a valid framebuffer is already created, use it.  This is not done when the swapchain
3019         // is being resolved, because the appropriate framebuffer needs to be queried from the back
3020         // buffer.
3021         framebufferHandle.setHandle(mCurrentFramebuffer.getHandle());
3022     }
3023     else
3024     {
3025         // For the default framebuffer attached to a window surface, WindowSurfaceVk caches a
3026         // handful of framebuffer objects which are queried here.  For the rest, a framebuffer needs
3027         // to be created based on the current attachments to the FBO.
3028         if (mBackbuffer == nullptr)
3029         {
3030             // Create a new framebuffer
3031             ANGLE_TRY(createNewFramebuffer(contextVk, framebufferWidth, framebufferHeight,
3032                                            framebufferLayers, unpackedAttachments,
3033                                            renderTargetsInfo));
3034             ASSERT(mCurrentFramebuffer.valid());
3035             framebufferHandle.setHandle(mCurrentFramebuffer.getHandle());
3036         }
3037         else
3038         {
3039             const vk::RenderPass *compatibleRenderPass = nullptr;
3040             ANGLE_TRY(contextVk->getCompatibleRenderPass(mRenderPassDesc, &compatibleRenderPass));
3041 
3042             // If there is a backbuffer, query the framebuffer from WindowSurfaceVk instead.
3043             ANGLE_TRY(mBackbuffer->getCurrentFramebuffer(
3044                 contextVk,
3045                 mRenderPassDesc.hasColorFramebufferFetch() ? vk::FramebufferFetchMode::Color
3046                                                            : vk::FramebufferFetchMode::None,
3047                 *compatibleRenderPass, &framebufferHandle));
3048         }
3049     }
3050 
3051     if (mBackbuffer != nullptr)
3052     {
3053         // Account for swapchain pre-rotation
3054         framebufferWidth  = renderTargetsInfo[0].renderTarget->getRotatedExtents().width;
3055         framebufferHeight = renderTargetsInfo[0].renderTarget->getRotatedExtents().height;
3056     }
3057 
3058     const vk::ImagelessFramebuffer imagelessFramebuffer =
3059         contextVk->getFeatures().preferDynamicRendering.enabled ||
3060                 (contextVk->getFeatures().supportsImagelessFramebuffer.enabled &&
3061                  mBackbuffer == nullptr)
3062             ? vk::ImagelessFramebuffer::Yes
3063             : vk::ImagelessFramebuffer::No;
3064     const vk::RenderPassSource source = mBackbuffer == nullptr
3065                                             ? vk::RenderPassSource::FramebufferObject
3066                                             : vk::RenderPassSource::DefaultFramebuffer;
3067 
3068     framebufferOut->setFramebuffer(
3069         contextVk, std::move(framebufferHandle), std::move(unpackedAttachments), framebufferWidth,
3070         framebufferHeight, framebufferLayers, imagelessFramebuffer, source);
3071 
3072     return angle::Result::Continue;
3073 }
3074 
mergeClearsWithDeferredClears(gl::DrawBufferMask clearColorBuffers,bool clearDepth,bool clearStencil,const gl::DrawBuffersArray<VkClearColorValue> & clearColorValues,const VkClearDepthStencilValue & clearDepthStencilValue)3075 void FramebufferVk::mergeClearsWithDeferredClears(
3076     gl::DrawBufferMask clearColorBuffers,
3077     bool clearDepth,
3078     bool clearStencil,
3079     const gl::DrawBuffersArray<VkClearColorValue> &clearColorValues,
3080     const VkClearDepthStencilValue &clearDepthStencilValue)
3081 {
3082     // Apply clears to mDeferredClears.  Note that clears override deferred clears.
3083 
3084     // Color clears.
3085     for (size_t colorIndexGL : clearColorBuffers)
3086     {
3087         ASSERT(mState.getEnabledDrawBuffers().test(colorIndexGL));
3088         VkClearValue clearValue =
3089             getCorrectedColorClearValue(colorIndexGL, clearColorValues[colorIndexGL]);
3090         mDeferredClears.store(static_cast<uint32_t>(colorIndexGL), VK_IMAGE_ASPECT_COLOR_BIT,
3091                               clearValue);
3092     }
3093 
3094     // Depth and stencil clears.
3095     VkImageAspectFlags dsAspectFlags = 0;
3096     VkClearValue dsClearValue        = {};
3097     dsClearValue.depthStencil        = clearDepthStencilValue;
3098     if (clearDepth)
3099     {
3100         dsAspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
3101     }
3102     if (clearStencil)
3103     {
3104         dsAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
3105     }
3106 
3107     if (dsAspectFlags != 0)
3108     {
3109         mDeferredClears.store(vk::kUnpackedDepthIndex, dsAspectFlags, dsClearValue);
3110     }
3111 }
3112 
clearWithDraw(ContextVk * contextVk,const gl::Rectangle & clearArea,gl::DrawBufferMask clearColorBuffers,bool clearDepth,bool clearStencil,gl::BlendStateExt::ColorMaskStorage::Type colorMasks,uint8_t stencilMask,const gl::DrawBuffersArray<VkClearColorValue> & clearColorValues,const VkClearDepthStencilValue & clearDepthStencilValue)3113 angle::Result FramebufferVk::clearWithDraw(
3114     ContextVk *contextVk,
3115     const gl::Rectangle &clearArea,
3116     gl::DrawBufferMask clearColorBuffers,
3117     bool clearDepth,
3118     bool clearStencil,
3119     gl::BlendStateExt::ColorMaskStorage::Type colorMasks,
3120     uint8_t stencilMask,
3121     const gl::DrawBuffersArray<VkClearColorValue> &clearColorValues,
3122     const VkClearDepthStencilValue &clearDepthStencilValue)
3123 {
3124     // All deferred clears should be handled already.
3125     ASSERT(mDeferredClears.empty());
3126 
3127     UtilsVk::ClearFramebufferParameters params = {};
3128     params.clearArea                           = clearArea;
3129     params.depthStencilClearValue              = clearDepthStencilValue;
3130     params.stencilMask                         = stencilMask;
3131 
3132     params.clearColor   = true;
3133     params.clearDepth   = clearDepth;
3134     params.clearStencil = clearStencil;
3135 
3136     const auto &colorRenderTargets = mRenderTargetCache.getColors();
3137     for (size_t colorIndexGL : clearColorBuffers)
3138     {
3139         const RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
3140         ASSERT(colorRenderTarget);
3141 
3142         params.colorClearValue = clearColorValues[colorIndexGL];
3143         params.colorFormat     = &colorRenderTarget->getImageForRenderPass().getActualFormat();
3144         params.colorAttachmentIndexGL = static_cast<uint32_t>(colorIndexGL);
3145         params.colorMaskFlags =
3146             gl::BlendStateExt::ColorMaskStorage::GetValueIndexed(colorIndexGL, colorMasks);
3147         if (mEmulatedAlphaAttachmentMask[colorIndexGL])
3148         {
3149             params.colorMaskFlags &= ~VK_COLOR_COMPONENT_A_BIT;
3150         }
3151 
3152         // TODO: implement clear of layered framebuffers.  UtilsVk::clearFramebuffer should add a
3153         // geometry shader that is instanced layerCount times (or loops layerCount times), each time
3154         // selecting a different layer.
3155         // http://anglebug.com/42263992
3156         ASSERT(mCurrentFramebufferDesc.isMultiview() || colorRenderTarget->getLayerCount() == 1);
3157 
3158         ANGLE_TRY(contextVk->getUtils().clearFramebuffer(contextVk, this, params));
3159 
3160         // Clear depth/stencil only once!
3161         params.clearDepth   = false;
3162         params.clearStencil = false;
3163     }
3164 
3165     // If there was no color clear, clear depth/stencil alone.
3166     if (params.clearDepth || params.clearStencil)
3167     {
3168         params.clearColor = false;
3169         ANGLE_TRY(contextVk->getUtils().clearFramebuffer(contextVk, this, params));
3170     }
3171 
3172     return angle::Result::Continue;
3173 }
3174 
getCorrectedColorClearValue(size_t colorIndexGL,const VkClearColorValue & clearColor) const3175 VkClearValue FramebufferVk::getCorrectedColorClearValue(size_t colorIndexGL,
3176                                                         const VkClearColorValue &clearColor) const
3177 {
3178     VkClearValue clearValue = {};
3179     clearValue.color        = clearColor;
3180 
3181     if (!mEmulatedAlphaAttachmentMask[colorIndexGL])
3182     {
3183         return clearValue;
3184     }
3185 
3186     // If the render target doesn't have alpha, but its emulated format has it, clear the alpha
3187     // to 1.
3188     RenderTargetVk *renderTarget = getColorDrawRenderTarget(colorIndexGL);
3189     const angle::Format &format  = renderTarget->getImageActualFormat();
3190 
3191     if (format.isUint())
3192     {
3193         clearValue.color.uint32[3] = kEmulatedAlphaValue;
3194     }
3195     else if (format.isSint())
3196     {
3197         clearValue.color.int32[3] = kEmulatedAlphaValue;
3198     }
3199     else
3200     {
3201         clearValue.color.float32[3] = kEmulatedAlphaValue;
3202     }
3203 
3204     return clearValue;
3205 }
3206 
restageDeferredClears(ContextVk * contextVk)3207 void FramebufferVk::restageDeferredClears(ContextVk *contextVk)
3208 {
3209     // Called when restaging clears of the draw framebuffer.  In that case, there can't be any
3210     // render passes open, otherwise the clear would have applied to the render pass.  In the
3211     // exceptional occasion in blit where the read framebuffer accumulates deferred clears, it can
3212     // be deferred while this assumption doesn't hold (and restageDeferredClearsForReadFramebuffer
3213     // should be used instead).
3214     ASSERT(!contextVk->hasActiveRenderPass() || !mDeferredClears.any());
3215     restageDeferredClearsImpl(contextVk);
3216 }
3217 
restageDeferredClearsForReadFramebuffer(ContextVk * contextVk)3218 void FramebufferVk::restageDeferredClearsForReadFramebuffer(ContextVk *contextVk)
3219 {
3220     restageDeferredClearsImpl(contextVk);
3221 }
3222 
restageDeferredClearsImpl(ContextVk * contextVk)3223 void FramebufferVk::restageDeferredClearsImpl(ContextVk *contextVk)
3224 {
3225     // Set the appropriate aspect and clear values for depth and stencil.
3226     VkImageAspectFlags dsAspectFlags  = 0;
3227     VkClearValue dsClearValue         = {};
3228     dsClearValue.depthStencil.depth   = mDeferredClears.getDepthValue();
3229     dsClearValue.depthStencil.stencil = mDeferredClears.getStencilValue();
3230 
3231     if (mDeferredClears.testDepth())
3232     {
3233         dsAspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
3234         mDeferredClears.reset(vk::kUnpackedDepthIndex);
3235     }
3236 
3237     if (mDeferredClears.testStencil())
3238     {
3239         dsAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
3240         mDeferredClears.reset(vk::kUnpackedStencilIndex);
3241     }
3242 
3243     // Go through deferred clears and stage the clears for future.
3244     for (size_t colorIndexGL : mDeferredClears.getColorMask())
3245     {
3246         RenderTargetVk *renderTarget = getColorDrawRenderTarget(colorIndexGL);
3247         gl::ImageIndex imageIndex =
3248             renderTarget->getImageIndexForClear(mCurrentFramebufferDesc.getLayerCount());
3249         renderTarget->getImageForWrite().stageClear(imageIndex, VK_IMAGE_ASPECT_COLOR_BIT,
3250                                                     mDeferredClears[colorIndexGL]);
3251         mDeferredClears.reset(colorIndexGL);
3252     }
3253 
3254     if (dsAspectFlags)
3255     {
3256         RenderTargetVk *renderTarget = getDepthStencilRenderTarget();
3257         ASSERT(renderTarget);
3258 
3259         gl::ImageIndex imageIndex =
3260             renderTarget->getImageIndexForClear(mCurrentFramebufferDesc.getLayerCount());
3261         renderTarget->getImageForWrite().stageClear(imageIndex, dsAspectFlags, dsClearValue);
3262     }
3263 }
3264 
clearWithCommand(ContextVk * contextVk,const gl::Rectangle & scissoredRenderArea,ClearWithCommand behavior,vk::ClearValuesArray * clears)3265 void FramebufferVk::clearWithCommand(ContextVk *contextVk,
3266                                      const gl::Rectangle &scissoredRenderArea,
3267                                      ClearWithCommand behavior,
3268                                      vk::ClearValuesArray *clears)
3269 {
3270     // Clear is not affected by viewport, so ContextVk::updateScissor may have decided on a smaller
3271     // render area.  Grow the render area to the full framebuffer size as this clear path is taken
3272     // when not scissored.
3273     vk::RenderPassCommandBufferHelper *renderPassCommands =
3274         &contextVk->getStartedRenderPassCommands();
3275     renderPassCommands->growRenderArea(contextVk, scissoredRenderArea);
3276 
3277     gl::AttachmentVector<VkClearAttachment> attachments;
3278 
3279     const bool optimizeWithLoadOp = behavior == ClearWithCommand::OptimizeWithLoadOp;
3280 
3281     // Go through deferred clears and add them to the list of attachments to clear.  If any
3282     // attachment is unused, skip the clear.  clearWithLoadOp will follow and move the remaining
3283     // clears up to loadOp.
3284     vk::PackedAttachmentIndex colorIndexVk(0);
3285     for (size_t colorIndexGL : mState.getColorAttachmentsMask())
3286     {
3287         if (clears->getColorMask().test(colorIndexGL))
3288         {
3289             if (renderPassCommands->hasAnyColorAccess(colorIndexVk) ||
3290                 renderPassCommands->getRenderPassDesc().hasColorUnresolveAttachment(colorIndexGL) ||
3291                 !optimizeWithLoadOp)
3292             {
3293                 // With render pass objects, the clears are indexed by the subpass-mapped locations.
3294                 // With dynamic rendering, they are indexed by the actual attachment index.
3295                 const uint32_t clearAttachmentIndex =
3296                     contextVk->getFeatures().preferDynamicRendering.enabled
3297                         ? colorIndexVk.get()
3298                         : static_cast<uint32_t>(colorIndexGL);
3299 
3300                 attachments.emplace_back(VkClearAttachment{
3301                     VK_IMAGE_ASPECT_COLOR_BIT, clearAttachmentIndex, (*clears)[colorIndexGL]});
3302                 clears->reset(colorIndexGL);
3303                 ++contextVk->getPerfCounters().colorClearAttachments;
3304 
3305                 renderPassCommands->onColorAccess(colorIndexVk, vk::ResourceAccess::ReadWrite);
3306             }
3307             else
3308             {
3309                 // Skip this attachment, so we can use a renderpass loadOp to clear it instead.
3310                 // Note that if loadOp=Clear was already used for this color attachment, it will be
3311                 // overriden by the new clear, which is valid because the attachment wasn't used in
3312                 // between.
3313             }
3314         }
3315         ++colorIndexVk;
3316     }
3317 
3318     // Add depth and stencil to list of attachments as needed.
3319     VkImageAspectFlags dsAspectFlags  = 0;
3320     VkClearValue dsClearValue         = {};
3321     dsClearValue.depthStencil.depth   = clears->getDepthValue();
3322     dsClearValue.depthStencil.stencil = clears->getStencilValue();
3323     if (clears->testDepth() &&
3324         (renderPassCommands->hasAnyDepthAccess() ||
3325          renderPassCommands->getRenderPassDesc().hasDepthUnresolveAttachment() ||
3326          !optimizeWithLoadOp))
3327     {
3328         dsAspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
3329         // Explicitly mark a depth write because we are clearing the depth buffer.
3330         renderPassCommands->onDepthAccess(vk::ResourceAccess::ReadWrite);
3331         clears->reset(vk::kUnpackedDepthIndex);
3332         ++contextVk->getPerfCounters().depthClearAttachments;
3333     }
3334 
3335     if (clears->testStencil() &&
3336         (renderPassCommands->hasAnyStencilAccess() ||
3337          renderPassCommands->getRenderPassDesc().hasStencilUnresolveAttachment() ||
3338          !optimizeWithLoadOp))
3339     {
3340         dsAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
3341         // Explicitly mark a stencil write because we are clearing the stencil buffer.
3342         renderPassCommands->onStencilAccess(vk::ResourceAccess::ReadWrite);
3343         clears->reset(vk::kUnpackedStencilIndex);
3344         ++contextVk->getPerfCounters().stencilClearAttachments;
3345     }
3346 
3347     if (dsAspectFlags != 0)
3348     {
3349         attachments.emplace_back(VkClearAttachment{dsAspectFlags, 0, dsClearValue});
3350 
3351         // Because we may have changed the depth/stencil access mode, update read only depth/stencil
3352         // mode.
3353         renderPassCommands->updateDepthStencilReadOnlyMode(
3354             contextVk->getDepthStencilAttachmentFlags(), dsAspectFlags);
3355     }
3356 
3357     if (attachments.empty())
3358     {
3359         // If called with the intent to definitely clear something with vkCmdClearAttachments, there
3360         // must have been something to clear!
3361         ASSERT(optimizeWithLoadOp);
3362         return;
3363     }
3364 
3365     const uint32_t layerCount = mState.isMultiview() ? 1 : mCurrentFramebufferDesc.getLayerCount();
3366 
3367     VkClearRect rect                                     = {};
3368     rect.rect.offset.x                                   = scissoredRenderArea.x;
3369     rect.rect.offset.y                                   = scissoredRenderArea.y;
3370     rect.rect.extent.width                               = scissoredRenderArea.width;
3371     rect.rect.extent.height                              = scissoredRenderArea.height;
3372     rect.layerCount                                      = layerCount;
3373     vk::RenderPassCommandBuffer *renderPassCommandBuffer = &renderPassCommands->getCommandBuffer();
3374 
3375     renderPassCommandBuffer->clearAttachments(static_cast<uint32_t>(attachments.size()),
3376                                               attachments.data(), 1, &rect);
3377     return;
3378 }
3379 
clearWithLoadOp(ContextVk * contextVk)3380 void FramebufferVk::clearWithLoadOp(ContextVk *contextVk)
3381 {
3382     vk::RenderPassCommandBufferHelper *renderPassCommands =
3383         &contextVk->getStartedRenderPassCommands();
3384 
3385     // Update the render pass loadOps to clear the attachments.
3386     vk::PackedAttachmentIndex colorIndexVk(0);
3387     for (size_t colorIndexGL : mState.getColorAttachmentsMask())
3388     {
3389         if (!mDeferredClears.test(colorIndexGL))
3390         {
3391             ++colorIndexVk;
3392             continue;
3393         }
3394 
3395         ASSERT(!renderPassCommands->hasAnyColorAccess(colorIndexVk));
3396 
3397         renderPassCommands->updateRenderPassColorClear(colorIndexVk, mDeferredClears[colorIndexGL]);
3398 
3399         mDeferredClears.reset(colorIndexGL);
3400 
3401         ++colorIndexVk;
3402     }
3403 
3404     VkClearValue dsClearValue         = {};
3405     dsClearValue.depthStencil.depth   = mDeferredClears.getDepthValue();
3406     dsClearValue.depthStencil.stencil = mDeferredClears.getStencilValue();
3407     VkImageAspectFlags dsAspects      = 0;
3408 
3409     if (mDeferredClears.testDepth())
3410     {
3411         ASSERT(!renderPassCommands->hasAnyDepthAccess());
3412         dsAspects |= VK_IMAGE_ASPECT_DEPTH_BIT;
3413         mDeferredClears.reset(vk::kUnpackedDepthIndex);
3414     }
3415 
3416     if (mDeferredClears.testStencil())
3417     {
3418         ASSERT(!renderPassCommands->hasAnyStencilAccess());
3419         dsAspects |= VK_IMAGE_ASPECT_STENCIL_BIT;
3420         mDeferredClears.reset(vk::kUnpackedStencilIndex);
3421     }
3422 
3423     if (dsAspects != 0)
3424     {
3425         renderPassCommands->updateRenderPassDepthStencilClear(dsAspects, dsClearValue);
3426 
3427         // The render pass can no longer be in read-only depth/stencil mode.
3428         renderPassCommands->updateDepthStencilReadOnlyMode(
3429             contextVk->getDepthStencilAttachmentFlags(), dsAspects);
3430     }
3431 }
3432 
getSamplePosition(const gl::Context * context,size_t index,GLfloat * xy) const3433 angle::Result FramebufferVk::getSamplePosition(const gl::Context *context,
3434                                                size_t index,
3435                                                GLfloat *xy) const
3436 {
3437     int sampleCount = getSamples();
3438     rx::GetSamplePosition(sampleCount, index, xy);
3439     return angle::Result::Continue;
3440 }
3441 
startNewRenderPass(ContextVk * contextVk,const gl::Rectangle & renderArea,vk::RenderPassCommandBuffer ** commandBufferOut,bool * renderPassDescChangedOut)3442 angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
3443                                                 const gl::Rectangle &renderArea,
3444                                                 vk::RenderPassCommandBuffer **commandBufferOut,
3445                                                 bool *renderPassDescChangedOut)
3446 {
3447     ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::NewRenderPass));
3448 
3449     // Initialize RenderPass info.
3450     vk::AttachmentOpsArray renderPassAttachmentOps;
3451     vk::PackedClearValuesArray packedClearValues;
3452     gl::DrawBufferMask previousUnresolveColorMask =
3453         mRenderPassDesc.getColorUnresolveAttachmentMask();
3454     const bool hasDeferredClears        = mDeferredClears.any();
3455     const bool previousUnresolveDepth   = mRenderPassDesc.hasDepthUnresolveAttachment();
3456     const bool previousUnresolveStencil = mRenderPassDesc.hasStencilUnresolveAttachment();
3457 
3458     // Make sure render pass and framebuffer are in agreement w.r.t unresolve attachments.
3459     ASSERT(mCurrentFramebufferDesc.getUnresolveAttachmentMask() ==
3460            MakeUnresolveAttachmentMask(mRenderPassDesc));
3461     // ... w.r.t sRGB write control.
3462     ASSERT(mCurrentFramebufferDesc.getWriteControlMode() ==
3463            mRenderPassDesc.getSRGBWriteControlMode());
3464     // ... w.r.t foveation.
3465     ASSERT(mCurrentFramebufferDesc.hasFragmentShadingRateAttachment() ==
3466            mRenderPassDesc.hasFragmentShadingAttachment());
3467 
3468     // Color attachments.
3469     const auto &colorRenderTargets = mRenderTargetCache.getColors();
3470     vk::PackedAttachmentIndex colorIndexVk(0);
3471     for (size_t colorIndexGL : mState.getColorAttachmentsMask())
3472     {
3473         RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
3474         ASSERT(colorRenderTarget);
3475 
3476         // Color render targets are never entirely transient.  Only depth/stencil
3477         // multisampled-render-to-texture textures can be so.
3478         ASSERT(!colorRenderTarget->isEntirelyTransient());
3479         const vk::RenderPassStoreOp storeOp = colorRenderTarget->isImageTransient()
3480                                                   ? vk::RenderPassStoreOp::DontCare
3481                                                   : vk::RenderPassStoreOp::Store;
3482 
3483         if (mDeferredClears.test(colorIndexGL))
3484         {
3485             renderPassAttachmentOps.setOps(colorIndexVk, vk::RenderPassLoadOp::Clear, storeOp);
3486             packedClearValues.storeColor(colorIndexVk, mDeferredClears[colorIndexGL]);
3487             mDeferredClears.reset(colorIndexGL);
3488         }
3489         else
3490         {
3491             const vk::RenderPassLoadOp loadOp = colorRenderTarget->hasDefinedContent()
3492                                                     ? vk::RenderPassLoadOp::Load
3493                                                     : vk::RenderPassLoadOp::DontCare;
3494 
3495             renderPassAttachmentOps.setOps(colorIndexVk, loadOp, storeOp);
3496             packedClearValues.storeColor(colorIndexVk, kUninitializedClearValue);
3497         }
3498         renderPassAttachmentOps.setStencilOps(colorIndexVk, vk::RenderPassLoadOp::DontCare,
3499                                               vk::RenderPassStoreOp::DontCare);
3500 
3501         // If there's a resolve attachment, and loadOp needs to be LOAD, the multisampled attachment
3502         // needs to take its value from the resolve attachment.  In this case, an initial subpass is
3503         // added for this very purpose which uses the resolve attachment as input attachment.  As a
3504         // result, loadOp of the multisampled attachment can remain DONT_CARE.
3505         //
3506         // Note that this only needs to be done if the multisampled image and the resolve attachment
3507         // come from the same source.  isImageTransient() indicates whether this should happen.
3508         if (colorRenderTarget->hasResolveAttachment() && colorRenderTarget->isImageTransient())
3509         {
3510             if (renderPassAttachmentOps[colorIndexVk].loadOp == VK_ATTACHMENT_LOAD_OP_LOAD)
3511             {
3512                 renderPassAttachmentOps[colorIndexVk].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
3513 
3514                 // Update the render pass desc to specify that this attachment should be unresolved.
3515                 mRenderPassDesc.packColorUnresolveAttachment(colorIndexGL);
3516             }
3517             else
3518             {
3519                 mRenderPassDesc.removeColorUnresolveAttachment(colorIndexGL);
3520             }
3521         }
3522         else
3523         {
3524             ASSERT(!mRenderPassDesc.getColorUnresolveAttachmentMask().test(colorIndexGL));
3525         }
3526 
3527         ++colorIndexVk;
3528     }
3529 
3530     // Depth/stencil attachment.
3531     vk::PackedAttachmentIndex depthStencilAttachmentIndex = vk::kAttachmentIndexInvalid;
3532     RenderTargetVk *depthStencilRenderTarget              = getDepthStencilRenderTarget();
3533     if (depthStencilRenderTarget)
3534     {
3535         // depth stencil attachment always immediately follows color attachment
3536         depthStencilAttachmentIndex = colorIndexVk;
3537 
3538         vk::RenderPassLoadOp depthLoadOp     = vk::RenderPassLoadOp::Load;
3539         vk::RenderPassLoadOp stencilLoadOp   = vk::RenderPassLoadOp::Load;
3540         vk::RenderPassStoreOp depthStoreOp   = vk::RenderPassStoreOp::Store;
3541         vk::RenderPassStoreOp stencilStoreOp = vk::RenderPassStoreOp::Store;
3542 
3543         // If the image data was previously discarded (with no update in between), don't attempt to
3544         // load the image.  Additionally, if the multisampled image data is transient and there is
3545         // no resolve attachment, there's no data to load.  The latter is the case with
3546         // depth/stencil texture attachments per GL_EXT_multisampled_render_to_texture2.
3547         if (!depthStencilRenderTarget->hasDefinedContent() ||
3548             depthStencilRenderTarget->isEntirelyTransient())
3549         {
3550             depthLoadOp = vk::RenderPassLoadOp::DontCare;
3551         }
3552         if (!depthStencilRenderTarget->hasDefinedStencilContent() ||
3553             depthStencilRenderTarget->isEntirelyTransient())
3554         {
3555             stencilLoadOp = vk::RenderPassLoadOp::DontCare;
3556         }
3557 
3558         // If depth/stencil image is transient, no need to store its data at the end of the render
3559         // pass.
3560         if (depthStencilRenderTarget->isImageTransient())
3561         {
3562             depthStoreOp   = vk::RenderPassStoreOp::DontCare;
3563             stencilStoreOp = vk::RenderPassStoreOp::DontCare;
3564         }
3565 
3566         if (mDeferredClears.testDepth() || mDeferredClears.testStencil())
3567         {
3568             VkClearValue clearValue = {};
3569 
3570             if (mDeferredClears.testDepth())
3571             {
3572                 depthLoadOp                   = vk::RenderPassLoadOp::Clear;
3573                 clearValue.depthStencil.depth = mDeferredClears.getDepthValue();
3574                 mDeferredClears.reset(vk::kUnpackedDepthIndex);
3575             }
3576 
3577             if (mDeferredClears.testStencil())
3578             {
3579                 stencilLoadOp                   = vk::RenderPassLoadOp::Clear;
3580                 clearValue.depthStencil.stencil = mDeferredClears.getStencilValue();
3581                 mDeferredClears.reset(vk::kUnpackedStencilIndex);
3582             }
3583 
3584             packedClearValues.storeDepthStencil(depthStencilAttachmentIndex, clearValue);
3585         }
3586         else
3587         {
3588             packedClearValues.storeDepthStencil(depthStencilAttachmentIndex,
3589                                                 kUninitializedClearValue);
3590         }
3591 
3592         const angle::Format &format = depthStencilRenderTarget->getImageIntendedFormat();
3593         // If the format we picked has stencil but user did not ask for it due to hardware
3594         // limitations, use DONT_CARE for load/store. The same logic for depth follows.
3595         if (format.stencilBits == 0)
3596         {
3597             stencilLoadOp  = vk::RenderPassLoadOp::DontCare;
3598             stencilStoreOp = vk::RenderPassStoreOp::DontCare;
3599         }
3600         if (format.depthBits == 0)
3601         {
3602             depthLoadOp  = vk::RenderPassLoadOp::DontCare;
3603             depthStoreOp = vk::RenderPassStoreOp::DontCare;
3604         }
3605 
3606         // Similar to color attachments, if there's a resolve attachment and the multisampled image
3607         // is transient, depth/stencil data need to be unresolved in an initial subpass.
3608         if (depthStencilRenderTarget->hasResolveAttachment() &&
3609             depthStencilRenderTarget->isImageTransient())
3610         {
3611             const bool unresolveDepth   = depthLoadOp == vk::RenderPassLoadOp::Load;
3612             const bool unresolveStencil = stencilLoadOp == vk::RenderPassLoadOp::Load;
3613 
3614             if (unresolveDepth)
3615             {
3616                 depthLoadOp = vk::RenderPassLoadOp::DontCare;
3617             }
3618 
3619             if (unresolveStencil)
3620             {
3621                 stencilLoadOp = vk::RenderPassLoadOp::DontCare;
3622 
3623                 // If VK_EXT_shader_stencil_export is not supported, stencil unresolve is done
3624                 // through a method that requires stencil to have been cleared.
3625                 if (!contextVk->getFeatures().supportsShaderStencilExport.enabled)
3626                 {
3627                     stencilLoadOp = vk::RenderPassLoadOp::Clear;
3628 
3629                     VkClearValue clearValue = packedClearValues[depthStencilAttachmentIndex];
3630                     clearValue.depthStencil.stencil = 0;
3631                     packedClearValues.storeDepthStencil(depthStencilAttachmentIndex, clearValue);
3632                 }
3633             }
3634 
3635             if (unresolveDepth || unresolveStencil)
3636             {
3637                 if (unresolveDepth)
3638                 {
3639                     mRenderPassDesc.packDepthUnresolveAttachment();
3640                 }
3641                 if (unresolveStencil)
3642                 {
3643                     mRenderPassDesc.packStencilUnresolveAttachment();
3644                 }
3645             }
3646             else
3647             {
3648                 mRenderPassDesc.removeDepthStencilUnresolveAttachment();
3649             }
3650         }
3651 
3652         renderPassAttachmentOps.setOps(depthStencilAttachmentIndex, depthLoadOp, depthStoreOp);
3653         renderPassAttachmentOps.setStencilOps(depthStencilAttachmentIndex, stencilLoadOp,
3654                                               stencilStoreOp);
3655     }
3656 
3657     // If render pass description is changed, the previous render pass desc is no longer compatible.
3658     // Tell the context so that the graphics pipelines can be recreated.
3659     //
3660     // Note that render passes are compatible only if the differences are in loadOp/storeOp values,
3661     // or the existence of resolve attachments in single subpass render passes.  The modification
3662     // here can add/remove a subpass, or modify its input attachments.
3663     gl::DrawBufferMask unresolveColorMask = mRenderPassDesc.getColorUnresolveAttachmentMask();
3664     const bool unresolveDepth             = mRenderPassDesc.hasDepthUnresolveAttachment();
3665     const bool unresolveStencil           = mRenderPassDesc.hasStencilUnresolveAttachment();
3666     const bool unresolveChanged           = previousUnresolveColorMask != unresolveColorMask ||
3667                                   previousUnresolveDepth != unresolveDepth ||
3668                                   previousUnresolveStencil != unresolveStencil;
3669     if (unresolveChanged)
3670     {
3671         // Make sure framebuffer is recreated.
3672         releaseCurrentFramebuffer(contextVk);
3673 
3674         mCurrentFramebufferDesc.updateUnresolveMask(MakeUnresolveAttachmentMask(mRenderPassDesc));
3675     }
3676 
3677     vk::RenderPassFramebuffer framebuffer = {};
3678     ANGLE_TRY(getFramebuffer(contextVk, &framebuffer));
3679 
3680     // If deferred clears were used in the render pass, the render area must cover the whole
3681     // framebuffer.
3682     ASSERT(!hasDeferredClears || renderArea == getRotatedCompleteRenderArea(contextVk));
3683 
3684     ANGLE_TRY(contextVk->beginNewRenderPass(
3685         std::move(framebuffer), renderArea, mRenderPassDesc, renderPassAttachmentOps, colorIndexVk,
3686         depthStencilAttachmentIndex, packedClearValues, commandBufferOut));
3687     mLastRenderPassQueueSerial = contextVk->getStartedRenderPassCommands().getQueueSerial();
3688 
3689     // Add the images to the renderpass tracking list (through onColorDraw).
3690     vk::PackedAttachmentIndex colorAttachmentIndex(0);
3691     for (size_t colorIndexGL : mState.getColorAttachmentsMask())
3692     {
3693         RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
3694         colorRenderTarget->onColorDraw(contextVk, mCurrentFramebufferDesc.getLayerCount(),
3695                                        colorAttachmentIndex);
3696         ++colorAttachmentIndex;
3697     }
3698 
3699     if (depthStencilRenderTarget)
3700     {
3701         // This must be called after hasDefined*Content() since it will set content to valid.  If
3702         // the attachment ends up not used in the render pass, contents will be marked undefined at
3703         // endRenderPass.  The actual layout determination is also deferred until the same time.
3704         depthStencilRenderTarget->onDepthStencilDraw(contextVk,
3705                                                      mCurrentFramebufferDesc.getLayerCount());
3706     }
3707 
3708     const bool anyUnresolve = unresolveColorMask.any() || unresolveDepth || unresolveStencil;
3709     if (anyUnresolve)
3710     {
3711         // Unresolve attachments if any.
3712         UtilsVk::UnresolveParameters params;
3713         params.unresolveColorMask = unresolveColorMask;
3714         params.unresolveDepth     = unresolveDepth;
3715         params.unresolveStencil   = unresolveStencil;
3716 
3717         ANGLE_TRY(contextVk->getUtils().unresolve(contextVk, this, params));
3718 
3719         // The unresolve subpass has only one draw call.
3720         ANGLE_TRY(contextVk->startNextSubpass());
3721     }
3722 
3723     if (unresolveChanged || anyUnresolve)
3724     {
3725         contextVk->onDrawFramebufferRenderPassDescChange(this, renderPassDescChangedOut);
3726     }
3727 
3728     // Add fragment shading rate to the tracking list.
3729     if (mCurrentFramebufferDesc.hasFragmentShadingRateAttachment())
3730     {
3731         contextVk->onFragmentShadingRateRead(&mFragmentShadingRateImage);
3732     }
3733 
3734     return angle::Result::Continue;
3735 }
3736 
getRenderArea(ContextVk * contextVk) const3737 gl::Rectangle FramebufferVk::getRenderArea(ContextVk *contextVk) const
3738 {
3739     if (hasDeferredClears())
3740     {
3741         return getRotatedCompleteRenderArea(contextVk);
3742     }
3743     else
3744     {
3745         return getRotatedScissoredRenderArea(contextVk);
3746     }
3747 }
3748 
updateActiveColorMasks(size_t colorIndexGL,bool r,bool g,bool b,bool a)3749 void FramebufferVk::updateActiveColorMasks(size_t colorIndexGL, bool r, bool g, bool b, bool a)
3750 {
3751     gl::BlendStateExt::ColorMaskStorage::SetValueIndexed(
3752         colorIndexGL, gl::BlendStateExt::PackColorMask(r, g, b, a),
3753         &mActiveColorComponentMasksForClear);
3754 }
3755 
getEmulatedAlphaAttachmentMask() const3756 const gl::DrawBufferMask &FramebufferVk::getEmulatedAlphaAttachmentMask() const
3757 {
3758     return mEmulatedAlphaAttachmentMask;
3759 }
3760 
readPixelsImpl(ContextVk * contextVk,const gl::Rectangle & area,const PackPixelsParams & packPixelsParams,VkImageAspectFlagBits copyAspectFlags,RenderTargetVk * renderTarget,void * pixels)3761 angle::Result FramebufferVk::readPixelsImpl(ContextVk *contextVk,
3762                                             const gl::Rectangle &area,
3763                                             const PackPixelsParams &packPixelsParams,
3764                                             VkImageAspectFlagBits copyAspectFlags,
3765                                             RenderTargetVk *renderTarget,
3766                                             void *pixels)
3767 {
3768     ANGLE_TRACE_EVENT0("gpu.angle", "FramebufferVk::readPixelsImpl");
3769     gl::LevelIndex levelGL = renderTarget->getLevelIndex();
3770     uint32_t layer         = renderTarget->getLayerIndex();
3771     return renderTarget->getImageForCopy().readPixels(contextVk, area, packPixelsParams,
3772                                                       copyAspectFlags, levelGL, layer, pixels);
3773 }
3774 
getReadImageExtents() const3775 gl::Extents FramebufferVk::getReadImageExtents() const
3776 {
3777     RenderTargetVk *readRenderTarget = mRenderTargetCache.getColorRead(mState);
3778     return readRenderTarget->getExtents();
3779 }
3780 
3781 // Return the framebuffer's rotated render area.  This is a gl::Rectangle that is based on the
3782 // dimensions of the framebuffer, IS ROTATED for the draw FBO, and IS NOT y-flipped
3783 //
3784 // Note: Since the rectangle is not scissored (i.e. x and y are guaranteed to be zero), only the
3785 // width and height must be swapped if the rotation is 90 or 270 degrees.
getRotatedCompleteRenderArea(ContextVk * contextVk) const3786 gl::Rectangle FramebufferVk::getRotatedCompleteRenderArea(ContextVk *contextVk) const
3787 {
3788     gl::Rectangle renderArea = getNonRotatedCompleteRenderArea();
3789     if (contextVk->isRotatedAspectRatioForDrawFBO())
3790     {
3791         // The surface is rotated 90/270 degrees.  This changes the aspect ratio of the surface.
3792         std::swap(renderArea.width, renderArea.height);
3793     }
3794     return renderArea;
3795 }
3796 
3797 // Return the framebuffer's scissored and rotated render area.  This is a gl::Rectangle that is
3798 // based on the dimensions of the framebuffer, is clipped to the scissor, IS ROTATED and IS
3799 // Y-FLIPPED for the draw FBO.
3800 //
3801 // Note: Since the rectangle is scissored, it must be fully rotated, and not just have the width
3802 // and height swapped.
getRotatedScissoredRenderArea(ContextVk * contextVk) const3803 gl::Rectangle FramebufferVk::getRotatedScissoredRenderArea(ContextVk *contextVk) const
3804 {
3805     const gl::Rectangle renderArea = getNonRotatedCompleteRenderArea();
3806     bool invertViewport            = contextVk->isViewportFlipEnabledForDrawFBO();
3807     gl::Rectangle scissoredArea    = ClipRectToScissor(contextVk->getState(), renderArea, false);
3808     gl::Rectangle rotatedScissoredArea;
3809     RotateRectangle(contextVk->getRotationDrawFramebuffer(), invertViewport, renderArea.width,
3810                     renderArea.height, scissoredArea, &rotatedScissoredArea);
3811     return rotatedScissoredArea;
3812 }
3813 
getSamples() const3814 GLint FramebufferVk::getSamples() const
3815 {
3816     const gl::FramebufferAttachment *lastAttachment = nullptr;
3817 
3818     for (size_t colorIndexGL : mState.getEnabledDrawBuffers() & mState.getColorAttachmentsMask())
3819     {
3820         const gl::FramebufferAttachment *color = mState.getColorAttachment(colorIndexGL);
3821         ASSERT(color);
3822 
3823         if (color->isRenderToTexture())
3824         {
3825             return color->getSamples();
3826         }
3827 
3828         lastAttachment = color;
3829     }
3830     const gl::FramebufferAttachment *depthStencil = mState.getDepthOrStencilAttachment();
3831     if (depthStencil)
3832     {
3833         if (depthStencil->isRenderToTexture())
3834         {
3835             return depthStencil->getSamples();
3836         }
3837         lastAttachment = depthStencil;
3838     }
3839 
3840     // If none of the attachments are multisampled-render-to-texture, take the sample count from the
3841     // last attachment (any would have worked, as they would all have the same sample count).
3842     return std::max(lastAttachment ? lastAttachment->getSamples() : 1, 1);
3843 }
3844 
flushDepthStencilDeferredClear(ContextVk * contextVk,VkImageAspectFlagBits aspect)3845 angle::Result FramebufferVk::flushDepthStencilDeferredClear(ContextVk *contextVk,
3846                                                             VkImageAspectFlagBits aspect)
3847 {
3848     const bool isDepth = aspect == VK_IMAGE_ASPECT_DEPTH_BIT;
3849 
3850     // Pick out the deferred clear for the given aspect, and issue it ahead of the render pass.
3851     // This is used when switching this aspect to read-only mode, in which case the clear operation
3852     // for the aspect cannot be done as part of the render pass loadOp.
3853     ASSERT(!isDepth || hasDeferredDepthClear());
3854     ASSERT(isDepth || hasDeferredStencilClear());
3855     ASSERT(mState.getDepthOrStencilAttachment() != nullptr);
3856 
3857     RenderTargetVk *renderTarget = getDepthStencilRenderTarget();
3858     vk::ImageHelper &image       = renderTarget->getImageForCopy();
3859 
3860     // Depth/stencil attachments cannot be 3D.
3861     ASSERT(!renderTarget->is3DImage());
3862 
3863     vk::CommandBufferAccess access;
3864     access.onImageTransferWrite(renderTarget->getLevelIndex(), 1, renderTarget->getLayerIndex(), 1,
3865                                 image.getAspectFlags(), &image);
3866     vk::OutsideRenderPassCommandBuffer *commandBuffer;
3867     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
3868 
3869     VkImageSubresourceRange range = {};
3870     range.aspectMask              = aspect;
3871     range.baseMipLevel            = image.toVkLevel(renderTarget->getLevelIndex()).get();
3872     range.levelCount              = 1;
3873     range.baseArrayLayer          = renderTarget->getLayerIndex();
3874     range.layerCount              = 1;
3875 
3876     VkClearDepthStencilValue clearValue = {};
3877 
3878     if (isDepth)
3879     {
3880         clearValue.depth = mDeferredClears.getDepthValue();
3881         mDeferredClears.reset(vk::kUnpackedDepthIndex);
3882     }
3883     else
3884     {
3885         clearValue.stencil = mDeferredClears.getStencilValue();
3886         mDeferredClears.reset(vk::kUnpackedStencilIndex);
3887     }
3888 
3889     commandBuffer->clearDepthStencilImage(image.getImage(), image.getCurrentLayout(), clearValue, 1,
3890                                           &range);
3891     return angle::Result::Continue;
3892 }
3893 
flushDeferredClears(ContextVk * contextVk)3894 angle::Result FramebufferVk::flushDeferredClears(ContextVk *contextVk)
3895 {
3896     if (mDeferredClears.empty())
3897     {
3898         return angle::Result::Continue;
3899     }
3900 
3901     return contextVk->startRenderPass(getRotatedCompleteRenderArea(contextVk), nullptr, nullptr);
3902 }
3903 
switchToColorFramebufferFetchMode(ContextVk * contextVk,bool hasColorFramebufferFetch)3904 void FramebufferVk::switchToColorFramebufferFetchMode(ContextVk *contextVk,
3905                                                       bool hasColorFramebufferFetch)
3906 {
3907     // Framebuffer fetch use by the shader does not affect the framebuffer object in any way with
3908     // dynamic rendering.
3909     ASSERT(!contextVk->getFeatures().preferDynamicRendering.enabled);
3910 
3911     // The switch happens once, and is permanent.
3912     if (mCurrentFramebufferDesc.hasColorFramebufferFetch() == hasColorFramebufferFetch)
3913     {
3914         return;
3915     }
3916 
3917     mCurrentFramebufferDesc.setColorFramebufferFetchMode(hasColorFramebufferFetch);
3918 
3919     mRenderPassDesc.setFramebufferFetchMode(hasColorFramebufferFetch
3920                                                 ? vk::FramebufferFetchMode::Color
3921                                                 : vk::FramebufferFetchMode::None);
3922     contextVk->onDrawFramebufferRenderPassDescChange(this, nullptr);
3923 
3924     // Make sure framebuffer is recreated.
3925     releaseCurrentFramebuffer(contextVk);
3926 
3927     // Clear the framebuffer cache, as none of the old framebuffers are usable.
3928     if (contextVk->getFeatures().permanentlySwitchToFramebufferFetchMode.enabled)
3929     {
3930         ASSERT(hasColorFramebufferFetch);
3931         releaseCurrentFramebuffer(contextVk);
3932     }
3933 }
3934 
updateLegacyDither(ContextVk * contextVk)3935 bool FramebufferVk::updateLegacyDither(ContextVk *contextVk)
3936 {
3937     if (contextVk->getFeatures().supportsLegacyDithering.enabled &&
3938         mRenderPassDesc.isLegacyDitherEnabled() != contextVk->isDitherEnabled())
3939     {
3940         mRenderPassDesc.setLegacyDither(contextVk->isDitherEnabled());
3941         return true;
3942     }
3943 
3944     return false;
3945 }
3946 }  // namespace rx
3947