Flutter Impeller
texture_vk.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
6 
11 
12 namespace impeller {
13 
14 TextureVK::TextureVK(std::weak_ptr<Context> context,
15  std::shared_ptr<TextureSourceVK> source)
16  : Texture(source->GetTextureDescriptor()),
17  context_(std::move(context)),
18  source_(std::move(source)) {
19 #ifdef IMPELLER_DEBUG
20  has_validation_layers_ = HasValidationLayers();
21 #endif // IMPELLER_DEBUG
22 }
23 
24 TextureVK::~TextureVK() = default;
25 
26 void TextureVK::SetLabel(std::string_view label) {
27 #ifdef IMPELLER_DEBUG
28  if (!has_validation_layers_) {
29  return;
30  }
31  auto context = context_.lock();
32  if (!context) {
33  // The context may have died.
34  return;
35  }
36  ContextVK::Cast(*context).SetDebugName(GetImage(), label);
37  ContextVK::Cast(*context).SetDebugName(GetImageView(), label);
38 #endif // IMPELLER_DEBUG
39 }
40 
41 void TextureVK::SetLabel(std::string_view label, std::string_view trailing) {
42 #ifdef IMPELLER_DEBUG
43  auto context = context_.lock();
44  if (!context) {
45  // The context may have died.
46  return;
47  }
48 
49  ContextVK::Cast(*context).SetDebugName(GetImage(), label, trailing);
50  ContextVK::Cast(*context).SetDebugName(GetImageView(), label, trailing);
51 #endif // IMPELLER_DEBUG
52 }
53 
54 bool TextureVK::OnSetContents(const uint8_t* contents,
55  size_t length,
56  size_t slice) {
57  if (!IsValid() || !contents) {
58  return false;
59  }
60 
61  const auto& desc = GetTextureDescriptor();
62 
63  // Out of bounds access.
64  if (length != desc.GetByteSizeOfBaseMipLevel()) {
65  VALIDATION_LOG << "Illegal to set contents for invalid size.";
66  return false;
67  }
68 
69  auto context = context_.lock();
70  if (!context) {
71  VALIDATION_LOG << "Context died before setting contents on texture.";
72  return false;
73  }
74 
75  auto staging_buffer =
76  context->GetResourceAllocator()->CreateBufferWithCopy(contents, length);
77 
78  if (!staging_buffer) {
79  VALIDATION_LOG << "Could not create staging buffer.";
80  return false;
81  }
82 
83  auto cmd_buffer = context->CreateCommandBuffer();
84 
85  if (!cmd_buffer) {
86  return false;
87  }
88 
89  auto& cmd_buffer_vk = CommandBufferVK::Cast(*cmd_buffer);
90 
91  if (!cmd_buffer_vk.Track(staging_buffer) || !cmd_buffer_vk.Track(source_)) {
92  return false;
93  }
94 
95  const auto& vk_cmd_buffer = cmd_buffer_vk.GetCommandBuffer();
96 
97  BarrierVK barrier;
98  barrier.cmd_buffer = vk_cmd_buffer;
99  barrier.new_layout = vk::ImageLayout::eTransferDstOptimal;
100  barrier.src_access = {};
101  barrier.src_stage = vk::PipelineStageFlagBits::eTopOfPipe;
102  barrier.dst_access = vk::AccessFlagBits::eTransferWrite;
103  barrier.dst_stage = vk::PipelineStageFlagBits::eTransfer;
104 
105  if (!SetLayout(barrier)) {
106  return false;
107  }
108 
109  vk::BufferImageCopy copy;
110  copy.bufferOffset = 0u;
111  copy.bufferRowLength = 0u; // 0u means tightly packed per spec.
112  copy.bufferImageHeight = 0u; // 0u means tightly packed per spec.
113  copy.imageOffset.x = 0u;
114  copy.imageOffset.y = 0u;
115  copy.imageOffset.z = 0u;
116  copy.imageExtent.width = desc.size.width;
117  copy.imageExtent.height = desc.size.height;
118  copy.imageExtent.depth = 1u;
119  copy.imageSubresource.aspectMask =
121  copy.imageSubresource.mipLevel = 0u;
122  copy.imageSubresource.baseArrayLayer = slice;
123  copy.imageSubresource.layerCount = 1u;
124 
125  vk_cmd_buffer.copyBufferToImage(
126  DeviceBufferVK::Cast(*staging_buffer).GetBuffer(), // src buffer
127  GetImage(), // dst image
128  barrier.new_layout, // dst image layout
129  1u, // region count
130  &copy // regions
131  );
132 
133  // Transition to shader-read.
134  {
135  BarrierVK barrier;
136  barrier.cmd_buffer = vk_cmd_buffer;
137  barrier.src_access = vk::AccessFlagBits::eColorAttachmentWrite |
138  vk::AccessFlagBits::eTransferWrite;
139  barrier.src_stage = vk::PipelineStageFlagBits::eColorAttachmentOutput |
140  vk::PipelineStageFlagBits::eTransfer;
141  barrier.dst_access = vk::AccessFlagBits::eShaderRead;
142  barrier.dst_stage = vk::PipelineStageFlagBits::eFragmentShader;
143 
144  barrier.new_layout = vk::ImageLayout::eShaderReadOnlyOptimal;
145 
146  if (!SetLayout(barrier)) {
147  return false;
148  }
149  }
150 
151  return context->GetCommandQueue()->Submit({cmd_buffer}).ok();
152 }
153 
154 bool TextureVK::OnSetContents(std::shared_ptr<const fml::Mapping> mapping,
155  size_t slice) {
156  // Vulkan has no threading restrictions. So we can pass this data along to the
157  // client rendering API immediately.
158  return OnSetContents(mapping->GetMapping(), mapping->GetSize(), slice);
159 }
160 
161 bool TextureVK::IsValid() const {
162  return !!source_;
163 }
164 
166  return GetTextureDescriptor().size;
167 }
168 
169 vk::Image TextureVK::GetImage() const {
170  return source_->GetImage();
171 }
172 
173 vk::ImageView TextureVK::GetImageView() const {
174  return source_->GetImageView();
175 }
176 
177 std::shared_ptr<const TextureSourceVK> TextureVK::GetTextureSource() const {
178  return source_;
179 }
180 
181 bool TextureVK::SetLayout(const BarrierVK& barrier) const {
182  return source_ ? source_->SetLayout(barrier).ok() : false;
183 }
184 
186  vk::ImageLayout layout) const {
187  return source_ ? source_->SetLayoutWithoutEncoding(layout)
188  : vk::ImageLayout::eUndefined;
189 }
190 
191 vk::ImageLayout TextureVK::GetLayout() const {
192  return source_ ? source_->GetLayout() : vk::ImageLayout::eUndefined;
193 }
194 
195 vk::ImageView TextureVK::GetRenderTargetView() const {
196  return source_->GetRenderTargetView();
197 }
198 
200  const SharedHandleVK<vk::Framebuffer>& framebuffer) {
201  source_->SetCachedFramebuffer(framebuffer);
202 }
203 
205  const SharedHandleVK<vk::RenderPass>& render_pass) {
206  source_->SetCachedRenderPass(render_pass);
207 }
208 
210  return source_->GetCachedFramebuffer();
211 }
212 
214  return source_->GetCachedRenderPass();
215 }
216 
218  mipmap_generated_ = true;
219 }
220 
222  return source_->IsSwapchainImage();
223 }
224 
225 std::shared_ptr<SamplerVK> TextureVK::GetImmutableSamplerVariant(
226  const SamplerVK& sampler) const {
227  if (!source_) {
228  return nullptr;
229  }
230  std::shared_ptr<YUVConversionVK> conversion = source_->GetYUVConversion();
231  if (!conversion) {
232  // Most textures don't need a sampler conversion and will go down this path.
233  // Only needed for YUV sampling from external textures.
234  return nullptr;
235  }
236  return sampler.CreateVariantForConversion(std::move(conversion));
237 }
238 
239 } // namespace impeller
static ContextVK & Cast(Context &base)
Definition: backend_cast.h:13
bool SetDebugName(T handle, std::string_view label) const
Definition: context_vk.h:151
vk::Buffer GetBuffer() const
std::shared_ptr< SamplerVK > CreateVariantForConversion(std::shared_ptr< YUVConversionVK > conversion) const
Definition: sampler_vk.cc:118
const TextureDescriptor & GetTextureDescriptor() const
Definition: texture.cc:57
bool mipmap_generated_
Definition: texture.h:79
vk::ImageView GetImageView() const
Definition: texture_vk.cc:173
std::shared_ptr< const TextureSourceVK > GetTextureSource() const
Definition: texture_vk.cc:177
bool IsSwapchainImage() const
Definition: texture_vk.cc:221
vk::ImageView GetRenderTargetView() const
Definition: texture_vk.cc:195
void SetCachedFramebuffer(const SharedHandleVK< vk::Framebuffer > &framebuffer)
Definition: texture_vk.cc:199
SharedHandleVK< vk::RenderPass > GetCachedRenderPass() const
Definition: texture_vk.cc:213
vk::ImageLayout SetLayoutWithoutEncoding(vk::ImageLayout layout) const
Definition: texture_vk.cc:185
std::shared_ptr< SamplerVK > GetImmutableSamplerVariant(const SamplerVK &sampler) const
Definition: texture_vk.cc:225
ISize GetSize() const override
Definition: texture_vk.cc:165
TextureVK(std::weak_ptr< Context > context, std::shared_ptr< TextureSourceVK > source)
Definition: texture_vk.cc:14
SharedHandleVK< vk::Framebuffer > GetCachedFramebuffer() const
Definition: texture_vk.cc:209
bool SetLayout(const BarrierVK &barrier) const
Definition: texture_vk.cc:181
vk::ImageLayout GetLayout() const
Definition: texture_vk.cc:191
void SetCachedRenderPass(const SharedHandleVK< vk::RenderPass > &render_pass)
Definition: texture_vk.cc:204
~TextureVK() override
vk::Image GetImage() const
Definition: texture_vk.cc:169
std::shared_ptr< SharedObjectVKT< T > > SharedHandleVK
bool HasValidationLayers()
Definition: context_vk.cc:53
constexpr vk::ImageAspectFlags ToImageAspectFlags(PixelFormat format)
Definition: formats_vk.h:586
Definition: comparable.h:95
Defines an operations and memory access barrier on a resource.
Definition: barrier_vk.h:27
#define VALIDATION_LOG
Definition: validation.h:91