Skip to content

Instantly share code, notes, and snippets.

@rossant
Last active January 25, 2024 20:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rossant/610961a9f9b7210cb208b616e69f4f37 to your computer and use it in GitHub Desktop.
Save rossant/610961a9f9b7210cb208b616e69f4f37 to your computer and use it in GitHub Desktop.
Vulkan minimal example that generates a SYNC-HAZARD-WRITE-AFTER-READ validation error
// Requires gcc, the Vulkan SDK, and libglfw3-dev
// On Linux, compile with:
// gcc -Wall -o fail fail.c -Ibuild/_deps/glfw-src/include/ -lglfw -lvulkan
#include <assert.h>
#include <stdbool.h>
#include <string.h>
#include <vulkan/vulkan.h>
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
const uint32_t WIDTH = 800;
const uint32_t HEIGHT = 600;
#define STR(r) \
case VK_##r: \
str = #r; \
break
#define noop
static inline int check_result(VkResult res)
{
char* str = "UNKNOWN_ERROR";
switch (res)
{
STR(NOT_READY);
STR(TIMEOUT);
STR(EVENT_SET);
STR(EVENT_RESET);
STR(INCOMPLETE);
STR(ERROR_OUT_OF_HOST_MEMORY);
STR(ERROR_OUT_OF_DEVICE_MEMORY);
STR(ERROR_INITIALIZATION_FAILED);
STR(ERROR_DEVICE_LOST);
STR(ERROR_MEMORY_MAP_FAILED);
STR(ERROR_LAYER_NOT_PRESENT);
STR(ERROR_EXTENSION_NOT_PRESENT);
STR(ERROR_FEATURE_NOT_PRESENT);
STR(ERROR_INCOMPATIBLE_DRIVER);
STR(ERROR_TOO_MANY_OBJECTS);
STR(ERROR_FORMAT_NOT_SUPPORTED);
STR(ERROR_SURFACE_LOST_KHR);
STR(ERROR_NATIVE_WINDOW_IN_USE_KHR);
STR(SUBOPTIMAL_KHR);
STR(ERROR_OUT_OF_DATE_KHR);
STR(ERROR_INCOMPATIBLE_DISPLAY_KHR);
STR(ERROR_VALIDATION_FAILED_EXT);
STR(ERROR_INVALID_SHADER_NV);
default:
noop;
}
if (res != VK_SUCCESS)
{
printf("VkResult is %s in %s at line %d\n", str, __FILE__, __LINE__);
return 1;
}
return 0;
}
#define VK_CHECK_RESULT(f) \
{ \
VkResult res = (f); \
check_result(res); \
}
static VkResult create_debug_utils_messenger_EXT(
VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo,
const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pDebugMessenger)
{
PFN_vkCreateDebugUtilsMessengerEXT func =
(PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(
instance, "vkCreateDebugUtilsMessengerEXT");
if (func != NULL)
{
return func(instance, pCreateInfo, pAllocator, pDebugMessenger);
}
else
{
return VK_ERROR_EXTENSION_NOT_PRESENT;
}
}
static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback(
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData)
{
// Hide long list of extensions.
if (strstr(pCallbackData->pMessage, "Extension: VK_") != NULL)
return VK_FALSE;
printf("validation layer: %s\n", pCallbackData->pMessage);
if (messageSeverity >= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT && pUserData != NULL)
{
uint32_t* n_errors = (uint32_t*)pUserData;
(*n_errors)++;
}
return VK_FALSE;
}
static void destroy_debug_utils_messenger_EXT(
VkInstance instance, VkDebugUtilsMessengerEXT debug_messenger,
const VkAllocationCallbacks* pAllocator)
{
PFN_vkDestroyDebugUtilsMessengerEXT func =
(PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(
instance, "vkDestroyDebugUtilsMessengerEXT");
if (func != NULL)
{
func(instance, debug_messenger, pAllocator);
}
}
static VkInstance createInstance(VkDebugUtilsMessengerEXT* debug_messenger, void* debug_data)
{
uint32_t glfwExtensionCount = 0;
const char** glfwExtensions;
glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
const char* addExtensions[] = {
"VK_EXT_debug_utils", //
};
uint32_t addExtensionCount = sizeof(addExtensions) / sizeof(char*);
uint32_t extensionCount = glfwExtensionCount + addExtensionCount;
char** extensions = calloc(extensionCount, sizeof(char*));
memcpy(extensions, glfwExtensions, glfwExtensionCount * sizeof(char*));
memcpy(&extensions[glfwExtensionCount], addExtensions, sizeof(addExtensions));
// Prepare the creation of the Vulkan instance.
VkApplicationInfo appInfo = {0};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = "fail";
appInfo.applicationVersion = 1;
appInfo.pEngineName = "fail";
appInfo.engineVersion = 1;
appInfo.apiVersion = VK_API_VERSION_1_3;
VkInstanceCreateInfo info_inst = {0};
info_inst.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
info_inst.pApplicationInfo = &appInfo;
info_inst.enabledExtensionCount = extensionCount;
info_inst.ppEnabledExtensionNames = (const char* const*)extensions;
// Validation layers.
VkDebugUtilsMessengerCreateInfoEXT info_debug = {0};
info_debug.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
info_debug.flags = 0;
info_debug.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
info_debug.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
info_debug.pfnUserCallback = debug_callback;
info_debug.pUserData = debug_data;
VkValidationFeatureEnableEXT enables[16] = {0};
VkValidationFeaturesEXT features = {0};
info_inst.enabledLayerCount = 1;
info_inst.ppEnabledLayerNames = (const char*[]){"VK_LAYER_KHRONOS_validation"};
// https://vulkan.lunarg.com/doc/sdk/1.2.170.0/linux/best_practices.html
enables[0] = VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT;
enables[1] = VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT;
enables[2] = VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT;
features.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT;
features.enabledValidationFeatureCount = 3;
features.pEnabledValidationFeatures = enables;
// pNext chain
features.pNext = (VkDebugUtilsMessengerCreateInfoEXT*)&info_debug;
info_inst.pNext = &features;
// Create the Vulkan instance.
VkInstance instance;
VK_CHECK_RESULT(vkCreateInstance(&info_inst, NULL, &instance));
// Create the debug utils messenger.
VK_CHECK_RESULT(
create_debug_utils_messenger_EXT(instance, &info_debug, NULL, debug_messenger));
free(extensions);
return instance;
}
VkPhysicalDevice pickPhysicalDevice(VkInstance instance)
{
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
uint32_t deviceCount = 0;
vkEnumeratePhysicalDevices(instance, &deviceCount, NULL);
if (deviceCount == 0)
{
fprintf(stderr, "Failed to find GPUs with Vulkan support!\n");
exit(1);
}
VkPhysicalDevice devices[deviceCount];
vkEnumeratePhysicalDevices(instance, &deviceCount, devices);
// Just pick the first device for simplicity
physicalDevice = devices[0];
return physicalDevice;
}
VkDevice createLogicalDevice(VkPhysicalDevice physicalDevice, uint32_t* queueFamilyIndex)
{
VkDevice device;
VkDeviceQueueCreateInfo queueCreateInfo = {0};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = *queueFamilyIndex;
queueCreateInfo.queueCount = 1;
float queuePriority = 1.0f;
queueCreateInfo.pQueuePriorities = &queuePriority;
VkPhysicalDeviceFeatures deviceFeatures = {0};
vkGetPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);
VkDeviceCreateInfo createInfo = {0};
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
createInfo.pQueueCreateInfos = &queueCreateInfo;
createInfo.queueCreateInfoCount = 1;
createInfo.pEnabledFeatures = &deviceFeatures;
createInfo.enabledExtensionCount = 1;
createInfo.ppEnabledExtensionNames = (const char*[]){
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
};
if (vkCreateDevice(physicalDevice, &createInfo, NULL, &device) != VK_SUCCESS)
{
fprintf(stderr, "Failed to create logical device!\n");
exit(1);
}
return device;
}
uint32_t findQueueFamilies(VkPhysicalDevice device)
{
uint32_t queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, NULL);
VkQueueFamilyProperties queueFamilies[queueFamilyCount];
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies);
for (uint32_t i = 0; i < queueFamilyCount; i++)
{
if (queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
{
return i;
}
}
fprintf(stderr, "Failed to find a suitable queue family!\n");
exit(1);
}
VkSurfaceKHR createSurface(VkInstance instance, GLFWwindow* window)
{
VkSurfaceKHR surface;
if (glfwCreateWindowSurface(instance, window, NULL, &surface) != VK_SUCCESS)
{
fprintf(stderr, "Failed to create window surface!\n");
exit(1);
}
return surface;
}
VkSwapchainKHR createSwapChain(
VkPhysicalDevice physicalDevice, VkDevice device, VkSurfaceKHR surface, VkFormat* format,
uint32_t* imageCount, VkExtent2D* extent, VkImage* swapChainImages)
{
assert(device);
VkSwapchainKHR swapChain;
VkSurfaceCapabilitiesKHR capabilities;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &capabilities);
VkSurfaceFormatKHR surfaceFormat;
uint32_t formatCount;
vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, NULL);
VkSurfaceFormatKHR formats[formatCount];
vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, formats);
surfaceFormat = formats[0];
VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;
VkSwapchainCreateInfoKHR createInfo = {0};
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
createInfo.surface = surface;
createInfo.minImageCount = capabilities.minImageCount + 1;
createInfo.imageFormat = surfaceFormat.format;
createInfo.imageColorSpace = surfaceFormat.colorSpace;
createInfo.imageExtent = capabilities.currentExtent;
createInfo.imageArrayLayers = 1;
createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
createInfo.preTransform = capabilities.currentTransform;
createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
createInfo.presentMode = presentMode;
createInfo.clipped = VK_TRUE;
createInfo.oldSwapchain = VK_NULL_HANDLE;
if (vkCreateSwapchainKHR(device, &createInfo, NULL, &swapChain) != VK_SUCCESS)
{
fprintf(stderr, "Failed to create swap chain!\n");
exit(1);
}
*extent = createInfo.imageExtent;
vkGetSwapchainImagesKHR(device, swapChain, imageCount, NULL);
vkGetSwapchainImagesKHR(device, swapChain, imageCount, swapChainImages);
*format = createInfo.imageFormat;
return swapChain;
}
VkImageView createImageView(VkDevice device, VkImage image, VkFormat format)
{
VkImageViewCreateInfo viewInfo = {0};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.image = image;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = format;
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
viewInfo.subresourceRange.baseMipLevel = 0;
viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.baseArrayLayer = 0;
viewInfo.subresourceRange.layerCount = 1;
VkImageView imageView;
if (vkCreateImageView(device, &viewInfo, NULL, &imageView) != VK_SUCCESS)
{
fprintf(stderr, "Failed to create image views!\n");
exit(1);
}
return imageView;
}
VkRenderPass createRenderPass(VkDevice device, VkFormat format)
{
VkRenderPass renderPass;
VkAttachmentDescription colorAttachment = {0};
colorAttachment.format = 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;
VkAttachmentReference colorAttachmentRef = {0};
colorAttachmentRef.attachment = 0;
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpass = {0};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorAttachmentRef;
VkRenderPassCreateInfo renderPassInfo = {0};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.attachmentCount = 1;
renderPassInfo.pAttachments = &colorAttachment;
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass;
if (vkCreateRenderPass(device, &renderPassInfo, NULL, &renderPass) != VK_SUCCESS)
{
fprintf(stderr, "Failed to create render pass!\n");
exit(1);
}
return renderPass;
}
VkFramebuffer createFramebuffer(
VkDevice device, VkRenderPass renderPass, VkImageView imageView, VkExtent2D extent)
{
VkFramebuffer framebuffer;
VkImageView attachments[] = {imageView};
VkFramebufferCreateInfo framebufferInfo = {0};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.renderPass = renderPass;
framebufferInfo.attachmentCount = 1;
framebufferInfo.pAttachments = attachments;
framebufferInfo.width = extent.width;
framebufferInfo.height = extent.height;
framebufferInfo.layers = 1;
if (vkCreateFramebuffer(device, &framebufferInfo, NULL, &framebuffer) != VK_SUCCESS)
{
fprintf(stderr, "Failed to create framebuffer!\n");
exit(1);
}
return framebuffer;
}
VkCommandPool createCommandPool(VkDevice device, uint32_t queueFamilyIndex)
{
VkCommandPoolCreateInfo poolInfo = {};
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
poolInfo.queueFamilyIndex = queueFamilyIndex;
poolInfo.flags = 0;
VkCommandPool commandPool;
if (vkCreateCommandPool(device, &poolInfo, NULL, &commandPool) != VK_SUCCESS)
{
fprintf(stderr, "Failed to create command pool\n");
exit(1);
}
return commandPool;
}
VkCommandBuffer* createCommandBuffers(
VkDevice device, VkCommandPool commandPool, VkRenderPass renderPass, VkImage image,
VkFramebuffer* framebuffers, VkExtent2D extent, uint32_t imageCount)
{
VkCommandBuffer* commandBuffers = malloc(imageCount * sizeof(VkCommandBuffer));
VkCommandBufferAllocateInfo allocInfo = {};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.commandPool = commandPool;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandBufferCount = imageCount;
vkAllocateCommandBuffers(device, &allocInfo, commandBuffers);
VkImageMemoryBarrier imageBarrier = {};
imageBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
imageBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
imageBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
imageBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imageBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imageBarrier.image = image;
imageBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageBarrier.subresourceRange.baseMipLevel = 0;
imageBarrier.subresourceRange.levelCount = 1;
imageBarrier.subresourceRange.baseArrayLayer = 0;
imageBarrier.subresourceRange.layerCount = 1;
for (size_t i = 0; i < imageCount; i++)
{
VkCommandBufferBeginInfo beginInfo = {};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
vkBeginCommandBuffer(commandBuffers[i], &beginInfo);
VkRenderPassBeginInfo renderPassInfo = {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = renderPass;
renderPassInfo.framebuffer = framebuffers[i];
renderPassInfo.renderArea.offset = (VkOffset2D){0, 0};
renderPassInfo.renderArea.extent = extent;
VkClearValue clearColor = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
renderPassInfo.clearValueCount = 1;
renderPassInfo.pClearValues = &clearColor;
vkCmdPipelineBarrier(
commandBuffers[i], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, NULL, 0, NULL, 1, &imageBarrier);
vkCmdBeginRenderPass(commandBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdEndRenderPass(commandBuffers[i]);
vkEndCommandBuffer(commandBuffers[i]);
}
return commandBuffers;
}
VkSemaphore createSemaphore(VkDevice device)
{
VkSemaphoreCreateInfo semaphoreInfo = {};
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
VkSemaphore semaphore;
if (vkCreateSemaphore(device, &semaphoreInfo, NULL, &semaphore) != VK_SUCCESS)
{
fprintf(stderr, "Failed to create semaphore\n");
exit(1);
}
return semaphore;
}
int main()
{
if (!glfwInit())
{
fprintf(stderr, "Failed to initialize GLFW\n");
return -1;
}
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan Window", NULL, NULL);
if (!window)
{
fprintf(stderr, "Failed to create GLFW window\n");
glfwTerminate();
return -1;
}
VkDebugUtilsMessengerEXT debug_callback;
VkInstance instance = createInstance(&debug_callback, NULL);
VkPhysicalDevice physicalDevice = pickPhysicalDevice(instance);
uint32_t queueFamilyIndex = findQueueFamilies(physicalDevice);
VkDevice device = createLogicalDevice(physicalDevice, &queueFamilyIndex);
VkSurfaceKHR surface = createSurface(instance, window);
VkFormat format;
uint32_t imageCount;
VkExtent2D extent;
VkImage swapChainImages[10] = {0};
VkSwapchainKHR swapChain = createSwapChain(
physicalDevice, device, surface, &format, &imageCount, &extent, swapChainImages);
VkImageView* imageViews = malloc(imageCount * sizeof(VkImageView));
for (uint32_t i = 0; i < imageCount; i++)
imageViews[i] = createImageView(device, swapChainImages[i], format);
VkRenderPass renderPass = createRenderPass(device, format);
VkFramebuffer* framebuffers = malloc(imageCount * sizeof(VkFramebuffer));
for (uint32_t i = 0; i < imageCount; i++)
framebuffers[i] = createFramebuffer(device, renderPass, imageViews[i], extent);
VkCommandPool commandPool = createCommandPool(device, queueFamilyIndex);
VkCommandBuffer* commandBuffers = createCommandBuffers(
device, commandPool, renderPass, swapChainImages[0], framebuffers, extent, imageCount);
VkSemaphore imageAvailableSemaphore = createSemaphore(device);
VkSemaphore renderFinishedSemaphore = createSemaphore(device);
uint32_t imageIndex;
vkAcquireNextImageKHR(
device, swapChain, UINT64_MAX, imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex);
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
VkSemaphore waitSemaphores[] = {imageAvailableSemaphore};
// NOTE: the warning disappears by putting VK_PIPELINE_STAGE_ALL_COMMANDS_BIT here,
// but then we've got:
//
// Validation Warning: [ UNASSIGNED-BestPractices-pipeline-stage-flags ] | MessageID =
// 0x48a09f6c | vkQueueSubmit(): pSubmits[0].pWaitDstStageMask[0] using
// VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitStages;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffers[imageIndex];
VkSemaphore signalSemaphores[] = {renderFinishedSemaphore};
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores;
VkQueue graphicsQueue;
vkGetDeviceQueue(device, queueFamilyIndex, 0, &graphicsQueue);
vkQueueSubmit(graphicsQueue, 1, &submitInfo, NULL);
/*
Here we get this:
validation layer: Validation Error: [ SYNC-HAZARD-WRITE-AFTER-READ ] Object 0: handle =
0x5599afbbf520, type = VK_OBJECT_TYPE_QUEUE; | MessageID = 0x376bc9df | vkQueueSubmit(): Hazard
WRITE_AFTER_READ for entry 0, VkCommandBuffer 0x5599b202e960[], Submitted access info
(submitted_usage: SYNC_IMAGE_LAYOUT_TRANSITION, command: vkCmdBeginRenderPass, seq_no: 1,
renderpass: VkRenderPass 0xcad092000000000d[], reset_no: 1). Access info (prior_usage:
SYNC_PRESENT_ENGINE_SYNCVAL_PRESENT_ACQUIRE_READ_SYNCVAL, read_barriers:
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT|VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT, ,
batch_tag: 1, vkAcquireNextImageKHR aquire_tag:1: VkSwapchainKHR 0xf443490000000006[],
image_index: 0image: VkImage 0xcb3ee80000000007[]).
*/
VkPresentInfoKHR presentInfo = {};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = signalSemaphores;
VkSwapchainKHR swapChains[] = {swapChain};
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = swapChains;
presentInfo.pImageIndices = &imageIndex;
vkQueuePresentKHR(graphicsQueue, &presentInfo);
vkQueueWaitIdle(graphicsQueue);
destroy_debug_utils_messenger_EXT(instance, debug_callback, NULL);
vkDestroySemaphore(device, imageAvailableSemaphore, NULL);
vkDestroySemaphore(device, renderFinishedSemaphore, NULL);
for (uint32_t i = 0; i < imageCount; i++)
{
vkDestroyFramebuffer(device, framebuffers[i], NULL);
vkDestroyImageView(device, imageViews[i], NULL);
}
vkDestroyCommandPool(device, commandPool, NULL);
vkDestroyRenderPass(device, renderPass, NULL);
vkDestroySwapchainKHR(device, swapChain, NULL);
vkDestroyDevice(device, NULL);
vkDestroySurfaceKHR(instance, surface, NULL);
vkDestroyInstance(instance, NULL);
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment