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