1 // Copyright 2016 Dolphin Emulator Project
2 // Licensed under GPLv2+
3 // Refer to the license.txt file included.
4 
5 #include "VideoBackends/Vulkan/VertexFormat.h"
6 
7 #include "Common/Assert.h"
8 
9 #include "VideoBackends/Vulkan/CommandBufferManager.h"
10 #include "VideoBackends/Vulkan/ObjectCache.h"
11 
12 #include "VideoCommon/VertexLoaderManager.h"
13 #include "VideoCommon/VertexShaderGen.h"
14 
15 namespace Vulkan
16 {
VarToVkFormat(VarType t,uint32_t components,bool integer)17 static VkFormat VarToVkFormat(VarType t, uint32_t components, bool integer)
18 {
19   static const VkFormat float_type_lookup[][4] = {
20       {VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM, VK_FORMAT_R8G8B8_UNORM,
21        VK_FORMAT_R8G8B8A8_UNORM},  // VAR_UNSIGNED_BYTE
22       {VK_FORMAT_R8_SNORM, VK_FORMAT_R8G8_SNORM, VK_FORMAT_R8G8B8_SNORM,
23        VK_FORMAT_R8G8B8A8_SNORM},  // VAR_BYTE
24       {VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM, VK_FORMAT_R16G16B16_UNORM,
25        VK_FORMAT_R16G16B16A16_UNORM},  // VAR_UNSIGNED_SHORT
26       {VK_FORMAT_R16_SNORM, VK_FORMAT_R16G16_SNORM, VK_FORMAT_R16G16B16_SNORM,
27        VK_FORMAT_R16G16B16A16_SNORM},  // VAR_SHORT
28       {VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_R32G32B32_SFLOAT,
29        VK_FORMAT_R32G32B32A32_SFLOAT}  // VAR_FLOAT
30   };
31 
32   static const VkFormat integer_type_lookup[][4] = {
33       {VK_FORMAT_R8_UINT, VK_FORMAT_R8G8_UINT, VK_FORMAT_R8G8B8_UINT,
34        VK_FORMAT_R8G8B8A8_UINT},  // VAR_UNSIGNED_BYTE
35       {VK_FORMAT_R8_SINT, VK_FORMAT_R8G8_SINT, VK_FORMAT_R8G8B8_SINT,
36        VK_FORMAT_R8G8B8A8_SINT},  // VAR_BYTE
37       {VK_FORMAT_R16_UINT, VK_FORMAT_R16G16_UINT, VK_FORMAT_R16G16B16_UINT,
38        VK_FORMAT_R16G16B16A16_UINT},  // VAR_UNSIGNED_SHORT
39       {VK_FORMAT_R16_SINT, VK_FORMAT_R16G16_SINT, VK_FORMAT_R16G16B16_SINT,
40        VK_FORMAT_R16G16B16A16_SINT},  // VAR_SHORT
41       {VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_R32G32B32_SFLOAT,
42        VK_FORMAT_R32G32B32A32_SFLOAT}  // VAR_FLOAT
43   };
44 
45   ASSERT(components > 0 && components <= 4);
46   return integer ? integer_type_lookup[t][components - 1] : float_type_lookup[t][components - 1];
47 }
48 
VertexFormat(const PortableVertexDeclaration & vtx_decl)49 VertexFormat::VertexFormat(const PortableVertexDeclaration& vtx_decl) : NativeVertexFormat(vtx_decl)
50 {
51   MapAttributes();
52   SetupInputState();
53 }
54 
GetVertexInputStateInfo() const55 const VkPipelineVertexInputStateCreateInfo& VertexFormat::GetVertexInputStateInfo() const
56 {
57   return m_input_state_info;
58 }
59 
MapAttributes()60 void VertexFormat::MapAttributes()
61 {
62   m_num_attributes = 0;
63 
64   if (m_decl.position.enable)
65     AddAttribute(
66         SHADER_POSITION_ATTRIB, 0,
67         VarToVkFormat(m_decl.position.type, m_decl.position.components, m_decl.position.integer),
68         m_decl.position.offset);
69 
70   for (uint32_t i = 0; i < 3; i++)
71   {
72     if (m_decl.normals[i].enable)
73       AddAttribute(SHADER_NORM0_ATTRIB + i, 0,
74                    VarToVkFormat(m_decl.normals[i].type, m_decl.normals[i].components,
75                                  m_decl.normals[i].integer),
76                    m_decl.normals[i].offset);
77   }
78 
79   for (uint32_t i = 0; i < 2; i++)
80   {
81     if (m_decl.colors[i].enable)
82       AddAttribute(SHADER_COLOR0_ATTRIB + i, 0,
83                    VarToVkFormat(m_decl.colors[i].type, m_decl.colors[i].components,
84                                  m_decl.colors[i].integer),
85                    m_decl.colors[i].offset);
86   }
87 
88   for (uint32_t i = 0; i < 8; i++)
89   {
90     if (m_decl.texcoords[i].enable)
91       AddAttribute(SHADER_TEXTURE0_ATTRIB + i, 0,
92                    VarToVkFormat(m_decl.texcoords[i].type, m_decl.texcoords[i].components,
93                                  m_decl.texcoords[i].integer),
94                    m_decl.texcoords[i].offset);
95   }
96 
97   if (m_decl.posmtx.enable)
98     AddAttribute(SHADER_POSMTX_ATTRIB, 0,
99                  VarToVkFormat(m_decl.posmtx.type, m_decl.posmtx.components, m_decl.posmtx.integer),
100                  m_decl.posmtx.offset);
101 }
102 
SetupInputState()103 void VertexFormat::SetupInputState()
104 {
105   m_binding_description.binding = 0;
106   m_binding_description.stride = m_decl.stride;
107   m_binding_description.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
108 
109   m_input_state_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
110   m_input_state_info.pNext = nullptr;
111   m_input_state_info.flags = 0;
112   m_input_state_info.vertexBindingDescriptionCount = 1;
113   m_input_state_info.pVertexBindingDescriptions = &m_binding_description;
114   m_input_state_info.vertexAttributeDescriptionCount = m_num_attributes;
115   m_input_state_info.pVertexAttributeDescriptions = m_attribute_descriptions.data();
116 }
117 
AddAttribute(uint32_t location,uint32_t binding,VkFormat format,uint32_t offset)118 void VertexFormat::AddAttribute(uint32_t location, uint32_t binding, VkFormat format,
119                                 uint32_t offset)
120 {
121   ASSERT(m_num_attributes < MAX_VERTEX_ATTRIBUTES);
122 
123   m_attribute_descriptions[m_num_attributes].location = location;
124   m_attribute_descriptions[m_num_attributes].binding = binding;
125   m_attribute_descriptions[m_num_attributes].format = format;
126   m_attribute_descriptions[m_num_attributes].offset = offset;
127   m_num_attributes++;
128 }
129 }  // namespace Vulkan
130