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 // RenderTargetVk: 7 // Wrapper around a Vulkan renderable resource, using an ImageView. 8 // 9 10 #ifndef LIBANGLE_RENDERER_VULKAN_RENDERTARGETVK_H_ 11 #define LIBANGLE_RENDERER_VULKAN_RENDERTARGETVK_H_ 12 13 #include "common/vulkan/vk_headers.h" 14 #include "libANGLE/FramebufferAttachment.h" 15 #include "libANGLE/renderer/renderer_utils.h" 16 #include "libANGLE/renderer/vulkan/vk_helpers.h" 17 18 namespace rx 19 { 20 namespace vk 21 { 22 class FramebufferHelper; 23 class ImageHelper; 24 class ImageView; 25 class Resource; 26 class RenderPassDesc; 27 } // namespace vk 28 29 class ContextVk; 30 class TextureVk; 31 32 enum class RenderTargetTransience 33 { 34 // Regular render targets that load and store from the image. 35 Default, 36 // Multisampled-render-to-texture textures, where the implicit multisampled image is transient, 37 // but the resolved image is persistent. 38 MultisampledTransient, 39 // Renderable YUV textures, where the color attachment (if it exists at all) is transient, 40 // but the resolved image is persistent. 41 YuvResolveTransient, 42 // Multisampled-render-to-texture depth/stencil textures. 43 EntirelyTransient, 44 }; 45 46 // This is a very light-weight class that does not own to the resources it points to. 47 // It's meant only to copy across some information from a FramebufferAttachment to the 48 // business rendering logic. It stores Images and ImageViews by pointer for performance. 49 class RenderTargetVk final : public FramebufferAttachmentRenderTarget 50 { 51 public: 52 RenderTargetVk(); 53 ~RenderTargetVk() override; 54 55 // Used in std::vector initialization. 56 RenderTargetVk(RenderTargetVk &&other); 57 58 void init(vk::ImageHelper *image, 59 vk::ImageViewHelper *imageViews, 60 vk::ImageHelper *resolveImage, 61 vk::ImageViewHelper *resolveImageViews, 62 UniqueSerial imageSiblingSerial, 63 gl::LevelIndex levelIndexGL, 64 uint32_t layerIndex, 65 uint32_t layerCount, 66 RenderTargetTransience transience); 67 68 vk::ImageOrBufferViewSubresourceSerial getDrawSubresourceSerial() const; 69 vk::ImageOrBufferViewSubresourceSerial getResolveSubresourceSerial() const; 70 71 // Note: RenderTargets should be called in order, with the depth/stencil onRender last. 72 void onColorDraw(ContextVk *contextVk, 73 uint32_t framebufferLayerCount, 74 vk::PackedAttachmentIndex index); 75 void onColorResolve(ContextVk *contextVk, 76 uint32_t framebufferLayerCount, 77 size_t readColorIndexGL, 78 const vk::ImageView &view); 79 void onDepthStencilDraw(ContextVk *contextVk, uint32_t framebufferLayerCount); 80 void onDepthStencilResolve(ContextVk *contextVk, 81 uint32_t framebufferLayerCount, 82 VkImageAspectFlags aspects, 83 const vk::ImageView &view); 84 85 vk::ImageHelper &getImageForRenderPass(); 86 const vk::ImageHelper &getImageForRenderPass() const; 87 88 vk::ImageHelper &getResolveImageForRenderPass(); 89 const vk::ImageHelper &getResolveImageForRenderPass() const; 90 91 vk::ImageHelper &getImageForCopy() const; 92 vk::ImageHelper &getImageForWrite() const; 93 94 // For cube maps we use single-level single-layer 2D array views. 95 angle::Result getImageView(vk::ErrorContext *context, const vk::ImageView **imageViewOut) const; 96 angle::Result getImageViewWithColorspace(vk::ErrorContext *context, 97 gl::SrgbWriteControlMode srgbWriteContrlMode, 98 const vk::ImageView **imageViewOut) const; 99 angle::Result getResolveImageView(vk::ErrorContext *context, 100 const vk::ImageView **imageViewOut) const; 101 angle::Result getDepthOrStencilImageView(vk::ErrorContext *context, 102 VkImageAspectFlagBits aspect, 103 const vk::ImageView **imageViewOut) const; 104 angle::Result getDepthOrStencilImageViewForCopy(vk::ErrorContext *context, 105 VkImageAspectFlagBits aspect, 106 const vk::ImageView **imageViewOut) const; 107 angle::Result getResolveDepthOrStencilImageView(vk::ErrorContext *context, 108 VkImageAspectFlagBits aspect, 109 const vk::ImageView **imageViewOut) const; 110 111 // For 3D textures, the 2D view created for render target is invalid to read from. The 112 // following will return a view to the whole image (for all types, including 3D and 2DArray). 113 angle::Result getCopyImageView(vk::ErrorContext *context, 114 const vk::ImageView **imageViewOut) const; 115 116 angle::FormatID getImageActualFormatID() const; 117 const angle::Format &getImageActualFormat() const; 118 angle::FormatID getImageIntendedFormatID() const; 119 const angle::Format &getImageIntendedFormat() const; 120 121 gl::Extents getExtents() const; 122 gl::Extents getRotatedExtents() const; getLevelIndex()123 gl::LevelIndex getLevelIndex() const { return mLevelIndexGL; } 124 gl::LevelIndex getLevelIndexForImage(const vk::ImageHelper &image) const; getLayerIndex()125 uint32_t getLayerIndex() const { return mLayerIndex; } getLayerCount()126 uint32_t getLayerCount() const { return mLayerCount; } is3DImage()127 bool is3DImage() const { return getOwnerOfData()->getType() == VK_IMAGE_TYPE_3D; } 128 129 gl::ImageIndex getImageIndexForClear(uint32_t layerCount) const; 130 131 // Special mutator for Surface RenderTargets. Allows the Framebuffer to keep a single 132 // RenderTargetVk pointer. 133 void updateSwapchainImage(vk::ImageHelper *image, 134 vk::ImageViewHelper *imageViews, 135 vk::ImageHelper *resolveImage, 136 vk::ImageViewHelper *resolveImageViews); 137 138 angle::Result flushStagedUpdates(ContextVk *contextVk, 139 vk::ClearValuesArray *deferredClears, 140 uint32_t deferredClearIndex, 141 uint32_t framebufferLayerCount); 142 143 bool hasDefinedContent() const; 144 bool hasDefinedStencilContent() const; 145 // Mark content as undefined so that certain optimizations are possible such as using DONT_CARE 146 // as loadOp of the render target in the next renderpass. If |preferToKeepContentsDefinedOut| 147 // is set to true, it's preferred to ignore the invalidation due to image format and device 148 // architecture properties. 149 void invalidateEntireContent(ContextVk *contextVk, bool *preferToKeepContentsDefinedOut); 150 void invalidateEntireStencilContent(ContextVk *contextVk, bool *preferToKeepContentsDefinedOut); 151 152 // See the description of mTransience for details of how the following two can interact. hasResolveAttachment()153 bool hasResolveAttachment() const { return mResolveImage != nullptr && !isEntirelyTransient(); } isImageTransient()154 bool isImageTransient() const { return mTransience != RenderTargetTransience::Default; } isEntirelyTransient()155 bool isEntirelyTransient() const 156 { 157 return mTransience == RenderTargetTransience::EntirelyTransient; 158 } isYuvResolve()159 bool isYuvResolve() const 160 { 161 return mResolveImage != nullptr ? mResolveImage->isYuvResolve() : false; 162 } 163 onNewFramebuffer(const vk::SharedFramebufferCacheKey & sharedFramebufferCacheKey)164 void onNewFramebuffer(const vk::SharedFramebufferCacheKey &sharedFramebufferCacheKey) 165 { 166 mFramebufferCacheManager.addKey(sharedFramebufferCacheKey); 167 } releaseFramebuffers(ContextVk * contextVk)168 void releaseFramebuffers(ContextVk *contextVk) 169 { 170 mFramebufferCacheManager.releaseKeys(contextVk); 171 } 172 // Resets all members to the initial state without releasing framebuffers since Window Surface 173 // framebuffers are not managed by the cache. releaseSwapchainImage()174 void releaseSwapchainImage() { reset(); } 175 // Releases framebuffers and resets all members to the initial state. release(ContextVk * contextVk)176 void release(ContextVk *contextVk) 177 { 178 releaseFramebuffers(contextVk); 179 reset(); 180 } 181 // Destroys framebuffers and resets all members to the initial state. destroy(vk::Renderer * renderer)182 void destroy(vk::Renderer *renderer) 183 { 184 mFramebufferCacheManager.destroyKeys(renderer); 185 reset(); 186 } 187 188 // Helpers to update rendertarget colorspace updateWriteColorspace(gl::SrgbWriteControlMode srgbWriteControlMode)189 void updateWriteColorspace(gl::SrgbWriteControlMode srgbWriteControlMode) 190 { 191 ASSERT(mImage && mImage->valid() && mImageViews); 192 mImageViews->updateSrgbWiteControlMode(*mImage, srgbWriteControlMode); 193 } hasColorspaceOverrideForRead()194 bool hasColorspaceOverrideForRead() const 195 { 196 ASSERT(mImage && mImage->valid() && mImageViews); 197 return mImageViews->hasColorspaceOverrideForRead(*mImage); 198 } hasColorspaceOverrideForWrite()199 bool hasColorspaceOverrideForWrite() const 200 { 201 ASSERT(mImage && mImage->valid() && mImageViews); 202 return mImageViews->hasColorspaceOverrideForWrite(*mImage); 203 } getColorspaceOverrideFormatForWrite(angle::FormatID format)204 angle::FormatID getColorspaceOverrideFormatForWrite(angle::FormatID format) const 205 { 206 ASSERT(mImage && mImage->valid() && mImageViews); 207 return mImageViews->getColorspaceOverrideFormatForWrite(format); 208 } 209 210 private: 211 void reset(); 212 213 angle::Result getImageViewImpl(vk::ErrorContext *context, 214 const vk::ImageHelper &image, 215 vk::ImageViewHelper *imageViews, 216 const vk::ImageView **imageViewOut) const; 217 angle::Result getDepthOrStencilImageViewImpl(vk::ErrorContext *context, 218 const vk::ImageHelper &image, 219 vk::ImageViewHelper *imageViews, 220 VkImageAspectFlagBits aspect, 221 const vk::ImageView **imageViewOut) const; 222 223 vk::ImageOrBufferViewSubresourceSerial getSubresourceSerialImpl( 224 vk::ImageViewHelper *imageViews) const; 225 226 bool isResolveImageOwnerOfData() const; 227 vk::ImageHelper *getOwnerOfData() const; 228 229 // The color or depth/stencil attachment of the framebuffer and its view. 230 vk::ImageHelper *mImage; 231 vk::ImageViewHelper *mImageViews; 232 233 // If present, this is the corresponding resolve attachment and its view. This is used to 234 // implement GL_EXT_multisampled_render_to_texture, so while the rendering is done on mImage 235 // during the renderpass, the resolved image is the one that actually holds the data. This 236 // means that data uploads and blit are done on this image, copies are done out of this image 237 // etc. This means that if there is no clear, and hasDefined*Content(), the contents of 238 // mResolveImage must be copied to mImage since the loadOp of the attachment must be set to 239 // LOAD. 240 vk::ImageHelper *mResolveImage; 241 vk::ImageViewHelper *mResolveImageViews; 242 243 UniqueSerial mImageSiblingSerial; 244 245 // Which subresource of the image is used as render target. 246 // 247 // |mLevelIndexGL| applies to the level index of mImage unless there is a resolve attachment, 248 // in which case |mLevelIndexGL| applies to the mResolveImage since mImage is always 249 // single-level. 250 // 251 // For single-layer render targets, |mLayerIndex| will contain the layer index and |mLayerCount| 252 // will be 1. For layered render targets, |mLayerIndex| will be 0 and |mLayerCount| will be the 253 // number of layers in the image (or level depth, if image is 3D). Note that blit and other 254 // functions that read or write to the render target always use layer 0, so this works out for 255 // users of |getLayerIndex()|. 256 gl::LevelIndex mLevelIndexGL; 257 uint32_t mLayerIndex; 258 uint32_t mLayerCount; 259 260 // If resolve attachment exists, |mTransience| could be *Transient if the multisampled results 261 // need to be discarded. 262 // 263 // - GL_EXT_multisampled_render_to_texture[2]: this is |MultisampledTransient| for render 264 // targets created from color textures, as well as color or depth/stencil renderbuffers. 265 // - GL_EXT_multisampled_render_to_texture2: this is |EntirelyTransient| for depth/stencil 266 // textures per this extension, even though a resolve attachment is not even provided. 267 // 268 // Based on the above, we have: 269 // 270 // mResolveImage == nullptr 271 // Normal rendering 272 // Default No resolve 273 // storeOp = STORE 274 // Owner of data: mImage 275 // 276 // --------------------------------------------- 277 // 278 // mResolveImage != nullptr 279 // GL_EXT_multisampled_render_to_texture 280 // Multisampled Resolve 281 // Transient storeOp = DONT_CARE 282 // resolve storeOp = STORE 283 // Owner of data: mResolveImage 284 // 285 // --------------------------------------------- 286 // 287 // mResolveImage != nullptr 288 // GL_EXT_multisampled_render_to_texture2 289 // Entirely No Resolve 290 // Transient storeOp = DONT_CARE 291 // Owner of data: mResolveImage 292 // 293 // In the above, storeOp of the resolve attachment is always STORE. If |Default|, storeOp is 294 // affected by a framebuffer invalidate call. Note that even though |EntirelyTransient| has a 295 // resolve attachment, it is not used. The only purpose of |mResolveImage| is to store deferred 296 // clears. 297 RenderTargetTransience mTransience; 298 299 // Track references to the cached Framebuffer object that created out of this object 300 vk::FramebufferCacheManager mFramebufferCacheManager; 301 }; 302 303 // A vector of rendertargets 304 using RenderTargetVector = std::vector<RenderTargetVk>; 305 } // namespace rx 306 307 #endif // LIBANGLE_RENDERER_VULKAN_RENDERTARGETVK_H_ 308