Skip to content

Commit e54daec

Browse files
committed
Add instanced-rendering and refactor
1 parent 0d0ed17 commit e54daec

40 files changed

+4329
-1604
lines changed

docs/codes/03/30_multisample/main.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1793,8 +1793,8 @@ class HelloTriangleApplication {
17931793
if(counts & vk::SampleCountFlagBits::e32) return vk::SampleCountFlagBits::e32;
17941794
if(counts & vk::SampleCountFlagBits::e16) return vk::SampleCountFlagBits::e16;
17951795
if(counts & vk::SampleCountFlagBits::e8) return vk::SampleCountFlagBits::e8;
1796-
if(counts & vk::SampleCountFlagBits::e8) return vk::SampleCountFlagBits::e4;
1797-
if(counts & vk::SampleCountFlagBits::e8) return vk::SampleCountFlagBits::e2;
1796+
if(counts & vk::SampleCountFlagBits::e4) return vk::SampleCountFlagBits::e4;
1797+
if(counts & vk::SampleCountFlagBits::e2) return vk::SampleCountFlagBits::e2;
17981798
return vk::SampleCountFlagBits::e1;
17991799
}
18001800
void createColorResources() {

docs/codes/03/30_multisample/main.diff

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,8 @@ index 46c75ca..b0d2dfe 100644
181181
+ if(counts & vk::SampleCountFlagBits::e32) return vk::SampleCountFlagBits::e32;
182182
+ if(counts & vk::SampleCountFlagBits::e16) return vk::SampleCountFlagBits::e16;
183183
+ if(counts & vk::SampleCountFlagBits::e8) return vk::SampleCountFlagBits::e8;
184-
+ if(counts & vk::SampleCountFlagBits::e8) return vk::SampleCountFlagBits::e4;
185-
+ if(counts & vk::SampleCountFlagBits::e8) return vk::SampleCountFlagBits::e2;
184+
+ if(counts & vk::SampleCountFlagBits::e4) return vk::SampleCountFlagBits::e4;
185+
+ if(counts & vk::SampleCountFlagBits::e2) return vk::SampleCountFlagBits::e2;
186186
+ return vk::SampleCountFlagBits::e1;
187187
+ }
188188
+ void createColorResources() {

docs/codes/03/40_pushconstant/main.cpp renamed to docs/codes/03/40_instancedrendering/main.cpp

Lines changed: 139 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <tiny_obj_loader.h>
1414

1515
#include <chrono>
16+
#include <random>
1617
#include <iostream>
1718
#include <fstream>
1819
#include <vector>
@@ -38,6 +39,7 @@ class HelloTriangleApplication {
3839
/////////////////////////////////////////////////////////////////
3940
/// forwoard declare
4041
struct Vertex;
42+
struct InstanceData;
4143
/////////////////////////////////////////////////////////////////
4244

4345
/////////////////////////////////////////////////////////////////
@@ -63,6 +65,7 @@ class HelloTriangleApplication {
6365
#endif
6466

6567
static constexpr int MAX_FRAMES_IN_FLIGHT = 2;
68+
static constexpr int BUNNY_NUMBER = 5;
6669
/////////////////////////////////////////////////////////////////
6770

6871
/////////////////////////////////////////////////////////////////
@@ -77,10 +80,13 @@ class HelloTriangleApplication {
7780
vk::raii::Queue m_graphicsQueue{ nullptr };
7881
vk::raii::Queue m_presentQueue{ nullptr };
7982
std::vector<Vertex> m_vertices;
83+
std::vector<InstanceData> m_instanceDatas;
8084
std::vector<uint32_t> m_indices;
81-
std::vector<uint32_t> m_indicesOffsets;
85+
std::vector<uint32_t> m_firstIndices;
8286
vk::raii::DeviceMemory m_vertexBufferMemory{ nullptr };
8387
vk::raii::Buffer m_vertexBuffer{ nullptr };
88+
vk::raii::DeviceMemory m_instanceBufferMemory{ nullptr };
89+
vk::raii::Buffer m_instanceBuffer{ nullptr };
8490
vk::raii::DeviceMemory m_indexBufferMemory{ nullptr };
8591
vk::raii::Buffer m_indexBuffer{ nullptr };
8692
std::vector<vk::raii::DeviceMemory> m_uniformBuffersMemory;
@@ -157,7 +163,9 @@ class HelloTriangleApplication {
157163
createTextureSampler();
158164
loadModel(MODEL_PATH);
159165
loadModel(BUNNY_PATH);
166+
initInstanceDatas();
160167
createVertexBuffer();
168+
createInstanceBuffer();
161169
createIndexBuffer();
162170
createUniformBuffers();
163171
createDescriptorPool();
@@ -643,10 +651,28 @@ class HelloTriangleApplication {
643651

644652
vk::PipelineVertexInputStateCreateInfo vertexInputInfo;
645653

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();
648658

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);
650676
vertexInputInfo.setVertexAttributeDescriptions(attributeDescriptions);
651677

652678
vk::PipelineInputAssemblyStateCreateInfo inputAssembly;
@@ -690,18 +716,8 @@ class HelloTriangleApplication {
690716
depthStencil.depthBoundsTestEnable = false; // Optional
691717
depthStencil.stencilTestEnable = false; // Optional
692718

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-
701719
vk::PipelineLayoutCreateInfo pipelineLayoutInfo;
702720
pipelineLayoutInfo.setSetLayouts(*m_descriptorSetLayout);
703-
pipelineLayoutInfo.setPushConstantRanges( pushConstantRanges );
704-
705721
m_pipelineLayout = m_device.createPipelineLayout( pipelineLayoutInfo );
706722

707723
vk::GraphicsPipelineCreateInfo pipelineInfo;
@@ -805,9 +821,9 @@ class HelloTriangleApplication {
805821
);
806822
commandBuffer.setScissor(0, scissor);
807823

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 );
811827
commandBuffer.bindIndexBuffer( m_indexBuffer, 0, vk::IndexType::eUint32 );
812828

813829
commandBuffer.bindDescriptorSets(
@@ -818,44 +834,20 @@ class HelloTriangleApplication {
818834
nullptr
819835
);
820836

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+
);
859851

860852
commandBuffer.endRenderPass();
861853
commandBuffer.end();
@@ -1019,7 +1011,8 @@ class HelloTriangleApplication {
10191011
vk::BufferUsageFlags usage,
10201012
vk::MemoryPropertyFlags properties,
10211013
vk::raii::Buffer& buffer,
1022-
vk::raii::DeviceMemory& bufferMemory) {
1014+
vk::raii::DeviceMemory& bufferMemory
1015+
) {
10231016

10241017
vk::BufferCreateInfo bufferInfo;
10251018
bufferInfo.size = size;
@@ -1119,7 +1112,6 @@ class HelloTriangleApplication {
11191112
/////////////////////////////////////////////////////////////////
11201113
/// descriptor layout and buffer
11211114
struct alignas(16) UniformBufferObject {
1122-
glm::mat4 model;
11231115
glm::mat4 view;
11241116
glm::mat4 proj;
11251117
};
@@ -1623,7 +1615,7 @@ class HelloTriangleApplication {
16231615
throw std::runtime_error(warn + err);
16241616
}
16251617

1626-
m_indicesOffsets.push_back(m_indices.size());
1618+
m_firstIndices.push_back(m_indices.size());
16271619

16281620
static std::unordered_map<
16291621
Vertex,
@@ -1652,6 +1644,8 @@ class HelloTriangleApplication {
16521644
attrib.texcoords[2 * index.texcoord_index],
16531645
1.0f - attrib.texcoords[2 * index.texcoord_index + 1]
16541646
};
1647+
} else {
1648+
vertex.texCoord = {0.0f, 0.0f};
16551649
}
16561650

16571651
vertex.color = {1.0f, 1.0f, 1.0f};
@@ -1837,8 +1831,8 @@ class HelloTriangleApplication {
18371831
if(counts & vk::SampleCountFlagBits::e32) return vk::SampleCountFlagBits::e32;
18381832
if(counts & vk::SampleCountFlagBits::e16) return vk::SampleCountFlagBits::e16;
18391833
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;
18421836
return vk::SampleCountFlagBits::e1;
18431837
}
18441838
void createColorResources() {
@@ -1867,11 +1861,94 @@ class HelloTriangleApplication {
18671861
/////////////////////////////////////////////////////////////////
18681862

18691863
/////////////////////////////////////////////////////////////////
1870-
/// push constant
1871-
struct PushConstantData {
1864+
/// instance data
1865+
struct alignas(16) InstanceData {
18721866
glm::mat4 model;
18731867
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+
}
18741892
};
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+
}
18751952
/////////////////////////////////////////////////////////////////
18761953
};
18771954

0 commit comments

Comments
 (0)