| 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
5 #include "impeller/renderer/backend/vulkan/texture_vk.h"
6
7 #include "impeller/core/texture_descriptor.h"
8 #include "impeller/renderer/backend/vulkan/command_buffer_vk.h"
9 #include "impeller/renderer/backend/vulkan/formats_vk.h"
10 #include "impeller/renderer/backend/vulkan/sampler_vk.h"
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 =
120 ToImageAspectFlags(GetTextureDescriptor().format);
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
165 ISize TextureVK::GetSize() const {
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
185 vk::ImageLayout TextureVK::SetLayoutWithoutEncoding(
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
199 void TextureVK::SetCachedFramebuffer(
200 const SharedHandleVK<vk::Framebuffer>& framebuffer) {
201 source_->SetCachedFramebuffer(framebuffer);
202 }
203
204 void TextureVK::SetCachedRenderPass(
205 const SharedHandleVK<vk::RenderPass>& render_pass) {
206 source_->SetCachedRenderPass(render_pass);
207 }
208
209 SharedHandleVK<vk::Framebuffer> TextureVK::GetCachedFramebuffer() const {
210 return source_->GetCachedFramebuffer();
211 }
212
213 SharedHandleVK<vk::RenderPass> TextureVK::GetCachedRenderPass() const {
214 return source_->GetCachedRenderPass();
215 }
216
217 void TextureVK::SetMipMapGenerated() {
218 mipmap_generated_ = true;
219 }
220
221 bool TextureVK::IsSwapchainImage() const {
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
impeller::BackendCast< ContextVK, Context >::Cast
static ContextVK & Cast(Context &base)
Definition: backend_cast.h:13
impeller::ContextVK::SetDebugName
bool SetDebugName(T handle, std::string_view label) const
Definition: context_vk.h:150
impeller::DeviceBufferVK::GetBuffer
vk::Buffer GetBuffer() const
Definition: device_buffer_vk.cc:98
impeller::SamplerVK
Definition: sampler_vk.h:18
impeller::SamplerVK::CreateVariantForConversion
std::shared_ptr< SamplerVK > CreateVariantForConversion(std::shared_ptr< YUVConversionVK > conversion) const
Definition: sampler_vk.cc:118
impeller::Texture
Definition: texture.h:17
impeller::Texture::GetTextureDescriptor
const TextureDescriptor & GetTextureDescriptor() const
Definition: texture.cc:57
impeller::Texture::mipmap_generated_
bool mipmap_generated_
Definition: texture.h:79
impeller::TextureVK::GetImageView
vk::ImageView GetImageView() const
Definition: texture_vk.cc:173
impeller::TextureVK::GetTextureSource
std::shared_ptr< const TextureSourceVK > GetTextureSource() const
Definition: texture_vk.cc:177
impeller::TextureVK::IsSwapchainImage
bool IsSwapchainImage() const
Definition: texture_vk.cc:221
impeller::TextureVK::GetRenderTargetView
vk::ImageView GetRenderTargetView() const
Definition: texture_vk.cc:195
impeller::TextureVK::SetCachedFramebuffer
void SetCachedFramebuffer(const SharedHandleVK< vk::Framebuffer > &framebuffer)
Definition: texture_vk.cc:199
impeller::TextureVK::SetMipMapGenerated
void SetMipMapGenerated()
Definition: texture_vk.cc:217
impeller::TextureVK::GetCachedRenderPass
SharedHandleVK< vk::RenderPass > GetCachedRenderPass() const
Definition: texture_vk.cc:213
impeller::TextureVK::SetLayoutWithoutEncoding
vk::ImageLayout SetLayoutWithoutEncoding(vk::ImageLayout layout) const
Definition: texture_vk.cc:185
impeller::TextureVK::GetImmutableSamplerVariant
std::shared_ptr< SamplerVK > GetImmutableSamplerVariant(const SamplerVK &sampler) const
Definition: texture_vk.cc:225
impeller::TextureVK::GetSize
ISize GetSize() const override
Definition: texture_vk.cc:165
impeller::TextureVK::TextureVK
TextureVK(std::weak_ptr< Context > context, std::shared_ptr< TextureSourceVK > source)
Definition: texture_vk.cc:14
impeller::TextureVK::GetCachedFramebuffer
SharedHandleVK< vk::Framebuffer > GetCachedFramebuffer() const
Definition: texture_vk.cc:209
impeller::TextureVK::SetLayout
bool SetLayout(const BarrierVK &barrier) const
Definition: texture_vk.cc:181
impeller::TextureVK::GetLayout
vk::ImageLayout GetLayout() const
Definition: texture_vk.cc:191
impeller::TextureVK::SetCachedRenderPass
void SetCachedRenderPass(const SharedHandleVK< vk::RenderPass > &render_pass)
Definition: texture_vk.cc:204
impeller::TextureVK::~TextureVK
~TextureVK() override
impeller::TextureVK::GetImage
vk::Image GetImage() const
Definition: texture_vk.cc:169
command_buffer_vk.h
formats_vk.h
impeller
Definition: allocation.cc:12
impeller::SharedHandleVK
std::shared_ptr< SharedObjectVKT< T > > SharedHandleVK
Definition: shared_object_vk.h:53
impeller::HasValidationLayers
bool HasValidationLayers()
Definition: context_vk.cc:53
impeller::ToImageAspectFlags
constexpr vk::ImageAspectFlags ToImageAspectFlags(PixelFormat format)
Definition: formats_vk.h:586
std
Definition: comparable.h:95
sampler_vk.h
impeller::BarrierVK
Defines an operations and memory access barrier on a resource.
Definition: barrier_vk.h:27
impeller::TSize
Definition: size.h:25
impeller::TextureDescriptor::size
ISize size
Definition: texture_descriptor.h:42
texture_descriptor.h
texture_vk.h
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:91