]> git.tdb.fi Git - libs/gl.git/blob - source/backends/vulkan/vertexsetup_backend.cpp
Initial implementation of Vulkan backend
[libs/gl.git] / source / backends / vulkan / vertexsetup_backend.cpp
1 #include <msp/core/hash.h>
2 #include "buffer.h"
3 #include "structurebuilder.h"
4 #include "vertexarray.h"
5 #include "vertexformat.h"
6 #include "vertexsetup.h"
7 #include "vertexsetup_backend.h"
8 #include "vulkan.h"
9
10 using namespace std;
11
12 namespace Msp {
13 namespace GL {
14
15 VulkanVertexSetup::VulkanVertexSetup(VulkanVertexSetup &&other):
16         creation_info(move(other.creation_info))
17 { }
18
19 void VulkanVertexSetup::update(unsigned) const
20 {
21         const VertexSetup &self = *static_cast<const VertexSetup *>(this);
22
23         n_bindings = (self.inst_format.empty() ? 1 : 2);
24         unsigned n_attribs = 0;
25         for(VertexAttribute a: self.vertex_format)
26                 n_attribs += !is_padding(a);
27         for(VertexAttribute a: self.inst_format)
28                 n_attribs += !is_padding(a);
29
30         StructureBuilder sb(creation_info, 3);
31         VkPipelineVertexInputStateCreateInfo *&input_state = sb.add<VkPipelineVertexInputStateCreateInfo>();
32         VkVertexInputBindingDescription *&bindings = sb.add<VkVertexInputBindingDescription>(n_bindings);
33         VkVertexInputAttributeDescription *&attribs = sb.add<VkVertexInputAttributeDescription>(n_attribs);
34
35         bindings[0].binding = 0;
36         bindings[0].stride = self.vertex_format.stride();
37         bindings[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
38         update_attributes(self.vertex_format, 0, attribs);
39
40         if(!self.inst_format.empty())
41         {
42                 bindings[1].binding = 1;
43                 bindings[1].stride = self.inst_format.stride();
44                 bindings[1].inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
45                 update_attributes(self.inst_format, 1, attribs+self.vertex_format.size());
46         }
47
48         input_state->sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
49         input_state->vertexBindingDescriptionCount = n_bindings;
50         input_state->pVertexBindingDescriptions = bindings;
51         input_state->vertexAttributeDescriptionCount = n_attribs;
52         input_state->pVertexAttributeDescriptions = attribs;
53
54         buffers[0] = self.vertex_array->get_buffer()->handle;
55         offsets[0] = self.vertex_array->get_offset();
56
57         if(self.inst_array)
58         {
59                 buffers[1] = self.inst_array->get_buffer()->handle;
60                 offsets[1] = self.inst_array->get_offset();
61         }
62 }
63
64 void VulkanVertexSetup::update_attributes(const VertexFormat &fmt, unsigned binding, void *buffer) const
65 {
66         VkVertexInputAttributeDescription *attrib = reinterpret_cast<VkVertexInputAttributeDescription *>(buffer);
67         unsigned offset = 0;
68         for(VertexAttribute a: fmt)
69         {
70                 if(!is_padding(a))
71                 {
72                         attrib->location = get_attribute_semantic(a);
73                         attrib->binding = binding;
74                         attrib->format = static_cast<VkFormat>(get_vulkan_attribute_format(a));
75                         attrib->offset = offset;
76                         ++attrib;
77                 }
78                 offset += get_attribute_size(a);
79         }
80 }
81
82 uint64_t VulkanVertexSetup::compute_hash() const
83 {
84         const VertexSetup &self = *static_cast<const VertexSetup *>(this);
85
86         uint64_t result = hash<64>(0, 0);
87         for(VertexAttribute a: self.vertex_format)
88                 result = hash_update<64>(result, a);
89         for(VertexAttribute a: self.inst_format)
90                 result = hash_update<64>(result, a);
91
92         return result;
93 }
94
95 } // namespace GL
96 } // namespace Msp