VKKKKKK
VKKKKKK
VKKKKKK
h>
#include <string.h>
#include <vector>
#include <string>
#include <malloc.h>
#include <iostream>
#include <sstream>
#include <assert.h>
#include <algorithm>
#include <fstream>
#ifdef WIN32
#include <Windows.h>
#elif defined(__linux__)
#include <xcb/xcb.h>
#endif
#include "vulkanhelper.h"
#include "raytracing.h"
#define VSYNC
uint32_t memoryType = 0;
for (uint32_t memoryTypeIndex = 0; memoryTypeIndex < VK_MAX_MEMORY_TYPES; +
+memoryTypeIndex) {
memoryType = memoryTypeIndex;
break;
return memoryType;
#ifdef WIN32
LRESULT CALLBACK wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
switch (message)
case WM_SIZE:
} break;
case WM_CLOSE: {
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
#endif
#ifdef _DEBUG
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT /*messageTypes*/,
void* /*pUserData*/)
std::string prefix;
if (messageSeverity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
prefix += "WARNING";
prefix += "ERROR";
if (pCallbackData) {
return VK_FALSE;
#endif
int main() {
CVulkanHelper::initVulkan();
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.apiVersion = VK_API_VERSION_1_2;
appInfo.applicationVersion = VK_MAKE_VERSION(1,0,0);
appInfo.pApplicationName = "Something";
appInfo.engineVersion = VK_MAKE_VERSION(1,0,0);
uint32_t instanceLayerCount;
vkEnumerateInstanceLayerProperties(&instanceLayerCount, nullptr);
std::vector<VkLayerProperties> instanceLayers(instanceLayerCount);
vkEnumerateInstanceLayerProperties(&instanceLayerCount, instanceLayers.data());
uint32_t instanceExtensionCount;
std::vector<VkExtensionProperties> instanceExtensions(instanceExtensionCount);
vkEnumerateInstanceExtensionProperties(nullptr, &instanceExtensionCount,
instanceExtensions.data());
enabledExtensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
#ifdef WIN32
enabledExtensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
#elif defined(__linux__)
enabledExtensions.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
#endif
#ifdef _DEBUG
enabledExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
#endif
//enabledExtensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
enabledExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
#ifdef _DEBUG
enableValidationLayers.push_back("VK_LAYER_KHRONOS_validation");
#endif
enableValidationLayers.push_back("VK_LAYER_LUNARG_monitor");
instanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instanceInfo.pApplicationInfo = &appInfo;
instanceInfo.enabledExtensionCount = static_cast<uint32_t>(enabledExtensions.size());
instanceInfo.ppEnabledExtensionNames = enabledExtensions.data();
instanceInfo.enabledLayerCount = static_cast<uint32_t>(enableValidationLayers.size());
instanceInfo.ppEnabledLayerNames = enableValidationLayers.data();
VkInstance instance;
if (res != VK_SUCCESS) {
printf("vkCreateInstance failed\n");
CVulkanHelper::initVulkanInstanceFunctions(instance);
#ifdef _DEBUG
debugMessengerInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
debugMessengerInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
debugMessengerInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
debugMessengerInfo.pfnUserCallback = debug_callback;
PFN_vkCreateDebugUtilsMessengerEXT pfnCreateDebugUtilsMessengerEXT =
(PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance,
"vkCreateDebugUtilsMessengerEXT");
VkDebugUtilsMessengerEXT debugMessenger;
#endif
VkPhysicalDevice gpu;
uint32_t gpuCount;
std::vector<VkPhysicalDevice> gpus(gpuCount);
gpu = gpus[0];
uint32_t deviceLayerCount;
std::vector<VkLayerProperties> deviceLayers(deviceLayerCount);
uint32_t deviceExtensionCount;
std::vector<VkExtensionProperties> deviceExtensions(deviceExtensionCount);
uint32_t queuePropertyCount;
std::vector<VkQueueFamilyProperties> queueProperties(queuePropertyCount);
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = 0;
queueCreateInfo.queueCount = 1;
queueCreateInfo.pQueuePriorities = &queuePriority;
activatedDeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
activatedDeviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
//activatedDeviceExtensions.push_back(VK_NV_RAY_TRACING_EXTENSION_NAME);
activatedDeviceExtensions.push_back(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME);
activatedDeviceExtensions.push_back(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME);
activatedDeviceExtensions.push_back(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME);
activatedDeviceExtensions.push_back(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME);
activatedDeviceExtensions.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
VkDevice device;
// descriptorIndexingFeatures.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT;
accelerationStructureFeatures.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR;
raytracingPipelineFeatures.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR;
raytracingPipelineFeatures.pNext = &accelerationStructureFeatures;
vulkan12Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
vulkan12Features.pNext = &raytracingPipelineFeatures;
features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
features2.pNext = &vulkan12Features;
vkGetPhysicalDeviceFeatures2(gpu, &features2);
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
deviceCreateInfo.pNext = &features2;
deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
deviceCreateInfo.queueCreateInfoCount = 1;
deviceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(activatedDeviceExtensions.size());
deviceCreateInfo.ppEnabledExtensionNames = activatedDeviceExtensions.data();
if (res != VK_SUCCESS) {
printf("vkCreateDevice failed\n");
CVulkanHelper::initVulkanDeviceFunctions(device);
VkQueue queue;
vkGetDeviceQueue(device, 0, 0, &queue);
cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
cmdPoolInfo.queueFamilyIndex = 0;
VkCommandPool commandPool;
VkPhysicalDeviceMemoryProperties gpuMemProps;
vkGetPhysicalDeviceMemoryProperties(gpu, &gpuMemProps);
std::vector<VkDescriptorPoolSize> poolSizes;
poolSize0.type = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
poolSize0.descriptorCount = 2;
poolSizes.push_back(poolSize0);
poolSize1.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
poolSize1.descriptorCount = 2;
poolSizes.push_back(poolSize1);
poolSize2.type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
poolSize2.descriptorCount = 2;
poolSizes.push_back(poolSize2);
poolSize3.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
poolSize3.descriptorCount = 2;
poolSizes.push_back(poolSize3);
descriptorPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
descriptorPoolInfo.maxSets = 3;
descriptorPoolInfo.poolSizeCount = static_cast<uint32_t>(poolSizes.size());
descriptorPoolInfo.pPoolSizes = poolSizes.data();
VkDescriptorPool descriptorPool;
accelerationStructureProperties.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR;
raytracingPipelineProperties.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR;
raytracingPipelineProperties.pNext = &accelerationStructureProperties;
props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
props.pNext = &raytracingPipelineProperties;
vkGetPhysicalDeviceProperties2(gpu, &props);
rayTracing.init();
rayTracing.initScene();
rayTracing.buildProceduralGeometryAABBs();
rayTracing.buildTriangleAccelerationStructure();
rayTracing.updateAABBPrimitivesAttributes(0.0f);
std::vector<VkDescriptorSetLayoutBinding> layoutbindings;
layoutbindingAccelerationStructure.binding = 0;
layoutbindingAccelerationStructure.descriptorType =
VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
layoutbindingAccelerationStructure.descriptorCount = 1;
layoutbindingAccelerationStructure.stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR |
VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
layoutbindings.push_back(layoutbindingAccelerationStructure);
layoutbindingOuputImage.binding = 1;
layoutbindingOuputImage.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
layoutbindingOuputImage.descriptorCount = 1;
layoutbindingOuputImage.stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR;
layoutbindings.push_back(layoutbindingOuputImage);
layoutbindingSceneBuffer.binding = 2;
layoutbindingSceneBuffer.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
layoutbindingSceneBuffer.descriptorCount = 1;
layoutbindingSceneBuffer.stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR |
VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_INTERSECTION_BIT_KHR;
layoutbindings.push_back(layoutbindingSceneBuffer);
layoutbindingFacesBuffer.binding = 3;
layoutbindingFacesBuffer.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
layoutbindingFacesBuffer.descriptorCount = 1;
layoutbindingFacesBuffer.stageFlags = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
layoutbindings.push_back(layoutbindingFacesBuffer);
layoutbindingNormalBuffer.binding = 4;
layoutbindingNormalBuffer.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
layoutbindingNormalBuffer.descriptorCount = 1;
layoutbindingNormalBuffer.stageFlags = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
layoutbindings.push_back(layoutbindingNormalBuffer);
layoutbindingAABBPrimitiveBuffer.binding = 5;
layoutbindingAABBPrimitiveBuffer.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
layoutbindingAABBPrimitiveBuffer.descriptorCount = 1;
layoutbindingAABBPrimitiveBuffer.stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR |
VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_INTERSECTION_BIT_KHR;
layoutbindings.push_back(layoutbindingAABBPrimitiveBuffer);
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layoutInfo.bindingCount = static_cast<uint32_t>(layoutbindings.size());
layoutInfo.pBindings = layoutbindings.data();
std::vector<VkDescriptorSetLayout> descriptorSetLayouts;
VkDescriptorSetLayout descriptorSetLayout;
descriptorSetLayouts.push_back(descriptorSetLayout);
rayTracing.createShaderStages();
descriptorSetAllocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
descriptorSetAllocInfo.descriptorSetCount = static_cast<uint32_t>(descriptorSetLayouts.size());
descriptorSetAllocInfo.pSetLayouts = descriptorSetLayouts.data();
descriptorSetAllocInfo.descriptorPool = descriptorPool;
VkDescriptorSet descriptorSet;
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 1;
pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout;
VkPipelineLayout pipelineLayout;
if (res != VK_SUCCESS) {
printf("vkCreatePipelineLayout failed\n");
VkSurfaceKHR surface;
#ifdef WIN32
WNDCLASSEX windowClass;
windowClass.lpfnWndProc = (WNDPROC)wndProc;
windowClass.cbClsExtra = 0;
windowClass.cbWndExtra = 0;
windowClass.hInstance = hInstance;
windowClass.hIcon = LoadIcon(NULL, IDI_WINLOGO);
windowClass.hIconSm = windowClass.hIcon;
windowClass.hbrBackground = NULL;
windowClass.lpszMenuName = NULL;
windowClass.lpszClassName = applicationName;
windowClass.cbSize = sizeof(WNDCLASSEX);
RegisterClassEx(&windowClass);
ShowWindow(hWnd, SW_SHOW);
SetForegroundWindow(hWnd);
SetFocus(hWnd);
surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
surfaceCreateInfo.hinstance = hInstance;
surfaceCreateInfo.hwnd = hWnd;
#elif defined(__linux__)
int screenp = 0;
xcb_screen_next(&iter);
surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
surfaceCreateInfo.window = window;
surfaceCreateInfo.connection = connection;
#endif
VkBool32 queueSupported;
vkGetPhysicalDeviceSurfaceSupportKHR(gpu, 0, surface, &queueSupported);
uint32_t formatCount;
std::vector<VkSurfaceFormatKHR> surfaceFormats(formatCount);
vkGetDeviceQueue(device, 0, 0, &presentQueue);
VkSurfaceCapabilitiesKHR capabilities;
uint32_t presentModeCount;
std::vector<VkPresentModeKHR> presentModes(presentModeCount);
VkSurfaceFormatKHR surfaceFormat;
else {
surfaceFormat = surfaceFormats[formatIndex];
break;
#ifndef VSYNC
if (presentModes[presentModeIndex] == VK_PRESENT_MODE_MAILBOX_KHR) {
presentMode = presentModes[presentModeIndex];
break;
presentMode = presentModes[presentModeIndex];
#endif
VkExtent2D swapExtent;
if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max()) {
swapExtent = capabilities.currentExtent;
else {
swapExtent.height = std::max(capabilities.minImageExtent.height,
std::min(capabilities.maxImageExtent.height, swapExtent.height));
imageCount = capabilities.maxImageCount;
swapChainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
swapChainInfo.surface = surface;
swapChainInfo.minImageCount = imageCount;
swapChainInfo.imageFormat = surfaceFormat.format;
swapChainInfo.imageColorSpace = surfaceFormat.colorSpace;
swapChainInfo.imageExtent = swapExtent;
swapChainInfo.imageArrayLayers = 1;
swapChainInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
VK_IMAGE_USAGE_TRANSFER_DST_BIT;
swapChainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
swapChainInfo.queueFamilyIndexCount = 0;
swapChainInfo.pQueueFamilyIndices = nullptr;
swapChainInfo.preTransform = capabilities.currentTransform;
swapChainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
swapChainInfo.presentMode = presentMode;
swapChainInfo.clipped = VK_TRUE;
swapChainInfo.oldSwapchain = VK_NULL_HANDLE;
VkSwapchainKHR swapchain;
uint32_t swapImageCount;
std::vector<VkImage> swapImages(swapImageCount);
std::vector<VkImageView> swapImageViews(swapImageCount);
imageViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
imageViewInfo.image = swapImages[swapImageIndex];
imageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
imageViewInfo.format = surfaceFormat.format;
imageViewInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
imageViewInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
imageViewInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
imageViewInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
imageViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageViewInfo.subresourceRange.baseMipLevel = 0;
imageViewInfo.subresourceRange.levelCount = 1;
imageViewInfo.subresourceRange.baseArrayLayer = 0;
imageViewInfo.subresourceRange.layerCount = 1;
}
rayTracing.createSceneBuffer();
rayTracing.updateSceneBuffer();
rayTracing.createAABBPrimitiveBuffer();
rayTracing.updateAABBPrimitiveBuffer();
rayTracing.updateDescriptors(descriptorSet);
colorAttachment.format = surfaceFormat.format;
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
colorAttachmentRef.attachment = 0;
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorAttachmentRef;
VkRenderPassCreateInfo renderpassInfo = {};
renderpassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderpassInfo.attachmentCount = 1;
renderpassInfo.pAttachments = &colorAttachment;
renderpassInfo.subpassCount = 1;
renderpassInfo.pSubpasses = &subpass;
VkRenderPass renderpass;
std::vector<VkFramebuffer> swapFramebuffers(swapImageCount);
VkImageView attachments[] = {
swapImageViews[frameBufferIndex]
};
frameBufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
frameBufferInfo.renderPass = renderpass;
frameBufferInfo.attachmentCount = 1;
frameBufferInfo.pAttachments = attachments;
frameBufferInfo.width = swapExtent.width;
frameBufferInfo.height = swapExtent.height;
frameBufferInfo.layers = 1;
}
std::vector<VkCommandBuffer> commandBuffers(swapFramebuffers.size());
cmdBufferAllocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
cmdBufferAllocInfo.commandPool = commandPool;
cmdBufferAllocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
cmdBufferAllocInfo.commandBufferCount = static_cast<uint32_t>(commandBuffers.size());
raygenStridedBufferRegion.deviceAddress = raygenShaderGroup.address;
raygenStridedBufferRegion.stride = raytracingPipelineProperties.shaderGroupHandleSize;
raygenStridedBufferRegion.size = raytracingPipelineProperties.shaderGroupHandleSize;
uint32_t raygenAlignment =
CVulkanHelper::alignTo(raytracingPipelineProperties.shaderGroupHandleSize,
raytracingPipelineProperties.shaderGroupBaseAlignment);
missStridedBufferRegion.stride = raytracingPipelineProperties.shaderGroupHandleSize;
missStridedBufferRegion.size = raytracingPipelineProperties.shaderGroupHandleSize * 2;
uint32_t missAlignment =
CVulkanHelper::alignTo(raytracingPipelineProperties.shaderGroupHandleSize * 2,
raytracingPipelineProperties.shaderGroupBaseAlignment);
hitStridedBufferRegion.stride = (raytracingPipelineProperties.shaderGroupHandleSize +
sizeof(PrimitiveConstantBuffer) + sizeof(PrimitiveInstanceConstantBuffer));
hitStridedBufferRegion.size = (raytracingPipelineProperties.shaderGroupHandleSize +
sizeof(PrimitiveConstantBuffer) + sizeof(PrimitiveInstanceConstantBuffer)) * 10;
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
vkBeginCommandBuffer(commandBuffers[commandBufferIndex], &beginInfo);
subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
subresourceRange.baseMipLevel = 0;
subresourceRange.levelCount = 1;
subresourceRange.baseArrayLayer = 0;
subresourceRange.layerCount = 1;
imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
imageMemoryBarrier.srcAccessMask = 0;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imageMemoryBarrier.image = offscreenImage.handle;
imageMemoryBarrier.subresourceRange = subresourceRange;
vkCmdPipelineBarrier(commandBuffers[commandBufferIndex],
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0,
nullptr, 1, &imageMemoryBarrier);
vkCmdBindPipeline(commandBuffers[commandBufferIndex],
VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, raytracingPipeline);
vkCmdBindDescriptorSets(commandBuffers[commandBufferIndex],
VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr);
vkCmdTraceRaysKHR(commandBuffers[commandBufferIndex],
&raygenStridedBufferRegion,
&missStridedBufferRegion,
&hitStridedBufferRegion,
&callableStridedBufferRegion,
imageMemoryBarrier.srcAccessMask = 0;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imageMemoryBarrier.image = swapImages[commandBufferIndex];
imageMemoryBarrier.subresourceRange = subresourceRange;
vkCmdPipelineBarrier(commandBuffers[commandBufferIndex],
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1,
&imageMemoryBarrier);
imageMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imageMemoryBarrier.image = offscreenImage.handle;
imageMemoryBarrier.subresourceRange = subresourceRange;
vkCmdPipelineBarrier(commandBuffers[commandBufferIndex],
VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0,
nullptr, 0, nullptr, 1, &imageMemoryBarrier);
VkImageCopy copyRegion;
copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
copyRegion.srcOffset = { 0, 0, 0 };
copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
copyRegion.dstOffset = { 0, 0, 0 };
vkCmdCopyImage(commandBuffers[commandBufferIndex], offscreenImage.handle,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, swapImages[commandBufferIndex],
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Region);
imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
imageMemoryBarrier.dstAccessMask = 0;
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imageMemoryBarrier.image = swapImages[commandBufferIndex];
imageMemoryBarrier.subresourceRange = subresourceRange;
vkCmdPipelineBarrier(commandBuffers[commandBufferIndex],
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0,
nullptr, 1, &imageMemoryBarrier);
vkEndCommandBuffer(commandBuffers[commandBufferIndex]);
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
std::vector<VkSemaphore> imageAvailableSemaphores(swapImageCount);
std::vector<VkSemaphore> renderFinishedSemaphores(swapImageCount);
fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
std::vector<VkFence> fences(swapImageCount);
#ifdef WIN32
#elif defined(__linux__)
xcb_map_window(connection, window);
xcb_flush(connection);
xcb_generic_event_t *event;
xcb_client_message_event_t *cm;
#endif
uint32_t frameIndex = 0;
while (running) {
#ifdef WIN32
MSG msg;
TranslateMessage(&msg);
DispatchMessage(&msg);
if (msg.message == WM_QUIT) {
running = false;
#elif defined(__linux__)
case XCB_CLIENT_MESSAGE: {
cm = reinterpret_cast<xcb_client_message_event_t*>(event);
if (cm->data.data32[0] == wmDeleteWin) {
running = false;
} break;
free(event);
#endif
rayTracing.update();
uint32_t imageIndex;
vkAcquireNextImageKHR(device, swapchain, std::numeric_limits<uint64_t>::max(),
imageAvailableSemaphores[frameIndex], VK_NULL_HANDLE, &imageIndex);
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = &imageAvailableSemaphores[frameIndex];
submitInfo.pWaitDstStageMask = &waitStageMask;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffers[frameIndex];
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = &renderFinishedSemaphores[frameIndex];
vkResetFences(device, 1, &fence);
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = &renderFinishedSemaphores[frameIndex];
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = &swapchain;
presentInfo.pImageIndices = &imageIndex;
vkQueuePresentKHR(queue, &presentInfo);
#ifdef WIN32
#elif defined(__linux__)
xcb_destroy_window(connection, window);
#endif
return 0;