HoviTron Video Pipeline
BuffersControllerBlending.cpp
1/* ----------------------
2* Copyright 2023 Université Libre de Bruxelles(ULB), Universidad Politécnica de Madrid(UPM), CREAL, Deutsches Zentrum für Luft - und Raumfahrt(DLR)
3
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at < http://www.apache.org/licenses/LICENSE-2.0>
7
8* Unless required by applicable law or agreed to in writing, software
9* distributed under the License is distributed on an "AS IS" BASIS,
10* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11* See the License for the specific language governing permissionsand
12* limitations under the License.
13---------------------- */
14
15
19
20#include"VulkanContext.h"
21#include"VulkanRenderPass.h"
22#include"VulkanWrapper.h"
23
24
26{
27 this->context = context;
28 this->renderpass = renderpass;
29 this->pipeline = pipeline;
30 this->inputView = inputView;
31 this->wrapper = wraps;
32
33 attachmentCount = wrapper->multiviewSetup ? wrapper->getViewNumber() : wrapper->getAttachmentSize();
34}
35
37{
38 if (inputView == 0) {
39 createVertexBuffer();
40 createIndexBuffer();
41 }
42 createUniformBuffer(attachmentCount);
43 createDescriptorPool();
44 createDescriptorSets();
45}
46
47void BufferControllerBlending::createVertexBuffer()
48{
49 std::vector<glm::vec4> vert = {
50 {-1.0f, 1.0f, 0.0f, 1.0f},
51 {-1.0f, -1.0f, 0.0f, 0.0f},
52 {1.0f, -1.0f, 1.0f, 0.0f},
53 {1.0f, 1.0f, 1.0f, 1.0f}};
54
55 vk::DeviceSize bufferSize = sizeof(glm::vec4) * vert.size();
56
57 vk::Buffer stagingBuffer;
58 vk::DeviceMemory stagingBufferMemory;
59
60 createBuffer(bufferSize, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent, stagingBuffer, stagingBufferMemory, context->device, context->physicalDevice);
61
62 // copy the vertex and color data into that device memory
63 void* data;
64 context->device.mapMemory(stagingBufferMemory, 0, bufferSize, {}, &data);
65 memcpy(data, vert.data(), (size_t)bufferSize);
66 context->device.unmapMemory(stagingBufferMemory);
67
68 createBuffer(bufferSize, vk::BufferUsageFlagBits::eTransferDst | vk::BufferUsageFlagBits::eVertexBuffer, vk::MemoryPropertyFlagBits::eDeviceLocal, vertexBuffer, vertexBufferMemory, context->device, context->physicalDevice);
69
70 copyBuffer(stagingBuffer, vertexBuffer, bufferSize);
71
72 context->device.destroyBuffer(stagingBuffer, nullptr);
73 context->device.freeMemory(stagingBufferMemory, nullptr);
74}
75
76void BufferControllerBlending::createIndexBuffer()
77{
78 indices = std::vector<uint32_t>{
79 0, 2, 1, 0, 3, 2
80 };
81
82 indiceCount = static_cast<uint32_t>(indices.size());
83
84 vk::DeviceSize bufferSize = sizeof(indices[0]) * indices.size();
85 vk::Buffer stagingBuffer;
86 vk::DeviceMemory stagingBufferMemory;
87 createBuffer(bufferSize, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent, stagingBuffer, stagingBufferMemory, context->device, context->physicalDevice);
88
89 void* data;
90 context->device.mapMemory(stagingBufferMemory, 0, bufferSize, {}, &data);
91 memcpy(data, indices.data(), (size_t)bufferSize);
92 context->device.unmapMemory(stagingBufferMemory);
93
94 createBuffer(bufferSize, vk::BufferUsageFlagBits::eTransferDst | vk::BufferUsageFlagBits::eIndexBuffer, vk::MemoryPropertyFlagBits::eDeviceLocal, indexBuffer, indexBufferMemory, context->device, context->physicalDevice);
95
96 copyBuffer(stagingBuffer, indexBuffer, bufferSize);
97
98 context->device.destroyBuffer(stagingBuffer, nullptr);
99 context->device.freeMemory(stagingBufferMemory, nullptr);
100}
101
102void BufferControllerBlending::createUniformBuffer(int size)
103{
104 VkDeviceSize bufferSize = sizeof(BlendingParameters);
105
106 uniformBuffers.resize(size);
107 uniformBuffersMemory.resize(size);
108
109 for (size_t i = 0; i < size; i++) {
110 createBuffer(bufferSize, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent, uniformBuffers[i], uniformBuffersMemory[i], context->device, context->physicalDevice);
111 }
112}
113
114void BufferControllerBlending::createDescriptorPool()
115{
116 std::array<vk::DescriptorPoolSize, 6> poolSizes{};
117 poolSizes[0] = vk::DescriptorPoolSize(vk::DescriptorType::eUniformBuffer, static_cast<uint32_t> (attachmentCount));
118 poolSizes[1] = vk::DescriptorPoolSize(vk::DescriptorType::eInputAttachment, static_cast<uint32_t> (attachmentCount));
119 poolSizes[2] = vk::DescriptorPoolSize(vk::DescriptorType::eInputAttachment, static_cast<uint32_t> (attachmentCount));
120 poolSizes[3] = vk::DescriptorPoolSize(vk::DescriptorType::eInputAttachment, static_cast<uint32_t> (attachmentCount));
121 poolSizes[4] = vk::DescriptorPoolSize(vk::DescriptorType::eInputAttachment, static_cast<uint32_t> (attachmentCount));
122 poolSizes[5] = vk::DescriptorPoolSize(vk::DescriptorType::eInputAttachment, static_cast<uint32_t> (attachmentCount));
123
124 vk::DescriptorPoolCreateInfo poolInfo(
125 vk::DescriptorPoolCreateFlags(), //flags
126 static_cast<uint32_t>(attachmentCount), // max sets
127 static_cast<uint32_t>(poolSizes.size()), //pool size
128 poolSizes.data() //pPoolSize
129 );
130
131 descriptorPool = context->device.createDescriptorPool(poolInfo);
132}
133
134void BufferControllerBlending::createDescriptorSets()
135{
136 std::vector<vk::DescriptorSetLayout> layouts(attachmentCount, pipeline->descriptorSetLayout);
137
138 vk::DescriptorSetAllocateInfo allocInfo(descriptorPool, static_cast<uint32_t>(attachmentCount), layouts.data());
139
140 descriptorSets = context->device.allocateDescriptorSets(allocInfo);
141
142 for (size_t i = 0; i < attachmentCount; i++) {
143 vk::DescriptorBufferInfo bufferInfo(uniformBuffers[i], 0, sizeof(BlendingParameters));
144
145 vk::DescriptorImageInfo imageInfo(nullptr, renderpass->attachementColor[i].imageView, vk::ImageLayout::eShaderReadOnlyOptimal);
146 vk::DescriptorImageInfo qualityInfo(nullptr, renderpass->attachementQualityFloat[i].imageView, vk::ImageLayout::eShaderReadOnlyOptimal);
147 vk::DescriptorImageInfo depthInfo(nullptr, renderpass->attachementDepthFloat[i].imageView, vk::ImageLayout::eShaderReadOnlyOptimal);
148
149 vk::DescriptorImageInfo accuImageInfo(nullptr, renderpass->attachementAccuColor[i].imageView, vk::ImageLayout::eShaderReadOnlyOptimal);
150 vk::DescriptorImageInfo accuQualityInfo(nullptr, renderpass->attachementAccuQuality[i].imageView, vk::ImageLayout::eShaderReadOnlyOptimal);
151
152 vk::DescriptorImageInfo accuDepthInfo;
153
154 if(inputView % 2 == 1){
155 accuImageInfo.imageView = renderpass->attachementAccuColor2[i].imageView;
156 accuImageInfo.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
157
158 accuQualityInfo.imageView = renderpass->attachementAccuQuality2[i].imageView;
159 accuQualityInfo.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
160 }
161
162
163 if (wrapper->isDepthOutputRecquired()) {
164 if (inputView % 2 == 1) {
165 accuDepthInfo = vk::DescriptorImageInfo(nullptr, renderpass->attachementAccuDepth2[i].imageView, vk::ImageLayout::eShaderReadOnlyOptimal);
166 }
167 else {
168 accuDepthInfo = vk::DescriptorImageInfo(nullptr, renderpass->attachementAccuDepth[i].imageView, vk::ImageLayout::eShaderReadOnlyOptimal);
169 }
170 }
171
172 std::vector<vk::WriteDescriptorSet> descriptorWrites{};
173
174
175 if (wrapper->isDepthOutputRecquired()) {
176 descriptorWrites.resize(7);
177 }
178 else {
179 descriptorWrites.resize(6);
180 }
181 descriptorWrites[0] = vk::WriteDescriptorSet(
182 descriptorSets[i],
183 1, //dstBinding
184 0, //dstArrayElement
185 1, //descriptorCount
186 vk::DescriptorType::eUniformBuffer, //descriptorType
187 nullptr, //pImageInfo
188 &bufferInfo, // pBufferInfo
189 nullptr //pTexelBufferView
190 );
191 descriptorWrites[1] = vk::WriteDescriptorSet(
192 descriptorSets[i],
193 3, //dstBinding
194 0, //dstArrayElement
195 1, //descriptorCount
196 vk::DescriptorType::eInputAttachment, //descriptorType
197 &imageInfo, //pImageInfo
198 nullptr, // pBufferInfo
199 nullptr //pTexelBufferView
200 );
201 descriptorWrites[2] = vk::WriteDescriptorSet(
202 descriptorSets[i],
203 5, //dstBinding
204 0, //dstArrayElement
205 1, //descriptorCount
206 vk::DescriptorType::eInputAttachment, //descriptorType
207 &qualityInfo, //pImageInfo
208 nullptr, // pBufferInfo
209 nullptr //pTexelBufferView
210 );
211 descriptorWrites[3] = vk::WriteDescriptorSet(
212 descriptorSets[i],
213 6, //dstBinding
214 0, //dstArrayElement
215 1, //descriptorCount
216 vk::DescriptorType::eInputAttachment, //descriptorType
217 &depthInfo, //pImageInfo
218 nullptr, // pBufferInfo
219 nullptr //pTexelBufferView
220 );
221 descriptorWrites[4] = vk::WriteDescriptorSet(
222 descriptorSets[i],
223 2, //dstBinding
224 0, //dstArrayElement
225 1, //descriptorCount
226 vk::DescriptorType::eInputAttachment, //descriptorType
227 &accuImageInfo, //pImageInfo
228 nullptr, // pBufferInfo
229 nullptr //pTexelBufferView
230 );
231 descriptorWrites[5] = vk::WriteDescriptorSet(
232 descriptorSets[i],
233 4, //dstBinding
234 0, //dstArrayElement
235 1, //descriptorCount
236 vk::DescriptorType::eInputAttachment, //descriptorType
237 &accuQualityInfo, //pImageInfo
238 nullptr, // pBufferInfo
239 nullptr //pTexelBufferView
240 );
241
242 if (wrapper->isDepthOutputRecquired()) {
243 descriptorWrites[6] = vk::WriteDescriptorSet(
244 descriptorSets[i],
245 7, //dstBinding
246 0, //dstArrayElement
247 1, //descriptorCount
248 vk::DescriptorType::eInputAttachment, //descriptorType
249 &accuDepthInfo, //pImageInfo
250 nullptr, // pBufferInfo
251 nullptr //pTexelBufferView
252 );
253 }
254 context->device.updateDescriptorSets(static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr);
255
256 }
257}
258
259void BufferControllerBlending::bindBuffers(vk::CommandBuffer& commandBuffer, int currentSwapIndex, InputProvider::StreamFrameInfo & frameInfos, int view)
260{
261 int index = wrapper->multiviewSetup ? view : currentSwapIndex ;
262 vk::Buffer vertexBuffers[] = { vertexBuffer };
263 vk::DeviceSize offsets[] = { 0 };
264 commandBuffer.bindVertexBuffers(0, 1, vertexBuffers, offsets);
265 commandBuffer.bindIndexBuffer(indexBuffer, 0, vk::IndexType::eUint32);
266
267 commandBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipeline->pipelineLayout, 0, 1, &descriptorSets[index], 0, nullptr);
268}
269
270void BufferControllerBlending::updateUniformBuffer(uint32_t currentImage, int view)
271{
272 //nothing to update for the moment
273};
274void BufferControllerBlending::updateAllUniformBuffer(uint32_t currentImage, int view)
275{
276 int index = wrapper->multiviewSetup ? view : currentImage;
277
278 this->blendingParam.blendingFactor = wrapper->params.blendingFactor;
279 this->blendingParam.ZNearHeadset = wrapper->params.nearPlaneHeadset;
280 this->blendingParam.ZFarHeadset = wrapper->params.farPlaneHeadset;
281 this->blendingParam.ZFar = wrapper->params.max_depth;
282 this->blendingParam.maxMul = wrapper->params.maxMult;
283 this->blendingParam.scaleFactor = wrapper->params.scaleFactor;
284
285 //float alphaBlend = blendingFactor;
286 void* data;
287 context->device.mapMemory(uniformBuffersMemory[index], 0, sizeof(BlendingParameters), {}, &data);
288 memcpy(data, &this->blendingParam, sizeof(BlendingParameters));
289 context->device.unmapMemory(uniformBuffersMemory[index]);
290}
291
293{
294 for (size_t i = 0; i < uniformBuffers.size(); i++) {
295 context->device.destroyBuffer(uniformBuffers[i], nullptr);
296 context->device.freeMemory(uniformBuffersMemory[i], nullptr);
297 }
298
299 if (inputView == 0) {
300 context->device.destroyBuffer(vertexBuffer);
301 context->device.freeMemory(vertexBufferMemory, nullptr);
302
303 context->device.destroyBuffer(indexBuffer);
304 context->device.freeMemory(indexBufferMemory, nullptr);
305 }
306
307 context->device.destroyDescriptorPool(descriptorPool);
308}
309
310vk::VertexInputBindingDescription BufferControllerBlending::getBindingDescription()
311{
312 vk::VertexInputBindingDescription bindingDescription{
313 0, //binding
314 sizeof(glm::vec4), // stride
315 vk::VertexInputRate::eVertex //inputRate
316 };
317 return bindingDescription;
318}
319
320std::vector<vk::VertexInputAttributeDescription> BufferControllerBlending::getAttributeDescription()
321{
322 std::vector<vk::VertexInputAttributeDescription> attributeDescriptions{
323 vk::VertexInputAttributeDescription(
324 0, //location
325 0, //binding
326 vk::Format::eR32G32B32A32Sfloat, //format
327 0 //offset
328 ) };
329 return attributeDescriptions;
330}
331
332void BufferControllerBlending::update(std::span<InputProvider::StreamFrameInfo> frameInfo, int view)
333{
334 //Does nothing for blending
335
336 //in OMAF rotation vector is rotation against z axis, y axis, and x axis
337 auto R_from = glmEulerAnglesDegreeToRotationMatrix(frameInfo[view].extrinsics.rotation);
338 //------------ Virtual camera parameter may not be in OMAF but can be converted to it using the conversion at wrapper->params.conversionToOMAF
339 // (in general it would be openxr coordinate system)
340 // and the rotation is defined as rotation against x axis, y axis, z axis
341 auto R_start = glmEulerAnglesDegreeToRotationMatrixNotOMAF(wrapper->params.getStartingRotation());
342 auto R_to = glmEulerAnglesDegreeToRotationMatrixNotOMAF(wrapper->params.getVirtualExtrinsics(view).rotation);
343 R_to = (R_start * R_to * glm::transpose(R_start)) * R_start;
344 R_to = wrapper->params.conversionToOMAF * R_to * glm::transpose(wrapper->params.conversionToOMAF);
345
346 auto R = glm::transpose(R_to) * R_from;
347
348 auto t_from = frameInfo[view].extrinsics.position;
349 auto t_start = wrapper->params.getStartingPosition();
350 auto t_to = wrapper->params.getVirtualExtrinsics(view).position;
351 t_to = t_start + R_start * t_to;// *glm::transpose(R_start); //
352
353 t_to = wrapper->params.conversionToOMAF * t_to;
354 glm::vec3 T = -glm::transpose(R_to) * (t_to - t_from);
355 this->blendingParam.inputDistance = std::max(0.01f, glm::length(T));
356}
357
359{
360 return indiceCount;
361}
File that contains class and struct for the management of the ressources for the blending pipeline.
File that contain the VulkanContext class to manage Vulkan Instance, Physical device,...
Class that contains helper functions for Vulkan.
file that conthains a class that manages the pipeline for the blending
file that contains the class that manage the renderPass containing the synthesis and blending steps
file that contains the VulkanWrapper class that manages the classes related to Vulkan code and ease t...
void updateAllUniformBuffer(uint32_t currentImage, int view) override
void update(std::span< InputProvider::StreamFrameInfo > infos, int view) override
void bindBuffers(vk::CommandBuffer &commandBuffer, int index, InputProvider::StreamFrameInfo &frameInfo, int view) override
BufferControllerBlending(VulkanContext *context, VulkanRenderPass *renderpass, VulkanPipelineBlending *pipeline, VulkanWrapper *wraps, int inputView)
vk::VertexInputBindingDescription getBindingDescription() override
void updateUniformBuffer(uint32_t currentImage, int view) override
std::vector< vk::VertexInputAttributeDescription > getAttributeDescription() override
static std::vector< uint32_t > indices
void copyBuffer(vk::Buffer srcBuffer, vk::Buffer dstBuffer, vk::DeviceSize size)
VulkanRenderPass * renderpass
const InputProvider::Extrinsics getVirtualExtrinsics(int view)
const glm::mat3x3 conversionToOMAF
const glm::vec3 getStartingPosition()
const glm::vec3 getStartingRotation()
class that manages tasks related to Vulkan context (Vulkan Instance, Vulkan Physical device,...
Definition: VulkanContext.h:59
vk::PhysicalDevice physicalDevice
Definition: VulkanContext.h:85
vk::Device device
Definition: VulkanContext.h:87
vk::DescriptorSetLayout descriptorSetLayout
vk::PipelineLayout pipelineLayout
Class that manages a graphics pipeline for the blending.
Class that manage the renderPass containing the synthesis and blending steps.
std::vector< ImageStruct > attachementAccuQuality2
std::vector< ImageStruct > attachementAccuColor2
std::vector< ImageStruct > attachementDepthFloat
std::vector< ImageStruct > attachementAccuDepth2
std::vector< ImageStruct > attachementQualityFloat
std::vector< ImageStruct > attachementAccuDepth
std::vector< ImageStruct > attachementAccuColor
std::vector< ImageStruct > attachementAccuQuality
std::vector< ImageStruct > attachementColor
Class that manages the classes related to Vulkan code and act as a wrapper around them.
Definition: VulkanWrapper.h:66
bool isDepthOutputRecquired()
const bool multiviewSetup
RenderingParameters params
Struct that contains value to be sent to the fragment shader of the blending pipeline.