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