@@ -258,6 +258,7 @@ void App::create_descriptor_pool() {
258
258
// 2 uniform buffers, can be more if desired.
259
259
vk::DescriptorPoolSize{vk::DescriptorType::eUniformBuffer, 2 },
260
260
vk::DescriptorPoolSize{vk::DescriptorType::eCombinedImageSampler, 2 },
261
+ vk::DescriptorPoolSize{vk::DescriptorType::eStorageBuffer, 2 },
261
262
};
262
263
auto pool_ci = vk::DescriptorPoolCreateInfo{};
263
264
// allow 16 sets to be allocated from this pool.
@@ -271,6 +272,7 @@ void App::create_pipeline_layout() {
271
272
};
272
273
static constexpr auto set_1_bindings_v = std::array{
273
274
layout_binding (0 , vk::DescriptorType::eCombinedImageSampler),
275
+ layout_binding (1 , vk::DescriptorType::eStorageBuffer),
274
276
};
275
277
auto set_layout_cis = std::array<vk::DescriptorSetLayoutCreateInfo, 2 >{};
276
278
set_layout_cis[0 ].setBindings (set_0_bindings_v);
@@ -347,6 +349,9 @@ void App::create_shader_resources() {
347
349
m_view_ubo.emplace (m_allocator.get (), m_gpu.queue_family ,
348
350
vk::BufferUsageFlagBits::eUniformBuffer);
349
351
352
+ m_instance_ssbo.emplace (m_allocator.get (), m_gpu.queue_family ,
353
+ vk::BufferUsageFlagBits::eStorageBuffer);
354
+
350
355
using Pixel = std::array<std::byte, 4 >;
351
356
static constexpr auto rgby_pixels_v = std::array{
352
357
Pixel{std::byte{0xff }, {}, {}, std::byte{0xff }},
@@ -484,6 +489,7 @@ void App::render(vk::CommandBuffer const command_buffer) {
484
489
command_buffer.beginRendering (rendering_info);
485
490
inspect ();
486
491
update_view ();
492
+ update_instances ();
487
493
draw (command_buffer);
488
494
command_buffer.endRendering ();
489
495
@@ -564,11 +570,27 @@ void App::inspect() {
564
570
line_width_range[0 ], line_width_range[1 ]);
565
571
}
566
572
573
+ static auto const inspect_transform = [](Transform& out) {
574
+ ImGui::DragFloat2 (" position" , &out.position .x );
575
+ ImGui::DragFloat (" rotation" , &out.rotation );
576
+ ImGui::DragFloat2 (" scale" , &out.scale .x , 0 .1f );
577
+ };
578
+
567
579
ImGui::Separator ();
568
580
if (ImGui::TreeNode (" View" )) {
569
- ImGui::DragFloat2 (" position" , &m_view_transform.position .x );
570
- ImGui::DragFloat (" rotation" , &m_view_transform.rotation );
571
- ImGui::DragFloat2 (" scale" , &m_view_transform.scale .x , 0 .1f );
581
+ inspect_transform (m_view_transform);
582
+ ImGui::TreePop ();
583
+ }
584
+
585
+ ImGui::Separator ();
586
+ if (ImGui::TreeNode (" Instances" )) {
587
+ for (std::size_t i = 0 ; i < m_instances.size (); ++i) {
588
+ auto const label = std::to_string (i);
589
+ if (ImGui::TreeNode (label.c_str ())) {
590
+ inspect_transform (m_instances.at (i));
591
+ ImGui::TreePop ();
592
+ }
593
+ }
572
594
ImGui::TreePop ();
573
595
}
574
596
}
@@ -586,6 +608,20 @@ void App::update_view() {
586
608
m_view_ubo->write_at (m_frame_index, bytes);
587
609
}
588
610
611
+ void App::update_instances () {
612
+ m_instance_data.clear ();
613
+ m_instance_data.reserve (m_instances.size ());
614
+ for (auto const & transform : m_instances) {
615
+ m_instance_data.push_back (transform.model_matrix ());
616
+ }
617
+ // can't use bit_cast anymore, reinterpret data as a byte array instead.
618
+ auto const span = std::span{m_instance_data};
619
+ void * data = span.data ();
620
+ auto const bytes =
621
+ std::span{static_cast <std::byte const *>(data), span.size_bytes ()};
622
+ m_instance_ssbo->write_at (m_frame_index, bytes);
623
+ }
624
+
589
625
void App::draw (vk::CommandBuffer const command_buffer) const {
590
626
m_shader->bind (command_buffer, m_framebuffer_size);
591
627
bind_descriptor_sets (command_buffer);
@@ -594,12 +630,13 @@ void App::draw(vk::CommandBuffer const command_buffer) const {
594
630
// u32 indices after offset of 4 vertices.
595
631
command_buffer.bindIndexBuffer (m_vbo.get ().buffer , 4 * sizeof (Vertex),
596
632
vk::IndexType::eUint32);
633
+ auto const instances = static_cast <std::uint32_t >(m_instances.size ());
597
634
// m_vbo has 6 indices.
598
- command_buffer.drawIndexed (6 , 1 , 0 , 0 , 0 );
635
+ command_buffer.drawIndexed (6 , instances , 0 , 0 , 0 );
599
636
}
600
637
601
638
void App::bind_descriptor_sets (vk::CommandBuffer const command_buffer) const {
602
- auto writes = std::array<vk::WriteDescriptorSet, 2 >{};
639
+ auto writes = std::array<vk::WriteDescriptorSet, 3 >{};
603
640
auto const & descriptor_sets = m_descriptor_sets.at (m_frame_index);
604
641
auto const set0 = descriptor_sets[0 ];
605
642
auto write = vk::WriteDescriptorSet{};
@@ -619,6 +656,14 @@ void App::bind_descriptor_sets(vk::CommandBuffer const command_buffer) const {
619
656
.setDstSet (set1)
620
657
.setDstBinding (0 );
621
658
writes[1 ] = write ;
659
+ auto const instance_ssbo_info =
660
+ m_instance_ssbo->descriptor_info_at (m_frame_index);
661
+ write .setBufferInfo (instance_ssbo_info)
662
+ .setDescriptorType (vk::DescriptorType::eStorageBuffer)
663
+ .setDescriptorCount (1 )
664
+ .setDstSet (set1)
665
+ .setDstBinding (1 );
666
+ writes[2 ] = write ;
622
667
623
668
m_device->updateDescriptorSets (writes, {});
624
669
0 commit comments