void submitCommandsAndWait (const DeviceInterface& vk, const VkDevice device, const VkQueue queue, const VkCommandBuffer commandBuffer) { const VkFenceCreateInfo fenceParams = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType; DE_NULL, // const void* pNext; 0u, // VkFenceCreateFlags flags; }; const Unique<VkFence> fence(createFence(vk, device, &fenceParams)); const VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType; DE_NULL, // const void* pNext; 0u, // deUint32 waitSemaphoreCount; DE_NULL, // const VkSemaphore* pWaitSemaphores; (const VkPipelineStageFlags*)DE_NULL, 1u, // deUint32 commandBufferCount; &commandBuffer, // const VkCommandBuffer* pCommandBuffers; 0u, // deUint32 signalSemaphoreCount; DE_NULL, // const VkSemaphore* pSignalSemaphores; }; VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence)); VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull)); }
void getSemaphoreNative (const vk::DeviceInterface& vkd, vk::VkDevice device, vk::VkSemaphore semaphore, vk::VkExternalSemaphoreHandleTypeFlagBitsKHR externalType, NativeHandle& nativeHandle) { if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR) { const vk::VkSemaphoreGetFdInfoKHR info = { vk::VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR, DE_NULL, semaphore, externalType }; int fd = -1; VK_CHECK(vkd.getSemaphoreFdKHR(device, &info, &fd)); TCU_CHECK(fd >= 0); nativeHandle = fd; } else if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR) { const vk::VkSemaphoreGetWin32HandleInfoKHR info = { vk::VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR, DE_NULL, semaphore, externalType }; vk::pt::Win32Handle handle (DE_NULL); VK_CHECK(vkd.getSemaphoreWin32HandleKHR(device, &info, &handle)); switch (externalType) { case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR: nativeHandle.setWin32Handle(NativeHandle::WIN32HANDLETYPE_NT, handle); break; case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR: nativeHandle.setWin32Handle(NativeHandle::WIN32HANDLETYPE_KMT, handle); break; default: DE_FATAL("Unknow external memory handle type"); } } else DE_FATAL("Unknow external semaphore handle type"); }
void Copy_To_Swapchain::create() { set_layout = Descriptor_Set_Layout() .sampler (0, VK_SHADER_STAGE_COMPUTE_BIT) .sampled_image (1, VK_SHADER_STAGE_COMPUTE_BIT) .storage_image (2, VK_SHADER_STAGE_COMPUTE_BIT) .create ("copy_to_swapchain_set_layout"); // pipeline layout { VkPushConstantRange range; range.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; range.offset = 0; range.size = 8; // uint32 width + uint32 height VkPipelineLayoutCreateInfo create_info { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO }; create_info.setLayoutCount = 1; create_info.pSetLayouts = &set_layout; create_info.pushConstantRangeCount = 1; create_info.pPushConstantRanges = ⦥ VK_CHECK(vkCreatePipelineLayout(vk.device, &create_info, nullptr, &pipeline_layout)); } // pipeline { VkShaderModule copy_shader = vk_load_spirv("spirv/copy_to_swapchain.comp.spv"); VkPipelineShaderStageCreateInfo compute_stage { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO }; compute_stage.stage = VK_SHADER_STAGE_COMPUTE_BIT; compute_stage.module = copy_shader; compute_stage.pName = "main"; VkComputePipelineCreateInfo create_info{ VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO }; create_info.stage = compute_stage; create_info.layout = pipeline_layout; VK_CHECK(vkCreateComputePipelines(vk.device, VK_NULL_HANDLE, 1, &create_info, nullptr, &pipeline)); vkDestroyShaderModule(vk.device, copy_shader, nullptr); } // point sampler { VkSamplerCreateInfo create_info { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO }; VK_CHECK(vkCreateSampler(vk.device, &create_info, nullptr, &point_sampler)); vk_set_debug_name(point_sampler, "point_sampler"); } }
void Copy_To_Swapchain::update_resolution_dependent_descriptors(VkImageView output_image_view) { if (sets.size() < vk.swapchain_info.images.size()) { size_t n = vk.swapchain_info.images.size() - sets.size(); for (size_t i = 0; i < n; i++) { VkDescriptorSetAllocateInfo alloc_info { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO }; alloc_info.descriptorPool = vk.descriptor_pool; alloc_info.descriptorSetCount = 1; alloc_info.pSetLayouts = &set_layout; VkDescriptorSet set; VK_CHECK(vkAllocateDescriptorSets(vk.device, &alloc_info, &set)); sets.push_back(set); Descriptor_Writes(set).sampler(0, point_sampler); } } for (size_t i = 0; i < vk.swapchain_info.images.size(); i++) { Descriptor_Writes(sets[i]) .sampled_image(1, output_image_view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) .storage_image(2, vk.swapchain_info.image_views[i]); } }
void importSemaphore (const vk::DeviceInterface& vkd, const vk::VkDevice device, const vk::VkSemaphore semaphore, vk::VkExternalSemaphoreHandleTypeFlagBitsKHR externalType, NativeHandle& handle, vk::VkSemaphoreImportFlagsKHR flags) { if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR) { const vk::VkImportSemaphoreFdInfoKHR importInfo = { vk::VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR, DE_NULL, semaphore, flags, externalType, handle.getFd() }; VK_CHECK(vkd.importSemaphoreFdKHR(device, &importInfo)); handle.disown(); } else if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR) { const vk::VkImportSemaphoreWin32HandleInfoKHR importInfo = { vk::VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR, DE_NULL, semaphore, flags, externalType, handle.getWin32Handle(), DE_NULL }; VK_CHECK(vkd.importSemaphoreWin32HandleKHR(device, &importInfo)); // \note File descriptors and win32 handles behave differently, but this call wil make it seem like they would behave in same way handle.reset(); } else DE_FATAL("Unknown semaphore external handle type"); }
std::vector<VkPresentModeKHR> getPhysicalDeviceSurfacePresentModes (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface) { deUint32 numModes = 0; VK_CHECK(vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &numModes, DE_NULL)); if (numModes > 0) { std::vector<VkPresentModeKHR> modes (numModes); VK_CHECK(vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &numModes, &modes[0])); return modes; } else return std::vector<VkPresentModeKHR>(); }
std::vector<VkImage> getSwapchainImages (const DeviceInterface& vkd, VkDevice device, VkSwapchainKHR swapchain) { deUint32 numImages = 0; VK_CHECK(vkd.getSwapchainImagesKHR(device, swapchain, &numImages, DE_NULL)); if (numImages > 0) { std::vector<VkImage> images (numImages); VK_CHECK(vkd.getSwapchainImagesKHR(device, swapchain, &numImages, &images[0])); return images; } else return std::vector<VkImage>(); }
Buffer::Buffer (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkBufferCreateInfo& bufferCreateInfo, const MemoryRequirement memoryRequirement) { m_buffer = createBuffer(vk, device, &bufferCreateInfo); m_allocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *m_buffer), memoryRequirement); VK_CHECK(vk.bindBufferMemory(device, *m_buffer, m_allocation->getMemory(), m_allocation->getOffset())); }
Image (const vk::DeviceInterface& vk, const vk::VkDevice device, vk::Allocator& allocator, const vk::VkImageCreateInfo& imageCreateInfo, const vk::MemoryRequirement memoryRequirement) : m_image (createImage(vk, device, &imageCreateInfo)) , m_allocation (allocator.allocate(getImageMemoryRequirements(vk, device, *m_image), memoryRequirement)) { VK_CHECK(vk.bindImageMemory(device, *m_image, m_allocation->getMemory(), m_allocation->getOffset())); }
Buffer (const vk::DeviceInterface& vk, const vk::VkDevice device, vk::Allocator& allocator, const vk::VkBufferCreateInfo& bufferCreateInfo, const vk::MemoryRequirement memoryRequirement) : m_buffer (createBuffer(vk, device, &bufferCreateInfo)) , m_allocation (allocator.allocate(getBufferMemoryRequirements(vk, device, *m_buffer), memoryRequirement)) { VK_CHECK(vk.bindBufferMemory(device, *m_buffer, m_allocation->getMemory(), m_allocation->getOffset())); }
std::vector<VkSurfaceFormatKHR> getPhysicalDeviceSurfaceFormats (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface) { deUint32 numFormats = 0; VK_CHECK(vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &numFormats, DE_NULL)); if (numFormats > 0) { std::vector<VkSurfaceFormatKHR> formats (numFormats); VK_CHECK(vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &numFormats, &formats[0])); return formats; } else return std::vector<VkSurfaceFormatKHR>(); }
Image::Image (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkImageCreateInfo& imageCreateInfo, const MemoryRequirement memoryRequirement) { m_image = createImage(vk, device, &imageCreateInfo); m_allocation = allocator.allocate(getImageMemoryRequirements(vk, device, *m_image), memoryRequirement); VK_CHECK(vk.bindImageMemory(device, *m_image, m_allocation->getMemory(), m_allocation->getOffset())); }
Move<VkSurfaceKHR> createSurface (const InstanceInterface& vki, VkInstance instance, Type wsiType, const Display& nativeDisplay, const Window& nativeWindow, const VkAllocationCallbacks* pAllocator) { VkSurfaceKHR object = 0; VK_CHECK(createSurface(vki, instance, wsiType, nativeDisplay, nativeWindow, pAllocator, &object)); return Move<VkSurfaceKHR>(check<VkSurfaceKHR>(object), Deleter<VkSurfaceKHR>(vki, instance, pAllocator)); }
VkBool32 getPhysicalDeviceSurfaceSupport (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, deUint32 queueFamilyIndex, VkSurfaceKHR surface) { VkBool32 result = 0; VK_CHECK(vki.getPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface, &result)); return result; }
void beginCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer) { const VkCommandBufferBeginInfo commandBufBeginParams = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; DE_NULL, // const void* pNext; 0u, // VkCommandBufferUsageFlags flags; (const VkCommandBufferInheritanceInfo*)DE_NULL, }; VK_CHECK(vk.beginCommandBuffer(commandBuffer, &commandBufBeginParams)); }
VkFence FenceManager::requestClearedFence() { if (count < fences.size()) return fences[count++]; VkFence fence; VkFenceCreateInfo info = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO }; VK_CHECK(vkCreateFence(device, &info, nullptr, &fence)); fences.push_back(fence); count++; return fence; }
VkSurfaceCapabilitiesKHR getPhysicalDeviceSurfaceCapabilities (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface) { VkSurfaceCapabilitiesKHR capabilities; deMemset(&capabilities, 0, sizeof(capabilities)); VK_CHECK(vki.getPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &capabilities)); return capabilities; }
VkShaderModule loadShaderModule(VkDevice device, const char *pPath) { vector<uint32_t> buffer; if (FAILED(OS::getAssetManager().readBinaryFile(&buffer, pPath))) { LOGE("Failed to read SPIR-V file: %s.\n", pPath); return VK_NULL_HANDLE; } VkShaderModuleCreateInfo moduleInfo = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO }; moduleInfo.codeSize = buffer.size() * sizeof(uint32_t); moduleInfo.pCode = buffer.data(); VkShaderModule shaderModule; VK_CHECK(vkCreateShaderModule(device, &moduleInfo, nullptr, &shaderModule)); return shaderModule; }
int getMemoryFd (const vk::DeviceInterface& vkd, vk::VkDevice device, vk::VkDeviceMemory memory, vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType) { const vk::VkMemoryGetFdInfoKHR info = { vk::VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR, DE_NULL, memory, externalType }; int fd = -1; VK_CHECK(vkd.getMemoryFdKHR(device, &info, &fd)); TCU_CHECK(fd >= 0); return fd; }
int getSemaphoreFd (const vk::DeviceInterface& vkd, vk::VkDevice device, vk::VkSemaphore semaphore, vk::VkExternalSemaphoreHandleTypeFlagBitsKHR externalType) { const vk::VkSemaphoreGetFdInfoKHR info = { vk::VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR, DE_NULL, semaphore, externalType }; int fd = -1; VK_CHECK(vkd.getSemaphoreFdKHR(device, &info, &fd)); TCU_CHECK(fd >= 0); return fd; }
int getFenceFd (const vk::DeviceInterface& vkd, vk::VkDevice device, vk::VkFence fence, vk::VkExternalFenceHandleTypeFlagBitsKHR externalType) { const vk::VkFenceGetFdInfoKHR info = { vk::VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR, DE_NULL, fence, externalType }; int fd = -1; VK_CHECK(vkd.getFenceFdKHR(device, &info, &fd)); TCU_CHECK(fd >= 0); return fd; }
static void glfw_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { if (action == GLFW_PRESS) { if (key == GLFW_KEY_ESCAPE) { glfwSetWindowShouldClose(window, GLFW_TRUE); } else if (key == GLFW_KEY_F11 || key == GLFW_KEY_ENTER && mods == GLFW_MOD_ALT) { static int last_window_xpos, last_window_ypos; static int last_window_width, last_window_height; VK_CHECK(vkDeviceWaitIdle(vk.device)); GLFWmonitor* monitor = glfwGetWindowMonitor(window); if (monitor == nullptr) { glfwGetWindowPos(window, &last_window_xpos, &last_window_ypos); last_window_width = window_width; last_window_height = window_height; monitor = glfwGetPrimaryMonitor(); const GLFWvidmode* mode = glfwGetVideoMode(monitor); glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate); } else { glfwSetWindowMonitor(window, nullptr, last_window_xpos, last_window_ypos, last_window_width, last_window_height, 0); } } } }
void endCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer) { VK_CHECK(vk.endCommandBuffer(commandBuffer)); }
int main(int argc, char** argv) { Command_Line_Options options{}; if (!parse_command_line(argc, argv, options)) return 0; glfwSetErrorCallback(glfw_error_callback); if (!glfwInit()) error("glfwInit failed"); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); GLFWwindow* glfw_window = glfwCreateWindow(window_width, window_height, "Vulkan demo", nullptr, nullptr); assert(glfw_window != nullptr); glfwSetKeyCallback(glfw_window, glfw_key_callback); Vk_Demo demo{}; demo.initialize(glfw_window, options.enable_validation_layers); bool prev_vsync = demo.vsync_enabled(); bool window_active = true; while (!glfwWindowShouldClose(glfw_window)) { if (window_active) demo.run_frame(); glfwPollEvents(); int width, height; glfwGetWindowSize(glfw_window, &width, &height); bool recreate_swapchain = false; if (prev_vsync != demo.vsync_enabled()) { prev_vsync = demo.vsync_enabled(); recreate_swapchain = true; } else if (width != window_width || height != window_height) { window_width = width; window_height = height; recreate_swapchain = true; } window_active = (width != 0 && height != 0); if (!window_active) continue; if (recreate_swapchain) { VK_CHECK(vkDeviceWaitIdle(vk.device)); demo.release_resolution_dependent_resources(); vk_release_resolution_dependent_resources(); vk_restore_resolution_dependent_resources(demo.vsync_enabled()); demo.restore_resolution_dependent_resources(); recreate_swapchain = false; } platform::sleep(1); } demo.shutdown(); glfwTerminate(); return 0; }