MythTV master
mythtexturevulkan.cpp
Go to the documentation of this file.
1// MythTV
4
5#define LOC QString("VulkanTex: ")
6
8 VkSampler Sampler, VkCommandBuffer CommandBuffer)
9{
10 MythTextureVulkan* result = nullptr;
11 if (Image)
12 result = new MythTextureVulkan(Vulkan, Image, Sampler, CommandBuffer);
13
14 if (result && !result->IsValidVulkan())
15 {
16 delete result;
17 result = nullptr;
18 }
19 return result;
20}
21
23 QImage *Image, VkSampler Sampler,
24 VkCommandBuffer CommandBuffer)
25 : MythVulkanObject(Vulkan),
26 MythComboBufferVulkan(Image->width(), Image->height())
27{
28 if (!m_vulkanValid)
29 return;
30
31 // retrieve and check Image data
32 auto datasize = static_cast<VkDeviceSize>((Image->width() * Image->height() * Image->depth()) >> 3);
33 auto datasize2 = Image->sizeInBytes();
34 if (datasize != static_cast<VkDeviceSize>(datasize2))
35 LOG(VB_GENERAL, LOG_WARNING, LOC + "Inconsistent image data size");
36
37 const auto *data = Image->constBits();
38
39 // Create staging buffer
40 if (!m_vulkanRender->CreateBuffer(datasize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
41 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
43 {
44 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create staging buffer");
45 return;
46 }
47
48 // Map memory and copy data
49 void* memory = nullptr;
50 m_vulkanFuncs->vkMapMemory(m_vulkanDevice, m_stagingMemory, 0, datasize, 0, &memory);
51 memcpy(memory, data, static_cast<size_t>(datasize));
53
54 // Create image
55 if (m_vulkanRender->CreateImage(Image->size(), VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_TILING_OPTIMAL,
56 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
57 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, m_image, m_deviceMemory))
58 {
59 VkCommandBuffer commandbuffer = CommandBuffer ? CommandBuffer : m_vulkanRender->CreateSingleUseCommandBuffer();
60
61 // Transition
62 m_vulkanRender->TransitionImageLayout(m_image, VK_IMAGE_LAYOUT_UNDEFINED,
63 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, commandbuffer);
64 m_vulkanRender->CopyBufferToImage(m_stagingBuffer, m_image, static_cast<uint32_t>(Image->width()),
65 static_cast<uint32_t>(Image->height()), commandbuffer);
66 m_vulkanRender->TransitionImageLayout(m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
67 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, commandbuffer);
68
69 // Create sampler if needed
70 if (!Sampler)
71 {
72 m_sampler = m_vulkanRender->CreateSampler(VK_FILTER_LINEAR, VK_FILTER_LINEAR);
73 m_createdSampler = true;
74 }
75 else
76 {
77 m_sampler = Sampler;
78 }
79
80 // Create image view
81 VkImageViewCreateInfo viewinfo { };
82 viewinfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
83 viewinfo.image = m_image;
84 viewinfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
85 viewinfo.format = VK_FORMAT_B8G8R8A8_UNORM;
86 viewinfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
87 viewinfo.subresourceRange.baseMipLevel = 0;
88 viewinfo.subresourceRange.levelCount = 1;
89 viewinfo.subresourceRange.baseArrayLayer = 0;
90 viewinfo.subresourceRange.layerCount = 1;
91 if (m_vulkanFuncs->vkCreateImageView(m_vulkanDevice, &viewinfo, nullptr, &m_view) != VK_SUCCESS)
92 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create image view");
93
94 m_dataSize = datasize;
96
97 if (!CommandBuffer)
99 }
100 else
101 {
102 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create texture image");
103 }
104
105 // If this is a single use command buffer, staging is complete and we can
106 // release the staging resources
107 if (!CommandBuffer)
109}
110
112{
113 if (m_descriptor)
114 LOG(VB_GENERAL, LOG_WARNING, LOC + "Texture has not returned descriptor");
115
116 if (m_vulkanValid)
117 {
120 m_vulkanFuncs->vkDestroySampler(m_vulkanDevice, m_sampler, nullptr);
121 m_vulkanFuncs->vkDestroyImageView(m_vulkanDevice, m_view, nullptr);
122 m_vulkanFuncs->vkDestroyImage(m_vulkanDevice, m_image, nullptr);
123 m_vulkanFuncs->vkFreeMemory(m_vulkanDevice, m_deviceMemory, nullptr);
124 }
125}
126
128{
129 m_vulkanFuncs->vkDestroyBuffer(m_vulkanDevice, m_stagingBuffer, nullptr);
130 m_vulkanFuncs->vkFreeMemory(m_vulkanDevice, m_stagingMemory, nullptr);
133}
134
135VkDescriptorImageInfo MythTextureVulkan::GetDescriptorImage(void) const
136{
137 return { m_sampler, m_view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL };
138}
139
140void MythTextureVulkan::AddDescriptor(VkDescriptorSet Descriptor)
141{
142 m_descriptor = Descriptor;
143}
144
146{
147 VkDescriptorSet result = m_descriptor;
149 return result;
150}
bool CreateImage(QSize Size, VkFormat Format, VkImageTiling Tiling, VkImageUsageFlags Usage, VkMemoryPropertyFlags Properties, VkImage &Image, VkDeviceMemory &ImageMemory)
VkSampler CreateSampler(VkFilter Min, VkFilter Mag)
bool CreateBuffer(VkDeviceSize Size, VkBufferUsageFlags Usage, VkMemoryPropertyFlags Properties, VkBuffer &Buffer, VkDeviceMemory &Memory)
void FinishSingleUseCommandBuffer(VkCommandBuffer &Buffer)
void TransitionImageLayout(VkImage &Image, VkImageLayout OldLayout, VkImageLayout NewLayout, VkCommandBuffer CommandBuffer=nullptr)
VkCommandBuffer CreateSingleUseCommandBuffer(void)
void CopyBufferToImage(VkBuffer Buffer, VkImage Image, uint32_t Width, uint32_t Height, VkCommandBuffer CommandBuffer=nullptr)
VkDescriptorImageInfo GetDescriptorImage(void) const
void AddDescriptor(VkDescriptorSet Descriptor)
VkDeviceMemory m_deviceMemory
VkDeviceMemory m_stagingMemory
VkDescriptorSet m_descriptor
VkDescriptorSet TakeDescriptor(void)
MythTextureVulkan(MythVulkanObject *Vulkan, QImage *Image, VkSampler Sampler, VkCommandBuffer CommandBuffer=nullptr)
static MythTextureVulkan * Create(MythVulkanObject *Vulkan, QImage *Image, VkSampler Sampler, VkCommandBuffer CommandBuffer=nullptr)
QVulkanDeviceFunctions * m_vulkanFuncs
MythRenderVulkan * m_vulkanRender
bool IsValidVulkan() const
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
#define MYTH_NULL_DISPATCH
#define LOC