13
13
#include < tiny_obj_loader.h>
14
14
15
15
#include < chrono>
16
+ #include < random>
16
17
#include < iostream>
17
18
#include < fstream>
18
19
#include < vector>
@@ -38,6 +39,7 @@ class HelloTriangleApplication {
38
39
// ///////////////////////////////////////////////////////////////
39
40
// / forwoard declare
40
41
struct Vertex ;
42
+ struct InstanceData ;
41
43
// ///////////////////////////////////////////////////////////////
42
44
43
45
// ///////////////////////////////////////////////////////////////
@@ -63,6 +65,7 @@ class HelloTriangleApplication {
63
65
#endif
64
66
65
67
static constexpr int MAX_FRAMES_IN_FLIGHT = 2 ;
68
+ static constexpr int BUNNY_NUMBER = 5 ;
66
69
// ///////////////////////////////////////////////////////////////
67
70
68
71
// ///////////////////////////////////////////////////////////////
@@ -77,10 +80,13 @@ class HelloTriangleApplication {
77
80
vk::raii::Queue m_graphicsQueue{ nullptr };
78
81
vk::raii::Queue m_presentQueue{ nullptr };
79
82
std::vector<Vertex> m_vertices;
83
+ std::vector<InstanceData> m_instanceDatas;
80
84
std::vector<uint32_t > m_indices;
81
- std::vector<uint32_t > m_indicesOffsets ;
85
+ std::vector<uint32_t > m_firstIndices ;
82
86
vk::raii::DeviceMemory m_vertexBufferMemory{ nullptr };
83
87
vk::raii::Buffer m_vertexBuffer{ nullptr };
88
+ vk::raii::DeviceMemory m_instanceBufferMemory{ nullptr };
89
+ vk::raii::Buffer m_instanceBuffer{ nullptr };
84
90
vk::raii::DeviceMemory m_indexBufferMemory{ nullptr };
85
91
vk::raii::Buffer m_indexBuffer{ nullptr };
86
92
std::vector<vk::raii::DeviceMemory> m_uniformBuffersMemory;
@@ -157,7 +163,9 @@ class HelloTriangleApplication {
157
163
createTextureSampler ();
158
164
loadModel (MODEL_PATH);
159
165
loadModel (BUNNY_PATH);
166
+ initInstanceDatas ();
160
167
createVertexBuffer ();
168
+ createInstanceBuffer ();
161
169
createIndexBuffer ();
162
170
createUniformBuffers ();
163
171
createDescriptorPool ();
@@ -643,10 +651,28 @@ class HelloTriangleApplication {
643
651
644
652
vk::PipelineVertexInputStateCreateInfo vertexInputInfo;
645
653
646
- auto bindingDescription = Vertex::getBindingDescription ();
647
- auto attributeDescriptions = Vertex::getAttributeDescriptions ();
654
+ auto vertexBindingDescription = Vertex::getBindingDescription ();
655
+ auto vertexAttributeDescriptions = Vertex::getAttributeDescriptions ();
656
+ auto instanceBindingDescription = InstanceData::getBindingDescription ();
657
+ auto instanceAttributeDescriptions = InstanceData::getAttributeDescriptions ();
648
658
649
- vertexInputInfo.setVertexBindingDescriptions (bindingDescription);
659
+ std::vector<vk::VertexInputBindingDescription> bindingDescriptions = {
660
+ vertexBindingDescription,
661
+ instanceBindingDescription
662
+ };
663
+ std::vector<vk::VertexInputAttributeDescription> attributeDescriptions;
664
+ attributeDescriptions.insert (
665
+ attributeDescriptions.end (),
666
+ vertexAttributeDescriptions.begin (),
667
+ vertexAttributeDescriptions.end ()
668
+ );
669
+ attributeDescriptions.insert (
670
+ attributeDescriptions.end (),
671
+ instanceAttributeDescriptions.begin (),
672
+ instanceAttributeDescriptions.end ()
673
+ );
674
+
675
+ vertexInputInfo.setVertexBindingDescriptions (bindingDescriptions);
650
676
vertexInputInfo.setVertexAttributeDescriptions (attributeDescriptions);
651
677
652
678
vk::PipelineInputAssemblyStateCreateInfo inputAssembly;
@@ -690,18 +716,8 @@ class HelloTriangleApplication {
690
716
depthStencil.depthBoundsTestEnable = false ; // Optional
691
717
depthStencil.stencilTestEnable = false ; // Optional
692
718
693
- std::array<vk::PushConstantRange, 2 > pushConstantRanges;
694
- pushConstantRanges[0 ].stageFlags = vk::ShaderStageFlagBits::eVertex;
695
- pushConstantRanges[0 ].offset = 0 ;
696
- pushConstantRanges[0 ].size = sizeof (glm::mat4);
697
- pushConstantRanges[1 ].stageFlags = vk::ShaderStageFlagBits::eFragment;
698
- pushConstantRanges[1 ].offset = sizeof (glm::mat4);
699
- pushConstantRanges[1 ].size = sizeof (uint32_t );
700
-
701
719
vk::PipelineLayoutCreateInfo pipelineLayoutInfo;
702
720
pipelineLayoutInfo.setSetLayouts (*m_descriptorSetLayout);
703
- pipelineLayoutInfo.setPushConstantRanges ( pushConstantRanges );
704
-
705
721
m_pipelineLayout = m_device.createPipelineLayout ( pipelineLayoutInfo );
706
722
707
723
vk::GraphicsPipelineCreateInfo pipelineInfo;
@@ -805,9 +821,9 @@ class HelloTriangleApplication {
805
821
);
806
822
commandBuffer.setScissor (0 , scissor);
807
823
808
- // std::array< vk::Buffer,1> vertexBuffers { m_vertexBuffer };
809
- // std::array< vk::DeviceSize,1> offsets { 0 };
810
- commandBuffer.bindVertexBuffers ( 0 , *m_vertexBuffer, vk::DeviceSize{ 0 } );
824
+ vk::Buffer vertexBuffers[] = { * m_vertexBuffer, *m_instanceBuffer };
825
+ vk::DeviceSize offsets[] = { 0 , 0 };
826
+ commandBuffer.bindVertexBuffers ( 0 , vertexBuffers, offsets );
811
827
commandBuffer.bindIndexBuffer ( m_indexBuffer, 0 , vk::IndexType::eUint32 );
812
828
813
829
commandBuffer.bindDescriptorSets (
@@ -818,44 +834,20 @@ class HelloTriangleApplication {
818
834
nullptr
819
835
);
820
836
821
- for (size_t counter = 1 ; const uint32_t firstIndex : m_indicesOffsets) {
822
- PushConstantData pcData;
823
- if (counter == 1 ) {
824
- pcData.model = glm::rotate (
825
- glm::mat4 (1 .0f ),
826
- glm::radians (-90 .0f ),
827
- glm::vec3 (1 .0f , 0 .0f , 0 .0f )
828
- ) * glm::rotate (
829
- glm::mat4 (1 .0f ),
830
- glm::radians (-90 .0f ),
831
- glm::vec3 (0 .0f , 0 .0f , 1 .0f )
832
- );
833
- pcData.enableTexture = 1 ;
834
- } else {
835
- pcData.model = glm::translate (glm::mat4 (1 .0f ), glm::vec3 (0 .5f , 0 .12f , 0 .0f ));
836
- pcData.enableTexture = 0 ;
837
- }
838
- commandBuffer.pushConstants <glm::mat4>(
839
- m_pipelineLayout,
840
- vk::ShaderStageFlagBits::eVertex,
841
- 0 , // offset
842
- pcData.model
843
- );
844
- commandBuffer.pushConstants <uint32_t >(
845
- m_pipelineLayout,
846
- vk::ShaderStageFlagBits::eFragment,
847
- sizeof (glm::mat4), // offset
848
- pcData.enableTexture
849
- );
850
- commandBuffer.drawIndexed (
851
- counter == m_indicesOffsets.size () ? m_indices.size () - firstIndex : m_indicesOffsets[counter] - firstIndex,
852
- 1 ,
853
- firstIndex,
854
- 0 ,
855
- 0
856
- );
857
- ++counter;
858
- }
837
+ commandBuffer.drawIndexed ( // draw the room
838
+ m_firstIndices[1 ],
839
+ 1 ,
840
+ 0 ,
841
+ 0 ,
842
+ 0
843
+ );
844
+ commandBuffer.drawIndexed ( // draw the bunny
845
+ static_cast <uint32_t >(m_indices.size () - m_firstIndices[1 ]),
846
+ BUNNY_NUMBER,
847
+ m_firstIndices[1 ],
848
+ 0 ,
849
+ 1
850
+ );
859
851
860
852
commandBuffer.endRenderPass ();
861
853
commandBuffer.end ();
@@ -1019,7 +1011,8 @@ class HelloTriangleApplication {
1019
1011
vk::BufferUsageFlags usage,
1020
1012
vk::MemoryPropertyFlags properties,
1021
1013
vk::raii::Buffer& buffer,
1022
- vk::raii::DeviceMemory& bufferMemory) {
1014
+ vk::raii::DeviceMemory& bufferMemory
1015
+ ) {
1023
1016
1024
1017
vk::BufferCreateInfo bufferInfo;
1025
1018
bufferInfo.size = size;
@@ -1119,7 +1112,6 @@ class HelloTriangleApplication {
1119
1112
// ///////////////////////////////////////////////////////////////
1120
1113
// / descriptor layout and buffer
1121
1114
struct alignas (16 ) UniformBufferObject {
1122
- glm::mat4 model;
1123
1115
glm::mat4 view;
1124
1116
glm::mat4 proj;
1125
1117
};
@@ -1623,7 +1615,7 @@ class HelloTriangleApplication {
1623
1615
throw std::runtime_error (warn + err);
1624
1616
}
1625
1617
1626
- m_indicesOffsets .push_back (m_indices.size ());
1618
+ m_firstIndices .push_back (m_indices.size ());
1627
1619
1628
1620
static std::unordered_map<
1629
1621
Vertex,
@@ -1652,6 +1644,8 @@ class HelloTriangleApplication {
1652
1644
attrib.texcoords [2 * index.texcoord_index ],
1653
1645
1 .0f - attrib.texcoords [2 * index.texcoord_index + 1 ]
1654
1646
};
1647
+ } else {
1648
+ vertex.texCoord = {0 .0f , 0 .0f };
1655
1649
}
1656
1650
1657
1651
vertex.color = {1 .0f , 1 .0f , 1 .0f };
@@ -1837,8 +1831,8 @@ class HelloTriangleApplication {
1837
1831
if (counts & vk::SampleCountFlagBits::e32 ) return vk::SampleCountFlagBits::e32 ;
1838
1832
if (counts & vk::SampleCountFlagBits::e16 ) return vk::SampleCountFlagBits::e16 ;
1839
1833
if (counts & vk::SampleCountFlagBits::e8 ) return vk::SampleCountFlagBits::e8 ;
1840
- if (counts & vk::SampleCountFlagBits::e8 ) return vk::SampleCountFlagBits::e4 ;
1841
- if (counts & vk::SampleCountFlagBits::e8 ) return vk::SampleCountFlagBits::e2 ;
1834
+ if (counts & vk::SampleCountFlagBits::e4 ) return vk::SampleCountFlagBits::e4 ;
1835
+ if (counts & vk::SampleCountFlagBits::e2 ) return vk::SampleCountFlagBits::e2 ;
1842
1836
return vk::SampleCountFlagBits::e1 ;
1843
1837
}
1844
1838
void createColorResources () {
@@ -1867,11 +1861,94 @@ class HelloTriangleApplication {
1867
1861
// ///////////////////////////////////////////////////////////////
1868
1862
1869
1863
// ///////////////////////////////////////////////////////////////
1870
- // / push constant
1871
- struct PushConstantData {
1864
+ // / instance data
1865
+ struct alignas ( 16 ) InstanceData {
1872
1866
glm::mat4 model;
1873
1867
uint32_t enableTexture;
1868
+
1869
+ static vk::VertexInputBindingDescription getBindingDescription () {
1870
+ vk::VertexInputBindingDescription bindingDescription;
1871
+ bindingDescription.binding = 1 ; // binding 1 for instance data
1872
+ bindingDescription.stride = sizeof (InstanceData);
1873
+ bindingDescription.inputRate = vk::VertexInputRate::eInstance;
1874
+
1875
+ return bindingDescription;
1876
+ }
1877
+
1878
+ static std::array<vk::VertexInputAttributeDescription, 5 > getAttributeDescriptions () {
1879
+ std::array<vk::VertexInputAttributeDescription, 5 > attributeDescriptions;
1880
+ for (uint32_t i = 0 ; i < 4 ; ++i) {
1881
+ attributeDescriptions[i].binding = 1 ; // binding 1 for instance data
1882
+ attributeDescriptions[i].location = 3 + i; // location 3, 4, 5, 6
1883
+ attributeDescriptions[i].format = vk::Format::eR32G32B32A32Sfloat;
1884
+ attributeDescriptions[i].offset = sizeof (glm::vec4) * i;
1885
+ }
1886
+ attributeDescriptions[4 ].binding = 1 ;
1887
+ attributeDescriptions[4 ].location = 7 ;
1888
+ attributeDescriptions[4 ].format = vk::Format::eR32Uint;
1889
+ attributeDescriptions[4 ].offset = sizeof (glm::mat4);
1890
+ return attributeDescriptions;
1891
+ }
1874
1892
};
1893
+ void initInstanceDatas () {
1894
+ InstanceData instanceData;
1895
+ m_instanceDatas.reserve (BUNNY_NUMBER + 1 );
1896
+ // room model
1897
+ instanceData.model = glm::rotate (
1898
+ glm::mat4 (1 .0f ),
1899
+ glm::radians (-90 .0f ),
1900
+ glm::vec3 (1 .0f , 0 .0f , 0 .0f )
1901
+ ) * glm::rotate (
1902
+ glm::mat4 (1 .0f ),
1903
+ glm::radians (-90 .0f ),
1904
+ glm::vec3 (0 .0f , 0 .0f , 1 .0f )
1905
+ );
1906
+ instanceData.enableTexture = 1 ; // enable texture sampling
1907
+ m_instanceDatas.emplace_back ( instanceData );
1908
+
1909
+ std::random_device rd;
1910
+ std::mt19937 gen (rd ());
1911
+ std::uniform_real_distribution<float > dis (-1 .0f , 1 .0f );
1912
+ // initialize BUNNY_NUMBER instances
1913
+ for (int i = 0 ; i < BUNNY_NUMBER; ++i) {
1914
+ // randomly generate position and rotation
1915
+ instanceData.model = glm::translate (
1916
+ glm::mat4 (1 .0f ),
1917
+ glm::vec3 (dis (gen), dis (gen), dis (gen))
1918
+ ) * glm::rotate (
1919
+ glm::mat4 (1 .0f ),
1920
+ glm::radians (dis (gen) * 180 .0f ),
1921
+ glm::vec3 (0 .0f , 1 .0f , 0 .0f )
1922
+ );
1923
+ instanceData.enableTexture = 0 ; // disable texture sampling
1924
+ m_instanceDatas.emplace_back ( instanceData );
1925
+ }
1926
+ }
1927
+ void createInstanceBuffer () {
1928
+ vk::DeviceSize bufferSize = sizeof (InstanceData) * m_instanceDatas.size ();
1929
+
1930
+ vk::raii::DeviceMemory stagingBufferMemory{ nullptr };
1931
+ vk::raii::Buffer stagingBuffer{ nullptr };
1932
+ createBuffer (bufferSize,
1933
+ vk::BufferUsageFlagBits::eTransferSrc,
1934
+ vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent,
1935
+ stagingBuffer,
1936
+ stagingBufferMemory
1937
+ );
1938
+
1939
+ void * data = stagingBufferMemory.mapMemory (0 , bufferSize);
1940
+ memcpy (data, m_instanceDatas.data (), static_cast <size_t >(bufferSize));
1941
+ stagingBufferMemory.unmapMemory ();
1942
+
1943
+ createBuffer (bufferSize,
1944
+ vk::BufferUsageFlagBits::eTransferDst | vk::BufferUsageFlagBits::eVertexBuffer,
1945
+ vk::MemoryPropertyFlagBits::eDeviceLocal,
1946
+ m_instanceBuffer,
1947
+ m_instanceBufferMemory
1948
+ );
1949
+
1950
+ copyBuffer (stagingBuffer, m_instanceBuffer, bufferSize);
1951
+ }
1875
1952
// ///////////////////////////////////////////////////////////////
1876
1953
};
1877
1954
0 commit comments