UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
vulkan_transfer_image.cpp
Go to the documentation of this file.
1
5/*
6 * Copyright (c) 2021-2023 CESNET, z. s. p. o.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, is permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * 3. Neither the name of CESNET nor the names of its contributors may be
21 * used to endorse or promote products derived from this software without
22 * specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
26 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
28 * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
34 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
35 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
39
40using namespace vulkan_display_detail;
41using namespace vulkan_display;
42
43namespace {
44
45/*constexpr vk::DeviceSize add_padding(vk::DeviceSize size, vk::DeviceSize allignment) {
46 vk::DeviceSize remainder = size % allignment;
47 if (remainder == 0) {
48 return size;
49 }
50 return size + allignment - remainder;
51}*/
52
53
57template<typename T>
58constexpr bool flags_present(T provided_flags, T required_flags) {
59 return (provided_flags & required_flags) == required_flags;
60}
61
62uint32_t get_memory_type(
63 uint32_t memory_type_bits,
64 vk::MemoryPropertyFlags requested_properties, vk::MemoryPropertyFlags optional_properties,
65 vk::PhysicalDevice gpu)
66{
67 uint32_t possible_memory_type = UINT32_MAX;
68 auto supported_properties = gpu.getMemoryProperties();
69 for (uint32_t i = 0; i < supported_properties.memoryTypeCount; i++) {
70 // if i-th bit in memory_type_bits is set, than i-th memory type can be used
71 bool is_type_usable = (1u << i) & memory_type_bits;
72 auto& mem_type = supported_properties.memoryTypes[i];
73 if (flags_present(mem_type.propertyFlags, requested_properties) && is_type_usable) {
74 if (flags_present(mem_type.propertyFlags, optional_properties)) {
75 return i;
76 }
77 possible_memory_type = i;
78 }
79 }
80 if (possible_memory_type != UINT32_MAX) {
81 return possible_memory_type;
82 }
83 throw VulkanError{"No available memory for transfer images found."};
84}
85
86} //namespace -------------------------------------------------------------
87
88namespace vulkan_display_detail{
89
92 return { description.size.width / 2, description.size.height };
93 }
94 return description.size;
95}
96
97void TransferImageImpl::init(vk::Device device, uint32_t id) {
98 this->id = id;
99 vk::FenceCreateInfo fence_info{};
100 is_available_fence = device.createFence(fence_info);
101}
102
104 vk::Extent2D size, vk::Format format, vk::ImageUsageFlags usage,
105 vk::AccessFlags initial_access, InitialImageData preinitialised, MemoryLocation memory_location)
106{
107 vk::ImageTiling tiling;
108 vk::MemoryPropertyFlags requested_properties;
109 vk::MemoryPropertyFlags optional_properties;
110
111 using MemBits = vk::MemoryPropertyFlagBits;
112 if (memory_location == MemoryLocation::host_local){
113 tiling = vk::ImageTiling::eLinear;
114 requested_properties = MemBits::eHostVisible | MemBits::eHostCoherent;
115 optional_properties = MemBits::eHostCached;
116 }
117 else{
118 tiling = vk::ImageTiling::eOptimal;
119 requested_properties = {};
120 optional_properties = MemBits::eDeviceLocal;
121 }
122 this->init(context, size, format, usage, initial_access, preinitialised, tiling, requested_properties, optional_properties);
123}
124
125void Image2D::init(VulkanContext& context, vk::Extent2D size, vk::Format format, vk::ImageUsageFlags usage,
126 vk::AccessFlags initial_access, InitialImageData preinitialised, vk::ImageTiling tiling,
127 vk::MemoryPropertyFlags requested_properties, vk::MemoryPropertyFlags optional_properties)
128{
129 this->format = format;
130 this->size = size;
131 this->access = initial_access;
132 this->layout = preinitialised == InitialImageData::preinitialised ?
133 vk::ImageLayout::ePreinitialized :
134 vk::ImageLayout::eUndefined;
135 this->view = nullptr;
136
137 vk::Device device = context.get_device();
138 vk::ImageCreateInfo image_info{};
139 image_info
140 .setImageType(vk::ImageType::e2D)
141 .setExtent(vk::Extent3D{ size, 1 })
142 .setMipLevels(1)
143 .setArrayLayers(1)
144 .setFormat(format)
145 .setTiling(tiling)
146 .setInitialLayout(layout)
147 .setUsage(usage)
148 .setSharingMode(vk::SharingMode::eExclusive)
149 .setSamples(vk::SampleCountFlagBits::e1);
150 image = device.createImage(image_info);
151
152 vk::MemoryRequirements memory_requirements = device.getImageMemoryRequirements(image);
153 byte_size = memory_requirements.size;
154
155 uint32_t memory_type = get_memory_type(memory_requirements.memoryTypeBits,
156 requested_properties, optional_properties, context.get_gpu());
157
158 vk::MemoryAllocateInfo allocInfo{ byte_size , memory_type };
159 memory = device.allocateMemory(allocInfo);
160
161 device.bindImageMemory(image, memory, 0);
162}
163
164vk::ImageView Image2D::get_image_view(vk::Device device, vk::SamplerYcbcrConversion conversion) {
165 if(!view){
166 assert(image);
167 vk::ImageViewCreateInfo view_info =
169 view_info.setImage(image);
170
171 vk::SamplerYcbcrConversionInfo yCbCr_info{ conversion };
172 view_info.setPNext(conversion ? &yCbCr_info : nullptr);
173 view = device.createImageView(view_info);
174 }
175 return view;
176}
177
178void Image2D::destroy(vk::Device device) {
179 device.destroy(view);
180 view = nullptr;
181 device.destroy(image);
182 image = nullptr;
183
184 if (memory) {
185 device.freeMemory(memory);
186 }
187}
188
190 assert(id != NO_ID);
191 buffer.destroy(context.get_device());
192
193 auto device = context.get_device();
194
195 buffer.init(context, get_buffer_size(description), description.format_info().buffer_format, vk::ImageUsageFlagBits::eSampled, vk::AccessFlagBits::eHostWrite,
197
198 void* void_ptr = device.mapMemory(buffer.memory, 0, buffer.byte_size);
199 if (void_ptr == nullptr) {
200 throw VulkanError{"Image memory cannot be mapped."};
201 }
202 ptr = reinterpret_cast<unsigned char*>(void_ptr);
203
204 vk::ImageSubresource subresource{ vk::ImageAspectFlagBits::eColor, 0, 0 };
205 row_pitch = device.getImageSubresourceLayout(buffer.image, subresource).rowPitch;
206
208}
209
210vk::ImageMemoryBarrier Image2D::create_memory_barrier(
211 vk::ImageLayout new_layout, vk::AccessFlags new_access_mask,
212 uint32_t src_queue_family_index, uint32_t dst_queue_family_index)
213{
214 vk::ImageMemoryBarrier memory_barrier{};
215 memory_barrier
216 .setImage(image)
217 .setOldLayout(layout)
218 .setNewLayout(new_layout)
219 .setSrcAccessMask(access)
220 .setDstAccessMask(new_access_mask)
221 .setSrcQueueFamilyIndex(src_queue_family_index)
222 .setDstQueueFamilyIndex(dst_queue_family_index);
223 memory_barrier.subresourceRange
224 .setAspectMask(vk::ImageAspectFlagBits::eColor)
225 .setLayerCount(1)
226 .setLevelCount(1);
227
228 layout = new_layout;
229 access = new_access_mask;
230 return memory_barrier;
231}
232
234 if (preprocess_fun) {
236 preprocess_fun(img);
237 img.set_process_function(nullptr);
238 }
239}
240
241void TransferImageImpl::destroy(vk::Device device) {
242 device.unmapMemory(buffer.memory);
243 buffer.destroy(device);
244 device.destroy(is_available_fence);
245}
246
247} //vulkan_display_detail
void init(VulkanContext &context, vk::Extent2D size, vk::Format format, vk::ImageUsageFlags usage, vk::AccessFlags initial_access, InitialImageData preinitialised, MemoryLocation memory_location)
vk::ImageMemoryBarrier create_memory_barrier(vk::ImageLayout new_layout, vk::AccessFlags new_access_mask, uint32_t src_queue_family_index=VK_QUEUE_FAMILY_IGNORED, uint32_t dst_queue_family_index=VK_QUEUE_FAMILY_IGNORED)
vk::ImageView get_image_view(vk::Device device, vk::SamplerYcbcrConversion conversion)
void recreate(VulkanContext &context, vulkan_display::ImageDescription description)
void init(vk::Device device, uint32_t id)
vulkan_display::ImageDescription image_description
void usage()
Definition main.cpp:28
vk::Extent2D get_buffer_size(const vulkan_display::ImageDescription &description)
vk::ImageViewCreateInfo default_image_view_create_info(vk::Format format)
const char * description
Definition cineform.cpp:126