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::Context *context, const vk::ImageView **imageViewOut) const; 96 angle::Result getImageViewWithColorspace(vk::Context *context, 97 gl::SrgbWriteControlMode srgbWriteContrlMode, 98 const vk::ImageView **imageViewOut) const; 99 angle::Result getResolveImageView(vk::Context *context, 100 const vk::ImageView **imageViewOut) const; 101 angle::Result getDepthOrStencilImageView(vk::Context *context, 102 VkImageAspectFlagBits aspect, 103 const vk::ImageView **imageViewOut) const; 104 angle::Result getDepthOrStencilImageViewForCopy(vk::Context *context, 105 VkImageAspectFlagBits aspect, 106 const vk::ImageView **imageViewOut) const; 107 angle::Result getResolveDepthOrStencilImageView(vk::Context *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::Context *context, const vk::ImageView **imageViewOut) const; 114 115 angle::FormatID getImageActualFormatID() const; 116 const angle::Format &getImageActualFormat() const; 117 angle::FormatID getImageIntendedFormatID() const; 118 const angle::Format &getImageIntendedFormat() const; 119 120 gl::Extents getExtents() const; 121 gl::Extents getRotatedExtents() const; getLevelIndex()122 gl::LevelIndex getLevelIndex() const { return mLevelIndexGL; } 123 gl::LevelIndex getLevelIndexForImage(const vk::ImageHelper &image) const; getLayerIndex()124 uint32_t getLayerIndex() const { return mLayerIndex; } getLayerCount()125 uint32_t getLayerCount() const { return mLayerCount; } is3DImage()126 bool is3DImage() const { return getOwnerOfData()->getType() == VK_IMAGE_TYPE_3D; } 127 128 gl::ImageIndex getImageIndexForClear(uint32_t layerCount) const; 129 130 // Special mutator for Surface RenderTargets. Allows the Framebuffer to keep a single 131 // RenderTargetVk pointer. 132 void updateSwapchainImage(vk::ImageHelper *image, 133 vk::ImageViewHelper *imageViews, 134 vk::ImageHelper *resolveImage, 135 vk::ImageViewHelper *resolveImageViews); 136 137 angle::Result flushStagedUpdates(ContextVk *contextVk, 138 vk::ClearValuesArray *deferredClears, 139 uint32_t deferredClearIndex, 140 uint32_t framebufferLayerCount); 141 142 bool hasDefinedContent() const; 143 bool hasDefinedStencilContent() const; 144 // Mark content as undefined so that certain optimizations are possible such as using DONT_CARE 145 // as loadOp of the render target in the next renderpass. If |preferToKeepContentsDefinedOut| 146 // is set to true, it's preferred to ignore the invalidation due to image format and device 147 // architecture properties. 148 void invalidateEntireContent(ContextVk *contextVk, bool *preferToKeepContentsDefinedOut); 149 void invalidateEntireStencilContent(ContextVk *contextVk, bool *preferToKeepContentsDefinedOut); 150 151 // See the description of mTransience for details of how the following two can interact. hasResolveAttachment()152 bool hasResolveAttachment() const { return mResolveImage != nullptr && !isEntirelyTransient(); } isImageTransient()153 bool isImageTransient() const { return mTransience != RenderTargetTransience::Default; } isEntirelyTransient()154 bool isEntirelyTransient() const 155 { 156 return mTransience == RenderTargetTransience::EntirelyTransient; 157 } isYuvResolve()158 bool isYuvResolve() const 159 { 160 return mResolveImage != nullptr ? mResolveImage->isYuvResolve() : false; 161 } 162 onNewFramebuffer(const vk::SharedFramebufferCacheKey & sharedFramebufferCacheKey)163 void onNewFramebuffer(const vk::SharedFramebufferCacheKey &sharedFramebufferCacheKey) 164 { 165 mFramebufferCacheManager.addKey(sharedFramebufferCacheKey); 166 } releaseFramebuffers(ContextVk * contextVk)167 void releaseFramebuffers(ContextVk *contextVk) 168 { 169 mFramebufferCacheManager.releaseKeys(contextVk); 170 } 171 // Releases framebuffers and resets Image and ImageView pointers, while keeping other 172 // members intact, in order to allow |updateSwapchainImage| call later. releaseImageAndViews(ContextVk * contextVk)173 void releaseImageAndViews(ContextVk *contextVk) 174 { 175 releaseFramebuffers(contextVk); 176 invalidateImageAndViews(); 177 } 178 // Releases framebuffers and resets all members to the initial state. destroy(vk::Renderer * renderer)179 void destroy(vk::Renderer *renderer) 180 { 181 mFramebufferCacheManager.destroyKeys(renderer); 182 reset(); 183 } 184 185 // Helpers to update rendertarget colorspace updateWriteColorspace(gl::SrgbWriteControlMode srgbWriteControlMode)186 void updateWriteColorspace(gl::SrgbWriteControlMode srgbWriteControlMode) 187 { 188 ASSERT(mImage && mImage->valid() && mImageViews); 189 mImageViews->updateSrgbWiteControlMode(*mImage, srgbWriteControlMode); 190 } hasColorspaceOverrideForRead()191 bool hasColorspaceOverrideForRead() const 192 { 193 ASSERT(mImage && mImage->valid() && mImageViews); 194 return mImageViews->hasColorspaceOverrideForRead(*mImage); 195 } hasColorspaceOverrideForWrite()196 bool hasColorspaceOverrideForWrite() const 197 { 198 ASSERT(mImage && mImage->valid() && mImageViews); 199 return mImageViews->hasColorspaceOverrideForWrite(*mImage); 200 } getColorspaceOverrideFormatForWrite(angle::FormatID format)201 angle::FormatID getColorspaceOverrideFormatForWrite(angle::FormatID format) const 202 { 203 ASSERT(mImage && mImage->valid() && mImageViews); 204 return mImageViews->getColorspaceOverrideFormatForWrite(format); 205 } 206 207 private: 208 void invalidateImageAndViews(); 209 void reset(); 210 211 angle::Result getImageViewImpl(vk::Context *context, 212 const vk::ImageHelper &image, 213 vk::ImageViewHelper *imageViews, 214 const vk::ImageView **imageViewOut) const; 215 angle::Result getDepthOrStencilImageViewImpl(vk::Context *context, 216 const vk::ImageHelper &image, 217 vk::ImageViewHelper *imageViews, 218 VkImageAspectFlagBits aspect, 219 const vk::ImageView **imageViewOut) const; 220 221 vk::ImageOrBufferViewSubresourceSerial getSubresourceSerialImpl( 222 vk::ImageViewHelper *imageViews) const; 223 224 bool isResolveImageOwnerOfData() const; 225 vk::ImageHelper *getOwnerOfData() const; 226 227 // The color or depth/stencil attachment of the framebuffer and its view. 228 vk::ImageHelper *mImage; 229 vk::ImageViewHelper *mImageViews; 230 231 // If present, this is the corresponding resolve attachment and its view. This is used to 232 // implement GL_EXT_multisampled_render_to_texture, so while the rendering is done on mImage 233 // during the renderpass, the resolved image is the one that actually holds the data. This 234 // means that data uploads and blit are done on this image, copies are done out of this image 235 // etc. This means that if there is no clear, and hasDefined*Content(), the contents of 236 // mResolveImage must be copied to mImage since the loadOp of the attachment must be set to 237 // LOAD. 238 vk::ImageHelper *mResolveImage; 239 vk::ImageViewHelper *mResolveImageViews; 240 241 UniqueSerial mImageSiblingSerial; 242 243 // Which subresource of the image is used as render target. 244 // 245 // |mLevelIndexGL| applies to the level index of mImage unless there is a resolve attachment, 246 // in which case |mLevelIndexGL| applies to the mResolveImage since mImage is always 247 // single-level. 248 // 249 // For single-layer render targets, |mLayerIndex| will contain the layer index and |mLayerCount| 250 // will be 1. For layered render targets, |mLayerIndex| will be 0 and |mLayerCount| will be the 251 // number of layers in the image (or level depth, if image is 3D). Note that blit and other 252 // functions that read or write to the render target always use layer 0, so this works out for 253 // users of |getLayerIndex()|. 254 gl::LevelIndex mLevelIndexGL; 255 uint32_t mLayerIndex; 256 uint32_t mLayerCount; 257 258 // If resolve attachment exists, |mTransience| could be *Transient if the multisampled results 259 // need to be discarded. 260 // 261 // - GL_EXT_multisampled_render_to_texture[2]: this is |MultisampledTransient| for render 262 // targets created from color textures, as well as color or depth/stencil renderbuffers. 263 // - GL_EXT_multisampled_render_to_texture2: this is |EntirelyTransient| for depth/stencil 264 // textures per this extension, even though a resolve attachment is not even provided. 265 // 266 // Based on the above, we have: 267 // 268 // mResolveImage == nullptr 269 // Normal rendering 270 // Default No resolve 271 // storeOp = STORE 272 // Owner of data: mImage 273 // 274 // --------------------------------------------- 275 // 276 // mResolveImage != nullptr 277 // GL_EXT_multisampled_render_to_texture 278 // Multisampled Resolve 279 // Transient storeOp = DONT_CARE 280 // resolve storeOp = STORE 281 // Owner of data: mResolveImage 282 // 283 // --------------------------------------------- 284 // 285 // mResolveImage != nullptr 286 // GL_EXT_multisampled_render_to_texture2 287 // Entirely No Resolve 288 // Transient storeOp = DONT_CARE 289 // Owner of data: mResolveImage 290 // 291 // In the above, storeOp of the resolve attachment is always STORE. If |Default|, storeOp is 292 // affected by a framebuffer invalidate call. Note that even though |EntirelyTransient| has a 293 // resolve attachment, it is not used. The only purpose of |mResolveImage| is to store deferred 294 // clears. 295 RenderTargetTransience mTransience; 296 297 // Track references to the cached Framebuffer object that created out of this object 298 vk::FramebufferCacheManager mFramebufferCacheManager; 299 }; 300 301 // A vector of rendertargets 302 using RenderTargetVector = std::vector<RenderTargetVk>; 303 } // namespace rx 304 305 #endif // LIBANGLE_RENDERER_VULKAN_RENDERTARGETVK_H_ 306