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