| // |
| // 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. |
| // |
| // RenderTargetVk: |
| // Wrapper around a Vulkan renderable resource, using an ImageView. |
| // |
| |
| #ifndef LIBANGLE_RENDERER_VULKAN_RENDERTARGETVK_H_ |
| #define LIBANGLE_RENDERER_VULKAN_RENDERTARGETVK_H_ |
| |
| #include "common/vulkan/vk_headers.h" |
| #include "libANGLE/FramebufferAttachment.h" |
| #include "libANGLE/renderer/renderer_utils.h" |
| #include "libANGLE/renderer/vulkan/vk_helpers.h" |
| |
| namespace rx |
| { |
| namespace vk |
| { |
| class FramebufferHelper; |
| class ImageHelper; |
| class ImageView; |
| class Resource; |
| class RenderPassDesc; |
| } // namespace vk |
| |
| class ContextVk; |
| class TextureVk; |
| |
| enum class RenderTargetTransience |
| { |
| // Regular render targets that load and store from the image. |
| Default, |
| // Multisampled-render-to-texture textures, where the implicit multisampled image is transient, |
| // but the resolved image is persistent. |
| MultisampledTransient, |
| // Multisampled-render-to-texture depth/stencil textures. |
| EntirelyTransient, |
| }; |
| |
| // This is a very light-weight class that does not own to the resources it points to. |
| // It's meant only to copy across some information from a FramebufferAttachment to the |
| // business rendering logic. It stores Images and ImageViews by pointer for performance. |
| class RenderTargetVk final : public FramebufferAttachmentRenderTarget |
| { |
| public: |
| RenderTargetVk(); |
| ~RenderTargetVk() override; |
| |
| // Used in std::vector initialization. |
| RenderTargetVk(RenderTargetVk &&other); |
| |
| void init(vk::ImageHelper *image, |
| vk::ImageViewHelper *imageViews, |
| vk::ImageHelper *resolveImage, |
| vk::ImageViewHelper *resolveImageViews, |
| gl::LevelIndex levelIndexGL, |
| uint32_t layerIndex, |
| uint32_t layerCount, |
| RenderTargetTransience transience); |
| void reset(); |
| |
| vk::ImageOrBufferViewSubresourceSerial getDrawSubresourceSerial() const; |
| vk::ImageOrBufferViewSubresourceSerial getResolveSubresourceSerial() const; |
| |
| // Note: RenderTargets should be called in order, with the depth/stencil onRender last. |
| void onColorDraw(ContextVk *contextVk, |
| uint32_t framebufferLayerCount, |
| vk::PackedAttachmentIndex index); |
| void onColorResolve(ContextVk *contextVk, uint32_t framebufferLayerCount); |
| void onDepthStencilDraw(ContextVk *contextVk, uint32_t framebufferLayerCount); |
| |
| vk::ImageHelper &getImageForRenderPass(); |
| const vk::ImageHelper &getImageForRenderPass() const; |
| |
| vk::ImageHelper &getResolveImageForRenderPass(); |
| const vk::ImageHelper &getResolveImageForRenderPass() const; |
| |
| vk::ImageHelper &getImageForCopy() const; |
| vk::ImageHelper &getImageForWrite() const; |
| |
| // For cube maps we use single-level single-layer 2D array views. |
| angle::Result getImageView(vk::Context *contextVk, const vk::ImageView **imageViewOut) const; |
| angle::Result getImageViewWithColorspace(vk::Context *context, |
| gl::SrgbWriteControlMode srgbWriteContrlMode, |
| const vk::ImageView **imageViewOut) const; |
| angle::Result getResolveImageView(vk::Context *context, |
| const vk::ImageView **imageViewOut) const; |
| |
| // For 3D textures, the 2D view created for render target is invalid to read from. The |
| // following will return a view to the whole image (for all types, including 3D and 2DArray). |
| angle::Result getCopyImageView(vk::Context *context, const vk::ImageView **imageViewOut) const; |
| |
| angle::FormatID getImageActualFormatID() const; |
| const angle::Format &getImageActualFormat() const; |
| angle::FormatID getImageIntendedFormatID() const; |
| const angle::Format &getImageIntendedFormat() const; |
| |
| gl::Extents getExtents() const; |
| gl::Extents getRotatedExtents() const; |
| gl::LevelIndex getLevelIndex() const { return mLevelIndexGL; } |
| uint32_t getLayerIndex() const { return mLayerIndex; } |
| uint32_t getLayerCount() const { return mLayerCount; } |
| |
| gl::ImageIndex getImageIndexForClear(uint32_t layerCount) const; |
| |
| // Special mutator for Surface RenderTargets. Allows the Framebuffer to keep a single |
| // RenderTargetVk pointer. |
| void updateSwapchainImage(vk::ImageHelper *image, |
| vk::ImageViewHelper *imageViews, |
| vk::ImageHelper *resolveImage, |
| vk::ImageViewHelper *resolveImageViews); |
| |
| angle::Result flushStagedUpdates(ContextVk *contextVk, |
| vk::ClearValuesArray *deferredClears, |
| uint32_t deferredClearIndex, |
| uint32_t framebufferLayerCount); |
| |
| bool hasDefinedContent() const; |
| bool hasDefinedStencilContent() const; |
| // Mark content as undefined so that certain optimizations are possible such as using DONT_CARE |
| // as loadOp of the render target in the next renderpass. If |preferToKeepContentsDefinedOut| |
| // is set to true, it's preferred to ignore the invalidation due to image format and device |
| // architecture properties. |
| void invalidateEntireContent(ContextVk *contextVk, bool *preferToKeepContentsDefinedOut); |
| void invalidateEntireStencilContent(ContextVk *contextVk, bool *preferToKeepContentsDefinedOut); |
| |
| // See the description of mTransience for details of how the following two can interact. |
| bool hasResolveAttachment() const { return mResolveImage != nullptr && !isEntirelyTransient(); } |
| bool isImageTransient() const { return mTransience != RenderTargetTransience::Default; } |
| bool isEntirelyTransient() const |
| { |
| return mTransience == RenderTargetTransience::EntirelyTransient; |
| } |
| |
| private: |
| angle::Result getImageViewImpl(vk::Context *context, |
| const vk::ImageHelper &image, |
| gl::SrgbWriteControlMode mode, |
| vk::ImageViewHelper *imageViews, |
| const vk::ImageView **imageViewOut) const; |
| |
| vk::ImageOrBufferViewSubresourceSerial getSubresourceSerialImpl( |
| vk::ImageViewHelper *imageViews) const; |
| |
| bool isResolveImageOwnerOfData() const; |
| vk::ImageHelper *getOwnerOfData() const; |
| |
| // The color or depth/stencil attachment of the framebuffer and its view. |
| vk::ImageHelper *mImage; |
| vk::ImageViewHelper *mImageViews; |
| |
| // If present, this is the corresponding resolve attachment and its view. This is used to |
| // implement GL_EXT_multisampled_render_to_texture, so while the rendering is done on mImage |
| // during the renderpass, the resolved image is the one that actually holds the data. This |
| // means that data uploads and blit are done on this image, copies are done out of this image |
| // etc. This means that if there is no clear, and hasDefined*Content(), the contents of |
| // mResolveImage must be copied to mImage since the loadOp of the attachment must be set to |
| // LOAD. |
| vk::ImageHelper *mResolveImage; |
| vk::ImageViewHelper *mResolveImageViews; |
| |
| // Which subresource of the image is used as render target. For single-layer render targets, |
| // |mLayerIndex| will contain the layer index and |mLayerCount| will be 1. For layered render |
| // targets, |mLayerIndex| will be 0 and |mLayerCount| will be the number of layers in the image |
| // (or level depth, if image is 3D). Note that blit and other functions that read or write to |
| // the render target always use layer 0, so this works out for users of |getLayerIndex()|. |
| gl::LevelIndex mLevelIndexGL; |
| uint32_t mLayerIndex; |
| uint32_t mLayerCount; |
| |
| // If resolve attachment exists, |mTransience| could be *Transient if the multisampled results |
| // need to be discarded. |
| // |
| // - GL_EXT_multisampled_render_to_texture[2]: this is |MultisampledTransient| for render |
| // targets created from color textures, as well as color or depth/stencil renderbuffers. |
| // - GL_EXT_multisampled_render_to_texture2: this is |EntirelyTransient| for depth/stencil |
| // textures per this extension, even though a resolve attachment is not even provided. |
| // |
| // Based on the above, we have: |
| // |
| // mResolveImage == nullptr |
| // Normal rendering |
| // Default No resolve |
| // storeOp = STORE |
| // Owner of data: mImage |
| // |
| // --------------------------------------------- |
| // |
| // mResolveImage != nullptr |
| // GL_EXT_multisampled_render_to_texture |
| // Multisampled Resolve |
| // Transient storeOp = DONT_CARE |
| // resolve storeOp = STORE |
| // Owner of data: mResolveImage |
| // |
| // --------------------------------------------- |
| // |
| // mResolveImage != nullptr |
| // GL_EXT_multisampled_render_to_texture2 |
| // Entirely No Resolve |
| // Transient storeOp = DONT_CARE |
| // Owner of data: mResolveImage |
| // |
| // In the above, storeOp of the resolve attachment is always STORE. If |Default|, storeOp is |
| // affected by a framebuffer invalidate call. Note that even though |EntirelyTransient| has a |
| // resolve attachment, it is not used. The only purpose of |mResolveImage| is to store deferred |
| // clears. |
| RenderTargetTransience mTransience; |
| }; |
| |
| // A vector of rendertargets |
| using RenderTargetVector = std::vector<RenderTargetVk>; |
| } // namespace rx |
| |
| #endif // LIBANGLE_RENDERER_VULKAN_RENDERTARGETVK_H_ |