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 // Multisampled-render-to-texture depth/stencil textures. 40 EntirelyTransient, 41 }; 42 43 // This is a very light-weight class that does not own to the resources it points to. 44 // It's meant only to copy across some information from a FramebufferAttachment to the 45 // business rendering logic. It stores Images and ImageViews by pointer for performance. 46 class RenderTargetVk final : public FramebufferAttachmentRenderTarget 47 { 48 public: 49 RenderTargetVk(); 50 ~RenderTargetVk() override; 51 52 // Used in std::vector initialization. 53 RenderTargetVk(RenderTargetVk &&other); 54 55 void init(vk::ImageHelper *image, 56 vk::ImageViewHelper *imageViews, 57 vk::ImageHelper *resolveImage, 58 vk::ImageViewHelper *resolveImageViews, 59 UniqueSerial imageSiblingSerial, 60 gl::LevelIndex levelIndexGL, 61 uint32_t layerIndex, 62 uint32_t layerCount, 63 RenderTargetTransience transience); 64 65 vk::ImageOrBufferViewSubresourceSerial getDrawSubresourceSerial() const; 66 vk::ImageOrBufferViewSubresourceSerial getResolveSubresourceSerial() const; 67 68 // Note: RenderTargets should be called in order, with the depth/stencil onRender last. 69 void onColorDraw(ContextVk *contextVk, 70 uint32_t framebufferLayerCount, 71 vk::PackedAttachmentIndex index); 72 void onColorResolve(ContextVk *contextVk, uint32_t framebufferLayerCount); 73 void onDepthStencilDraw(ContextVk *contextVk, uint32_t framebufferLayerCount); 74 75 vk::ImageHelper &getImageForRenderPass(); 76 const vk::ImageHelper &getImageForRenderPass() const; 77 78 vk::ImageHelper &getResolveImageForRenderPass(); 79 const vk::ImageHelper &getResolveImageForRenderPass() const; 80 81 vk::ImageHelper &getImageForCopy() const; 82 vk::ImageHelper &getImageForWrite() const; 83 84 // For cube maps we use single-level single-layer 2D array views. 85 angle::Result getImageView(vk::Context *contextVk, const vk::ImageView **imageViewOut) const; 86 angle::Result getImageViewWithColorspace(vk::Context *context, 87 gl::SrgbWriteControlMode srgbWriteContrlMode, 88 const vk::ImageView **imageViewOut) const; 89 angle::Result getResolveImageView(vk::Context *context, 90 const vk::ImageView **imageViewOut) const; 91 92 // For 3D textures, the 2D view created for render target is invalid to read from. The 93 // following will return a view to the whole image (for all types, including 3D and 2DArray). 94 angle::Result getCopyImageView(vk::Context *context, const vk::ImageView **imageViewOut) const; 95 96 angle::FormatID getImageActualFormatID() const; 97 const angle::Format &getImageActualFormat() const; 98 angle::FormatID getImageIntendedFormatID() const; 99 const angle::Format &getImageIntendedFormat() const; 100 101 gl::Extents getExtents() const; 102 gl::Extents getRotatedExtents() const; getLevelIndex()103 gl::LevelIndex getLevelIndex() const { return mLevelIndexGL; } getLayerIndex()104 uint32_t getLayerIndex() const { return mLayerIndex; } getLayerCount()105 uint32_t getLayerCount() const { return mLayerCount; } 106 107 gl::ImageIndex getImageIndexForClear(uint32_t layerCount) const; 108 109 // Special mutator for Surface RenderTargets. Allows the Framebuffer to keep a single 110 // RenderTargetVk pointer. 111 void updateSwapchainImage(vk::ImageHelper *image, 112 vk::ImageViewHelper *imageViews, 113 vk::ImageHelper *resolveImage, 114 vk::ImageViewHelper *resolveImageViews); 115 116 angle::Result flushStagedUpdates(ContextVk *contextVk, 117 vk::ClearValuesArray *deferredClears, 118 uint32_t deferredClearIndex, 119 uint32_t framebufferLayerCount); 120 121 bool hasDefinedContent() const; 122 bool hasDefinedStencilContent() const; 123 // Mark content as undefined so that certain optimizations are possible such as using DONT_CARE 124 // as loadOp of the render target in the next renderpass. If |preferToKeepContentsDefinedOut| 125 // is set to true, it's preferred to ignore the invalidation due to image format and device 126 // architecture properties. 127 void invalidateEntireContent(ContextVk *contextVk, bool *preferToKeepContentsDefinedOut); 128 void invalidateEntireStencilContent(ContextVk *contextVk, bool *preferToKeepContentsDefinedOut); 129 130 // See the description of mTransience for details of how the following two can interact. hasResolveAttachment()131 bool hasResolveAttachment() const { return mResolveImage != nullptr && !isEntirelyTransient(); } isImageTransient()132 bool isImageTransient() const { return mTransience != RenderTargetTransience::Default; } isEntirelyTransient()133 bool isEntirelyTransient() const 134 { 135 return mTransience == RenderTargetTransience::EntirelyTransient; 136 } 137 onNewFramebuffer(const vk::SharedFramebufferCacheKey & sharedFramebufferCacheKey)138 void onNewFramebuffer(const vk::SharedFramebufferCacheKey &sharedFramebufferCacheKey) 139 { 140 ASSERT(!mFramebufferCacheManager.containsKey(sharedFramebufferCacheKey)); 141 mFramebufferCacheManager.addKey(sharedFramebufferCacheKey); 142 } release(ContextVk * contextVk)143 void release(ContextVk *contextVk) { mFramebufferCacheManager.releaseKeys(contextVk); } destroy(RendererVk * renderer)144 void destroy(RendererVk *renderer) { mFramebufferCacheManager.destroyKeys(renderer); } 145 146 private: 147 void reset(); 148 149 angle::Result getImageViewImpl(vk::Context *context, 150 const vk::ImageHelper &image, 151 gl::SrgbWriteControlMode mode, 152 vk::ImageViewHelper *imageViews, 153 const vk::ImageView **imageViewOut) const; 154 155 vk::ImageOrBufferViewSubresourceSerial getSubresourceSerialImpl( 156 vk::ImageViewHelper *imageViews) const; 157 158 bool isResolveImageOwnerOfData() const; 159 vk::ImageHelper *getOwnerOfData() const; 160 161 // The color or depth/stencil attachment of the framebuffer and its view. 162 vk::ImageHelper *mImage; 163 vk::ImageViewHelper *mImageViews; 164 165 // If present, this is the corresponding resolve attachment and its view. This is used to 166 // implement GL_EXT_multisampled_render_to_texture, so while the rendering is done on mImage 167 // during the renderpass, the resolved image is the one that actually holds the data. This 168 // means that data uploads and blit are done on this image, copies are done out of this image 169 // etc. This means that if there is no clear, and hasDefined*Content(), the contents of 170 // mResolveImage must be copied to mImage since the loadOp of the attachment must be set to 171 // LOAD. 172 vk::ImageHelper *mResolveImage; 173 vk::ImageViewHelper *mResolveImageViews; 174 175 UniqueSerial mImageSiblingSerial; 176 177 // Which subresource of the image is used as render target. For single-layer render targets, 178 // |mLayerIndex| will contain the layer index and |mLayerCount| will be 1. For layered render 179 // targets, |mLayerIndex| will be 0 and |mLayerCount| will be the number of layers in the image 180 // (or level depth, if image is 3D). Note that blit and other functions that read or write to 181 // the render target always use layer 0, so this works out for users of |getLayerIndex()|. 182 gl::LevelIndex mLevelIndexGL; 183 uint32_t mLayerIndex; 184 uint32_t mLayerCount; 185 186 // If resolve attachment exists, |mTransience| could be *Transient if the multisampled results 187 // need to be discarded. 188 // 189 // - GL_EXT_multisampled_render_to_texture[2]: this is |MultisampledTransient| for render 190 // targets created from color textures, as well as color or depth/stencil renderbuffers. 191 // - GL_EXT_multisampled_render_to_texture2: this is |EntirelyTransient| for depth/stencil 192 // textures per this extension, even though a resolve attachment is not even provided. 193 // 194 // Based on the above, we have: 195 // 196 // mResolveImage == nullptr 197 // Normal rendering 198 // Default No resolve 199 // storeOp = STORE 200 // Owner of data: mImage 201 // 202 // --------------------------------------------- 203 // 204 // mResolveImage != nullptr 205 // GL_EXT_multisampled_render_to_texture 206 // Multisampled Resolve 207 // Transient storeOp = DONT_CARE 208 // resolve storeOp = STORE 209 // Owner of data: mResolveImage 210 // 211 // --------------------------------------------- 212 // 213 // mResolveImage != nullptr 214 // GL_EXT_multisampled_render_to_texture2 215 // Entirely No Resolve 216 // Transient storeOp = DONT_CARE 217 // Owner of data: mResolveImage 218 // 219 // In the above, storeOp of the resolve attachment is always STORE. If |Default|, storeOp is 220 // affected by a framebuffer invalidate call. Note that even though |EntirelyTransient| has a 221 // resolve attachment, it is not used. The only purpose of |mResolveImage| is to store deferred 222 // clears. 223 RenderTargetTransience mTransience; 224 225 // Track references to the cached Framebuffer object that created out of this object 226 vk::FramebufferCacheManager mFramebufferCacheManager; 227 }; 228 229 // A vector of rendertargets 230 using RenderTargetVector = std::vector<RenderTargetVk>; 231 } // namespace rx 232 233 #endif // LIBANGLE_RENDERER_VULKAN_RENDERTARGETVK_H_ 234