From 5ca3c804107234fa92f226290f80544098864b97 Mon Sep 17 00:00:00 2001 From: Roman Kuznetsov Date: Mon, 11 Feb 2019 22:40:15 +0300 Subject: [PATCH] [vulkan] Added draw commands --- drape/vertex_array_buffer.cpp | 3 +- drape/vertex_array_buffer.hpp | 2 + drape/vulkan/vulkan_base_context.cpp | 15 +++ drape/vulkan/vulkan_base_context.hpp | 6 +- drape/vulkan/vulkan_gpu_buffer_impl.hpp | 4 + drape/vulkan/vulkan_mesh_object_impl.cpp | 54 ++++++++++- drape/vulkan/vulkan_pipeline.cpp | 5 + .../vulkan_vertex_array_buffer_impl.cpp | 96 +++++++++++++------ 8 files changed, 150 insertions(+), 35 deletions(-) diff --git a/drape/vertex_array_buffer.cpp b/drape/vertex_array_buffer.cpp index 96e4c12602..3f03b508bc 100644 --- a/drape/vertex_array_buffer.cpp +++ b/drape/vertex_array_buffer.cpp @@ -242,12 +242,11 @@ void VertexArrayBuffer::UploadData(ref_ptr context, BindingInfo buffer = GetOrCreateStaticBuffer(bindingInfo); else buffer = GetOrCreateDynamicBuffer(bindingInfo); + m_impl->AddBindingInfo(bindingInfo); if (count > 0) m_isChanged = true; buffer->GetBuffer()->UploadData(context, data, count); - - //TODO(@rokuz): inject binding info } ref_ptr VertexArrayBuffer::GetOrCreateDynamicBuffer(BindingInfo const & bindingInfo) diff --git a/drape/vertex_array_buffer.hpp b/drape/vertex_array_buffer.hpp index ab9ee9c0c8..0689a283dc 100644 --- a/drape/vertex_array_buffer.hpp +++ b/drape/vertex_array_buffer.hpp @@ -34,6 +34,8 @@ public: virtual void BindBuffers(BuffersMap const & buffers) const = 0; virtual void RenderRange(ref_ptr context, bool drawAsLine, IndicesRange const & range) = 0; + + virtual void AddBindingInfo(dp::BindingInfo const & bindingInfo) {} }; namespace metal diff --git a/drape/vulkan/vulkan_base_context.cpp b/drape/vulkan/vulkan_base_context.cpp index e6ee19da87..87fbecd397 100644 --- a/drape/vulkan/vulkan_base_context.cpp +++ b/drape/vulkan/vulkan_base_context.cpp @@ -597,5 +597,20 @@ void VulkanBaseContext::SetStencilReferenceValue(uint32_t stencilReferenceValue) { m_stencilReferenceValue = stencilReferenceValue; } + +void VulkanBaseContext::SetPrimitiveTopology(VkPrimitiveTopology topology) +{ + //TODO +} + +void VulkanBaseContext::SetBindingInfo(std::vector const & bindingInfo) +{ + //TODO +} + +VkPipeline VulkanBaseContext::GetCurrentPipeline() +{ + return nullptr; +} } // namespace vulkan } // namespace dp diff --git a/drape/vulkan/vulkan_base_context.hpp b/drape/vulkan/vulkan_base_context.hpp index 96736906f9..48b96dc005 100644 --- a/drape/vulkan/vulkan_base_context.hpp +++ b/drape/vulkan/vulkan_base_context.hpp @@ -62,6 +62,9 @@ public: StencilAction depthFailAction, StencilAction passAction) override; void SetStencilReferenceValue(uint32_t stencilReferenceValue) override; + void SetPrimitiveTopology(VkPrimitiveTopology topology); + void SetBindingInfo(std::vector const & bindingInfo); + void SetSurface(VkSurfaceKHR surface, VkSurfaceFormatKHR surfaceFormat, VkSurfaceCapabilitiesKHR surfaceCapabilities, int width, int height); void ResetSurface(); @@ -77,6 +80,8 @@ public: VkCommandBuffer GetCurrentCommandBuffer() const { return m_commandBuffer; } + VkPipeline GetCurrentPipeline(); + enum class HandlerType : uint8_t { PrePresent = 0, @@ -156,7 +161,6 @@ protected: StencilAction m_stencilFailAction = {}; StencilAction m_depthFailAction = {}; StencilAction m_passAction = {}; - uint32_t m_stencilReferenceValue = 1; }; } // namespace vulkan diff --git a/drape/vulkan/vulkan_gpu_buffer_impl.hpp b/drape/vulkan/vulkan_gpu_buffer_impl.hpp index bb68cc96c1..5069a6a79f 100644 --- a/drape/vulkan/vulkan_gpu_buffer_impl.hpp +++ b/drape/vulkan/vulkan_gpu_buffer_impl.hpp @@ -32,6 +32,8 @@ public: uint32_t elementOffset, uint32_t elementCount); void Unmap(ref_ptr context); + VkBuffer GetVulkanBuffer() const { return m_geometryBuffer.m_buffer; } + protected: void Resize(ref_ptr context, void const * data, uint32_t elementCount); @@ -87,6 +89,8 @@ public: } void Bind() override {} + + VkBuffer GetVulkanBuffer() const { return m_buffer->GetVulkanBuffer(); } }; } // namespace vulkan } // namespace dp diff --git a/drape/vulkan/vulkan_mesh_object_impl.cpp b/drape/vulkan/vulkan_mesh_object_impl.cpp index 854ee577d9..1e53227cf4 100644 --- a/drape/vulkan/vulkan_mesh_object_impl.cpp +++ b/drape/vulkan/vulkan_mesh_object_impl.cpp @@ -16,6 +16,20 @@ namespace dp { namespace vulkan { +namespace +{ +VkPrimitiveTopology GetPrimitiveType(MeshObject::DrawPrimitive primitive) +{ + switch (primitive) + { + case MeshObject::DrawPrimitive::Triangles: return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + case MeshObject::DrawPrimitive::TriangleStrip: return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; + case MeshObject::DrawPrimitive::LineStrip: return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP; + } + CHECK(false, ("Unsupported type")); +} +} // namespace + class VulkanMeshObjectImpl : public MeshObjectImpl { public: @@ -29,7 +43,9 @@ public: m_objectManager = vulkanContext->GetObjectManager(); VkDevice device = vulkanContext->GetDevice(); + m_pipeline = {}; m_geometryBuffers.resize(m_mesh->m_buffers.size()); + m_bindingInfo.resize(m_mesh->m_buffers.size()); for (size_t i = 0; i < m_mesh->m_buffers.size(); i++) { if (m_mesh->m_buffers[i].m_data.empty()) @@ -47,6 +63,19 @@ public: CHECK_VK_CALL(vkBindBufferMemory(device, m_geometryBuffers[i].m_buffer, m_geometryBuffers[i].GetMemory(), m_geometryBuffers[i].GetAlignedOffset())); + + m_bindingInfo[i] = dp::BindingInfo(static_cast(m_mesh->m_buffers[i].m_attributes.size()), + static_cast(i)); + for (size_t j = 0; j < m_mesh->m_buffers[i].m_attributes.size(); ++j) + { + auto const & attr = m_mesh->m_buffers[i].m_attributes[j]; + auto & binding = m_bindingInfo[i].GetBindingDecl(static_cast(j)); + binding.m_attributeName = attr.m_attributeName; + binding.m_componentCount = static_cast(attr.m_componentsCount); + binding.m_componentType = gl_const::GLFloatType; + binding.m_offset = static_cast(attr.m_offset); + binding.m_stride = static_cast(m_mesh->m_buffers[i].m_stride); + } } } @@ -55,6 +84,7 @@ public: for (auto const & b : m_geometryBuffers) m_objectManager->DestroyObject(b); m_geometryBuffers.clear(); + m_pipeline = {}; } void UpdateBuffer(ref_ptr context, uint32_t bufferInd) override @@ -121,8 +151,26 @@ public: void DrawPrimitives(ref_ptr context, uint32_t verticesCount) override { - //TODO (@rokuz, @darina): Implement. - //CHECK(false, ()); + ref_ptr vulkanContext = context; + VkCommandBuffer commandBuffer = vulkanContext->GetCurrentCommandBuffer(); + CHECK(commandBuffer != nullptr, ()); + + if (!m_pipeline) + { + vulkanContext->SetPrimitiveTopology(GetPrimitiveType(m_mesh->m_drawPrimitive)); + vulkanContext->SetBindingInfo(m_bindingInfo); + m_pipeline = vulkanContext->GetCurrentPipeline(); + if (!m_pipeline) + return; + } + + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline); + + VkDeviceSize offsets[1] = {0}; + for (uint32_t i = 0; i < static_cast(m_geometryBuffers.size()); ++i) + vkCmdBindVertexBuffers(commandBuffer, i, 1, &m_geometryBuffers[i].m_buffer, offsets); + + vkCmdDraw(commandBuffer, verticesCount, 1, 0, 0); } void Bind(ref_ptr program) override {} @@ -132,6 +180,8 @@ private: ref_ptr m_mesh; ref_ptr m_objectManager; std::vector m_geometryBuffers; + std::vector m_bindingInfo; + VkPipeline m_pipeline = {}; }; } // namespace vulkan diff --git a/drape/vulkan/vulkan_pipeline.cpp b/drape/vulkan/vulkan_pipeline.cpp index fa74aaea04..075849d761 100644 --- a/drape/vulkan/vulkan_pipeline.cpp +++ b/drape/vulkan/vulkan_pipeline.cpp @@ -244,6 +244,11 @@ void VulkanPipeline::Dump(VkDevice device) void VulkanPipeline::Destroy(VkDevice device) { Dump(device); + + for (auto const & p : m_pipelineCache) + vkDestroyPipeline(device, p.second, nullptr); + m_pipelineCache.clear(); + vkDestroyPipelineCache(device, m_vulkanPipelineCache, nullptr); } diff --git a/drape/vulkan/vulkan_vertex_array_buffer_impl.cpp b/drape/vulkan/vulkan_vertex_array_buffer_impl.cpp index 0fa162bee2..3f44d9f663 100644 --- a/drape/vulkan/vulkan_vertex_array_buffer_impl.cpp +++ b/drape/vulkan/vulkan_vertex_array_buffer_impl.cpp @@ -9,9 +9,11 @@ #include #include +#include #include #include #include +#include namespace dp { @@ -33,46 +35,80 @@ public: bool Bind() override { return true; } void Unbind() override {} void BindBuffers(dp::BuffersMap const & buffers) const override {} + + void AddBindingInfo(dp::BindingInfo const & bindingInfo) override + { + auto const id = bindingInfo.GetID(); + auto const it = std::find_if(m_bindingInfo.begin(), m_bindingInfo.end(), + [id](dp::BindingInfo const & info) + { + return info.GetID() == id; + }); + if (it != m_bindingInfo.end()) + { + CHECK(*it == bindingInfo, ("Incorrect binding info.")); + return; + } + + m_bindingInfo.push_back(bindingInfo); + std::sort(m_bindingInfo.begin(), m_bindingInfo.end(), + [](dp::BindingInfo const & info1, dp::BindingInfo const & info2) + { + return info1.GetID() < info2.GetID(); + }); + } void RenderRange(ref_ptr context, bool drawAsLine, IndicesRange const & range) override { -// CHECK(false, ()); + ref_ptr vulkanContext = context; + VkCommandBuffer commandBuffer = vulkanContext->GetCurrentCommandBuffer(); + CHECK(commandBuffer != nullptr, ()); -// ref_ptr metalContext = context; -// if (!metalContext->HasAppliedPipelineState()) -// return; + if (!m_pipeline || (m_lastDrawAsLine != drawAsLine)) + { + m_lastDrawAsLine = drawAsLine; -// id encoder = metalContext->GetCommandEncoder(); -// -// uint32_t bufferIndex = 0; -// for (auto & buffer : m_vertexArrayBuffer->m_staticBuffers) -// { -// ref_ptr b = buffer.second->GetBuffer(); -// [encoder setVertexBuffer:b->GetMetalBuffer() offset:0 atIndex:bufferIndex]; -// bufferIndex++; -// } -// for (auto & buffer : m_vertexArrayBuffer->m_dynamicBuffers) -// { -// ref_ptr b = buffer.second->GetBuffer(); -// [encoder setVertexBuffer:b->GetMetalBuffer() offset:0 atIndex:bufferIndex]; -// bufferIndex++; -// } -// -// ref_ptr ib = m_vertexArrayBuffer->m_indexBuffer->GetBuffer(); -// auto const isSupported32bit = dp::IndexStorage::IsSupported32bit(); -// auto const indexType = isSupported32bit ? MTLIndexTypeUInt32 : MTLIndexTypeUInt16; -// auto const indexSize = isSupported32bit ? sizeof(unsigned int) : sizeof(unsigned short); -// -// [encoder drawIndexedPrimitives:(drawAsLine ? MTLPrimitiveTypeLine : MTLPrimitiveTypeTriangle) -// indexCount:range.m_idxCount -// indexType:indexType -// indexBuffer:ib->GetMetalBuffer() -// indexBufferOffset:range.m_idxStart * indexSize]; + vulkanContext->SetPrimitiveTopology(drawAsLine ? VK_PRIMITIVE_TOPOLOGY_LINE_LIST : + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); + vulkanContext->SetBindingInfo(m_bindingInfo); + m_pipeline = vulkanContext->GetCurrentPipeline(); + if (!m_pipeline) + return; + } + + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline); + + VkDeviceSize offsets[1] = {0}; + uint32_t bufferIndex = 0; + for (auto & buffer : m_vertexArrayBuffer->m_staticBuffers) + { + ref_ptr b = buffer.second->GetBuffer(); + VkBuffer vulkanBuffer = b->GetVulkanBuffer(); + vkCmdBindVertexBuffers(commandBuffer, bufferIndex, 1, &vulkanBuffer, offsets); + bufferIndex++; + } + for (auto & buffer : m_vertexArrayBuffer->m_dynamicBuffers) + { + ref_ptr b = buffer.second->GetBuffer(); + VkBuffer vulkanBuffer = b->GetVulkanBuffer(); + vkCmdBindVertexBuffers(commandBuffer, bufferIndex, 1, &vulkanBuffer, offsets); + bufferIndex++; + } + + ref_ptr ib = m_vertexArrayBuffer->m_indexBuffer->GetBuffer(); + VkBuffer vulkanIndexBuffer = ib->GetVulkanBuffer(); + auto const indexType = dp::IndexStorage::IsSupported32bit() ? VK_INDEX_TYPE_UINT32 : VK_INDEX_TYPE_UINT16; + vkCmdBindIndexBuffer(commandBuffer, vulkanIndexBuffer, 0, indexType); + + vkCmdDrawIndexed(commandBuffer, range.m_idxCount, 1, range.m_idxStart, 0, 0); } private: ref_ptr m_vertexArrayBuffer; + std::vector m_bindingInfo; + VkPipeline m_pipeline = {}; + bool m_lastDrawAsLine = false; }; } // namespace vulkan