]> git.tdb.fi Git - libs/gl.git/blobdiff - source/backends/vulkan/vertexsetup_backend.cpp
Initial implementation of Vulkan backend
[libs/gl.git] / source / backends / vulkan / vertexsetup_backend.cpp
diff --git a/source/backends/vulkan/vertexsetup_backend.cpp b/source/backends/vulkan/vertexsetup_backend.cpp
new file mode 100644 (file)
index 0000000..0d25181
--- /dev/null
@@ -0,0 +1,96 @@
+#include <msp/core/hash.h>
+#include "buffer.h"
+#include "structurebuilder.h"
+#include "vertexarray.h"
+#include "vertexformat.h"
+#include "vertexsetup.h"
+#include "vertexsetup_backend.h"
+#include "vulkan.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+VulkanVertexSetup::VulkanVertexSetup(VulkanVertexSetup &&other):
+       creation_info(move(other.creation_info))
+{ }
+
+void VulkanVertexSetup::update(unsigned) const
+{
+       const VertexSetup &self = *static_cast<const VertexSetup *>(this);
+
+       n_bindings = (self.inst_format.empty() ? 1 : 2);
+       unsigned n_attribs = 0;
+       for(VertexAttribute a: self.vertex_format)
+               n_attribs += !is_padding(a);
+       for(VertexAttribute a: self.inst_format)
+               n_attribs += !is_padding(a);
+
+       StructureBuilder sb(creation_info, 3);
+       VkPipelineVertexInputStateCreateInfo *&input_state = sb.add<VkPipelineVertexInputStateCreateInfo>();
+       VkVertexInputBindingDescription *&bindings = sb.add<VkVertexInputBindingDescription>(n_bindings);
+       VkVertexInputAttributeDescription *&attribs = sb.add<VkVertexInputAttributeDescription>(n_attribs);
+
+       bindings[0].binding = 0;
+       bindings[0].stride = self.vertex_format.stride();
+       bindings[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
+       update_attributes(self.vertex_format, 0, attribs);
+
+       if(!self.inst_format.empty())
+       {
+               bindings[1].binding = 1;
+               bindings[1].stride = self.inst_format.stride();
+               bindings[1].inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
+               update_attributes(self.inst_format, 1, attribs+self.vertex_format.size());
+       }
+
+       input_state->sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+       input_state->vertexBindingDescriptionCount = n_bindings;
+       input_state->pVertexBindingDescriptions = bindings;
+       input_state->vertexAttributeDescriptionCount = n_attribs;
+       input_state->pVertexAttributeDescriptions = attribs;
+
+       buffers[0] = self.vertex_array->get_buffer()->handle;
+       offsets[0] = self.vertex_array->get_offset();
+
+       if(self.inst_array)
+       {
+               buffers[1] = self.inst_array->get_buffer()->handle;
+               offsets[1] = self.inst_array->get_offset();
+       }
+}
+
+void VulkanVertexSetup::update_attributes(const VertexFormat &fmt, unsigned binding, void *buffer) const
+{
+       VkVertexInputAttributeDescription *attrib = reinterpret_cast<VkVertexInputAttributeDescription *>(buffer);
+       unsigned offset = 0;
+       for(VertexAttribute a: fmt)
+       {
+               if(!is_padding(a))
+               {
+                       attrib->location = get_attribute_semantic(a);
+                       attrib->binding = binding;
+                       attrib->format = static_cast<VkFormat>(get_vulkan_attribute_format(a));
+                       attrib->offset = offset;
+                       ++attrib;
+               }
+               offset += get_attribute_size(a);
+       }
+}
+
+uint64_t VulkanVertexSetup::compute_hash() const
+{
+       const VertexSetup &self = *static_cast<const VertexSetup *>(this);
+
+       uint64_t result = hash<64>(0, 0);
+       for(VertexAttribute a: self.vertex_format)
+               result = hash_update<64>(result, a);
+       for(VertexAttribute a: self.inst_format)
+               result = hash_update<64>(result, a);
+
+       return result;
+}
+
+} // namespace GL
+} // namespace Msp