21#define _USE_MATH_DEFINES
24#include <glm/gtc/quaternion.hpp>
29uint32_t findMemoryType(vk::PhysicalDevice& physicalDevice, uint32_t typeFilter, vk::MemoryPropertyFlags properties)
31 vk::PhysicalDeviceMemoryProperties memProperties = physicalDevice.getMemoryProperties();
32 for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
33 if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) {
37 throw std::runtime_error(
"failed to find suitable memory type!");
39uint32_t findFastMemoryType(vk::PhysicalDevice& physicalDevice, uint32_t typeFilter, vk::MemoryPropertyFlags properties)
41 vk::PhysicalDeviceMemoryProperties memProperties = physicalDevice.getMemoryProperties();
43 uint32_t memoryType = 0;
46 for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
47 if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) {
53 if ( ((properties & vk::MemoryPropertyFlagBits::eHostVisible) == vk::MemoryPropertyFlagBits::eHostVisible)&& (memProperties.memoryTypes[i].propertyFlags & (vk::MemoryPropertyFlagBits::eDeviceLocal | vk::MemoryPropertyFlagBits::eHostVisible))) {
58 else if ( ((properties & vk::MemoryPropertyFlagBits::eDeviceLocal) == vk::MemoryPropertyFlagBits::eDeviceLocal)&& !(memProperties.memoryTypes[i].propertyFlags & (vk::MemoryPropertyFlagBits::eDeviceLocal | vk::MemoryPropertyFlagBits::eHostVisible))) {
69 throw std::runtime_error(
"failed to find suitable memory type!");
73void createImage(vk::Device& device, vk::PhysicalDevice& physicalDevice, uint32_t width, uint32_t height, vk::Format format, vk::ImageTiling tiling, vk::ImageUsageFlags usage, vk::MemoryPropertyFlags properties, vk::Image& image, vk::DeviceMemory& imageMemory)
75 vk::ImageCreateInfo imageInfo(
76 vk::ImageCreateFlags(),
79 {
static_cast<uint32_t
>(width),
static_cast<uint32_t
>(height), 1 },
82 vk::SampleCountFlagBits::e1,
85 vk::SharingMode::eExclusive
87 imageInfo.initialLayout = vk::ImageLayout::eUndefined;
89 image = device.createImage(imageInfo);
91 vk::MemoryRequirements memRequirement = device.getImageMemoryRequirements(image);
92 vk::MemoryAllocateInfo allocInfo(memRequirement.size, findMemoryType(physicalDevice, memRequirement.memoryTypeBits, properties));
94 imageMemory = device.allocateMemory(allocInfo,
nullptr);
95 device.bindImageMemory(image, imageMemory, 0);
98vk::ImageView createImageView(vk::Device& device, vk::Image image, vk::Format format, vk::ImageAspectFlags aspectFlags)
100 vk::ImageSubresourceRange subRessources(
107 vk::ImageViewCreateInfo viewInfo(
108 vk::ImageViewCreateFlags(),
110 vk::ImageViewType::e2D,
115 return device.createImageView(viewInfo);
117vk::CommandBuffer beginSingleTimeCommands(
VulkanContext* context, vk::CommandPool& commandPool)
119 vk::CommandBufferAllocateInfo allocInfo(commandPool, vk::CommandBufferLevel::ePrimary, 1);
120 vk::CommandBuffer commandBuffer = context->
device.allocateCommandBuffers(allocInfo).front();
122 vk::CommandBufferBeginInfo beginInfo(vk::CommandBufferUsageFlagBits::eOneTimeSubmit);
123 commandBuffer.begin(beginInfo);
125 return commandBuffer;
128void endSingleTimeCommands(
VulkanContext* context, vk::CommandPool& commandPool, vk::CommandBuffer commandBuffer)
132 vk::SubmitInfo submitInfo(0,
nullptr,
nullptr, 1, &commandBuffer);
136 context->
device.freeCommandBuffers(commandPool, 1, &commandBuffer);
139void transitionImageLayout(
VulkanContext* context, vk::CommandPool& commandPool, vk::Image image, vk::Format format, vk::ImageLayout oldLayout, vk::ImageLayout newLayout)
141 vk::CommandBuffer commandBuffer = beginSingleTimeCommands(context, commandPool);
143 vk::ImageAspectFlags aspectMask = vk::ImageAspectFlagBits::eColor;
145 if (newLayout == vk::ImageLayout::eDepthStencilAttachmentOptimal) {
146 aspectMask = vk::ImageAspectFlagBits::eDepth;
149 aspectMask |= vk::ImageAspectFlagBits::eStencil;
153 vk::ImageSubresourceRange subRessources(
160 vk::PipelineStageFlags sourceStage;
161 vk::PipelineStageFlags destinationStage;
162 vk::AccessFlags srcAccess;
163 vk::AccessFlags dstAccess;
165 if (oldLayout == vk::ImageLayout::eUndefined && newLayout == vk::ImageLayout::eTransferDstOptimal) {
167 dstAccess = vk::AccessFlagBits::eTransferWrite;
169 sourceStage = vk::PipelineStageFlagBits::eTopOfPipe;
170 destinationStage = vk::PipelineStageFlagBits::eTransfer;
172 else if (oldLayout == vk::ImageLayout::eTransferDstOptimal && newLayout == vk::ImageLayout::eShaderReadOnlyOptimal) {
173 srcAccess = vk::AccessFlagBits::eTransferWrite;
174 dstAccess = vk::AccessFlagBits::eShaderRead;
176 sourceStage = vk::PipelineStageFlagBits::eTransfer;
177 destinationStage = vk::PipelineStageFlagBits::eFragmentShader;
179 else if (oldLayout == vk::ImageLayout::eUndefined && newLayout == vk::ImageLayout::eShaderReadOnlyOptimal) {
181 dstAccess = vk::AccessFlagBits::eShaderRead;
183 sourceStage = vk::PipelineStageFlagBits::eTopOfPipe;
184 destinationStage = vk::PipelineStageFlagBits::eFragmentShader;
186 else if (oldLayout == vk::ImageLayout::eUndefined && newLayout == vk::ImageLayout::eDepthStencilAttachmentOptimal) {
188 dstAccess = vk::AccessFlagBits::eDepthStencilAttachmentRead | vk::AccessFlagBits::eDepthStencilAttachmentWrite;
190 sourceStage = vk::PipelineStageFlagBits::eTopOfPipe;
191 destinationStage = vk::PipelineStageFlagBits::eEarlyFragmentTests;
193 else if (oldLayout == vk::ImageLayout::eUndefined && newLayout == vk::ImageLayout::eColorAttachmentOptimal) {
196 dstAccess = vk::AccessFlagBits::eColorAttachmentWrite;
198 sourceStage = vk::PipelineStageFlagBits::eTopOfPipe;
199 destinationStage = vk::PipelineStageFlagBits::eColorAttachmentOutput;
203 throw std::invalid_argument(
"unsupported layout transition!");
207 vk::ImageMemoryBarrier barrier(
212 VK_QUEUE_FAMILY_IGNORED,
213 VK_QUEUE_FAMILY_IGNORED,
217 commandBuffer.pipelineBarrier(sourceStage, destinationStage, {}, 0,
nullptr, 0,
nullptr, 1, &barrier);
220 endSingleTimeCommands(context, commandPool, commandBuffer);
224void createFastBuffer(vk::DeviceSize size, vk::BufferUsageFlags usage, vk::MemoryPropertyFlags properties, vk::Buffer& buffer, vk::DeviceMemory& bufferMemory, vk::Device& device, vk::PhysicalDevice& physicalDevice)
227 vk::BufferCreateInfo createInfo(
228 vk::BufferCreateFlags(),
231 vk::SharingMode::eExclusive
233 buffer = device.createBuffer(createInfo);
236 vk::MemoryRequirements memRequirements = device.getBufferMemoryRequirements(buffer);
237 uint32_t memoryTypeIndex = findFastMemoryType(physicalDevice, memRequirements.memoryTypeBits, properties);
238 vk::MemoryAllocateInfo memAllocInfo(memRequirements.size, memoryTypeIndex);
239 bufferMemory = device.allocateMemory(memAllocInfo);
241 device.bindBufferMemory(buffer, bufferMemory, 0);
243void createBuffer(vk::DeviceSize size, vk::BufferUsageFlags usage, vk::MemoryPropertyFlags properties, vk::Buffer& buffer, vk::DeviceMemory& bufferMemory, vk::Device & device, vk::PhysicalDevice & physicalDevice)
246 vk::BufferCreateInfo createInfo(
247 vk::BufferCreateFlags(),
250 vk::SharingMode::eExclusive
252 buffer = device.createBuffer(createInfo);
255 vk::MemoryRequirements memRequirements = device.getBufferMemoryRequirements(buffer);
256 uint32_t memoryTypeIndex = findMemoryType(physicalDevice, memRequirements.memoryTypeBits, properties);
257 vk::MemoryAllocateInfo memAllocInfo(memRequirements.size, memoryTypeIndex);
258 bufferMemory = device.allocateMemory(memAllocInfo);
260 device.bindBufferMemory(buffer, bufferMemory, 0);
265std::vector<uint32_t> generate_picture_EBO(
const glm::vec2 & s)
267 const size_t tileSize = 4;
268 const size_t W = s[0];
269 const size_t H = s[1];
271 const size_t nbOfTileW = (W + tileSize - 1) / tileSize;
272 const size_t nbOfTileH = (H + tileSize - 1) / tileSize;
274 size_t elements_number = 3 * 2 * (H - 1) * (W - 1);
275 std::vector<uint32_t> indices;
276 indices.resize(elements_number);
279 const auto tileOffset = 6 * tileSize * tileSize;
281 for (
size_t yTile = 0; yTile < nbOfTileH ; ++yTile)
283 for (
size_t xTile = 0; xTile < nbOfTileW ; ++xTile)
285 auto yBase = yTile * tileSize;
286 auto xBase = xTile * tileSize;
288 auto currentTileOffset = offset;
290 for (
size_t xd = 0 ; xd < tileSize ; xd++) {
291 for (
size_t yd = 0 ; yd < tileSize ; yd++) {
295 auto currentTileSizeW = std::min(tileSize, W -1 - xBase);
296 if (x < W - 1 && y < H-1) {
297 indices[currentTileOffset + 6 * INDEX_E(xd, yd, (currentTileSizeW)) + 0] = uint32_t(INDEX_E(x, y, W));
298 indices[currentTileOffset + 6 * INDEX_E(xd, yd, (currentTileSizeW)) + 1] = uint32_t(INDEX_E(x + 1, y, W));
299 indices[currentTileOffset + 6 * INDEX_E(xd, yd, (currentTileSizeW)) + 2] = uint32_t(INDEX_E(x, y + 1, W));
301 indices[currentTileOffset + 6 * INDEX_E(xd, yd, (currentTileSizeW)) + 3] = uint32_t(INDEX_E(x, y + 1, W));
302 indices[currentTileOffset + 6 * INDEX_E(xd, yd, (currentTileSizeW)) + 4] = uint32_t(INDEX_E(x + 1, y, W));
303 indices[currentTileOffset + 6 * INDEX_E(xd, yd, (currentTileSizeW)) + 5] = uint32_t(INDEX_E(x + 1, y + 1, W));
312 printf(
"Real number of elements %i\n",
int(elements_number));
316glm::mat3x3 glmRotationMatrixFromRotationAroundX(
float rx)
326 0.f, cos(rx), sin(rx),
327 0.f, -sin(rx), cos(rx));
330glm::mat3x3 glmRotationMatrixFromRotationAroundY(
float ry)
340 cos(ry), 0.f, -sin(ry),
342 sin(ry), 0.f, cos(ry));
345glm::mat3x3 glmRotationMatrixFromRotationAroundZ(
float rz)
354 cos(rz), sin(rz), 0.f,
355 -sin(rz), cos(rz), 0.f,
359glm::mat3x3 glmEulerAnglesDegreeToRotationMatrix(glm::vec3 rotationDegrees)
363 auto const radperdeg = 0.01745329252f;
364 auto rotation = radperdeg * rotationDegrees;
366 glmRotationMatrixFromRotationAroundZ(rotation[0]) *
367 glmRotationMatrixFromRotationAroundY(rotation[1]) *
368 glmRotationMatrixFromRotationAroundX(rotation[2]);
371glm::mat3x3 glmEulerAnglesDegreeToRotationMatrixNotOMAF(glm::vec3 rotationDegrees)
375 auto const radperdeg = 0.01745329252f;
376 auto rotation = radperdeg * rotationDegrees;
377 return glmRotationMatrixFromRotationAroundZ(rotation[2]) *
378 glmRotationMatrixFromRotationAroundY(rotation[1]) *
379 glmRotationMatrixFromRotationAroundX(rotation[0]);
384glm::quat XrQuaternionToGLMQuat(XrQuaternionf & q) {
393XrQuaternionf GLMQuatToXrQuaternion(glm::quat & q) {
406glm::quat ApproximateAverage(std::vector<glm::quat> quaternions) {
407 auto qLength = quaternions.size();
408 const float weightCst = 1.0f / qLength;
409 glm::quat qAvg = { 0.0, 0.0, 0.0, 0.0 };
410 for (
int i = 0; i < qLength; i++) {
411 glm::quat q = quaternions[i];
412 double weight = weightCst;
417 if (i > 0 && glm::dot(quaternions[i], quaternions[0]) < 0.0) {
421 qAvg += glm::quat(weight * q.x, weight * q.y, weight * q.z, weight * q.w);
423 return glm::normalize(qAvg);
426glm::vec3 eulerAngleXYZFromRotationMatrix(glm::mat3x3& matA) {
428 auto mat = glm::transpose(matA);
430 auto R11 = mat[0][0];
431 auto R21 = mat[1][0];
432 auto R31 = mat[2][0];
434 auto R12 = mat[0][1];
435 auto R22 = mat[1][1];
436 auto R32 = mat[2][1];
438 auto R13 = mat[0][2];
439 auto R23 = mat[1][2];
440 auto R33 = mat[2][2];
447 const double pi = std::numbers::pi;
449 const double pi = M_PI;
451 if (std::abs(R31) != 1) {
452 auto t1 = std::asin(R31);
454 theta = std::abs(t1) <= std::abs(t2) ? t1 : t2;
456 auto cost1 = std::cos(t1);
457 auto cost2 = std::cos(t2);
459 auto psi1 = std::atan2(R32/cost1,R33/cost1);
460 auto psi2 = std::atan2(R32 /cost2, R33 /cost2);
461 psi = std::abs(t1) <= std::abs(t2) ? psi1 : psi2;
463 auto phi1 = std::atan2(R21 / cost1, R11 / cost1);
464 auto phi2 = std::atan2(R21 / cost2, R11 / cost2);
465 phi = std::abs(t1) <= std::abs(t2) ? phi1 : phi2;
471 psi = phi + atan2(R12, R13);
474 theta = -1.0f * pi / 2.0f;
475 psi = -1 * phi + atan2(-R12, -R13);
478 return 180.0f * glm::vec3(psi,theta,phi) / (float) pi;
495glm::vec3 quatToEuler(glm::quat q) {
497 glm::vec3 out = {0,0,0};
500 double siny_cosp = 2 * (q.w * q.z + q.x * q.y);
501 double cosy_cosp = 1 - 2 * (q.y * q.y + q.z * q.z);
502 out[2] = std::atan2(siny_cosp, cosy_cosp) * (180.0 / M_PI);
505 double sinp = 2 * (q.w * q.y - q.z * q.x);
506 if (std::abs(sinp) >= 1) {
507 out[1] = std::copysign(M_PI / 2, sinp) * (180.0 / M_PI);
511 out[1] = std::asin(sinp) * (180.0 / M_PI);
515 double sinr_cosp = 2 * (q.w * q.x + q.y * q.z);
516 double cosr_cosp = 1 - 2 * (q.x * q.x + q.y * q.y);
518 out[0] = std::atan2(sinr_cosp, cosr_cosp) * (180.0 / M_PI);
File that contain the VulkanContext class to manage Vulkan Instance, Physical device,...
Class that contains helper functions for Vulkan.
class that manages tasks related to Vulkan context (Vulkan Instance, Vulkan Physical device,...
bool hasStencilComponent(vk::Format format)
file that contains the common include for the Vulkan part