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 #include "libANGLE/renderer/vulkan/RenderTargetVk.h"
11
12 #include "libANGLE/renderer/vulkan/CommandGraph.h"
13 #include "libANGLE/renderer/vulkan/ContextVk.h"
14 #include "libANGLE/renderer/vulkan/TextureVk.h"
15 #include "libANGLE/renderer/vulkan/vk_format_utils.h"
16 #include "libANGLE/renderer/vulkan/vk_helpers.h"
17
18 namespace rx
19 {
RenderTargetVk()20 RenderTargetVk::RenderTargetVk()
21 : mImage(nullptr),
22 mImageView(nullptr),
23 mCubeImageFetchView(nullptr),
24 mLevelIndex(0),
25 mLayerIndex(0)
26 {}
27
~RenderTargetVk()28 RenderTargetVk::~RenderTargetVk() {}
29
RenderTargetVk(RenderTargetVk && other)30 RenderTargetVk::RenderTargetVk(RenderTargetVk &&other)
31 : mImage(other.mImage),
32 mImageView(other.mImageView),
33 mCubeImageFetchView(other.mCubeImageFetchView),
34 mLevelIndex(other.mLevelIndex),
35 mLayerIndex(other.mLayerIndex)
36 {}
37
init(vk::ImageHelper * image,vk::ImageView * imageView,vk::ImageView * cubeImageFetchView,uint32_t levelIndex,uint32_t layerIndex)38 void RenderTargetVk::init(vk::ImageHelper *image,
39 vk::ImageView *imageView,
40 vk::ImageView *cubeImageFetchView,
41 uint32_t levelIndex,
42 uint32_t layerIndex)
43 {
44 mImage = image;
45 mImageView = imageView;
46 mCubeImageFetchView = cubeImageFetchView;
47 mLevelIndex = levelIndex;
48 mLayerIndex = layerIndex;
49 }
50
reset()51 void RenderTargetVk::reset()
52 {
53 mImage = nullptr;
54 mImageView = nullptr;
55 mCubeImageFetchView = nullptr;
56 mLevelIndex = 0;
57 mLayerIndex = 0;
58 }
59
onColorDraw(ContextVk * contextVk,vk::FramebufferHelper * framebufferVk,vk::CommandBuffer * commandBuffer)60 angle::Result RenderTargetVk::onColorDraw(ContextVk *contextVk,
61 vk::FramebufferHelper *framebufferVk,
62 vk::CommandBuffer *commandBuffer)
63 {
64 ASSERT(commandBuffer->valid());
65 ASSERT(!mImage->getFormat().imageFormat().hasDepthOrStencilBits());
66
67 // TODO(jmadill): Use automatic layout transition. http://anglebug.com/2361
68 mImage->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ColorAttachment,
69 commandBuffer);
70
71 // Set up dependencies between the RT resource and the Framebuffer.
72 mImage->addWriteDependency(framebufferVk);
73
74 return angle::Result::Continue;
75 }
76
onDepthStencilDraw(ContextVk * contextVk,vk::FramebufferHelper * framebufferVk,vk::CommandBuffer * commandBuffer)77 angle::Result RenderTargetVk::onDepthStencilDraw(ContextVk *contextVk,
78 vk::FramebufferHelper *framebufferVk,
79 vk::CommandBuffer *commandBuffer)
80 {
81 ASSERT(commandBuffer->valid());
82 ASSERT(mImage->getFormat().imageFormat().hasDepthOrStencilBits());
83
84 // TODO(jmadill): Use automatic layout transition. http://anglebug.com/2361
85 const angle::Format &format = mImage->getFormat().imageFormat();
86 VkImageAspectFlags aspectFlags = vk::GetDepthStencilAspectFlags(format);
87
88 mImage->changeLayout(aspectFlags, vk::ImageLayout::DepthStencilAttachment, commandBuffer);
89
90 // Set up dependencies between the RT resource and the Framebuffer.
91 mImage->addWriteDependency(framebufferVk);
92
93 return angle::Result::Continue;
94 }
95
getImage()96 vk::ImageHelper &RenderTargetVk::getImage()
97 {
98 ASSERT(mImage && mImage->valid());
99 return *mImage;
100 }
101
getImage() const102 const vk::ImageHelper &RenderTargetVk::getImage() const
103 {
104 ASSERT(mImage && mImage->valid());
105 return *mImage;
106 }
107
getDrawImageView() const108 vk::ImageView *RenderTargetVk::getDrawImageView() const
109 {
110 ASSERT(mImageView && mImageView->valid());
111 return mImageView;
112 }
113
getReadImageView() const114 vk::ImageView *RenderTargetVk::getReadImageView() const
115 {
116 return getDrawImageView();
117 }
118
getFetchImageView() const119 vk::ImageView *RenderTargetVk::getFetchImageView() const
120 {
121 return mCubeImageFetchView && mCubeImageFetchView->valid() ? mCubeImageFetchView
122 : getReadImageView();
123 }
124
getImageFormat() const125 const vk::Format &RenderTargetVk::getImageFormat() const
126 {
127 ASSERT(mImage && mImage->valid());
128 return mImage->getFormat();
129 }
130
getExtents() const131 gl::Extents RenderTargetVk::getExtents() const
132 {
133 ASSERT(mImage && mImage->valid());
134 return mImage->getLevelExtents2D(static_cast<uint32_t>(mLevelIndex));
135 }
136
updateSwapchainImage(vk::ImageHelper * image,vk::ImageView * imageView)137 void RenderTargetVk::updateSwapchainImage(vk::ImageHelper *image, vk::ImageView *imageView)
138 {
139 ASSERT(image && image->valid() && imageView && imageView->valid());
140 mImage = image;
141 mImageView = imageView;
142 mCubeImageFetchView = nullptr;
143 }
144
getImageForRead(vk::CommandGraphResource * readingResource,vk::ImageLayout layout,vk::CommandBuffer * commandBuffer)145 vk::ImageHelper *RenderTargetVk::getImageForRead(vk::CommandGraphResource *readingResource,
146 vk::ImageLayout layout,
147 vk::CommandBuffer *commandBuffer)
148 {
149 ASSERT(mImage && mImage->valid());
150
151 // TODO(jmadill): Better simultaneous resource access. http://anglebug.com/2679
152 //
153 // A better alternative would be:
154 //
155 // if (mImage->isLayoutChangeNecessary(layout)
156 // {
157 // vk::CommandBuffer *srcLayoutChange;
158 // ANGLE_TRY(mImage->recordCommands(contextVk, &srcLayoutChange));
159 // mImage->changeLayout(mImage->getAspectFlags(), layout, srcLayoutChange);
160 // }
161 // mImage->addReadDependency(readingResource);
162 //
163 // I.e. the transition should happen on a node generated from mImage itself.
164 // However, this needs context to be available here, or all call sites changed
165 // to perform the layout transition and set the dependency.
166 mImage->addWriteDependency(readingResource);
167
168 mImage->changeLayout(mImage->getAspectFlags(), layout, commandBuffer);
169
170 return mImage;
171 }
172
getImageForWrite(vk::CommandGraphResource * writingResource) const173 vk::ImageHelper *RenderTargetVk::getImageForWrite(vk::CommandGraphResource *writingResource) const
174 {
175 ASSERT(mImage && mImage->valid());
176 mImage->addWriteDependency(writingResource);
177 return mImage;
178 }
179
flushStagedUpdates(ContextVk * contextVk)180 angle::Result RenderTargetVk::flushStagedUpdates(ContextVk *contextVk)
181 {
182 ASSERT(mImage->valid());
183 if (!mImage->hasStagedUpdates())
184 return angle::Result::Continue;
185
186 vk::CommandBuffer *commandBuffer;
187 ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer));
188 return mImage->flushStagedUpdates(contextVk, mLevelIndex, mLevelIndex + 1, mLayerIndex,
189 mLayerIndex + 1, commandBuffer);
190 }
191
192 } // namespace rx
193