Hash :
e3b3dd68
Author :
Date :
2024-11-14T23:00:52
Vulkan: Optimize color clears vs read-only depth/stencil switch When switching to read-only depth/stencil mode, if the aspect that intends to be in read-only mode has a deferred clear, the clear is flushed separately beforehands (as that would be a write operation). Prior to this change, _all_ deferred clears were flushed for simplicity. In this change, only the aspect that is switching modes is cleared, leaving the other aspects free to be optimized as loadOp of the following render pass. Bug: angleproject:378058737 Change-Id: Iba4371590bee99f5022575c09b0d32231562488c Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/6019829 Reviewed-by: Amirali Abdolrashidi <abdolrashidi@google.com> Reviewed-by: Charlie Lao <cclao@google.com> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
//
// Copyright 2016 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// FramebufferVk.h:
// Defines the class interface for FramebufferVk, implementing FramebufferImpl.
//
#ifndef LIBANGLE_RENDERER_VULKAN_FRAMEBUFFERVK_H_
#define LIBANGLE_RENDERER_VULKAN_FRAMEBUFFERVK_H_
#include "libANGLE/angletypes.h"
#include "libANGLE/renderer/FramebufferImpl.h"
#include "libANGLE/renderer/RenderTargetCache.h"
#include "libANGLE/renderer/vulkan/BufferVk.h"
#include "libANGLE/renderer/vulkan/SurfaceVk.h"
#include "libANGLE/renderer/vulkan/UtilsVk.h"
#include "libANGLE/renderer/vulkan/vk_cache_utils.h"
#include "libANGLE/renderer/vulkan/vk_helpers.h"
#include "libANGLE/renderer/vulkan/vk_resource.h"
namespace rx
{
class RenderTargetVk;
class WindowSurfaceVk;
class FramebufferVk : public FramebufferImpl
{
public:
FramebufferVk(vk::Renderer *renderer, const gl::FramebufferState &state);
~FramebufferVk() override;
void destroy(const gl::Context *context) override;
angle::Result discard(const gl::Context *context,
size_t count,
const GLenum *attachments) override;
angle::Result invalidate(const gl::Context *context,
size_t count,
const GLenum *attachments) override;
angle::Result invalidateSub(const gl::Context *context,
size_t count,
const GLenum *attachments,
const gl::Rectangle &area) override;
angle::Result clear(const gl::Context *context, GLbitfield mask) override;
angle::Result clearBufferfv(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
const GLfloat *values) override;
angle::Result clearBufferuiv(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
const GLuint *values) override;
angle::Result clearBufferiv(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
const GLint *values) override;
angle::Result clearBufferfi(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
GLfloat depth,
GLint stencil) override;
const gl::InternalFormat &getImplementationColorReadFormat(
const gl::Context *context) const override;
angle::Result readPixels(const gl::Context *context,
const gl::Rectangle &area,
GLenum format,
GLenum type,
const gl::PixelPackState &pack,
gl::Buffer *packBuffer,
void *pixels) override;
angle::Result blit(const gl::Context *context,
const gl::Rectangle &sourceArea,
const gl::Rectangle &destArea,
GLbitfield mask,
GLenum filter) override;
gl::FramebufferStatus checkStatus(const gl::Context *context) const override;
angle::Result syncState(const gl::Context *context,
GLenum binding,
const gl::Framebuffer::DirtyBits &dirtyBits,
gl::Command command) override;
angle::Result getSamplePosition(const gl::Context *context,
size_t index,
GLfloat *xy) const override;
RenderTargetVk *getDepthStencilRenderTarget() const;
// Internal helper function for readPixels operations.
angle::Result readPixelsImpl(ContextVk *contextVk,
const gl::Rectangle &area,
const PackPixelsParams &packPixelsParams,
VkImageAspectFlagBits copyAspectFlags,
RenderTargetVk *renderTarget,
void *pixels);
gl::Extents getReadImageExtents() const;
gl::Rectangle getNonRotatedCompleteRenderArea() const;
gl::Rectangle getRotatedCompleteRenderArea(ContextVk *contextVk) const;
gl::Rectangle getRotatedScissoredRenderArea(ContextVk *contextVk) const;
// Returns render area with deferred clears in consideration. When deferred clear is used
// in the render pass, the render area must cover the whole framebuffer.
gl::Rectangle getRenderArea(ContextVk *contextVk) const;
uint32_t getLayerCount() const { return mCurrentFramebufferDesc.getLayerCount(); }
const gl::DrawBufferMask &getEmulatedAlphaAttachmentMask() const;
RenderTargetVk *getColorDrawRenderTarget(size_t colorIndexGL) const;
RenderTargetVk *getColorReadRenderTarget() const;
angle::Result startNewRenderPass(ContextVk *contextVk,
const gl::Rectangle &renderArea,
vk::RenderPassCommandBuffer **commandBufferOut,
bool *renderPassDescChangedOut);
GLint getSamples() const;
const vk::RenderPassDesc &getRenderPassDesc() const { return mRenderPassDesc; }
angle::Result getFramebuffer(ContextVk *contextVk, vk::RenderPassFramebuffer *framebufferOut);
bool hasDeferredClears() const { return !mDeferredClears.empty(); }
bool hasDeferredDepthClear() const { return mDeferredClears.testDepth(); }
bool hasDeferredStencilClear() const { return mDeferredClears.testStencil(); }
angle::Result flushDepthStencilDeferredClear(ContextVk *contextVk,
VkImageAspectFlagBits aspect);
void switchToColorFramebufferFetchMode(ContextVk *contextVk, bool hasColorFramebufferFetch);
bool updateLegacyDither(ContextVk *contextVk);
void setBackbuffer(WindowSurfaceVk *backbuffer) { mBackbuffer = backbuffer; }
WindowSurfaceVk *getBackbuffer() const { return mBackbuffer; }
void releaseCurrentFramebuffer(ContextVk *contextVk);
const QueueSerial &getLastRenderPassQueueSerial() const { return mLastRenderPassQueueSerial; }
bool hasAnyExternalAttachments() const { return mIsExternalColorAttachments.any(); }
bool hasFrontBufferUsage() const
{
return (mAttachmentHasFrontBufferUsage & mState.getColorAttachmentsMask()).any();
}
bool isFoveationEnabled() { return mFoveationState.isFoveated(); }
private:
enum class ClearWithCommand
{
Always,
OptimizeWithLoadOp,
};
enum class RenderTargetImage
{
Attachment,
Resolve,
FragmentShadingRate,
};
struct RenderTargetInfo
{
RenderTargetInfo() : renderTarget(nullptr), renderTargetImage(RenderTargetImage::Attachment)
{}
RenderTargetInfo(RenderTargetVk *renderTarget, RenderTargetImage renderTargetImage)
: renderTarget(renderTarget), renderTargetImage(renderTargetImage)
{}
RenderTargetVk *renderTarget;
RenderTargetImage renderTargetImage;
};
// Returns the attachments to be used to create a framebuffer. The views returned in
// |unpackedAttachments| are not necessarily packed, but the render targets in
// |packedRenderTargetsInfoOut| are. In particular, the resolve attachment views need to stay
// sparse to be placed in |RenderPassFramebuffer|, but the calling function will have to pack
// them to match the render buffers before creating a framebuffer.
angle::Result getAttachmentsAndRenderTargets(
vk::Context *context,
vk::FramebufferAttachmentsVector<VkImageView> *unpackedAttachments,
vk::FramebufferAttachmentsVector<RenderTargetInfo> *packedRenderTargetsInfoOut);
angle::Result createNewFramebuffer(
ContextVk *contextVk,
uint32_t framebufferWidth,
const uint32_t framebufferHeight,
const uint32_t framebufferLayers,
const vk::FramebufferAttachmentsVector<VkImageView> &unpackedAttachments,
const vk::FramebufferAttachmentsVector<RenderTargetInfo> &renderTargetsInfo);
// The 'in' rectangles must be clipped to the scissor and FBO. The clipping is done in 'blit'.
angle::Result 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);
// Resolve color with subpass attachment
angle::Result resolveColorWithSubpass(ContextVk *contextVk,
const UtilsVk::BlitResolveParameters ¶ms);
// Resolve depth/stencil with subpass attachment
angle::Result resolveDepthStencilWithSubpass(ContextVk *contextVk,
const UtilsVk::BlitResolveParameters ¶ms,
VkImageAspectFlags aspects);
// Resolve color with vkCmdResolveImage
angle::Result resolveColorWithCommand(ContextVk *contextVk,
const UtilsVk::BlitResolveParameters ¶ms,
vk::ImageHelper *srcImage);
angle::Result clearImpl(const gl::Context *context,
gl::DrawBufferMask clearColorBuffers,
bool clearDepth,
bool clearStencil,
const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue);
void mergeClearsWithDeferredClears(
gl::DrawBufferMask clearColorBuffers,
bool clearDepth,
bool clearStencil,
const gl::DrawBuffersArray<VkClearColorValue> &clearColorValues,
const VkClearDepthStencilValue &clearDepthStencilValue);
angle::Result clearWithDraw(ContextVk *contextVk,
const gl::Rectangle &clearArea,
gl::DrawBufferMask clearColorBuffers,
bool clearDepth,
bool clearStencil,
gl::BlendStateExt::ColorMaskStorage::Type colorMasks,
uint8_t stencilMask,
const gl::DrawBuffersArray<VkClearColorValue> &clearColorValues,
const VkClearDepthStencilValue &clearDepthStencilValue);
void restageDeferredClears(ContextVk *contextVk);
void restageDeferredClearsForReadFramebuffer(ContextVk *contextVk);
void restageDeferredClearsImpl(ContextVk *contextVk);
angle::Result flushDeferredClears(ContextVk *contextVk);
void clearWithCommand(ContextVk *contextVk,
const gl::Rectangle &scissoredRenderArea,
ClearWithCommand behavior,
vk::ClearValuesArray *clears);
void clearWithLoadOp(ContextVk *contextVk);
void updateActiveColorMasks(size_t colorIndex, bool r, bool g, bool b, bool a);
void updateRenderPassDesc(ContextVk *contextVk);
angle::Result updateColorAttachment(const gl::Context *context, uint32_t colorIndex);
void updateColorAttachmentColorspace(gl::SrgbWriteControlMode srgbWriteControlMode);
angle::Result updateDepthStencilAttachment(const gl::Context *context);
void updateDepthStencilAttachmentSerial(ContextVk *contextVk);
angle::Result flushColorAttachmentUpdates(const gl::Context *context,
bool deferClears,
uint32_t colorIndex);
angle::Result flushDepthStencilAttachmentUpdates(const gl::Context *context, bool deferClears);
angle::Result invalidateImpl(ContextVk *contextVk,
size_t count,
const GLenum *attachments,
bool isSubInvalidate,
const gl::Rectangle &invalidateArea);
RenderTargetVk *getReadPixelsRenderTarget(GLenum format) const;
VkImageAspectFlagBits getReadPixelsAspectFlags(GLenum format) const;
VkClearValue getCorrectedColorClearValue(size_t colorIndexGL,
const VkClearColorValue &clearColor) const;
void updateLayerCount();
angle::Result ensureFragmentShadingRateImageAndViewInitialized(
ContextVk *contextVk,
const uint32_t fragmentShadingRateAttachmentWidth,
const uint32_t fragmentShadingRateAttachmentHeight);
angle::Result generateFragmentShadingRateWithCPU(
ContextVk *contextVk,
const uint32_t fragmentShadingRateWidth,
const uint32_t fragmentShadingRateHeight,
const uint32_t fragmentShadingRateBlockWidth,
const uint32_t fragmentShadingRateBlockHeight,
const uint32_t foveatedAttachmentWidth,
const uint32_t foveatedAttachmentHeight,
const std::vector<gl::FocalPoint> &activeFocalPoints);
angle::Result generateFragmentShadingRateWithCompute(
ContextVk *contextVk,
const uint32_t fragmentShadingRateWidth,
const uint32_t fragmentShadingRateHeight,
const uint32_t fragmentShadingRateBlockWidth,
const uint32_t fragmentShadingRateBlockHeight,
const uint32_t foveatedAttachmentWidth,
const uint32_t foveatedAttachmentHeight,
const std::vector<gl::FocalPoint> &activeFocalPoints);
angle::Result updateFragmentShadingRateAttachment(ContextVk *contextVk,
const gl::FoveationState &foveationState,
const gl::Extents &foveatedAttachmentSize);
angle::Result updateFoveationState(ContextVk *contextVk,
const gl::FoveationState &newFoveationState,
const gl::Extents &foveatedAttachmentSize);
void insertCache(ContextVk *contextVk,
const vk::FramebufferDesc &desc,
vk::FramebufferHelper &&newFramebuffer);
WindowSurfaceVk *mBackbuffer;
vk::RenderPassDesc mRenderPassDesc;
RenderTargetCache<RenderTargetVk> mRenderTargetCache;
// This variable is used to quickly compute if we need to do a masked clear. If a color
// channel is masked out, we check against the Framebuffer Attachments (RenderTargets) to see
// if the masked out channel is present in any of the attachments.
gl::BlendStateExt::ColorMaskStorage::Type mActiveColorComponentMasksForClear;
// When we draw to the framebuffer, and the real format has an alpha channel but the format of
// the framebuffer does not, we need to mask out the alpha channel. This DrawBufferMask will
// contain the mask to apply to the alpha channel when drawing.
gl::DrawBufferMask mEmulatedAlphaAttachmentMask;
// mCurrentFramebufferDesc is used to detect framebuffer changes using its serials. Therefore,
// it must be maintained even when using the imageless framebuffer extension.
vk::FramebufferDesc mCurrentFramebufferDesc;
// The framebuffer cache actually owns the Framebuffer object and manages its lifetime. We just
// store the current VkFramebuffer handle here that associated with mCurrentFramebufferDesc.
vk::Framebuffer mCurrentFramebuffer;
vk::ClearValuesArray mDeferredClears;
// Whether any of the color attachments are an external image such as dmabuf, AHB etc. In such
// cases, some optimizations are disabled such as deferred clears because the results need to be
// made externally available.
gl::DrawBufferMask mIsExternalColorAttachments;
gl::DrawBufferMask mAttachmentHasFrontBufferUsage;
bool mIsCurrentFramebufferCached;
bool mIsYUVResolve;
gl::FoveationState mFoveationState;
vk::ImageHelper mFragmentShadingRateImage;
vk::ImageViewHelper mFragmentShadingRateImageView;
// Serial of the render pass this framebuffer has opened, if any.
QueueSerial mLastRenderPassQueueSerial;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_FRAMEBUFFERVK_H_