Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/drape
diff options
context:
space:
mode:
authorDaria Volvenkova <d.volvenkova@corp.mail.ru>2019-02-04 17:30:08 +0300
committerDaria Volvenkova <d.volvenkova@corp.mail.ru>2019-03-01 10:45:24 +0300
commit19a92b08e96c9a4ab218921a5df7ea4ff75f138c (patch)
tree1c425934b280da8c8249c787aa32e5a7fd408825 /drape
parente4419da54e33a279566a3e6d253838b7632d4a71 (diff)
[vulkan] Rendering sketch.
Diffstat (limited to 'drape')
-rw-r--r--drape/graphics_context.hpp1
-rw-r--r--drape/vulkan/vulkan_base_context.cpp501
-rw-r--r--drape/vulkan/vulkan_base_context.hpp97
-rw-r--r--drape/vulkan/vulkan_memory_manager.cpp9
-rw-r--r--drape/vulkan/vulkan_mesh_object_impl.cpp2
-rw-r--r--drape/vulkan/vulkan_object_manager.cpp25
-rw-r--r--drape/vulkan/vulkan_object_manager.hpp2
-rw-r--r--drape/vulkan/vulkan_texture.cpp13
-rw-r--r--drape/vulkan/vulkan_utils.hpp6
-rw-r--r--drape/vulkan/vulkan_vertex_array_buffer_impl.cpp2
10 files changed, 604 insertions, 54 deletions
diff --git a/drape/graphics_context.hpp b/drape/graphics_context.hpp
index 6600d64f60..1019ec6d9f 100644
--- a/drape/graphics_context.hpp
+++ b/drape/graphics_context.hpp
@@ -51,6 +51,7 @@ class GraphicsContext
{
public:
virtual ~GraphicsContext() = default;
+ virtual void BeginRendering() {}
virtual void Present() = 0;
virtual void MakeCurrent() = 0;
virtual void DoneCurrent() {}
diff --git a/drape/vulkan/vulkan_base_context.cpp b/drape/vulkan/vulkan_base_context.cpp
index 3b85d9f400..f5f7ecaf03 100644
--- a/drape/vulkan/vulkan_base_context.cpp
+++ b/drape/vulkan/vulkan_base_context.cpp
@@ -1,4 +1,5 @@
#include "drape/vulkan/vulkan_base_context.hpp"
+#include "drape/vulkan/vulkan_utils.hpp"
#include "drape/framebuffer.hpp"
@@ -15,14 +16,28 @@ namespace vulkan
VulkanBaseContext::VulkanBaseContext(VkInstance vulkanInstance, VkPhysicalDevice gpu,
VkPhysicalDeviceProperties const & gpuProperties,
VkDevice device, uint32_t renderingQueueFamilyIndex,
- ref_ptr<VulkanObjectManager> objectManager)
+ VkFormat depthFormat, ref_ptr<VulkanObjectManager> objectManager)
: m_vulkanInstance(vulkanInstance)
, m_gpu(gpu)
, m_gpuProperties(gpuProperties)
, m_device(device)
, m_renderingQueueFamilyIndex(renderingQueueFamilyIndex)
+ , m_depthFormat(depthFormat)
, m_objectManager(objectManager)
-{}
+{
+ // Get a graphics queue from the device
+ vkGetDeviceQueue(m_device, m_renderingQueueFamilyIndex, 0, &m_queue);
+}
+
+VulkanBaseContext::~VulkanBaseContext()
+{
+ DestroyDefaultFramebuffer();
+ DestroyDepthTexture();
+ DestroySwapchain();
+ DestroyRenderPass();
+ DestroyCommandBuffer();
+ DestroyCommandPool();
+}
std::string VulkanBaseContext::GetRendererName() const
{
@@ -41,26 +56,115 @@ std::string VulkanBaseContext::GetRendererVersion() const
return ss.str();
}
-void VulkanBaseContext::SetStencilReferenceValue(uint32_t stencilReferenceValue)
+void VulkanBaseContext::MakeCurrent()
{
- m_stencilReferenceValue = stencilReferenceValue;
+
}
-void VulkanBaseContext::SetSurface(VkSurfaceKHR surface, VkFormat surfaceFormat,
- int width, int height)
+void VulkanBaseContext::DoneCurrent()
+{
+
+}
+
+bool VulkanBaseContext::Validate()
+{
+ return true;
+}
+
+void VulkanBaseContext::Resize(int w, int h)
+{
+}
+
+void VulkanBaseContext::SetFramebuffer(ref_ptr<dp::BaseFramebuffer> framebuffer)
+{
+
+}
+
+void VulkanBaseContext::ApplyFramebuffer(std::string const & framebufferLabel)
+{
+}
+
+void VulkanBaseContext::Init(ApiVersion apiVersion)
+{
+}
+
+void VulkanBaseContext::SetClearColor(Color const & color)
+{
+
+}
+
+void VulkanBaseContext::Clear(uint32_t clearBits, uint32_t storeBits)
+{
+ //vkCmdClearColorImage();
+}
+
+void VulkanBaseContext::Flush()
+{
+
+}
+
+void VulkanBaseContext::SetViewport(uint32_t x, uint32_t y, uint32_t w, uint32_t h)
+{
+ VkViewport viewport;
+ viewport.width = w;
+ viewport.height = h;
+ viewport.minDepth = 0.0f;
+ viewport.maxDepth = 1.0f;
+ vkCmdSetViewport(GetCurrentCommandBuffer(), 0, 1, &viewport);
+
+ VkRect2D scissor = {};
+ scissor.extent = {w, h};
+ scissor.offset.x = x;
+ scissor.offset.y = y;
+ vkCmdSetScissor(GetCurrentCommandBuffer(), 0, 1, &scissor);
+}
+
+void VulkanBaseContext::SetSurface(VkSurfaceKHR surface, VkSurfaceFormatKHR surfaceFormat,
+ VkSurfaceCapabilitiesKHR surfaceCapabilities, int width, int height)
{
m_surface = surface;
- //TODO: initialize swapchains, image views and so on.
+ if (!m_surfaceFormat.is_initialized() ||
+ m_surfaceFormat.get().format != surfaceFormat.format ||
+ m_surfaceFormat.get().colorSpace != surfaceFormat.colorSpace)
+ {
+ if (m_surfaceFormat.is_initialized())
+ {
+ DestroyRenderPass();
+ DestroyCommandBuffer();
+ DestroyCommandPool();
+ DestroyDepthTexture();
+ }
+ m_surfaceFormat = surfaceFormat;
+ m_surfaceCapabilities = surfaceCapabilities;
+ CreateRenderPass();
+ CreateCommandPool();
+ CreateCommandBuffer();
+ CreateDepthTexture();
+ }
+ RecreateSwapchain();
+ CreateDefaultFramebuffer();
}
void VulkanBaseContext::ResetSurface()
{
vkDeviceWaitIdle(m_device);
-
- //TODO: reset swapchains, image views and so on.
+ DestroyDefaultFramebuffer();
m_surface.reset();
}
+void VulkanBaseContext::BeginRendering()
+{
+ // Record command buffer.
+ // A fence is used to wait until this command buffer has finished execution and is no longer in-flight
+ // Command buffers can only be re-recorded or destroyed if they are not in-flight
+ CHECK_VK_CALL(vkWaitForFences(m_device, 1, &m_fence, VK_TRUE, UINT64_MAX));
+ CHECK_VK_CALL(vkResetFences(m_device, 1, &m_fence));
+
+ VkCommandBufferBeginInfo commandBufferBeginInfo = {};
+ commandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ CHECK_VK_CALL(vkBeginCommandBuffer(m_commandBuffer, &commandBufferBeginInfo));
+}
+
void VulkanBaseContext::Present()
{
// Resetting of the default staging buffer must be before submitting the queue.
@@ -72,7 +176,83 @@ void VulkanBaseContext::Present()
// TODO: wait for all map-memory operations.
- // TODO: submit queue, wait for finishing of rendering.
+ // Prepare frame. Acquire next image.
+ // By setting timeout to UINT64_MAX we will always wait until the next image has been acquired or an actual
+ // error is thrown. With that we don't have to handle VK_NOT_READY
+ VkResult res = vkAcquireNextImageKHR(m_device, m_swapchain, UINT64_MAX, m_presentComplete,
+ (VkFence)nullptr, &m_imageIndex); //???????????????????????????????????
+ if (res == VK_ERROR_OUT_OF_DATE_KHR || res == VK_SUBOPTIMAL_KHR)
+ {
+ // Recreate the swapchain if it's no longer compatible with the surface (OUT_OF_DATE)
+ // or no longer optimal for presentation (SUBOPTIMAL)
+ RecreateSwapchain();
+ }
+ else
+ {
+ CHECK_RESULT_VK_CALL(vkAcquireNextImageKHR, res);
+ }
+
+ VkClearValue clearValues[2];
+ clearValues[0].color = {1.0f, 0.0f, 1.0f, 1.0f};
+ clearValues[1].depthStencil = { 1.0f, 0 };
+
+ VkRenderPassBeginInfo renderPassBeginInfo = {};
+ renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ renderPassBeginInfo.renderPass = m_renderPass;
+ renderPassBeginInfo.renderArea.offset.x = 0;
+ renderPassBeginInfo.renderArea.offset.y = 0;
+ renderPassBeginInfo.renderArea.extent = m_surfaceCapabilities.currentExtent;
+ renderPassBeginInfo.clearValueCount = 2;
+ renderPassBeginInfo.pClearValues = clearValues;
+ renderPassBeginInfo.framebuffer = m_defaultFramebuffers[m_imageIndex];
+ vkCmdBeginRenderPass(m_commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+ vkCmdEndRenderPass(m_commandBuffer);
+ CHECK_VK_CALL(vkEndCommandBuffer(m_commandBuffer));
+
+ // Pipeline stage at which the queue submission will wait (via pWaitSemaphores)
+ const VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+
+ VkSubmitInfo submitInfo = {};
+ submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submitInfo.pWaitDstStageMask = &waitStageMask;
+ submitInfo.pWaitSemaphores = &m_presentComplete;
+ submitInfo.waitSemaphoreCount = 1;
+ submitInfo.pSignalSemaphores = &m_renderComplete;
+ submitInfo.signalSemaphoreCount = 1;
+ submitInfo.commandBufferCount = 1;
+ submitInfo.pCommandBuffers = &m_commandBuffer;
+
+ CHECK_VK_CALL(vkQueueSubmit(m_queue, 1, &submitInfo, m_fence));
+ //CHECK_VK_CALL(vkQueueWaitIdle(m_queue));
+
+ // Queue an image for presentation.
+ VkPresentInfoKHR presentInfo = {};
+ presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
+ presentInfo.pNext = nullptr;
+ presentInfo.swapchainCount = 1;
+ presentInfo.pSwapchains = &m_swapchain;
+ presentInfo.pImageIndices = &m_imageIndex;
+ // Check if a wait semaphore has been specified to wait for before presenting the image
+ presentInfo.pWaitSemaphores = &m_renderComplete;
+ presentInfo.waitSemaphoreCount = 1;
+ res = vkQueuePresentKHR(m_queue, &presentInfo);
+ if (!(res == VK_SUCCESS || res == VK_SUBOPTIMAL_KHR))
+ {
+ if (res == VK_ERROR_OUT_OF_DATE_KHR)
+ {
+ // Swap chain is no longer compatible with the surface and needs to be recreated
+ RecreateSwapchain();
+ }
+ else
+ {
+ CHECK_RESULT_VK_CALL(vkQueuePresentKHR, res);
+ }
+ }
+ else
+ {
+ CHECK_VK_CALL(vkQueueWaitIdle(m_queue));
+ }
for (auto const & h : m_handlers[static_cast<uint32_t>(HandlerType::PostPresent)])
h.second(make_ref(this));
@@ -104,5 +284,306 @@ void VulkanBaseContext::UnregisterHandler(uint32_t id)
}), m_handlers[i].end());
}
}
+
+void VulkanBaseContext::RecreateSwapchain()
+{
+ CHECK(m_surface.is_initialized(), ());
+ CHECK(m_surfaceFormat.is_initialized(), ());
+
+ VkSwapchainKHR oldSwapchain = m_swapchain;
+
+ VkSwapchainCreateInfoKHR swapchainCreateInfo = {};
+ swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
+ swapchainCreateInfo.pNext = nullptr;
+ swapchainCreateInfo.surface = m_surface.get();
+ swapchainCreateInfo.minImageCount = std::min(m_surfaceCapabilities.minImageCount + 1,
+ m_surfaceCapabilities.maxImageCount);
+ swapchainCreateInfo.imageFormat = m_surfaceFormat.get().format;
+ swapchainCreateInfo.imageColorSpace = m_surfaceFormat.get().colorSpace;
+ swapchainCreateInfo.imageExtent = m_surfaceCapabilities.currentExtent;
+
+ swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+
+ if (m_surfaceCapabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT)
+ swapchainCreateInfo.imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+
+ if (m_surfaceCapabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT)
+ swapchainCreateInfo.imageUsage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+
+ CHECK(m_surfaceCapabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, ());
+ swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
+
+ swapchainCreateInfo.imageArrayLayers = 1;
+ swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ swapchainCreateInfo.queueFamilyIndexCount = 0;
+ swapchainCreateInfo.pQueueFamilyIndices = nullptr;
+
+ CHECK(m_surfaceCapabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR, ());
+ swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
+
+ // This mode waits for the vertical blank ("v-sync")
+ swapchainCreateInfo.presentMode = VK_PRESENT_MODE_FIFO_KHR;
+
+ swapchainCreateInfo.oldSwapchain = oldSwapchain;
+ // Setting clipped to VK_TRUE allows the implementation to discard rendering outside of the surface area
+ swapchainCreateInfo.clipped = VK_TRUE;
+
+ CHECK_VK_CALL(vkCreateSwapchainKHR(m_device, &swapchainCreateInfo, nullptr, &m_swapchain));
+
+ if (oldSwapchain != VK_NULL_HANDLE)
+ {
+ for (auto const & imageView : m_swapchainImageViews)
+ vkDestroyImageView(m_device, imageView, nullptr);
+ m_swapchainImageViews.clear();
+ vkDestroySwapchainKHR(m_device, oldSwapchain, nullptr);
+ }
+
+ // Create swapchain image views
+ uint32_t swapchainImageCount = 0;
+ CHECK_VK_CALL(vkGetSwapchainImagesKHR(m_device, m_swapchain, &swapchainImageCount, nullptr));
+
+ std::vector<VkImage> swapchainImages(swapchainImageCount);
+ CHECK_VK_CALL(vkGetSwapchainImagesKHR(m_device, m_swapchain, &swapchainImageCount, swapchainImages.data()));
+
+ m_swapchainImageViews.resize(swapchainImages.size());
+ for (size_t i = 0; i < m_swapchainImageViews.size(); ++i)
+ {
+ VkImageViewCreateInfo colorAttachmentImageView = {};
+ colorAttachmentImageView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ colorAttachmentImageView.image = swapchainImages[i];
+ colorAttachmentImageView.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ colorAttachmentImageView.format = m_surfaceFormat.get().format;
+ colorAttachmentImageView.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
+ colorAttachmentImageView.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
+ colorAttachmentImageView.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
+ colorAttachmentImageView.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
+ colorAttachmentImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ colorAttachmentImageView.subresourceRange.baseMipLevel = 0;
+ colorAttachmentImageView.subresourceRange.levelCount = 1;
+ colorAttachmentImageView.subresourceRange.baseArrayLayer = 0;
+ colorAttachmentImageView.subresourceRange.layerCount = 1;
+ CHECK_VK_CALL(vkCreateImageView(m_device, &colorAttachmentImageView, nullptr, &m_swapchainImageViews[i]));
+ }
+}
+
+void VulkanBaseContext::DestroySwapchain()
+{
+ for (auto const & imageView : m_swapchainImageViews)
+ vkDestroyImageView(m_device, imageView, nullptr);
+ m_swapchainImageViews.clear();
+ vkDestroySwapchainKHR(m_device, m_swapchain, nullptr);
+ m_swapchain = VK_NULL_HANDLE;
+}
+
+void VulkanBaseContext::CreateCommandPool()
+{
+ VkCommandPoolCreateInfo commandPoolCI = {};
+ commandPoolCI.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+ // This flag will implicitly reset command buffers from this pool when calling vkBeginCommandBuffer
+ commandPoolCI.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
+ commandPoolCI.queueFamilyIndex = m_renderingQueueFamilyIndex;
+ CHECK_VK_CALL(vkCreateCommandPool(m_device, &commandPoolCI, nullptr, &m_commandPool));
+}
+
+void VulkanBaseContext::DestroyCommandPool()
+{
+ vkDestroyCommandPool(m_device, m_commandPool, nullptr);
+}
+
+void VulkanBaseContext::CreateCommandBuffer()
+{
+ // A fence is need to check for command buffer completion before we can recreate it
+ VkFenceCreateInfo fenceCI = {};
+ fenceCI.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+ fenceCI.flags = VK_FENCE_CREATE_SIGNALED_BIT;
+ CHECK_VK_CALL(vkCreateFence(m_device, &fenceCI, nullptr, &m_fence));
+
+ // Semaphores are used to order queue submissions
+ VkSemaphoreCreateInfo semaphoreCI = {};
+ semaphoreCI.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+
+ CHECK_VK_CALL(vkCreateSemaphore(m_device, &semaphoreCI, nullptr, &m_presentComplete));
+ CHECK_VK_CALL(vkCreateSemaphore(m_device, &semaphoreCI, nullptr, &m_renderComplete));
+
+ // Create a single command buffer that is recorded every frame
+ VkCommandBufferAllocateInfo cmdBufAllocateInfo = {};
+ cmdBufAllocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ cmdBufAllocateInfo.commandPool = m_commandPool;
+ cmdBufAllocateInfo.commandBufferCount = 1;
+ cmdBufAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ CHECK_VK_CALL(vkAllocateCommandBuffers(m_device, &cmdBufAllocateInfo, &m_commandBuffer));
+}
+
+void VulkanBaseContext::DestroyCommandBuffer()
+{
+ vkDestroyFence(m_device, m_fence, nullptr);
+ vkDestroySemaphore(m_device, m_presentComplete, nullptr);
+ vkDestroySemaphore(m_device, m_renderComplete, nullptr);
+ vkFreeCommandBuffers(m_device, m_commandPool, 1, &m_commandBuffer);
+}
+
+void VulkanBaseContext::CreateDepthTexture()
+{
+ CHECK(m_depthStencil.m_image == VK_NULL_HANDLE, ());
+ m_depthStencil = m_objectManager->CreateImage(
+ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
+ m_depthFormat,
+ VK_IMAGE_ASPECT_DEPTH_BIT /*| VK_IMAGE_ASPECT_STENCIL_BIT*/,
+ m_surfaceCapabilities.currentExtent.width, m_surfaceCapabilities.currentExtent.height);
+}
+
+void VulkanBaseContext::DestroyDepthTexture()
+{
+ if (m_depthStencil.m_image != VK_NULL_HANDLE)
+ m_objectManager->DestroyObject(m_depthStencil);
+}
+
+void VulkanBaseContext::CreateDefaultFramebuffer()
+{
+ std::array<VkImageView, 2> attachments = {};
+
+ // Depth/Stencil attachment is the same for all frame buffers
+ attachments[1] = m_depthStencil.m_imageView;
+
+ VkFramebufferCreateInfo frameBufferCreateInfo = {};
+ frameBufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ frameBufferCreateInfo.pNext = nullptr;
+ frameBufferCreateInfo.renderPass = m_renderPass;
+ frameBufferCreateInfo.attachmentCount = 2;
+ frameBufferCreateInfo.pAttachments = attachments.data();
+ frameBufferCreateInfo.width = m_surfaceCapabilities.currentExtent.width;
+ frameBufferCreateInfo.height = m_surfaceCapabilities.currentExtent.height;
+ frameBufferCreateInfo.layers = 1;
+
+ // Create frame buffers for every swap chain image
+ m_defaultFramebuffers.resize(m_swapchainImageViews.size());
+ for (uint32_t i = 0; i < m_defaultFramebuffers.size(); i++)
+ {
+ attachments[0] = m_swapchainImageViews[i];
+ CHECK_VK_CALL(vkCreateFramebuffer(m_device, &frameBufferCreateInfo, nullptr, &m_defaultFramebuffers[i]));
+ }
+}
+
+void VulkanBaseContext::DestroyDefaultFramebuffer()
+{
+ for (uint32_t i = 0; i < m_defaultFramebuffers.size(); i++)
+ {
+ vkDestroyFramebuffer(m_device, m_defaultFramebuffers[i], nullptr);
+ }
+ m_defaultFramebuffers.clear();
+}
+
+void VulkanBaseContext::CreateRenderPass()
+{
+ std::array<VkAttachmentDescription, 2> attachments = {};
+
+ // Color attachment
+ attachments[0].format = m_surfaceFormat.get().format;
+ attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
+ attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+ // Depth attachment
+ attachments[1].format = m_depthFormat;
+ attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
+ attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+ VkAttachmentReference colorReference = {};
+ colorReference.attachment = 0;
+ colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ VkAttachmentReference depthReference = {};
+ depthReference.attachment = 1;
+ depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+ VkSubpassDescription subpassDescription = {};
+ subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ subpassDescription.colorAttachmentCount = 1;
+ subpassDescription.pColorAttachments = &colorReference;
+ subpassDescription.pDepthStencilAttachment = &depthReference;
+ subpassDescription.inputAttachmentCount = 0;
+ subpassDescription.pInputAttachments = nullptr;
+ subpassDescription.preserveAttachmentCount = 0;
+ subpassDescription.pPreserveAttachments = nullptr;
+ subpassDescription.pResolveAttachments = nullptr;
+
+ // Subpass dependencies for layout transitions
+ std::array<VkSubpassDependency, 2> dependencies;
+
+ dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
+ dependencies[0].dstSubpass = 0;
+ dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
+ dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
+
+ dependencies[1].srcSubpass = 0;
+ dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL;
+ dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; //??????????????????????
+ dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
+ dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
+
+ VkRenderPassCreateInfo renderPassInfo = {};
+ renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ renderPassInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
+ renderPassInfo.pAttachments = attachments.data();
+ renderPassInfo.subpassCount = 1;
+ renderPassInfo.pSubpasses = &subpassDescription;
+ renderPassInfo.dependencyCount = static_cast<uint32_t>(dependencies.size());
+ renderPassInfo.pDependencies = dependencies.data();
+
+ CHECK_VK_CALL(vkCreateRenderPass(m_device, &renderPassInfo, nullptr, &m_renderPass));
+}
+
+void VulkanBaseContext::DestroyRenderPass()
+{
+ vkDestroyRenderPass(m_device, m_renderPass, nullptr);
+}
+
+void VulkanBaseContext::SetDepthTestEnabled(bool enabled)
+{
+ m_depthEnabled = enabled;
+}
+
+void VulkanBaseContext::SetDepthTestFunction(TestFunction depthFunction)
+{
+ m_depthFunction = depthFunction;
+}
+
+void VulkanBaseContext::SetStencilTestEnabled(bool enabled)
+{
+ m_stencilEnabled = enabled;
+}
+
+void VulkanBaseContext::SetStencilFunction(StencilFace face, TestFunction stencilFunction)
+{
+ m_stencilFunctionFace = face;
+ m_stencilFunction = stencilFunction;
+}
+
+void VulkanBaseContext::SetStencilActions(StencilFace face, StencilAction stencilFailAction,
+ StencilAction depthFailAction, StencilAction passAction)
+{
+ m_stencilActionFace = face;
+ m_stencilFailAction = stencilFailAction;
+ m_depthFailAction = depthFailAction;
+ m_passAction = passAction;
+}
+
+void VulkanBaseContext::SetStencilReferenceValue(uint32_t stencilReferenceValue)
+{
+ m_stencilReferenceValue = stencilReferenceValue;
+}
} // namespace vulkan
} // namespace dp
diff --git a/drape/vulkan/vulkan_base_context.hpp b/drape/vulkan/vulkan_base_context.hpp
index ac5f0657c7..640cef3ac5 100644
--- a/drape/vulkan/vulkan_base_context.hpp
+++ b/drape/vulkan/vulkan_base_context.hpp
@@ -26,18 +26,20 @@ public:
VulkanBaseContext(VkInstance vulkanInstance, VkPhysicalDevice gpu,
VkPhysicalDeviceProperties const & gpuProperties,
VkDevice device, uint32_t renderingQueueFamilyIndex,
- ref_ptr<VulkanObjectManager> objectManager);
+ VkFormat depthFormat, ref_ptr<VulkanObjectManager> objectManager);
+ ~VulkanBaseContext() override;
using ContextHandler = std::function<void(ref_ptr<VulkanBaseContext>)>;
+ void BeginRendering() override;
void Present() override;
- void MakeCurrent() override {}
- void DoneCurrent() override {}
- bool Validate() override { return true; }
- void Resize(int w, int h) override {}
- void SetFramebuffer(ref_ptr<dp::BaseFramebuffer> framebuffer) override {}
- void ApplyFramebuffer(std::string const & framebufferLabel) override {}
- void Init(ApiVersion apiVersion) override {}
+ void MakeCurrent() override;
+ void DoneCurrent() override;
+ bool Validate() override;
+ void Resize(int w, int h) override;
+ void SetFramebuffer(ref_ptr<dp::BaseFramebuffer> framebuffer) override;
+ void ApplyFramebuffer(std::string const & framebufferLabel) override;
+ void Init(ApiVersion apiVersion) override;
ApiVersion GetApiVersion() const override { return dp::ApiVersion::Vulkan; }
std::string GetRendererName() const override;
std::string GetRendererVersion() const override;
@@ -46,19 +48,20 @@ public:
void PushDebugLabel(std::string const & label) override {}
void PopDebugLabel() override {}
- void SetClearColor(Color const & color) override {}
- void Clear(uint32_t clearBits, uint32_t storeBits) override {}
- void Flush() override {}
- void SetViewport(uint32_t x, uint32_t y, uint32_t w, uint32_t h) override {}
- void SetDepthTestEnabled(bool enabled) override {}
- void SetDepthTestFunction(TestFunction depthFunction) override {}
- void SetStencilTestEnabled(bool enabled) override {}
- void SetStencilFunction(StencilFace face, TestFunction stencilFunction) override {}
+ void SetClearColor(Color const & color) override;
+ void Clear(uint32_t clearBits, uint32_t storeBits) override;
+ void Flush() override;
+ void SetViewport(uint32_t x, uint32_t y, uint32_t w, uint32_t h) override;
+ void SetDepthTestEnabled(bool enabled) override;
+ void SetDepthTestFunction(TestFunction depthFunction) override;
+ void SetStencilTestEnabled(bool enabled) override;
+ void SetStencilFunction(StencilFace face, TestFunction stencilFunction) override;
void SetStencilActions(StencilFace face, StencilAction stencilFailAction,
- StencilAction depthFailAction, StencilAction passAction) override {}
+ StencilAction depthFailAction, StencilAction passAction) override;
void SetStencilReferenceValue(uint32_t stencilReferenceValue) override;
- void SetSurface(VkSurfaceKHR surface, VkFormat surfaceFormat, int width, int height);
+ void SetSurface(VkSurfaceKHR surface, VkSurfaceFormatKHR surfaceFormat,
+ VkSurfaceCapabilitiesKHR surfaceCapabilities, int width, int height);
void ResetSurface();
VkPhysicalDevice const GetPhysicalDevice() const { return m_gpu; }
@@ -70,7 +73,7 @@ public:
ref_ptr<VulkanObjectManager> GetObjectManager() const { return m_objectManager; }
- VkCommandBuffer GetCurrentCommandBuffer() const { CHECK(false, ("Implement me")); return nullptr; }
+ VkCommandBuffer GetCurrentCommandBuffer() const { return m_commandBuffer; }
enum class HandlerType : uint8_t
{
@@ -83,18 +86,74 @@ public:
void UnregisterHandler(uint32_t id);
protected:
+ void RecreateSwapchain();
+ void DestroySwapchain();
+
+ void CreateCommandPool();
+ void DestroyCommandPool();
+
+ void CreateCommandBuffer();
+ void DestroyCommandBuffer();
+
+ void CreateDepthTexture();
+ void DestroyDepthTexture();
+
+ void CreateDefaultFramebuffer();
+ void DestroyDefaultFramebuffer();
+
+ void CreateRenderPass();
+ void DestroyRenderPass();
+
VkInstance const m_vulkanInstance;
VkPhysicalDevice const m_gpu;
VkPhysicalDeviceProperties const m_gpuProperties;
VkDevice const m_device;
uint32_t const m_renderingQueueFamilyIndex;
+ VkFormat const m_depthFormat;
+
+ VkQueue m_queue;
+ VkCommandPool m_commandPool;
+ VkPipelineCache m_pipelineCache;
+ VkSubmitInfo m_submitInfo;
+ VkCommandBuffer m_commandBuffer;
+ VkRenderPass m_renderPass;
+
+ // Swap chain image presentation
+ VkSemaphore m_presentComplete;
+ // Command buffer submission and execution
+ VkSemaphore m_renderComplete;
+
+ VkDescriptorPool m_descriptorPool = VK_NULL_HANDLE;
+ VkFence m_fence;
ref_ptr<VulkanObjectManager> m_objectManager;
boost::optional<VkSurfaceKHR> m_surface;
+ VkSurfaceCapabilitiesKHR m_surfaceCapabilities;
+ boost::optional<VkSurfaceFormatKHR> m_surfaceFormat;
+
+ VkSwapchainKHR m_swapchain = VK_NULL_HANDLE;
+ std::vector<VkImageView> m_swapchainImageViews;
+ uint32_t m_imageIndex = 0;
+
+ VulkanObject m_depthStencil;
+ std::vector<VkFramebuffer> m_defaultFramebuffers;
+
+ ref_ptr<dp::BaseFramebuffer> m_currentFramebuffer;
+
std::array<std::vector<std::pair<uint32_t, ContextHandler>>,
static_cast<size_t>(HandlerType::Count)> m_handlers;
+ bool m_depthEnabled = false;
+ bool m_stencilEnabled = false;
+ StencilFace m_stencilFunctionFace = {};
+ TestFunction m_stencilFunction = {};
+ TestFunction m_depthFunction = {};
+ StencilFace m_stencilActionFace = {};
+ StencilAction m_stencilFailAction = {};
+ StencilAction m_depthFailAction = {};
+ StencilAction m_passAction = {};
+
uint32_t m_stencilReferenceValue = 1;
};
} // namespace vulkan
diff --git a/drape/vulkan/vulkan_memory_manager.cpp b/drape/vulkan/vulkan_memory_manager.cpp
index 619d3c2e2a..3fc797a61e 100644
--- a/drape/vulkan/vulkan_memory_manager.cpp
+++ b/drape/vulkan/vulkan_memory_manager.cpp
@@ -146,7 +146,7 @@ VulkanMemoryManager::AllocationPtr VulkanMemoryManager::Allocate(ResourceType re
auto const alignedOffset = GetAligned(block->m_freeOffset, GetOffsetAlignment(resourceType));
// There is space in the current block.
- if (!block->m_isBlocked && (block->m_blockSize <= alignedOffset + alignedSize))
+ if (!block->m_isBlocked && (block->m_blockSize >= alignedOffset + alignedSize))
{
block->m_freeOffset = alignedOffset + alignedSize;
block->m_allocationCounter++;
@@ -187,13 +187,10 @@ VulkanMemoryManager::AllocationPtr VulkanMemoryManager::Allocate(ResourceType re
{
flags = fallbackFlags.value();
memoryTypeIndex = GetMemoryTypeIndex(memReqs.memoryTypeBits, flags);
- if (!memoryTypeIndex)
- CHECK(false, ("Unsupported memory allocation configuration."));
}
- else
- {
+
+ if (!memoryTypeIndex)
CHECK(false, ("Unsupported memory allocation configuration."));
- }
// Create new memory block.
auto const blockSize = std::max(kMinBlockSizeInBytes[static_cast<size_t>(resourceType)],
diff --git a/drape/vulkan/vulkan_mesh_object_impl.cpp b/drape/vulkan/vulkan_mesh_object_impl.cpp
index cffadd4efa..854ee577d9 100644
--- a/drape/vulkan/vulkan_mesh_object_impl.cpp
+++ b/drape/vulkan/vulkan_mesh_object_impl.cpp
@@ -122,7 +122,7 @@ public:
void DrawPrimitives(ref_ptr<dp::GraphicsContext> context, uint32_t verticesCount) override
{
//TODO (@rokuz, @darina): Implement.
- CHECK(false, ());
+ //CHECK(false, ());
}
void Bind(ref_ptr<dp::GpuProgram> program) override {}
diff --git a/drape/vulkan/vulkan_object_manager.cpp b/drape/vulkan/vulkan_object_manager.cpp
index 6ce98d5397..9d686816aa 100644
--- a/drape/vulkan/vulkan_object_manager.cpp
+++ b/drape/vulkan/vulkan_object_manager.cpp
@@ -40,7 +40,8 @@ VulkanObject VulkanObjectManager::CreateBuffer(VulkanMemoryManager::ResourceType
info.flags = 0;
info.size = sizeInBytes;
if (resourceType == VulkanMemoryManager::ResourceType::Geometry)
- info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
+ info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT |
+ VK_BUFFER_USAGE_TRANSFER_DST_BIT;
else if (resourceType == VulkanMemoryManager::ResourceType::Uniform)
info.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
else if (resourceType == VulkanMemoryManager::ResourceType::Staging)
@@ -48,7 +49,7 @@ VulkanObject VulkanObjectManager::CreateBuffer(VulkanMemoryManager::ResourceType
else
CHECK(false, ("Unsupported resource type."));
- info.usage = VK_SHARING_MODE_EXCLUSIVE;
+ info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
info.queueFamilyIndexCount = 1;
info.pQueueFamilyIndices = &m_queueFamilyIndex;
CHECK_VK_CALL(vkCreateBuffer(m_device, &info, nullptr, &result.m_buffer));
@@ -60,7 +61,7 @@ VulkanObject VulkanObjectManager::CreateBuffer(VulkanMemoryManager::ResourceType
return result;
}
-VulkanObject VulkanObjectManager::CreateImage(VkImageUsageFlagBits usageFlagBits, VkFormat format,
+VulkanObject VulkanObjectManager::CreateImage(VkImageUsageFlags usageFlags, VkFormat format,
VkImageAspectFlags aspectFlags, uint32_t width, uint32_t height)
{
std::lock_guard<std::mutex> lock(m_mutex);
@@ -78,9 +79,18 @@ VulkanObject VulkanObjectManager::CreateImage(VkImageUsageFlagBits usageFlagBits
imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageCreateInfo.extent = { width, height, 1 };
- imageCreateInfo.usage = usageFlagBits | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+ imageCreateInfo.usage = usageFlags | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
CHECK_VK_CALL(vkCreateImage(m_device, &imageCreateInfo, nullptr, &result.m_image));
+ VkMemoryRequirements memReqs = {};
+ vkGetImageMemoryRequirements(m_device, result.m_image, &memReqs);
+
+ result.m_allocation = m_memoryManager.Allocate(VulkanMemoryManager::ResourceType::Image,
+ memReqs, 0 /* blockHash */);
+
+ CHECK_VK_CALL(vkBindImageMemory(m_device, result.m_image,
+ result.GetMemory(), result.GetAlignedOffset()));
+
VkImageViewCreateInfo viewCreateInfo = {};
viewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewCreateInfo.pNext = nullptr;
@@ -96,11 +106,6 @@ VulkanObject VulkanObjectManager::CreateImage(VkImageUsageFlagBits usageFlagBits
viewCreateInfo.image = result.m_image;
CHECK_VK_CALL(vkCreateImageView(m_device, &viewCreateInfo, nullptr, &result.m_imageView));
- VkMemoryRequirements memReqs = {};
- vkGetImageMemoryRequirements(m_device, result.m_image, &memReqs);
-
- result.m_allocation = m_memoryManager.Allocate(VulkanMemoryManager::ResourceType::Image,
- memReqs, 0 /* blockHash */);
return result;
}
@@ -113,13 +118,11 @@ void VulkanObjectManager::DestroyObject(VulkanObject object)
void VulkanObjectManager::FlushDefaultStagingBuffer()
{
- std::lock_guard<std::mutex> lock(m_mutex);
m_defaultStagingBuffer->Flush();
}
void VulkanObjectManager::ResetDefaultStagingBuffer()
{
- std::lock_guard<std::mutex> lock(m_mutex);
m_defaultStagingBuffer->Reset();
}
diff --git a/drape/vulkan/vulkan_object_manager.hpp b/drape/vulkan/vulkan_object_manager.hpp
index 8fadbf8b57..e638f3dfbc 100644
--- a/drape/vulkan/vulkan_object_manager.hpp
+++ b/drape/vulkan/vulkan_object_manager.hpp
@@ -56,7 +56,7 @@ public:
VulkanObject CreateBuffer(VulkanMemoryManager::ResourceType resourceType,
uint32_t sizeInBytes, uint64_t batcherHash);
- VulkanObject CreateImage(VkImageUsageFlagBits usageFlagBits, VkFormat format,
+ VulkanObject CreateImage(VkImageUsageFlags usageFlags, VkFormat format,
VkImageAspectFlags aspectFlags, uint32_t width, uint32_t height);
uint8_t * Map(VulkanObject object);
diff --git a/drape/vulkan/vulkan_texture.cpp b/drape/vulkan/vulkan_texture.cpp
index a72d40abe5..c1847811b4 100644
--- a/drape/vulkan/vulkan_texture.cpp
+++ b/drape/vulkan/vulkan_texture.cpp
@@ -84,7 +84,7 @@ VkBufferImageCopy BufferCopyRegion(uint32_t x, uint32_t y, uint32_t width, uint3
{
VkBufferImageCopy bufferCopyRegion = {};
bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- bufferCopyRegion.imageSubresource.mipLevel = 1;
+ bufferCopyRegion.imageSubresource.mipLevel = 0;
bufferCopyRegion.imageSubresource.baseArrayLayer = 0;
bufferCopyRegion.imageSubresource.layerCount = 1;
bufferCopyRegion.imageExtent.width = width;
@@ -127,8 +127,11 @@ void VulkanTexture::Create(ref_ptr<dp::GraphicsContext> context, Params const &
m_isMutable = params.m_isMutable;
if (params.m_isRenderTarget)
{
- CHECK(false, ());
- //TODO
+ // Create image.
+ //m_textureObject = m_objectManager->CreateImage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
+ // format,
+ // VK_IMAGE_ASPECT_COLOR_BIT,
+ // params.m_width, params.m_height);
}
else
{
@@ -149,8 +152,8 @@ void VulkanTexture::Create(ref_ptr<dp::GraphicsContext> context, Params const &
m_textureObject = m_objectManager->CreateImage(VK_IMAGE_USAGE_SAMPLED_BIT, format,
VK_IMAGE_ASPECT_COLOR_BIT,
params.m_width, params.m_height);
- CHECK_VK_CALL(vkBindImageMemory(vulkanContext->GetDevice(), m_textureObject.m_image,
- m_textureObject.GetMemory(), m_textureObject.GetAlignedOffset()));
+ //CHECK_VK_CALL(vkBindImageMemory(vulkanContext->GetDevice(), m_textureObject.m_image,
+ // m_textureObject.GetMemory(), m_textureObject.GetAlignedOffset()));
}
}
diff --git a/drape/vulkan/vulkan_utils.hpp b/drape/vulkan/vulkan_utils.hpp
index 605c5ffe2c..d290440cde 100644
--- a/drape/vulkan/vulkan_utils.hpp
+++ b/drape/vulkan/vulkan_utils.hpp
@@ -28,3 +28,9 @@ extern std::string GetVulkanResultString(VkResult result);
CHECK(statusCode == VK_SUCCESS, ("Vulkan error:", #method, "finished with code", \
dp::vulkan::GetVulkanResultString(statusCode))); \
} while (false)
+
+#define CHECK_RESULT_VK_CALL(method, statusCode) \
+ do { \
+ CHECK(statusCode == VK_SUCCESS, ("Vulkan error:", #method, "finished with code", \
+ dp::vulkan::GetVulkanResultString(statusCode))); \
+ } while (false)
diff --git a/drape/vulkan/vulkan_vertex_array_buffer_impl.cpp b/drape/vulkan/vulkan_vertex_array_buffer_impl.cpp
index f6bfc006b5..0fa162bee2 100644
--- a/drape/vulkan/vulkan_vertex_array_buffer_impl.cpp
+++ b/drape/vulkan/vulkan_vertex_array_buffer_impl.cpp
@@ -37,7 +37,7 @@ public:
void RenderRange(ref_ptr<GraphicsContext> context, bool drawAsLine,
IndicesRange const & range) override
{
- CHECK(false, ());
+// CHECK(false, ());
// ref_ptr<dp::metal::MetalBaseContext> metalContext = context;
// if (!metalContext->HasAppliedPipelineState())