[Bf-blender-cvs] [73b585b0b23] tmp-vulkan: GHOST: Vulkan: Add Test command buffers and sync primitives
Clément Foucault
noreply at git.blender.org
Fri Jul 24 22:09:20 CEST 2020
Commit: 73b585b0b2319597c27a276517d2d74ca7904a59
Author: Clément Foucault
Date: Fri Jul 24 17:00:06 2020 +0200
Branches: tmp-vulkan
https://developer.blender.org/rB73b585b0b2319597c27a276517d2d74ca7904a59
GHOST: Vulkan: Add Test command buffers and sync primitives
===================================================================
M intern/ghost/intern/GHOST_ContextVK.cpp
M intern/ghost/intern/GHOST_ContextVK.h
===================================================================
diff --git a/intern/ghost/intern/GHOST_ContextVK.cpp b/intern/ghost/intern/GHOST_ContextVK.cpp
index a5a735500d6..69fa7290a93 100644
--- a/intern/ghost/intern/GHOST_ContextVK.cpp
+++ b/intern/ghost/intern/GHOST_ContextVK.cpp
@@ -109,6 +109,9 @@ static const char *vulkan_error_as_string(VkResult result)
} \
} while (0)
+/* Tripple buffering. */
+const int MAX_FRAMES_IN_FLIGHT = 2;
+
GHOST_ContextVK::GHOST_ContextVK(bool stereoVisual,
#ifdef _WIN32
HWND hwnd,
@@ -133,6 +136,7 @@ GHOST_ContextVK::GHOST_ContextVK(bool stereoVisual,
m_instance(VK_NULL_HANDLE),
m_physical_device(VK_NULL_HANDLE),
m_device(VK_NULL_HANDLE),
+ m_commandPool(VK_NULL_HANDLE),
m_surface(VK_NULL_HANDLE),
m_swapchain(VK_NULL_HANDLE),
m_renderPass(VK_NULL_HANDLE)
@@ -141,6 +145,19 @@ GHOST_ContextVK::GHOST_ContextVK(bool stereoVisual,
GHOST_ContextVK::~GHOST_ContextVK()
{
+ if (m_device) {
+ vkDeviceWaitIdle(m_device);
+ }
+
+ for (auto semaphore : m_imageAvailableSemaphores) {
+ vkDestroySemaphore(m_device, semaphore, NULL);
+ }
+ for (auto semaphore : m_renderFinishedSemaphores) {
+ vkDestroySemaphore(m_device, semaphore, NULL);
+ }
+ for (auto fence : m_inFlightFences) {
+ vkDestroyFence(m_device, fence, NULL);
+ }
for (auto framebuffer : m_swapChainFramebuffers) {
vkDestroyFramebuffer(m_device, framebuffer, NULL);
}
@@ -153,6 +170,9 @@ GHOST_ContextVK::~GHOST_ContextVK()
if (m_swapchain != VK_NULL_HANDLE) {
vkDestroySwapchainKHR(m_device, m_swapchain, NULL);
}
+ if (m_commandPool != VK_NULL_HANDLE) {
+ vkDestroyCommandPool(m_device, m_commandPool, NULL);
+ }
if (m_device != VK_NULL_HANDLE) {
vkDestroyDevice(m_device, NULL);
}
@@ -166,6 +186,57 @@ GHOST_ContextVK::~GHOST_ContextVK()
GHOST_TSuccess GHOST_ContextVK::swapBuffers()
{
+ if (m_swapchain == VK_NULL_HANDLE) {
+ return GHOST_kFailure;
+ }
+
+ vkWaitForFences(m_device, 1, &m_inFlightFences[m_currentFrame], VK_TRUE, UINT64_MAX);
+
+ uint32_t image_id;
+ VK_CHECK(vkAcquireNextImageKHR(m_device,
+ m_swapchain,
+ UINT64_MAX,
+ m_imageAvailableSemaphores[m_currentFrame],
+ VK_NULL_HANDLE,
+ &image_id));
+
+ // Check if a previous frame is using this image (i.e. there is its fence to wait on)
+ if (m_imagesInFlight[image_id] != VK_NULL_HANDLE) {
+ vkWaitForFences(m_device, 1, &m_imagesInFlight[image_id], VK_TRUE, UINT64_MAX);
+ }
+ m_imagesInFlight[image_id] = m_inFlightFences[m_currentFrame];
+
+ VkPipelineStageFlags wait_stages[] = {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT};
+
+ VkSubmitInfo submit_info{
+ .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ .waitSemaphoreCount = 1,
+ .pWaitSemaphores = &m_imageAvailableSemaphores[m_currentFrame],
+ .pWaitDstStageMask = wait_stages,
+ .commandBufferCount = 1,
+ .pCommandBuffers = &m_commandBuffers[image_id],
+ .signalSemaphoreCount = 1,
+ .pSignalSemaphores = &m_renderFinishedSemaphores[m_currentFrame],
+ };
+
+ vkResetFences(m_device, 1, &m_inFlightFences[m_currentFrame]);
+
+ VK_CHECK(vkQueueSubmit(m_graphic_queue, 1, &submit_info, m_inFlightFences[m_currentFrame]));
+
+ VkPresentInfoKHR present_info{
+ .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
+ .waitSemaphoreCount = 1,
+ .pWaitSemaphores = &m_renderFinishedSemaphores[m_currentFrame],
+ .swapchainCount = 1,
+ .pSwapchains = &m_swapchain,
+ .pImageIndices = &image_id,
+ .pResults = NULL,
+ };
+
+ VK_CHECK(vkQueuePresentKHR(m_present_queue, &present_info));
+
+ m_currentFrame = (m_currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
+
return GHOST_kSuccess;
}
@@ -444,6 +515,34 @@ static GHOST_TSuccess create_render_pass(VkDevice device,
return GHOST_kSuccess;
}
+static GHOST_TSuccess selectPresentMode(VkPhysicalDevice device,
+ VkSurfaceKHR surface,
+ VkPresentModeKHR *r_presentMode)
+{
+ uint32_t present_count;
+ vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &present_count, NULL);
+ vector<VkPresentModeKHR> presents(present_count);
+ vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &present_count, presents.data());
+ /* MAILBOX is the lowest latency V-Sync enabled mode so use it if available */
+ for (auto present_mode : presents) {
+ if (present_mode == VK_PRESENT_MODE_FIFO_KHR) {
+ *r_presentMode = present_mode;
+ return GHOST_kSuccess;
+ }
+ }
+ /* FIFO present mode is always available. */
+ for (auto present_mode : presents) {
+ if (present_mode == VK_PRESENT_MODE_MAILBOX_KHR) {
+ *r_presentMode = present_mode;
+ return GHOST_kSuccess;
+ }
+ }
+
+ cout << "Error: FIFO present mode is not supported by the swap chain!\n";
+
+ return GHOST_kFailure;
+}
+
GHOST_TSuccess GHOST_ContextVK::createSwapChain(void)
{
VkPhysicalDevice device = m_physical_device;
@@ -456,13 +555,10 @@ GHOST_TSuccess GHOST_ContextVK::createSwapChain(void)
/* TODO choose appropriate format. */
VkSurfaceFormatKHR format = formats[0];
- uint32_t present_count;
- vkGetPhysicalDeviceSurfacePresentModesKHR(device, m_surface, &present_count, NULL);
- vector<VkPresentModeKHR> presents(present_count);
- vkGetPhysicalDeviceSurfacePresentModesKHR(device, m_surface, &present_count, presents.data());
-
- /* TODO choose appropriate present mode . */
- VkPresentModeKHR present_mode = presents[0];
+ VkPresentModeKHR present_mode;
+ if (!selectPresentMode(device, m_surface, &present_mode)) {
+ return GHOST_kFailure;
+ }
VkSurfaceCapabilitiesKHR capabilities;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, m_surface, &capabilities);
@@ -524,6 +620,7 @@ GHOST_TSuccess GHOST_ContextVK::createSwapChain(void)
m_swapChainImages.resize(image_count);
vkGetSwapchainImagesKHR(m_device, m_swapchain, &image_count, m_swapChainImages.data());
+ m_imagesInFlight.resize(image_count, VK_NULL_HANDLE);
m_swapChainImageViews.resize(image_count);
m_swapChainFramebuffers.resize(image_count);
for (int i = 0; i < image_count; i++) {
@@ -566,6 +663,26 @@ GHOST_TSuccess GHOST_ContextVK::createSwapChain(void)
VK_CHECK(vkCreateFramebuffer(m_device, &fb_create_info, NULL, &m_swapChainFramebuffers[i]));
}
+ m_imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
+ m_renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
+ m_inFlightFences.resize(MAX_FRAMES_IN_FLIGHT);
+ for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
+
+ VkSemaphoreCreateInfo semaphore_info = {
+ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
+ };
+
+ VK_CHECK(vkCreateSemaphore(m_device, &semaphore_info, NULL, &m_imageAvailableSemaphores[i]));
+ VK_CHECK(vkCreateSemaphore(m_device, &semaphore_info, NULL, &m_renderFinishedSemaphores[i]));
+
+ VkFenceCreateInfo fence_info = {
+ .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
+ .flags = VK_FENCE_CREATE_SIGNALED_BIT,
+ };
+
+ VK_CHECK(vkCreateFence(m_device, &fence_info, NULL, &m_inFlightFences[i]));
+ }
+
return GHOST_kSuccess;
}
@@ -707,8 +824,64 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
vkGetDeviceQueue(m_device, m_queue_family_present, 0, &m_present_queue);
createSwapChain();
- }
+ {
+ /* This is only a test. */
+ m_commandBuffers.resize(m_swapChainImageViews.size());
+
+ VkCommandPoolCreateInfo poolInfo = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
+ .flags = 0, // Optional
+ .queueFamilyIndex = m_queue_family_graphic,
+ };
+
+ VK_CHECK(vkCreateCommandPool(m_device, &poolInfo, NULL, &m_commandPool));
+
+ VkCommandBufferAllocateInfo alloc_info = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+ .commandPool = m_commandPool,
+ .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+ .commandBufferCount = static_cast<uint32_t>(m_commandBuffers.size()),
+ };
+
+ VK_CHECK(vkAllocateCommandBuffers(m_device, &alloc_info, m_commandBuffers.data()));
+
+ for (int i = 0; i < m_commandBuffers.size(); i++) {
+ VkCommandBufferBeginInfo begin_info = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+ .flags = 0,
+ .pInheritanceInfo = NULL, // Optional
+ };
+
+ VK_CHECK(vkBeginCommandBuffer(m_commandBuffers[i], &begin_info));
+
+ {
+ VkRect2D area = {
+ .offset = {0, 0},
+ .extent = m_swapChainExtent,
+ };
+
+ VkClearValue clearColor = {0.0f, 0.5f, 0.3f, 1.0f};
+ VkRenderPassBeginInfo render_pass_info = {
+ .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
+ .renderPass = m_renderPass,
+ .framebuffer = m_swapChainFramebuffers[i],
+ .renderArea = area,
+ .clearValueCount = 1,
+ .pClearValues = &clearColor,
+ };
+
+ vkCmdBeginRenderPass(m_commandBuffers[i], &render_pass_info, VK_SUBPASS_CONTENTS_INLINE);
+
+ /* TODO draw something. */
+
+ vkCmdEndRenderPass(m_commandBuffers[i]);
+ }
+
+ VK_CHECK(vkEndCommandBuffer(m_commandBuffers[i]));
+ }
+ }
+ }
return GHOST_kFailure;
}
diff --git a/intern/ghost/intern/GHOST_ContextVK.h b/intern/ghost/intern/GHOST_ContextVK.h
index a7493fab014..248d7ef5a5e 100644
--- a/intern/ghost/intern/GHOST_ContextVK.h
+++ b/intern/ghost/intern/GHOST_ContextVK.h
@@ -128,6 +128,7 @@ class GHOST_ContextVK : public GHOST_Context {
VkInstance m_instance;
VkPhysicalDevice m_physical_device;
VkDevice m_device;
+ VkCommandPool m_commandPool;
uint32_t m_queue_family_graphic;
uint32_t m_queue_family_present;
@@ -141,9 +142,15 @@ class GHOST_ContextVK : public GHOST_Context {
std::vector<VkImage> m_swapChainImages;
std::vector<VkImageView> m_swapChainImageViews;
std::vector<VkFramebuffer> m_swapChainFramebuffers;
+ std::vector<VkCommandBuffer> m_commandBuffers;
VkR
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list