Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 1cf7023

Browse files
authored
[impeller] [vulkan] Support textures backed by vk::Images (#35163)
1 parent 1f9d87d commit 1cf7023

File tree

4 files changed

+143
-3
lines changed

4 files changed

+143
-3
lines changed

impeller/renderer/backend/vulkan/allocator_vk.cc

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ _Pragma("GCC diagnostic ignored \"-Wthread-safety-analysis\"");
1010
#define VMA_IMPLEMENTATION
1111
#include "impeller/renderer/backend/vulkan/allocator_vk.h"
1212
#include "impeller/renderer/backend/vulkan/device_buffer_vk.h"
13+
#include "impeller/renderer/backend/vulkan/formats_vk.h"
14+
#include "impeller/renderer/backend/vulkan/texture_vk.h"
1315

1416
#include <memory>
1517

@@ -61,7 +63,47 @@ bool AllocatorVK::IsValid() const {
6163
std::shared_ptr<Texture> AllocatorVK::CreateTexture(
6264
StorageMode mode,
6365
const TextureDescriptor& desc) {
64-
FML_UNREACHABLE();
66+
auto image_create_info = vk::ImageCreateInfo{};
67+
image_create_info.imageType = vk::ImageType::e2D;
68+
image_create_info.format = ToVKImageFormat(desc.format);
69+
image_create_info.extent.width = desc.size.width;
70+
image_create_info.extent.height = desc.size.height;
71+
image_create_info.samples = ToVKSampleCount(desc.sample_count);
72+
image_create_info.mipLevels = desc.mip_count;
73+
74+
// TODO (kaushikiska): should we read these from desc?
75+
image_create_info.extent.depth = 1;
76+
image_create_info.arrayLayers = 1;
77+
78+
image_create_info.tiling = vk::ImageTiling::eOptimal;
79+
image_create_info.initialLayout = vk::ImageLayout::eUndefined;
80+
image_create_info.usage = vk::ImageUsageFlagBits::eSampled |
81+
vk::ImageUsageFlagBits::eColorAttachment;
82+
83+
VmaAllocationCreateInfo alloc_create_info = {};
84+
alloc_create_info.usage = VMA_MEMORY_USAGE_AUTO;
85+
// docs recommend using `VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT` for image
86+
// allocations, but setting them to be host visible for now.
87+
alloc_create_info.flags =
88+
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
89+
VMA_ALLOCATION_CREATE_MAPPED_BIT;
90+
91+
auto create_info_native =
92+
static_cast<vk::ImageCreateInfo::NativeType>(image_create_info);
93+
94+
VkImage img;
95+
VmaAllocation allocation;
96+
VmaAllocationInfo allocation_info;
97+
auto result = vk::Result{vmaCreateImage(allocator_, &create_info_native,
98+
&alloc_create_info, &img, &allocation,
99+
&allocation_info)};
100+
if (result != vk::Result::eSuccess) {
101+
VALIDATION_LOG << "Unable to allocate an image";
102+
return nullptr;
103+
}
104+
105+
return std::make_shared<TextureVK>(desc, context_, allocator_, img,
106+
allocation, allocation_info);
65107
}
66108

67109
// |Allocator|

impeller/renderer/backend/vulkan/formats_vk.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,4 +132,32 @@ constexpr std::optional<vk::ShaderStageFlagBits> ToVKShaderStageFlagBits(
132132
FML_UNREACHABLE();
133133
}
134134

135+
constexpr vk::Format ToVKImageFormat(PixelFormat format) {
136+
switch (format) {
137+
case PixelFormat::kUnknown:
138+
return vk::Format::eUndefined;
139+
case PixelFormat::kA8UNormInt:
140+
return vk::Format::eA8B8G8R8UnormPack32;
141+
case PixelFormat::kR8G8B8A8UNormInt:
142+
return vk::Format::eR8G8B8A8Unorm;
143+
case PixelFormat::kR8G8B8A8UNormIntSRGB:
144+
return vk::Format::eR8G8B8A8Srgb;
145+
case PixelFormat::kB8G8R8A8UNormInt:
146+
return vk::Format::eB8G8R8A8Unorm;
147+
case PixelFormat::kB8G8R8A8UNormIntSRGB:
148+
return vk::Format::eB8G8R8A8Srgb;
149+
case PixelFormat::kS8UInt:
150+
return vk::Format::eS8Uint;
151+
}
152+
}
153+
154+
constexpr vk::SampleCountFlagBits ToVKSampleCount(SampleCount sample_count) {
155+
switch (sample_count) {
156+
case SampleCount::kCount1:
157+
return vk::SampleCountFlagBits::e1;
158+
case SampleCount::kCount4:
159+
return vk::SampleCountFlagBits::e4;
160+
}
161+
}
162+
135163
} // namespace impeller

impeller/renderer/backend/vulkan/texture_vk.cc

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,63 @@
66

77
namespace impeller {
88

9-
//
9+
TextureVK::TextureVK(TextureDescriptor desc,
10+
ContextVK& context,
11+
const VmaAllocator& allocator,
12+
VkImage image,
13+
VmaAllocation allocation,
14+
VmaAllocationInfo allocation_info)
15+
: Texture(desc),
16+
context_(context),
17+
allocator_(allocator),
18+
image_(image),
19+
allocation_(allocation),
20+
allocation_info_(allocation_info) {}
21+
22+
TextureVK::~TextureVK() {
23+
if (image_) {
24+
vmaDestroyImage(allocator_, image_, allocation_);
25+
}
26+
}
27+
28+
void TextureVK::SetLabel(std::string_view label) {
29+
context_.SetDebugName(vk::Image{image_}, label);
30+
}
31+
32+
bool TextureVK::OnSetContents(const uint8_t* contents,
33+
size_t length,
34+
size_t slice) {
35+
if (!image_ || !contents) {
36+
return false;
37+
}
38+
39+
const auto& desc = GetTextureDescriptor();
40+
41+
// Out of bounds access.
42+
if (length != desc.GetByteSizeOfBaseMipLevel()) {
43+
VALIDATION_LOG << "illegal to set contents for invalid size";
44+
return false;
45+
}
46+
47+
// currently we are only supporting 2d textures, no cube textures etc.
48+
memcpy(allocation_info_.pMappedData, contents, length);
49+
50+
return true;
51+
}
52+
53+
bool TextureVK::OnSetContents(std::shared_ptr<const fml::Mapping> mapping,
54+
size_t slice) {
55+
// Vulkan has no threading restrictions. So we can pass this data along to the
56+
// client rendering API immediately.
57+
return OnSetContents(mapping->GetMapping(), mapping->GetSize(), slice);
58+
}
59+
60+
bool TextureVK::IsValid() const {
61+
return image_;
62+
}
63+
64+
ISize TextureVK::GetSize() const {
65+
return GetTextureDescriptor().size;
66+
}
1067

1168
} // namespace impeller

impeller/renderer/backend/vulkan/texture_vk.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,31 @@
66

77
#include "flutter/fml/macros.h"
88
#include "impeller/base/backend_cast.h"
9+
#include "impeller/renderer/backend/vulkan/context_vk.h"
10+
#include "impeller/renderer/backend/vulkan/vk.h"
911
#include "impeller/renderer/texture.h"
1012

1113
namespace impeller {
1214

1315
class TextureVK final : public Texture, public BackendCast<TextureVK, Texture> {
1416
public:
15-
TextureVK(TextureDescriptor desc);
17+
TextureVK(TextureDescriptor desc,
18+
ContextVK& context,
19+
const VmaAllocator& allocator,
20+
VkImage image,
21+
VmaAllocation allocation,
22+
VmaAllocationInfo allocation_info);
1623

1724
// |Texture|
1825
~TextureVK() override;
1926

2027
private:
28+
ContextVK& context_;
29+
const VmaAllocator& allocator_;
30+
VkImage image_;
31+
VmaAllocation allocation_;
32+
VmaAllocationInfo allocation_info_;
33+
2134
// |Texture|
2235
void SetLabel(std::string_view label) override;
2336

0 commit comments

Comments
 (0)